2014-06-24 00:42:43 +02:00
|
|
|
/*******************************************************************************
|
|
|
|
|
2023-12-04 18:10:34 +01:00
|
|
|
uBlock Origin - a comprehensive, efficient content blocker
|
2018-07-20 19:52:14 +02:00
|
|
|
Copyright (C) 2014-present Raymond Hill
|
2014-06-24 00:42:43 +02:00
|
|
|
|
|
|
|
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
|
|
|
|
*/
|
|
|
|
|
2022-11-06 22:54:32 +01:00
|
|
|
/* globals browser */
|
|
|
|
|
2016-08-13 22:42:58 +02:00
|
|
|
'use strict';
|
2014-06-24 00:42:43 +02:00
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
2021-10-07 20:41:29 +02:00
|
|
|
import './vapi-common.js';
|
|
|
|
import './vapi-background.js';
|
|
|
|
import './vapi-background-ext.js';
|
|
|
|
|
2023-03-07 22:02:09 +01:00
|
|
|
/******************************************************************************/
|
|
|
|
|
2021-10-07 20:41:29 +02:00
|
|
|
// The following modules are loaded here until their content is better organized
|
|
|
|
import './commands.js';
|
|
|
|
import './messaging.js';
|
|
|
|
import './storage.js';
|
|
|
|
import './tab.js';
|
|
|
|
import './ublock.js';
|
|
|
|
import './utils.js';
|
|
|
|
|
2023-12-01 20:35:28 +01:00
|
|
|
import io from './assets.js';
|
|
|
|
import µb from './background.js';
|
|
|
|
import { filteringBehaviorChanged } from './broadcast.js';
|
2021-07-29 01:48:38 +02:00
|
|
|
import cacheStorage from './cachestorage.js';
|
2023-12-01 20:35:28 +01:00
|
|
|
import { ubolog } from './console.js';
|
2021-07-29 01:48:38 +02:00
|
|
|
import contextMenu from './contextmenu.js';
|
2023-12-01 20:35:28 +01:00
|
|
|
import { redirectEngine } from './redirect-engine.js';
|
2021-07-29 01:48:38 +02:00
|
|
|
import staticFilteringReverseLookup from './reverselookup.js';
|
2023-12-01 20:35:28 +01:00
|
|
|
import staticExtFilteringEngine from './static-ext-filtering.js';
|
2021-07-29 01:48:38 +02:00
|
|
|
import staticNetFilteringEngine from './static-net-filtering.js';
|
2021-10-07 20:41:29 +02:00
|
|
|
import webRequest from './traffic.js';
|
2021-07-29 01:48:38 +02:00
|
|
|
|
|
|
|
import {
|
|
|
|
permanentFirewall,
|
|
|
|
sessionFirewall,
|
|
|
|
permanentSwitches,
|
|
|
|
sessionSwitches,
|
|
|
|
permanentURLFiltering,
|
|
|
|
sessionURLFiltering,
|
2021-08-03 18:19:25 +02:00
|
|
|
} from './filtering-engines.js';
|
2021-07-25 16:55:35 +02:00
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
2024-03-03 00:02:43 +01:00
|
|
|
let lastVersionInt = 0;
|
|
|
|
let thisVersionInt = 0;
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
2023-03-07 22:02:09 +01:00
|
|
|
vAPI.app.onShutdown = ( ) => {
|
2021-07-29 01:48:38 +02:00
|
|
|
staticFilteringReverseLookup.shutdown();
|
|
|
|
io.updateStop();
|
|
|
|
staticNetFilteringEngine.reset();
|
|
|
|
staticExtFilteringEngine.reset();
|
|
|
|
sessionFirewall.reset();
|
|
|
|
permanentFirewall.reset();
|
|
|
|
sessionURLFiltering.reset();
|
|
|
|
permanentURLFiltering.reset();
|
|
|
|
sessionSwitches.reset();
|
|
|
|
permanentSwitches.reset();
|
2015-06-11 18:12:23 +02:00
|
|
|
};
|
|
|
|
|
2024-02-28 19:32:24 +01:00
|
|
|
vAPI.alarms.onAlarm.addListener(alarm => {
|
|
|
|
µb.alarmQueue.push(alarm.name);
|
|
|
|
});
|
|
|
|
|
2015-06-11 18:12:23 +02:00
|
|
|
/******************************************************************************/
|
|
|
|
|
2018-10-28 14:58:25 +01:00
|
|
|
// This is called only once, when everything has been loaded in memory after
|
|
|
|
// the extension was launched. It can be used to inject content scripts
|
|
|
|
// in already opened web pages, to remove whatever nuisance could make it to
|
|
|
|
// the web pages before uBlock was ready.
|
2020-07-19 23:41:13 +02:00
|
|
|
//
|
|
|
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=1652925#c19
|
|
|
|
// Mind discarded tabs.
|
2018-10-28 14:58:25 +01:00
|
|
|
|
2023-03-07 22:02:09 +01:00
|
|
|
const initializeTabs = async ( ) => {
|
2019-09-16 22:17:48 +02:00
|
|
|
const manifest = browser.runtime.getManifest();
|
|
|
|
if ( manifest instanceof Object === false ) { return; }
|
|
|
|
|
|
|
|
const toCheck = [];
|
2020-07-19 23:41:13 +02:00
|
|
|
const tabIds = [];
|
|
|
|
{
|
|
|
|
const checker = { file: 'js/scriptlets/should-inject-contentscript.js' };
|
|
|
|
const tabs = await vAPI.tabs.query({ url: '<all_urls>' });
|
|
|
|
for ( const tab of tabs ) {
|
|
|
|
if ( tab.discarded === true ) { continue; }
|
2023-03-30 18:30:44 +02:00
|
|
|
if ( tab.status === 'unloaded' ) { continue; }
|
2020-07-19 23:41:13 +02:00
|
|
|
const { id, url } = tab;
|
|
|
|
µb.tabContextManager.commit(id, url);
|
2021-07-16 14:59:30 +02:00
|
|
|
µb.bindTabToPageStore(id, 'tabCommitted', tab);
|
2020-07-19 23:41:13 +02:00
|
|
|
// https://github.com/chrisaljoudi/uBlock/issues/129
|
|
|
|
// Find out whether content scripts need to be injected
|
|
|
|
// programmatically. This may be necessary for web pages which
|
|
|
|
// were loaded before uBO launched.
|
|
|
|
toCheck.push(
|
|
|
|
/^https?:\/\//.test(url)
|
2020-07-20 00:38:35 +02:00
|
|
|
? vAPI.tabs.executeScript(id, checker)
|
2020-07-19 23:41:13 +02:00
|
|
|
: false
|
|
|
|
);
|
|
|
|
tabIds.push(id);
|
|
|
|
}
|
2019-09-16 15:45:17 +02:00
|
|
|
}
|
2023-03-30 18:30:44 +02:00
|
|
|
// We do not want to block on content scripts injection
|
|
|
|
Promise.all(toCheck).then(results => {
|
|
|
|
for ( let i = 0; i < results.length; i++ ) {
|
|
|
|
const result = results[i];
|
|
|
|
if ( result.length === 0 || result[0] !== true ) { continue; }
|
|
|
|
// Inject declarative content scripts programmatically.
|
|
|
|
for ( const contentScript of manifest.content_scripts ) {
|
|
|
|
for ( const file of contentScript.js ) {
|
|
|
|
vAPI.tabs.executeScript(tabIds[i], {
|
|
|
|
file: file,
|
|
|
|
allFrames: contentScript.all_frames,
|
|
|
|
runAt: contentScript.run_at
|
|
|
|
});
|
|
|
|
}
|
2019-09-16 22:17:48 +02:00
|
|
|
}
|
|
|
|
}
|
2023-03-30 18:30:44 +02:00
|
|
|
});
|
2015-02-13 18:10:10 +01:00
|
|
|
};
|
2014-12-20 21:28:16 +01:00
|
|
|
|
2014-08-21 01:39:49 +02:00
|
|
|
/******************************************************************************/
|
|
|
|
|
2015-02-24 19:48:03 +01:00
|
|
|
// To bring older versions up to date
|
2022-01-19 15:16:01 +01:00
|
|
|
//
|
|
|
|
// https://www.reddit.com/r/uBlockOrigin/comments/s7c9go/
|
|
|
|
// Abort suspending network requests when uBO is merely being installed.
|
2015-02-24 19:48:03 +01:00
|
|
|
|
Redesign cache storage
In uBO, the "cache storage" is used to save resources which can
be safely discarded, though at the cost of having to fetch or
recompute them again.
Extension storage (browser.storage.local) is now always used as
cache storage backend. This has always been the default for
Chromium-based browsers.
For Firefox-based browsers, IndexedDB was used as backend for
cache storage, with fallback to extension storage when using
Firefox in private mode by default.
Extension storage is reliable since it works in all contexts,
though it may not be the most performant one.
To speed-up loading of resources from extension storage, uBO will
now make use of Cache API storage, which will mirror content of
key assets saved to extension storage. Typically loading resources
from Cache API is faster than loading the same resources from
the extension storage.
Only resources which must be loaded in memory as fast as possible
will make use of the Cache API storage layered on top of the
extension storage.
Compiled filter lists and memory snapshot of filtering engines
(aka "selfies") will be mirrored to the Cache API storage, since
these must be loaded into memory as fast as possible, and reloading
filter lists from their compiled counterpart is a common
operation.
This new design makes it now seamless to work in permanent private
mode for Firefox-based browsers, since extension storage now
always contains cache-related assets.
Support for IndexedDB is removed for the time being, except to
support migration of cached assets the first time uBO runs with
the new cache storage design.
In order to easily support all choices of storage, a new serializer
has been introduced, which is capable of serializing/deserializing
structure-cloneable data to/from a JS string.
Because of this new serializer, JS data structures can be stored
directly from their native representation, and deserialized
directly to their native representation from uBO's point of view,
since the serialization occurs (if needed) only at the storage
interface level.
This new serializer simplifies many code paths where data
structures such as Set, Map, TypedArray, RegExp, etc. had to be
converted in a disparate manner to be able to persist them to
extension storage.
The new serializer supports workers and LZ4 compression. These
can be configured through advanced settings.
With this new layered design, it's possible to introduce more
storage layers if measured as beneficial (i.e. maybe
browser.storage.session)
References:
- https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage/local
- https://developer.mozilla.org/en-US/docs/Web/API/Cache
- https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm
2024-02-26 22:50:11 +01:00
|
|
|
const onVersionReady = async lastVersion => {
|
2024-03-03 00:02:43 +01:00
|
|
|
lastVersionInt = vAPI.app.intFromVersion(lastVersion);
|
|
|
|
thisVersionInt = vAPI.app.intFromVersion(vAPI.app.version);
|
|
|
|
if ( thisVersionInt === lastVersionInt ) { return; }
|
2018-03-30 14:55:51 +02:00
|
|
|
|
2023-04-25 20:01:47 +02:00
|
|
|
vAPI.storage.set({
|
|
|
|
version: vAPI.app.version,
|
|
|
|
versionUpdateTime: Date.now(),
|
|
|
|
});
|
2021-06-12 15:18:56 +02:00
|
|
|
|
2022-01-19 15:16:01 +01:00
|
|
|
// Special case: first installation
|
|
|
|
if ( lastVersionInt === 0 ) {
|
|
|
|
vAPI.net.unsuspend({ all: true, discard: true });
|
|
|
|
return;
|
|
|
|
}
|
2021-06-12 15:18:56 +02:00
|
|
|
|
2024-02-28 19:32:24 +01:00
|
|
|
// Remove cache items with obsolete names
|
|
|
|
if ( lastVersionInt < vAPI.app.intFromVersion('1.56.1b5') ) {
|
|
|
|
io.remove(`compiled/${µb.pslAssetKey}`);
|
|
|
|
io.remove('compiled/redirectEngine/resources');
|
|
|
|
io.remove('selfie/main');
|
|
|
|
}
|
|
|
|
|
2019-07-03 15:40:12 +02:00
|
|
|
// Since built-in resources may have changed since last version, we
|
|
|
|
// force a reload of all resources.
|
2021-08-02 15:23:48 +02:00
|
|
|
redirectEngine.invalidateResourcesSelfie(io);
|
2015-02-13 18:10:10 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/******************************************************************************/
|
2014-09-08 23:46:58 +02:00
|
|
|
|
2021-01-04 13:54:24 +01:00
|
|
|
// https://github.com/uBlockOrigin/uBlock-issues/issues/1433
|
|
|
|
// Allow admins to add their own trusted-site directives.
|
2015-02-13 18:10:10 +01:00
|
|
|
|
2023-03-07 22:02:09 +01:00
|
|
|
const onNetWhitelistReady = (netWhitelistRaw, adminExtra) => {
|
2019-06-25 17:57:14 +02:00
|
|
|
if ( typeof netWhitelistRaw === 'string' ) {
|
|
|
|
netWhitelistRaw = netWhitelistRaw.split('\n');
|
|
|
|
}
|
2024-03-03 00:02:43 +01:00
|
|
|
|
|
|
|
// Remove now obsolete built-in trusted directives
|
|
|
|
if ( lastVersionInt !== thisVersionInt ) {
|
|
|
|
if ( lastVersionInt < vAPI.app.intFromVersion('1.56.1b12') ) {
|
|
|
|
const obsolete = [
|
|
|
|
'about-scheme',
|
|
|
|
'chrome-scheme',
|
|
|
|
'edge-scheme',
|
|
|
|
'opera-scheme',
|
|
|
|
'vivaldi-scheme',
|
|
|
|
'wyciwyg-scheme',
|
|
|
|
];
|
|
|
|
for ( const directive of obsolete ) {
|
|
|
|
const i = netWhitelistRaw.findIndex(s =>
|
|
|
|
s === directive || s === `# ${directive}`
|
|
|
|
);
|
|
|
|
if ( i === -1 ) { continue; }
|
|
|
|
netWhitelistRaw.splice(i, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-04 13:54:24 +01:00
|
|
|
// Append admin-controlled trusted-site directives
|
2024-03-03 00:02:43 +01:00
|
|
|
if ( adminExtra instanceof Object ) {
|
|
|
|
if ( Array.isArray(adminExtra.trustedSiteDirectives) ) {
|
|
|
|
for ( const directive of adminExtra.trustedSiteDirectives ) {
|
|
|
|
µb.netWhitelistDefault.push(directive);
|
|
|
|
netWhitelistRaw.push(directive);
|
|
|
|
}
|
2021-01-04 13:54:24 +01:00
|
|
|
}
|
|
|
|
}
|
2024-03-03 00:02:43 +01:00
|
|
|
|
2019-06-25 17:57:14 +02:00
|
|
|
µb.netWhitelist = µb.whitelistFromArray(netWhitelistRaw);
|
2015-02-24 19:48:03 +01:00
|
|
|
µb.netWhitelistModifyTime = Date.now();
|
2015-02-13 18:10:10 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
|
|
|
// User settings are in memory
|
|
|
|
|
2023-03-07 22:02:09 +01:00
|
|
|
const onUserSettingsReady = fetched => {
|
2021-12-30 15:24:38 +01:00
|
|
|
// Terminate suspended state?
|
2022-02-13 15:24:57 +01:00
|
|
|
const tnow = Date.now() - vAPI.T0;
|
|
|
|
if (
|
|
|
|
vAPI.Net.canSuspend() &&
|
|
|
|
fetched.suspendUntilListsAreLoaded === false
|
|
|
|
) {
|
2021-12-30 15:24:38 +01:00
|
|
|
vAPI.net.unsuspend({ all: true, discard: true });
|
2022-02-13 15:24:57 +01:00
|
|
|
ubolog(`Unsuspend network activity listener at ${tnow} ms`);
|
|
|
|
µb.supportStats.unsuspendAfter = `${tnow} ms`;
|
|
|
|
} else if (
|
|
|
|
vAPI.Net.canSuspend() === false &&
|
|
|
|
fetched.suspendUntilListsAreLoaded
|
|
|
|
) {
|
|
|
|
vAPI.net.suspend();
|
|
|
|
ubolog(`Suspend network activity listener at ${tnow} ms`);
|
2021-12-30 15:24:38 +01:00
|
|
|
}
|
|
|
|
|
2021-01-31 16:30:12 +01:00
|
|
|
// `externalLists` will be deprecated in some future, it is kept around
|
|
|
|
// for forward compatibility purpose, and should reflect the content of
|
|
|
|
// `importedLists`.
|
|
|
|
if ( Array.isArray(fetched.externalLists) ) {
|
|
|
|
fetched.externalLists = fetched.externalLists.join('\n');
|
|
|
|
vAPI.storage.set({ externalLists: fetched.externalLists });
|
|
|
|
}
|
|
|
|
if (
|
|
|
|
fetched.importedLists.length === 0 &&
|
|
|
|
fetched.externalLists !== ''
|
|
|
|
) {
|
2024-02-29 19:28:04 +01:00
|
|
|
fetched.importedLists = fetched.externalLists.trim().split(/[\n\r]+/);
|
2021-01-08 15:18:26 +01:00
|
|
|
}
|
|
|
|
|
2021-01-16 16:35:56 +01:00
|
|
|
fromFetch(µb.userSettings, fetched);
|
2014-08-21 16:56:36 +02:00
|
|
|
|
2016-10-19 16:20:26 +02:00
|
|
|
if ( µb.privacySettingsSupported ) {
|
|
|
|
vAPI.browserSettings.set({
|
2021-01-16 16:35:56 +01:00
|
|
|
'hyperlinkAuditing': !µb.userSettings.hyperlinkAuditingDisabled,
|
|
|
|
'prefetching': !µb.userSettings.prefetchingDisabled,
|
2021-09-15 13:40:32 +02:00
|
|
|
'webrtcIPAddress': !µb.userSettings.webrtcIPAddressHidden
|
2016-10-19 16:20:26 +02:00
|
|
|
});
|
|
|
|
}
|
2021-03-02 19:00:56 +01:00
|
|
|
|
|
|
|
// https://github.com/uBlockOrigin/uBlock-issues/issues/1513
|
|
|
|
if (
|
|
|
|
vAPI.net.canUncloakCnames &&
|
|
|
|
µb.userSettings.cnameUncloakEnabled === false
|
|
|
|
) {
|
|
|
|
vAPI.net.setOptions({ cnameUncloakEnabled: false });
|
|
|
|
}
|
2015-02-13 18:10:10 +01:00
|
|
|
};
|
|
|
|
|
2015-02-24 00:31:29 +01:00
|
|
|
/******************************************************************************/
|
|
|
|
|
2019-11-14 14:22:28 +01:00
|
|
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=1588916
|
|
|
|
// Save magic format numbers into the cache storage itself.
|
2020-12-04 12:17:18 +01:00
|
|
|
// https://github.com/uBlockOrigin/uBlock-issues/issues/1365
|
|
|
|
// Wait for removal of invalid cached data to be completed.
|
2015-02-24 19:48:03 +01:00
|
|
|
|
2023-04-22 16:57:10 +02:00
|
|
|
const onCacheSettingsReady = async (fetched = {}) => {
|
Redesign cache storage
In uBO, the "cache storage" is used to save resources which can
be safely discarded, though at the cost of having to fetch or
recompute them again.
Extension storage (browser.storage.local) is now always used as
cache storage backend. This has always been the default for
Chromium-based browsers.
For Firefox-based browsers, IndexedDB was used as backend for
cache storage, with fallback to extension storage when using
Firefox in private mode by default.
Extension storage is reliable since it works in all contexts,
though it may not be the most performant one.
To speed-up loading of resources from extension storage, uBO will
now make use of Cache API storage, which will mirror content of
key assets saved to extension storage. Typically loading resources
from Cache API is faster than loading the same resources from
the extension storage.
Only resources which must be loaded in memory as fast as possible
will make use of the Cache API storage layered on top of the
extension storage.
Compiled filter lists and memory snapshot of filtering engines
(aka "selfies") will be mirrored to the Cache API storage, since
these must be loaded into memory as fast as possible, and reloading
filter lists from their compiled counterpart is a common
operation.
This new design makes it now seamless to work in permanent private
mode for Firefox-based browsers, since extension storage now
always contains cache-related assets.
Support for IndexedDB is removed for the time being, except to
support migration of cached assets the first time uBO runs with
the new cache storage design.
In order to easily support all choices of storage, a new serializer
has been introduced, which is capable of serializing/deserializing
structure-cloneable data to/from a JS string.
Because of this new serializer, JS data structures can be stored
directly from their native representation, and deserialized
directly to their native representation from uBO's point of view,
since the serialization occurs (if needed) only at the storage
interface level.
This new serializer simplifies many code paths where data
structures such as Set, Map, TypedArray, RegExp, etc. had to be
converted in a disparate manner to be able to persist them to
extension storage.
The new serializer supports workers and LZ4 compression. These
can be configured through advanced settings.
With this new layered design, it's possible to introduce more
storage layers if measured as beneficial (i.e. maybe
browser.storage.session)
References:
- https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage/local
- https://developer.mozilla.org/en-US/docs/Web/API/Cache
- https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm
2024-02-26 22:50:11 +01:00
|
|
|
let selfieIsInvalid = false;
|
2015-02-24 19:48:03 +01:00
|
|
|
if ( fetched.compiledMagic !== µb.systemSettings.compiledMagic ) {
|
2019-10-27 16:49:05 +01:00
|
|
|
µb.compiledFormatChanged = true;
|
Redesign cache storage
In uBO, the "cache storage" is used to save resources which can
be safely discarded, though at the cost of having to fetch or
recompute them again.
Extension storage (browser.storage.local) is now always used as
cache storage backend. This has always been the default for
Chromium-based browsers.
For Firefox-based browsers, IndexedDB was used as backend for
cache storage, with fallback to extension storage when using
Firefox in private mode by default.
Extension storage is reliable since it works in all contexts,
though it may not be the most performant one.
To speed-up loading of resources from extension storage, uBO will
now make use of Cache API storage, which will mirror content of
key assets saved to extension storage. Typically loading resources
from Cache API is faster than loading the same resources from
the extension storage.
Only resources which must be loaded in memory as fast as possible
will make use of the Cache API storage layered on top of the
extension storage.
Compiled filter lists and memory snapshot of filtering engines
(aka "selfies") will be mirrored to the Cache API storage, since
these must be loaded into memory as fast as possible, and reloading
filter lists from their compiled counterpart is a common
operation.
This new design makes it now seamless to work in permanent private
mode for Firefox-based browsers, since extension storage now
always contains cache-related assets.
Support for IndexedDB is removed for the time being, except to
support migration of cached assets the first time uBO runs with
the new cache storage design.
In order to easily support all choices of storage, a new serializer
has been introduced, which is capable of serializing/deserializing
structure-cloneable data to/from a JS string.
Because of this new serializer, JS data structures can be stored
directly from their native representation, and deserialized
directly to their native representation from uBO's point of view,
since the serialization occurs (if needed) only at the storage
interface level.
This new serializer simplifies many code paths where data
structures such as Set, Map, TypedArray, RegExp, etc. had to be
converted in a disparate manner to be able to persist them to
extension storage.
The new serializer supports workers and LZ4 compression. These
can be configured through advanced settings.
With this new layered design, it's possible to introduce more
storage layers if measured as beneficial (i.e. maybe
browser.storage.session)
References:
- https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage/local
- https://developer.mozilla.org/en-US/docs/Web/API/Cache
- https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm
2024-02-26 22:50:11 +01:00
|
|
|
selfieIsInvalid = true;
|
2021-12-04 16:55:33 +01:00
|
|
|
ubolog(`Serialized format of static filter lists changed`);
|
2015-02-24 00:31:29 +01:00
|
|
|
}
|
2015-02-24 19:48:03 +01:00
|
|
|
if ( fetched.selfieMagic !== µb.systemSettings.selfieMagic ) {
|
Redesign cache storage
In uBO, the "cache storage" is used to save resources which can
be safely discarded, though at the cost of having to fetch or
recompute them again.
Extension storage (browser.storage.local) is now always used as
cache storage backend. This has always been the default for
Chromium-based browsers.
For Firefox-based browsers, IndexedDB was used as backend for
cache storage, with fallback to extension storage when using
Firefox in private mode by default.
Extension storage is reliable since it works in all contexts,
though it may not be the most performant one.
To speed-up loading of resources from extension storage, uBO will
now make use of Cache API storage, which will mirror content of
key assets saved to extension storage. Typically loading resources
from Cache API is faster than loading the same resources from
the extension storage.
Only resources which must be loaded in memory as fast as possible
will make use of the Cache API storage layered on top of the
extension storage.
Compiled filter lists and memory snapshot of filtering engines
(aka "selfies") will be mirrored to the Cache API storage, since
these must be loaded into memory as fast as possible, and reloading
filter lists from their compiled counterpart is a common
operation.
This new design makes it now seamless to work in permanent private
mode for Firefox-based browsers, since extension storage now
always contains cache-related assets.
Support for IndexedDB is removed for the time being, except to
support migration of cached assets the first time uBO runs with
the new cache storage design.
In order to easily support all choices of storage, a new serializer
has been introduced, which is capable of serializing/deserializing
structure-cloneable data to/from a JS string.
Because of this new serializer, JS data structures can be stored
directly from their native representation, and deserialized
directly to their native representation from uBO's point of view,
since the serialization occurs (if needed) only at the storage
interface level.
This new serializer simplifies many code paths where data
structures such as Set, Map, TypedArray, RegExp, etc. had to be
converted in a disparate manner to be able to persist them to
extension storage.
The new serializer supports workers and LZ4 compression. These
can be configured through advanced settings.
With this new layered design, it's possible to introduce more
storage layers if measured as beneficial (i.e. maybe
browser.storage.session)
References:
- https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage/local
- https://developer.mozilla.org/en-US/docs/Web/API/Cache
- https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm
2024-02-26 22:50:11 +01:00
|
|
|
selfieIsInvalid = true;
|
2021-12-04 16:55:33 +01:00
|
|
|
ubolog(`Serialized format of selfie changed`);
|
2015-02-24 00:31:29 +01:00
|
|
|
}
|
Redesign cache storage
In uBO, the "cache storage" is used to save resources which can
be safely discarded, though at the cost of having to fetch or
recompute them again.
Extension storage (browser.storage.local) is now always used as
cache storage backend. This has always been the default for
Chromium-based browsers.
For Firefox-based browsers, IndexedDB was used as backend for
cache storage, with fallback to extension storage when using
Firefox in private mode by default.
Extension storage is reliable since it works in all contexts,
though it may not be the most performant one.
To speed-up loading of resources from extension storage, uBO will
now make use of Cache API storage, which will mirror content of
key assets saved to extension storage. Typically loading resources
from Cache API is faster than loading the same resources from
the extension storage.
Only resources which must be loaded in memory as fast as possible
will make use of the Cache API storage layered on top of the
extension storage.
Compiled filter lists and memory snapshot of filtering engines
(aka "selfies") will be mirrored to the Cache API storage, since
these must be loaded into memory as fast as possible, and reloading
filter lists from their compiled counterpart is a common
operation.
This new design makes it now seamless to work in permanent private
mode for Firefox-based browsers, since extension storage now
always contains cache-related assets.
Support for IndexedDB is removed for the time being, except to
support migration of cached assets the first time uBO runs with
the new cache storage design.
In order to easily support all choices of storage, a new serializer
has been introduced, which is capable of serializing/deserializing
structure-cloneable data to/from a JS string.
Because of this new serializer, JS data structures can be stored
directly from their native representation, and deserialized
directly to their native representation from uBO's point of view,
since the serialization occurs (if needed) only at the storage
interface level.
This new serializer simplifies many code paths where data
structures such as Set, Map, TypedArray, RegExp, etc. had to be
converted in a disparate manner to be able to persist them to
extension storage.
The new serializer supports workers and LZ4 compression. These
can be configured through advanced settings.
With this new layered design, it's possible to introduce more
storage layers if measured as beneficial (i.e. maybe
browser.storage.session)
References:
- https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage/local
- https://developer.mozilla.org/en-US/docs/Web/API/Cache
- https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm
2024-02-26 22:50:11 +01:00
|
|
|
if ( selfieIsInvalid === false ) { return; }
|
|
|
|
µb.selfieManager.destroy({ janitor: true });
|
|
|
|
cacheStorage.set(µb.systemSettings);
|
2015-02-24 19:48:03 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
2023-03-07 22:02:09 +01:00
|
|
|
const onHiddenSettingsReady = async ( ) => {
|
2021-09-22 15:37:21 +02:00
|
|
|
// Maybe customize webext flavor
|
|
|
|
if ( µb.hiddenSettings.modifyWebextFlavor !== 'unset' ) {
|
|
|
|
const tokens = µb.hiddenSettings.modifyWebextFlavor.split(/\s+/);
|
|
|
|
for ( const token of tokens ) {
|
|
|
|
switch ( token[0] ) {
|
|
|
|
case '+':
|
|
|
|
vAPI.webextFlavor.soup.add(token.slice(1));
|
|
|
|
break;
|
|
|
|
case '-':
|
|
|
|
vAPI.webextFlavor.soup.delete(token.slice(1));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
vAPI.webextFlavor.soup.add(token);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ubolog(`Override default webext flavor with ${tokens}`);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Maybe disable WebAssembly
|
|
|
|
if ( vAPI.canWASM && µb.hiddenSettings.disableWebAssembly !== true ) {
|
|
|
|
const wasmModuleFetcher = function(path) {
|
|
|
|
return fetch(`${path}.wasm`, { mode: 'same-origin' }).then(
|
|
|
|
WebAssembly.compileStreaming
|
|
|
|
).catch(reason => {
|
|
|
|
ubolog(reason);
|
|
|
|
});
|
|
|
|
};
|
|
|
|
staticNetFilteringEngine.enableWASM(wasmModuleFetcher, './js/wasm/').then(result => {
|
|
|
|
if ( result !== true ) { return; }
|
|
|
|
ubolog(`WASM modules ready ${Date.now()-vAPI.T0} ms after launch`);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
2023-03-07 22:02:09 +01:00
|
|
|
const onFirstFetchReady = (fetched, adminExtra) => {
|
2019-04-03 18:18:47 +02:00
|
|
|
// https://github.com/uBlockOrigin/uBlock-issues/issues/507
|
|
|
|
// Firefox-specific: somehow `fetched` is undefined under certain
|
|
|
|
// circumstances even though we asked to load with default values.
|
|
|
|
if ( fetched instanceof Object === false ) {
|
|
|
|
fetched = createDefaultProps();
|
|
|
|
}
|
|
|
|
|
2015-02-24 19:48:03 +01:00
|
|
|
// Order is important -- do not change:
|
2015-03-07 05:36:09 +01:00
|
|
|
fromFetch(µb.restoreBackupSettings, fetched);
|
2021-01-16 16:35:56 +01:00
|
|
|
|
2021-07-29 01:48:38 +02:00
|
|
|
permanentFirewall.fromString(fetched.dynamicFilteringString);
|
|
|
|
sessionFirewall.assign(permanentFirewall);
|
|
|
|
permanentURLFiltering.fromString(fetched.urlFilteringString);
|
|
|
|
sessionURLFiltering.assign(permanentURLFiltering);
|
|
|
|
permanentSwitches.fromString(fetched.hostnameSwitchesString);
|
|
|
|
sessionSwitches.assign(permanentSwitches);
|
2021-01-16 16:35:56 +01:00
|
|
|
|
2021-01-04 13:54:24 +01:00
|
|
|
onNetWhitelistReady(fetched.netWhitelist, adminExtra);
|
2015-02-24 19:48:03 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
2023-03-07 22:02:09 +01:00
|
|
|
const toFetch = (from, fetched) => {
|
2019-02-14 19:33:55 +01:00
|
|
|
for ( const k in from ) {
|
|
|
|
if ( from.hasOwnProperty(k) === false ) { continue; }
|
2015-02-24 19:48:03 +01:00
|
|
|
fetched[k] = from[k];
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2023-03-07 22:02:09 +01:00
|
|
|
const fromFetch = (to, fetched) => {
|
2019-02-14 19:33:55 +01:00
|
|
|
for ( const k in to ) {
|
|
|
|
if ( to.hasOwnProperty(k) === false ) { continue; }
|
|
|
|
if ( fetched.hasOwnProperty(k) === false ) { continue; }
|
2015-02-24 19:48:03 +01:00
|
|
|
to[k] = fetched[k];
|
|
|
|
}
|
2015-02-24 00:31:29 +01:00
|
|
|
};
|
|
|
|
|
2023-03-07 22:02:09 +01:00
|
|
|
const createDefaultProps = ( ) => {
|
2019-02-14 19:33:55 +01:00
|
|
|
const fetchableProps = {
|
2021-10-12 17:19:56 +02:00
|
|
|
'dynamicFilteringString': µb.dynamicFilteringDefault.join('\n'),
|
2016-01-03 19:58:25 +01:00
|
|
|
'urlFilteringString': '',
|
2021-10-12 17:19:56 +02:00
|
|
|
'hostnameSwitchesString': µb.hostnameSwitchesDefault.join('\n'),
|
2019-06-25 17:57:14 +02:00
|
|
|
'netWhitelist': µb.netWhitelistDefault,
|
2016-01-03 19:58:25 +01:00
|
|
|
'version': '0.0.0.0'
|
2015-10-21 17:53:03 +02:00
|
|
|
};
|
2016-01-03 19:58:25 +01:00
|
|
|
toFetch(µb.restoreBackupSettings, fetchableProps);
|
2019-04-03 18:18:47 +02:00
|
|
|
return fetchableProps;
|
2016-01-03 19:58:25 +01:00
|
|
|
};
|
2017-01-26 16:17:38 +01:00
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
2023-12-10 18:33:51 +01:00
|
|
|
(async ( ) => {
|
|
|
|
// >>>>> start of async/await scope
|
|
|
|
|
2019-09-15 13:58:28 +02:00
|
|
|
try {
|
2023-03-18 19:37:49 +01:00
|
|
|
ubolog(`Start sequence of loading storage-based data ${Date.now()-vAPI.T0} ms after launch`);
|
|
|
|
|
2019-09-15 13:58:28 +02:00
|
|
|
// https://github.com/gorhill/uBlock/issues/531
|
|
|
|
await µb.restoreAdminSettings();
|
2021-07-29 01:48:38 +02:00
|
|
|
ubolog(`Admin settings ready ${Date.now()-vAPI.T0} ms after launch`);
|
2019-02-17 21:40:09 +01:00
|
|
|
|
2019-09-15 13:58:28 +02:00
|
|
|
await µb.loadHiddenSettings();
|
2021-10-13 14:31:04 +02:00
|
|
|
await onHiddenSettingsReady();
|
2021-07-29 01:48:38 +02:00
|
|
|
ubolog(`Hidden settings ready ${Date.now()-vAPI.T0} ms after launch`);
|
2016-01-03 19:58:25 +01:00
|
|
|
|
2021-01-05 18:16:50 +01:00
|
|
|
const adminExtra = await vAPI.adminStorage.get('toAdd');
|
2021-07-29 01:48:38 +02:00
|
|
|
ubolog(`Extra admin settings ready ${Date.now()-vAPI.T0} ms after launch`);
|
2021-01-04 13:54:24 +01:00
|
|
|
|
2024-02-28 23:31:29 +01:00
|
|
|
// Maybe override default cache storage
|
|
|
|
µb.supportStats.cacheBackend = await cacheStorage.select(
|
|
|
|
µb.hiddenSettings.cacheStorageAPI
|
|
|
|
);
|
|
|
|
ubolog(`Backend storage for cache will be ${µb.supportStats.cacheBackend}`);
|
|
|
|
|
2024-03-03 00:02:43 +01:00
|
|
|
await vAPI.storage.get(createDefaultProps()).then(async fetched => {
|
Redesign cache storage
In uBO, the "cache storage" is used to save resources which can
be safely discarded, though at the cost of having to fetch or
recompute them again.
Extension storage (browser.storage.local) is now always used as
cache storage backend. This has always been the default for
Chromium-based browsers.
For Firefox-based browsers, IndexedDB was used as backend for
cache storage, with fallback to extension storage when using
Firefox in private mode by default.
Extension storage is reliable since it works in all contexts,
though it may not be the most performant one.
To speed-up loading of resources from extension storage, uBO will
now make use of Cache API storage, which will mirror content of
key assets saved to extension storage. Typically loading resources
from Cache API is faster than loading the same resources from
the extension storage.
Only resources which must be loaded in memory as fast as possible
will make use of the Cache API storage layered on top of the
extension storage.
Compiled filter lists and memory snapshot of filtering engines
(aka "selfies") will be mirrored to the Cache API storage, since
these must be loaded into memory as fast as possible, and reloading
filter lists from their compiled counterpart is a common
operation.
This new design makes it now seamless to work in permanent private
mode for Firefox-based browsers, since extension storage now
always contains cache-related assets.
Support for IndexedDB is removed for the time being, except to
support migration of cached assets the first time uBO runs with
the new cache storage design.
In order to easily support all choices of storage, a new serializer
has been introduced, which is capable of serializing/deserializing
structure-cloneable data to/from a JS string.
Because of this new serializer, JS data structures can be stored
directly from their native representation, and deserialized
directly to their native representation from uBO's point of view,
since the serialization occurs (if needed) only at the storage
interface level.
This new serializer simplifies many code paths where data
structures such as Set, Map, TypedArray, RegExp, etc. had to be
converted in a disparate manner to be able to persist them to
extension storage.
The new serializer supports workers and LZ4 compression. These
can be configured through advanced settings.
With this new layered design, it's possible to introduce more
storage layers if measured as beneficial (i.e. maybe
browser.storage.session)
References:
- https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage/local
- https://developer.mozilla.org/en-US/docs/Web/API/Cache
- https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm
2024-02-26 22:50:11 +01:00
|
|
|
ubolog(`Version ready ${Date.now()-vAPI.T0} ms after launch`);
|
|
|
|
await onVersionReady(fetched.version);
|
|
|
|
return fetched;
|
|
|
|
}).then(fetched => {
|
|
|
|
ubolog(`First fetch ready ${Date.now()-vAPI.T0} ms after launch`);
|
|
|
|
onFirstFetchReady(fetched, adminExtra);
|
|
|
|
});
|
|
|
|
|
|
|
|
await Promise.all([
|
2019-09-15 13:58:28 +02:00
|
|
|
µb.loadSelectedFilterLists().then(( ) => {
|
2021-07-29 01:48:38 +02:00
|
|
|
ubolog(`List selection ready ${Date.now()-vAPI.T0} ms after launch`);
|
2019-09-15 13:58:28 +02:00
|
|
|
}),
|
2021-01-16 16:35:56 +01:00
|
|
|
µb.loadUserSettings().then(fetched => {
|
2021-07-29 01:48:38 +02:00
|
|
|
ubolog(`User settings ready ${Date.now()-vAPI.T0} ms after launch`);
|
2021-01-16 16:35:56 +01:00
|
|
|
onUserSettingsReady(fetched);
|
|
|
|
}),
|
2019-09-15 13:58:28 +02:00
|
|
|
µb.loadPublicSuffixList().then(( ) => {
|
2021-07-29 01:48:38 +02:00
|
|
|
ubolog(`PSL ready ${Date.now()-vAPI.T0} ms after launch`);
|
2019-09-15 13:58:28 +02:00
|
|
|
}),
|
Redesign cache storage
In uBO, the "cache storage" is used to save resources which can
be safely discarded, though at the cost of having to fetch or
recompute them again.
Extension storage (browser.storage.local) is now always used as
cache storage backend. This has always been the default for
Chromium-based browsers.
For Firefox-based browsers, IndexedDB was used as backend for
cache storage, with fallback to extension storage when using
Firefox in private mode by default.
Extension storage is reliable since it works in all contexts,
though it may not be the most performant one.
To speed-up loading of resources from extension storage, uBO will
now make use of Cache API storage, which will mirror content of
key assets saved to extension storage. Typically loading resources
from Cache API is faster than loading the same resources from
the extension storage.
Only resources which must be loaded in memory as fast as possible
will make use of the Cache API storage layered on top of the
extension storage.
Compiled filter lists and memory snapshot of filtering engines
(aka "selfies") will be mirrored to the Cache API storage, since
these must be loaded into memory as fast as possible, and reloading
filter lists from their compiled counterpart is a common
operation.
This new design makes it now seamless to work in permanent private
mode for Firefox-based browsers, since extension storage now
always contains cache-related assets.
Support for IndexedDB is removed for the time being, except to
support migration of cached assets the first time uBO runs with
the new cache storage design.
In order to easily support all choices of storage, a new serializer
has been introduced, which is capable of serializing/deserializing
structure-cloneable data to/from a JS string.
Because of this new serializer, JS data structures can be stored
directly from their native representation, and deserialized
directly to their native representation from uBO's point of view,
since the serialization occurs (if needed) only at the storage
interface level.
This new serializer simplifies many code paths where data
structures such as Set, Map, TypedArray, RegExp, etc. had to be
converted in a disparate manner to be able to persist them to
extension storage.
The new serializer supports workers and LZ4 compression. These
can be configured through advanced settings.
With this new layered design, it's possible to introduce more
storage layers if measured as beneficial (i.e. maybe
browser.storage.session)
References:
- https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage/local
- https://developer.mozilla.org/en-US/docs/Web/API/Cache
- https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm
2024-02-26 22:50:11 +01:00
|
|
|
cacheStorage.get({ compiledMagic: 0, selfieMagic: 0 }).then(bin => {
|
|
|
|
ubolog(`Cache magic numbers ready ${Date.now()-vAPI.T0} ms after launch`);
|
|
|
|
onCacheSettingsReady(bin);
|
|
|
|
}),
|
2024-02-29 17:43:51 +01:00
|
|
|
µb.loadLocalSettings(),
|
2019-09-15 13:58:28 +02:00
|
|
|
]);
|
2021-06-12 15:18:56 +02:00
|
|
|
|
|
|
|
// https://github.com/uBlockOrigin/uBlock-issues/issues/1547
|
2024-03-03 00:02:43 +01:00
|
|
|
if ( lastVersionInt === 0 && vAPI.webextFlavor.soup.has('chromium') ) {
|
2021-06-12 15:18:56 +02:00
|
|
|
vAPI.app.restart();
|
|
|
|
return;
|
|
|
|
}
|
2019-12-14 17:14:00 +01:00
|
|
|
} catch (ex) {
|
|
|
|
console.trace(ex);
|
|
|
|
}
|
2019-09-15 13:58:28 +02:00
|
|
|
|
2020-02-23 18:18:45 +01:00
|
|
|
// Prime the filtering engines before first use.
|
2021-07-29 01:48:38 +02:00
|
|
|
staticNetFilteringEngine.prime();
|
2020-02-23 18:18:45 +01:00
|
|
|
|
2019-12-14 17:14:00 +01:00
|
|
|
// https://github.com/uBlockOrigin/uBlock-issues/issues/817#issuecomment-565730122
|
|
|
|
// Still try to load filter lists regardless of whether a serious error
|
|
|
|
// occurred in the previous initialization steps.
|
2020-01-21 16:52:13 +01:00
|
|
|
let selfieIsValid = false;
|
2019-12-14 17:14:00 +01:00
|
|
|
try {
|
2020-01-21 16:52:13 +01:00
|
|
|
selfieIsValid = await µb.selfieManager.load();
|
2019-09-15 13:58:28 +02:00
|
|
|
if ( selfieIsValid === true ) {
|
2024-02-28 19:32:24 +01:00
|
|
|
ubolog(`Loaded filtering engine from selfie ${Date.now()-vAPI.T0} ms after launch`);
|
2019-09-15 13:58:28 +02:00
|
|
|
}
|
|
|
|
} catch (ex) {
|
|
|
|
console.trace(ex);
|
|
|
|
}
|
2020-01-21 16:52:13 +01:00
|
|
|
if ( selfieIsValid !== true ) {
|
|
|
|
try {
|
|
|
|
await µb.loadFilterLists();
|
2021-07-29 01:48:38 +02:00
|
|
|
ubolog(`Filter lists ready ${Date.now()-vAPI.T0} ms after launch`);
|
2020-01-21 16:52:13 +01:00
|
|
|
} catch (ex) {
|
|
|
|
console.trace(ex);
|
|
|
|
}
|
|
|
|
}
|
2016-01-03 19:58:25 +01:00
|
|
|
|
2023-04-03 16:19:06 +02:00
|
|
|
// Flush memory cache -- unsure whether the browser does this internally
|
|
|
|
// when loading a new extension.
|
2023-12-01 20:35:28 +01:00
|
|
|
filteringBehaviorChanged();
|
2023-04-03 16:19:06 +02:00
|
|
|
|
2019-09-16 22:17:48 +02:00
|
|
|
// Final initialization steps after all needed assets are in memory.
|
|
|
|
|
2020-04-04 17:34:43 +02:00
|
|
|
// https://github.com/uBlockOrigin/uBlock-issues/issues/974
|
|
|
|
// This can be used to defer filtering decision-making.
|
|
|
|
µb.readyToFilter = true;
|
|
|
|
|
2023-03-30 18:30:44 +02:00
|
|
|
// Initialize internal state with maybe already existing tabs.
|
|
|
|
await initializeTabs();
|
|
|
|
|
2019-09-20 13:51:47 +02:00
|
|
|
// Start network observers.
|
2021-07-29 01:48:38 +02:00
|
|
|
webRequest.start();
|
2019-09-16 22:17:48 +02:00
|
|
|
|
2019-09-20 13:51:47 +02:00
|
|
|
// Force an update of the context menu according to the currently
|
|
|
|
// active tab.
|
2021-07-29 01:48:38 +02:00
|
|
|
contextMenu.update();
|
2019-09-16 22:17:48 +02:00
|
|
|
|
|
|
|
// https://github.com/uBlockOrigin/uBlock-issues/issues/717
|
2019-09-20 13:51:47 +02:00
|
|
|
// Prevent the extension from being restarted mid-session.
|
2019-09-16 22:17:48 +02:00
|
|
|
browser.runtime.onUpdateAvailable.addListener(details => {
|
|
|
|
const toInt = vAPI.app.intFromVersion;
|
|
|
|
if (
|
2021-07-25 16:55:35 +02:00
|
|
|
µb.hiddenSettings.extensionUpdateForceReload === true ||
|
2019-09-16 22:17:48 +02:00
|
|
|
toInt(details.version) <= toInt(vAPI.app.version)
|
|
|
|
) {
|
|
|
|
vAPI.app.restart();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2021-12-30 15:24:38 +01:00
|
|
|
µb.supportStats.allReadyAfter = `${Date.now() - vAPI.T0} ms`;
|
2021-12-08 19:43:02 +01:00
|
|
|
if ( selfieIsValid ) {
|
2021-12-30 15:24:38 +01:00
|
|
|
µb.supportStats.allReadyAfter += ' (selfie)';
|
2021-12-08 19:43:02 +01:00
|
|
|
}
|
2022-12-18 21:36:59 +01:00
|
|
|
ubolog(`All ready ${µb.supportStats.allReadyAfter} after launch`);
|
2015-03-11 23:26:00 +01:00
|
|
|
|
2023-12-10 18:33:51 +01:00
|
|
|
µb.isReadyResolve();
|
|
|
|
|
2024-03-02 01:52:55 +01:00
|
|
|
|
|
|
|
// https://github.com/chrisaljoudi/uBlock/issues/184
|
|
|
|
// Check for updates not too far in the future.
|
|
|
|
io.addObserver(µb.assetObserver.bind(µb));
|
|
|
|
if ( µb.userSettings.autoUpdate ) {
|
|
|
|
let needEmergencyUpdate = false;
|
|
|
|
const entries = await io.getUpdateAges({
|
|
|
|
filters: µb.selectedFilterLists,
|
|
|
|
internal: [ '*' ],
|
|
|
|
});
|
|
|
|
for ( const entry of entries ) {
|
|
|
|
if ( entry.ageNormalized < 2 ) { continue; }
|
|
|
|
needEmergencyUpdate = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
const updateDelay = needEmergencyUpdate
|
|
|
|
? 2000
|
|
|
|
: µb.hiddenSettings.autoUpdateDelayAfterLaunch * 1000;
|
|
|
|
µb.scheduleAssetUpdater({
|
|
|
|
auto: true,
|
|
|
|
updateDelay,
|
|
|
|
fetchDelay: needEmergencyUpdate ? 1000 : undefined
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2024-02-28 19:32:24 +01:00
|
|
|
// Process alarm queue
|
|
|
|
while ( µb.alarmQueue.length !== 0 ) {
|
|
|
|
const what = µb.alarmQueue.shift();
|
|
|
|
ubolog(`Processing alarm event from suspended state: '${what}'`);
|
|
|
|
switch ( what ) {
|
2024-03-02 01:52:55 +01:00
|
|
|
case 'assetUpdater':
|
|
|
|
µb.scheduleAssetUpdater({ auto: true, updateDelay: 2000, fetchDelay : 1000 });
|
|
|
|
break;
|
2024-02-28 19:32:24 +01:00
|
|
|
case 'createSelfie':
|
|
|
|
µb.selfieManager.create();
|
|
|
|
break;
|
2024-02-29 17:43:51 +01:00
|
|
|
case 'saveLocalSettings':
|
|
|
|
µb.saveLocalSettings();
|
|
|
|
break;
|
2024-02-28 19:32:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-10 18:33:51 +01:00
|
|
|
// <<<<< end of async/await scope
|
2019-09-15 13:58:28 +02:00
|
|
|
})();
|