Bug 719875 - "Tap to activate plugin" placeholder can't be tapped after going back/forward in history. r=mfinkle a=akeybl
authorMargaret Leibovic <margaret.leibovic@gmail.com>
Tue, 31 Jan 2012 12:49:25 -0800
changeset 88331 1f3329e303fe0676950a1430467427361e4fbb5a
parent 88330 ed8a492bca0a48482aa56f52b6d5d414f389fdf2
child 88332 68fb495e3183754b2692f438dbe664a1c48cbea9
push idunknown
push userunknown
push dateunknown
reviewersmfinkle, akeybl
bugs719875
milestone12.0a2
Bug 719875 - "Tap to activate plugin" placeholder can't be tapped after going back/forward in history. r=mfinkle a=akeybl
mobile/android/chrome/content/browser.js
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -1393,17 +1393,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;
 
@@ -1710,18 +1710,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)
@@ -1803,46 +1805,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) {
@@ -3711,32 +3714,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");