Bug 1257565 - Reload from disk when kinto blocklist was updated r=mossop
MozReview-Commit-ID: JPrDybWvbGc
--- a/toolkit/mozapps/extensions/nsBlocklistService.js
+++ b/toolkit/mozapps/extensions/nsBlocklistService.js
@@ -289,16 +289,17 @@ function Blocklist() {
gBlocklistLevel = Math.min(getPref("getIntPref", PREF_BLOCKLIST_LEVEL, DEFAULT_LEVEL),
MAX_BLOCK_LEVEL);
gPref.addObserver("extensions.blocklist.", this);
gPref.addObserver(PREF_EM_LOGGING_ENABLED, this);
this.wrappedJSObject = this;
// requests from child processes come in here, see receiveMessage.
Services.ppmm.addMessageListener("Blocklist:getPluginBlocklistState", this);
Services.ppmm.addMessageListener("Blocklist:content-blocklist-updated", this);
+ Services.ppmm.addMessageListener("Blocklist:reload-from-disk", this);
}
Blocklist.prototype = {
/**
* Extension ID -> array of Version Ranges
* Each value in the version range array is a JS Object that has the
* following properties:
* "minVersion" The minimum version in a version range (default = 0)
@@ -315,16 +316,17 @@ Blocklist.prototype = {
_addonEntries: null,
_gfxEntries: null,
_pluginEntries: null,
shutdown() {
Services.obs.removeObserver(this, "xpcom-shutdown");
Services.ppmm.removeMessageListener("Blocklist:getPluginBlocklistState", this);
Services.ppmm.removeMessageListener("Blocklist:content-blocklist-updated", this);
+ Services.ppmm.removeMessageListener("Blocklist:reload-from-disk", this);
gPref.removeObserver("extensions.blocklist.", this);
gPref.removeObserver(PREF_EM_LOGGING_ENABLED, this);
},
observe(aSubject, aTopic, aData) {
switch (aTopic) {
case "xpcom-shutdown":
this.shutdown();
@@ -360,16 +362,30 @@ Blocklist.prototype = {
// Message manager message handlers
receiveMessage(aMsg) {
switch (aMsg.name) {
case "Blocklist:getPluginBlocklistState":
return this.getPluginBlocklistState(aMsg.data.addonData,
aMsg.data.appVersion,
aMsg.data.toolkitVersion);
+ case "Blocklist:reload-from-disk":
+ // If blocklist updates are managed via Kinto, reload the new blocklist
+ // content from the recently updated files.
+ // Certificates are not concerned, their revokation is updated in
+ // OneCRLBlocklistClient from services/common/blocklist-clients.js.
+ if (!gBlocklistFromXML) {
+ const oldAddonEntries = this._addonEntries;
+ const oldPluginEntries = this._pluginEntries;
+ // Read JSON files from disk.
+ this._loadBlocklist();
+ // Update status of addons/plugins (mimic what happens in onXMLLoad()).
+ this._blocklistUpdated(oldAddonEntries, oldPluginEntries);
+ }
+ break;
case "Blocklist:content-blocklist-updated":
Services.obs.notifyObservers(null, "content-blocklist-updated");
break;
default:
throw new Error("Unknown blocklist message received from content: " + aMsg.name);
}
return undefined;
},
--- a/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_json.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_json.js
@@ -326,16 +326,77 @@ add_task(function* load_uses_preloaded_j
// Data loaded comes from preloaded content.
equal(blocklist._addonEntries[0].blockID, SAMPLE_ADDON_RECORD.blockID);
equal(blocklist._gfxEntries[0].blockID, SAMPLE_GFX_RECORD.blockID);
equal(blocklist._pluginEntries[0].blockID, SAMPLE_PLUGIN_RECORD.blockID);
});
+add_task(function* test_blocklist_is_reloaded_when_message_is_received() {
+ const blocklist = Blocklist();
+
+ blocklist._loadBlocklist();
+
+ // Write a fake JSON file in profile dir.
+ copyToProfile(SAMPLE_FILE, "addons");
+
+ // Send message.
+ yield Services.cpmm.sendAsyncMessage("Blocklist:reload-from-disk");
+
+ // Since message is loaded asynchronously, wait for its reception.
+ yield new Promise((resolve) => {
+ Services.obs.addObserver(function() {
+ Services.obs.removeObserver(arguments.callee, "blocklist-updated");
+ resolve();
+ }, "blocklist-updated");
+ });
+
+ // Blocklist was reloaded with the content from file.
+ equal(blocklist._addonEntries[0].blockID, "i53923");
+});
+
+
+add_task(function* test_message_is_sent_when_blocklist_is_refreshed() {
+ Services.prefs.setCharPref("services.settings.server",
+ `http://localhost:${gPort}/v1`);
+ Services.prefs.setBoolPref("services.blocklist.signing.enforced", false);
+
+ testserver.registerPathHandler("/v1/", (request, response) => response.write(`{}`));
+ testserver.registerPathHandler("/v1/buckets/monitor/collections/changes/records", (request, response) => {
+ response.write(`{"data": [{"bucket": "blocklists", "collection": "addons"}]}`);
+ });
+ testserver.registerPathHandler("/v1/buckets/blocklists/collections/addons", (request, response) => {
+ response.write(`{"data": {}}`);
+ });
+ testserver.registerPathHandler("/v1/buckets/blocklists/collections/addons/records", (request, response) => {
+ response.write(`{"data": [${JSON.stringify(SAMPLE_ADDON_RECORD)}]}`);
+ });
+
+ const blocklist = Blocklist();
+
+ const filename = yield new Promise((resolve) => {
+ const event = "Blocklist:reload-from-disk";
+ const observer = {
+ receiveMessage(aMsg) {
+ if (aMsg.name == event) {
+ Services.ppmm.removeMessageListener(event, this);
+ resolve(aMsg.data.filename);
+ }
+ }
+ };
+ Services.ppmm.addMessageListener(event, observer);
+
+ blocklist.notify(null);
+ });
+
+ ok(/addons.json/.test(filename));
+});
+
+
add_task(function* test_read_json_from_app_or_profile() {
const blocklist = Blocklist();
// Reads from app dir by default.
clearProfile("addons");
blocklist._loadBlocklist();
ok(blocklist._addonEntries.length >= 416);