зеркало из https://github.com/mozilla/gecko-dev.git
138 строки
3.5 KiB
JavaScript
138 строки
3.5 KiB
JavaScript
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
this.UrlClassifierSkipListService = function() {};
|
|
|
|
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
|
|
|
ChromeUtils.defineModuleGetter(
|
|
this,
|
|
"RemoteSettings",
|
|
"resource://services-settings/remote-settings.js"
|
|
);
|
|
|
|
const COLLECTION_NAME = "url-classifier-skip-urls";
|
|
|
|
class Feature {
|
|
constructor(name, prefName) {
|
|
this.name = name;
|
|
this.prefName = prefName;
|
|
this.observers = new Set();
|
|
this.prefValue = null;
|
|
this.remoteEntries = null;
|
|
|
|
if (prefName) {
|
|
this.prefValue = Services.prefs.getStringPref(this.prefName, null);
|
|
Services.prefs.addObserver(prefName, this);
|
|
}
|
|
}
|
|
|
|
async addObserver(observer) {
|
|
// If the remote settings list hasn't been populated yet we have to make sure
|
|
// to do it before firing the first notification.
|
|
if (!this.remoteEntries) {
|
|
let remoteEntries;
|
|
try {
|
|
// The data will be initially available from the local DB (via a
|
|
// resource:// URI).
|
|
remoteEntries = await RemoteSettings(COLLECTION_NAME).get();
|
|
} catch (e) {
|
|
remoteEntries = [];
|
|
}
|
|
this.onRemoteSettingsUpdate(remoteEntries);
|
|
}
|
|
|
|
this.observers.add(observer);
|
|
this.notifyObservers(observer);
|
|
}
|
|
|
|
removeObserver(observer) {
|
|
this.observers.delete(observer);
|
|
}
|
|
|
|
observe(subject, topic, data) {
|
|
if (topic != "nsPref:changed" || data != this.prefName) {
|
|
Cu.reportError(`Unexpected event ${topic} with ${data}`);
|
|
return;
|
|
}
|
|
|
|
this.prefValue = Services.prefs.getStringPref(this.prefName, null);
|
|
this.notifyObservers();
|
|
}
|
|
|
|
onRemoteSettingsUpdate(entries) {
|
|
this.remoteEntries = [];
|
|
for (let entry of entries) {
|
|
if (entry.feature == this.name) {
|
|
this.remoteEntries.push(entry.pattern.toLowerCase());
|
|
}
|
|
}
|
|
}
|
|
|
|
notifyObservers(observer = null) {
|
|
let entries = [];
|
|
if (this.prefValue) {
|
|
entries = this.prefValue.split(",");
|
|
}
|
|
|
|
for (let entry of this.remoteEntries) {
|
|
entries.push(entry);
|
|
}
|
|
|
|
let entriesAsString = entries.join(",").toLowerCase();
|
|
if (observer) {
|
|
observer.onSkipListUpdate(entriesAsString);
|
|
} else {
|
|
for (let obs of this.observers) {
|
|
obs.onSkipListUpdate(entriesAsString);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
UrlClassifierSkipListService.prototype = {
|
|
classID: Components.ID("{b9f4fd03-9d87-4bfd-9958-85a821750ddc}"),
|
|
QueryInterface: ChromeUtils.generateQI([Ci.nsIUrlClassifierSkipListService]),
|
|
|
|
features: {},
|
|
_initialized: false,
|
|
|
|
lazyInit() {
|
|
if (this._initialized) {
|
|
return;
|
|
}
|
|
|
|
RemoteSettings(COLLECTION_NAME).on("sync", event => {
|
|
let {
|
|
data: { current },
|
|
} = event;
|
|
for (let key of Object.keys(this.features)) {
|
|
let feature = this.features[key];
|
|
feature.onRemoteSettingsUpdate(current);
|
|
feature.notifyObservers();
|
|
}
|
|
});
|
|
|
|
this._initialized = true;
|
|
},
|
|
|
|
registerAndRunSkipListObserver(feature, prefName, observer) {
|
|
this.lazyInit();
|
|
|
|
if (!this.features[feature]) {
|
|
this.features[feature] = new Feature(feature, prefName);
|
|
}
|
|
this.features[feature].addObserver(observer);
|
|
},
|
|
|
|
unregisterSkipListObserver(feature, observer) {
|
|
if (!this.features[feature]) {
|
|
return;
|
|
}
|
|
this.features[feature].removeObserver(observer);
|
|
},
|
|
};
|
|
|
|
var EXPORTED_SYMBOLS = ["UrlClassifierSkipListService"];
|