Skip to content

Commit d19e62a

Browse files
committed
[mv3] Add support for admin configurations
See `managed_storage.json` for available settings. Currently only `noFiltering` setting is availale. `noFiltering` is an array of strings, each being a domain for which no filtering should occur. Related discussion: - uBlockOrigin/uBOL-home#35
1 parent 0541ddb commit d19e62a

File tree

9 files changed

+349
-362
lines changed

9 files changed

+349
-362
lines changed

platform/mv3/chromium/manifest.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@
3838
"storage"
3939
],
4040
"short_name": "uBO Lite",
41+
"storage": {
42+
"managed_schema": "managed_storage.json"
43+
},
4144
"version": "1.0",
4245
"web_accessible_resources": []
4346
}

platform/mv3/extension/js/background.js

Lines changed: 34 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,7 @@ import {
3434
} from './ext.js';
3535

3636
import {
37-
CURRENT_CONFIG_BASE_RULE_ID,
3837
getRulesetDetails,
39-
getDynamicRules,
4038
defaultRulesetsFromLanguage,
4139
enableRulesets,
4240
getEnabledRulesetsDetails,
@@ -70,6 +68,7 @@ const rulesetConfig = {
7068
const UBOL_ORIGIN = runtime.getURL('').replace(/\/$/, '');
7169

7270
let firstRun = false;
71+
let wakeupRun = false;
7372

7473
/******************************************************************************/
7574

@@ -83,53 +82,23 @@ async function loadRulesetConfig() {
8382
rulesetConfig.version = data.version;
8483
rulesetConfig.enabledRulesets = data.enabledRulesets;
8584
rulesetConfig.autoReload = data.autoReload;
86-
return false;
85+
wakeupRun = true;
86+
return;
8787
}
8888
data = await localRead('rulesetConfig');
8989
if ( data ) {
9090
rulesetConfig.version = data.version;
9191
rulesetConfig.enabledRulesets = data.enabledRulesets;
9292
rulesetConfig.autoReload = data.autoReload;
93-
return false;
94-
}
95-
data = await loadRulesetConfig.convertLegacyStorage();
96-
if ( data ) {
97-
rulesetConfig.version = data.version;
98-
rulesetConfig.enabledRulesets = data.enabledRulesets;
99-
rulesetConfig.autoReload = data.autoReload;
100-
return false;
93+
sessionWrite('rulesetConfig', rulesetConfig);
94+
return;
10195
}
10296
rulesetConfig.enabledRulesets = await defaultRulesetsFromLanguage();
10397
sessionWrite('rulesetConfig', rulesetConfig);
10498
localWrite('rulesetConfig', rulesetConfig);
105-
return true;
99+
firstRun = true;
106100
}
107101

108-
// TODO: To remove after next stable release is widespread (2023-06-04)
109-
loadRulesetConfig.convertLegacyStorage = async function() {
110-
const dynamicRuleMap = await getDynamicRules();
111-
const configRule = dynamicRuleMap.get(CURRENT_CONFIG_BASE_RULE_ID);
112-
if ( configRule === undefined ) { return; }
113-
let rawConfig;
114-
try {
115-
rawConfig = JSON.parse(self.atob(configRule.condition.urlFilter));
116-
} catch(ex) {
117-
return;
118-
}
119-
if ( rawConfig === undefined ) { return; }
120-
const config = {
121-
version: rawConfig[0],
122-
enabledRulesets: rawConfig[1],
123-
autoReload: rawConfig[2],
124-
};
125-
localWrite('rulesetConfig', config);
126-
sessionWrite('rulesetConfig', config);
127-
dnr.updateDynamicRules({
128-
removeRuleIds: [ CURRENT_CONFIG_BASE_RULE_ID ],
129-
});
130-
return config;
131-
};
132-
133102
async function saveRulesetConfig() {
134103
sessionWrite('rulesetConfig', rulesetConfig);
135104
return localWrite('rulesetConfig', rulesetConfig);
@@ -153,12 +122,13 @@ function hasOmnipotence() {
153122
async function onPermissionsRemoved() {
154123
const beforeMode = await getDefaultFilteringMode();
155124
const modified = await syncWithBrowserPermissions();
156-
if ( modified === false ) { return; }
125+
if ( modified === false ) { return false; }
157126
const afterMode = await getDefaultFilteringMode();
158127
if ( beforeMode > 1 && afterMode <= 1 ) {
159128
updateDynamicRules();
160129
}
161130
registerInjectables();
131+
return true;
162132
}
163133

164134
/******************************************************************************/
@@ -180,6 +150,7 @@ function onMessage(request, sender, callback) {
180150
}).catch(reason => {
181151
console.log(reason);
182152
});
153+
callback();
183154
return;
184155
}
185156

@@ -273,8 +244,7 @@ function onMessage(request, sender, callback) {
273244
}
274245

275246
case 'setDefaultFilteringMode': {
276-
getDefaultFilteringMode(
277-
).then(beforeLevel =>
247+
getDefaultFilteringMode().then(beforeLevel =>
278248
setDefaultFilteringMode(request.level).then(afterLevel =>
279249
({ beforeLevel, afterLevel })
280250
)
@@ -298,37 +268,44 @@ function onMessage(request, sender, callback) {
298268
/******************************************************************************/
299269

300270
async function start() {
301-
firstRun = await loadRulesetConfig();
302-
await enableRulesets(rulesetConfig.enabledRulesets);
271+
await loadRulesetConfig();
272+
273+
if ( wakeupRun === false ) {
274+
await enableRulesets(rulesetConfig.enabledRulesets);
275+
}
303276

304277
// We need to update the regex rules only when ruleset version changes.
305-
const currentVersion = getCurrentVersion();
306-
if ( currentVersion !== rulesetConfig.version ) {
307-
ubolLog(`Version change: ${rulesetConfig.version} => ${currentVersion}`);
308-
updateDynamicRules().then(( ) => {
309-
rulesetConfig.version = currentVersion;
310-
saveRulesetConfig();
311-
});
278+
if ( wakeupRun === false ) {
279+
const currentVersion = getCurrentVersion();
280+
if ( currentVersion !== rulesetConfig.version ) {
281+
ubolLog(`Version change: ${rulesetConfig.version} => ${currentVersion}`);
282+
updateDynamicRules().then(( ) => {
283+
rulesetConfig.version = currentVersion;
284+
saveRulesetConfig();
285+
});
286+
}
312287
}
313288

314289
// Permissions may have been removed while the extension was disabled
315-
await onPermissionsRemoved();
290+
const permissionsChanged = await onPermissionsRemoved();
316291

317292
// Unsure whether the browser remembers correctly registered css/scripts
318293
// after we quit the browser. For now uBOL will check unconditionally at
319294
// launch time whether content css/scripts are properly registered.
320-
registerInjectables();
295+
if ( wakeupRun === false || permissionsChanged ) {
296+
registerInjectables();
321297

322-
const enabledRulesets = await dnr.getEnabledRulesets();
323-
ubolLog(`Enabled rulesets: ${enabledRulesets}`);
298+
const enabledRulesets = await dnr.getEnabledRulesets();
299+
ubolLog(`Enabled rulesets: ${enabledRulesets}`);
324300

325-
dnr.getAvailableStaticRuleCount().then(count => {
326-
ubolLog(`Available static rule count: ${count}`);
327-
});
301+
dnr.getAvailableStaticRuleCount().then(count => {
302+
ubolLog(`Available static rule count: ${count}`);
303+
});
304+
}
328305

329306
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/declarativeNetRequest
330307
// Firefox API does not support `dnr.setExtensionActionOptions`
331-
if ( dnr.setExtensionActionOptions ) {
308+
if ( wakeupRun === false && dnr.setExtensionActionOptions ) {
332309
dnr.setExtensionActionOptions({ displayActionCountAsBadgeText: true });
333310
}
334311

platform/mv3/extension/js/ext.js

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -25,22 +25,22 @@
2525

2626
/******************************************************************************/
2727

28-
const browser =
28+
export const browser =
2929
self.browser instanceof Object &&
3030
self.browser instanceof Element === false
3131
? self.browser
3232
: self.chrome;
3333

34-
const dnr = browser.declarativeNetRequest;
35-
const i18n = browser.i18n;
36-
const runtime = browser.runtime;
34+
export const dnr = browser.declarativeNetRequest;
35+
export const i18n = browser.i18n;
36+
export const runtime = browser.runtime;
3737

3838
/******************************************************************************/
3939

4040
// The extension's service worker can be evicted at any time, so when we
4141
// send a message, we try a few more times when the message fails to be sent.
4242

43-
function sendMessage(msg) {
43+
export function sendMessage(msg) {
4444
return new Promise((resolve, reject) => {
4545
let i = 5;
4646
const send = ( ) => {
@@ -61,50 +61,59 @@ function sendMessage(msg) {
6161

6262
/******************************************************************************/
6363

64-
async function localRead(key) {
64+
export async function localRead(key) {
6565
if ( browser.storage instanceof Object === false ) { return; }
6666
if ( browser.storage.local instanceof Object === false ) { return; }
6767
try {
6868
const bin = await browser.storage.local.get(key);
6969
if ( bin instanceof Object === false ) { return; }
70-
return bin[key];
70+
return bin[key] ?? undefined;
7171
} catch(ex) {
7272
}
7373
}
7474

75-
async function localWrite(key, value) {
75+
export async function localWrite(key, value) {
7676
if ( browser.storage instanceof Object === false ) { return; }
7777
if ( browser.storage.local instanceof Object === false ) { return; }
7878
return browser.storage.local.set({ [key]: value });
7979
}
8080

81+
export async function localRemove(key) {
82+
if ( browser.storage instanceof Object === false ) { return; }
83+
if ( browser.storage.local instanceof Object === false ) { return; }
84+
return browser.storage.local.remove(key);
85+
}
86+
8187
/******************************************************************************/
8288

83-
async function sessionRead(key) {
89+
export async function sessionRead(key) {
8490
if ( browser.storage instanceof Object === false ) { return; }
8591
if ( browser.storage.session instanceof Object === false ) { return; }
8692
try {
8793
const bin = await browser.storage.session.get(key);
8894
if ( bin instanceof Object === false ) { return; }
89-
return bin[key];
95+
return bin[key] ?? undefined;
9096
} catch(ex) {
9197
}
9298
}
9399

94-
async function sessionWrite(key, value) {
100+
export async function sessionWrite(key, value) {
95101
if ( browser.storage instanceof Object === false ) { return; }
96102
if ( browser.storage.session instanceof Object === false ) { return; }
97103
return browser.storage.session.set({ [key]: value });
98104
}
99105

100106
/******************************************************************************/
101107

102-
export {
103-
browser,
104-
dnr,
105-
i18n,
106-
runtime,
107-
sendMessage,
108-
localRead, localWrite,
109-
sessionRead, sessionWrite,
110-
};
108+
export async function adminRead(key) {
109+
if ( browser.storage instanceof Object === false ) { return; }
110+
if ( browser.storage.local instanceof Object === false ) { return; }
111+
try {
112+
const bin = await browser.storage.managed.get(key);
113+
if ( bin instanceof Object === false ) { return; }
114+
return bin[key] ?? undefined;
115+
} catch(ex) {
116+
}
117+
}
118+
119+
/******************************************************************************/

0 commit comments

Comments
 (0)