bug 347736 instantiate <embed> plugins by extension if we don't have a MIME type
authorcbiesinger@gmx.at
Wed, 18 Jul 2007 14:48:18 -0700
changeset 3642 3a702175fcb9c14ca1da0d31d346f531a0d5a4c1
parent 3641 86e94d827c03e3e29f6d0feb385541a42032f36a
child 3643 1299a91e3916580803756cb32d8b38827597efce
push idunknown
push userunknown
push dateunknown
bugs347736
milestone1.9a7pre
bug 347736 instantiate <embed> plugins by extension if we don't have a MIME type r+sr=bz
content/base/src/nsObjectLoadingContent.cpp
--- a/content/base/src/nsObjectLoadingContent.cpp
+++ b/content/base/src/nsObjectLoadingContent.cpp
@@ -32,17 +32,17 @@
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 /*
- * A base class implementING nsIObjectLoadingContent for use by
+ * A base class implementing nsIObjectLoadingContent for use by
  * various content nodes that want to provide plugin/document/image
  * loading functionality (eg <embed>, <object>, <applet>, etc).
  */
 
 // Interface headers
 #include "imgILoader.h"
 #include "nsIContent.h"
 #include "nsIDocShell.h"
@@ -283,16 +283,53 @@ IsSupportedPlugin(const nsCString& aMIME
   if (!host) {
     return PR_FALSE;
   }
   nsresult rv = host->IsPluginEnabledForType(aMIMEType.get());
   // XXX do plugins expect to work via extension too?
   return NS_SUCCEEDED(rv);
 }
 
+static void
+GetExtensionFromURI(nsIURI* uri, nsCString& ext)
+{
+  nsCOMPtr<nsIURL> url(do_QueryInterface(uri));
+  if (url) {
+    url->GetFileExtension(ext);
+  } else {
+    nsCString spec;
+    uri->GetSpec(spec);
+
+    PRInt32 offset = spec.RFindChar('.');
+    if (offset != kNotFound) {
+      ext = Substring(spec, offset + 1, spec.Length());
+    }
+  }
+}
+
+/**
+ * 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 PRBool
+IsPluginEnabledByExtension(nsIURI* uri, nsCString& mimeType)
+{
+  nsCAutoString ext;
+  GetExtensionFromURI(uri, ext);
+
+  nsCOMPtr<nsIPluginHost> host(do_GetService("@mozilla.org/plugin/host;1"));
+  const char* typeFromExt;
+  if (host &&
+      NS_SUCCEEDED(host->IsPluginEnabledForExtension(ext.get(), typeFromExt))) {
+    mimeType = typeFromExt;
+    return PR_TRUE;
+  }
+  return PR_FALSE;
+}
+
 nsObjectLoadingContent::nsObjectLoadingContent()
   : mPendingInstantiateEvent(nsnull)
   , mChannel(nsnull)
   , mType(eType_Loading)
   , mInstantiating(PR_FALSE)
   , mUserDisabled(PR_FALSE)
   , mSuppressed(PR_FALSE)
   , mTypeUnsupported(PR_FALSE)
@@ -853,18 +890,30 @@ nsObjectLoadingContent::LoadObject(nsIUR
   nsresult rv = NS_ERROR_UNEXPECTED;
   // This fallback variable MUST be declared after the notifier variable. Do NOT
   // change the order of the declarations!
   AutoFallback fallback(this, &rv);
 
   PRUint32 caps = GetCapabilities();
   LOG(("OBJLC [%p]: Capabilities: %04x\n", this, caps));
 
-  if ((caps & eOverrideServerType) && !aTypeHint.IsEmpty()) {
-    ObjectType newType = GetTypeOfContent(aTypeHint);
+  nsCAutoString overrideType;
+  if ((caps & eOverrideServerType) &&
+      (!aTypeHint.IsEmpty() ||
+       (aURI && IsPluginEnabledByExtension(aURI, overrideType)))) {
+    NS_ASSERTION(aTypeHint.IsEmpty() ^ overrideType.IsEmpty(),
+                 "Exactly one of aTypeHint and overrideType should be empty!");
+
+    ObjectType newType;
+    if (overrideType.IsEmpty()) {
+      newType = GetTypeOfContent(aTypeHint);
+    } else {
+      newType = eType_Plugin;
+    }
+
     if (newType != mType) {
       LOG(("OBJLC [%p]: (eOverrideServerType) Changing type from %u to %u\n", this, mType, newType));
 
       UnloadContent();
 
       // Must have a frameloader before creating a frame, or the frame will
       // create its own.
       if (!mFrameLoader && newType == eType_Document) {
@@ -1361,37 +1410,17 @@ nsObjectLoadingContent::Instantiate(cons
   nsIObjectFrame* frame = GetFrame();
   if (!frame) {
     LOG(("OBJLC [%p]: Attempted to instantiate, but have no frame\n", this));
     return NS_OK; // Not a failure to have no frame
   }
 
   nsCString typeToUse(aMIMEType);
   if (typeToUse.IsEmpty() && aURI) {
-    nsCAutoString ext;
-    
-    nsCOMPtr<nsIURL> url(do_QueryInterface(aURI));
-    if (url) {
-      url->GetFileExtension(ext);
-    } else {
-      nsCString spec;
-      aURI->GetSpec(spec);
-
-      PRInt32 offset = spec.RFindChar('.');
-      if (offset != kNotFound) {
-        ext = Substring(spec, offset + 1, spec.Length());
-      }
-    }
-
-    nsCOMPtr<nsIPluginHost> host(do_GetService("@mozilla.org/plugin/host;1"));
-    const char* typeFromExt;
-    if (host &&
-        NS_SUCCEEDED(host->IsPluginEnabledForExtension(ext.get(), typeFromExt))) {
-      typeToUse = typeFromExt;
-    }
+    IsPluginEnabledByExtension(aURI, typeToUse);
   }
 
   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...
     nsCOMPtr<nsIContent> thisContent = 
       do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));