--- a/toolkit/mozapps/extensions/Blocklist.jsm
+++ b/toolkit/mozapps/extensions/Blocklist.jsm
@@ -727,17 +727,17 @@ var Blocklist = {
if (!this.isLoaded) {
await this.loadBlocklistAsync();
}
var oldAddonEntries = this._addonEntries;
var oldPluginEntries = this._pluginEntries;
- this._loadBlocklistFromXML(responseXML);
+ await this._loadBlocklistFromXML(responseXML);
// We don't inform the users when the graphics blocklist changed at runtime.
// However addons and plugins blocking status is refreshed.
this._blocklistUpdated(oldAddonEntries, oldPluginEntries);
try {
let path = OS.Path.join(OS.Constants.Path.profileDir, FILE_BLOCKLIST);
await OS.File.writeAtomic(path, request.responseText, {tmpPath: path + ".tmp"});
} catch (e) {
@@ -773,77 +773,77 @@ var Blocklist = {
return this._addonEntries != null && this._gfxEntries != null && this._pluginEntries != null;
},
/* Used for testing */
_clear() {
this._addonEntries = null;
this._gfxEntries = null;
this._pluginEntries = null;
- delete this._preloadPromise;
+ delete this._loadPromise;
},
/**
* Trigger loading the blocklist content asynchronously.
*/
async loadBlocklistAsync() {
if (this.isLoaded) {
return;
}
- if (!this._preloadPromise) {
- this._preloadPromise = this._loadBlocklistAsyncInternal();
+ if (!this._loadPromise) {
+ this._loadPromise = this._loadBlocklistAsyncInternal();
}
- await this._preloadPromise;
+ await this._loadPromise;
},
async _loadBlocklistAsyncInternal() {
try {
// Get the path inside the try...catch because there's no profileDir in e.g. xpcshell tests.
let profFile = FileUtils.getFile(KEY_PROFILEDIR, [FILE_BLOCKLIST]);
- await this._preloadBlocklistFile(profFile);
+ await this._loadFileInternal(profFile);
return;
} catch (e) {
LOG("Blocklist::loadBlocklistAsync: Failed to load XML file " + e);
}
var appFile = FileUtils.getFile(KEY_APPDIR, [FILE_BLOCKLIST]);
try {
- await this._preloadBlocklistFile(appFile);
+ await this._loadFileInternal(appFile);
return;
} catch (e) {
LOG("Blocklist::loadBlocklistAsync: Failed to load XML file " + e);
}
LOG("Blocklist::loadBlocklistAsync: no XML File found");
// Neither file is present, so we just add empty lists, to avoid JS errors fetching
// blocklist information otherwise.
this._addonEntries = [];
this._gfxEntries = [];
this._pluginEntries = [];
},
- async _preloadBlocklistFile(file) {
+ async _loadFileInternal(file) {
if (this.isLoaded) {
return;
}
if (!gBlocklistEnabled) {
- LOG("Blocklist::_preloadBlocklistFile: blocklist is disabled");
+ LOG("Blocklist::_loadFileInternal: blocklist is disabled");
return;
}
let xmlDoc = await new Promise((resolve, reject) => {
let request = new XMLHttpRequest();
request.open("GET", Services.io.newFileURI(file).spec, true);
request.overrideMimeType("text/xml");
request.addEventListener("error", reject);
request.addEventListener("load", function() {
let {status} = request;
if (status != 200 && status != 0) {
- LOG("_preloadBlocklistFile: there was an error during load, got status: " + status);
+ LOG("_loadFileInternal: there was an error during load, got status: " + status);
reject(new Error("Couldn't load blocklist file"));
return;
}
let doc = request.responseXML;
if (doc.documentElement.namespaceURI != XMLURI_BLOCKLIST) {
LOG("Blocklist::_loadBlocklistFromString: aborting due to incorrect " +
"XML Namespace.\nExpected: " + XMLURI_BLOCKLIST + "\n" +
"Received: " + doc.documentElement.namespaceURI);
@@ -851,45 +851,45 @@ var Blocklist = {
return;
}
resolve(doc);
});
request.send(null);
});
await new Promise(resolve => {
- ChromeUtils.idleDispatch(() => {
+ ChromeUtils.idleDispatch(async () => {
if (!this.isLoaded) {
- this._loadBlocklistFromXML(xmlDoc);
+ await this._loadBlocklistFromXML(xmlDoc);
}
resolve();
});
});
},
- _loadBlocklistFromXML(doc) {
+ async _loadBlocklistFromXML(doc) {
this._addonEntries = [];
this._gfxEntries = [];
this._pluginEntries = [];
try {
var children = doc.documentElement.children;
for (let element of children) {
switch (element.localName) {
case "emItems":
- this._addonEntries = this._processItemNodes(element.children, "emItem",
- this._handleEmItemNode);
+ this._addonEntries = await this._processItemNodes(element.children, "emItem",
+ this._handleEmItemNode);
break;
case "pluginItems":
- this._pluginEntries = this._processItemNodes(element.children, "pluginItem",
- this._handlePluginItemNode);
+ this._pluginEntries = await this._processItemNodes(element.children, "pluginItem",
+ this._handlePluginItemNode);
break;
case "gfxItems":
// Parse as simple list of objects.
- this._gfxEntries = this._processItemNodes(element.children, "gfxBlacklistEntry",
- this._handleGfxBlacklistNode);
+ this._gfxEntries = await this._processItemNodes(element.children, "gfxBlacklistEntry",
+ this._handleGfxBlacklistNode);
break;
default:
LOG("Blocklist::_loadBlocklistFromXML: ignored entries " + element.localName);
}
}
if (this._gfxEntries.length > 0) {
this._notifyObserversBlocklistGFX();
}
@@ -899,22 +899,26 @@ var Blocklist = {
// Dispatch to mainthread because consumers may try to construct nsIPluginHost
// again based on this notification, while we were called from nsIPluginHost
// anyway, leading to re-entrancy.
Services.tm.dispatchToMainThread(function() {
Services.obs.notifyObservers(null, "blocklist-loaded");
});
},
- _processItemNodes(items, itemName, handler) {
+ async _processItemNodes(items, itemName, handler) {
var result = [];
+ let deadline = await new Promise(ChromeUtils.idleDispatch);
for (let item of items) {
if (item.localName == itemName) {
handler(item, result);
}
+ if (!deadline || deadline.didTimeout || deadline.timeRemaining() < 1) {
+ deadline = await new Promise(ChromeUtils.idleDispatch);
+ }
}
return result;
},
_handleEmItemNode(blocklistElement, result) {
if (!matchesOSABI(blocklistElement))
return;