@eyeo/webext-ad-filtering-solution
Advanced tools
Comparing version 1.10.0 to 1.11.0
@@ -96,23 +96,19 @@ /* | ||
function getCondition(filter, urlFilter, resourceTypes, matchCase) { | ||
let condition = {}; | ||
function getConditions(filter, urlFilter, resourceTypes, matchCase) { | ||
let baseCondition = {}; | ||
if (urlFilter) { | ||
condition.urlFilter = urlFilter; | ||
baseCondition.urlFilter = urlFilter; | ||
} | ||
else if (filter.regexp) { | ||
condition.regexFilter = filter.regexp.source; | ||
baseCondition.regexFilter = filter.regexp.source; | ||
} | ||
if (resourceTypes) { | ||
condition.resourceTypes = resourceTypes; | ||
} | ||
// Before Chromium 118, the default for isUrlFilterCaseSensitive is true. From | ||
// Chromium 118, the default is false. If we at some point make our minimum | ||
// supported Chromium 118, then we can leave this undefined if !matchCase. | ||
condition.isUrlFilterCaseSensitive = matchCase; | ||
baseCondition.isUrlFilterCaseSensitive = matchCase; | ||
if (filter.thirdParty != null) { | ||
condition.domainType = filter.thirdParty ? "thirdParty" : "firstParty"; | ||
baseCondition.domainType = filter.thirdParty ? "thirdParty" : "firstParty"; | ||
} | ||
@@ -122,10 +118,59 @@ | ||
if (domains.length) { | ||
condition.domains = domains; | ||
let conditions = []; | ||
if (resourceTypes && (domains.length || excludedDomains.length)) { | ||
let mainFrameResourceTypes = resourceTypes.filter(t => t == "main_frame"); | ||
let otherResourceTypes = resourceTypes.filter(t => t != "main_frame"); | ||
if (mainFrameResourceTypes.length) { | ||
let condition = { | ||
resourceTypes: mainFrameResourceTypes, | ||
...baseCondition | ||
}; | ||
if (domains.length) { | ||
condition.requestDomains = domains; | ||
} | ||
if (excludedDomains.length) { | ||
condition.excludedRequestDomains = excludedDomains; | ||
} | ||
conditions.push(condition); | ||
} | ||
if (otherResourceTypes.length) { | ||
let condition = { | ||
resourceTypes: otherResourceTypes, | ||
...baseCondition | ||
}; | ||
if (domains.length) { | ||
condition.initiatorDomains = domains; | ||
} | ||
if (excludedDomains.length) { | ||
condition.excludedInitiatorDomains = excludedDomains; | ||
} | ||
conditions.push(condition); | ||
} | ||
} | ||
if (excludedDomains.length) { | ||
condition.excludedDomains = excludedDomains; | ||
else { | ||
let condition = { | ||
...baseCondition | ||
}; | ||
if (resourceTypes) { | ||
condition.resourceTypes = resourceTypes; | ||
} | ||
if (domains.length) { | ||
condition.initiatorDomains = domains; | ||
} | ||
if (excludedDomains.length) { | ||
condition.excludedInitiatorDomains = excludedDomains; | ||
} | ||
conditions.push(condition); | ||
} | ||
return [condition, isGenericFilter]; | ||
return {conditions, isGenericFilter}; | ||
} | ||
@@ -149,22 +194,24 @@ | ||
let [condition, isGenericFilter] = getCondition( | ||
let {conditions, isGenericFilter} = getConditions( | ||
filter, urlFilter, resourceTypes, matchCase | ||
); | ||
return [{ | ||
priority: isGenericFilter ? GENERIC_PRIORITY : SPECIFIC_PRIORITY, | ||
condition, | ||
action: { | ||
type: "redirect", | ||
redirect: {url} | ||
} | ||
}]; | ||
return conditions.map(condition => { | ||
return { | ||
priority: isGenericFilter ? GENERIC_PRIORITY : SPECIFIC_PRIORITY, | ||
condition, | ||
action: { | ||
type: "redirect", | ||
redirect: {url} | ||
} | ||
}; | ||
}); | ||
}; | ||
exports.generateCSPRules = function(filter, urlFilter, matchCase) { | ||
let [condition, isGenericFilter] = getCondition( | ||
let {conditions, isGenericFilter} = getConditions( | ||
filter, urlFilter, ["main_frame", "sub_frame"], matchCase | ||
); | ||
let rule; | ||
let rules; | ||
@@ -186,61 +233,31 @@ if (!filter.blocking) { | ||
// need to reconsider this in the future. | ||
rule = { | ||
action: { | ||
type: "allow" | ||
}, | ||
condition, | ||
priority: filter.contentType & contentTypes.GENERICBLOCK ? | ||
GENERIC_PRIORITY : SPECIFIC_PRIORITY | ||
}; | ||
rules = conditions.map(condition => { | ||
return { | ||
action: { | ||
type: "allow" | ||
}, | ||
condition, | ||
priority: filter.contentType & contentTypes.GENERICBLOCK ? | ||
GENERIC_PRIORITY : SPECIFIC_PRIORITY | ||
}; | ||
}); | ||
} | ||
else { | ||
rule = { | ||
action: { | ||
type: "modifyHeaders", | ||
responseHeaders: [{ | ||
header: "Content-Security-Policy", | ||
operation: "append", | ||
value: filter.csp | ||
}] | ||
}, | ||
condition, | ||
priority: isGenericFilter ? GENERIC_PRIORITY : SPECIFIC_PRIORITY | ||
}; | ||
rules = conditions.map(condition => { | ||
return { | ||
action: { | ||
type: "modifyHeaders", | ||
responseHeaders: [{ | ||
header: "Content-Security-Policy", | ||
operation: "append", | ||
value: filter.csp | ||
}] | ||
}, | ||
condition, | ||
priority: isGenericFilter ? GENERIC_PRIORITY : SPECIFIC_PRIORITY | ||
}; | ||
}); | ||
} | ||
// Chromium doesn't consider main_frame requests to have initiated from their | ||
// URL, so the domains/excludedDomains rule conditions won't work as expected | ||
// for main_frame requests. This is a problem for $csp filters which also use | ||
// the $domain option. As a partial workaround, we generate a separate | ||
// urlFilter rule for each domain. But note, we can't support excludedDomains | ||
// ($csp=...$~domain=...) or urlFilter conditions (||...$csp=...,domain=...). | ||
// See https://bugs.chromium.org/p/chromium/issues/detail?id=1207326 | ||
// | ||
// Note: Hopefully, this workaround won't be necessary for long, but if we | ||
// need it long-term, then perhaps we should generate one rule with a longer | ||
// regexFilter condition instead. But if we do that, we will need to be | ||
// careful not to hit the memory limit for regular expression rule conditions | ||
// and also to match subdomains correctly. | ||
if (rule.condition.excludedDomains) { | ||
return []; | ||
} | ||
if (rule.condition.domains) { | ||
if (condition.urlFilter) { | ||
return []; | ||
} | ||
let {domains} = condition; | ||
delete condition.domains; | ||
let rules = []; | ||
for (let domain of domains) { | ||
let domainRule = JSON.parse(JSON.stringify(rule)); | ||
domainRule.condition.urlFilter = "||" + domain + "^"; | ||
rules.push(domainRule); | ||
} | ||
return rules; | ||
} | ||
return [rule]; | ||
return rules; | ||
}; | ||
@@ -257,13 +274,15 @@ | ||
let [condition, isGenericFilter] = getCondition( | ||
let {conditions, isGenericFilter} = getConditions( | ||
filter, urlFilter, resourceTypes, matchCase | ||
); | ||
return [{ | ||
priority: isGenericFilter ? GENERIC_PRIORITY : SPECIFIC_PRIORITY, | ||
condition, | ||
action: { | ||
type: "block" | ||
} | ||
}]; | ||
return conditions.map(condition => { | ||
return { | ||
priority: isGenericFilter ? GENERIC_PRIORITY : SPECIFIC_PRIORITY, | ||
condition, | ||
action: { | ||
type: "block" | ||
} | ||
}; | ||
}); | ||
}; | ||
@@ -280,11 +299,17 @@ | ||
rules.push({ | ||
priority: genericBlock ? | ||
GENERIC_ALLOW_ALL_PRIORITY : SPECIFIC_ALLOW_ALL_PRIORITY, | ||
condition: getCondition( | ||
filter, urlFilter, ["main_frame", "sub_frame"], matchCase)[0], | ||
action: { | ||
type: "allowAllRequests" | ||
} | ||
}); | ||
let {conditions} = getConditions(filter, | ||
urlFilter, | ||
["main_frame", "sub_frame"], | ||
matchCase); | ||
for (let condition of conditions) { | ||
rules.push({ | ||
priority: genericBlock ? | ||
GENERIC_ALLOW_ALL_PRIORITY : SPECIFIC_ALLOW_ALL_PRIORITY, | ||
condition, | ||
action: { | ||
type: "allowAllRequests" | ||
} | ||
}); | ||
} | ||
} | ||
@@ -294,9 +319,14 @@ | ||
if (!resourceTypes || resourceTypes.length) { | ||
rules.push({ | ||
priority: genericBlock ? GENERIC_PRIORITY : SPECIFIC_PRIORITY, | ||
condition: getCondition(filter, urlFilter, resourceTypes, matchCase)[0], | ||
action: { | ||
type: "allow" | ||
} | ||
}); | ||
let {conditions} = | ||
getConditions(filter, urlFilter, resourceTypes, matchCase); | ||
for (let condition of conditions) { | ||
rules.push({ | ||
priority: genericBlock ? GENERIC_PRIORITY : SPECIFIC_PRIORITY, | ||
condition, | ||
action: { | ||
type: "allow" | ||
} | ||
}); | ||
} | ||
} | ||
@@ -303,0 +333,0 @@ |
@@ -297,4 +297,3 @@ /* | ||
"&disabled=" + String(disabled) + | ||
"&manifestVersion=" + encodeURIComponent(manifestVersion) + | ||
"&safe=true"; | ||
"&manifestVersion=" + encodeURIComponent(manifestVersion); | ||
@@ -301,0 +300,0 @@ if (downloadable.firstVersion && !downloadable.redirectURL) { |
{ | ||
"name": "@eyeo/webext-ad-filtering-solution", | ||
"version": "1.10.0", | ||
"version": "1.11.0", | ||
"description": "eyeo's WebExtension Ad-Filtering Solution", | ||
@@ -5,0 +5,0 @@ "repository": { |
Unreleased | ||
========== | ||
🐫 1.11.0 - 2024-08-08 🐫 | ||
========================= | ||
## General | ||
- Reverted a new query parameter in `downloader`. (EE-511, EE-837) | ||
## Fixes | ||
- In MV3, use the `requestDomains` condition in DNR rules for main frames, so | ||
that `$document` filters work correctly together with the `$domain` filter | ||
option. (EXT-55) | ||
- Fixed the CDP sessions counting (now using the correct time frame | ||
and deferring the browser events processing until the sessions data is loaded). (EXT-10) | ||
- Fix issue where diff updates in MV3 would sometimes get into a state where | ||
diffs would no longer be applied because the system had stored that | ||
update had already been applied. The diff update mechanism will now always | ||
apply the diff to the base version of the subscription that is bundled with | ||
the extension. If the base version cannot be loaded, then the update will fail | ||
with a `downloadStatus` of `synchronize_diff_error`. (EXT-54) | ||
🙈 1.10.0 - 2024-07-09 🙈 | ||
@@ -5,0 +26,0 @@ ========================= |
@@ -45,4 +45,2 @@ /* | ||
downloadUrl += downloadUrl.includes("?") ? "&safe=true" : "?safe=true"; | ||
return new Promise((resolve, reject) => { | ||
@@ -49,0 +47,0 @@ const file = fs.createWriteStream(toFile); |
@@ -35,2 +35,8 @@ /* | ||
let _forceEarlyUploads = false; | ||
export function setForceEarlyUploads(value) { | ||
_forceEarlyUploads = value; | ||
} | ||
let scheduler = null; | ||
@@ -263,6 +269,9 @@ | ||
if (bundle.scheduledSendTimestamp > now) { | ||
continue; | ||
if (!_forceEarlyUploads) { // for testing purpose | ||
continue; | ||
} | ||
} | ||
let startTimestamp = new Date(bundle.referenceDateLocal).getTime(); | ||
let startTimestamp = new Date(bundle.referenceDateLocal).getTime() + | ||
storage.getState().dayCutoffMinutes * MILLIS_IN_MINUTE; | ||
let endTimestamp = startTimestamp + MILLIS_IN_DAY; | ||
@@ -269,0 +278,0 @@ |
@@ -28,3 +28,3 @@ /* | ||
import {PersistentState} from "./persistence.js"; | ||
import {trace, debug} from "./debugging.js"; | ||
import {trace, debug, warn} from "./debugging.js"; | ||
import {isFirefox} from "./info.js"; | ||
@@ -58,4 +58,16 @@ | ||
let cdpDomains; | ||
let deferredEvents = []; | ||
// CDP events and pages user activity loading delay (for testing) | ||
let _loadDelay = 0; | ||
/** | ||
* @param {Number} millis Number of milliseconds to delay data loading | ||
* @ignore | ||
*/ | ||
export function setLoadDelay(millis) { | ||
_loadDelay = millis; | ||
} | ||
/** | ||
* Configure CDP | ||
@@ -99,15 +111,27 @@ * @ignore | ||
// Map<String(event type), Map<String(siteId), Array<Number>(event timestamp)>> | ||
let events = new Map([ | ||
[EVENT_PAGE_VIEW, new PersistentState("ewe:cdp-page-view", browser.storage.local)], | ||
[EVENT_SESSION_START, new PersistentState("ewe:cdp-session", browser.storage.local)], | ||
[EVENT_BLOCKING, new PersistentState("ewe:cdp-blocking", browser.storage.local)] | ||
]); | ||
for (const state of events.values()) { | ||
state.doDebounce(); | ||
let events; | ||
function initializeEvents() { | ||
events = new Map([ | ||
[EVENT_PAGE_VIEW, new PersistentState("ewe:cdp-page-view", browser.storage.local)], | ||
[EVENT_SESSION_START, new PersistentState("ewe:cdp-session", browser.storage.local)], | ||
[EVENT_BLOCKING, new PersistentState("ewe:cdp-blocking", browser.storage.local)] | ||
]); | ||
for (const state of events.values()) { | ||
state.doDebounce(); | ||
} | ||
} | ||
initializeEvents(); | ||
// Map<String(domain), Number(last user activity timestamp)> | ||
let activity = new PersistentState("ewe:cdp-activity", browser.storage.local); | ||
activity.doDebounce(); | ||
let activity; | ||
function initializeActivity() { | ||
activity = new PersistentState("ewe:cdp-activity", browser.storage.local); | ||
activity.doDebounce(); | ||
} | ||
initializeActivity(); | ||
// Map<Listener, Object (filter options)> | ||
@@ -204,4 +228,7 @@ let listeners = new Map(); | ||
timestamps.push(timeStamp); | ||
await state.save(); | ||
if (isStateLoaded()) { | ||
await state.save(); | ||
} | ||
await emitEvent(eventType, siteId, timeStamp); | ||
@@ -323,2 +350,8 @@ } | ||
if (!isStateLoaded()) { | ||
warn(() => `Deferring browser event: ${JSON.stringify(details)}`); | ||
deferredEvents.push({details, doMarkActive}); | ||
return; | ||
} | ||
if (details.frameId != TOP_LEVEL_FRAME_ID) { | ||
@@ -438,5 +471,46 @@ // Counting only outer-most frames | ||
function isStateLoaded() { | ||
for (const state of events.values()) { | ||
if (!state.loaded) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
function handleDeferredEvents() { | ||
if (deferredEvents.length > 0) { | ||
for (const eachEvent of deferredEvents) { | ||
handleBrowserEvent(eachEvent.details, eachEvent.doMarkActive); | ||
} | ||
warn(`Processed ${deferredEvents.length} deferred events`); | ||
deferredEvents = []; | ||
} | ||
} | ||
/** | ||
* @ignore | ||
*/ | ||
export function stop() { | ||
if (!startupPromise) { | ||
return; | ||
} | ||
startupPromise = null; | ||
new BlockableEventDispatcher().removeListener(onBlockableItem, { | ||
filterType: "blocking" | ||
}); | ||
browser.webNavigation.onBeforeNavigate.removeListener(onBeforeNavigate); | ||
browser.webNavigation.onHistoryStateUpdated.removeListener( | ||
onHistoryStateUpdated); | ||
initializeEvents(); | ||
initializeActivity(); | ||
} | ||
/** | ||
* @ignore | ||
*/ | ||
export async function start() { | ||
@@ -463,4 +537,15 @@ if (!startupPromise) { | ||
await loadEvents(); | ||
await activity.load(); | ||
async function loadData() { | ||
await loadEvents(); | ||
await activity.load(); | ||
handleDeferredEvents(); | ||
} | ||
if (_loadDelay == 0) { | ||
await loadData(); | ||
} | ||
else { | ||
// for testing purpose | ||
setTimeout(loadData, _loadDelay); | ||
} | ||
})(); | ||
@@ -467,0 +552,0 @@ } |
@@ -20,2 +20,3 @@ /* | ||
import {getFilterText} from "./subscriptions-utils.js"; | ||
import {Filter, InvalidFilter, URLFilter, isActiveFilter} | ||
@@ -37,4 +38,3 @@ from "adblockpluscore/lib/filterClasses.js"; | ||
import {default as initializer} from "./initializer.js"; | ||
import {filtersUpdateDiff} from "./set-operations.js"; | ||
import {trace, debug, error} from "./debugging.js"; | ||
import {debug, error} from "./debugging.js"; | ||
@@ -50,5 +50,2 @@ import {FilterError} from "./types.js"; | ||
// Subscription id to last diff update map | ||
let lastDiffUpdates = null; | ||
let initializationPromise; | ||
@@ -66,17 +63,2 @@ | ||
export async function restoreDynamicRules(subscriptionId) { | ||
for (let subscription of filterEngine.filterStorage.subscriptions()) { | ||
if (subscription.id == subscriptionId) { | ||
ensureRulesetUpdatesLoaded(); | ||
let lastUpdate = lastDiffUpdates.get(subscription.id); | ||
if (lastUpdate) { | ||
await _dnrDiffSubscriptionUpdate(subscription, lastUpdate, true); | ||
} | ||
break; | ||
} | ||
} | ||
} | ||
export async function disableDynamicRules(subscriptionId) { | ||
@@ -270,4 +252,2 @@ let subscriptionDynRules = findDynamicFilters(subscriptionId); | ||
async function _dnrFullSubscriptionUpdate(subscription, filterText) { | ||
trace({subscription, filterText}); | ||
// With some path of code the filter engine might not be initialized | ||
@@ -337,8 +317,6 @@ // if the service worker got awaken. | ||
export async function _dnrDiffSubscriptionUpdate( | ||
subscription, updates, skipEmitting) { | ||
export async function _dnrDiffSubscriptionUpdate(subscription, updates) { | ||
if (!browser.declarativeNetRequest || !updates) { | ||
return; | ||
} | ||
trace({subscription, updates}); | ||
@@ -360,3 +338,2 @@ // For now we only want to handle subscriptions that are in the | ||
let rollbackCallback = null; | ||
let filterTextToRuleIdsMapper = null; // to static rules ids | ||
@@ -380,29 +357,15 @@ | ||
ensureRulesetUpdatesLoaded(); | ||
let lastUpdate = lastDiffUpdates.get(subscription.id); | ||
// All the dynamic filters for this subscription must be removed. | ||
knownDynamicFilters = findDynamicFilters(subscription.id); | ||
rollbackCallback = async() => { | ||
if (!lastUpdate) { | ||
lastUpdate = {added: [], removed: []}; | ||
} | ||
await _dnrDiffSubscriptionUpdate(subscription, lastUpdate); | ||
}; | ||
} | ||
let filters = await processFilterTexts( | ||
let plannedChanges = await processFilterTexts( | ||
added, subscription.id, filterTextToRuleIdsMapper); | ||
if (knownDynamicFilters.size != 0) { | ||
filters.relateToThisSubscription.forEach( | ||
plannedChanges.relateToThisSubscription.forEach( | ||
text => knownDynamicFilters.delete(text)); | ||
} | ||
// Adding subscription.id into existing filter | ||
for (let text of filters.relateToOtherSubscriptions) { | ||
let filter = dynamicFilters.get(text); | ||
knownDynamicFilters.delete(text); | ||
filter.subscriptionIds.push(subscription.id); | ||
plannedChanges.relateToOtherSubscriptions.forEach( | ||
text => knownDynamicFilters.delete(text)); | ||
} | ||
@@ -414,41 +377,10 @@ | ||
let dynamicFiltersToRemove = removed.concat(...knownDynamicFilters.keys()); | ||
let removeRulesCount = countRulesToRemove(subscription.url, | ||
dynamicFiltersToRemove); | ||
// Removing subscription.id from existing filters that are removed. | ||
let {removedDynamicFilters, removeRuleIds} = | ||
removeDynamicFilters(subscription.id, dynamicFiltersToRemove); | ||
if (filters.add.length - removeRuleIds.length > | ||
if (plannedChanges.add.length - removeRulesCount > | ||
await dynamicRulesAvailable()) { | ||
if (rollbackCallback) { | ||
await rollbackCallback(); | ||
} | ||
throw new FilterError(ERROR_TOO_MANY_FILTERS); | ||
} | ||
// Empty array cause exceptions. Make it `undefined`. | ||
if (removeRuleIds.length == 0) { | ||
removeRuleIds = void 0; | ||
} | ||
// `skipEmitting` signals that's the restoring of dynamic filters, | ||
// so the subscription is about to be enabled. | ||
let subscriptionActive = skipEmitting || | ||
((await subscriptions.has(subscription.url)) && !subscription.disabled); | ||
await browser.declarativeNetRequest.updateDynamicRules( | ||
{addRules: subscriptionActive ? filters.add : void 0, removeRuleIds} | ||
); | ||
removedDynamicFilters.forEach(text => dynamicFilters.delete(text)); | ||
if (subscriptionActive) { | ||
filters.details.forEach(details => { | ||
let {useFilterEngine, filter, ruleIds, enabled} = details; | ||
setHighestRuleId(ruleIds); | ||
dynamicFilters.set(filter.text, | ||
{ruleIds, useFilterEngine, enabled, metadata: {}, | ||
subscriptionIds: [subscription.id]}); | ||
}); | ||
} | ||
if (needUpdateStaticRules) { | ||
@@ -468,3 +400,3 @@ if (removed.length > 0) { | ||
let enableRuleIds = [...filters.staticRulesToEnable]; | ||
let enableRuleIds = [...plannedChanges.staticRulesToEnable]; | ||
// Reenable the disabled rules to reset the state: | ||
@@ -486,5 +418,2 @@ // `browser.declarativeNetRequest.updateStaticRules` will handle this | ||
// currently seem to be another appropriate field it identify this case. | ||
if (rollbackCallback) { | ||
await rollbackCallback(); | ||
} | ||
throw new FilterError(ERROR_TOO_MANY_FILTERS); | ||
@@ -496,15 +425,38 @@ } | ||
let storageUpdate = await applyFilterTextUpdate(subscription, updates); | ||
// Adding subscription.id into existing filter | ||
for (let text of plannedChanges.relateToOtherSubscriptions) { | ||
let filter = dynamicFilters.get(text); | ||
filter.subscriptionIds.push(subscription.id); | ||
} | ||
lastDiffUpdates.set(subscription.id, updates); | ||
storeRulesetUpdates(); | ||
storeDynamicFilters(); | ||
// Removing subscription.id from existing filters that are removed. | ||
let {removedDynamicFilters, removeRuleIds} = | ||
removeDynamicFilters(subscription.id, dynamicFiltersToRemove); | ||
if (!skipEmitting) { | ||
// `dnrDiffSubscriptionUpdate()` is currently used for some internal | ||
// routines, eg. restoring the dynamic rules for the subscription, | ||
// which does not mean there was a subscription update actually (EE-163), | ||
// so we might skip emitting the event. | ||
filterNotifier.emit("subscription.updated", subscription, storageUpdate); | ||
// Empty array cause exceptions. Make it `undefined`. | ||
if (removeRuleIds.length == 0) { | ||
removeRuleIds = void 0; | ||
} | ||
let subscriptionActive = (await subscriptions.has(subscription.url)) && | ||
!subscription.disabled; | ||
await browser.declarativeNetRequest.updateDynamicRules( | ||
{addRules: subscriptionActive ? plannedChanges.add : void 0, removeRuleIds} | ||
); | ||
removedDynamicFilters.forEach(text => dynamicFilters.delete(text)); | ||
if (subscriptionActive) { | ||
plannedChanges.details.forEach(details => { | ||
let {useFilterEngine, filter, ruleIds, enabled} = details; | ||
setHighestRuleId(ruleIds); | ||
dynamicFilters.set(filter.text, | ||
{ruleIds, useFilterEngine, enabled, metadata: {}, | ||
subscriptionIds: [subscription.id]}); | ||
}); | ||
} | ||
await applyFilterTextUpdate(subscription, updates); | ||
storeDynamicFilters(); | ||
} | ||
@@ -518,31 +470,18 @@ | ||
*/ | ||
export async function applyFilterTextUpdate(subscription, updates) { | ||
ensureRulesetUpdatesLoaded(); | ||
async function applyFilterTextUpdate(subscription, updates) { | ||
let {filterText} = await getFilterText(subscription); | ||
// apply the update to the storage | ||
let base = lastDiffUpdates.get(subscription.id); | ||
let storageUpdate; | ||
if (base) { | ||
storageUpdate = filtersUpdateDiff(base, updates); | ||
} | ||
else { | ||
storageUpdate = { | ||
added: updates.added, | ||
removed: updates.removed | ||
}; | ||
} | ||
for (let text of storageUpdate.removed) { | ||
let index = subscription.findFilterTextIndex(text); | ||
for (let removeText of updates.removed) { | ||
let index = filterText.indexOf(removeText); | ||
if (index >= 0) { | ||
subscription.deleteFilterAt(index); | ||
filterText.splice(index, 1); | ||
} | ||
} | ||
for (let text of storageUpdate.added) { | ||
subscription.addFilterText(text); | ||
for (let addText of updates.added) { | ||
filterText.push(addText); | ||
} | ||
await filterEngine.filterStorage.saveToDisk(); | ||
return storageUpdate; | ||
let storageUpdate = subscription.updateFilterText(filterText); | ||
filterNotifier.emit("subscription.updated", subscription, storageUpdate); | ||
} | ||
@@ -604,26 +543,4 @@ | ||
function storeRulesetUpdates() { | ||
let storageArray = []; | ||
storageArray.push(...lastDiffUpdates); | ||
Prefs.ruleset_updates = storageArray; | ||
} | ||
function ensureRulesetUpdatesLoaded() { | ||
if (!lastDiffUpdates) { | ||
loadRulesetUpdates(); | ||
} | ||
} | ||
function loadRulesetUpdates() { | ||
let rulesetUpdatesArray = Prefs.ruleset_updates; | ||
if (!Array.isArray(rulesetUpdatesArray)) { | ||
rulesetUpdatesArray = []; | ||
} | ||
lastDiffUpdates = new Map(rulesetUpdatesArray); | ||
} | ||
export function clearRulesetUpdates() { | ||
ensureRulesetUpdatesLoaded(); | ||
lastDiffUpdates.clear(); | ||
// This isn't used anymore. It can be cleared out to save storage. | ||
Prefs.ruleset_updates = []; | ||
@@ -630,0 +547,0 @@ } |
@@ -20,2 +20,5 @@ /* | ||
import {PersistentState} from "./persistence.js"; | ||
import {parseFilterList} from "adblockpluscore/lib/filters/lists.js"; | ||
import {readFileContent} from "./io.js"; | ||
import {addonBundledSubscriptionsPath} from "./info.js"; | ||
@@ -104,1 +107,15 @@ function getRuleset(rulesetId) { | ||
} | ||
export async function getFilterText(subscription) { | ||
let subscriptionPath = `${addonBundledSubscriptionsPath}/${subscription.id}`; | ||
let rawLines = await readFileContent(subscriptionPath); | ||
let {lines, params, error} = parseFilterList(rawLines); | ||
if (error) { | ||
throw new Error(error); | ||
} | ||
if (!lines) { | ||
throw new Error("invalid filter list"); | ||
} | ||
lines.shift(); | ||
return {filterText: lines, params}; | ||
} |
@@ -21,3 +21,3 @@ /* | ||
import {validate as validateSubscriptions} from "./subscriptions-validator.js"; | ||
import {rulesetExistsInManifest} from "./subscriptions-utils.js"; | ||
import {rulesetExistsInManifest, getFilterText} from "./subscriptions-utils.js"; | ||
import {Subscription, CountableSubscription, RegularSubscription, | ||
@@ -30,6 +30,4 @@ FullUpdatableSubscription, SpecialSubscription, | ||
import {Filter} from "adblockpluscore/lib/filterClasses.js"; | ||
import {parseFilterList} from "adblockpluscore/lib/filters/lists.js"; | ||
import {addonBundledSubscriptions, addonBundledSubscriptionsPath} | ||
from "./info.js"; | ||
import {addonBundledSubscriptions} from "./info.js"; | ||
import {default as initializer} from "./initializer.js"; | ||
@@ -39,6 +37,4 @@ import {filterEngine} from "./core.js"; | ||
import {convertFilter} from "./filters.js"; | ||
import {disableDynamicRules, restoreDynamicRules, | ||
isDnrSubscriptionUpdating} from "./dnr-filters.js"; | ||
import {disableDynamicRules, isDnrSubscriptionUpdating} from "./dnr-filters.js"; | ||
import {readFileContent} from "./io.js"; | ||
import {Prefs} from "./prefs.js"; | ||
@@ -243,4 +239,2 @@ | ||
}); | ||
await restoreDynamicRules(rulesetId); | ||
} | ||
@@ -269,16 +263,2 @@ } | ||
async function getFilterText(subscription, path) { | ||
let subscriptionPath = `${path}/${subscription.id}`; | ||
let rawLines = await readFileContent(subscriptionPath); | ||
let {lines, params, error} = parseFilterList(rawLines); | ||
if (error) { | ||
throw new Error(error); | ||
} | ||
if (!lines) { | ||
throw new Error("invalid filter list"); | ||
} | ||
lines.shift(); | ||
return {filterText: lines, params}; | ||
} | ||
/** | ||
@@ -369,4 +349,3 @@ * @ignore | ||
try { | ||
let {filterText} = await getFilterText( | ||
subscriptionInfo, addonBundledSubscriptionsPath); | ||
let {filterText} = await getFilterText(subscriptionInfo); | ||
subscription.setFilterText(filterText); | ||
@@ -447,4 +426,3 @@ } | ||
try { | ||
({filterText, params} = await getFilterText( | ||
subscriptionInfo, addonBundledSubscriptionsPath)); | ||
({filterText, params} = await getFilterText(subscriptionInfo)); | ||
} | ||
@@ -828,8 +806,3 @@ catch (e) { | ||
if (browser.declarativeNetRequest) { | ||
if (subscription instanceof FullUpdatableSubscription) { | ||
await restoreDynamicRules(subscription.url); | ||
} | ||
else { | ||
await enableRuleset(subscription.id); | ||
} | ||
await enableRuleset(subscription.id); | ||
} | ||
@@ -836,0 +809,0 @@ |
@@ -39,4 +39,4 @@ /* | ||
import {dnrDiffSubscriptionUpdate, dynamicRulesAvailable, getDynamicFilters, | ||
removeAllDynamicFilters, clearRulesetUpdates, | ||
testSetDynamicRulesAvailable, clearIsDnrSubscriptionUpdating} | ||
removeAllDynamicFilters, testSetDynamicRulesAvailable, | ||
clearIsDnrSubscriptionUpdating} | ||
from "./dnr-filters.js"; | ||
@@ -51,5 +51,3 @@ import {getSubscriptionRulesetMap} from "./subscriptions-utils.js"; | ||
import {getDeferredMessages} from "./content-message-deferrer.js"; | ||
import {setData, getData, clearData, clearActivity, | ||
_restoreConfig, _setConfig} | ||
from "./cdp.js"; | ||
import * as cdp from "./cdp.js"; | ||
import {_clear} from "./frame-state.js"; | ||
@@ -187,3 +185,2 @@ | ||
await removeAllDynamicFilters(); | ||
await clearRulesetUpdates(); | ||
clearIsDnrSubscriptionUpdating(); | ||
@@ -305,6 +302,19 @@ | ||
resetTelemetry: telemetry.reset, | ||
stopCdpMetricsUploader: cdpMetricsUploader.stop, | ||
startCdpMetricsUploader: cdpMetricsUploader.start, | ||
resetCdpMetricsUploader: cdpMetricsUploader.reset, | ||
setForceEarlyCdpUploads: cdpMetricsUploader.setForceEarlyUploads, | ||
stopCdp: cdp.stop, | ||
startCdp: cdp.start, | ||
setCdpLoadDelay: cdp.setLoadDelay, | ||
_setCdpConfig: cdp._setConfig, | ||
_restoreCdpConfig: cdp._restoreConfig, | ||
_setCdpData: cdp.setData, | ||
_getCdpData: cdp.getData, | ||
_clearCdpData: cdp.clearData, | ||
_clearCdpActivity: cdp.clearActivity, | ||
clearSkipInitRulesets, | ||
@@ -339,9 +349,3 @@ checkAndInitSubscriptions, | ||
_setCdpConfig: _setConfig, | ||
_restoreCdpConfig: _restoreConfig, | ||
_setCdpData: setData, | ||
_getCdpData: getData, | ||
_clearCdpData: clearData, | ||
_clearCdpActivity: clearActivity, | ||
_clearFrameState: _clear | ||
}; |
Sorry, the diff of this file is too big to display
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
4341982
146
72120
19