Bug 719875 - "Tap to activate plugin" placeholder can't be tapped after going back/forward in history. r=mfinkle
authorMargaret Leibovic <margaret.leibovic@gmail.com>
Tue, 31 Jan 2012 12:49:25 -0800
changeset 86121 f3dfff9cb09a3824599b2bee5f09a94b11fe11f9
parent 86120 8f2ca4c209e4c3e2ad1fa087acbc7d47ef9e65b5
child 86122 ba54adee1e958dd3933aab3c63183cad3eb66518
push id5683
push usermleibovic@mozilla.com
push dateFri, 03 Feb 2012 16:04:54 +0000
treeherdermozilla-inbound@f3dfff9cb09a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmfinkle
bugs719875
milestone13.0a1
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
Bug 719875 - "Tap to activate plugin" placeholder can't be tapped after going back/forward in history. r=mfinkle
mobile/android/chrome/content/browser.js
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -1407,17 +1407,17 @@ function Tab(aURL, aParams) {
   this.id = 0;
   this.showProgress = true;
   this.create(aURL, aParams);
   this._viewport = { x: 0, y: 0, width: gScreenWidth, height: gScreenHeight, offsetX: 0, offsetY: 0,
                      pageWidth: gScreenWidth, pageHeight: gScreenHeight, zoom: 1.0 };
   this.viewportExcess = { x: 0, y: 0 };
   this.documentIdForCurrentViewport = null;
   this.userScrollPos = { x: 0, y: 0 };
-  this._pluginsToPlay = [];
+  this._pluginCount = 0;
   this._pluginOverlayShowing = false;
 }
 
 Tab.prototype = {
   create: function(aURL, aParams) {
     if (this.browser)
       return;
 
@@ -1724,18 +1724,20 @@ Tab.prototype = {
         if (/^about:/.test(target.documentURI)) {
           this.browser.addEventListener("click", ErrorPageEventHandler, false);
           this.browser.addEventListener("pagehide", function listener() {
             this.browser.removeEventListener("click", ErrorPageEventHandler, false);
             this.browser.removeEventListener("pagehide", listener, true);
           }.bind(this), true);
         }
 
-        // Show a plugin doorhanger if there are no clickable overlays showing
-        if (this._pluginsToPlay.length && !this._pluginOverlayShowing)
+        // Show a plugin doorhanger if there are plugins on the page but no
+        // clickable overlays showing (this doesn't work on pages loaded after
+        // back/forward navigation - see bug 719875)
+        if (this._pluginCount && !this._pluginOverlayShowing)
           PluginHelper.showDoorHanger(this);
 
         break;
       }
 
       case "DOMLinkAdded": {
         let target = aEvent.originalTarget;
         if (!target.href || target.disabled)
@@ -1817,46 +1819,47 @@ Tab.prototype = {
               type: "Viewport:UpdateLater"
             }
           });
         }
         break;
       }
 
       case "PluginClickToPlay": {
+        // Keep track of the number of plugins to know whether or not to show
+        // the hidden plugins doorhanger
+        this._pluginCount++;
+
         let plugin = aEvent.target;
-        // Keep track of all the plugins on the current page
-        this._pluginsToPlay.push(plugin);
-
         let overlay = plugin.ownerDocument.getAnonymousElementByAttribute(plugin, "class", "mainBox");
         if (!overlay)
           return;
 
         // If the overlay is too small, hide the overlay and act like this
         // is a hidden plugin object
         if (PluginHelper.isTooSmall(plugin, overlay)) {
           overlay.style.visibility = "hidden";
           return;
         }
 
-        // Add click to play listener
-        plugin.addEventListener("click", (function(event) {
+        // Add click to play listener to the overlay
+        overlay.addEventListener("click", (function(event) {
           // Play all the plugin objects when the user clicks on one
           PluginHelper.playAllPlugins(this, event);
         }).bind(this), true);
 
         this._pluginOverlayShowing = true;
         break;
       }
 
       case "pagehide": {
         // Check to make sure it's top-level pagehide
         if (aEvent.target.defaultView == this.browser.contentWindow) {
           // Reset plugin state when we leave the page
-          this._pluginsToPlay = [];
+          this._pluginCount = 0;
           this._pluginOverlayShowing = false;
         }
         break;
       }
     }
   },
 
   onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus) {
@@ -3725,32 +3728,50 @@ var PluginHelper = {
           // Do nothing
         }
       }
     ]
     NativeWindow.doorhanger.show(message, "ask-to-play-plugins", buttons, aTab.id);
   },
 
   playAllPlugins: function(aTab, aEvent) {
-    let plugins = aTab._pluginsToPlay;
-    if (!plugins.length)
-      return;
-
     if (aEvent) {
       if (!aEvent.isTrusted)
         return;
       aEvent.preventDefault();
     }
 
-    for (let i = 0; i < plugins.length; i++) {
-      let objLoadingContent = plugins[i].QueryInterface(Ci.nsIObjectLoadingContent);
-      objLoadingContent.playPlugin();
+    this._findAndPlayAllPlugins(aTab.browser.contentWindow);
+  },
+
+  // Helper function that recurses through sub-frames to find all plugin objects
+  _findAndPlayAllPlugins: function _findAndPlayAllPlugins(aWindow) {
+    let embeds = aWindow.document.getElementsByTagName("embed");
+    for (let i = 0; i < embeds.length; i++) {
+      if (!embeds[i].hasAttribute("played"))
+        this._playPlugin(embeds[i]);
     }
-    // Clear _pluginsToPlay so we don't accidentally re-load them
-    aTab._pluginsToPlay = [];
+
+    let objects = aWindow.document.getElementsByTagName("object");
+    for (let i = 0; i < objects.length; i++) {
+      if (!objects[i].hasAttribute("played"))
+        this._playPlugin(objects[i]);
+    }
+
+    for (let i = 0; i < aWindow.frames.length; i++) {
+      this._findAndPlayAllPlugins(aWindow.frames[i]);
+    }
+  },
+
+  _playPlugin: function _playPlugin(aPlugin) {
+    let objLoadingContent = aPlugin.QueryInterface(Ci.nsIObjectLoadingContent);
+    objLoadingContent.playPlugin();
+
+    // Set an attribute on the plugin object to avoid re-loading it
+    aPlugin.setAttribute("played", true);
   },
 
   getPluginPreference: function getPluginPreference() {
     let pluginDisable = Services.prefs.getBoolPref("plugin.disable");
     if (pluginDisable)
       return "0";
 
     let clickToPlay = Services.prefs.getBoolPref("plugins.click_to_play");