Bug 998863: Asynchronous Plugin Initialization, Part 10: PluginInstanceParent changes; r=jimm
authorAaron Klotz <aklotz@mozilla.com>
Mon, 29 Dec 2014 16:14:03 -0700
changeset 247413 ce5bf5f8493215a05e63c596f95ca78c3fd157cd
parent 247412 8a4c2bf5ec09977e94cc055267c0bc6280914966
child 247414 8534359e8965a3ca4855e49afd10df0f701089a9
push id4489
push userraliiev@mozilla.com
push dateMon, 23 Feb 2015 15:17:55 +0000
treeherdermozilla-beta@fd7c3dc24146 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjimm
bugs998863
milestone37.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 998863: Asynchronous Plugin Initialization, Part 10: PluginInstanceParent changes; r=jimm
dom/plugins/ipc/PluginInstanceParent.cpp
dom/plugins/ipc/PluginInstanceParent.h
--- a/dom/plugins/ipc/PluginInstanceParent.cpp
+++ b/dom/plugins/ipc/PluginInstanceParent.cpp
@@ -5,27 +5,29 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/DebugOnly.h"
 #include <stdint.h> // for intptr_t
 
 #include "mozilla/Telemetry.h"
 #include "PluginInstanceParent.h"
 #include "BrowserStreamParent.h"
+#include "PluginAsyncSurrogate.h"
 #include "PluginBackgroundDestroyer.h"
 #include "PluginModuleParent.h"
 #include "PluginStreamParent.h"
 #include "StreamNotifyParent.h"
 #include "npfunctions.h"
 #include "nsAutoPtr.h"
 #include "gfxASurface.h"
 #include "gfxContext.h"
 #include "gfxPlatform.h"
 #include "gfxSharedImageSurface.h"
 #include "nsNPAPIPluginInstance.h"
+#include "nsPluginInstanceOwner.h"
 #ifdef MOZ_X11
 #include "gfxXlibSurface.h"
 #endif
 #include "gfxContext.h"
 #include "gfxColor.h"
 #include "gfxUtils.h"
 #include "mozilla/gfx/2D.h"
 #include "Layers.h"
@@ -70,17 +72,19 @@ StreamNotifyParent::RecvRedirectNotifyRe
   instance->mNPNIface->urlredirectresponse(instance->mNPP, this, static_cast<NPBool>(allow));
   return true;
 }
 
 PluginInstanceParent::PluginInstanceParent(PluginModuleParent* parent,
                                            NPP npp,
                                            const nsCString& aMimeType,
                                            const NPNetscapeFuncs* npniface)
-  : mParent(parent)
+    : mParent(parent)
+    , mSurrogate(PluginAsyncSurrogate::Cast(npp))
+    , mUseSurrogate(true)
     , mNPP(npp)
     , mNPNIface(npniface)
     , mWindowType(NPWindowTypeWindow)
     , mDrawingModel(kDefaultDrawingModel)
 #if defined(OS_WIN)
     , mPluginHWND(nullptr)
     , mPluginWndProc(nullptr)
     , mNestedEventState(false)
@@ -774,16 +778,22 @@ PluginInstanceParent::EndUpdateBackgroun
     XSync(DefaultXDisplay(), False);
 #endif
 
     unused << SendUpdateBackground(BackgroundDescriptor(), aRect);
 
     return NS_OK;
 }
 
+PluginAsyncSurrogate*
+PluginInstanceParent::GetAsyncSurrogate()
+{
+    return mSurrogate;
+}
+
 bool
 PluginInstanceParent::CreateBackground(const nsIntSize& aSize)
 {
     NS_ABORT_IF_FALSE(!mBackground, "Already have a background");
 
     // XXX refactor me
 
 #if defined(MOZ_X11)
@@ -1300,35 +1310,47 @@ NPError
 PluginInstanceParent::NPP_NewStream(NPMIMEType type, NPStream* stream,
                                     NPBool seekable, uint16_t* stype)
 {
     PLUGIN_LOG_DEBUG(("%s (type=%s, stream=%p, seekable=%i)",
                       FULLFUNCTION, (char*) type, (void*) stream, (int) seekable));
 
     BrowserStreamParent* bs = new BrowserStreamParent(this, stream);
 
-    NPError err;
-    {   // Scope for timer
-        Telemetry::AutoTimer<Telemetry::BLOCKED_ON_PLUGIN_STREAM_INIT_MS>
-            timer(Module()->GetHistogramKey());
-        if (!CallPBrowserStreamConstructor(bs,
-                                           NullableString(stream->url),
-                                           stream->end,
-                                           stream->lastmodified,
-                                           static_cast<PStreamNotifyParent*>(stream->notifyData),
-                                           NullableString(stream->headers),
-                                           NullableString(type), seekable,
-                                           &err, stype)) {
-            return NPERR_GENERIC_ERROR;
+    if (!SendPBrowserStreamConstructor(bs,
+                                       NullableString(stream->url),
+                                       stream->end,
+                                       stream->lastmodified,
+                                       static_cast<PStreamNotifyParent*>(stream->notifyData),
+                                       NullableString(stream->headers))) {
+        return NPERR_GENERIC_ERROR;
+    }
+
+    Telemetry::AutoTimer<Telemetry::BLOCKED_ON_PLUGIN_STREAM_INIT_MS>
+        timer(Module()->GetHistogramKey());
+
+    NPError err = NPERR_NO_ERROR;
+    if (mParent->IsStartingAsync()) {
+        MOZ_ASSERT(mSurrogate);
+        mSurrogate->AsyncCallDeparting();
+        if (SendAsyncNPP_NewStream(bs, NullableString(type), seekable)) {
+            *stype = UINT16_MAX;
+        } else {
+            err = NPERR_GENERIC_ERROR;
+        }
+    } else {
+        bs->SetAlive();
+        if (!CallNPP_NewStream(bs, NullableString(type), seekable, &err, stype)) {
+            err = NPERR_GENERIC_ERROR;
+        }
+        if (NPERR_NO_ERROR != err) {
+            unused << PBrowserStreamParent::Send__delete__(bs);
         }
     }
 
-    if (NPERR_NO_ERROR != err)
-        unused << PBrowserStreamParent::Send__delete__(bs);
-
     return err;
 }
 
 NPError
 PluginInstanceParent::NPP_DestroyStream(NPStream* stream, NPReason reason)
 {
     PLUGIN_LOG_DEBUG(("%s (stream=%p, reason=%i)",
                       FULLFUNCTION, (void*) stream, (int) reason));
@@ -1627,16 +1649,59 @@ PluginInstanceParent::RecvNegotiatedCarb
     nsNPAPIPluginInstance *inst = static_cast<nsNPAPIPluginInstance*>(mNPP->ndata);
     if (!inst) {
         return false;
     }
     inst->CarbonNPAPIFailure();
     return true;
 }
 
+nsPluginInstanceOwner*
+PluginInstanceParent::GetOwner()
+{
+    nsNPAPIPluginInstance* inst = static_cast<nsNPAPIPluginInstance*>(mNPP->ndata);
+    if (!inst) {
+        return nullptr;
+    }
+    return inst->GetOwner();
+}
+
+bool
+PluginInstanceParent::RecvAsyncNPP_NewResult(const NPError& aResult)
+{
+    // NB: mUseSurrogate must be cleared before doing anything else, especially
+    //     calling NPP_SetWindow!
+    mUseSurrogate = false;
+
+    mSurrogate->AsyncCallArriving();
+    if (aResult == NPERR_NO_ERROR) {
+        mSurrogate->SetAcceptingCalls(true);
+    }
+
+    nsPluginInstanceOwner* owner = GetOwner();
+    if (!owner) {
+        // This is possible in async plugin land; the instance may outlive
+        // the owner
+        return true;
+    }
+
+    if (aResult != NPERR_NO_ERROR) {
+        owner->NotifyHostAsyncInitFailed();
+        return true;
+    }
+
+    // Now we need to do a bunch of exciting post-NPP_New housekeeping.
+    owner->NotifyHostCreateWidget();
+
+    MOZ_ASSERT(mSurrogate);
+    mSurrogate->OnInstanceCreated(this);
+
+    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
@@ -1866,8 +1931,34 @@ PluginInstanceParent::AnswerPluginFocusC
       ::SendMessage(mPluginHWND, gOOPPPluginFocusEvent, gotFocus ? 1 : 0, 0);
     }
     return true;
 #else
     NS_NOTREACHED("PluginInstanceParent::AnswerPluginFocusChange not implemented!");
     return false;
 #endif
 }
+
+PluginInstanceParent*
+PluginInstanceParent::Cast(NPP aInstance, PluginAsyncSurrogate** aSurrogate)
+{
+    PluginDataResolver* resolver =
+        static_cast<PluginDataResolver*>(aInstance->pdata);
+
+    // If the plugin crashed and the PluginInstanceParent was deleted,
+    // aInstance->pdata will be nullptr.
+    if (!resolver) {
+        return nullptr;
+    }
+
+    PluginInstanceParent* instancePtr = resolver->GetInstance();
+
+    if (instancePtr && aInstance != instancePtr->mNPP) {
+        NS_RUNTIMEABORT("Corrupted plugin data.");
+    }
+
+    if (aSurrogate) {
+        *aSurrogate = resolver->GetAsyncSurrogate();
+    }
+
+    return instancePtr;
+}
+
--- a/dom/plugins/ipc/PluginInstanceParent.h
+++ b/dom/plugins/ipc/PluginInstanceParent.h
@@ -17,36 +17,39 @@
 #include "mozilla/gfx/QuartzSupport.h"
 #endif
 
 #include "npfunctions.h"
 #include "nsAutoPtr.h"
 #include "nsDataHashtable.h"
 #include "nsHashKeys.h"
 #include "nsRect.h"
+#include "PluginDataResolver.h"
 
 #ifdef MOZ_X11
 class gfxXlibSurface;
 #endif
 #include "mozilla/unused.h"
 
 class gfxASurface;
 class gfxContext;
+class nsPluginInstanceOwner;
 
 namespace mozilla {
 namespace layers {
 class ImageContainer;
 class CompositionNotifySink;
 }
 namespace plugins {
 
 class PBrowserStreamParent;
 class PluginModuleParent;
 
 class PluginInstanceParent : public PPluginInstanceParent
+                           , public PluginDataResolver
 {
     friend class PluginModuleParent;
     friend class BrowserStreamParent;
     friend class PluginStreamParent;
     friend class StreamNotifyParent;
 
 public:
     PluginInstanceParent(PluginModuleParent* parent,
@@ -69,18 +72,17 @@ public:
 
     virtual bool
     DeallocPPluginScriptableObjectParent(PPluginScriptableObjectParent* aObject) MOZ_OVERRIDE;
     virtual PBrowserStreamParent*
     AllocPBrowserStreamParent(const nsCString& url,
                               const uint32_t& length,
                               const uint32_t& lastmodified,
                               PStreamNotifyParent* notifyData,
-                              const nsCString& headers)
-                              MOZ_OVERRIDE;
+                              const nsCString& headers) MOZ_OVERRIDE;
     virtual bool
     DeallocPBrowserStreamParent(PBrowserStreamParent* stream) MOZ_OVERRIDE;
 
     virtual PPluginStreamParent*
     AllocPPluginStreamParent(const nsCString& mimeType,
                              const nsCString& target,
                              NPError* result) MOZ_OVERRIDE;
     virtual bool
@@ -202,16 +204,19 @@ public:
                            bool *result) MOZ_OVERRIDE;
 
     virtual bool
     RecvRedrawPlugin() MOZ_OVERRIDE;
 
     virtual bool
     RecvNegotiatedCarbon() MOZ_OVERRIDE;
 
+    virtual bool
+    RecvAsyncNPP_NewResult(const NPError& aResult) MOZ_OVERRIDE;
+
     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);
 
@@ -246,16 +251,22 @@ public:
     GetActorForNPObject(NPObject* aObject);
 
     NPP
     GetNPP()
     {
       return mNPP;
     }
 
+    bool
+    UseSurrogate() const
+    {
+        return mUseSurrogate;
+    }
+
     virtual bool
     AnswerPluginFocusChange(const bool& gotFocus) MOZ_OVERRIDE;
 
     nsresult AsyncSetWindow(NPWindow* window);
     nsresult GetImageContainer(mozilla::layers::ImageContainer** aContainer);
     nsresult GetImageSize(nsIntSize* aSize);
 #ifdef XP_MACOSX
     nsresult IsRemoteDrawingCoreAnimation(bool *aDrawing);
@@ -263,16 +274,23 @@ public:
 #endif
     nsresult SetBackgroundUnknown();
     nsresult BeginUpdateBackground(const nsIntRect& aRect,
                                    gfxContext** aCtx);
     nsresult EndUpdateBackground(gfxContext* aCtx,
                                  const nsIntRect& aRect);
     void DidComposite() { unused << SendNPP_DidComposite(); }
 
+    virtual PluginAsyncSurrogate* GetAsyncSurrogate();
+
+    virtual PluginInstanceParent* GetInstance() { return this; }
+
+    static PluginInstanceParent* Cast(NPP instance,
+                                      PluginAsyncSurrogate** aSurrogate = nullptr);
+
 private:
     // Create an appropriate platform surface for a background of size
     // |aSize|.  Return true if successful.
     bool CreateBackground(const nsIntSize& aSize);
     void DestroyBackground();
     SurfaceDescriptor BackgroundDescriptor() /*const*/;
 
     typedef mozilla::layers::ImageContainer ImageContainer;
@@ -283,18 +301,22 @@ private:
 
     virtual bool
     DeallocPPluginBackgroundDestroyerParent(PPluginBackgroundDestroyerParent* aActor) MOZ_OVERRIDE;
 
     bool InternalGetValueForNPObject(NPNVariable aVariable,
                                      PPluginScriptableObjectParent** aValue,
                                      NPError* aResult);
 
+    nsPluginInstanceOwner* GetOwner();
+
 private:
     PluginModuleParent* mParent;
+    nsRefPtr<PluginAsyncSurrogate> mSurrogate;
+    bool mUseSurrogate;
     NPP mNPP;
     const NPNetscapeFuncs* mNPNIface;
     NPWindowType mWindowType;
     int16_t            mDrawingModel;
     nsAutoPtr<mozilla::layers::CompositionNotifySink> mNotifySink;
 
     nsDataHashtable<nsPtrHashKey<NPObject>, PluginScriptableObjectParent*> mScriptableObjects;