1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 ChromeUtils.defineESModuleGetters(lazy, {
8 RemoteSettings: "resource://services-settings/remote-settings.sys.mjs",
11 // Name of the RemoteSettings collection containing the rules.
12 const COLLECTION_NAME = "bounce-tracking-protection-exceptions";
14 export class BTPRemoteExceptionList {
15 classId = Components.ID("{06F13674-FB28-4DFC-BF25-342C83705B2F}");
16 QueryInterface = ChromeUtils.generateQI(["nsIBTPRemoteExceptionList"]);
19 // Stores the this-wrapped on-sync callback so it can be unregistered on
21 #onSyncCallback = null;
23 // Weak reference to nsIBounceTrackingProtection.
27 this.#rs = lazy.RemoteSettings(COLLECTION_NAME);
30 async init(bounceTrackingProtection) {
31 if (!bounceTrackingProtection) {
32 throw new Error("Missing required argument bounceTrackingProtection");
34 // Get a weak ref to BounceTrackingProtection to avoid a reference cycle.
35 this.#btp = Cu.getWeakReference(bounceTrackingProtection);
37 await this.importAllExceptions();
39 // Register callback for collection changes.
40 // Only register if not already registered.
41 if (!this.#onSyncCallback) {
42 this.#onSyncCallback = this.onSync.bind(this);
43 this.#rs.on("sync", this.#onSyncCallback);
48 // Unregister callback for collection changes.
49 if (this.#onSyncCallback) {
50 this.#rs.off("sync", this.#onSyncCallback);
51 this.#onSyncCallback = null;
56 * Called for remote settings "sync" events.
58 onSync({ data: { created = [], updated = [], deleted = [] } }) {
59 // Check if feature is still active before attempting to send updates.
60 let btp = this.#btp?.get();
65 let siteHostsToRemove = deleted.map(ex => ex.siteHost);
66 let siteHostsToAdd = created.map(ex => ex.siteHost);
68 updated.forEach(ex => {
69 // We only care about site host changes.
70 if (ex.old.siteHost == ex.new.siteHost) {
73 siteHostsToRemove.push(ex.old.siteHost);
74 siteHostsToAdd.push(ex.new.siteHost);
77 if (siteHostsToRemove.length) {
78 btp.removeSiteHostExceptions(siteHostsToRemove);
80 if (siteHostsToAdd.length) {
81 btp.addSiteHostExceptions(siteHostsToAdd);
85 async importAllExceptions() {
87 let exceptions = await this.#rs.get();
88 if (!exceptions.length) {
91 this.onSync({ data: { created: exceptions } });
94 "Error while importing BTP exceptions from RemoteSettings",