Bug 1132874 - Simplify PPluginWidget protocol handling, and avoid sending async messages from the parent. Addresses a problem with sub protocols that are torn down randomly from either side of the connection. r=aklotz
authorJim Mathies <jmathies@mozilla.com>
Tue, 07 Apr 2015 08:17:27 -0500
changeset 267839 24bb85e9dced4e8d8b33c2e1e48649ea1ffbc9a2
parent 267838 aa38fd43c148a52554ff6b904649d4b9534623a9
child 267840 119d3c0fd0f60076f0a1014e9db1dc7ba63b1b9e
push id4830
push userjlund@mozilla.com
push dateMon, 29 Jun 2015 20:18:48 +0000
treeherdermozilla-beta@4c2175bb0420 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersaklotz
bugs1132874
milestone40.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 1132874 - Simplify PPluginWidget protocol handling, and avoid sending async messages from the parent. Addresses a problem with sub protocols that are torn down randomly from either side of the connection. r=aklotz
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/PContent.ipdl
dom/ipc/PPluginWidget.ipdl
dom/ipc/TabChild.h
dom/plugins/ipc/PluginWidgetChild.cpp
dom/plugins/ipc/PluginWidgetChild.h
dom/plugins/ipc/PluginWidgetParent.cpp
dom/plugins/ipc/PluginWidgetParent.h
widget/PluginWidgetProxy.cpp
widget/windows/nsWindowGfx.cpp
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -44,16 +44,17 @@
 #include "mozilla/ipc/GeckoChildProcessHost.h"
 #include "mozilla/ipc/TestShellChild.h"
 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
 #include "mozilla/layers/CompositorChild.h"
 #include "mozilla/layers/ImageBridgeChild.h"
 #include "mozilla/layers/PCompositorChild.h"
 #include "mozilla/layers/SharedBufferManagerChild.h"
 #include "mozilla/net/NeckoChild.h"
+#include "mozilla/plugins/PluginInstanceParent.h"
 #include "mozilla/plugins/PluginModuleParent.h"
 
 #if defined(MOZ_CONTENT_SANDBOX)
 #if defined(XP_WIN)
 #define TARGET_SANDBOX_EXPORTS
 #include "mozilla/sandboxTarget.h"
 #elif defined(XP_LINUX)
 #include "mozilla/Sandbox.h"
@@ -2667,16 +2668,36 @@ ContentChild::GetBrowserOrId(TabChild* a
         this == aTabChild->Manager()) {
         return PBrowserOrId(aTabChild);
     }
     else {
         return PBrowserOrId(aTabChild->GetTabId());
     }
 }
 
+bool
+ContentChild::RecvUpdateWindow(const uintptr_t& aChildId)
+{
+#if defined(XP_WIN)
+  NS_ASSERTION(aChildId, "Expected child hwnd value for remote plugin instance.");
+  mozilla::plugins::PluginInstanceParent* parentInstance =
+    mozilla::plugins::PluginInstanceParent::LookupPluginInstanceByID(aChildId);
+  NS_ASSERTION(parentInstance, "Expected matching plugin instance");
+  if (parentInstance) {
+    // sync! update call to the plugin instance that forces the
+    // plugin to paint its child window.
+    parentInstance->CallUpdateWindow();
+  }
+  return true;
+#else
+  NS_NOTREACHED("ContentChild::RecvUpdateWindow calls unexpected on this platform.");
+  return false;
+#endif
+}
+
 // This code goes here rather than nsGlobalWindow.cpp because nsGlobalWindow.cpp
 // can't include ContentChild.h since it includes windows.h.
 
 static uint64_t gNextWindowID = 0;
 
 // We use only 53 bits for the window ID so that it can be converted to and from
 // a JS value without loss of precision. The upper bits of the window ID hold the
 // process ID. The lower bits identify the window.
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -379,16 +379,17 @@ public:
                                         const nsString& aData) override;
 
     virtual bool RecvOnAppThemeChanged() override;
 
     virtual bool RecvAssociatePluginId(const uint32_t& aPluginId,
                                        const base::ProcessId& aProcessId) override;
     virtual bool RecvLoadPluginResult(const uint32_t& aPluginId,
                                       const bool& aResult) override;
+    virtual bool RecvUpdateWindow(const uintptr_t& aChildId) override;
 
     virtual bool RecvStartProfiler(const uint32_t& aEntries,
                                    const double& aInterval,
                                    nsTArray<nsCString>&& aFeatures,
                                    nsTArray<nsCString>&& aThreadNameFilters) override;
     virtual bool RecvStopProfiler() override;
     virtual bool RecvGetProfile(nsCString* aProfile) override;
     virtual bool RecvDomainSetChanged(const uint32_t& aSetType, const uint32_t& aChangeType,
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -869,16 +869,37 @@ ContentParent::GetInitialProcessPriority
         return PROCESS_PRIORITY_FOREGROUND;
     }
 
     return browserFrame->GetIsExpectingSystemMessage() ?
                PROCESS_PRIORITY_FOREGROUND_HIGH :
                PROCESS_PRIORITY_FOREGROUND;
 }
 
+#if defined(XP_WIN)
+extern const wchar_t* kPluginWidgetContentParentProperty;
+
+/*static*/ void
+ContentParent::SendAsyncUpdate(nsIWidget* aWidget)
+{
+  if (!aWidget || aWidget->Destroyed()) {
+    return;
+  }
+  printf_stderr("TabParent::SendAsyncUpdate()\n");
+  // Fire off an async request to the plugin to paint its window
+  HWND hwnd = (HWND)aWidget->GetNativeData(NS_NATIVE_WINDOW);
+  NS_ASSERTION(hwnd, "Expected valid hwnd value.");
+  ContentParent* cp = reinterpret_cast<ContentParent*>(
+    ::GetPropW(hwnd, kPluginWidgetContentParentProperty));
+  if (cp && !cp->IsDestroyed()) {
+    cp->SendUpdateWindow((uintptr_t)hwnd);
+  }
+}
+#endif // defined(XP_WIN)
+
 bool
 ContentParent::PreallocatedProcessReady()
 {
 #ifdef MOZ_NUWA_PROCESS
     return PreallocatedProcessManager::PreallocatedProcessReady();
 #else
     return true;
 #endif
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -30,16 +30,17 @@
 class mozIApplication;
 class nsConsoleService;
 class nsICycleCollectorLogSink;
 class nsIDOMBlob;
 class nsIDumpGCAndCCLogsCallback;
 class nsIMemoryReporter;
 class nsITimer;
 class ParentIdleListener;
+class nsIWidget;
 
 namespace mozilla {
 class PRemoteSpellcheckEngineParent;
 
 namespace ipc {
 class OptionalURIParams;
 class PFileDescriptorSetParent;
 class URIParams;
@@ -139,16 +140,30 @@ public:
 
     static void GetAll(nsTArray<ContentParent*>& aArray);
     static void GetAllEvenIfDead(nsTArray<ContentParent*>& aArray);
 
     static bool IgnoreIPCPrincipal();
 
     static void NotifyUpdatedDictionaries();
 
+#if defined(XP_WIN)
+    /**
+     * Windows helper for firing off an update window request to a plugin
+     * instance.
+     *
+     * aWidget - the eWindowType_plugin_ipc_chrome widget associated with
+     *           this plugin window.
+     */
+    static void SendAsyncUpdate(nsIWidget* aWidget);
+#endif
+
+    // Let managees query if it is safe to send messages.
+    bool IsDestroyed() { return !mIPCOpen; }
+
     virtual bool RecvCreateChildProcess(const IPCTabContext& aContext,
                                         const hal::ProcessPriority& aPriority,
                                         const TabId& aOpenerTabId,
                                         ContentParentId* aCpId,
                                         bool* aIsForApp,
                                         bool* aIsForBrowser,
                                         TabId* aTabId) override;
     virtual bool RecvBridgeToChildProcess(const ContentParentId& aCpId) override;
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -577,16 +577,22 @@ child:
     /**
      * Notify the child to shutdown. The child will in turn call FinishShutdown
      * and let the parent close the channel.
      */
     async Shutdown();
 
     async LoadProcessScript(nsString url);
 
+    /**
+     * Requests a full native update of a native plugin child window. This is
+     * a Windows specific call.
+     */
+    async UpdateWindow(uintptr_t aChildId);
+
 parent:
     /**
      * Tell the parent process a new accessible document has been created.
      * aParentDoc is the accessible document it was created in if any, and
      * aParentAcc is the id of the accessible in that document the new document
      * is a child of.
      */
     PDocAccessible(nullable PDocAccessible aParentDoc, uint64_t aParentAcc);
--- a/dom/ipc/PPluginWidget.ipdl
+++ b/dom/ipc/PPluginWidget.ipdl
@@ -26,38 +26,22 @@ namespace plugins {
  * be torn down first by the tab, followed by the deref'ing of the nsIWidget
  * via layout.
  */
 sync protocol PPluginWidget {
   manager PBrowser;
 
 parent:
   async __delete__();
-
-parent:
   sync Create() returns (nsresult aResult);
-
-  async Destroy();
   async SetFocus(bool aRaise);
 
   /**
    * Returns NS_NATIVE_PLUGIN_PORT and its variants: a sharable native
    * window for plugins. On Linux, this returns an XID for a socket widget
    * embedded in the chrome side native window. On Windows this returns the
    * native HWND of the plugin widget.
    */
   sync GetNativePluginPort() returns (uintptr_t value);
-
-child:
-  /**
-   * Event indicating the parent is shutting down.
-   * aWhichSide - indicates which side intititated the shutdown.
-   */
-  async ParentShutdown(uint16_t aWhichSide);
-
-  /**
-   * Requests a full update of the plugin window.
-   */
-  async UpdateWindow(uintptr_t aChildId);
 };
 
 }
 }
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -262,17 +262,18 @@ public:
     static void PreloadSlowThings();
     static void PostForkPreload();
 
     /** Return a TabChild with the given attributes. */
     static already_AddRefed<TabChild>
     Create(nsIContentChild* aManager, const TabId& aTabId, const TabContext& aContext, uint32_t aChromeFlags);
 
     bool IsRootContentDocument();
-
+    // Let managees query if it is safe to send messages.
+    bool IsDestroyed() { return mDestroyed; }
     const TabId GetTabId() const {
       MOZ_ASSERT(mUniqueId != 0);
       return mUniqueId;
     }
 
     NS_DECL_ISUPPORTS_INHERITED
     NS_DECL_NSIWEBBROWSERCHROME
     NS_DECL_NSIWEBBROWSERCHROME2
--- a/dom/plugins/ipc/PluginWidgetChild.cpp
+++ b/dom/plugins/ipc/PluginWidgetChild.cpp
@@ -1,94 +1,67 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/plugins/PluginWidgetChild.h"
+
+#include "mozilla/dom/TabChild.h"
 #include "mozilla/plugins/PluginWidgetParent.h"
 #include "PluginWidgetProxy.h"
+
+#include "mozilla/unused.h"
 #include "mozilla/DebugOnly.h"
 #include "nsDebug.h"
 
-#if defined(XP_WIN)
-#include "mozilla/plugins/PluginInstanceParent.h"
-using mozilla::plugins::PluginInstanceParent;
-#endif
-
 #define PWLOG(...)
-// #define PWLOG(...) printf_stderr(__VA_ARGS__)
+//#define PWLOG(...) printf_stderr(__VA_ARGS__)
 
 namespace mozilla {
 namespace plugins {
 
 PluginWidgetChild::PluginWidgetChild() :
   mWidget(nullptr)
 {
+  PWLOG("PluginWidgetChild::PluginWidgetChild()\n");
   MOZ_COUNT_CTOR(PluginWidgetChild);
 }
 
 PluginWidgetChild::~PluginWidgetChild()
 {
+  PWLOG("PluginWidgetChild::~PluginWidgetChild()\n");
   MOZ_COUNT_DTOR(PluginWidgetChild);
 }
 
 // Called by the proxy widget when it is destroyed by layout. Only gets
 // called once.
 void
 PluginWidgetChild::ProxyShutdown()
 {
   PWLOG("PluginWidgetChild::ProxyShutdown()\n");
   if (mWidget) {
-    SendDestroy();
     mWidget = nullptr;
+    auto tab = static_cast<mozilla::dom::TabChild*>(Manager());
+    if (!tab->IsDestroyed()) {
+      unused << Send__delete__(this);
+    }
   }
 }
 
 void
 PluginWidgetChild::KillWidget()
 {
   PWLOG("PluginWidgetChild::KillWidget()\n");
   if (mWidget) {
     mWidget->ChannelDestroyed();
   }
   mWidget = nullptr;
 }
 
 void
 PluginWidgetChild::ActorDestroy(ActorDestroyReason aWhy)
 {
-  PWLOG("PluginWidgetChild::ActorDestroy()\n");
-  KillWidget();
-}
-
-bool
-PluginWidgetChild::RecvParentShutdown(const uint16_t& aType)
-{
-  PWLOG("PluginWidgetChild::RecvParentShutdown()\n");
+  PWLOG("PluginWidgetChild::ActorDestroy(%d)\n", aWhy);
   KillWidget();
-  if (aType == PluginWidgetParent::CONTENT) {
-    Send__delete__(this);
-  }
-  return true;
-}
-
-bool
-PluginWidgetChild::RecvUpdateWindow(const uintptr_t& aChildId)
-{
-#if defined(XP_WIN)
-  NS_ASSERTION(aChildId, "Expected child hwnd value for remote plugin instance.");
-  PluginInstanceParent* parentInstance =
-    PluginInstanceParent::LookupPluginInstanceByID(aChildId);
-  NS_ASSERTION(parentInstance, "Expected matching plugin instance");
-  if (parentInstance) {
-    // sync! update call to the plugin instance that forces the
-    // plugin to paint its child window.
-    parentInstance->CallUpdateWindow();
-  }
-  return true;
-#else
-  NS_NOTREACHED("PluginWidgetChild::RecvUpdateWindow calls unexpected on this platform.");
-  return false;
-#endif
 }
 
 } // namespace plugins
 } // namespace mozilla
--- a/dom/plugins/ipc/PluginWidgetChild.h
+++ b/dom/plugins/ipc/PluginWidgetChild.h
@@ -14,19 +14,17 @@ class PluginWidgetProxy;
 namespace plugins {
 
 class PluginWidgetChild : public PPluginWidgetChild
 {
 public:
   PluginWidgetChild();
   virtual ~PluginWidgetChild();
 
-  virtual bool RecvUpdateWindow(const uintptr_t& aChildId) override;
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
-  virtual bool RecvParentShutdown(const uint16_t& aType) override;
 
   void SetWidget(mozilla::widget::PluginWidgetProxy* aWidget) {
     mWidget = aWidget;
   }
   void ProxyShutdown();
 
 private:
   void KillWidget();
--- a/dom/plugins/ipc/PluginWidgetParent.cpp
+++ b/dom/plugins/ipc/PluginWidgetParent.cpp
@@ -2,66 +2,54 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "PluginWidgetParent.h"
 #include "mozilla/dom/TabParent.h"
 #include "mozilla/dom/ContentParent.h"
 #include "nsComponentManagerUtils.h"
 #include "nsWidgetsCID.h"
+
+#include "mozilla/unused.h"
 #include "mozilla/DebugOnly.h"
 #include "nsDebug.h"
-#include "mozilla/unused.h"
 
 #if defined(MOZ_WIDGET_GTK)
 #include "nsPluginNativeWindowGtk.h"
 #endif
 
 using namespace mozilla;
 using namespace mozilla::widget;
 
 #define PWLOG(...)
-// #define PWLOG(...) printf_stderr(__VA_ARGS__)
+//#define PWLOG(...) printf_stderr(__VA_ARGS__)
+
+#if defined(XP_WIN)
+namespace mozilla {
+namespace dom {
+// For nsWindow
+const wchar_t* kPluginWidgetContentParentProperty =
+  L"kPluginWidgetParentProperty";
+} }
+#endif
 
 namespace mozilla {
 namespace plugins {
 
-#if defined(XP_WIN)
-// For nsWindow
-const wchar_t* kPluginWidgetParentProperty =
-  L"kPluginWidgetParentProperty";
-#endif
-
 static NS_DEFINE_CID(kWidgetCID, NS_CHILD_CID);
 
 // This macro returns true to prevent an abort in the child process when
 // ipc message delivery fails.
 #define ENSURE_CHANNEL {                                      \
   if (!mWidget) {                                             \
     NS_WARNING("called on an invalid remote widget.");        \
     return true;                                              \
   }                                                           \
 }
 
-/*
- * Tear down scenarios
- * layout (plugin content unloading):
- *  - PluginWidgetProxy::Destroy() calls PluginWidgetChild::ProxyShutdown(), calls SendDestroy()
- *  - PluginWidgetParent::RecvDestroy(), sends async ParentShutdown(CONTENT)
- *  - PluginWidgetChild::RecvParentShutdown(CONTENT), calls Send__delete__()
- *  - PluginWidgetParent::ActorDestroy() called in response to __delete__
- * PBrowser teardown (tab closing):
- *  - PluginWidgetParent::ParentDestroy() called by TabParent::Destroy(), sends async ParentShutdown(TAB_CLOSURE)
- *  - PluginWidgetChild::RecvParentShutdown(TAB_CLOSURE) (PluginWidgetProxy disabled)
- *  - PluginWidgetParent::ActorDestroy()
- *  - PluginWidgetParent::~PluginWidgetParent() in response to PBrowserParent::DeallocSubtree()
- *  - PluginWidgetChild::ActorDestroy() from PPluginWidgetChild::DestroySubtree
- *  - ~PluginWidgetChild() in response to PBrowserChild::DeallocSubtree()
- **/
-
 PluginWidgetParent::PluginWidgetParent()
 {
   PWLOG("PluginWidgetParent::PluginWidgetParent()\n");
   MOZ_COUNT_CTOR(PluginWidgetParent);
 }
 
 PluginWidgetParent::~PluginWidgetParent()
 {
@@ -82,35 +70,16 @@ PluginWidgetParent::GetTabParent()
 void
 PluginWidgetParent::SetParent(nsIWidget* aParent)
 {
   if (mWidget && aParent) {
     mWidget->SetParent(aParent);
   }
 }
 
-#if defined(XP_WIN)
-// static
-void
-PluginWidgetParent::SendAsyncUpdate(nsIWidget* aWidget)
-{
-  if (!aWidget || aWidget->Destroyed()) {
-    return;
-  }
-  // Fire off an async request to the plugin to paint its window
-  HWND hwnd = (HWND)aWidget->GetNativeData(NS_NATIVE_WINDOW);
-  NS_ASSERTION(hwnd, "Expected valid hwnd value.");
-  PluginWidgetParent* parent = reinterpret_cast<PluginWidgetParent*>(
-    ::GetPropW(hwnd, mozilla::plugins::kPluginWidgetParentProperty));
-  if (parent && !parent->ActorDestroyed()) {
-    parent->SendUpdateWindow((uintptr_t)hwnd);
-  }
-}
-#endif // defined(XP_WIN)
-
 // When plugins run in chrome, nsPluginNativeWindow(Plat) implements platform
 // specific functionality that wraps plugin widgets. With e10s we currently
 // bypass this code on Window, and reuse a bit of it on Linux. Content still
 // makes use of some of the utility functions as well.
 
 bool
 PluginWidgetParent::RecvCreate(nsresult* aResult)
 {
@@ -163,17 +132,18 @@ PluginWidgetParent::RecvCreate(nsresult*
   mWrapper->window = mWidget->GetNativeData(NS_NATIVE_PLUGIN_PORT);
   drv = mWrapper->CreateXEmbedWindow(false);
   NS_ASSERTION(NS_SUCCEEDED(drv), "widget call failure");
   mWrapper->SetAllocation();
   PWLOG("Plugin XID=%p\n", (void*)mWrapper->window);
 #elif defined(XP_WIN)
   DebugOnly<DWORD> winres =
     ::SetPropW((HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW),
-               kPluginWidgetParentProperty, this);
+               mozilla::dom::kPluginWidgetContentParentProperty,
+               GetTabParent()->Manager()->AsContentParent());
   NS_ASSERTION(winres, "SetPropW call failure");
 #endif
 
   // This is a special call we make to nsBaseWidget to register this
   // window as a remote plugin window which is expected to receive
   // visibility updates from the compositor, which ships this data
   // over with corresponding layer updates.
   mWidget->RegisterPluginWindowForRemoteUpdates();
@@ -189,72 +159,51 @@ PluginWidgetParent::KillWidget()
     mWidget->UnregisterPluginWindowForRemoteUpdates();
     DebugOnly<nsresult> rv = mWidget->Destroy();
     NS_ASSERTION(NS_SUCCEEDED(rv), "widget destroy failure");
 #if defined(MOZ_WIDGET_GTK)
     mWidget->SetNativeData(NS_NATIVE_PLUGIN_OBJECT_PTR, (uintptr_t)0);
     mWrapper = nullptr;
 #elif defined(XP_WIN)
     ::RemovePropW((HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW),
-                  kPluginWidgetParentProperty);
+                  mozilla::dom::kPluginWidgetContentParentProperty);
 #endif
     mWidget = nullptr;
   }
 }
 
 void
-PluginWidgetParent::Shutdown(ShutdownType aType)
-{
-  if (mWidget) {
-    KillWidget();
-    unused << SendParentShutdown(aType);
-  }
-}
-
-void
 PluginWidgetParent::ActorDestroy(ActorDestroyReason aWhy)
 {
-  PWLOG("PluginWidgetParent::ActorDestroy()\n");
+  PWLOG("PluginWidgetParent::ActorDestroy(%d)\n", aWhy);
   KillWidget();
 }
 
 // Called by TabParent's Destroy() in response to an early tear down (Early
 // in that this is happening before layout in the child has had a chance
 // to destroy the child widget.) when the tab is closing.
 void
 PluginWidgetParent::ParentDestroy()
 {
   PWLOG("PluginWidgetParent::ParentDestroy()\n");
-  Shutdown(TAB_CLOSURE);
-}
-
-// Called by the child when a plugin is torn down within a tab
-// normally. Messages back via ParentShutdown().
-bool
-PluginWidgetParent::RecvDestroy()
-{
-  PWLOG("PluginWidgetParent::RecvDestroy()\n");
-  Shutdown(CONTENT);
-  return true;
 }
 
 bool
 PluginWidgetParent::RecvSetFocus(const bool& aRaise)
 {
   ENSURE_CHANNEL;
   PWLOG("PluginWidgetParent::RecvSetFocus(%d)\n", aRaise);
   mWidget->SetFocus(aRaise);
   return true;
 }
 
 bool
 PluginWidgetParent::RecvGetNativePluginPort(uintptr_t* value)
 {
   ENSURE_CHANNEL;
-  PWLOG("PluginWidgetParent::RecvGetNativeData()\n");
 #if defined(MOZ_WIDGET_GTK)
   *value = (uintptr_t)mWrapper->window;
   NS_ASSERTION(*value, "no xid??");
 #else
   *value = (uintptr_t)mWidget->GetNativeData(NS_NATIVE_PLUGIN_PORT);
   NS_ASSERTION(*value, "no native port??");
 #endif
   PWLOG("PluginWidgetParent::RecvGetNativeData() %p\n", (void*)*value);
--- a/dom/plugins/ipc/PluginWidgetParent.h
+++ b/dom/plugins/ipc/PluginWidgetParent.h
@@ -19,55 +19,38 @@ namespace dom {
 class TabParent;
 }
 
 namespace plugins {
 
 class PluginWidgetParent : public PPluginWidgetParent
 {
 public:
-  /**
-   * Windows helper for firing off an update window request to a plugin.
-   *
-   * aWidget - the eWindowType_plugin_ipc_chrome widget associated with
-   *           this plugin window.
-   */
-  static void SendAsyncUpdate(nsIWidget* aWidget);
-
   PluginWidgetParent();
   virtual ~PluginWidgetParent();
 
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
   virtual bool RecvCreate(nsresult* aResult) override;
-  virtual bool RecvDestroy() override;
   virtual bool RecvSetFocus(const bool& aRaise) override;
   virtual bool RecvGetNativePluginPort(uintptr_t* value) override;
 
   // Helper for compositor checks on the channel
   bool ActorDestroyed() { return !mWidget; }
 
   // Called by PBrowser when it receives a Destroy() call from the child.
   void ParentDestroy();
 
   // Sets mWidget's parent
   void SetParent(nsIWidget* aParent);
 
 private:
   // The tab our connection is associated with.
   mozilla::dom::TabParent* GetTabParent();
 
-public:
-  // Identifies the side of the connection that initiates shutdown.
-  enum ShutdownType {
-    TAB_CLOSURE = 1,
-    CONTENT     = 2
-  };
-
 private:
-  void Shutdown(ShutdownType aType);
   void KillWidget();
 
   // The chrome side native widget.
   nsCOMPtr<nsIWidget> mWidget;
 #if defined(MOZ_WIDGET_GTK)
   nsAutoPtr<nsPluginNativeWindowGtk> mWrapper;
 #endif
 };
--- a/widget/PluginWidgetProxy.cpp
+++ b/widget/PluginWidgetProxy.cpp
@@ -117,16 +117,20 @@ PluginWidgetProxy::GetWindowClipRegion(n
 }
 
 void*
 PluginWidgetProxy::GetNativeData(uint32_t aDataType)
 {
   if (!mActor) {
     return nullptr;
   }
+  auto tab = static_cast<mozilla::dom::TabChild*>(mActor->Manager());
+  if (tab && tab->IsDestroyed()) {
+    return nullptr;
+  }
   switch (aDataType) {
     case NS_NATIVE_PLUGIN_PORT:
     case NS_NATIVE_WINDOW:
     case NS_NATIVE_SHAREABLE_WINDOW:
       break;
     default:
       NS_WARNING("PluginWidgetProxy::GetNativeData received request for unsupported data type.");
       return nullptr;
--- a/widget/windows/nsWindowGfx.cpp
+++ b/widget/windows/nsWindowGfx.cpp
@@ -2,34 +2,29 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /*
  * nsWindowGfx - Painting and aceleration.
  */
 
-// XXX Future: this should really be a stand alone class stored as
-// a member of nsWindow with getters and setters for things like render
-// mode and methods for handling paint.
-
 /**************************************************************
  **************************************************************
  **
  ** BLOCK: Includes
  **
  ** Include headers.
  **
  **************************************************************
  **************************************************************/
 
+#include "mozilla/dom/ContentParent.h"
 #include "mozilla/plugins/PluginInstanceParent.h"
 using mozilla::plugins::PluginInstanceParent;
-#include "mozilla/plugins/PluginWidgetParent.h"
-using mozilla::plugins::PluginWidgetParent;
 
 #include "nsWindowGfx.h"
 #include "nsAppRunner.h"
 #include <windows.h>
 #include "gfxImageSurface.h"
 #include "gfxUtils.h"
 #include "gfxWindowsSurface.h"
 #include "gfxWindowsPlatform.h"
@@ -52,23 +47,16 @@ using mozilla::plugins::PluginWidgetPare
 #include "nsUXThemeData.h"
 #include "nsUXThemeConstants.h"
 
 extern "C" {
 #define PIXMAN_DONT_DEFINE_STDINT
 #include "pixman.h"
 }
 
-namespace mozilla {
-namespace plugins {
-// For plugins with e10s
-extern const wchar_t* kPluginWidgetParentProperty;
-}
-}
-
 using namespace mozilla;
 using namespace mozilla::gfx;
 using namespace mozilla::layers;
 using namespace mozilla::widget;
 using namespace mozilla::plugins;
 
 /**************************************************************
  **************************************************************
@@ -209,17 +197,17 @@ bool nsWindow::OnPaint(HDC aDC, uint32_t
       PAINTSTRUCT ps;
       BeginPaint(mWnd, &ps);
       EndPaint(mWnd, &ps);
       return true;
     }
 
     if (mWindowType == eWindowType_plugin_ipc_chrome) {
       // Fire off an async request to the plugin to paint its window
-      PluginWidgetParent::SendAsyncUpdate(this);
+      mozilla::dom::ContentParent::SendAsyncUpdate(this);
       ValidateRect(mWnd, nullptr);
       return true;
     }
 
     PluginInstanceParent* instance = reinterpret_cast<PluginInstanceParent*>(
       ::GetPropW(mWnd, L"PluginInstanceParentProperty"));
     if (instance) {
       unused << instance->CallUpdateWindow();