Skip to content

Commit

Permalink
[mv3] Fix undue blocking of network requests for unfiltered sites
Browse files Browse the repository at this point in the history
Related issue:
uBlockOrigin/uBOL-home#247

Use session rules with `TAB_ID_NONE` to properly exclude network
requests from service workers potentially used by trusted websites.
  • Loading branch information
gorhill committed Dec 20, 2024
1 parent 143cc02 commit c311315
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 45 deletions.
1 change: 1 addition & 0 deletions platform/mv3/extension/js/ext.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export const browser =
export const dnr = browser.declarativeNetRequest;
export const i18n = browser.i18n;
export const runtime = browser.runtime;
export const TAB_ID_NONE = browser.tabs.TAB_ID_NONE;
export const windows = browser.windows;

/******************************************************************************/
Expand Down
112 changes: 67 additions & 45 deletions platform/mv3/extension/js/ruleset-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
*/

import {
TAB_ID_NONE,
browser,
dnr,
i18n,
Expand Down Expand Up @@ -47,19 +48,6 @@ let dynamicRuleId = 1;

/******************************************************************************/

const eqSets = (setBefore, setAfter) => {
if ( setBefore.size !== setAfter.size ) { return false; }
for ( const hn of setAfter ) {
if ( setBefore.has(hn) === false ) { return false; }
}
for ( const hn of setBefore ) {
if ( setAfter.has(hn) === false ) { return false; }
}
return true;
};

/******************************************************************************/

function getRulesetDetails() {
if ( getRulesetDetails.rulesetDetailsPromise !== undefined ) {
return getRulesetDetails.rulesetDetailsPromise;
Expand Down Expand Up @@ -472,13 +460,17 @@ async function updateDynamicRules() {
/******************************************************************************/

async function filteringModesToDNR(modes) {
const trustedRules = await dnr.getDynamicRules({
ruleIds: [ TRUSTED_DIRECTIVE_BASE_RULE_ID+0 ],
});
const trustedRule = trustedRules.length !== 0 && trustedRules[0] || undefined;
const beforeRequestDomainSet = new Set(trustedRule?.condition.requestDomains);
const beforeExcludedRrequestDomainSet = new Set(trustedRule?.condition.excludedRequestDomains);
if ( trustedRule !== undefined && beforeRequestDomainSet.size === 0 ) {
const [
dynamicRules,
sessionRules,
] = await Promise.all([
dnr.getDynamicRules({ ruleIds: [ TRUSTED_DIRECTIVE_BASE_RULE_ID+0 ] }),
dnr.getSessionRules({ ruleIds: [ TRUSTED_DIRECTIVE_BASE_RULE_ID+1 ] }),
]);
const dynamicRule = dynamicRules?.length && dynamicRules[0] || undefined;
const beforeRequestDomainSet = new Set(dynamicRule?.condition.requestDomains);
const beforeExcludedRrequestDomainSet = new Set(dynamicRule?.condition.excludedRequestDomains);
if ( dynamicRule !== undefined && beforeRequestDomainSet.size === 0 ) {
beforeRequestDomainSet.add('all-urls');
} else {
beforeExcludedRrequestDomainSet.add('all-urls');
Expand All @@ -493,27 +485,19 @@ async function filteringModesToDNR(modes) {
afterExcludedRequestDomainSet = notNoneHostnames;
} else {
afterRequestDomainSet = noneHostnames;
afterExcludedRequestDomainSet = new Set([ 'all-urls' ]);
afterExcludedRequestDomainSet = new Set();
}

if ( eqSets(beforeRequestDomainSet, afterRequestDomainSet) ) {
if ( eqSets(beforeExcludedRrequestDomainSet, afterExcludedRequestDomainSet) ) {
return;
}
}

const removeRuleIds = [];
if ( trustedRule ) {
removeRuleIds.push(
TRUSTED_DIRECTIVE_BASE_RULE_ID+0,
TRUSTED_DIRECTIVE_BASE_RULE_ID+1
);
const removeDynamicRuleIds = [];
const removeSessionRuleIds = [];
if ( dynamicRule ) {
removeDynamicRuleIds.push(TRUSTED_DIRECTIVE_BASE_RULE_ID+0);
removeSessionRuleIds.push(TRUSTED_DIRECTIVE_BASE_RULE_ID+1);
}

const allowEverywhere = afterRequestDomainSet.delete('all-urls');
afterExcludedRequestDomainSet.delete('all-urls');

const addRules = [];
const addDynamicRules = [];
const addSessionRules = [];
if (
allowEverywhere ||
afterRequestDomainSet.size !== 0 ||
Expand All @@ -528,33 +512,71 @@ async function filteringModesToDNR(modes) {
priority: 100,
};
if ( afterRequestDomainSet.size !== 0 ) {
rule0.condition.requestDomains = Array.from(afterRequestDomainSet);
rule0.condition.requestDomains =
Array.from(afterRequestDomainSet).sort();
} else if ( afterExcludedRequestDomainSet.size !== 0 ) {
rule0.condition.excludedRequestDomains = Array.from(afterExcludedRequestDomainSet);
rule0.condition.excludedRequestDomains =
Array.from(afterExcludedRequestDomainSet).sort();
}
addRules.push(rule0);
addDynamicRules.push(rule0);
// https://github.com/uBlockOrigin/uBOL-home/issues/114
// https://github.com/uBlockOrigin/uBOL-home/issues/247
const rule1 = {
id: TRUSTED_DIRECTIVE_BASE_RULE_ID+1,
action: { type: 'allow' },
condition: {
resourceTypes: [ 'script' ],
tabIds: [ TAB_ID_NONE ],
},
priority: 100,
};
if ( rule0.condition.requestDomains ) {
rule1.condition.initiatorDomains = rule0.condition.requestDomains.slice();
rule1.condition.initiatorDomains =
rule0.condition.requestDomains.slice();
} else if ( rule0.condition.excludedRequestDomains ) {
rule1.condition.excludedInitiatorDomains = rule0.condition.excludedRequestDomains.slice();
rule1.condition.excludedInitiatorDomains =
rule0.condition.excludedRequestDomains.slice();
}
addRules.push(rule1);
addSessionRules.push(rule1);
}

if ( addRules.length === 0 && removeRuleIds.length === 0 ) { return; }
const noneCount = noneHostnames.has('all-urls')
? -notNoneHostnames.size
: noneHostnames.size;

return dnr.updateDynamicRules({ addRules, removeRuleIds });
const promises = [];
if ( isDifferentAllowRules(addDynamicRules, dynamicRules) ) {
promises.push(dnr.updateDynamicRules({
addRules: addDynamicRules,
removeRuleIds: removeDynamicRuleIds,
}));
ubolLog(`Add "allowAllRequests" dynamic rule for ${noneCount} sites`);
}
if ( isDifferentAllowRules(addSessionRules, sessionRules) ) {
promises.push(dnr.updateSessionRules({
addRules: addSessionRules,
removeRuleIds: removeSessionRuleIds,
}));
ubolLog(`Add "allow" session rule for ${noneCount} sites`);
}
if ( promises.length === 0 ) { return; }
return Promise.all(promises);
}

const isDifferentAllowRules = (a, b) => {
const pp = [
'requestDomains',
'excludedRequestDomains',
'initiatorDomains',
'excludedInitiatorDomains',
];
for ( const p of pp ) {
const ac = a?.length && a[0].condition[p] || [];
const bc = b?.length && b[0].condition[p] || [];
if ( ac.join() !== bc.join() ) { return true; }
}
return false;
};

/******************************************************************************/

async function defaultRulesetsFromLanguage() {
Expand Down

0 comments on commit c311315

Please sign in to comment.