Bug 723217: Fix click-to-play support for plugins on Android. r=snorp
authorJosh Aas <joshmoz@gmail.com>
Fri, 10 Feb 2012 08:39:40 -0500
changeset 86617 40c36f6068d69afb75afa6633bf129fbdd553f58
parent 86616 5d76c57d1e8c1f724e72baa1af341e16a9886e43
child 86618 82612a816cc0f7af875639a9eb023fd040c8c21b
push id22035
push userbmo@edmorley.co.uk
push dateSat, 11 Feb 2012 01:49:34 +0000
treeherdermozilla-central@d71dab82fff4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssnorp
bugs723217
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 723217: Fix click-to-play support for plugins on Android. r=snorp
content/base/src/nsObjectLoadingContent.cpp
content/base/src/nsObjectLoadingContent.h
dom/plugins/base/nsPluginHost.cpp
dom/plugins/base/nsPluginHost.h
layout/build/nsContentDLF.cpp
--- a/content/base/src/nsObjectLoadingContent.cpp
+++ b/content/base/src/nsObjectLoadingContent.cpp
@@ -479,26 +479,28 @@ IsSupportedImage(const nsCString& aMimeT
     return false;
   }
 
   bool supported;
   nsresult rv = loader->SupportImageWithMimeType(aMimeType.get(), &supported);
   return NS_SUCCEEDED(rv) && supported;
 }
 
-static bool
-IsSupportedPlugin(const nsCString& aMIMEType, bool aShouldPlay)
+nsresult nsObjectLoadingContent::IsPluginEnabledForType(const nsCString& aMIMEType)
 {
+  if (!mShouldPlay) {
+    return NS_ERROR_PLUGIN_CLICKTOPLAY;
+  }
+
   nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
   nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
   if (!pluginHost) {
     return false;
   }
-  nsresult rv = pluginHost->IsPluginEnabledForType(aMIMEType.get(), aShouldPlay);
-  return NS_SUCCEEDED(rv);
+  return pluginHost->IsPluginEnabledForType(aMIMEType.get());
 }
 
 static void
 GetExtensionFromURI(nsIURI* uri, nsCString& ext)
 {
   nsCOMPtr<nsIURL> url(do_QueryInterface(uri));
   if (url) {
     url->GetFileExtension(ext);
@@ -512,35 +514,37 @@ GetExtensionFromURI(nsIURI* uri, nsCStri
     }
   }
 }
 
 /**
  * Checks whether a plugin exists and is enabled for the extension
  * in the given URI. The MIME type is returned in the mimeType out parameter.
  */
-static bool
-IsPluginEnabledByExtension(nsIURI* uri, nsCString& mimeType, bool aShouldPlay)
+bool nsObjectLoadingContent::IsPluginEnabledByExtension(nsIURI* uri, nsCString& mimeType)
 {
+  if (!mShouldPlay) {
+    return false;
+  }
+
   nsCAutoString ext;
   GetExtensionFromURI(uri, ext);
 
   if (ext.IsEmpty()) {
     return false;
   }
 
   nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
   nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
   if (!pluginHost) {
     return false;
   }
 
   const char* typeFromExt;
-  if (NS_SUCCEEDED(pluginHost->IsPluginEnabledForExtension(ext.get(), typeFromExt,
-                                                           aShouldPlay))) {
+  if (NS_SUCCEEDED(pluginHost->IsPluginEnabledForExtension(ext.get(), typeFromExt))) {
     mimeType = typeFromExt;
     return true;
   }
   return false;
 }
 
 nsObjectLoadingContent::nsObjectLoadingContent()
   : mPendingInstantiateEvent(nsnull)
@@ -563,16 +567,20 @@ nsObjectLoadingContent::~nsObjectLoading
   if (mFrameLoader) {
     mFrameLoader->Destroy();
   }
 }
 
 nsresult
 nsObjectLoadingContent::InstantiatePluginInstance(const char* aMimeType, nsIURI* aURI)
 {
+  if (!mShouldPlay) {
+    return NS_ERROR_PLUGIN_CLICKTOPLAY;
+  }
+
   // Don't do anything if we already have an active instance.
   if (mInstanceOwner) {
     return NS_OK;
   }
 
   // Don't allow re-entry into initialization code.
   if (mInstantiating) {
     return NS_OK;
@@ -581,21 +589,16 @@ nsObjectLoadingContent::InstantiatePlugi
   AutoSetInstantiatingToFalse autoInstantiating(this);
 
   // Instantiating an instance can result in script execution, which
   // can destroy this DOM object. Don't allow that for the scope
   // of this method.
   nsCOMPtr<nsIObjectLoadingContent> kungFuDeathGrip = this;
   nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
 
-  nsCString typeToUse(aMimeType);
-  if (typeToUse.IsEmpty() && aURI) {
-    IsPluginEnabledByExtension(aURI, typeToUse, mShouldPlay);
-  }
-
   nsCOMPtr<nsIURI> baseURI;
   if (!aURI) {
     // We need some URI. If we have nothing else, use the base URI.
     // XXX(biesi): The code used to do this. Not sure why this is correct...
     GetObjectBaseURI(thisContent, getter_AddRefs(baseURI));
     aURI = baseURI;
   }
 
@@ -725,20 +728,20 @@ nsObjectLoadingContent::OnStartRequest(n
   // We want to use the channel type unless one of the following is true:
   //
   // 1) The channel type is application/octet-stream and we have a
   //    type hint and the type hint is not a document type.
   // 2) Our type hint is a type that we support with a plugin.
   if ((channelType.EqualsASCII(APPLICATION_OCTET_STREAM) && 
        !mContentType.IsEmpty() &&
        GetTypeOfContent(mContentType) != eType_Document) ||
-      // Need to check IsSupportedPlugin() in addition to GetTypeOfContent()
+      // Need to check IsPluginEnabledForType() in addition to GetTypeOfContent()
       // because otherwise the default plug-in's catch-all behavior would
       // confuse things.
-      (IsSupportedPlugin(mContentType, mShouldPlay) && 
+      (NS_SUCCEEDED(IsPluginEnabledForType(mContentType)) && 
        GetTypeOfContent(mContentType) == eType_Plugin)) {
     // Set the type we'll use for dispatch on the channel.  Otherwise we could
     // end up trying to dispatch to a nsFrameLoader, which will complain that
     // it couldn't find a way to handle application/octet-stream
     nsCAutoString typeHint, dummy;
     NS_ParseContentType(mContentType, typeHint, dummy);
     if (!typeHint.IsEmpty()) {
       chan->SetContentType(typeHint);
@@ -747,17 +750,17 @@ nsObjectLoadingContent::OnStartRequest(n
     mContentType = channelType;
   }
 
   nsCOMPtr<nsIURI> uri;
   chan->GetURI(getter_AddRefs(uri));
 
   if (mContentType.EqualsASCII(APPLICATION_OCTET_STREAM)) {
     nsCAutoString extType;
-    if (IsPluginEnabledByExtension(uri, extType, mShouldPlay)) {
+    if (IsPluginEnabledByExtension(uri, extType)) {
       mContentType = extType;
       chan->SetContentType(extType);
     }
   }
 
   // Now find out what type the content is
   // UnloadContent will set our type to null; need to be sure to only set it to
   // the real value on success
@@ -1292,18 +1295,18 @@ nsObjectLoadingContent::LoadObject(nsIUR
   // change the order of the declarations!
   AutoFallback fallback(this, &rv);
 
   PRUint32 caps = GetCapabilities();
   LOG(("OBJLC [%p]: Capabilities: %04x\n", this, caps));
 
   nsCAutoString overrideType;
   if ((caps & eOverrideServerType) &&
-      ((!aTypeHint.IsEmpty() && IsSupportedPlugin(aTypeHint, mShouldPlay)) ||
-       (aURI && IsPluginEnabledByExtension(aURI, overrideType, mShouldPlay)))) {
+      ((!aTypeHint.IsEmpty() && NS_SUCCEEDED(IsPluginEnabledForType(aTypeHint))) ||
+       (aURI && IsPluginEnabledByExtension(aURI, overrideType)))) {
     ObjectType newType;
     if (overrideType.IsEmpty()) {
       newType = GetTypeOfContent(aTypeHint);
     } else {
       mContentType = overrideType;
       newType = eType_Plugin;
     }
 
@@ -1429,17 +1432,17 @@ nsObjectLoadingContent::LoadObject(nsIUR
 
   // E.g. mms://
   if (!CanHandleURI(aURI)) {
     if (aTypeHint.IsEmpty()) {
       rv = NS_ERROR_NOT_AVAILABLE;
       return NS_OK;
     }
 
-    if (IsSupportedPlugin(aTypeHint, mShouldPlay)) {
+    if (NS_SUCCEEDED(IsPluginEnabledForType(aTypeHint))) {
       mType = eType_Plugin;
     } else {
       rv = NS_ERROR_NOT_AVAILABLE;
       // No plugin to load, notify of the failure.
       UpdateFallbackState(thisContent, fallback, aTypeHint);
     }
 
     return NS_OK;
@@ -1739,49 +1742,43 @@ nsObjectLoadingContent::GetTypeOfContent
 
   bool isSVG = aMIMEType.LowerCaseEqualsLiteral("image/svg+xml");
   bool supportedSVG = isSVG && (caps & eSupportSVG);
   if (((caps & eSupportDocuments) || supportedSVG) &&
       IsSupportedDocument(aMIMEType)) {
     return eType_Document;
   }
 
-  if ((caps & eSupportPlugins) && IsSupportedPlugin(aMIMEType, mShouldPlay)) {
+  if ((caps & eSupportPlugins) && NS_SUCCEEDED(IsPluginEnabledForType(aMIMEType))) {
     return eType_Plugin;
   }
 
   return eType_Null;
 }
 
 nsresult
 nsObjectLoadingContent::TypeForClassID(const nsAString& aClassID,
                                        nsACString& aType)
 {
-  nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
-  nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
-  if (!pluginHost) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-
   if (StringBeginsWith(aClassID, NS_LITERAL_STRING("java:"))) {
     // Supported if we have a java plugin
     aType.AssignLiteral("application/x-java-vm");
-    nsresult rv = pluginHost->IsPluginEnabledForType("application/x-java-vm");
+    nsresult rv = IsPluginEnabledForType(NS_LITERAL_CSTRING("application/x-java-vm"));
     return NS_SUCCEEDED(rv) ? NS_OK : NS_ERROR_NOT_AVAILABLE;
   }
 
   // If it starts with "clsid:", this is ActiveX content
   if (StringBeginsWith(aClassID, NS_LITERAL_STRING("clsid:"), nsCaseInsensitiveStringComparator())) {
     // Check if we have a plugin for that
 
-    if (NS_SUCCEEDED(pluginHost->IsPluginEnabledForType("application/x-oleobject"))) {
+    if (NS_SUCCEEDED(IsPluginEnabledForType(NS_LITERAL_CSTRING("application/x-oleobject")))) {
       aType.AssignLiteral("application/x-oleobject");
       return NS_OK;
     }
-    if (NS_SUCCEEDED(pluginHost->IsPluginEnabledForType("application/oleobject"))) {
+    if (NS_SUCCEEDED(IsPluginEnabledForType(NS_LITERAL_CSTRING("application/oleobject")))) {
       aType.AssignLiteral("application/oleobject");
       return NS_OK;
     }
   }
 
   return NS_ERROR_NOT_AVAILABLE;
 }
 
@@ -1827,17 +1824,17 @@ nsObjectLoadingContent::HandleBeingBlock
     if (aRetval == nsIContentPolicy::REJECT_TYPE) {
       mUserDisabled = true;
     } else if (aRetval == nsIContentPolicy::REJECT_SERVER) {
       mSuppressed = true;
     }
   }
 }
 
-/* static */ PluginSupportState
+PluginSupportState
 nsObjectLoadingContent::GetPluginSupportState(nsIContent* aContent,
                                               const nsCString& aContentType)
 {
   if (!aContent->IsHTML()) {
     return ePluginOtherState;
   }
 
   if (aContent->Tag() == nsGkAtoms::embed ||
@@ -1861,26 +1858,20 @@ nsObjectLoadingContent::GetPluginSupport
         nsStyleUtil::IsSignificantChild(child, true, false);
     }
   }
 
   return hasAlternateContent ? ePluginOtherState :
     GetPluginDisabledState(aContentType);
 }
 
-/* static */ PluginSupportState
+PluginSupportState
 nsObjectLoadingContent::GetPluginDisabledState(const nsCString& aContentType)
 {
-  nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
-  nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
-  if (!pluginHost) {
-    return ePluginUnsupported;
-  }
-
-  nsresult rv = pluginHost->IsPluginEnabledForType(aContentType.get());
+  nsresult rv = IsPluginEnabledForType(aContentType);
   if (rv == NS_ERROR_PLUGIN_DISABLED)
     return ePluginDisabled;
   if (rv == NS_ERROR_PLUGIN_CLICKTOPLAY)
     return ePluginClickToPlay;
   if (rv == NS_ERROR_PLUGIN_BLOCKLISTED)
     return ePluginBlocklisted;
   return ePluginUnsupported;
 }
@@ -2112,11 +2103,12 @@ nsObjectLoadingContent::NotifyContentObj
 }
 
 NS_IMETHODIMP
 nsObjectLoadingContent::PlayPlugin()
 {
   if (!nsContentUtils::IsCallerChrome())
     return NS_OK;
 
+  mSrcStreamLoadInitiated = false;
   mShouldPlay = true;
   return LoadObject(mURI, true, mContentType, true);
 }
--- a/content/base/src/nsObjectLoadingContent.h
+++ b/content/base/src/nsObjectLoadingContent.h
@@ -323,38 +323,36 @@ class nsObjectLoadingContent : public ns
 
     /**
      * Get the plugin support state for the given content node and MIME type.
      * This is used for purposes of determining whether to fire PluginNotFound
      * events etc.  aContentType is the MIME type we ended up with.
      *
      * This should only be called if the type of this content is eType_Null.
      */
-    static PluginSupportState
-      GetPluginSupportState(nsIContent* aContent,
-                            const nsCString& aContentType);
+    PluginSupportState GetPluginSupportState(nsIContent* aContent, const nsCString& aContentType);
 
     /**
      * If the plugin for aContentType is disabled, return ePluginDisabled.
      * Otherwise (including if there is no plugin for aContentType at all),
      * return ePluginUnsupported.
      *
      * This should only be called if the type of this content is eType_Null.
      */
-    static PluginSupportState
-      GetPluginDisabledState(const nsCString& aContentType);
+    PluginSupportState GetPluginDisabledState(const nsCString& aContentType);
 
     /**
      * When there is no usable plugin available this will send UI events and
      * update the AutoFallback object appropriate to the reason for there being
      * no plugin available.
      */
-    static void
-      UpdateFallbackState(nsIContent* aContent, AutoFallback& fallback,
-                          const nsCString& aTypeHint);
+    void UpdateFallbackState(nsIContent* aContent, AutoFallback& fallback, const nsCString& aTypeHint);
+
+    nsresult IsPluginEnabledForType(const nsCString& aMIMEType);
+    bool IsPluginEnabledByExtension(nsIURI* uri, nsCString& mimeType);
 
     /**
      * The final listener to ship the data to (imagelib, uriloader, etc)
      */
     nsCOMPtr<nsIStreamListener> mFinalListener;
 
     /**
      * Frame loader, for content documents we load.
--- a/dom/plugins/base/nsPluginHost.cpp
+++ b/dom/plugins/base/nsPluginHost.cpp
@@ -1363,42 +1363,34 @@ nsPluginHost::TrySetUpPluginInstance(con
 #endif
 
   return rv;
 }
 
 nsresult
 nsPluginHost::IsPluginEnabledForType(const char* aMimeType)
 {
-  // If plugins.click_to_play is false, plugins should always play
-  return IsPluginEnabledForType(aMimeType,
-                                !Preferences::GetBool("plugins.click_to_play", false));
-}
-
-nsresult
-nsPluginHost::IsPluginEnabledForType(const char* aMimeType, bool aShouldPlay)
-{
   nsPluginTag *plugin = FindPluginForType(aMimeType, true);
   if (plugin)
-    return aShouldPlay ? NS_OK : NS_ERROR_PLUGIN_CLICKTOPLAY;
+    return NS_OK;
 
   // Pass false as the second arg so we can return NS_ERROR_PLUGIN_DISABLED
   // for disabled plug-ins.
   plugin = FindPluginForType(aMimeType, false);
   if (!plugin)
     return NS_ERROR_FAILURE;
 
   if (!plugin->IsEnabled()) {
     if (plugin->HasFlag(NS_PLUGIN_FLAG_BLOCKLISTED))
       return NS_ERROR_PLUGIN_BLOCKLISTED;
     else
       return NS_ERROR_PLUGIN_DISABLED;
   }
 
-  return aShouldPlay ? NS_OK : NS_ERROR_PLUGIN_CLICKTOPLAY;
+  return NS_OK;
 }
 
 // check comma delimitered extensions
 static int CompareExtensions(const char *aExtensionList, const char *aExtension)
 {
   if (!aExtensionList || !aExtension)
     return -1;
 
@@ -1417,31 +1409,22 @@ static int CompareExtensions(const char 
     pComma = strchr(pExt, ',');
   }
 
   // the last one
   return PL_strcasecmp(pExt, aExtension);
 }
 
 nsresult
-nsPluginHost::IsPluginEnabledForExtension(const char* aExtension, const char* &aMimeType)
-{
-  // If plugins.click_to_play is false, plugins should always play
-  return IsPluginEnabledForExtension(aExtension, aMimeType,
-                                     !Preferences::GetBool("plugins.click_to_play", false));
-}
-
-nsresult
 nsPluginHost::IsPluginEnabledForExtension(const char* aExtension,
-                                          const char* &aMimeType,
-                                          bool aShouldPlay)
+                                          const char* &aMimeType)
 {
   nsPluginTag *plugin = FindPluginEnabledForExtension(aExtension, aMimeType);
   if (plugin)
-    return aShouldPlay ? NS_OK : NS_ERROR_PLUGIN_CLICKTOPLAY;
+    return NS_OK;
 
   return NS_ERROR_FAILURE;
 }
 
 class DOMMimeTypeImpl : public nsIDOMMimeType {
 public:
   NS_DECL_ISUPPORTS
 
--- a/dom/plugins/base/nsPluginHost.h
+++ b/dom/plugins/base/nsPluginHost.h
@@ -115,21 +115,18 @@ public:
   nsresult LoadPlugins();
   nsresult InstantiatePluginForChannel(nsIChannel* aChannel,
                                        nsObjectLoadingContent* aContent,
                                        nsIStreamListener** aListener);
   nsresult SetUpPluginInstance(const char *aMimeType,
                                nsIURI *aURL,
                                nsIPluginInstanceOwner *aOwner);
   nsresult IsPluginEnabledForType(const char* aMimeType);
-  nsresult IsPluginEnabledForType(const char* aMimeType,
-                                  bool aShouldPlay);
   nsresult IsPluginEnabledForExtension(const char* aExtension, const char* &aMimeType);
-  nsresult IsPluginEnabledForExtension(const char* aExtension, const char* &aMimeType,
-                                       bool aShouldPlay);
+
   nsresult GetPluginCount(PRUint32* aPluginCount);
   nsresult GetPlugins(PRUint32 aPluginCount, nsIDOMPlugin** aPluginArray);
 
   nsresult GetURL(nsISupports* pluginInst,
                   const char* url,
                   const char* target,
                   nsIPluginStreamListener* streamListener,
                   const char* altHost,
--- a/layout/build/nsContentDLF.cpp
+++ b/layout/build/nsContentDLF.cpp
@@ -305,17 +305,17 @@ nsContentDLF::CreateInstance(const char*
                           aChannel, aLoadGroup,
                           aContainer, kImageDocumentCID,
                           aDocListener, aDocViewer);
   }
 
   nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
   nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
   if(pluginHost &&
-     NS_SUCCEEDED(pluginHost->IsPluginEnabledForType(aContentType, true))) {
+     NS_SUCCEEDED(pluginHost->IsPluginEnabledForType(aContentType))) {
     return CreateDocument(aCommand,
                           aChannel, aLoadGroup,
                           aContainer, kPluginDocumentCID,
                           aDocListener, aDocViewer);
   }
 
   // If we get here, then we weren't able to create anything. Sorry!
   return NS_ERROR_FAILURE;