This commit is contained in:
gorhill 2014-12-20 15:28:16 -05:00
parent a66c26ebef
commit 4f229c7c27
3 changed files with 67 additions and 36 deletions

View File

@ -19,9 +19,7 @@
Home: https://github.com/gorhill/uBlock Home: https://github.com/gorhill/uBlock
*/ */
/* global µBlock, YaMD5 */ /* global vAPI, µBlock, YaMD5 */
'use strict';
/******************************************************************************* /*******************************************************************************
@ -43,6 +41,8 @@ File system structure:
µBlock.assets = (function() { µBlock.assets = (function() {
'use strict';
/******************************************************************************/ /******************************************************************************/
var oneSecond = 1000; var oneSecond = 1000;
@ -58,14 +58,16 @@ var nullFunc = function() {};
var reIsExternalPath = /^https?:\/\/[a-z0-9]/; var reIsExternalPath = /^https?:\/\/[a-z0-9]/;
var reIsUserPath = /^assets\/user\//; var reIsUserPath = /^assets\/user\//;
var lastRepoMetaTimestamp = 0; var lastRepoMetaTimestamp = 0;
var lastRepoMetaIsRemote = false;
var refreshRepoMetaPeriod = 5 * oneHour; var refreshRepoMetaPeriod = 5 * oneHour;
// TODO: move vAPI.i18n to XAL
var errorCantConnectTo = vAPI.i18n('errorCantConnectTo'); var errorCantConnectTo = vAPI.i18n('errorCantConnectTo');
var exports = { var exports = {
autoUpdate: true, autoUpdate: true,
autoUpdateDelay: 4 * oneDay autoUpdateDelay: 4 * oneDay,
// https://github.com/gorhill/uBlock/issues/426
allowRemoteFetch: true
}; };
/******************************************************************************/ /******************************************************************************/
@ -86,6 +88,18 @@ var repoMetadata = null;
/******************************************************************************/ /******************************************************************************/
var stringIsNotEmpty = function(s) {
return typeof s === 'string' && s !== '';
};
/******************************************************************************/
var cacheIsObsolete = function(t) {
return typeof t !== 'number' || (Date.now() - t) >= exports.autoUpdateDelay;
};
/******************************************************************************/
var cachedAssetsManager = (function() { var cachedAssetsManager = (function() {
var exports = {}; var exports = {};
var entries = null; var entries = null;
@ -148,10 +162,9 @@ var cachedAssetsManager = (function() {
// be because the save occurred while I was stepping in the code // be because the save occurred while I was stepping in the code
// though, which means it would not occur during normal operation. // though, which means it would not occur during normal operation.
// Still, just to be safe. // Still, just to be safe.
if ( bin[cachedContentPath] === undefined ) { if ( stringIsNotEmpty(bin[cachedContentPath]) === false ) {
exports.remove(path);
details.error = 'Error: not found'; details.error = 'Error: not found';
delete entries[path];
vAPI.storage.set({ 'cached_asset_entries': entries });
cbError(details); cbError(details);
return; return;
} }
@ -176,6 +189,11 @@ var cachedAssetsManager = (function() {
path: path, path: path,
content: content content: content
}; };
if ( content === '' ) {
exports.remove(path);
cbSuccess(details);
return;
}
var cachedContentPath = cachedAssetPathPrefix + path; var cachedContentPath = cachedAssetPathPrefix + path;
var bin = {}; var bin = {};
bin[cachedContentPath] = content; bin[cachedContentPath] = content;
@ -246,8 +264,7 @@ var getTextFileFromURL = function(url, onLoad, onError) {
// https://github.com/gorhill/uMatrix/issues/15 // https://github.com/gorhill/uMatrix/issues/15
var onResponseReceived = function() { var onResponseReceived = function() {
// xhr for local files gives status 0, but actually succeeds // xhr for local files gives status 0, but actually succeeds
if ( this.status >= 200 && this.status < 300 if ( (this.status >= 200 && this.status < 300) || (this.status === 0 && this.responseText) ) {
|| this.status === 0 && this.responseText ) {
return onLoad.call(this); return onLoad.call(this);
} }
return onError.call(this); return onError.call(this);
@ -288,6 +305,9 @@ var updateLocalChecksums = function() {
var getRepoMetadata = function(callback) { var getRepoMetadata = function(callback) {
callback = callback || nullFunc; callback = callback || nullFunc;
if ( exports.allowRemoteFetch && lastRepoMetaIsRemote === false ) {
lastRepoMetaTimestamp = 0;
}
if ( (Date.now() - lastRepoMetaTimestamp) >= refreshRepoMetaPeriod ) { if ( (Date.now() - lastRepoMetaTimestamp) >= refreshRepoMetaPeriod ) {
repoMetadata = null; repoMetadata = null;
} }
@ -301,6 +321,7 @@ var getRepoMetadata = function(callback) {
} }
lastRepoMetaTimestamp = Date.now(); lastRepoMetaTimestamp = Date.now();
lastRepoMetaIsRemote = exports.allowRemoteFetch;
var localChecksums; var localChecksums;
var repoChecksums; var repoChecksums;
@ -459,6 +480,12 @@ var readLocalFile = function(path, callback) {
// Get the repository copy of a built-in asset. // Get the repository copy of a built-in asset.
var readRepoFile = function(path, callback) { var readRepoFile = function(path, callback) {
// https://github.com/gorhill/uBlock/issues/426
if ( exports.allowRemoteFetch === false ) {
readLocalFile(path, callback);
return;
}
var reportBack = function(content, err) { var reportBack = function(content, err) {
var details = { var details = {
'path': path, 'path': path,
@ -552,7 +579,7 @@ var readRepoCopyAsset = function(path, callback) {
var onRepoFileLoaded = function() { var onRepoFileLoaded = function() {
this.onload = this.onerror = null; this.onload = this.onerror = null;
if ( typeof this.responseText !== 'string' || this.responseText === '' ) { if ( stringIsNotEmpty(this.responseText) === false ) {
console.error('µBlock> readRepoCopyAsset("%s") / onRepoFileLoaded("%s"): error', path, repositoryURL); console.error('µBlock> readRepoCopyAsset("%s") / onRepoFileLoaded("%s"): error', path, repositoryURL);
cachedAssetsManager.load(path, onCachedContentLoaded, onCachedContentError); cachedAssetsManager.load(path, onCachedContentLoaded, onCachedContentError);
return; return;
@ -570,7 +597,7 @@ var readRepoCopyAsset = function(path, callback) {
var onHomeFileLoaded = function() { var onHomeFileLoaded = function() {
this.onload = this.onerror = null; this.onload = this.onerror = null;
if ( typeof this.responseText !== 'string' || this.responseText === '' ) { if ( stringIsNotEmpty(this.responseText) === false ) {
console.error('µBlock> readRepoCopyAsset("%s") / onHomeFileLoaded("%s"): no response', path, assetEntry.homeURL); console.error('µBlock> readRepoCopyAsset("%s") / onHomeFileLoaded("%s"): no response', path, assetEntry.homeURL);
// Fetch from repo only if obsolescence was due to repo checksum // Fetch from repo only if obsolescence was due to repo checksum
if ( assetEntry.localChecksum !== assetEntry.repoChecksum ) { if ( assetEntry.localChecksum !== assetEntry.repoChecksum ) {
@ -600,18 +627,17 @@ var readRepoCopyAsset = function(path, callback) {
// Fetch from remote if: // Fetch from remote if:
// - Auto-update enabled AND (not in cache OR in cache but obsolete) // - Auto-update enabled AND (not in cache OR in cache but obsolete)
var timestamp = entries[path]; var timestamp = entries[path];
var homeURL = assetEntry.homeURL; var inCache = typeof timestamp === 'number';
if ( exports.autoUpdate && typeof homeURL === 'string' && homeURL !== '' ) { if ( exports.allowRemoteFetch && exports.autoUpdate && stringIsNotEmpty(assetEntry.homeURL) ) {
var obsolete = Date.now() - exports.autoUpdateDelay; if ( inCache === false || cacheIsObsolete(timestamp) ) {
if ( typeof timestamp !== 'number' || timestamp <= obsolete ) {
//console.log('µBlock> readRepoCopyAsset("%s") / onCacheMetaReady(): not cached or obsolete', path); //console.log('µBlock> readRepoCopyAsset("%s") / onCacheMetaReady(): not cached or obsolete', path);
getTextFileFromURL(homeURL, onHomeFileLoaded, onHomeFileError); getTextFileFromURL(assetEntry.homeURL, onHomeFileLoaded, onHomeFileError);
return; return;
} }
} }
// In cache // In cache
if ( typeof timestamp === 'number' ) { if ( inCache ) {
cachedAssetsManager.load(path, onCachedContentLoaded, onCachedContentError); cachedAssetsManager.load(path, onCachedContentLoaded, onCachedContentError);
return; return;
} }
@ -630,10 +656,10 @@ var readRepoCopyAsset = function(path, callback) {
} }
// Repo copy changed: fetch from home URL // Repo copy changed: fetch from home URL
if ( exports.autoUpdate && assetEntry.localChecksum !== assetEntry.repoChecksum ) { if ( exports.allowRemoteFetch && exports.autoUpdate && assetEntry.localChecksum !== assetEntry.repoChecksum ) {
//console.log('µBlock> readRepoCopyAsset("%s") / onRepoMetaReady(): repo has newer version', path); //console.log('µBlock> readRepoCopyAsset("%s") / onRepoMetaReady(): repo has newer version', path);
var homeURL = assetEntry.homeURL; var homeURL = assetEntry.homeURL;
if ( typeof homeURL === 'string' && homeURL !== '' ) { if ( stringIsNotEmpty(homeURL) ) {
getTextFileFromURL(homeURL, onHomeFileLoaded, onHomeFileError); getTextFileFromURL(homeURL, onHomeFileLoaded, onHomeFileError);
} else { } else {
getTextFileFromURL(repositoryURLSkipCache, onRepoFileLoaded, onRepoFileError); getTextFileFromURL(repositoryURLSkipCache, onRepoFileLoaded, onRepoFileError);
@ -732,7 +758,7 @@ var readRepoOnlyAsset = function(path, callback) {
} }
// Asset added or changed: load from repo URL and then cache result // Asset added or changed: load from repo URL and then cache result
if ( exports.autoUpdate && assetEntry.localChecksum !== assetEntry.repoChecksum ) { if ( exports.allowRemoteFetch && exports.autoUpdate && assetEntry.localChecksum !== assetEntry.repoChecksum ) {
//console.log('µBlock> readRepoOnlyAsset("%s") / onRepoMetaReady(): repo has newer version', path); //console.log('µBlock> readRepoOnlyAsset("%s") / onRepoMetaReady(): repo has newer version', path);
getTextFileFromURL(repositoryURL, onRepoFileLoaded, onRepoFileError); getTextFileFromURL(repositoryURL, onRepoFileLoaded, onRepoFileError);
return; return;
@ -805,8 +831,9 @@ var readExternalAsset = function(path, callback) {
// //
// - Auto-update enabled AND in cache but obsolete // - Auto-update enabled AND in cache but obsolete
var timestamp = entries[path]; var timestamp = entries[path];
var obsolete = Date.now() - exports.autoUpdateDelay; var notInCache = typeof timestamp !== 'number';
if ( typeof timestamp !== 'number' || (exports.autoUpdate && timestamp <= obsolete) ) { var updateCache = exports.allowRemoteFetch && exports.autoUpdate && cacheIsObsolete(timestamp);
if ( notInCache || updateCache ) {
getTextFileFromURL(path, onExternalFileLoaded, onExternalFileError); getTextFileFromURL(path, onExternalFileLoaded, onExternalFileError);
return; return;
} }
@ -930,17 +957,14 @@ exports.metadata = function(callback) {
// We need to check cache obsolescence when both cache and repo meta data // We need to check cache obsolescence when both cache and repo meta data
// has been gathered. // has been gathered.
var checkCacheObsolescence = function() { var checkCacheObsolescence = function() {
var obsolete = Date.now() - exports.autoUpdateDelay;
var entry; var entry;
for ( var path in out ) { for ( var path in out ) {
if ( out.hasOwnProperty(path) === false ) { if ( out.hasOwnProperty(path) === false ) {
continue; continue;
} }
entry = out[path]; entry = out[path];
entry.cacheObsolete = entry.cacheObsolete = stringIsNotEmpty(entry.homeURL) &&
typeof entry.homeURL === 'string' && cacheIsObsolete(entry.lastModified);
entry.homeURL !== '' &&
(typeof entry.lastModified !== 'number' || entry.lastModified <= obsolete);
} }
callback(out); callback(out);
}; };

View File

@ -20,7 +20,6 @@
*/ */
/* global µBlock */ /* global µBlock */
'use strict';
/******************************************************************************/ /******************************************************************************/
@ -29,6 +28,8 @@
µBlock.updater = (function() { µBlock.updater = (function() {
'use strict';
/******************************************************************************/ /******************************************************************************/
var µb = µBlock; var µb = µBlock;

View File

@ -591,15 +591,16 @@
// - Initialize internal state with maybe already existing tabs. // - Initialize internal state with maybe already existing tabs.
// - Schedule next update operation. // - Schedule next update operation.
var onAllDone = function() { var onAllDone = function() {
// https://github.com/gorhill/uBlock/issues/426
// Important: remove barrier to remote fetching, this was useful only
// for launch time.
µb.assets.allowRemoteFetch = true;
vAPI.onLoadAllCompleted(); vAPI.onLoadAllCompleted();
// https://github.com/gorhill/uBlock/issues/184 // https://github.com/gorhill/uBlock/issues/184
// If we restored a selfie, check for updates not too far // Check for updates not too far in the future.
// in the future. µb.updater.restart(µb.firstUpdateAfter);
var nextUpdate = fromSelfie === false && µb.userSettings.autoUpdate ?
µb.nextUpdateAfter :
µb.firstUpdateAfter;
µb.updater.restart(nextUpdate);
}; };
var filtersReady = false; var filtersReady = false;
@ -644,6 +645,11 @@
// User settings are in memory // User settings are in memory
var onUserSettingsReady = function(settings) { var onUserSettingsReady = function(settings) {
// https://github.com/gorhill/uBlock/issues/426
// Important: block remote fetching for when loading assets at launch
// time.
µb.assets.allowRemoteFetch = false;
µb.assets.autoUpdate = settings.autoUpdate; µb.assets.autoUpdate = settings.autoUpdate;
µb.netFilteringEngine.dynamicFiltersFromSelfie(settings.dynamicFilteringSelfie); µb.netFilteringEngine.dynamicFiltersFromSelfie(settings.dynamicFilteringSelfie);
µb.fromSelfie(onSelfieReady); µb.fromSelfie(onSelfieReady);