Bug 629401: Carbon plugins that cannot load in X64 Mac should send an event or notifyObservers of failure. r=BenWa, a=blocks-betaN
authorJosh Aas <joshmoz@gmail.com>
Thu, 03 Feb 2011 09:31:01 -0800
changeset 61864 69f3807d4bb498a6bc9ffedbc8e2a02b7e92425b
parent 61863 4b90fd0c1c4d249436d38b6a07a7e77e1fb79c90
child 61865 9c815db836e360e9ca4fa4c6f54f31852e13f004
push idunknown
push userunknown
push dateunknown
reviewersBenWa, blocks-betaN
bugs629401
milestone2.0b12pre
Bug 629401: Carbon plugins that cannot load in X64 Mac should send an event or notifyObservers of failure. r=BenWa, a=blocks-betaN
dom/plugins/PPluginInstance.ipdl
dom/plugins/PluginInstanceParent.cpp
dom/plugins/PluginInstanceParent.h
dom/plugins/PluginModuleChild.cpp
modules/plugin/base/src/nsNPAPIPluginInstance.cpp
modules/plugin/base/src/nsNPAPIPluginInstance.h
--- a/dom/plugins/PPluginInstance.ipdl
+++ b/dom/plugins/PPluginInstance.ipdl
@@ -199,16 +199,21 @@ parent:
                                 int32_t port, nsCString scheme,
                                 nsCString realm)
     returns (nsCString username, nsCString password, NPError result);
 
   rpc NPN_ConvertPoint(double sourceX, bool ignoreDestX, double sourceY, bool ignoreDestY, NPCoordinateSpace sourceSpace,
                        NPCoordinateSpace destSpace)
     returns (double destX, double destY, bool result);
 
+  // Send notification that a plugin tried to negotiate Carbon NPAPI so that
+  // users can be notified that restarting the browser in i386 mode may allow
+  // them to use the plugin.
+  sync NegotiatedCarbon();
+
 both:
   async PPluginScriptableObject();
 
 child:
   /* NPP_NewStream */
   rpc PBrowserStream(nsCString url,
                      uint32_t length,
                      uint32_t lastmodified,
--- a/dom/plugins/PluginInstanceParent.cpp
+++ b/dom/plugins/PluginInstanceParent.cpp
@@ -51,16 +51,17 @@
 #include "gfxPlatform.h"
 #include "gfxSharedImageSurface.h"
 #ifdef MOZ_X11
 #include "gfxXlibSurface.h"
 #endif
 #include "gfxContext.h"
 #include "gfxColor.h"
 #include "gfxUtils.h"
+#include "nsNPAPIPluginInstance.h"
 
 #if defined(OS_WIN)
 #include <windowsx.h>
 #include "mozilla/plugins/PluginSurfaceParent.h"
 
 // Plugin focus event for widget.
 extern const PRUnichar* kOOPPPluginFocusEventId;
 UINT gOOPPPluginFocusEvent =
@@ -1236,16 +1237,27 @@ PluginInstanceParent::AnswerNPN_ConvertP
     *result = mNPNIface->convertpoint(mNPP, sourceX, sourceY, sourceSpace,
                                       ignoreDestX ? nsnull : destX,
                                       ignoreDestY ? nsnull : destY,
                                       destSpace);
 
     return true;
 }
 
+bool
+PluginInstanceParent::RecvNegotiatedCarbon()
+{
+  nsNPAPIPluginInstance *inst = static_cast<nsNPAPIPluginInstance*>(mNPP->ndata);
+  if (!inst) {
+    return false;
+  }
+  inst->CarbonNPAPIFailure();
+  return true;
+}
+
 #if defined(OS_WIN)
 
 /*
   plugin focus changes between processes
 
   focus from dom -> child:
     Focus manager calls on widget to set the focus on the window.
     We pick up the resulting wm_setfocus event here, and forward
--- a/dom/plugins/PluginInstanceParent.h
+++ b/dom/plugins/PluginInstanceParent.h
@@ -216,16 +216,19 @@ public:
                            const double& sourceY,
                            const bool&   ignoreDestY,
                            const NPCoordinateSpace& sourceSpace,
                            const NPCoordinateSpace& destSpace,
                            double *destX,
                            double *destY,
                            bool *result);
 
+    NS_OVERRIDE virtual bool
+    RecvNegotiatedCarbon();
+
     NPError NPP_SetWindow(const NPWindow* aWindow);
 
     NPError NPP_GetValue(NPPVariable variable, void* retval);
     NPError NPP_SetValue(NPNVariable variable, void* value);
 
     void NPP_URLRedirectNotify(const char* url, int32_t status,
                                void* notifyData);
 
--- a/dom/plugins/PluginModuleChild.cpp
+++ b/dom/plugins/PluginModuleChild.cpp
@@ -1879,17 +1879,23 @@ PluginModuleChild::AnswerPPluginInstance
 
 #if defined(XP_MACOSX) && defined(__i386__)
     // If an i386 Mac OS X plugin has selected the Carbon event model then
     // we have to fail. We do not support putting Carbon event model plugins
     // out of process. Note that Carbon is the default model so out of process
     // plugins need to actively negotiate something else in order to work
     // out of process.
     if (childInstance->EventModel() == NPEventModelCarbon) {
-        *rv = NPERR_MODULE_LOAD_FAILED_ERROR;
+      // Send notification that a plugin tried to negotiate Carbon NPAPI so that
+      // users can be notified that restarting the browser in i386 mode may allow
+      // them to use the plugin.
+      childInstance->SendNegotiatedCarbon();
+
+      // Fail to instantiate.
+      *rv = NPERR_MODULE_LOAD_FAILED_ERROR;
     }
 #endif
 
     return true;
 }
 
 bool
 PluginModuleChild::DeallocPPluginInstance(PPluginInstanceChild* aActor)
--- a/modules/plugin/base/src/nsNPAPIPluginInstance.cpp
+++ b/modules/plugin/base/src/nsNPAPIPluginInstance.cpp
@@ -44,16 +44,17 @@
 
 #include "nsNPAPIPluginInstance.h"
 #include "nsNPAPIPlugin.h"
 #include "nsNPAPIPluginStreamListener.h"
 #include "nsPluginHost.h"
 #include "nsPluginSafety.h"
 #include "nsPluginLogging.h"
 #include "nsIPrivateBrowsingService.h"
+#include "nsContentUtils.h"
 
 #include "nsIDocument.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIScriptContext.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsJSNPRuntime.h"
 #include "nsPluginStreamListenerPeer.h"
 
@@ -1249,8 +1250,51 @@ nsNPAPIPluginInstance::URLRedirectRespon
   PRUint32 listenerCount = mStreamListeners.Length();
   for (PRUint32 i = 0; i < listenerCount; i++) {
     nsNPAPIPluginStreamListener* currentListener = mStreamListeners[i];
     if (currentListener->GetNotifyData() == notifyData) {
       currentListener->URLRedirectResponse(allow);
     }
   }
 }
+
+class CarbonEventModelFailureEvent : public nsRunnable {
+public:
+  nsCOMPtr<nsIContent> mContent;
+
+  CarbonEventModelFailureEvent(nsIContent* aContent)
+    : mContent(aContent)
+  {}
+
+  ~CarbonEventModelFailureEvent() {}
+
+  NS_IMETHOD Run();
+};
+
+NS_IMETHODIMP
+CarbonEventModelFailureEvent::Run()
+{
+  nsString type = NS_LITERAL_STRING("npapi-carbon-event-model-failure");
+  nsContentUtils::DispatchTrustedEvent(mContent->GetDocument(), mContent,
+                                       type, PR_TRUE, PR_TRUE);
+  return NS_OK;
+}
+
+void
+nsNPAPIPluginInstance::CarbonNPAPIFailure()
+{
+  nsCOMPtr<nsIDOMElement> element;
+  GetDOMElement(getter_AddRefs(element));
+  if (!element) {
+    return;
+  }
+
+  nsCOMPtr<nsIContent> content(do_QueryInterface(element));
+  if (!content) {
+    return;
+  }
+
+  nsCOMPtr<nsIRunnable> e = new CarbonEventModelFailureEvent(content);
+  nsresult rv = NS_DispatchToCurrentThread(e);
+  if (NS_FAILED(rv)) {
+    NS_WARNING("Failed to dispatch CarbonEventModelFailureEvent.");
+  }
+}
--- a/modules/plugin/base/src/nsNPAPIPluginInstance.h
+++ b/modules/plugin/base/src/nsNPAPIPluginInstance.h
@@ -141,16 +141,20 @@ public:
   nsTArray<nsNPAPIPluginStreamListener*> *StreamListeners();
 
   nsTArray<nsPluginStreamListenerPeer*> *FileCachedStreamListeners();
 
   nsresult AsyncSetWindow(NPWindow& window);
 
   void URLRedirectResponse(void* notifyData, NPBool allow);
 
+  // Called when the instance fails to instantiate beceause the Carbon
+  // event model is not supported.
+  void CarbonNPAPIFailure();
+
 protected:
   nsresult InitializePlugin();
 
   nsresult GetTagType(nsPluginTagType *result);
   nsresult GetAttributes(PRUint16& n, const char*const*& names,
                          const char*const*& values);
   nsresult GetParameters(PRUint16& n, const char*const*& names,
                          const char*const*& values);