WIP move away from manually mocking nsIPluginTag in tests
MozReview-Commit-ID: 9yaIBwlU89v
--- a/dom/plugins/base/nsPluginHost.cpp
+++ b/dom/plugins/base/nsPluginHost.cpp
@@ -256,34 +256,43 @@ class BlocklistPromiseHandler final : pu
{
public:
NS_DECL_ISUPPORTS
BlocklistPromiseHandler(nsPluginTag *aTag, const bool aShouldSoftblock)
: mTag(aTag)
, mShouldDisableWhenSoftblocked(aShouldSoftblock)
{
+ MOZ_ASSERT(mTag, "Should always be passed a plugin tag");
sPendingBlocklistStateRequests++;
}
void
MaybeWriteBlocklistChanges()
{
- // If this is the only remaining pending request, check if we need to write
- // state and update the child processes.
- if (sPendingBlocklistStateRequests == 1 &&
+ // We're called immediately when the promise resolves/rejects, and (as a backup)
+ // when the handler is destroyed. To ensure we only run once, we use mTag as a
+ // sentinel, setting it to nullptr when we run.
+ if (!mTag) {
+ return;
+ }
+ mTag = nullptr;
+ sPendingBlocklistStateRequests--;
+ // If this was the only remaining pending request, check if we need to write
+ // state and if so update the child processes.
+ if (!sPendingBlocklistStateRequests &&
sPluginBlocklistStatesChangedSinceLastWrite) {
+ sPluginBlocklistStatesChangedSinceLastWrite = false;
+
RefPtr<nsPluginHost> host = nsPluginHost::GetInst();
- sPluginBlocklistStatesChangedSinceLastWrite = false;
// Write the changed list to disk:
host->WritePluginInfo();
- // We update blocklists asynchronously by just sending a new plugin list to
- // content.
- // We'll need to repack our tags and send them to content again.
+ // We update blocklist info in content processes asynchronously
+ // by just sending a new plugin list to content.
host->IncrementChromeEpoch();
host->SendPluginsToContent();
}
}
void
ResolvedCallback(JSContext *aCx, JS::Handle<JS::Value> aValue) override
{
@@ -313,18 +322,19 @@ class BlocklistPromiseHandler final : pu
RejectedCallback(JSContext *aCx, JS::Handle<JS::Value> aValue) override
{
MOZ_ASSERT(false, "Shouldn't reject plugin blocklist state request");
MaybeWriteBlocklistChanges();
}
private:
~BlocklistPromiseHandler() {
- // A request just resolved. Decrement counter of pending requests.
- sPendingBlocklistStateRequests--;
+ // If we have multiple plugins and the last pending request is GC'd
+ // and so never resolves/rejects, ensure we still write the blocklist.
+ MaybeWriteBlocklistChanges();
}
RefPtr<nsPluginTag> mTag;
bool mShouldDisableWhenSoftblocked;
// Whether we changed any of the plugins' blocklist states since
// we last started fetching them (async). This is reset to false
// every time we finish fetching plugin blocklist information.
@@ -2230,16 +2240,17 @@ nsresult nsPluginHost::ScanPluginsDirect
return NS_OK;
}
void
nsPluginHost::UpdatePluginBlocklistState(nsPluginTag* aPluginTag, bool aShouldSoftblock)
{
nsCOMPtr<nsIBlocklistService> blocklist =
do_GetService("@mozilla.org/extensions/blocklist;1");
+ MOZ_ASSERT(blocklist, "Should be able to access the blocklist");
if (!blocklist) {
return;
}
// Asynchronously get the blocklist state.
nsCOMPtr<nsISupports> result;
blocklist->GetPluginBlocklistState(aPluginTag, EmptyString(),
EmptyString(), getter_AddRefs(result));
RefPtr<Promise> promise = do_QueryObject(result);
--- a/toolkit/mozapps/extensions/nsBlocklistService.js
+++ b/toolkit/mozapps/extensions/nsBlocklistService.js
@@ -855,18 +855,19 @@ Blocklist.prototype = {
}
if (!this._preloadPromise) {
this._preloadPromise = this._loadBlocklistAsyncInternal();
}
await this._preloadPromise;
},
async _loadBlocklistAsyncInternal() {
- let profPath = OS.Path.join(OS.Constants.Path.profileDir, FILE_BLOCKLIST);
try {
+ // Get the path inside the try...catch because there's no profileDir in e.g. xpcshell tests.
+ let profPath = OS.Path.join(OS.Constants.Path.profileDir, FILE_BLOCKLIST);
await this._preloadBlocklistFile(profPath);
return;
} catch (e) {
LOG("Blocklist::loadBlocklistAsync: Failed to load XML file " + e);
}
var appFile = FileUtils.getFile(KEY_APPDIR, [FILE_BLOCKLIST]);
try {
--- a/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_plugin_outdated.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_plugin_outdated.js
@@ -12,44 +12,34 @@ const nsIBLS = Ci.nsIBlocklistService;
var gBlocklist = null;
var gTestserver = AddonTestUtils.createHttpServer({hosts: ["example.com"]});
gTestserver.registerDirectory("/data/", do_get_file("data"));
var PLUGINS = [{
// Tests a plugin whose state goes from not-blocked, to outdated
name: "test_bug514327_outdated",
+ handlerURI: "chrome://testing/content/test_bug514327_outdated.html",
+ mimeEntries: [{type: "application/x-shockwave-flash"}],
version: "5",
- disabled: false,
- blocklisted: false
}, {
// Used to trigger the blocklist dialog, which indicates the blocklist has updated
name: "test_bug514327_1",
+ handlerURI: "chrome://testing/content/test_bug514327_1.html",
+ mimeEntries: [{type: "application/x-shockwave-flash"}],
version: "5",
- disabled: false,
- blocklisted: false
}, {
// Used to trigger the blocklist dialog, which indicates the blocklist has updated
name: "test_bug514327_2",
+ handlerURI: "chrome://testing/content/test_bug514327_2.html",
+ mimeEntries: [{type: "application/x-shockwave-flash"}],
version: "5",
- disabled: false,
- blocklisted: false
} ];
-// A fake plugin host for the blocklist service to use
-var PluginHost = {
- getPluginTags(countRef) {
- countRef.value = PLUGINS.length;
- return PLUGINS;
- },
-
- QueryInterface: XPCOMUtils.generateQI(["nsIPluginHost"]),
-};
-
var BlocklistPrompt = {
get wrappedJSObject() { return this; },
prompt(list) {
// Should only include one item
Assert.equal(list.length, 1);
// And that item should be the blocked plugin, not the outdated one
var item = list[0];
@@ -66,25 +56,34 @@ async function loadBlocklist(file) {
Services.prefs.setCharPref("extensions.blocklist.url",
"http://example.com/data/" + file);
Services.blocklist.QueryInterface(Ci.nsITimerCallback).notify(null);
await blocklistUpdated;
}
-MockRegistrar.register("@mozilla.org/plugin/host;1", PluginHost);
-
let factory = XPCOMUtils.generateSingletonFactory(function() { return BlocklistPrompt; });
Cm.registerFactory(Components.ID("{26d32654-30c7-485d-b983-b4d2568aebba}"),
"Blocklist Prompt",
"@mozilla.org/addons/blocklist-prompt;1", factory);
add_task(async function setup() {
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9");
+ let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
+ for (let p of PLUGINS) {
+ p.niceName = p.name;
+ let plugin = pluginHost.registerFakePlugin(p);
+ plugin.enabledState = Ci.nsIPluginTag.STATE_ENABLED;
+ }
+ registerCleanupFunction(() => {
+ for (let p of PLUGINS) {
+ pluginHost.unregisterFakePlugin(p.handlerURI);
+ }
+ });
// initialize the blocklist with no entries
copyBlocklistToProfile(do_get_file("data/test_bug514327_3_empty.xml"));
await promiseStartupManager();
gBlocklist = Services.blocklist;