From 5370644901f8b3f8ecfe88df2940a46102a3e4c8 Mon Sep 17 00:00:00 2001 From: Alessio Vanni Date: Sun, 12 May 2019 21:46:26 +0200 Subject: Report error to console --- js/storage.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'js') diff --git a/js/storage.js b/js/storage.js index 4ca9b4f..ff00f24 100644 --- a/js/storage.js +++ b/js/storage.js @@ -518,7 +518,9 @@ var applyPublicSuffixList = function(details) { if ( !details.error ) { publicSuffixList.parse(details.content, punycode.toASCII); - } + } else { + console.error("Can't load public suffix list: "+details.error); + } callback(); }; -- cgit v1.2.3 From 5d142cf2bf9a552ef069dee02af28a2507934550 Mon Sep 17 00:00:00 2001 From: Alessio Vanni Date: Sun, 12 May 2019 21:58:03 +0200 Subject: Change directory name to be more informative --- js/vapi-background.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'js') diff --git a/js/vapi-background.js b/js/vapi-background.js index 08a84bc..719cbdf 100644 --- a/js/vapi-background.js +++ b/js/vapi-background.js @@ -348,7 +348,7 @@ vAPI.storage = (function() { // Create path var path = Services.dirsvc.get('ProfD', Ci.nsIFile); - path.append('extension-data'); + path.append('ematrix-data'); if ( !path.exists() ) { path.create(Ci.nsIFile.DIRECTORY_TYPE, parseInt('0774', 8)); } -- cgit v1.2.3 From 7859df9bc216bfd9f27a8841859da20f906dfb9d Mon Sep 17 00:00:00 2001 From: Alessio Vanni Date: Sun, 12 May 2019 22:06:31 +0200 Subject: Migrate database from old directory --- js/vapi-background.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'js') diff --git a/js/vapi-background.js b/js/vapi-background.js index 719cbdf..d2a9b66 100644 --- a/js/vapi-background.js +++ b/js/vapi-background.js @@ -347,7 +347,7 @@ vAPI.storage = (function() { } // Create path - var path = Services.dirsvc.get('ProfD', Ci.nsIFile); + let path = Services.dirsvc.get('ProfD', Ci.nsIFile); path.append('ematrix-data'); if ( !path.exists() ) { path.create(Ci.nsIFile.DIRECTORY_TYPE, parseInt('0774', 8)); @@ -355,6 +355,13 @@ vAPI.storage = (function() { if ( !path.isDirectory() ) { throw Error('Should be a directory...'); } + + let path2 = Services.dirsvc.get('ProfD', Ci.ndIFile); + path2.append('extension-data'); + if (path2.exists()) { + path2.append(location.host + '.sqlite'); + path2.copyTo(path, location.host + '.sqlite'); + } path.append(location.host + '.sqlite'); // Open database @@ -488,6 +495,7 @@ vAPI.storage = (function() { } var prepareResult = function(result) { + console.debug(result); var key; for ( key in result ) { if ( result.hasOwnProperty(key) === false ) { -- cgit v1.2.3 From 8ef453fe1ac8d80f90216de188e4b98df70dab22 Mon Sep 17 00:00:00 2001 From: Alessio Vanni Date: Sun, 12 May 2019 22:09:46 +0200 Subject: Fix typo --- js/vapi-background.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'js') diff --git a/js/vapi-background.js b/js/vapi-background.js index d2a9b66..09a5842 100644 --- a/js/vapi-background.js +++ b/js/vapi-background.js @@ -356,7 +356,7 @@ vAPI.storage = (function() { throw Error('Should be a directory...'); } - let path2 = Services.dirsvc.get('ProfD', Ci.ndIFile); + let path2 = Services.dirsvc.get('ProfD', Ci.nsIFile); path2.append('extension-data'); if (path2.exists()) { path2.append(location.host + '.sqlite'); -- cgit v1.2.3 From 08e1b5aef425090e4dc91978968a97bc5b38e53d Mon Sep 17 00:00:00 2001 From: Alessio Vanni Date: Mon, 13 May 2019 17:41:19 +0200 Subject: Fix handling of existing data --- js/vapi-background.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'js') diff --git a/js/vapi-background.js b/js/vapi-background.js index 09a5842..67d540e 100644 --- a/js/vapi-background.js +++ b/js/vapi-background.js @@ -359,8 +359,7 @@ vAPI.storage = (function() { let path2 = Services.dirsvc.get('ProfD', Ci.nsIFile); path2.append('extension-data'); if (path2.exists()) { - path2.append(location.host + '.sqlite'); - path2.copyTo(path, location.host + '.sqlite'); + path2.moveTo(null, path.leafName); } path.append(location.host + '.sqlite'); -- cgit v1.2.3 From 51b787e31052f8920692cc1a47df5e890c52c491 Mon Sep 17 00:00:00 2001 From: Alessio Vanni Date: Mon, 13 May 2019 17:51:20 +0200 Subject: Remove migration function Presumably, no one is using the old format anymore (especially since eMatrix is a different extension than uMatrix/uBlock...) --- js/assets.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'js') diff --git a/js/assets.js b/js/assets.js index 7190ca0..5219a82 100644 --- a/js/assets.js +++ b/js/assets.js @@ -388,7 +388,7 @@ api.unregisterAssetSource = function(assetKey) { **/ -var assetCacheRegistryStatus, +var assetCacheRegistryStatus = undefined, assetCacheRegistryStartTime = Date.now(), assetCacheRegistry = {}; @@ -426,7 +426,9 @@ var getAssetCacheRegistry = function(callback) { }); }; - migrate(migrationDone); + // Probably not needed anymore + // Commented out until something breaks + // migrate(migrationDone); }; var saveAssetCacheRegistry = (function() { -- cgit v1.2.3 From ed723f785722d91d2a19703e71aa703367fbecac Mon Sep 17 00:00:00 2001 From: Alessio Vanni Date: Mon, 13 May 2019 18:47:29 +0200 Subject: Remove a debugging statement --- js/vapi-background.js | 1 - 1 file changed, 1 deletion(-) (limited to 'js') diff --git a/js/vapi-background.js b/js/vapi-background.js index 67d540e..9088748 100644 --- a/js/vapi-background.js +++ b/js/vapi-background.js @@ -494,7 +494,6 @@ vAPI.storage = (function() { } var prepareResult = function(result) { - console.debug(result); var key; for ( key in result ) { if ( result.hasOwnProperty(key) === false ) { -- cgit v1.2.3 From b35adc655fa1a44d307355e07b38838413cfbc9b Mon Sep 17 00:00:00 2001 From: Alessio Vanni Date: Mon, 13 May 2019 20:53:00 +0200 Subject: Remove error reporting It's not actually needed anymore --- js/storage.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'js') diff --git a/js/storage.js b/js/storage.js index ff00f24..4ca9b4f 100644 --- a/js/storage.js +++ b/js/storage.js @@ -518,9 +518,7 @@ var applyPublicSuffixList = function(details) { if ( !details.error ) { publicSuffixList.parse(details.content, punycode.toASCII); - } else { - console.error("Can't load public suffix list: "+details.error); - } + } callback(); }; -- cgit v1.2.3 From 64c15c807f4f0387bf1e967354fab21dbdb9980c Mon Sep 17 00:00:00 2001 From: Alessio Vanni Date: Tue, 14 May 2019 19:08:56 +0200 Subject: Fix return statement The caller calling this function with topic equal to "before-asset-updated" expects a non-false value, but is never returned (a return with no value is equal to "return undefined" or something like that.) --- js/storage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'js') diff --git a/js/storage.js b/js/storage.js index 4ca9b4f..c56d414 100644 --- a/js/storage.js +++ b/js/storage.js @@ -564,7 +564,7 @@ ) { return false; } - return; + return true; } if ( topic === 'after-asset-updated' ) { -- cgit v1.2.3 From c83f575f798f795610aa1262776f5cabf24b12fb Mon Sep 17 00:00:00 2001 From: Alessio Vanni Date: Wed, 15 May 2019 15:40:42 +0200 Subject: Rewrite assets.js It has come to this in the end. --- js/assets.js | 1739 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 882 insertions(+), 857 deletions(-) (limited to 'js') diff --git a/js/assets.js b/js/assets.js index 5219a82..32090c7 100644 --- a/js/assets.js +++ b/js/assets.js @@ -27,888 +27,913 @@ ηMatrix.assets = (function() { -/******************************************************************************/ - -var reIsExternalPath = /^(?:[a-z-]+):\/\//, - errorCantConnectTo = vAPI.i18n('errorCantConnectTo'), - noopfunc = function(){}; - -var api = { -}; - -/******************************************************************************/ - -var observers = []; - -api.addObserver = function(observer) { - if ( observers.indexOf(observer) === -1 ) { - observers.push(observer); - } -}; - -api.removeObserver = function(observer) { - var pos; - while ( (pos = observers.indexOf(observer)) !== -1 ) { - observers.splice(pos, 1); - } -}; - -var fireNotification = function(topic, details) { - var result; - for ( var i = 0; i < observers.length; i++ ) { - if ( observers[i](topic, details) === false ) { - result = false; - } - } - return result; -}; - -/******************************************************************************/ - -api.fetchText = function(url, onLoad, onError) { - var actualUrl = reIsExternalPath.test(url) ? url : vAPI.getURL(url); - - if ( typeof onError !== 'function' ) { - onError = onLoad; - } - - // https://github.com/gorhill/uMatrix/issues/15 - var onResponseReceived = function() { - this.onload = this.onerror = this.ontimeout = null; - // xhr for local files gives status 0, but actually succeeds - var details = { - url: url, - content: '', - statusCode: this.status || 200, - statusText: this.statusText || '' - }; - if ( details.statusCode < 200 || details.statusCode >= 300 ) { - return onError.call(null, details); - } - // consider an empty result to be an error - if ( stringIsNotEmpty(this.responseText) === false ) { - return onError.call(null, details); - } - // we never download anything else than plain text: discard if response - // appears to be a HTML document: could happen when server serves - // some kind of error page I suppose - var text = this.responseText.trim(); - if ( text.startsWith('<') && text.endsWith('>') ) { - return onError.call(null, details); - } - details.content = this.responseText; - return onLoad.call(null, details); - }; - - var onErrorReceived = function() { - this.onload = this.onerror = this.ontimeout = null; - ηMatrix.logger.writeOne('', 'error', errorCantConnectTo.replace('{{url}}', actualUrl)); - onError.call(null, { url: url, content: '' }); - }; - - // Be ready for thrown exceptions: - // I am pretty sure it used to work, but now using a URL such as - // `file:///` on Chromium 40 results in an exception being thrown. - var xhr = new XMLHttpRequest(); - try { - xhr.open('get', actualUrl, true); - xhr.timeout = 30000; - xhr.onload = onResponseReceived; - xhr.onerror = onErrorReceived; - xhr.ontimeout = onErrorReceived; - xhr.responseType = 'text'; - xhr.send(); - } catch (e) { - onErrorReceived.call(xhr); - } -}; - -/******************************************************************************* - - TODO(seamless migration): - This block of code will be removed when I am confident all users have - moved to a version of uBO which does not require the old way of caching - assets. - - api.listKeyAliases: a map of old asset keys to new asset keys. - - migrate(): to seamlessly migrate the old cache manager to the new one: - - attempt to preserve and move content of cached assets to new locations; - - removes all traces of now obsolete cache manager entries in cacheStorage. - - This code will typically execute only once, when the newer version of uBO - is first installed and executed. - -**/ - -api.listKeyAliases = { - "assets/thirdparties/publicsuffix.org/list/effective_tld_names.dat": "public_suffix_list.dat", - "assets/thirdparties/hosts-file.net/ad-servers": "hphosts", - "assets/thirdparties/www.malwaredomainlist.com/hostslist/hosts.txt": "malware-0", - "assets/thirdparties/mirror1.malwaredomains.com/files/justdomains": "malware-1", - "assets/thirdparties/pgl.yoyo.org/as/serverlist": "plowe-0", - "assets/thirdparties/someonewhocares.org/hosts/hosts": "dpollock-0", - "assets/thirdparties/winhelp2002.mvps.org/hosts.txt": "mvps-0" -}; - -var migrate = function(callback) { - var entries, - moveCount = 0, - toRemove = []; - - var countdown = function(change) { - moveCount -= (change || 0); - if ( moveCount !== 0 ) { return; } - vAPI.cacheStorage.remove(toRemove); - saveAssetCacheRegistry(); - callback(); - }; - - var onContentRead = function(oldKey, newKey, bin) { - var content = bin && bin['cached_asset_content://' + oldKey] || undefined; - if ( content ) { - assetCacheRegistry[newKey] = { - readTime: Date.now(), - writeTime: entries[oldKey] - }; - if ( reIsExternalPath.test(oldKey) ) { - assetCacheRegistry[newKey].remoteURL = oldKey; - } - bin = {}; - bin['cache/' + newKey] = content; - vAPI.cacheStorage.set(bin); - } - countdown(1); - }; - - var onEntries = function(bin) { - entries = bin && bin.cached_asset_entries; - if ( !entries ) { return callback(); } - if ( bin && bin.assetCacheRegistry ) { - assetCacheRegistry = bin.assetCacheRegistry; - } - var aliases = api.listKeyAliases; - for ( var oldKey in entries ) { - var newKey = aliases[oldKey]; - if ( !newKey && /^https?:\/\//.test(oldKey) ) { - newKey = oldKey; - } - if ( newKey ) { - vAPI.cacheStorage.get( - 'cached_asset_content://' + oldKey, - onContentRead.bind(null, oldKey, newKey) - ); - moveCount += 1; - } - toRemove.push('cached_asset_content://' + oldKey); - } - toRemove.push('cached_asset_entries', 'extensionLastVersion'); - countdown(); - }; - - vAPI.cacheStorage.get( - [ 'cached_asset_entries', 'assetCacheRegistry' ], - onEntries - ); -}; - -/******************************************************************************* + let api = {}; + let observers = []; + let externalPathRegex = /^(?:[a-z-]+):\/\//; + let connectionError = vAPI.i18n('errorCantConnectTo'); - The purpose of the asset source registry is to keep key detail information - about an asset: - - Where to load it from: this may consist of one or more URLs, either local - or remote. - - After how many days an asset should be deemed obsolete -- i.e. in need of - an update. - - The origin and type of an asset. - - The last time an asset was registered. - -**/ - -var assetSourceRegistryStatus, - assetSourceRegistry = Object.create(null); - -var registerAssetSource = function(assetKey, dict) { - var entry = assetSourceRegistry[assetKey] || {}; - for ( var prop in dict ) { - if ( dict.hasOwnProperty(prop) === false ) { continue; } - if ( dict[prop] === undefined ) { - delete entry[prop]; - } else { - entry[prop] = dict[prop]; - } + function stub(string) { + console.debug("stub! "+string); } - var contentURL = dict.contentURL; - if ( contentURL !== undefined ) { - if ( typeof contentURL === 'string' ) { - contentURL = entry.contentURL = [ contentURL ]; - } else if ( Array.isArray(contentURL) === false ) { - contentURL = entry.contentURL = []; - } - var remoteURLCount = 0; - for ( var i = 0; i < contentURL.length; i++ ) { - if ( reIsExternalPath.test(contentURL[i]) ) { - remoteURLCount += 1; - } - } - entry.hasLocalURL = remoteURLCount !== contentURL.length; - entry.hasRemoteURL = remoteURLCount !== 0; - } else if ( entry.contentURL === undefined ) { - entry.contentURL = []; - } - if ( typeof entry.updateAfter !== 'number' ) { - entry.updateAfter = 13; - } - if ( entry.submitter ) { - entry.submitTime = Date.now(); // To detect stale entries - } - assetSourceRegistry[assetKey] = entry; -}; - -var unregisterAssetSource = function(assetKey) { - assetCacheRemove(assetKey); - delete assetSourceRegistry[assetKey]; -}; - -var saveAssetSourceRegistry = (function() { - var timer; - var save = function() { - timer = undefined; - vAPI.cacheStorage.set({ assetSourceRegistry: assetSourceRegistry }); - }; - return function(lazily) { - if ( timer !== undefined ) { - clearTimeout(timer); - } - if ( lazily ) { - timer = vAPI.setTimeout(save, 500); - } else { - save(); - } - }; -})(); - -var updateAssetSourceRegistry = function(json, silent) { - var newDict; - try { - newDict = JSON.parse(json); - } catch (ex) { - } - if ( newDict instanceof Object === false ) { return; } - - var oldDict = assetSourceRegistry, - assetKey; - - // Remove obsolete entries (only those which were built-in). - for ( assetKey in oldDict ) { - if ( - newDict[assetKey] === undefined && - oldDict[assetKey].submitter === undefined - ) { - unregisterAssetSource(assetKey); - } - } - // Add/update existing entries. Notify of new asset sources. - for ( assetKey in newDict ) { - if ( oldDict[assetKey] === undefined && !silent ) { - fireNotification( - 'builtin-asset-source-added', - { assetKey: assetKey, entry: newDict[assetKey] } - ); - } - registerAssetSource(assetKey, newDict[assetKey]); - } - saveAssetSourceRegistry(); -}; - -var getAssetSourceRegistry = function(callback) { - // Already loaded. - if ( assetSourceRegistryStatus === 'ready' ) { - callback(assetSourceRegistry); - return; - } - - // Being loaded. - if ( Array.isArray(assetSourceRegistryStatus) ) { - assetSourceRegistryStatus.push(callback); - return; - } - - // Not loaded: load it. - assetSourceRegistryStatus = [ callback ]; - - var registryReady = function() { - var callers = assetSourceRegistryStatus; - assetSourceRegistryStatus = 'ready'; - var fn; - while ( (fn = callers.shift()) ) { - fn(assetSourceRegistry); - } - }; - - // First-install case. - var createRegistry = function() { - api.fetchText( - ηMatrix.assetsBootstrapLocation || 'assets/assets.json', - function(details) { - updateAssetSourceRegistry(details.content, true); - registryReady(); - } - ); - }; - - vAPI.cacheStorage.get('assetSourceRegistry', function(bin) { - if ( !bin || !bin.assetSourceRegistry ) { - createRegistry(); - return; - } - assetSourceRegistry = bin.assetSourceRegistry; - registryReady(); - }); -}; - -api.registerAssetSource = function(assetKey, details) { - getAssetSourceRegistry(function() { - registerAssetSource(assetKey, details); - saveAssetSourceRegistry(true); - }); -}; - -api.unregisterAssetSource = function(assetKey) { - getAssetSourceRegistry(function() { - unregisterAssetSource(assetKey); - saveAssetSourceRegistry(true); - }); -}; - -/******************************************************************************* - - The purpose of the asset cache registry is to keep track of all assets - which have been persisted into the local cache. - -**/ - -var assetCacheRegistryStatus = undefined, - assetCacheRegistryStartTime = Date.now(), - assetCacheRegistry = {}; - -var getAssetCacheRegistry = function(callback) { - // Already loaded. - if ( assetCacheRegistryStatus === 'ready' ) { - callback(assetCacheRegistry); - return; - } - - // Being loaded. - if ( Array.isArray(assetCacheRegistryStatus) ) { - assetCacheRegistryStatus.push(callback); - return; - } - - // Not loaded: load it. - assetCacheRegistryStatus = [ callback ]; - - var registryReady = function() { - var callers = assetCacheRegistryStatus; - assetCacheRegistryStatus = 'ready'; - var fn; - while ( (fn = callers.shift()) ) { - fn(assetCacheRegistry); - } - }; - - var migrationDone = function() { - vAPI.cacheStorage.get('assetCacheRegistry', function(bin) { - if ( bin && bin.assetCacheRegistry ) { - assetCacheRegistry = bin.assetCacheRegistry; - } - registryReady(); - }); - }; - - // Probably not needed anymore - // Commented out until something breaks - // migrate(migrationDone); -}; -var saveAssetCacheRegistry = (function() { - var timer; - var save = function() { - timer = undefined; - vAPI.cacheStorage.set({ assetCacheRegistry: assetCacheRegistry }); - }; - return function(lazily) { - if ( timer !== undefined ) { clearTimeout(timer); } - if ( lazily ) { - timer = vAPI.setTimeout(save, 500); - } else { - save(); - } - }; -})(); + let notifyObservers = function (topic, details) { + let result; -var assetCacheRead = function(assetKey, callback) { - var internalKey = 'cache/' + assetKey; - - var reportBack = function(content, err) { - var details = { assetKey: assetKey, content: content }; - if ( err ) { details.error = err; } - callback(details); - }; - - var onAssetRead = function(bin) { - if ( !bin || !bin[internalKey] ) { - return reportBack('', 'E_NOTFOUND'); - } - var entry = assetCacheRegistry[assetKey]; - if ( entry === undefined ) { - return reportBack('', 'E_NOTFOUND'); - } - entry.readTime = Date.now(); - saveAssetCacheRegistry(true); - reportBack(bin[internalKey]); - }; + for (let i=0; i 0) { + vAPI.cacheStorage.remove(removedContent); + + let bin = { + assetCacheRegistry: cacheRegistry, + }; + + vAPI.cacheStorage.set(bin); + } + + if (typeof callback === 'function') { + callback(); + } + + for (let i=0; i now) { + continue; + } + if (notifyObservers('before-asset-updated', {assetKey: key})) { + return key; + } + + gcOne(key); + } + + return undefined; + }; + + let onUpdate = function (details) { + if (details.content !== '') { + updated.push(details.assetKey); + if (details.assetKey === 'asset.json') { + updateSourceRegistry(details.content); + } + } else { + notifyObservers('asset-update-failed', { + assetKey: details.assetKey, + }); + } + + if (findOne() !== undefined) { + vAPI.setTimeout(updateNext, updateDelay); + } else { + updateEnd(); + } + }; + + let updateOne = function () { + let key = findOne(); + if (key === undefined) { + updateEnd(); + return; + } + + updateFetch.add(key); + getRemote(key, onUpdate); + }; + + let onSourceReady = function (registry) { + updateOne(); + }; + + let onCacheReady = function (registry) { + getSourceRegistry(onSourceReady); + }; + + getCacheRegistry(onCacheReady); + }; + + let updateEnd = function () { + let keys = updated.slice(0); + updateFetch.clear(); + updateStatus = 'stop'; + updateDelay = updateDefaultDelay; + notifyObservers('after-asset-updated', { + assetKeys: keys, + }); + }; + + // Assets API + api.addObserver = function (observer) { + if (observers.indexOf(observer) === -1) { + observers.push(observer); + } + }; + + api.removeObserver = function (observer) { + let pos = observers.indexOf(observer); + if (pos !== -1) { + observers.splice(pos, 1); + } + }; + + api.fetchText = function (url, onLoad, onError) { + let iurl = externalPathRegex.test(url) ? url : vAPI.getURL(url); + + if (typeof onError !== 'function') { + onError = onLoad; + } + + let onResponseReceived = function () { + this.onload = this.onerror = this.ontimeout = null; + + let details = { + url: url, + content: '', + // On local files this.status is 0, but the request + // is successful + statusCode: this.status || 200, + statusText: this.statusText || '', + }; + + if (details.statusCode < 200 || details.statusCode >= 300) { + onError.call(null, details); + return; + } + + if (isEmptyString(this.responseText) === true) { + onError.call(null, details); + return; + } + + let t = this.responseText.trim(); + + // Discard HTML as it's probably an error + // (the request expects plain text as a response) + if (t.startsWith('<') && t.endsWith('>')) { + onError.call(null, details); + return; + } + + details.content = t; + onLoad.call(null, details); + }; + + let onErrorReceived = function () { + this.onload = this.onerror = this.ontimeout = null; + + ηMatrix.logger.writeOne('', 'error', + connectionError.replace('{{url}}', iurl)); + + onError.call(null, { + url: url, + content: '', + }); + }; + + let req = new XMLHttpRequest(); + req.open('GET', iurl, true); + req.timeout = 30000; + req.onload = onResponseReceived; + req.onerror = onErrorReceived; + req.ontimeout = onErrorReceived; + req.responseType = 'text'; + + try { + // This can throw in some cases + req.send(); + } catch (e) { + onErrorReceived.call(req); + } + }; + + api.registerAssetSource = function (key, details) { + getSourceRegistry(function () { + registerSource(key, details); + saveSourceRegistry(true); + }); + }; + + api.unregisterAssetSource = function (key) { + getSourceRegistry(function () { + unregisterSource(key); + saveSourceRegistry(true); + }); + }; + + api.get = function (key, options, callback) { + let cb; + let opt; + + if (typeof options === 'function') { + cb = options; + opt = {}; + } else if (typeof callback !== 'function') { + cb = noOp; + opt = options; + } else { + cb = callback; + opt = options; + } + + let assetDetails = {}; + let contentUrl = undefined; + + let report = function (content, error) { + let details = { + assetKey: key, + content: content, + }; + + if (error) { + details.error = assetDetails.error = error; + } else { + assetDetails.error = undefined; + } + + cb(details); + }; + + let onContentNotLoaded = function (details) { + let external; + let urls = []; + + console.debug(assetDetails); + + if (typeof assetDetails.contentURL === 'string') { + urls = [assetDetails.contentURL]; + } else if (Array.isArray(assetDetails.contentURL)) { + urls = assetDetails.contentURL.slice(0); + } + + while ((contentUrl = urls.shift())) { + external = externalPathRegex.test(contentUrl); + if (external === true && assetDetails.loaded !== true) { + break; + } + if (external === false || assetDetails.hasLocalURL !== true) { + break; + } + } + + if (!contentUrl) { + report('', 'E_NOTFOUND'); + return; + } + + api.fetchText(contentUrl, onContentLoaded, onContentNotLoaded); + }; + + let onContentLoaded = function (details) { + if (isEmptyString(details.content) === true) { + onContentNotLoaded(); + return; + } + + if (externalPathRegex.test(details.url) + && opt.dontCache !== true) { + writeCache(key, { + content: details.content, + url: contentUrl, + }); + } + + assetDetails.loaded = true; + + report(details.content); + }; + + let onCachedContentLoad = function (details) { + if (details.content !== '') { + report(details.content); + return; + } + + let onReady = function (registry) { + assetDetails = registry[key] || {}; + onContentNotLoaded(); + } + + getSourceRegistry(onReady); + }; + + readCache(key, onCachedContentLoad); + }; + + api.put = function (key, content, callback) { + writeCache(key, content, callback); + }; + + api.metadata = function (callback) { + let onSourceReady = function (registry) { + let source = JSON.parse(JSON.stringify(registry)); + let cache = cacheRegistry; + let sourceEntry; + let cacheEntry; + let now = Date.now(); + let obsoleteAfter; + + for (let key in source) { + sourceEntry = source[key]; + cacheEntry = cache[key]; + + if (cacheEntry) { + sourceEntry.cached = true; + sourceEntry.writeTime = cacheEntry.writeTime; + obsoleteAfter = cacheEntry.writeTime + + sourceEntry.updateAfter * 86400000; + sourceEntry.obsolete = obsoleteAfter < now; + sourceEntry.remoteURL = cacheEntry.remoteURL; + } else { + sourceEntry.writeTime = 0; + obsoleteAfter = 0; + sourceEntry.obsolete = true; + } + } - var onContentNotLoaded = function() { - var isExternal; - while ( (contentURL = contentURLs.shift()) ) { - isExternal = reIsExternalPath.test(contentURL); - if ( isExternal === false || assetDetails.hasLocalURL !== true ) { - break; - } - } - if ( !contentURL ) { - return reportBack('', 'E_NOTFOUND'); - } - api.fetchText(contentURL, onContentLoaded, onContentNotLoaded); + callback(source); + } + + let onCacheReady = function () { + getSourceRegistry(onSourceReady); + } + + getCacheRegistry(onCacheReady); + }; + + api.purge = function (pattern, exclude, callback) { + markDirtyCache(pattern, exclude, callback); }; - var onContentLoaded = function(details) { - if ( stringIsNotEmpty(details.content) === false ) { - onContentNotLoaded(); - return; - } - if ( reIsExternalPath.test(contentURL) && options.dontCache !== true ) { - assetCacheWrite(assetKey, { - content: details.content, - url: contentURL - }); - } - reportBack(details.content); + api.remove = function (pattern, callback) { + cacheRemove(pattern, callback); }; - var onCachedContentLoaded = function(details) { - if ( details.content !== '' ) { - return reportBack(details.content); - } - getAssetSourceRegistry(function(registry) { - assetDetails = registry[assetKey] || {}; - if ( typeof assetDetails.contentURL === 'string' ) { - contentURLs = [ assetDetails.contentURL ]; - } else if ( Array.isArray(assetDetails.contentURL) ) { - contentURLs = assetDetails.contentURL.slice(0); - } else { - contentURLs = []; - } - onContentNotLoaded(); - }); + api.rmrf = function () { + cacheRemove(/./); }; - assetCacheRead(assetKey, onCachedContentLoaded); -}; - -/******************************************************************************/ + api.updateStart = function (details) { + let oldDelay = updateDelay; + let newDelay = details.delay || updateDefaultDelay; -var getRemote = function(assetKey, callback) { - var assetDetails = {}, - contentURLs, - contentURL; - - var reportBack = function(content, err) { - var details = { assetKey: assetKey, content: content }; - if ( err ) { - details.error = assetDetails.lastError = err; - } else { - assetDetails.lastError = undefined; - } - callback(details); - }; + updateDelay = Math.min(oldDelay, newDelay); - var onRemoteContentLoaded = function(details) { - if ( stringIsNotEmpty(details.content) === false ) { - registerAssetSource(assetKey, { error: { time: Date.now(), error: 'No content' } }); - tryLoading(); - return; - } - assetCacheWrite(assetKey, { - content: details.content, - url: contentURL - }); - registerAssetSource(assetKey, { error: undefined }); - reportBack(details.content); - }; + if (updateStatus === 'running') { + if (newDelay < oldDelay) { + clearTimeout(updateTimer); + updateTimer = vAPI.setTimeout(updateNext, updateDelay); + } + return; + } - var onRemoteContentError = function(details) { - var text = details.statusText; - if ( details.statusCode === 0 ) { - text = 'network error'; - } - registerAssetSource(assetKey, { error: { time: Date.now(), error: text } }); - tryLoading(); + updateStart(); }; - var tryLoading = function() { - while ( (contentURL = contentURLs.shift()) ) { - if ( reIsExternalPath.test(contentURL) ) { break; } - } - if ( !contentURL ) { - return reportBack('', 'E_NOTFOUND'); - } - api.fetchText(contentURL, onRemoteContentLoaded, onRemoteContentError); + api.updateStop = function () { + if (updateTimer) { + clearTimeout(updateTimer); + updateTimer = undefined; + } + if (updateStatus === 'running') { + updateEnd(); + } }; - getAssetSourceRegistry(function(registry) { - assetDetails = registry[assetKey] || {}; - if ( typeof assetDetails.contentURL === 'string' ) { - contentURLs = [ assetDetails.contentURL ]; - } else if ( Array.isArray(assetDetails.contentURL) ) { - contentURLs = assetDetails.contentURL.slice(0); - } else { - contentURLs = []; - } - tryLoading(); - }); -}; - -/******************************************************************************/ - -api.put = function(assetKey, content, callback) { - assetCacheWrite(assetKey, content, callback); -}; - -/******************************************************************************/ - -api.metadata = function(callback) { - var assetRegistryReady = false, - cacheRegistryReady = false; - - var onReady = function() { - var assetDict = JSON.parse(JSON.stringify(assetSourceRegistry)), - cacheDict = assetCacheRegistry, - assetEntry, cacheEntry, - now = Date.now(), obsoleteAfter; - for ( var assetKey in assetDict ) { - assetEntry = assetDict[assetKey]; - cacheEntry = cacheDict[assetKey]; - if ( cacheEntry ) { - assetEntry.cached = true; - assetEntry.writeTime = cacheEntry.writeTime; - obsoleteAfter = cacheEntry.writeTime + assetEntry.updateAfter * 86400000; - assetEntry.obsolete = obsoleteAfter < now; - assetEntry.remoteURL = cacheEntry.remoteURL; - } else { - assetEntry.writeTime = 0; - obsoleteAfter = 0; - assetEntry.obsolete = true; - } - } - callback(assetDict); - }; - - getAssetSourceRegistry(function() { - assetRegistryReady = true; - if ( cacheRegistryReady ) { onReady(); } - }); - - getAssetCacheRegistry(function() { - cacheRegistryReady = true; - if ( assetRegistryReady ) { onReady(); } - }); -}; - -/******************************************************************************/ - -api.purge = assetCacheMarkAsDirty; - -api.remove = function(pattern, callback) { - assetCacheRemove(pattern, callback); -}; - -api.rmrf = function() { - assetCacheRemove(/./); -}; - -/******************************************************************************/ - -// Asset updater area. -var updaterStatus, - updaterTimer, - updaterAssetDelayDefault = 120000, - updaterAssetDelay = updaterAssetDelayDefault, - updaterUpdated = [], - updaterFetched = new Set(); - -var updateFirst = function() { - updaterStatus = 'updating'; - updaterFetched.clear(); - updaterUpdated = []; - fireNotification('before-assets-updated'); - updateNext(); -}; - -var updateNext = function() { - var assetDict, cacheDict; - - // This will remove a cached asset when it's no longer in use. - var garbageCollectOne = function(assetKey) { - var cacheEntry = cacheDict[assetKey]; - if ( cacheEntry && cacheEntry.readTime < assetCacheRegistryStartTime ) { - assetCacheRemove(assetKey); - } - }; - - var findOne = function() { - var now = Date.now(), - assetEntry, cacheEntry; - for ( var assetKey in assetDict ) { - assetEntry = assetDict[assetKey]; - if ( assetEntry.hasRemoteURL !== true ) { continue; } - if ( updaterFetched.has(assetKey) ) { continue; } - cacheEntry = cacheDict[assetKey]; - if ( cacheEntry && (cacheEntry.writeTime + assetEntry.updateAfter * 86400000) > now ) { - continue; - } - if ( fireNotification('before-asset-updated', { assetKey: assetKey }) !== false ) { - return assetKey; - } - garbageCollectOne(assetKey); - } - }; - - var updatedOne = function(details) { - if ( details.content !== '' ) { - updaterUpdated.push(details.assetKey); - if ( details.assetKey === 'assets.json' ) { - updateAssetSourceRegistry(details.content); - } - } else { - fireNotification('asset-update-failed', { assetKey: details.assetKey }); - } - if ( findOne() !== undefined ) { - vAPI.setTimeout(updateNext, updaterAssetDelay); - } else { - updateDone(); - } - }; - - var updateOne = function() { - var assetKey = findOne(); - if ( assetKey === undefined ) { - return updateDone(); - } - updaterFetched.add(assetKey); - getRemote(assetKey, updatedOne); - }; - - getAssetSourceRegistry(function(dict) { - assetDict = dict; - if ( !cacheDict ) { return; } - updateOne(); - }); - - getAssetCacheRegistry(function(dict) { - cacheDict = dict; - if ( !assetDict ) { return; } - updateOne(); - }); -}; - -var updateDone = function() { - var assetKeys = updaterUpdated.slice(0); - updaterFetched.clear(); - updaterUpdated = []; - updaterStatus = undefined; - updaterAssetDelay = updaterAssetDelayDefault; - fireNotification('after-assets-updated', { assetKeys: assetKeys }); -}; - -api.updateStart = function(details) { - var oldUpdateDelay = updaterAssetDelay, - newUpdateDelay = details.delay || updaterAssetDelayDefault; - updaterAssetDelay = Math.min(oldUpdateDelay, newUpdateDelay); - if ( updaterStatus !== undefined ) { - if ( newUpdateDelay < oldUpdateDelay ) { - clearTimeout(updaterTimer); - updaterTimer = vAPI.setTimeout(updateNext, updaterAssetDelay); - } - return; - } - updateFirst(); -}; - -api.updateStop = function() { - if ( updaterTimer ) { - clearTimeout(updaterTimer); - updaterTimer = undefined; - } - if ( updaterStatus !== undefined ) { - updateDone(); - } -}; - -/******************************************************************************/ - -return api; - -/******************************************************************************/ - + return api; })(); /******************************************************************************/ -- cgit v1.2.3 From a51744863384896b171fe54e952676ec36df6db0 Mon Sep 17 00:00:00 2001 From: Alessio Vanni Date: Wed, 15 May 2019 20:48:56 +0200 Subject: Remove debugging statements --- js/assets.js | 6 ------ 1 file changed, 6 deletions(-) (limited to 'js') diff --git a/js/assets.js b/js/assets.js index 32090c7..6a2d6e2 100644 --- a/js/assets.js +++ b/js/assets.js @@ -32,10 +32,6 @@ let externalPathRegex = /^(?:[a-z-]+):\/\//; let connectionError = vAPI.i18n('errorCantConnectTo'); - function stub(string) { - console.debug("stub! "+string); - } - let notifyObservers = function (topic, details) { let result; @@ -790,8 +786,6 @@ let onContentNotLoaded = function (details) { let external; let urls = []; - - console.debug(assetDetails); if (typeof assetDetails.contentURL === 'string') { urls = [assetDetails.contentURL]; -- cgit v1.2.3