Skip to content

Commit 264e394

Browse files
committed
Wait for seed DNR rule registration on first run
To avoid a race condition when we remove tracker data immediately following initialization in tests and Badger Sett.
1 parent 648e924 commit 264e394

File tree

2 files changed

+61
-4
lines changed

2 files changed

+61
-4
lines changed

src/js/background.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ function Badger(from_qunit) {
131131
await pbconfigPromise;
132132
// also get ready to create dynamic DNR rules
133133
subscribeToActionMapUpdates();
134+
// get ready to await initial DNR rules creation
135+
let dnrRegistrationPromise = self.subscribeToDnrUpdates().catch(console.error);
134136
// now async load seed data
135137
let seedDataPromise = self.updateTrackerData().catch(console.error);
136138

@@ -164,6 +166,8 @@ function Badger(from_qunit) {
164166
globalThis.DATA_LOAD_IN_PROGRESS = false;
165167
}
166168

169+
await dnrRegistrationPromise;
170+
167171
log("Initialization complete");
168172
self.INITIALIZED = true;
169173
globalThis.DEBUG = false;
@@ -386,6 +390,42 @@ Badger.prototype = {
386390
}
387391
},
388392

393+
/**
394+
* Resolves upon registration of the initial set of DNR rules on install.
395+
*
396+
* @returns {Promise}
397+
*/
398+
subscribeToDnrUpdates: function () {
399+
let self = this;
400+
401+
return new Promise((resolve) => {
402+
function onDynamicRulesUpdate(stats) {
403+
let sm = badger.storage.getStore('snitch_map'),
404+
num_blocked = sm.keys().filter(d =>
405+
sm.getItem(d).length >= constants.TRACKING_THRESHOLD).length;
406+
407+
// we are done if we registered a block of rules at least as big
408+
// as the count of (cookie)blocked eTLD+1 domains in seed data
409+
//
410+
// this check is here so that we don't think we are done too early,
411+
// when we register a smaller set of rules before we get to seed rules
412+
//
413+
// this assumes seed rules get generated in a single round
414+
if (stats.numAdded >= num_blocked) {
415+
return resolve();
416+
}
417+
418+
dnrUtils.updateDynamicRules.subscribeToNextUpdate(onDynamicRulesUpdate);
419+
}
420+
421+
if (!self.isFirstRun) {
422+
return resolve();
423+
}
424+
425+
dnrUtils.updateDynamicRules.subscribeToNextUpdate(onDynamicRulesUpdate);
426+
});
427+
},
428+
389429
/**
390430
* Loads seed dataset.
391431
*

src/lib/dnr/utils.js

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,8 @@ let updateSessionAllowRules = utils.debounce(async function (tempAllowlist) {
349349
* Debounced version of chrome.declarativeNetRequest.updateDynamicRules()
350350
*/
351351
let updateDynamicRules = (function () {
352-
let queue = [];
352+
let queue = [],
353+
subscribers = [];
353354

354355
let _update = utils.debounce(function () {
355356
let opts = {
@@ -367,19 +368,35 @@ let updateDynamicRules = (function () {
367368
}
368369
queue = [];
369370

370-
log("[DNR] updateDynamicRules: addRules=%s, removeRuleIds=%s",
371-
opts.addRules.length, opts.removeRuleIds.length);
371+
let num_added = opts.addRules.length,
372+
num_removed = opts.removeRuleIds.length;
372373

373-
chrome.declarativeNetRequest.updateDynamicRules(opts);
374+
log("[DNR] updateDynamicRules: addRules=%s, removeRuleIds=%s",
375+
num_added, num_removed);
376+
377+
chrome.declarativeNetRequest.updateDynamicRules(opts, function () {
378+
// notify all subscribers
379+
let fns = subscribers.slice(0);
380+
// avoid an infinite loop in case of immediate re-subscription
381+
subscribers = [];
382+
for (let fn of fns) {
383+
fn({ numAdded: num_added, numRemoved: num_removed });
384+
}
385+
});
374386
}, 100);
375387

376388
let ret = function (opts) {
377389
queue.push(opts);
378390
_update();
379391
};
380392

393+
ret.subscribeToNextUpdate = function (fn) {
394+
subscribers.push(fn);
395+
};
396+
381397
ret.clearQueue = function () {
382398
queue = [];
399+
subscribers = [];
383400
};
384401

385402
return ret;

0 commit comments

Comments
 (0)