Bug 687265 - Front-end support for flash on Android Fennec [r=mbrubeck r=blassey]
☠☠ backed out by dbb129f069b1 ☠ ☠
authorMark Finkle <mfinkle@mozilla.com>
Thu, 29 Sep 2011 10:44:03 -0400
changeset 77833 32e9422afd8dac2ebc3eeea3e22270f2c4ba9551
parent 77832 f8e26a743569f43baaaca6c3a091ecf3029308b6
child 77834 f96e4ff817a788d80e10b7b8d83c5da9e7f9b41f
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
reviewersmbrubeck, blassey
bugs687265
milestone10.0a1
Bug 687265 - Front-end support for flash on Android Fennec [r=mbrubeck r=blassey]
content/base/src/nsObjectLoadingContent.cpp
content/events/public/nsEventStates.h
dom/plugins/base/nsPluginHost.cpp
embedding/android/GeckoApp.java
layout/style/nsCSSPseudoClassList.h
mobile/app/mobile.js
mobile/chrome/content/browser.js
mobile/chrome/content/content.js
toolkit/locales/en-US/chrome/mozapps/plugins/plugins.dtd
toolkit/mozapps/plugins/content/pluginProblem.xml
toolkit/mozapps/plugins/content/pluginProblemBinding.css
toolkit/mozapps/plugins/content/pluginProblemContent.css
toolkit/themes/pinstripe/mozapps/plugins/pluginProblem.css
toolkit/themes/winstripe/mozapps/plugins/pluginProblem.css
--- a/content/base/src/nsObjectLoadingContent.cpp
+++ b/content/base/src/nsObjectLoadingContent.cpp
@@ -100,16 +100,20 @@
 
 #ifdef PR_LOGGING
 static PRLogModuleInfo* gObjectLog = PR_NewLogModule("objlc");
 #endif
 
 #define LOG(args) PR_LOG(gObjectLog, PR_LOG_DEBUG, args)
 #define LOG_ENABLED() PR_LOG_TEST(gObjectLog, PR_LOG_DEBUG)
 
+#ifdef ANDROID
+#include "nsXULAppAPI.h"
+#endif
+
 class nsAsyncInstantiateEvent : public nsRunnable {
 public:
   // This stores both the content and the frame so that Instantiate calls can be
   // avoided if the frame changed in the meantime.
   nsObjectLoadingContent *mContent;
   nsWeakFrame             mFrame;
   nsCString               mContentType;
   nsCOMPtr<nsIURI>        mURI;
@@ -1044,16 +1048,22 @@ nsObjectLoadingContent::AsyncOnChannelRe
   cb->OnRedirectVerifyCallback(NS_OK);
   return NS_OK;
 }
 
 // <public>
 nsEventStates
 nsObjectLoadingContent::ObjectState() const
 {
+#ifdef ANDROID
+  if (XRE_GetProcessType() == GeckoProcessType_Content) {
+    return NS_EVENT_STATE_TYPE_CLICK_TO_PLAY;
+  }
+#endif
+
   switch (mType) {
     case eType_Loading:
       return NS_EVENT_STATE_LOADING;
     case eType_Image:
       return ImageState();
     case eType_Plugin:
     case eType_Document:
       // These are OK. If documents start to load successfully, they display
--- a/content/events/public/nsEventStates.h
+++ b/content/events/public/nsEventStates.h
@@ -259,16 +259,18 @@ private:
 #define NS_EVENT_STATE_MOZ_SUBMITINVALID NS_DEFINE_EVENT_STATE_MACRO(31)
 // UI friendly version of :invalid pseudo-class.
 #define NS_EVENT_STATE_MOZ_UI_INVALID NS_DEFINE_EVENT_STATE_MACRO(32)
 // UI friendly version of :valid pseudo-class.
 #define NS_EVENT_STATE_MOZ_UI_VALID NS_DEFINE_EVENT_STATE_MACRO(33)
 // Content is the full screen element, or a frame containing the
 // current full-screen element.
 #define NS_EVENT_STATE_FULL_SCREEN   NS_DEFINE_EVENT_STATE_MACRO(34)
+// Handler for click to play plugin
+#define NS_EVENT_STATE_TYPE_CLICK_TO_PLAY NS_DEFINE_EVENT_STATE_MACRO(35)
 
 /**
  * NOTE: do not go over 63 without updating nsEventStates::InternalType!
  */
 
 #define ESM_MANAGED_STATES (NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_FOCUS |     \
                             NS_EVENT_STATE_HOVER | NS_EVENT_STATE_DRAGOVER |   \
                             NS_EVENT_STATE_URLTARGET | NS_EVENT_STATE_FOCUSRING | \
--- a/dom/plugins/base/nsPluginHost.cpp
+++ b/dom/plugins/base/nsPluginHost.cpp
@@ -89,16 +89,17 @@
 #include "nsIWritablePropertyBag2.h"
 #include "nsPluginStreamListenerPeer.h"
 
 #include "nsEnumeratorUtils.h"
 #include "nsXPCOM.h"
 #include "nsXPCOMCID.h"
 #include "nsISupportsPrimitives.h"
 
+#include "nsXULAppAPI.h"
 #include "nsIXULRuntime.h"
 
 // for the dialog
 #include "nsIStringBundle.h"
 #include "nsIWindowWatcher.h"
 #include "nsPIDOMWindow.h"
 
 #include "nsIScriptGlobalObject.h"
@@ -2246,16 +2247,21 @@ nsresult nsPluginHost::ScanPluginsDirect
       if (!aCreatePluginList && *aPluginsChanged)
         break;
     }
     return NS_OK;
 }
 
 nsresult nsPluginHost::LoadPlugins()
 {
+#ifdef ANDROID
+  if (XRE_GetProcessType() == GeckoProcessType_Content) {
+    return NS_OK;
+  }
+#endif
   // do not do anything if it is already done
   // use ReloadPlugins() to enforce loading
   if (mPluginsLoaded)
     return NS_OK;
 
   if (mPluginsDisabled)
     return NS_OK;
 
--- a/embedding/android/GeckoApp.java
+++ b/embedding/android/GeckoApp.java
@@ -146,40 +146,36 @@ abstract public class GeckoApp
 
     private static final String PLUGIN_SYSTEM_LIB = "/system/lib/plugins/";
 
     private static final String PLUGIN_TYPE = "type";
     private static final String TYPE_NATIVE = "native";
     public ArrayList<PackageInfo> mPackageInfoCache = new ArrayList<PackageInfo>();
 
     String[] getPluginDirectories() {
-
         ArrayList<String> directories = new ArrayList<String>();
         PackageManager pm = this.mAppContext.getPackageManager();
         List<ResolveInfo> plugins = pm.queryIntentServices(new Intent(PLUGIN_ACTION),
                 PackageManager.GET_SERVICES | PackageManager.GET_META_DATA);
 
         synchronized(mPackageInfoCache) {
-
             // clear the list of existing packageInfo objects
             mPackageInfoCache.clear();
 
-
             for (ResolveInfo info : plugins) {
 
                 // retrieve the plugin's service information
                 ServiceInfo serviceInfo = info.serviceInfo;
                 if (serviceInfo == null) {
                     Log.w(LOGTAG, "Ignore bad plugin");
                     continue;
                 }
 
                 Log.w(LOGTAG, "Loading plugin: " + serviceInfo.packageName);
 
-
                 // retrieve information from the plugin's manifest
                 PackageInfo pkgInfo;
                 try {
                     pkgInfo = pm.getPackageInfo(serviceInfo.packageName,
                                     PackageManager.GET_PERMISSIONS
                                     | PackageManager.GET_SIGNATURES);
                 } catch (Exception e) {
                     Log.w(LOGTAG, "Can't find plugin: " + serviceInfo.packageName);
--- a/layout/style/nsCSSPseudoClassList.h
+++ b/layout/style/nsCSSPseudoClassList.h
@@ -151,16 +151,18 @@ CSS_STATE_PSEUDO_CLASS(mozFocusRing, ":-
 CSS_STATE_PSEUDO_CLASS(mozBroken, ":-moz-broken", NS_EVENT_STATE_BROKEN)
 CSS_STATE_PSEUDO_CLASS(mozUserDisabled, ":-moz-user-disabled",
                        NS_EVENT_STATE_USERDISABLED)
 CSS_STATE_PSEUDO_CLASS(mozSuppressed, ":-moz-suppressed",
                        NS_EVENT_STATE_SUPPRESSED)
 CSS_STATE_PSEUDO_CLASS(mozLoading, ":-moz-loading", NS_EVENT_STATE_LOADING)
 CSS_STATE_PSEUDO_CLASS(mozTypeUnsupported, ":-moz-type-unsupported",
                        NS_EVENT_STATE_TYPE_UNSUPPORTED)
+CSS_STATE_PSEUDO_CLASS(mozHandlerClickToPlay, ":-moz-handler-clicktoplay",
+                       NS_EVENT_STATE_TYPE_CLICK_TO_PLAY)
 CSS_STATE_PSEUDO_CLASS(mozHandlerDisabled, ":-moz-handler-disabled",
                        NS_EVENT_STATE_HANDLER_DISABLED)
 CSS_STATE_PSEUDO_CLASS(mozHandlerBlocked, ":-moz-handler-blocked",
                        NS_EVENT_STATE_HANDLER_BLOCKED)
 CSS_STATE_PSEUDO_CLASS(mozHandlerCrashed, ":-moz-handler-crashed",
                        NS_EVENT_STATE_HANDLER_CRASHED)
 
 CSS_STATE_PSEUDO_CLASS(mozMathIncrementScriptLevel,
--- a/mobile/app/mobile.js
+++ b/mobile/app/mobile.js
@@ -432,20 +432,24 @@ pref("browser.ui.touch.left", 8);
 pref("browser.ui.touch.right", 8);
 pref("browser.ui.touch.top", 12);
 pref("browser.ui.touch.bottom", 4);
 pref("browser.ui.touch.weight.visited", 120); // percentage
 
 // plugins
 #if MOZ_PLATFORM_MAEMO == 6
 pref("plugin.disable", false);
+pref("dom.ipc.plugins.enabled", true);
+#elifdef ANDROID
+pref("plugin.disable", false);
+pref("dom.ipc.plugins.enabled", false);
 #else
 pref("plugin.disable", true);
+pref("dom.ipc.plugins.enabled", true);
 #endif
-pref("dom.ipc.plugins.enabled", true);
 
 // process priority
 // higher values give content process less CPU time
 #if MOZ_PLATFORM_MAEMO == 5
 pref("dom.ipc.content.nice", 10);
 #else
 pref("dom.ipc.content.nice", 1);
 #endif
--- a/mobile/chrome/content/browser.js
+++ b/mobile/chrome/content/browser.js
@@ -395,16 +395,17 @@ var Browser = {
     messageManager.addMessageListener("Browser:FormSubmit", this);
     messageManager.addMessageListener("Browser:KeyPress", this);
     messageManager.addMessageListener("Browser:ZoomToPoint:Return", this);
     messageManager.addMessageListener("Browser:CanUnload:Return", this);
     messageManager.addMessageListener("scroll", this);
     messageManager.addMessageListener("Browser:CertException", this);
     messageManager.addMessageListener("Browser:BlockedSite", this);
     messageManager.addMessageListener("Browser:ErrorPage", this);
+    messageManager.addMessageListener("Browser:PluginClickToPlay", this);
 
     // Broadcast a UIReady message so add-ons know we are finished with startup
     let event = document.createEvent("Events");
     event.initEvent("UIReady", true, false);
     window.dispatchEvent(event);
   },
 
   _alertShown: function _alertShown() {
@@ -493,16 +494,17 @@ var Browser = {
     messageManager.removeMessageListener("Browser:ViewportMetadata", this);
     messageManager.removeMessageListener("Browser:FormSubmit", this);
     messageManager.removeMessageListener("Browser:KeyPress", this);
     messageManager.removeMessageListener("Browser:ZoomToPoint:Return", this);
     messageManager.removeMessageListener("scroll", this);
     messageManager.removeMessageListener("Browser:CertException", this);
     messageManager.removeMessageListener("Browser:BlockedSite", this);
     messageManager.removeMessageListener("Browser:ErrorPage", this);
+    messageManager.removeMessageListener("Browser:PluginClickToPlay", this);
 
     var os = Services.obs;
     os.removeObserver(XPInstallObserver, "addon-install-blocked");
     os.removeObserver(XPInstallObserver, "addon-install-started");
     os.removeObserver(SessionHistoryObserver, "browser:purge-session-history");
     os.removeObserver(ContentCrashObserver, "ipc:content-shutdown");
     os.removeObserver(MemoryObserver, "memory-pressure");
     os.removeObserver(ActivityObserver, "application-background", false);
@@ -1265,16 +1267,41 @@ var Browser = {
         this._handleCertException(aMessage);
         break;
       case "Browser:BlockedSite":
         this._handleBlockedSite(aMessage);
         break;
       case "Browser:ErrorPage":
         this._handleErrorPage(aMessage);
         break;
+      case "Browser:PluginClickToPlay": {
+        // Save off session history
+        let parent = browser.parentNode;
+        let data = browser.__SS_data;
+        if (data.entries.length == 0)
+          return;
+
+        // Remove the browser from the DOM, effectively killing it's content
+        parent.removeChild(browser);
+
+        // Re-create the browser as non-remote, so plugins work
+        browser.setAttribute("remote", "false");
+        parent.appendChild(browser);
+
+        // Reload the content using session history
+        browser.__SS_data = data;
+        let json = {
+          uri: data.entries[data.index - 1].url,
+          flags: null,
+          entries: data.entries,
+          index: data.index
+        };
+        browser.messageManager.sendAsyncMessage("WebNavigation:LoadURI", json);
+        break;
+      }
     }
   },
 
   _grabbedSidebar: false, // true while the user is dragging the sidebar
   _sidebarOffset: 0, // tracks how far the sidebar has been dragged
   _slideMultiplier: 1, // set greater than 1 to amplify sidebar drags (makes swiping easier)
 
   /**
--- a/mobile/chrome/content/content.js
+++ b/mobile/chrome/content/content.js
@@ -278,16 +278,17 @@ let Content = {
 
     if (Util.isParentProcess())
       addEventListener("DOMActivate", this, true);
 
     addEventListener("MozApplicationManifest", this, false);
     addEventListener("DOMContentLoaded", this, false);
     addEventListener("pagehide", this, false);
     addEventListener("keypress", this, false, false);
+    addEventListener("PluginClickToPlay", this, false, true);
 
     // Attach a listener to watch for "click" events bubbling up from error
     // pages and other similar page. This lets us fix bugs like 401575 which
     // require error page UI to do privileged things, without letting error
     // pages have any privilege themselves.
     addEventListener("click", this, false);
 
     docShell.QueryInterface(Ci.nsIDocShellHistory).useGlobalHistory = true;
@@ -389,16 +390,20 @@ let Content = {
       case "DOMContentLoaded":
         this._maybeNotifyErroPage();
         break;
 
       case "pagehide":
         if (aEvent.target == content.document)
           this._resetFontSize();          
         break;
+
+      case "PluginClickToPlay":
+        sendAsyncMessage("Browser:PluginClickToPlay", { });
+        break;
     }
   },
 
   receiveMessage: function receiveMessage(aMessage) {
     let json = aMessage.json;
     let x = json.x;
     let y = json.y;
     let modifiers = json.modifiers;
--- a/toolkit/locales/en-US/chrome/mozapps/plugins/plugins.dtd
+++ b/toolkit/locales/en-US/chrome/mozapps/plugins/plugins.dtd
@@ -16,16 +16,17 @@
 <!ENTITY pluginWizard.installPluginsPage.description.label   "&brandShortName; is installing plugins…">
 
 <!ENTITY pluginWizard.finalPage.description.label            "&brandShortName; finished installing the missing plugins:">
 
 <!ENTITY pluginWizard.finalPage.moreInfo.label               "Find out more about Plugins or manually find missing plugins.">
 <!ENTITY pluginWizard.finalPage.restart.label                "&brandShortName; needs to be restarted for the plugin(s) to work.">
 
 <!ENTITY missingPlugin                                       "A plugin is needed to display this content.">
+<!ENTITY clickToPlayPlugin                                   "Tap here to activate plugin.">
 <!ENTITY disabledPlugin                                      "This plugin is disabled.">
 <!ENTITY blockedPlugin.label                                 "This plugin has been blocked for your protection.">
 
 <!ENTITY installPlugin                                       "Install plugin…">
 <!ENTITY managePlugins                                       "Manage plugins…">
 
 <!-- LOCALIZATION NOTE (reloadPlugin.pre): include a trailing space as needed -->
 <!-- LOCALIZATION NOTE (reloadPlugin.middle): avoid leading/trailing spaces, this text is a link -->
--- a/toolkit/mozapps/plugins/content/pluginProblem.xml
+++ b/toolkit/mozapps/plugins/content/pluginProblem.xml
@@ -53,16 +53,19 @@
         <stylesheet src="chrome://mozapps/content/plugins/pluginProblemContent.css"/>
     </resources>
 
     <content>
         <xul:vbox class="mainBox" flex="1" chromedir="&locale.dir;">
             <xul:spacer flex="1"/>
             <xul:box class="icon"/>
             <html:div class="msg msgUnsupported">&missingPlugin;</html:div>
+            <html:div class="msg msgClickToPlay" onclick="var evt = document.createEvent('Events'); evt.initEvent('PluginClickToPlay', true, false); this.dispatchEvent(evt);">
+               &clickToPlayPlugin;
+            </html:div>
             <html:div class="msg msgDisabled">&disabledPlugin;</html:div>
             <html:div class="msg msgBlocked">&blockedPlugin.label;</html:div>
             <html:div class="msg msgCrashed"><!-- set at runtime --></html:div>
 
             <html:div class="installStatus">
                 <html:div class="msg msgInstallPlugin"><html:a class="installPluginLink" href="">&installPlugin;</html:a></html:div>
             </html:div>
             <html:div class="msg msgManagePlugins"><html:a class="managePluginsLink" href="">&managePlugins;</html:a></html:div>
--- a/toolkit/mozapps/plugins/content/pluginProblemBinding.css
+++ b/toolkit/mozapps/plugins/content/pluginProblemBinding.css
@@ -36,18 +36,21 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 @namespace url(http://www.w3.org/1999/xhtml); /* set default namespace to HTML */
 
 embed:-moz-handler-disabled,
 embed:-moz-handler-blocked,
 embed:-moz-handler-crashed,
+embed:-moz-handler-clicktoplay,
 applet:-moz-handler-disabled,
 applet:-moz-handler-blocked,
 applet:-moz-handler-crashed,
+applet:-moz-handler-clicktoplay,
 object:-moz-has-handlerref:-moz-handler-disabled,
 object:-moz-has-handlerref:-moz-handler-blocked,
-object:-moz-handler-crashed {
+object:-moz-handler-crashed,
+object:-moz-handler-clicktoplay {
     display: inline-block;
     overflow: hidden;
     -moz-binding: url('chrome://mozapps/content/plugins/pluginProblem.xml#pluginProblem') !important;
 }
--- a/toolkit/mozapps/plugins/content/pluginProblemContent.css
+++ b/toolkit/mozapps/plugins/content/pluginProblemContent.css
@@ -8,21 +8,23 @@ html|applet:not([width]), html|applet[wi
 
 html|object:not([height]), html|object[height=""],
 html|embed:not([height]), html|embed[height=""],
 html|applet:not([height]), html|applet[height=""] {
   height: 200px;
 }
 
 :-moz-type-unsupported .mainBox,
+:-moz-handler-clicktoplay .mainBox,
 :-moz-handler-disabled .mainBox,
 :-moz-handler-blocked .mainBox {
   -moz-user-focus: normal;
 }
 :-moz-type-unsupported .mainBox:focus,
+:-moz-handler-clicktoplay .mainBox:focus,
 :-moz-handler-disabled .mainBox:focus,
 :-moz-handler-blocked .mainBox:focus {
   outline: 1px dotted;
 }
 
 .mainBox {
   width: inherit;
   height: inherit;
@@ -35,16 +37,17 @@ html|applet:not([height]), html|applet[h
   direction: rtl;
 }
 
 .msg {
   display: none;
 }
 
 :-moz-type-unsupported .msgUnsupported,
+:-moz-handler-clicktoplay .msgClickToPlay,
 :-moz-handler-disabled .msgDisabled,
 :-moz-handler-disabled .msgManagePlugins,
 :-moz-handler-blocked .msgBlocked,
 :-moz-handler-crashed .msgCrashed {
   display: block;
 }
 
 .installStatus[status="ready"] .msgInstallPlugin {
--- a/toolkit/themes/pinstripe/mozapps/plugins/pluginProblem.css
+++ b/toolkit/themes/pinstripe/mozapps/plugins/pluginProblem.css
@@ -29,16 +29,19 @@ html|a {
   background-repeat: no-repeat;
 }
 :-moz-type-unsupported .icon {
   background-image: url(chrome://mozapps/skin/plugins/contentPluginMissing.png);
 }
 :-moz-type-unsupported .icon[status="ready"] {
   background-image: url(chrome://mozapps/skin/plugins/contentPluginDownload.png);
 }
+:-moz-handler-clicktoplay .icon {
+  background-image: url(chrome://mozapps/skin/plugins/contentPluginMissing.png);
+}
 :-moz-handler-disabled .icon {
   background-image: url(chrome://mozapps/skin/plugins/contentPluginDisabled.png);
 }
 :-moz-handler-blocked .icon {
   background-image: url(chrome://mozapps/skin/plugins/contentPluginBlocked.png);
 }
 :-moz-handler-crashed .icon {
   background-image: url(chrome://mozapps/skin/plugins/contentPluginCrashed.png);
--- a/toolkit/themes/winstripe/mozapps/plugins/pluginProblem.css
+++ b/toolkit/themes/winstripe/mozapps/plugins/pluginProblem.css
@@ -29,16 +29,19 @@ html|a {
   background-repeat: no-repeat;
 }
 :-moz-type-unsupported .icon {
   background-image: url(chrome://mozapps/skin/plugins/contentPluginMissing.png);
 }
 :-moz-type-unsupported .icon[status="ready"] {
   background-image: url(chrome://mozapps/skin/plugins/contentPluginDownload.png);
 }
+:-moz-handler-clicktoplay .icon {
+  background-image: url(chrome://mozapps/skin/plugins/contentPluginMissing.png);
+}
 :-moz-handler-disabled .icon {
   background-image: url(chrome://mozapps/skin/plugins/contentPluginDisabled.png);
 }
 :-moz-handler-blocked .icon {
   background-image: url(chrome://mozapps/skin/plugins/contentPluginBlocked.png);
 }
 :-moz-handler-crashed .icon {
   background-image: url(chrome://mozapps/skin/plugins/contentPluginCrashed.png);