mirror of
https://github.com/gorhill/uBlock.git
synced 2026-03-11 09:04:36 +00:00
Possibly will fix cases of no content scripts found in Safari. Related issue: https://github.com/uBlockOrigin/uAssets/issues/30158#issuecomment-3869144473
788 lines
24 KiB
JavaScript
788 lines
24 KiB
JavaScript
/*******************************************************************************
|
|
|
|
uBlock Origin Lite - a comprehensive, MV3-compliant content blocker
|
|
Copyright (C) 2022-present 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
|
|
*/
|
|
|
|
import * as scrmgr from './scripting-manager.js';
|
|
|
|
import {
|
|
MODE_BASIC,
|
|
MODE_OPTIMAL,
|
|
defaultFilteringModes,
|
|
getDefaultFilteringMode,
|
|
getFilteringMode,
|
|
getFilteringModeDetails,
|
|
persistHostPermissions,
|
|
setDefaultFilteringMode,
|
|
setFilteringMode,
|
|
setFilteringModeDetails,
|
|
syncWithBrowserPermissions,
|
|
} from './mode-manager.js';
|
|
|
|
import {
|
|
addCustomFilters,
|
|
customFiltersFromHostname,
|
|
getAllCustomFilters,
|
|
hasCustomFilters,
|
|
injectCustomFilters,
|
|
removeAllCustomFilters,
|
|
removeCustomFilters,
|
|
startCustomFilters,
|
|
terminateCustomFilters,
|
|
} from './filter-manager.js';
|
|
|
|
import {
|
|
adminReadEx,
|
|
getAdminRulesets,
|
|
loadAdminConfig,
|
|
} from './admin.js';
|
|
|
|
import {
|
|
broadcastMessage,
|
|
hostnameFromMatch,
|
|
hostnamesFromMatches,
|
|
} from './utils.js';
|
|
|
|
import {
|
|
browser,
|
|
localRead, localRemove, localWrite,
|
|
runtime,
|
|
sessionAccessLevel,
|
|
webextFlavor,
|
|
} from './ext.js';
|
|
|
|
import {
|
|
defaultConfig,
|
|
loadRulesetConfig,
|
|
process,
|
|
rulesetConfig,
|
|
saveRulesetConfig,
|
|
} from './config.js';
|
|
|
|
import {
|
|
enableRulesets,
|
|
excludeFromStrictBlock,
|
|
getDefaultRulesetsFromEnv,
|
|
getEffectiveDynamicRules,
|
|
getEffectiveSessionRules,
|
|
getEffectiveUserRules,
|
|
getRulesetDetails,
|
|
patchDefaultRulesets,
|
|
setStrictBlockMode,
|
|
updateDynamicRules,
|
|
updateSessionRules,
|
|
updateUserRules,
|
|
} from './ruleset-manager.js';
|
|
|
|
import {
|
|
getConsoleOutput,
|
|
getMatchedRules,
|
|
isSideloaded,
|
|
toggleDeveloperMode,
|
|
ubolErr,
|
|
ubolLog,
|
|
} from './debug.js';
|
|
|
|
import {
|
|
gotoURL,
|
|
hasBroadHostPermissions,
|
|
} from './ext-utils.js';
|
|
|
|
import { dnr } from './ext-compat.js';
|
|
import { toggleToolbarIcon } from './action.js';
|
|
|
|
/******************************************************************************/
|
|
|
|
const UBOL_ORIGIN = runtime.getURL('').replace(/\/$/, '').toLowerCase();
|
|
const canShowBlockedCount = typeof dnr.setExtensionActionOptions === 'function';
|
|
const { registerInjectables } = scrmgr;
|
|
|
|
let pendingPermissionRequest;
|
|
|
|
/******************************************************************************/
|
|
|
|
function getCurrentVersion() {
|
|
return runtime.getManifest().version;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
|
|
async function reloadTab(tabId, url = '') {
|
|
return new Promise(resolve => {
|
|
self.setTimeout(( ) => {
|
|
if ( url !== '' ) {
|
|
browser.tabs.update(tabId, { url });
|
|
} else {
|
|
browser.tabs.reload(tabId);
|
|
}
|
|
resolve();
|
|
}, 437);
|
|
});
|
|
}
|
|
|
|
// When a new host permission is granted through the popup panel
|
|
async function onPermissionGrantedThruExtension(details, origins) {
|
|
await persistHostPermissions();
|
|
const defaultMode = await getDefaultFilteringMode();
|
|
if ( defaultMode >= MODE_OPTIMAL ) { return; }
|
|
if ( Array.isArray(origins) === false ) { return; }
|
|
const hostnames = hostnamesFromMatches(origins);
|
|
if ( hostnames.includes(details.hostname) === false ) { return; }
|
|
const beforeLevel = await getFilteringMode(details.hostname);
|
|
if ( beforeLevel === details.afterLevel ) { return; }
|
|
const afterLevel = await setFilteringMode(details.hostname, details.afterLevel);
|
|
if ( afterLevel !== details.afterLevel ) { return; }
|
|
await registerInjectables();
|
|
if ( rulesetConfig.autoReload !== true ) { return; }
|
|
await reloadTab(details.tabId, details.url);
|
|
}
|
|
|
|
// When a new host permission is granted through the browser
|
|
async function onPermissionGrantedThruBrowser(origins) {
|
|
const modified = await syncWithBrowserPermissions();
|
|
if ( modified === false ) { return; }
|
|
await registerInjectables();
|
|
if ( rulesetConfig.autoReload !== true ) { return; }
|
|
if ( origins.length !== 1 ) { return; }
|
|
const tabs = await browser.tabs.query({ active: true, currentWindow: true });
|
|
const tabId = tabs?.[0]?.id;
|
|
if ( typeof tabId !== 'number' || tabId === -1 ) { return; }
|
|
const results = await browser.scripting.executeScript({
|
|
target: { tabId, frameIds: [ 0 ] },
|
|
func: ( ) => document.location.hostname,
|
|
}).catch(( ) => {
|
|
});
|
|
const tabHostname = results?.[0]?.result;
|
|
if ( typeof tabHostname !== 'string' ) { return; }
|
|
const hostname = hostnameFromMatch(origins[0]);
|
|
if ( tabHostname.endsWith(hostname) === false ) { return; }
|
|
const pos = tabHostname.length - hostname.length;
|
|
if ( pos !== 0 && tabHostname.charAt(pos-1) !== '.' ) { return; }
|
|
await reloadTab(tabId);
|
|
}
|
|
|
|
// https://github.com/uBlockOrigin/uBOL-home/issues/280
|
|
async function onPermissionsAdded(permissions) {
|
|
const details = pendingPermissionRequest;
|
|
pendingPermissionRequest = undefined;
|
|
const { origins = [] } = permissions;
|
|
return details !== undefined
|
|
? onPermissionGrantedThruExtension(details, origins)
|
|
: onPermissionGrantedThruBrowser(origins);
|
|
}
|
|
|
|
async function onPermissionsRemoved() {
|
|
const modified = await syncWithBrowserPermissions();
|
|
if ( modified === false ) { return false; }
|
|
registerInjectables();
|
|
return true;
|
|
}
|
|
|
|
async function onPermissionsChanged(op, permissions) {
|
|
await isFullyInitialized;
|
|
const { pending } = onPermissionsChanged;
|
|
await Promise.all(pending);
|
|
const promise = op === 'removed'
|
|
? onPermissionsRemoved()
|
|
: onPermissionsAdded(permissions);
|
|
pending.push(promise);
|
|
}
|
|
onPermissionsChanged.pending = [];
|
|
|
|
/******************************************************************************/
|
|
|
|
function setDeveloperMode(state) {
|
|
rulesetConfig.developerMode = state === true;
|
|
toggleDeveloperMode(rulesetConfig.developerMode);
|
|
broadcastMessage({ developerMode: rulesetConfig.developerMode });
|
|
return Promise.all([
|
|
updateUserRules(),
|
|
saveRulesetConfig(),
|
|
]);
|
|
}
|
|
|
|
/******************************************************************************/
|
|
|
|
function onMessage(request, sender, callback) {
|
|
|
|
const tabId = sender?.tab?.id ?? false;
|
|
const frameId = tabId && (sender?.frameId ?? false);
|
|
|
|
// Does not require trusted origin.
|
|
|
|
switch ( request.what ) {
|
|
|
|
case 'insertCSS':
|
|
if ( frameId === false ) { return false; }
|
|
// https://bugs.webkit.org/show_bug.cgi?id=262491
|
|
if ( frameId !== 0 && webextFlavor === 'safari' ) { return false; }
|
|
browser.scripting.insertCSS({
|
|
css: request.css,
|
|
origin: 'USER',
|
|
target: { tabId, frameIds: [ frameId ] },
|
|
}).catch(reason => {
|
|
ubolErr(`insertCSS/${reason}`);
|
|
});
|
|
return false;
|
|
|
|
case 'removeCSS':
|
|
if ( frameId === false ) { return false; }
|
|
// https://bugs.webkit.org/show_bug.cgi?id=262491
|
|
if ( frameId !== 0 && webextFlavor === 'safari' ) { return false; }
|
|
browser.scripting.removeCSS({
|
|
css: request.css,
|
|
origin: 'USER',
|
|
target: { tabId, frameIds: [ frameId ] },
|
|
}).catch(reason => {
|
|
ubolErr(`removeCSS/${reason}`);
|
|
});
|
|
return false;
|
|
|
|
case 'toggleToolbarIcon': {
|
|
if ( tabId ) {
|
|
toggleToolbarIcon(tabId);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
case 'startCustomFilters':
|
|
if ( frameId === false ) { return false; }
|
|
startCustomFilters(tabId, frameId).then(( ) => {
|
|
callback();
|
|
});
|
|
return true;
|
|
|
|
case 'terminateCustomFilters':
|
|
if ( frameId === false ) { return false; }
|
|
terminateCustomFilters(tabId, frameId).then(( ) => {
|
|
callback();
|
|
});
|
|
return true;
|
|
|
|
case 'injectCustomFilters':
|
|
if ( frameId === false ) { return false; }
|
|
injectCustomFilters(tabId, frameId, request.hostname).then(selectors => {
|
|
callback(selectors);
|
|
});
|
|
return true;
|
|
|
|
case 'injectCSSProceduralAPI':
|
|
browser.scripting.executeScript({
|
|
files: [ '/js/scripting/css-procedural-api.js' ],
|
|
target: { tabId, frameIds: [ frameId ] },
|
|
injectImmediately: true,
|
|
}).catch(reason => {
|
|
ubolErr(`executeScript/${reason}`);
|
|
}).then(( ) => {
|
|
callback();
|
|
});
|
|
return true;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
// Does require trusted origin.
|
|
|
|
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/MessageSender
|
|
// Firefox API does not set `sender.origin`
|
|
if ( sender.origin !== undefined ) {
|
|
if ( sender.origin.toLowerCase() !== UBOL_ORIGIN ) { return; }
|
|
}
|
|
|
|
switch ( request.what ) {
|
|
|
|
case 'applyRulesets': {
|
|
enableRulesets(request.enabledRulesets).then(result => {
|
|
if ( result === undefined || result.error ) {
|
|
callback(result);
|
|
return;
|
|
}
|
|
rulesetConfig.enabledRulesets = result.enabledRulesets;
|
|
return saveRulesetConfig().then(( ) => {
|
|
return registerInjectables();
|
|
}).then(( ) => {
|
|
callback(result);
|
|
});
|
|
}).finally(( ) => {
|
|
broadcastMessage({ enabledRulesets: rulesetConfig.enabledRulesets });
|
|
});
|
|
return true;
|
|
}
|
|
|
|
case 'getDefaultConfig':
|
|
getDefaultRulesetsFromEnv().then(rulesets => {
|
|
callback({
|
|
autoReload: defaultConfig.autoReload,
|
|
developerMode: defaultConfig.developerMode,
|
|
showBlockedCount: defaultConfig.showBlockedCount,
|
|
strictBlockMode: defaultConfig.strictBlockMode,
|
|
rulesets,
|
|
filteringModes: Object.assign(defaultFilteringModes),
|
|
});
|
|
});
|
|
return true;
|
|
|
|
case 'getOptionsPageData':
|
|
Promise.all([
|
|
hasBroadHostPermissions(),
|
|
getDefaultFilteringMode(),
|
|
getRulesetDetails(),
|
|
dnr.getEnabledRulesets(),
|
|
getAdminRulesets(),
|
|
adminReadEx('disabledFeatures'),
|
|
]).then(results => {
|
|
const [
|
|
hasOmnipotence,
|
|
defaultFilteringMode,
|
|
rulesetDetails,
|
|
enabledRulesets,
|
|
adminRulesets,
|
|
disabledFeatures,
|
|
] = results;
|
|
callback({
|
|
hasOmnipotence,
|
|
defaultFilteringMode,
|
|
enabledRulesets,
|
|
adminRulesets,
|
|
maxNumberOfEnabledRulesets: dnr.MAX_NUMBER_OF_ENABLED_STATIC_RULESETS,
|
|
rulesetDetails: Array.from(rulesetDetails.values()),
|
|
autoReload: rulesetConfig.autoReload,
|
|
showBlockedCount: rulesetConfig.showBlockedCount,
|
|
canShowBlockedCount,
|
|
strictBlockMode: rulesetConfig.strictBlockMode,
|
|
firstRun: process.firstRun,
|
|
isSideloaded,
|
|
developerMode: rulesetConfig.developerMode,
|
|
disabledFeatures,
|
|
});
|
|
process.firstRun = false;
|
|
});
|
|
return true;
|
|
|
|
case 'getEnabledRulesets':
|
|
dnr.getEnabledRulesets().then(rulesets => {
|
|
callback(rulesets);
|
|
});
|
|
return true;
|
|
|
|
case 'getRulesetDetails':
|
|
getRulesetDetails().then(rulesetDetails => {
|
|
callback(Array.from(rulesetDetails.values()));
|
|
});
|
|
return true;
|
|
|
|
case 'hasBroadHostPermissions':
|
|
hasBroadHostPermissions().then(result => {
|
|
callback(result);
|
|
});
|
|
return true;
|
|
|
|
case 'setAutoReload':
|
|
rulesetConfig.autoReload = request.state && true || false;
|
|
saveRulesetConfig().then(( ) => {
|
|
callback();
|
|
broadcastMessage({ autoReload: rulesetConfig.autoReload });
|
|
});
|
|
return true;
|
|
|
|
case 'getShowBlockedCount':
|
|
callback(rulesetConfig.showBlockedCount);
|
|
break;
|
|
|
|
case 'setShowBlockedCount':
|
|
rulesetConfig.showBlockedCount = request.state && true || false;
|
|
if ( canShowBlockedCount ) {
|
|
dnr.setExtensionActionOptions({
|
|
displayActionCountAsBadgeText: rulesetConfig.showBlockedCount,
|
|
});
|
|
}
|
|
saveRulesetConfig().then(( ) => {
|
|
callback();
|
|
broadcastMessage({ showBlockedCount: rulesetConfig.showBlockedCount });
|
|
});
|
|
return true;
|
|
|
|
case 'setStrictBlockMode':
|
|
setStrictBlockMode(request.state).then(( ) => {
|
|
callback();
|
|
broadcastMessage({ strictBlockMode: rulesetConfig.strictBlockMode });
|
|
});
|
|
return true;
|
|
|
|
case 'setDeveloperMode':
|
|
setDeveloperMode(request.state).then(( ) => {
|
|
callback();
|
|
});
|
|
return true;
|
|
|
|
case 'popupPanelData': {
|
|
Promise.all([
|
|
hasBroadHostPermissions(),
|
|
getFilteringMode(request.hostname),
|
|
adminReadEx('disabledFeatures'),
|
|
hasCustomFilters(request.hostname),
|
|
]).then(results => {
|
|
callback({
|
|
hasOmnipotence: results[0],
|
|
level: results[1],
|
|
autoReload: rulesetConfig.autoReload,
|
|
isSideloaded,
|
|
developerMode: rulesetConfig.developerMode,
|
|
disabledFeatures: results[2],
|
|
hasCustomFilters: results[3],
|
|
});
|
|
});
|
|
return true;
|
|
}
|
|
|
|
case 'getFilteringMode': {
|
|
getFilteringMode(request.hostname).then(actualLevel => {
|
|
callback(actualLevel);
|
|
});
|
|
return true;
|
|
}
|
|
|
|
case 'gotoURL':
|
|
gotoURL(request.url, request.type);
|
|
break;
|
|
|
|
case 'setFilteringMode': {
|
|
getFilteringMode(request.hostname).then(beforeLevel => {
|
|
if ( request.level === beforeLevel ) { return beforeLevel; }
|
|
return setFilteringMode(request.hostname, request.level);
|
|
}).then(afterLevel => {
|
|
registerInjectables();
|
|
callback(afterLevel);
|
|
});
|
|
return true;
|
|
}
|
|
|
|
case 'setPendingFilteringMode':
|
|
pendingPermissionRequest = request;
|
|
break;
|
|
|
|
case 'getDefaultFilteringMode': {
|
|
getDefaultFilteringMode().then(level => {
|
|
callback(level);
|
|
});
|
|
return true;
|
|
}
|
|
|
|
case 'setDefaultFilteringMode':
|
|
getDefaultFilteringMode().then(beforeLevel =>
|
|
setDefaultFilteringMode(request.level).then(afterLevel =>
|
|
({ beforeLevel, afterLevel })
|
|
)
|
|
).then(({ beforeLevel, afterLevel }) => {
|
|
if ( afterLevel !== beforeLevel ) {
|
|
registerInjectables();
|
|
}
|
|
callback(afterLevel);
|
|
});
|
|
return true;
|
|
|
|
case 'getFilteringModeDetails':
|
|
getFilteringModeDetails(true).then(details => {
|
|
callback(details);
|
|
});
|
|
return true;
|
|
|
|
case 'setFilteringModeDetails':
|
|
setFilteringModeDetails(request.modes).then(( ) => {
|
|
registerInjectables();
|
|
getDefaultFilteringMode().then(defaultFilteringMode => {
|
|
broadcastMessage({ defaultFilteringMode });
|
|
});
|
|
getFilteringModeDetails(true).then(details => {
|
|
callback(details);
|
|
});
|
|
});
|
|
return true;
|
|
|
|
case 'excludeFromStrictBlock': {
|
|
excludeFromStrictBlock(request.hostname, request.permanent).then(( ) => {
|
|
callback();
|
|
});
|
|
return true;
|
|
}
|
|
|
|
case 'getMatchedRules':
|
|
getMatchedRules(request.tabId).then(entries => {
|
|
callback(entries);
|
|
});
|
|
return true;
|
|
|
|
case 'showMatchedRules':
|
|
browser.windows.create({
|
|
type: 'popup',
|
|
url: `/matched-rules.html?tab=${request.tabId}`,
|
|
});
|
|
break;
|
|
|
|
case 'getEffectiveDynamicRules':
|
|
getEffectiveDynamicRules().then(result => {
|
|
callback(result);
|
|
});
|
|
return true;
|
|
|
|
case 'getEffectiveSessionRules':
|
|
getEffectiveSessionRules().then(result => {
|
|
callback(result);
|
|
});
|
|
return true;
|
|
|
|
case 'getEffectiveUserRules':
|
|
getEffectiveUserRules().then(result => {
|
|
callback(result);
|
|
});
|
|
return true;
|
|
|
|
case 'updateUserDnrRules':
|
|
updateUserRules().then(result => {
|
|
callback(result);
|
|
});
|
|
return true;
|
|
|
|
case 'addCustomFilters':
|
|
addCustomFilters(request.hostname, request.selectors).then(modified => {
|
|
if ( modified !== true ) { return; }
|
|
return registerInjectables();
|
|
}).then(( ) => {
|
|
callback();
|
|
})
|
|
return true;
|
|
|
|
case 'removeCustomFilters':
|
|
removeCustomFilters(request.hostname, request.selectors).then(modified => {
|
|
if ( modified !== true ) { return; }
|
|
return registerInjectables();
|
|
}).then(( ) => {
|
|
callback();
|
|
});
|
|
return true;
|
|
|
|
case 'removeAllCustomFilters':
|
|
removeAllCustomFilters(request.hostname).then(modified => {
|
|
if ( modified !== true ) { return; }
|
|
return registerInjectables();
|
|
}).then(( ) => {
|
|
callback();
|
|
});
|
|
return true;
|
|
|
|
case 'customFiltersFromHostname':
|
|
customFiltersFromHostname(request.hostname).then(selectors => {
|
|
callback(selectors);
|
|
});
|
|
return true;
|
|
|
|
case 'getAllCustomFilters':
|
|
getAllCustomFilters().then(data => {
|
|
callback(data);
|
|
});
|
|
return true;
|
|
|
|
case 'getRegisteredContentScripts':
|
|
scrmgr.getRegisteredContentScripts().then(ids => {
|
|
callback(ids);
|
|
});
|
|
return true;
|
|
|
|
case 'getConsoleOutput':
|
|
callback(getConsoleOutput());
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
|
|
function onCommand(command, tab) {
|
|
switch ( command ) {
|
|
case 'enter-zapper-mode': {
|
|
if ( browser.scripting === undefined ) { return; }
|
|
browser.scripting.executeScript({
|
|
files: [ '/js/scripting/tool-overlay.js', '/js/scripting/zapper.js' ],
|
|
target: { tabId: tab.id },
|
|
});
|
|
break;
|
|
}
|
|
case 'enter-picker-mode': {
|
|
if ( browser.scripting === undefined ) { return; }
|
|
browser.scripting.executeScript({
|
|
files: [
|
|
'/js/scripting/css-procedural-api.js',
|
|
'/js/scripting/tool-overlay.js',
|
|
'/js/scripting/picker.js',
|
|
],
|
|
target: { tabId: tab.id },
|
|
});
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/******************************************************************************/
|
|
|
|
async function startSession() {
|
|
const currentVersion = getCurrentVersion();
|
|
const isNewVersion = currentVersion !== rulesetConfig.version;
|
|
|
|
// Admin settings override user settings
|
|
await loadAdminConfig();
|
|
|
|
// The default rulesets may have changed, find out new ruleset to enable,
|
|
// obsolete ruleset to remove.
|
|
if ( isNewVersion ) {
|
|
ubolLog(`Version change: ${rulesetConfig.version} => ${currentVersion}`);
|
|
rulesetConfig.version = currentVersion;
|
|
await patchDefaultRulesets();
|
|
saveRulesetConfig();
|
|
}
|
|
|
|
const rulesetsUpdated = await enableRulesets(rulesetConfig.enabledRulesets);
|
|
|
|
// We need to update the regex rules only when ruleset version changes.
|
|
if ( rulesetsUpdated === undefined ) {
|
|
if ( isNewVersion ) {
|
|
updateDynamicRules();
|
|
} else {
|
|
updateSessionRules();
|
|
}
|
|
}
|
|
|
|
// Permissions may have been removed while the extension was disabled
|
|
const permissionsUpdated = await syncWithBrowserPermissions();
|
|
|
|
const shouldInject = isNewVersion || permissionsUpdated ||
|
|
isSideloaded && rulesetConfig.developerMode;
|
|
if ( shouldInject ) {
|
|
await registerInjectables();
|
|
}
|
|
|
|
// Cosmetic filtering-related content scripts cache fitlering data in
|
|
// session storage.
|
|
sessionAccessLevel({ accessLevel: 'TRUSTED_AND_UNTRUSTED_CONTEXTS' });
|
|
|
|
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/declarativeNetRequest
|
|
// Firefox API does not support `dnr.setExtensionActionOptions`
|
|
if ( canShowBlockedCount ) {
|
|
dnr.setExtensionActionOptions({
|
|
displayActionCountAsBadgeText: rulesetConfig.showBlockedCount,
|
|
});
|
|
}
|
|
|
|
// Switch to basic filtering if uBOL doesn't have broad permissions at
|
|
// install time.
|
|
if ( process.firstRun ) {
|
|
const enableOptimal = await hasBroadHostPermissions();
|
|
if ( enableOptimal === false ) {
|
|
const afterLevel = await setDefaultFilteringMode(MODE_BASIC);
|
|
if ( afterLevel === MODE_BASIC ) {
|
|
registerInjectables();
|
|
process.firstRun = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Required to ensure up to date properties are available when needed
|
|
adminReadEx('disabledFeatures').then(items => {
|
|
if ( Array.isArray(items) === false ) { return; }
|
|
if ( items.includes('develop') ) {
|
|
if ( rulesetConfig.developerMode ) {
|
|
setDeveloperMode(false);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
/******************************************************************************/
|
|
|
|
async function start() {
|
|
await loadRulesetConfig();
|
|
|
|
if ( process.wakeupRun === false ) {
|
|
await startSession();
|
|
} else {
|
|
scrmgr.onWakeupRun();
|
|
}
|
|
|
|
const scripts = await scrmgr.getRegisteredContentScripts();
|
|
if ( scripts.length === 0 ) {
|
|
registerInjectables();
|
|
}
|
|
|
|
toggleDeveloperMode(rulesetConfig.developerMode);
|
|
}
|
|
|
|
/******************************************************************************/
|
|
|
|
// https://github.com/uBlockOrigin/uBOL-home/issues/199
|
|
// Force a restart of the extension once when an "internal error" occurs
|
|
|
|
const isFullyInitialized = start().then(( ) => {
|
|
localRemove('goodStart');
|
|
return false;
|
|
}).catch(reason => {
|
|
ubolErr(reason);
|
|
if ( process.wakeupRun ) { return; }
|
|
return localRead('goodStart').then(goodStart => {
|
|
if ( goodStart === false ) {
|
|
localRemove('goodStart');
|
|
return false;
|
|
}
|
|
return localWrite('goodStart', false).then(( ) => true);
|
|
});
|
|
}).then(restart => {
|
|
if ( restart !== true ) { return; }
|
|
runtime.reload();
|
|
});
|
|
|
|
runtime.onMessage.addListener((request, sender, callback) => {
|
|
isFullyInitialized.then(( ) => {
|
|
const r = onMessage(request, sender, callback);
|
|
if ( r !== true ) { callback(); }
|
|
});
|
|
return true;
|
|
});
|
|
|
|
browser.permissions.onRemoved.addListener((...args) => {
|
|
isFullyInitialized.then(( ) => {
|
|
onPermissionsChanged('removed', ...args);
|
|
});
|
|
});
|
|
|
|
browser.permissions.onAdded.addListener((...args) => {
|
|
isFullyInitialized.then(( ) => {
|
|
onPermissionsChanged('added', ...args);
|
|
});
|
|
});
|
|
|
|
browser.commands.onCommand.addListener((...args) => {
|
|
isFullyInitialized.then(( ) => {
|
|
onCommand(...args);
|
|
});
|
|
});
|