2016-02-09 21:51:08 +03:00
|
|
|
/* 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/. */
|
|
|
|
|
|
|
|
"use strict";
|
|
|
|
|
2016-04-18 12:38:25 +03:00
|
|
|
this.EXPORTED_SYMBOLS = ["AddonBlocklistClient",
|
|
|
|
"GfxBlocklistClient",
|
|
|
|
"OneCRLBlocklistClient",
|
2017-02-16 06:07:26 +03:00
|
|
|
"PluginBlocklistClient",
|
2016-12-16 19:34:42 +03:00
|
|
|
"PinningBlocklistClient",
|
2017-02-16 06:07:26 +03:00
|
|
|
"FILENAME_ADDONS_JSON",
|
|
|
|
"FILENAME_GFX_JSON",
|
|
|
|
"FILENAME_PLUGINS_JSON"];
|
2016-02-09 21:51:08 +03:00
|
|
|
|
|
|
|
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
|
|
|
|
|
|
|
Cu.import("resource://gre/modules/Services.jsm");
|
2017-01-09 13:12:26 +03:00
|
|
|
const { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
|
|
|
|
const { OS } = Cu.import("resource://gre/modules/osfile.jsm", {});
|
2016-06-02 11:01:26 +03:00
|
|
|
Cu.importGlobalProperties(["fetch"]);
|
2016-04-18 12:38:25 +03:00
|
|
|
|
2017-01-09 13:12:26 +03:00
|
|
|
const { Kinto } = Cu.import("resource://services-common/kinto-offline-client.js", {});
|
|
|
|
const { KintoHttpClient } = Cu.import("resource://services-common/kinto-http-client.js", {});
|
|
|
|
const { FirefoxAdapter } = Cu.import("resource://services-common/kinto-storage-adapter.js", {});
|
|
|
|
const { CanonicalJSON } = Components.utils.import("resource://gre/modules/CanonicalJSON.jsm", {});
|
2016-04-18 12:38:25 +03:00
|
|
|
|
2016-05-19 13:51:13 +03:00
|
|
|
const PREF_SETTINGS_SERVER = "services.settings.server";
|
|
|
|
const PREF_BLOCKLIST_BUCKET = "services.blocklist.bucket";
|
|
|
|
const PREF_BLOCKLIST_ONECRL_COLLECTION = "services.blocklist.onecrl.collection";
|
|
|
|
const PREF_BLOCKLIST_ONECRL_CHECKED_SECONDS = "services.blocklist.onecrl.checked";
|
|
|
|
const PREF_BLOCKLIST_ADDONS_COLLECTION = "services.blocklist.addons.collection";
|
|
|
|
const PREF_BLOCKLIST_ADDONS_CHECKED_SECONDS = "services.blocklist.addons.checked";
|
|
|
|
const PREF_BLOCKLIST_PLUGINS_COLLECTION = "services.blocklist.plugins.collection";
|
|
|
|
const PREF_BLOCKLIST_PLUGINS_CHECKED_SECONDS = "services.blocklist.plugins.checked";
|
2016-12-16 19:34:42 +03:00
|
|
|
const PREF_BLOCKLIST_PINNING_ENABLED = "services.blocklist.pinning.enabled";
|
|
|
|
const PREF_BLOCKLIST_PINNING_BUCKET = "services.blocklist.pinning.bucket";
|
|
|
|
const PREF_BLOCKLIST_PINNING_COLLECTION = "services.blocklist.pinning.collection";
|
|
|
|
const PREF_BLOCKLIST_PINNING_CHECKED_SECONDS = "services.blocklist.pinning.checked";
|
2016-05-19 13:51:13 +03:00
|
|
|
const PREF_BLOCKLIST_GFX_COLLECTION = "services.blocklist.gfx.collection";
|
|
|
|
const PREF_BLOCKLIST_GFX_CHECKED_SECONDS = "services.blocklist.gfx.checked";
|
2016-06-02 11:01:26 +03:00
|
|
|
const PREF_BLOCKLIST_ENFORCE_SIGNING = "services.blocklist.signing.enforced";
|
|
|
|
|
|
|
|
const INVALID_SIGNATURE = "Invalid content/signature";
|
2016-04-18 12:38:25 +03:00
|
|
|
|
Bug 1319884 - Address FirefoxAdapter feedback from kinto.js#589, r=mgoodwin
Change FirefoxAdapter definitively to require an externally-managed
Sqlite connection in order to function. This connection must be
produced by calling an openConnection() static method, which does the
work of initializing the tables and schema. Passing any other
connection is wrong, but won't be detected at runtime, and might even
work depending on the previous state of the database. Future work
might define a new KintoSqliteConnection type that can only be
produced by this method, so that it's impossible to create an
uninitialized Kinto database.
This change, since it moves Sqlite connections out of the
FirefoxAdapter, also means that the path option is no longer handled
or provided with a default. This means that the previous default,
"kinto.sqlite", is now preserved in a bunch of places all over the
codebase. This is unfortunate, but a migration is outside the scope of
this patch.
MozReview-Commit-ID: BKJqPR3jOTq
--HG--
extra : rebase_source : 91e0027890ac5fd0ba683abddc23e268f672d169
2016-11-23 22:18:53 +03:00
|
|
|
// FIXME: this was the default path in earlier versions of
|
|
|
|
// FirefoxAdapter, so for backwards compatibility we maintain this
|
|
|
|
// filename, even though it isn't descriptive of who is using it.
|
|
|
|
this.KINTO_STORAGE_PATH = "kinto.sqlite";
|
|
|
|
|
2017-02-16 06:07:26 +03:00
|
|
|
this.FILENAME_ADDONS_JSON = "blocklist-addons.json";
|
|
|
|
this.FILENAME_GFX_JSON = "blocklist-gfx.json";
|
|
|
|
this.FILENAME_PLUGINS_JSON = "blocklist-plugins.json";
|
2016-04-18 12:38:25 +03:00
|
|
|
|
2017-01-17 17:04:43 +03:00
|
|
|
|
2016-11-18 18:07:39 +03:00
|
|
|
function mergeChanges(collection, localRecords, changes) {
|
2016-06-02 11:01:26 +03:00
|
|
|
const records = {};
|
|
|
|
// Local records by id.
|
2016-11-18 18:07:39 +03:00
|
|
|
localRecords.forEach((record) => records[record.id] = collection.cleanLocalFields(record));
|
2016-06-02 11:01:26 +03:00
|
|
|
// All existing records are replaced by the version from the server.
|
|
|
|
changes.forEach((record) => records[record.id] = record);
|
|
|
|
|
|
|
|
return Object.values(records)
|
|
|
|
// Filter out deleted records.
|
|
|
|
.filter((record) => record.deleted != true)
|
|
|
|
// Sort list by record id.
|
2017-02-17 04:34:45 +03:00
|
|
|
.sort((a, b) => {
|
|
|
|
if (a.id < b.id) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return a.id > b.id ? 1 : 0;
|
|
|
|
});
|
2016-06-02 11:01:26 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-06 12:35:26 +03:00
|
|
|
function fetchCollectionMetadata(remote, collection) {
|
|
|
|
const client = new KintoHttpClient(remote);
|
2016-07-13 22:09:42 +03:00
|
|
|
return client.bucket(collection.bucket).collection(collection.name).getData()
|
2016-06-02 11:01:26 +03:00
|
|
|
.then(result => {
|
|
|
|
return result.signature;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-02-06 12:35:26 +03:00
|
|
|
function fetchRemoteCollection(remote, collection) {
|
|
|
|
const client = new KintoHttpClient(remote);
|
2016-06-02 11:01:26 +03:00
|
|
|
return client.bucket(collection.bucket)
|
|
|
|
.collection(collection.name)
|
|
|
|
.listRecords({sort: "id"});
|
|
|
|
}
|
2016-04-18 12:38:25 +03:00
|
|
|
|
2016-02-09 21:51:08 +03:00
|
|
|
|
2016-04-18 12:38:25 +03:00
|
|
|
class BlocklistClient {
|
|
|
|
|
2016-12-16 19:34:42 +03:00
|
|
|
constructor(collectionName, lastCheckTimePref, processCallback, bucketName, signerName) {
|
2016-04-18 12:38:25 +03:00
|
|
|
this.collectionName = collectionName;
|
|
|
|
this.lastCheckTimePref = lastCheckTimePref;
|
|
|
|
this.processCallback = processCallback;
|
2016-12-16 19:34:42 +03:00
|
|
|
this.bucketName = bucketName;
|
2016-06-02 11:01:26 +03:00
|
|
|
this.signerName = signerName;
|
2017-02-06 12:35:26 +03:00
|
|
|
|
|
|
|
this._kinto = new Kinto({
|
|
|
|
bucket: bucketName,
|
|
|
|
adapter: FirefoxAdapter,
|
|
|
|
});
|
2016-06-02 11:01:26 +03:00
|
|
|
}
|
|
|
|
|
2017-02-06 12:35:26 +03:00
|
|
|
validateCollectionSignature(remote, payload, collection, options = {}) {
|
|
|
|
const {ignoreLocal} = options;
|
|
|
|
|
2016-06-02 11:01:26 +03:00
|
|
|
return Task.spawn((function* () {
|
|
|
|
// this is a content-signature field from an autograph response.
|
2017-02-06 12:35:26 +03:00
|
|
|
const {x5u, signature} = yield fetchCollectionMetadata(remote, collection);
|
2016-06-02 11:01:26 +03:00
|
|
|
const certChain = yield fetch(x5u).then((res) => res.text());
|
|
|
|
|
|
|
|
const verifier = Cc["@mozilla.org/security/contentsignatureverifier;1"]
|
|
|
|
.createInstance(Ci.nsIContentSignatureVerifier);
|
|
|
|
|
2016-07-18 21:32:56 +03:00
|
|
|
let toSerialize;
|
|
|
|
if (ignoreLocal) {
|
|
|
|
toSerialize = {
|
|
|
|
last_modified: `${payload.last_modified}`,
|
|
|
|
data: payload.data
|
|
|
|
};
|
2016-06-02 11:01:26 +03:00
|
|
|
} else {
|
2017-01-17 17:04:43 +03:00
|
|
|
const {data: localRecords} = yield collection.list();
|
2016-11-18 18:07:39 +03:00
|
|
|
const records = mergeChanges(collection, localRecords, payload.changes);
|
2016-07-18 21:32:56 +03:00
|
|
|
toSerialize = {
|
|
|
|
last_modified: `${payload.lastModified}`,
|
|
|
|
data: records
|
|
|
|
};
|
2016-06-02 11:01:26 +03:00
|
|
|
}
|
2016-07-18 21:32:56 +03:00
|
|
|
|
|
|
|
const serialized = CanonicalJSON.stringify(toSerialize);
|
2016-06-02 11:01:26 +03:00
|
|
|
|
|
|
|
if (verifier.verifyContentSignature(serialized, "p384ecdsa=" + signature,
|
|
|
|
certChain,
|
|
|
|
this.signerName)) {
|
|
|
|
// In case the hash is valid, apply the changes locally.
|
|
|
|
return payload;
|
|
|
|
}
|
|
|
|
throw new Error(INVALID_SIGNATURE);
|
|
|
|
}).bind(this));
|
2016-04-18 12:38:25 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Synchronize from Kinto server, if necessary.
|
|
|
|
*
|
2017-02-16 06:07:26 +03:00
|
|
|
* @param {int} lastModified the lastModified date (on the server) for
|
|
|
|
the remote collection.
|
|
|
|
* @param {Date} serverTime the current date return by the server.
|
|
|
|
* @return {Promise} which rejects on sync or process failure.
|
2016-04-18 12:38:25 +03:00
|
|
|
*/
|
2017-02-16 06:07:26 +03:00
|
|
|
maybeSync(lastModified, serverTime) {
|
2017-02-06 12:35:26 +03:00
|
|
|
const remote = Services.prefs.getCharPref(PREF_SETTINGS_SERVER);
|
2017-02-16 06:07:26 +03:00
|
|
|
let enforceCollectionSigning =
|
2016-06-02 11:01:26 +03:00
|
|
|
Services.prefs.getBoolPref(PREF_BLOCKLIST_ENFORCE_SIGNING);
|
|
|
|
|
|
|
|
// if there is a signerName and collection signing is enforced, add a
|
|
|
|
// hook for incoming changes that validates the signature
|
2017-02-06 12:35:26 +03:00
|
|
|
let hooks;
|
2016-06-02 11:01:26 +03:00
|
|
|
if (this.signerName && enforceCollectionSigning) {
|
2017-02-06 12:35:26 +03:00
|
|
|
hooks = {
|
|
|
|
"incoming-changes": [(payload, collection) => {
|
|
|
|
return this.validateCollectionSignature(remote, payload, collection);
|
|
|
|
}]
|
2016-06-02 11:01:26 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-18 12:38:25 +03:00
|
|
|
return Task.spawn((function* syncCollection() {
|
2017-02-06 12:35:26 +03:00
|
|
|
let sqliteHandle;
|
2016-02-09 21:51:08 +03:00
|
|
|
try {
|
2017-02-06 12:35:26 +03:00
|
|
|
// Synchronize remote data into a local Sqlite DB.
|
|
|
|
sqliteHandle = yield FirefoxAdapter.openConnection({path: KINTO_STORAGE_PATH});
|
|
|
|
const options = {
|
|
|
|
hooks,
|
|
|
|
adapterOptions: {sqliteHandle},
|
|
|
|
};
|
|
|
|
const collection = this._kinto.collection(this.collectionName, options);
|
2016-04-18 12:38:25 +03:00
|
|
|
|
2017-02-16 06:07:26 +03:00
|
|
|
const collectionLastModified = yield collection.db.getLastModified();
|
2016-04-18 12:38:25 +03:00
|
|
|
// If the data is up to date, there's no need to sync. We still need
|
2016-02-09 21:51:08 +03:00
|
|
|
// to record the fact that a check happened.
|
|
|
|
if (lastModified <= collectionLastModified) {
|
2016-04-18 12:38:25 +03:00
|
|
|
this.updateLastCheck(serverTime);
|
2016-02-09 21:51:08 +03:00
|
|
|
return;
|
|
|
|
}
|
2016-04-18 12:38:25 +03:00
|
|
|
// Fetch changes from server.
|
2016-06-02 11:01:26 +03:00
|
|
|
try {
|
2017-02-06 12:35:26 +03:00
|
|
|
const {ok} = yield collection.sync({remote});
|
2017-01-17 17:04:43 +03:00
|
|
|
if (!ok) {
|
2016-06-02 11:01:26 +03:00
|
|
|
throw new Error("Sync failed");
|
|
|
|
}
|
|
|
|
} catch (e) {
|
|
|
|
if (e.message == INVALID_SIGNATURE) {
|
|
|
|
// if sync fails with a signature error, it's likely that our
|
|
|
|
// local data has been modified in some way.
|
|
|
|
// We will attempt to fix this by retrieving the whole
|
|
|
|
// remote collection.
|
2017-02-06 12:35:26 +03:00
|
|
|
const payload = yield fetchRemoteCollection(remote, collection);
|
|
|
|
yield this.validateCollectionSignature(remote, payload, collection, {ignoreLocal: true});
|
2016-07-18 21:32:56 +03:00
|
|
|
// if the signature is good (we haven't thrown), and the remote
|
|
|
|
// last_modified is newer than the local last_modified, replace the
|
2016-06-02 11:01:26 +03:00
|
|
|
// local data
|
2016-10-17 17:20:50 +03:00
|
|
|
const localLastModified = yield collection.db.getLastModified();
|
|
|
|
if (payload.last_modified >= localLastModified) {
|
2016-07-18 21:32:56 +03:00
|
|
|
yield collection.clear();
|
|
|
|
yield collection.loadDump(payload.data);
|
|
|
|
}
|
2016-06-02 11:01:26 +03:00
|
|
|
} else {
|
|
|
|
throw e;
|
|
|
|
}
|
|
|
|
}
|
2016-04-18 12:38:25 +03:00
|
|
|
// Read local collection of records.
|
2017-01-17 17:04:43 +03:00
|
|
|
const {data} = yield collection.list();
|
2016-04-18 12:38:25 +03:00
|
|
|
|
2017-01-17 17:04:43 +03:00
|
|
|
yield this.processCallback(data);
|
2016-04-18 12:38:25 +03:00
|
|
|
|
|
|
|
// Track last update.
|
|
|
|
this.updateLastCheck(serverTime);
|
2016-02-09 21:51:08 +03:00
|
|
|
} finally {
|
2017-02-06 12:35:26 +03:00
|
|
|
yield sqliteHandle.close();
|
2016-02-09 21:51:08 +03:00
|
|
|
}
|
2016-04-18 12:38:25 +03:00
|
|
|
}).bind(this));
|
2016-02-09 21:51:08 +03:00
|
|
|
}
|
2016-04-18 12:38:25 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Save last time server was checked in users prefs.
|
|
|
|
*
|
|
|
|
* @param {Date} serverTime the current date return by server.
|
|
|
|
*/
|
|
|
|
updateLastCheck(serverTime) {
|
2017-01-17 17:04:43 +03:00
|
|
|
const checkedServerTimeInSeconds = Math.round(serverTime / 1000);
|
2016-04-18 12:38:25 +03:00
|
|
|
Services.prefs.setIntPref(this.lastCheckTimePref, checkedServerTimeInSeconds);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Revoke the appropriate certificates based on the records from the blocklist.
|
|
|
|
*
|
|
|
|
* @param {Object} records current records in the local db.
|
|
|
|
*/
|
|
|
|
function* updateCertBlocklist(records) {
|
2017-01-17 17:04:43 +03:00
|
|
|
const certList = Cc["@mozilla.org/security/certblocklist;1"]
|
|
|
|
.getService(Ci.nsICertBlocklist);
|
2016-04-18 12:38:25 +03:00
|
|
|
for (let item of records) {
|
2016-07-14 23:31:54 +03:00
|
|
|
try {
|
|
|
|
if (item.issuerName && item.serialNumber) {
|
|
|
|
certList.revokeCertByIssuerAndSerial(item.issuerName,
|
|
|
|
item.serialNumber);
|
|
|
|
} else if (item.subject && item.pubKeyHash) {
|
|
|
|
certList.revokeCertBySubjectAndPubKey(item.subject,
|
|
|
|
item.pubKeyHash);
|
|
|
|
}
|
|
|
|
} catch (e) {
|
|
|
|
// prevent errors relating to individual blocklist entries from
|
2016-12-16 19:34:42 +03:00
|
|
|
// causing sync to fail. We will accumulate telemetry on these failures in
|
|
|
|
// bug 1254099.
|
2016-07-14 23:31:54 +03:00
|
|
|
Cu.reportError(e);
|
2016-04-18 12:38:25 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
certList.saveEntries();
|
2016-02-09 21:51:08 +03:00
|
|
|
}
|
|
|
|
|
2016-12-16 19:34:42 +03:00
|
|
|
/**
|
|
|
|
* Modify the appropriate security pins based on records from the remote
|
|
|
|
* collection.
|
|
|
|
*
|
|
|
|
* @param {Object} records current records in the local db.
|
|
|
|
*/
|
|
|
|
function* updatePinningList(records) {
|
2017-01-17 17:04:43 +03:00
|
|
|
if (!Services.prefs.getBoolPref(PREF_BLOCKLIST_PINNING_ENABLED)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const appInfo = Cc["@mozilla.org/xre/app-info;1"]
|
|
|
|
.getService(Ci.nsIXULAppInfo);
|
2016-12-16 19:34:42 +03:00
|
|
|
|
2017-01-17 17:04:43 +03:00
|
|
|
const siteSecurityService = Cc["@mozilla.org/ssservice;1"]
|
|
|
|
.getService(Ci.nsISiteSecurityService);
|
2016-12-16 19:34:42 +03:00
|
|
|
|
2017-01-17 17:04:43 +03:00
|
|
|
// clear the current preload list
|
|
|
|
siteSecurityService.clearPreloads();
|
2016-12-16 19:34:42 +03:00
|
|
|
|
2017-01-17 17:04:43 +03:00
|
|
|
// write each KeyPin entry to the preload list
|
|
|
|
for (let item of records) {
|
|
|
|
try {
|
|
|
|
const {pinType, pins = [], versions} = item;
|
|
|
|
if (versions.indexOf(appInfo.version) != -1) {
|
|
|
|
if (pinType == "KeyPin" && pins.length) {
|
|
|
|
siteSecurityService.setKeyPins(item.hostName,
|
|
|
|
item.includeSubdomains,
|
|
|
|
item.expires,
|
|
|
|
pins.length,
|
|
|
|
pins, true);
|
|
|
|
}
|
|
|
|
if (pinType == "STSPin") {
|
|
|
|
siteSecurityService.setHSTSPreload(item.hostName,
|
|
|
|
item.includeSubdomains,
|
|
|
|
item.expires);
|
2016-12-16 19:34:42 +03:00
|
|
|
}
|
|
|
|
}
|
2017-01-17 17:04:43 +03:00
|
|
|
} catch (e) {
|
|
|
|
// prevent errors relating to individual preload entries from causing
|
|
|
|
// sync to fail. We will accumulate telemetry for such failures in bug
|
|
|
|
// 1254099.
|
2016-12-16 19:34:42 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-18 12:38:25 +03:00
|
|
|
/**
|
|
|
|
* Write list of records into JSON file, and notify nsBlocklistService.
|
|
|
|
*
|
|
|
|
* @param {String} filename path relative to profile dir.
|
|
|
|
* @param {Object} records current records in the local db.
|
|
|
|
*/
|
|
|
|
function* updateJSONBlocklist(filename, records) {
|
|
|
|
// Write JSON dump for synchronous load at startup.
|
|
|
|
const path = OS.Path.join(OS.Constants.Path.profileDir, filename);
|
|
|
|
const serialized = JSON.stringify({data: records}, null, 2);
|
|
|
|
try {
|
|
|
|
yield OS.File.writeAtomic(path, serialized, {tmpPath: path + ".tmp"});
|
2017-02-16 06:07:26 +03:00
|
|
|
|
2016-04-18 12:38:25 +03:00
|
|
|
// Notify change to `nsBlocklistService`
|
2017-01-10 20:09:02 +03:00
|
|
|
const eventData = {filename};
|
2016-04-18 12:38:25 +03:00
|
|
|
Services.cpmm.sendAsyncMessage("Blocklist:reload-from-disk", eventData);
|
2017-01-10 20:09:02 +03:00
|
|
|
} catch (e) {
|
2016-04-18 12:38:25 +03:00
|
|
|
Cu.reportError(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
this.OneCRLBlocklistClient = new BlocklistClient(
|
2016-05-19 13:51:13 +03:00
|
|
|
Services.prefs.getCharPref(PREF_BLOCKLIST_ONECRL_COLLECTION),
|
|
|
|
PREF_BLOCKLIST_ONECRL_CHECKED_SECONDS,
|
2016-06-02 11:01:26 +03:00
|
|
|
updateCertBlocklist,
|
2016-12-16 19:34:42 +03:00
|
|
|
Services.prefs.getCharPref(PREF_BLOCKLIST_BUCKET),
|
2016-06-02 11:01:26 +03:00
|
|
|
"onecrl.content-signature.mozilla.org"
|
2016-04-18 12:38:25 +03:00
|
|
|
);
|
|
|
|
|
|
|
|
this.AddonBlocklistClient = new BlocklistClient(
|
2016-05-19 13:51:13 +03:00
|
|
|
Services.prefs.getCharPref(PREF_BLOCKLIST_ADDONS_COLLECTION),
|
|
|
|
PREF_BLOCKLIST_ADDONS_CHECKED_SECONDS,
|
2017-02-16 06:07:26 +03:00
|
|
|
updateJSONBlocklist.bind(undefined, FILENAME_ADDONS_JSON),
|
2016-12-16 19:34:42 +03:00
|
|
|
Services.prefs.getCharPref(PREF_BLOCKLIST_BUCKET)
|
2016-04-18 12:38:25 +03:00
|
|
|
);
|
|
|
|
|
|
|
|
this.GfxBlocklistClient = new BlocklistClient(
|
2016-05-19 13:51:13 +03:00
|
|
|
Services.prefs.getCharPref(PREF_BLOCKLIST_GFX_COLLECTION),
|
|
|
|
PREF_BLOCKLIST_GFX_CHECKED_SECONDS,
|
2017-02-16 06:07:26 +03:00
|
|
|
updateJSONBlocklist.bind(undefined, FILENAME_GFX_JSON),
|
2016-12-16 19:34:42 +03:00
|
|
|
Services.prefs.getCharPref(PREF_BLOCKLIST_BUCKET)
|
2016-04-18 12:38:25 +03:00
|
|
|
);
|
|
|
|
|
|
|
|
this.PluginBlocklistClient = new BlocklistClient(
|
2016-05-19 13:51:13 +03:00
|
|
|
Services.prefs.getCharPref(PREF_BLOCKLIST_PLUGINS_COLLECTION),
|
|
|
|
PREF_BLOCKLIST_PLUGINS_CHECKED_SECONDS,
|
2017-02-16 06:07:26 +03:00
|
|
|
updateJSONBlocklist.bind(undefined, FILENAME_PLUGINS_JSON),
|
2016-12-16 19:34:42 +03:00
|
|
|
Services.prefs.getCharPref(PREF_BLOCKLIST_BUCKET)
|
|
|
|
);
|
|
|
|
|
|
|
|
this.PinningPreloadClient = new BlocklistClient(
|
|
|
|
Services.prefs.getCharPref(PREF_BLOCKLIST_PINNING_COLLECTION),
|
|
|
|
PREF_BLOCKLIST_PINNING_CHECKED_SECONDS,
|
|
|
|
updatePinningList,
|
|
|
|
Services.prefs.getCharPref(PREF_BLOCKLIST_PINNING_BUCKET),
|
|
|
|
"pinning-preload.content-signature.mozilla.org"
|
2016-04-18 12:38:25 +03:00
|
|
|
);
|