Backed out 3 changesets (bug 1176019) for Browser-chrome failures on dom/plugins/test/mochitest/browser_tabswitchbetweenplugins.js. CLOSED TREE
authorDorel Luca <dluca@mozilla.com>
Fri, 11 May 2018 02:03:20 +0300
changeset 417820 4e08519eb8f0726820d67ac458d289d9dc503006
parent 417819 c43f79a262bf06e55963bf149681409a57c942d3
child 417821 33ae17f18193912b12e7a890175a4d8749d75d9a
push id33980
push userebalazs@mozilla.com
push dateFri, 11 May 2018 09:35:12 +0000
treeherdermozilla-central@8e9a4a323f0c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1176019
milestone62.0a1
backs out31b295f557db579744feb07900a5aa5e145452b0
6c591b484a11318e704bdc9ea0b9b24d51a6ffa3
3e7dbe6b5122796a60ba3073a4f6b5604ac76116
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 3 changesets (bug 1176019) for Browser-chrome failures on dom/plugins/test/mochitest/browser_tabswitchbetweenplugins.js. CLOSED TREE Backed out changeset 31b295f557db (bug 1176019) Backed out changeset 6c591b484a11 (bug 1176019) Backed out changeset 3e7dbe6b5122 (bug 1176019)
browser/app/profile/firefox.js
browser/base/content/docs/tabbrowser/async-tab-switcher.rst
browser/base/content/tabbrowser.js
browser/modules/AsyncTabSwitcher.jsm
dom/plugins/test/mochitest/browser_bug1196539.js
dom/plugins/test/mochitest/browser_tabswitchbetweenplugins.js
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1535,24 +1535,16 @@ pref("browser.tabs.remote.desktopbehavio
 // until bug 1453080 is fixed.
 //
 #if !defined(XP_MACOSX) || defined(NIGHTLY_BUILD)
 pref("browser.tabs.remote.warmup.enabled", true);
 #else
 pref("browser.tabs.remote.warmup.enabled", false);
 #endif
 
-// Caches tab layers to improve perceived performance
-// of tab switches.
-#if defined(NIGHTLY_BUILD)
-pref("browser.tabs.remote.tabCacheSize", 5);
-#else
-pref("browser.tabs.remote.tabCacheSize", 0);
-#endif
-
 pref("browser.tabs.remote.warmup.maxTabs", 3);
 pref("browser.tabs.remote.warmup.unloadDelayMs", 2000);
 
 // For the about:tabcrashed page
 pref("browser.tabs.crashReporting.sendReport", true);
 pref("browser.tabs.crashReporting.includeURL", false);
 pref("browser.tabs.crashReporting.requestEmail", false);
 pref("browser.tabs.crashReporting.emailMe", false);
--- a/browser/base/content/docs/tabbrowser/async-tab-switcher.rst
+++ b/browser/base/content/docs/tabbrowser/async-tab-switcher.rst
@@ -190,22 +190,16 @@ We use a few tricks and optimizations to
 1. Sometimes users switch between the same tabs quickly. We want to optimize for this case by not releasing the layers for tabs until some time has gone by. That way, quick switching just resolves in a re-composite in the compositor, as opposed to a full re-paint and re-upload of the layers from a remote tab’s content process.
 
 2. When a tab hasn’t ever been seen before, and is still in the process of loading (right now, dubiously checked by looking for the “busy” attribute on the ``<xul:tab>``) we show a blank content area until its layers are finally ready. The idea here is to shift perceived lag from the async tab switcher to the network by showing the blank space instead of the tab switch spinner.
 
 3. “Warming” is a nascent optimization that will allow us to pre-emptively render and cache the layers for tabs that we think the user is likely to switch to soon. After a timeout (``browser.tabs.remote.warmup.unloadDelayMs``), “warmed” tabs that aren’t switched to have their layers unloaded and cleared from the cache.
 
 4. On platforms that support ``occlusionstatechange`` events (as of this writing, only macOS) and ``sizemodechange`` events (Windows, macOS and Linux), we stop rendering the layers for the currently selected tab when the window is minimized or fully occluded by another window.
 
-5. Based on the browser.tabs.remote.tabCacheSize pref, we keep recently used tabs'
-layers around to speed up tab switches by avoiding the round trip to the content
-process. This uses a simple array (``_tabLayerCache``) inside tabbrowser.js, which
-we examine when determining if we want to unload a tab's layers or not. This is still
-experimental as of Nightly 62.
-
 .. _async-tab-switcher.warming:
 
 Warming
 =======
 
 Tab warming allows the browser to proactively render and upload layers to the compositor for tabs that the user is likely to switch to. The simplest example is when a user's mouse cursor is hovering over a tab. When this occurs, the async tab switcher is told to put that tab into a warming list, and to set its state to ``STATE_LOADING``, even though the user hasn't yet clicked on it.
 
 Warming a tab queues up a timer to unload background tabs (if no such timer already exists), which will clear out the warmed tab if the user doesn't eventually click on it. The unload will occur even if the user continues to hover the tab.
--- a/browser/base/content/tabbrowser.js
+++ b/browser/base/content/tabbrowser.js
@@ -92,18 +92,16 @@ window._gBrowser = {
   _autoScrollPopup: null,
 
   _previewMode: false,
 
   _lastFindValue: "",
 
   _contentWaitingCount: 0,
 
-  _tabLayerCache: [],
-
   tabAnimationsInProgress: 0,
 
   _XUL_NS: "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
 
   /**
    * Binding from browser to tab
    */
   _tabForBrowser: new WeakMap(),
@@ -2753,23 +2751,16 @@ window._gBrowser = {
       // If we were closed during onbeforeunload, we return false now
       // so we don't (try to) close the same tab again. Of course, we
       // also stop if the unload was cancelled by the user:
       if (aTab.closing || (!timedOut && !permitUnload)) {
         return false;
       }
     }
 
-    // this._switcher would normally cover removing a tab from this
-    // cache, but we may not have one at this time.
-    let tabCacheIndex = this._tabLayerCache.indexOf(aTab);
-    if (tabCacheIndex != -1) {
-      this._tabLayerCache.splice(tabCacheIndex, 1);
-    }
-
     this._blurTab(aTab);
 
     var closeWindow = false;
     var newTab = false;
     if (this.tabs.length - this._removingTabs.length == 1) {
       closeWindow = aCloseWindowWithLastTab != null ? aCloseWindowWithLastTab :
         !window.toolbar.visible ||
         Services.prefs.getBoolPref("browser.tabs.closeWindowWithLastTab");
--- a/browser/modules/AsyncTabSwitcher.jsm
+++ b/browser/modules/AsyncTabSwitcher.jsm
@@ -15,18 +15,16 @@ XPCOMUtils.defineLazyModuleGetters(this,
 });
 
 XPCOMUtils.defineLazyPreferenceGetter(this, "gTabWarmingEnabled",
   "browser.tabs.remote.warmup.enabled");
 XPCOMUtils.defineLazyPreferenceGetter(this, "gTabWarmingMax",
   "browser.tabs.remote.warmup.maxTabs");
 XPCOMUtils.defineLazyPreferenceGetter(this, "gTabWarmingUnloadDelayMs",
   "browser.tabs.remote.warmup.unloadDelayMs");
-XPCOMUtils.defineLazyPreferenceGetter(this, "gTabCacheSize",
-  "browser.tabs.remote.tabCacheSize");
 
 /**
  * The tab switcher is responsible for asynchronously switching
  * tabs in e10s. It waits until the new tab is ready (i.e., the
  * layer tree is available) before switching to it. Then it
  * unloads the layer tree for the old tab.
  *
  * The tab switcher is a state machine. For each tab, it
@@ -288,20 +286,16 @@ class AsyncTabSwitcher {
     }
   }
 
   get minimizedOrFullyOccluded() {
     return this.window.windowState == this.window.STATE_MINIMIZED ||
            this.window.isFullyOccluded;
   }
 
-  get tabLayerCache() {
-    return this.tabbrowser._tabLayerCache;
-  }
-
   finish() {
     this.log("FINISH");
 
     this.assert(this.tabbrowser._switcher);
     this.assert(this.tabbrowser._switcher === this);
     this.assert(!this.spinnerTab);
     this.assert(!this.blankTab);
     this.assert(!this.loadTimer);
@@ -509,25 +503,16 @@ class AsyncTabSwitcher {
   }
 
   // This function runs before every event. It fixes up the state
   // to account for closed tabs.
   preActions() {
     this.assert(this.tabbrowser._switcher);
     this.assert(this.tabbrowser._switcher === this);
 
-    for (let i = 0; i < this.tabLayerCache.length; i++) {
-      let tab = this.tabLayerCache[i];
-      if (!tab.linkedBrowser) {
-        this.tabState.delete(tab);
-        this.tabLayerCache.splice(i, 1);
-        i--;
-      }
-    }
-
     for (let [tab, ] of this.tabState) {
       if (!tab.linkedBrowser) {
         this.tabState.delete(tab);
         this.unwarmTab(tab);
       }
     }
 
     if (this.lastVisibleTab && !this.lastVisibleTab.linkedBrowser) {
@@ -576,35 +561,26 @@ class AsyncTabSwitcher {
     if (!this.loadTimer && !this.minimizedOrFullyOccluded &&
         (stateOfRequestedTab == this.STATE_UNLOADED ||
         stateOfRequestedTab == this.STATE_UNLOADING ||
         this.warmingTabs.has(this.requestedTab))) {
       this.assert(stateOfRequestedTab != this.STATE_LOADED);
       this.loadRequestedTab();
     }
 
-    let numBackgroundCached = 0;
-    for (let tab of this.tabLayerCache) {
-      if (tab !== this.requestedTab) {
-        numBackgroundCached++;
-      }
-    }
-
     // See how many tabs still have work to do.
     let numPending = 0;
     let numWarming = 0;
     for (let [tab, state] of this.tabState) {
       // Skip print preview browsers since they shouldn't affect tab switching.
       if (this.tabbrowser._printPreviewBrowsers.has(tab.linkedBrowser)) {
         continue;
       }
 
-      if (state == this.STATE_LOADED &&
-          tab !== this.requestedTab &&
-          !this.tabLayerCache.includes(tab)) {
+      if (state == this.STATE_LOADED && tab !== this.requestedTab) {
         numPending++;
 
         if (tab !== this.visibleTab) {
           numWarming++;
         }
       }
       if (state == this.STATE_LOADING || state == this.STATE_UNLOADING) {
         numPending++;
@@ -617,20 +593,18 @@ class AsyncTabSwitcher {
     // handlers, which might cause finish() to already have been called.
     // Check for that before calling finish() again.
     if (!this.tabbrowser._switcher) {
       return;
     }
 
     this.maybeFinishTabSwitch();
 
-    if (numWarming > gTabWarmingMax || numBackgroundCached > 0) {
-      if (numWarming > gTabWarmingMax) {
-        this.logState("Hit tabWarmingMax");
-      }
+    if (numWarming > gTabWarmingMax) {
+      this.logState("Hit tabWarmingMax");
       if (this.unloadTimer) {
         this.clearTimer(this.unloadTimer);
       }
       this.unloadNonRequiredTabs();
     }
 
     if (numPending == 0) {
       this.finish();
@@ -653,44 +627,31 @@ class AsyncTabSwitcher {
   // If there are any non-visible and non-requested tabs in
   // STATE_LOADED, sets them to STATE_UNLOADING. Also queues
   // up the unloadTimer to run onUnloadTimeout if there are still
   // tabs in the process of unloading.
   unloadNonRequiredTabs() {
     this.warmingTabs = new WeakSet();
     let numPending = 0;
 
-    for (let tab of this.tabLayerCache) {
-      if (tab !== this.requestedTab) {
-        let browser = tab.linkedBrowser;
-        browser.preserveLayers(true);
-        browser.docShellIsActive = false;
-      }
-    }
-
     // Unload any tabs that can be unloaded.
     for (let [tab, state] of this.tabState) {
       if (this.tabbrowser._printPreviewBrowsers.has(tab.linkedBrowser)) {
         continue;
       }
 
-      let isInLayerCache = this.tabLayerCache.includes(tab);
-
       if (state == this.STATE_LOADED &&
           !this.maybeVisibleTabs.has(tab) &&
           tab !== this.lastVisibleTab &&
           tab !== this.loadingTab &&
-          tab !== this.requestedTab &&
-          !isInLayerCache) {
+          tab !== this.requestedTab) {
         this.setTabState(tab, this.STATE_UNLOADING);
       }
 
-      if (state != this.STATE_UNLOADED &&
-          tab !== this.requestedTab &&
-          !isInLayerCache) {
+      if (state != this.STATE_UNLOADED && tab !== this.requestedTab) {
         numPending++;
       }
     }
 
     if (numPending) {
       // Keep the timer going since there may be more tabs to unload.
       this.unloadTimer = this.setTimer(() => this.onUnloadTimeout(), this.UNLOAD_DELAY);
     }
@@ -904,59 +865,27 @@ class AsyncTabSwitcher {
 
     this.logState("warmupTab " + this.tinfo(tab));
 
     this.warmingTabs.add(tab);
     this.setTabState(tab, this.STATE_LOADING);
     this.queueUnload(gTabWarmingUnloadDelayMs);
   }
 
-  cleanUpTabAfterEviction(tab) {
-    this.assert(tab !== this.requestedTab);
-    let browser = tab.linkedBrowser;
-    if (browser) {
-      browser.preserveLayers(false);
-    }
-    this.setTabState(tab, this.STATE_UNLOADING);
-  }
-
-  evictOldestTabFromCache() {
-    let tab = this.tabLayerCache.shift();
-    this.cleanUpTabAfterEviction(tab);
-  }
-
-  maybePromoteTabInLayerCache(tab) {
-    if (gTabCacheSize > 1 &&
-        tab.linkedBrowser.isRemoteBrowser &&
-        tab.linkedBrowser.currentURI.spec != "about:blank") {
-      let tabIndex = this.tabLayerCache.indexOf(tab);
-
-      if (tabIndex != -1) {
-        this.tabLayerCache.splice(tabIndex, 1);
-      }
-
-      this.tabLayerCache.push(tab);
-
-      if (this.tabLayerCache.length > gTabCacheSize) {
-        this.evictOldestTabFromCache();
-      }
-    }
-  }
-
   // Called when the user asks to switch to a given tab.
   requestTab(tab) {
     if (tab === this.requestedTab) {
       return;
     }
 
-    let tabState = this.getTabState(tab);
     if (gTabWarmingEnabled) {
       let warmingState = "disqualified";
 
       if (this.canWarmTab(tab)) {
+        let tabState = this.getTabState(tab);
         if (tabState == this.STATE_LOADING) {
           warmingState = "stillLoading";
         } else if (tabState == this.STATE_LOADED) {
           warmingState = "loaded";
         } else if (tabState == this.STATE_UNLOADING ||
                    tabState == this.STATE_UNLOADED) {
           // At this point, if the tab's browser was being inserted
           // lazily, we never had a chance to warm it up, and unfortunately
@@ -972,19 +901,16 @@ class AsyncTabSwitcher {
         .add(warmingState);
     }
 
     this._requestingTab = true;
     this.logState("requestTab " + this.tinfo(tab));
     this.startTabSwitch();
 
     this.requestedTab = tab;
-    if (tabState == this.STATE_LOADED) {
-      this.maybeVisibleTabs.clear();
-    }
 
     tab.linkedBrowser.setAttribute("primary", "true");
     if (this.lastPrimaryTab && this.lastPrimaryTab != tab) {
       this.lastPrimaryTab.linkedBrowser.removeAttribute("primary");
     }
     this.lastPrimaryTab = tab;
 
     this.queueUnload(this.UNLOAD_DELAY);
@@ -1061,20 +987,16 @@ class AsyncTabSwitcher {
    * the tab switch (layers are ready, paints are done, spinners
    * are hidden). This checks to make sure all conditions are
    * satisfied, and then records the tab switch as finished.
    */
   maybeFinishTabSwitch() {
     if (this.switchInProgress && this.requestedTab &&
         (this.getTabState(this.requestedTab) == this.STATE_LOADED ||
           this.requestedTab === this.blankTab)) {
-      if (this.requestedTab !== this.blankTab) {
-        this.maybePromoteTabInLayerCache(this.requestedTab);
-      }
-
       // After this point the tab has switched from the content thread's point of view.
       // The changes will be visible after the next refresh driver tick + composite.
       let time = TelemetryStopwatch.timeElapsed("FX_TAB_SWITCH_TOTAL_E10S_MS", this.window);
       if (time != -1) {
         TelemetryStopwatch.finish("FX_TAB_SWITCH_TOTAL_E10S_MS", this.window);
         this.log("DEBUG: tab switch time = " + time);
         this.addMarker("AsyncTabSwitch:Finish");
       }
@@ -1151,47 +1073,29 @@ class AsyncTabSwitcher {
     if (!this.logging())
       return;
 
     let accum = prefix + " ";
     for (let i = 0; i < this.tabbrowser.tabs.length; i++) {
       let tab = this.tabbrowser.tabs[i];
       let state = this.getTabState(tab);
       let isWarming = this.warmingTabs.has(tab);
-      let isCached = this.tabLayerCache.includes(tab);
-      let isClosing = tab.closing;
-      let linkedBrowser = tab.linkedBrowser;
-      let isActive = linkedBrowser && linkedBrowser.docShellIsActive;
-      let isRendered = linkedBrowser && linkedBrowser.renderLayers;
 
       accum += i + ":";
       if (tab === this.lastVisibleTab) accum += "V";
       if (tab === this.loadingTab) accum += "L";
       if (tab === this.requestedTab) accum += "R";
       if (tab === this.blankTab) accum += "B";
-
-      let extraStates = "";
-      if (isWarming) extraStates += "W";
-      if (isCached) extraStates += "C";
-      if (isClosing) extraStates += "X";
-      if (isActive) extraStates += "A";
-      if (isRendered) extraStates += "R";
-      if (extraStates != "") {
-        accum += `(${extraStates})`;
-      }
-
+      if (isWarming) accum += "(W)";
       if (state == this.STATE_LOADED) accum += "(+)";
       if (state == this.STATE_LOADING) accum += "(+?)";
       if (state == this.STATE_UNLOADED) accum += "(-)";
       if (state == this.STATE_UNLOADING) accum += "(-?)";
       accum += " ";
     }
-
-    accum += "cached: " + this.tabLayerCache.length;
-
     if (this._useDumpForLogging) {
       dump(accum + "\n");
     } else {
       Services.console.logStringMessage(accum);
     }
   }
 }
 
--- a/dom/plugins/test/mochitest/browser_bug1196539.js
+++ b/dom/plugins/test/mochitest/browser_bug1196539.js
@@ -9,20 +9,16 @@ function checkPaintCount(aCount) {
 // animate so this should really be just 1, but operating systems can
 // occasionally fire a few of these so we give these tests a fudge factor.
 // A bad regression would either be 0, or 100+.
 const kMaxPaints = 10;
 
 add_task(async function() {
   let result, tabSwitchedPromise;
 
-  // We want to make sure that we will paint in cases where we need to. The
-  // tab layer cache just gets in the way of measuring that.
-  await SpecialPowers.pushPrefEnv({set: [["browser.tabs.remote.tabCacheSize", 0]]});
-
   setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in");
 
   let testTab = gBrowser.selectedTab;
   let pluginTab = await BrowserTestUtils.openNewForegroundTab(gBrowser, gTestRoot + "plugin_test.html");
   let homeTab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:home");
 
   result = await ContentTask.spawn(pluginTab.linkedBrowser, null, async function() {
     let doc = content.document;
--- a/dom/plugins/test/mochitest/browser_tabswitchbetweenplugins.js
+++ b/dom/plugins/test/mochitest/browser_tabswitchbetweenplugins.js
@@ -1,36 +1,10 @@
 var gTestRoot = getRootDirectory(gTestPath).replace("chrome://mochitests/content/", "http://127.0.0.1:8888/");
 
-function waitForPluginVisibility(browser, shouldBeVisible, errorMessage) {
-  return new Promise((resolve, reject) => {
-    let visibilityCheckCount = 0;
-    let listener = async () => {
-      let visibility = await ContentTask.spawn(browser, null, async function() {
-        let doc = content.document;
-        let plugin = doc.getElementById("testplugin");
-        return XPCNativeWrapper.unwrap(plugin).nativeWidgetIsVisible();
-      });
-
-      if (visibility == shouldBeVisible) {
-        window.removeEventListener("MozAfterPaint", listener);
-        resolve();
-      } else if (++visibilityCheckCount > 1) {
-        // We want to allow for one failed check since we call listener
-        // directly, but if we get a MozAfterPaint notification and we
-        // still don't have the correct visibility, that's likely a
-        // problem.
-        reject();
-      }
-    };
-    window.addEventListener("MozAfterPaint", listener);
-    listener();
-  });
-}
-
 // tests that we get plugin updates when we flip between tabs that
 // have the same plugin in the same position in the page.
 
 add_task(async function() {
   let result, tabSwitchedPromise;
 
   setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in");
 
@@ -50,50 +24,82 @@ add_task(async function() {
     let plugin = doc.getElementById("testplugin");
     return !!plugin;
   });
   is(result, true, "plugin2 is loaded");
 
   // plugin tab 2 should be selected
   is(gBrowser.selectedTab == pluginTab2, true, "plugin2 is selected");
 
-  await waitForPluginVisibility(pluginTab1.linkedBrowser,
-                                false, "plugin1 should be hidden");
+  result = await ContentTask.spawn(pluginTab1.linkedBrowser, null, async function() {
+    let doc = content.document;
+    let plugin = doc.getElementById("testplugin");
+    return XPCNativeWrapper.unwrap(plugin).nativeWidgetIsVisible();
+  });
+  is(result, false, "plugin1 is hidden");
 
-  await waitForPluginVisibility(pluginTab2.linkedBrowser,
-                                true, "plugin2 should be visible");
+  result = await ContentTask.spawn(pluginTab2.linkedBrowser, null, async function() {
+    let doc = content.document;
+    let plugin = doc.getElementById("testplugin");
+    return XPCNativeWrapper.unwrap(plugin).nativeWidgetIsVisible();
+  });
+  is(result, true, "plugin2 is visible");
 
   // select plugin1 tab
   tabSwitchedPromise = waitTabSwitched();
   gBrowser.selectedTab = pluginTab1;
   await tabSwitchedPromise;
 
-  await waitForPluginVisibility(pluginTab1.linkedBrowser,
-                                true, "plugin1 should be visible");
+  result = await ContentTask.spawn(pluginTab1.linkedBrowser, null, async function() {
+    let doc = content.document;
+    let plugin = doc.getElementById("testplugin");
+    return XPCNativeWrapper.unwrap(plugin).nativeWidgetIsVisible();
+  });
+  is(result, true, "plugin1 is visible");
 
-  await waitForPluginVisibility(pluginTab2.linkedBrowser,
-                                false, "plugin2 should be hidden");
+  result = await ContentTask.spawn(pluginTab2.linkedBrowser, null, async function() {
+    let doc = content.document;
+    let plugin = doc.getElementById("testplugin");
+    return XPCNativeWrapper.unwrap(plugin).nativeWidgetIsVisible();
+  });
+  is(result, false, "plugin2 is hidden");
 
   // select plugin2 tab
   tabSwitchedPromise = waitTabSwitched();
   gBrowser.selectedTab = pluginTab2;
   await tabSwitchedPromise;
 
-  await waitForPluginVisibility(pluginTab1.linkedBrowser,
-                                false, "plugin1 should be hidden");
+  result = await ContentTask.spawn(pluginTab1.linkedBrowser, null, async function() {
+    let doc = content.document;
+    let plugin = doc.getElementById("testplugin");
+    return XPCNativeWrapper.unwrap(plugin).nativeWidgetIsVisible();
+  });
+  is(result, false, "plugin1 is hidden");
 
-  await waitForPluginVisibility(pluginTab2.linkedBrowser,
-                                true, "plugin2 should be visible");
+  result = await ContentTask.spawn(pluginTab2.linkedBrowser, null, async function() {
+    let doc = content.document;
+    let plugin = doc.getElementById("testplugin");
+    return XPCNativeWrapper.unwrap(plugin).nativeWidgetIsVisible();
+  });
+  is(result, true, "plugin2 is visible");
 
   // select test tab
   tabSwitchedPromise = waitTabSwitched();
   gBrowser.selectedTab = testTab;
   await tabSwitchedPromise;
 
-  await waitForPluginVisibility(pluginTab1.linkedBrowser,
-                                false, "plugin1 should be hidden");
+  result = await ContentTask.spawn(pluginTab1.linkedBrowser, null, async function() {
+    let doc = content.document;
+    let plugin = doc.getElementById("testplugin");
+    return XPCNativeWrapper.unwrap(plugin).nativeWidgetIsVisible();
+  });
+  is(result, false, "plugin1 is hidden");
 
-  await waitForPluginVisibility(pluginTab2.linkedBrowser,
-                                false, "plugin2 should be hidden");
+  result = await ContentTask.spawn(pluginTab2.linkedBrowser, null, async function() {
+    let doc = content.document;
+    let plugin = doc.getElementById("testplugin");
+    return XPCNativeWrapper.unwrap(plugin).nativeWidgetIsVisible();
+  });
+  is(result, false, "plugin2 is hidden");
 
   gBrowser.removeTab(pluginTab1);
   gBrowser.removeTab(pluginTab2);
 });