mirror of
https://github.com/gorhill/uBlock.git
synced 2026-03-11 09:04:36 +00:00
code review
This commit is contained in:
parent
ba96a4ff4a
commit
72f5e44ec0
7 changed files with 138 additions and 288 deletions
|
|
@ -11,7 +11,6 @@
|
||||||
<script src="js/vapi-common.js"></script>
|
<script src="js/vapi-common.js"></script>
|
||||||
<script src="js/vapi-background.js"></script>
|
<script src="js/vapi-background.js"></script>
|
||||||
<script src="js/background.js"></script>
|
<script src="js/background.js"></script>
|
||||||
<script src="js/async.js"></script>
|
|
||||||
<script src="js/utils.js"></script>
|
<script src="js/utils.js"></script>
|
||||||
<script src="js/uritools.js"></script>
|
<script src="js/uritools.js"></script>
|
||||||
<script src="js/assets.js"></script>
|
<script src="js/assets.js"></script>
|
||||||
|
|
|
||||||
203
src/js/async.js
203
src/js/async.js
|
|
@ -1,203 +0,0 @@
|
||||||
/*******************************************************************************
|
|
||||||
|
|
||||||
µBlock - a browser extension to block requests.
|
|
||||||
Copyright (C) 2014 Raymond Hill
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
|
||||||
|
|
||||||
Home: https://github.com/gorhill/uBlock
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* global µBlock */
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
// Async job queue module
|
|
||||||
|
|
||||||
µBlock.asyncJobs = (function() {
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
var processJobs = function() {
|
|
||||||
asyncJobManager.process();
|
|
||||||
};
|
|
||||||
|
|
||||||
var AsyncJobEntry = function(name) {
|
|
||||||
this.name = name;
|
|
||||||
this.data = null;
|
|
||||||
this.callback = null;
|
|
||||||
this.when = 0;
|
|
||||||
this.period = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
AsyncJobEntry.prototype.destroy = function() {
|
|
||||||
this.name = '';
|
|
||||||
this.data = null;
|
|
||||||
this.callback = null;
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
var AsyncJobManager = function() {
|
|
||||||
this.timeResolution = 200;
|
|
||||||
this.jobs = {};
|
|
||||||
this.jobCount = 0;
|
|
||||||
this.jobJunkyard = [];
|
|
||||||
this.timerId = null;
|
|
||||||
this.timerWhen = Number.MAX_VALUE;
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
AsyncJobManager.prototype.restartTimer = function() {
|
|
||||||
// TODO: Another way to do this is to extract the keys, sort the keys
|
|
||||||
// in chronological order, than pick the first entry to get the next
|
|
||||||
// time at which we want a time event to fire. Completely unsure the
|
|
||||||
// overhead of extracting keys/sorting is less than what is below.
|
|
||||||
// I could also keep the keys ordered, and use binary search when adding
|
|
||||||
// a new job.
|
|
||||||
var when = Number.MAX_VALUE;
|
|
||||||
var jobs = this.jobs, job;
|
|
||||||
for ( var jobName in jobs ) {
|
|
||||||
job = jobs[jobName];
|
|
||||||
if ( job instanceof AsyncJobEntry ) {
|
|
||||||
if ( job.when < when ) {
|
|
||||||
when = job.when;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Quantize time value
|
|
||||||
when = Math.floor((when + this.timeResolution - 1) / this.timeResolution) * this.timeResolution;
|
|
||||||
|
|
||||||
// TODO: Maybe use chrome.alarms() API when the next job is at more than
|
|
||||||
// one minute in the future... From reading about it, chrome.alarms() is
|
|
||||||
// smarter in that it will fire the event only when the browser is not
|
|
||||||
// too busy.
|
|
||||||
if ( when < this.timerWhen ) {
|
|
||||||
clearTimeout(this.timerId);
|
|
||||||
this.timerWhen = when;
|
|
||||||
this.timerId = vAPI.setTimeout(processJobs, Math.max(when - Date.now(), 10));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
AsyncJobManager.prototype.add = function(name, data, callback, delay, recurrent) {
|
|
||||||
var job = this.jobs[name];
|
|
||||||
if ( !job ) {
|
|
||||||
job = this.jobJunkyard.pop();
|
|
||||||
if ( !job ) {
|
|
||||||
job = new AsyncJobEntry(name);
|
|
||||||
} else {
|
|
||||||
job.name = name;
|
|
||||||
}
|
|
||||||
this.jobs[name] = job;
|
|
||||||
this.jobCount++;
|
|
||||||
}
|
|
||||||
job.data = data;
|
|
||||||
job.callback = callback;
|
|
||||||
job.when = Date.now() + delay;
|
|
||||||
job.period = recurrent ? delay : 0;
|
|
||||||
this.restartTimer();
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
AsyncJobManager.prototype.remove = function(jobName) {
|
|
||||||
if ( this.jobs.hasOwnProperty(jobName) === false ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var job = this.jobs[jobName];
|
|
||||||
delete this.jobs[jobName];
|
|
||||||
job.destroy();
|
|
||||||
this.jobCount--;
|
|
||||||
this.jobJunkyard.push(job);
|
|
||||||
this.restartTimer();
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
AsyncJobManager.prototype.process = function() {
|
|
||||||
this.timerId = null;
|
|
||||||
this.timerWhen = Number.MAX_VALUE;
|
|
||||||
var now = Date.now();
|
|
||||||
var job;
|
|
||||||
for ( var jobName in this.jobs ) {
|
|
||||||
if ( this.jobs.hasOwnProperty(jobName) === false ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
job = this.jobs[jobName];
|
|
||||||
if ( job.when > now ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
job.callback(job.data);
|
|
||||||
if ( job.period ) {
|
|
||||||
job.when = now + job.period;
|
|
||||||
} else {
|
|
||||||
delete this.jobs[jobName];
|
|
||||||
job.destroy();
|
|
||||||
this.jobCount--;
|
|
||||||
this.jobJunkyard.push(job);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.restartTimer();
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
// Only one instance
|
|
||||||
var asyncJobManager = new AsyncJobManager();
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
// Publish
|
|
||||||
return asyncJobManager;
|
|
||||||
|
|
||||||
})();
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
// Update visual of extension icon.
|
|
||||||
|
|
||||||
µBlock.updateBadgeAsync = (function() {
|
|
||||||
var tabIdToTimer = Object.create(null);
|
|
||||||
|
|
||||||
var updateBadge = function(tabId) {
|
|
||||||
delete tabIdToTimer[tabId];
|
|
||||||
|
|
||||||
var state = false;
|
|
||||||
var badge = '';
|
|
||||||
|
|
||||||
var pageStore = this.pageStoreFromTabId(tabId);
|
|
||||||
if ( pageStore !== null ) {
|
|
||||||
state = pageStore.getNetFilteringSwitch();
|
|
||||||
if ( state && this.userSettings.showIconBadge && pageStore.perLoadBlockedRequestCount ) {
|
|
||||||
badge = this.utils.formatCount(pageStore.perLoadBlockedRequestCount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vAPI.setIcon(tabId, state ? 'on' : 'off', badge);
|
|
||||||
};
|
|
||||||
|
|
||||||
return function(tabId) {
|
|
||||||
if ( tabIdToTimer[tabId] ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ( vAPI.isBehindTheSceneTabId(tabId) ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
tabIdToTimer[tabId] = vAPI.setTimeout(updateBadge.bind(this, tabId), 500);
|
|
||||||
};
|
|
||||||
})();
|
|
||||||
|
|
@ -1137,7 +1137,7 @@ var restoreUserData = function(request) {
|
||||||
var onAllRemoved = function() {
|
var onAllRemoved = function() {
|
||||||
// Be sure to adjust `countdown` if adding/removing anything below
|
// Be sure to adjust `countdown` if adding/removing anything below
|
||||||
µb.keyvalSetOne('version', userData.version);
|
µb.keyvalSetOne('version', userData.version);
|
||||||
µBlock.saveLocalSettings(true);
|
µBlock.saveLocalSettings();
|
||||||
vAPI.storage.set(userData.userSettings, onCountdown);
|
vAPI.storage.set(userData.userSettings, onCountdown);
|
||||||
µb.keyvalSetOne('remoteBlacklists', userData.filterLists, onCountdown);
|
µb.keyvalSetOne('remoteBlacklists', userData.filterLists, onCountdown);
|
||||||
µb.keyvalSetOne('netWhitelist', userData.netWhitelist || '', onCountdown);
|
µb.keyvalSetOne('netWhitelist', userData.netWhitelist || '', onCountdown);
|
||||||
|
|
@ -1173,7 +1173,7 @@ var resetUserData = function() {
|
||||||
vAPI.storage.clear();
|
vAPI.storage.clear();
|
||||||
|
|
||||||
// Keep global counts, people can become quite attached to numbers
|
// Keep global counts, people can become quite attached to numbers
|
||||||
µb.saveLocalSettings(true);
|
µb.saveLocalSettings();
|
||||||
|
|
||||||
vAPI.app.restart();
|
vAPI.app.restart();
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -302,10 +302,33 @@ RedirectEngine.prototype.supportedTypes = (function() {
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
RedirectEngine.prototype.toSelfie = function() {
|
RedirectEngine.prototype.toSelfie = function() {
|
||||||
return {
|
var r = {
|
||||||
resources: this.resources,
|
resources: this.resources,
|
||||||
rules: this.rules
|
rules: []
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var typeEntry, desEntry, entries, entry;
|
||||||
|
for ( var type in this.rules ) {
|
||||||
|
typeEntry = this.rules[type];
|
||||||
|
for ( var des in typeEntry ) {
|
||||||
|
desEntry = typeEntry[des];
|
||||||
|
for ( var src in desEntry ) {
|
||||||
|
entries = desEntry[src];
|
||||||
|
for ( var i = 0; i < entries.length; i++ ) {
|
||||||
|
entry = entries[i];
|
||||||
|
r.rules.push(
|
||||||
|
src + '\t' +
|
||||||
|
des + '\t' +
|
||||||
|
type + '\t' +
|
||||||
|
entry.c.source + '\t' +
|
||||||
|
entry.r
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
@ -321,26 +344,10 @@ RedirectEngine.prototype.fromSelfie = function(selfie) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rules.
|
// Rules.
|
||||||
var typeEntry, desEntry, srcEntry;
|
|
||||||
var rules = selfie.rules;
|
var rules = selfie.rules;
|
||||||
for ( var type in rules ) {
|
var i = rules.length;
|
||||||
if ( rules.hasOwnProperty(type) === false ) {
|
while ( i-- ) {
|
||||||
continue;
|
this.fromCompiledRule(rules[i]);
|
||||||
}
|
|
||||||
typeEntry = rules[type];
|
|
||||||
for ( var des in typeEntry ) {
|
|
||||||
if ( typeEntry.hasOwnProperty(des) === false ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
desEntry = typeEntry[des];
|
|
||||||
for ( var src in desEntry ) {
|
|
||||||
if ( desEntry.hasOwnProperty(des) === false ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
srcEntry = desEntry[src];
|
|
||||||
this.addRule(src, des, type, srcEntry.c, srcEntry.r);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -125,7 +125,10 @@ var onSelfieReady = function(selfie) {
|
||||||
if ( publicSuffixList.fromSelfie(selfie.publicSuffixList) !== true ) {
|
if ( publicSuffixList.fromSelfie(selfie.publicSuffixList) !== true ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//console.log('start.js/onSelfieReady: selfie looks good');
|
if ( selfie.redirectEngine === undefined ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
µb.remoteBlacklists = selfie.filterLists;
|
µb.remoteBlacklists = selfie.filterLists;
|
||||||
µb.staticNetFilteringEngine.fromSelfie(selfie.staticNetFilteringEngine);
|
µb.staticNetFilteringEngine.fromSelfie(selfie.staticNetFilteringEngine);
|
||||||
µb.redirectEngine.fromSelfie(selfie.redirectEngine);
|
µb.redirectEngine.fromSelfie(selfie.redirectEngine);
|
||||||
|
|
@ -197,7 +200,7 @@ var onSystemSettingsReady = function(fetched) {
|
||||||
}
|
}
|
||||||
if ( mustSaveSystemSettings ) {
|
if ( mustSaveSystemSettings ) {
|
||||||
fetched.selfie = null;
|
fetched.selfie = null;
|
||||||
µb.destroySelfie();
|
µb.selfieManager.destroy();
|
||||||
vAPI.storage.set(µb.systemSettings, µb.noopFunc);
|
vAPI.storage.set(µb.systemSettings, µb.noopFunc);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -46,28 +46,26 @@
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
µBlock.saveLocalSettings = function(force) {
|
µBlock.saveLocalSettings = (function() {
|
||||||
if ( force ) {
|
var saveAfter = 4 * 60 * 1000;
|
||||||
this.localSettingsModifyTime = Date.now();
|
|
||||||
}
|
|
||||||
if ( this.localSettingsModifyTime <= this.localSettingsSaveTime ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.localSettingsSaveTime = Date.now();
|
|
||||||
vAPI.storage.set(this.localSettings);
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
var save = function() {
|
||||||
|
this.localSettingsSaveTime = Date.now();
|
||||||
|
vAPI.storage.set(this.localSettings);
|
||||||
|
}.bind(µBlock);
|
||||||
|
|
||||||
// Save local settings regularly. Not critical.
|
var onTimeout = function() {
|
||||||
|
var µb = µBlock;
|
||||||
|
if ( µb.localSettingsModifyTime > µb.localSettingsSaveTime ) {
|
||||||
|
save();
|
||||||
|
}
|
||||||
|
vAPI.setTimeout(onTimeout, saveAfter);
|
||||||
|
};
|
||||||
|
|
||||||
µBlock.asyncJobs.add(
|
vAPI.setTimeout(onTimeout, saveAfter);
|
||||||
'autoSaveLocalSettings',
|
|
||||||
null,
|
return save;
|
||||||
µBlock.saveLocalSettings.bind(µBlock),
|
})();
|
||||||
4 * 60 * 1000,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
|
@ -187,6 +185,7 @@
|
||||||
µb.staticNetFilteringEngine.freeze();
|
µb.staticNetFilteringEngine.freeze();
|
||||||
µb.redirectEngine.freeze();
|
µb.redirectEngine.freeze();
|
||||||
µb.cosmeticFilteringEngine.freeze();
|
µb.cosmeticFilteringEngine.freeze();
|
||||||
|
µb.selfieManager.create();
|
||||||
};
|
};
|
||||||
|
|
||||||
var onLoaded = function(details) {
|
var onLoaded = function(details) {
|
||||||
|
|
@ -371,7 +370,7 @@
|
||||||
vAPI.messaging.broadcast({ what: 'allFilterListsReloaded' });
|
vAPI.messaging.broadcast({ what: 'allFilterListsReloaded' });
|
||||||
callback();
|
callback();
|
||||||
|
|
||||||
µb.toSelfieAsync();
|
µb.selfieManager.create();
|
||||||
};
|
};
|
||||||
|
|
||||||
var applyCompiledFilters = function(path, compiled) {
|
var applyCompiledFilters = function(path, compiled) {
|
||||||
|
|
@ -401,7 +400,7 @@
|
||||||
µb.redirectEngine.reset();
|
µb.redirectEngine.reset();
|
||||||
µb.cosmeticFilteringEngine.reset();
|
µb.cosmeticFilteringEngine.reset();
|
||||||
µb.staticNetFilteringEngine.reset();
|
µb.staticNetFilteringEngine.reset();
|
||||||
µb.destroySelfie();
|
µb.selfieManager.destroy();
|
||||||
µb.staticFilteringReverseLookup.resetLists();
|
µb.staticFilteringReverseLookup.resetLists();
|
||||||
|
|
||||||
// We need to build a complete list of assets to pull first: this is
|
// We need to build a complete list of assets to pull first: this is
|
||||||
|
|
@ -649,8 +648,6 @@
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
// TODO: toSelfie/fromSelfie.
|
|
||||||
|
|
||||||
µBlock.loadRedirectResources = function(callback) {
|
µBlock.loadRedirectResources = function(callback) {
|
||||||
var µb = this;
|
var µb = this;
|
||||||
|
|
||||||
|
|
@ -703,43 +700,55 @@
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
µBlock.toSelfie = function() {
|
|
||||||
var selfie = {
|
|
||||||
magic: this.systemSettings.selfieMagic,
|
|
||||||
publicSuffixList: publicSuffixList.toSelfie(),
|
|
||||||
filterLists: this.remoteBlacklists,
|
|
||||||
staticNetFilteringEngine: this.staticNetFilteringEngine.toSelfie(),
|
|
||||||
redirectEngine: this.redirectEngine.toSelfie(),
|
|
||||||
cosmeticFilteringEngine: this.cosmeticFilteringEngine.toSelfie()
|
|
||||||
};
|
|
||||||
vAPI.storage.set({ selfie: selfie });
|
|
||||||
//console.debug('storage.js > µBlock.toSelfie()');
|
|
||||||
};
|
|
||||||
|
|
||||||
// This is to be sure the selfie is generated in a sane manner: the selfie will
|
// This is to be sure the selfie is generated in a sane manner: the selfie will
|
||||||
// be generated if the user doesn't change his filter lists selection for
|
// be generated if the user doesn't change his filter lists selection for
|
||||||
// some set time.
|
// some set time.
|
||||||
|
|
||||||
µBlock.toSelfieAsync = function(after) {
|
µBlock.selfieManager = (function() {
|
||||||
if ( typeof after !== 'number' ) {
|
var µb = µBlock;
|
||||||
after = this.selfieAfter;
|
var timer = null;
|
||||||
}
|
|
||||||
this.asyncJobs.add(
|
|
||||||
'toSelfie',
|
|
||||||
null,
|
|
||||||
this.toSelfie.bind(this),
|
|
||||||
after,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
var create = function() {
|
||||||
|
timer = null;
|
||||||
|
|
||||||
µBlock.destroySelfie = function() {
|
var selfie = {
|
||||||
vAPI.storage.remove('selfie');
|
magic: µb.systemSettings.selfieMagic,
|
||||||
this.asyncJobs.remove('toSelfie');
|
publicSuffixList: publicSuffixList.toSelfie(),
|
||||||
//console.debug('µBlock.destroySelfie()');
|
filterLists: µb.remoteBlacklists,
|
||||||
};
|
staticNetFilteringEngine: µb.staticNetFilteringEngine.toSelfie(),
|
||||||
|
redirectEngine: µb.redirectEngine.toSelfie(),
|
||||||
|
cosmeticFilteringEngine: µb.cosmeticFilteringEngine.toSelfie()
|
||||||
|
};
|
||||||
|
|
||||||
|
vAPI.storage.set({ selfie: selfie });
|
||||||
|
};
|
||||||
|
|
||||||
|
var createAsync = function(after) {
|
||||||
|
if ( typeof after !== 'number' ) {
|
||||||
|
after = µb.selfieAfter;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( timer !== null ) {
|
||||||
|
clearTimeout(timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
timer = vAPI.setTimeout(create, after);
|
||||||
|
};
|
||||||
|
|
||||||
|
var destroy = function() {
|
||||||
|
if ( timer !== null ) {
|
||||||
|
clearTimeout(timer);
|
||||||
|
timer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
vAPI.storage.remove('selfie');
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
create: createAsync,
|
||||||
|
destroy: destroy
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
|
@ -874,6 +883,10 @@
|
||||||
// remote servers.
|
// remote servers.
|
||||||
µb.assets.remoteFetchBarrier += 1;
|
µb.assets.remoteFetchBarrier += 1;
|
||||||
|
|
||||||
|
if ( details.hasOwnProperty('assets/ublock/redirect-resources.txt') ) {
|
||||||
|
µb.loadRedirectResources();
|
||||||
|
}
|
||||||
|
|
||||||
var onFiltersReady = function() {
|
var onFiltersReady = function() {
|
||||||
µb.assets.remoteFetchBarrier -= 1;
|
µb.assets.remoteFetchBarrier -= 1;
|
||||||
};
|
};
|
||||||
|
|
@ -894,10 +907,6 @@
|
||||||
} else {
|
} else {
|
||||||
onPSLReady();
|
onPSLReady();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( details.hasOwnProperty('assets/ublock/redirect-resources.txt') ) {
|
|
||||||
µb.loadRedirectResources();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
@ -925,7 +934,7 @@
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.destroySelfie();
|
this.selfieManager.destroy();
|
||||||
barrier = false;
|
barrier = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -670,6 +670,41 @@ vAPI.tabs.registerListeners();
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
// Update visual of extension icon.
|
||||||
|
|
||||||
|
µb.updateBadgeAsync = (function() {
|
||||||
|
var tabIdToTimer = Object.create(null);
|
||||||
|
|
||||||
|
var updateBadge = function(tabId) {
|
||||||
|
delete tabIdToTimer[tabId];
|
||||||
|
|
||||||
|
var state = false;
|
||||||
|
var badge = '';
|
||||||
|
|
||||||
|
var pageStore = this.pageStoreFromTabId(tabId);
|
||||||
|
if ( pageStore !== null ) {
|
||||||
|
state = pageStore.getNetFilteringSwitch();
|
||||||
|
if ( state && this.userSettings.showIconBadge && pageStore.perLoadBlockedRequestCount ) {
|
||||||
|
badge = this.utils.formatCount(pageStore.perLoadBlockedRequestCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vAPI.setIcon(tabId, state ? 'on' : 'off', badge);
|
||||||
|
};
|
||||||
|
|
||||||
|
return function(tabId) {
|
||||||
|
if ( tabIdToTimer[tabId] ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( vAPI.isBehindTheSceneTabId(tabId) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tabIdToTimer[tabId] = vAPI.setTimeout(updateBadge.bind(this, tabId), 500);
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
µb.updateTitle = (function() {
|
µb.updateTitle = (function() {
|
||||||
var tabIdToTimer = Object.create(null);
|
var tabIdToTimer = Object.create(null);
|
||||||
var tabIdToTryCount = Object.create(null);
|
var tabIdToTryCount = Object.create(null);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue