Bug 669200 - Implement base PPluginWidget classes for managing plugin windows via content. r=billm
authorJim Mathies <jmathies@mozilla.com>
Wed, 12 Nov 2014 14:59:19 -0600
changeset 215361 bcaebd09531ca0c862f92d5e2ff80ffb22741419
parent 215360 dcc233b91a99e7d8cfaa39b508d2eb2c2496fab6
child 215362 ad862fdf75cd2be6681f713f051ea9150e4f76f5
push id27813
push userkwierso@gmail.com
push dateThu, 13 Nov 2014 01:03:17 +0000
treeherdermozilla-central@64f1fb1e2f38 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbillm
bugs669200
milestone36.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 669200 - Implement base PPluginWidget classes for managing plugin windows via content. r=billm
dom/ipc/TabChild.cpp
dom/ipc/TabChild.h
dom/ipc/TabParent.cpp
dom/ipc/TabParent.h
dom/plugins/ipc/PluginWidgetChild.cpp
dom/plugins/ipc/PluginWidgetChild.h
dom/plugins/ipc/PluginWidgetParent.cpp
dom/plugins/ipc/PluginWidgetParent.h
dom/plugins/ipc/moz.build
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -12,16 +12,17 @@
 #include "ContentChild.h"
 #include "TabParent.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/EventListenerManager.h"
 #include "mozilla/IntentionalCrash.h"
 #include "mozilla/docshell/OfflineCacheUpdateChild.h"
 #include "mozilla/dom/indexedDB/PIndexedDBPermissionRequestChild.h"
+#include "mozilla/plugins/PluginWidgetChild.h"
 #include "mozilla/ipc/DocumentRendererChild.h"
 #include "mozilla/ipc/FileDescriptorUtils.h"
 #include "mozilla/layers/ActiveElementManager.h"
 #include "mozilla/layers/APZCCallbackHelper.h"
 #include "mozilla/layers/APZCTreeManager.h"
 #include "mozilla/layers/CompositorChild.h"
 #include "mozilla/layers/ImageBridgeChild.h"
 #include "mozilla/layers/ShadowLayers.h"
@@ -3104,16 +3105,52 @@ TabChild::RecvUIResolutionChanged()
   static_cast<PuppetWidget*>(mWidget.get())->ClearBackingScaleCache();
   nsCOMPtr<nsIDocument> document(GetDocument());
   nsCOMPtr<nsIPresShell> presShell = document->GetShell();
   nsRefPtr<nsPresContext> presContext = presShell->GetPresContext();
   presContext->UIResolutionChanged();
   return true;
 }
 
+mozilla::plugins::PPluginWidgetChild*
+TabChild::AllocPPluginWidgetChild()
+{
+    return new mozilla::plugins::PluginWidgetChild();
+}
+
+bool
+TabChild::DeallocPPluginWidgetChild(mozilla::plugins::PPluginWidgetChild* aActor)
+{
+    delete aActor;
+    return true;
+}
+
+already_AddRefed<nsIWidget>
+TabChild::CreatePluginWidget(nsIWidget* aParent)
+{
+  mozilla::plugins::PluginWidgetChild* child =
+    static_cast<mozilla::plugins::PluginWidgetChild*>(SendPPluginWidgetConstructor());
+  if (!child) {
+    NS_ERROR("couldn't create PluginWidgetChild");
+    return nullptr;
+  }
+  nsCOMPtr<nsIWidget> pluginWidget = nsIWidget::CreatePluginProxyWidget(this, child);
+  if (!pluginWidget) {
+    NS_ERROR("couldn't create PluginWidgetProxy");
+    return nullptr;
+  }
+
+  nsresult rv = pluginWidget->Create(aParent, 0, nsIntRect(nsIntPoint(0, 0),
+                                     nsIntSize(0, 0)), nullptr, nullptr);
+  if (NS_FAILED(rv)) {
+    NS_WARNING("Creating native plugin widget on the chrome side failed.");
+  }
+  return pluginWidget.forget();
+}
+
 TabChildGlobal::TabChildGlobal(TabChildBase* aTabChild)
 : mTabChild(aTabChild)
 {
   SetIsNotDOMBinding();
 }
 
 TabChildGlobal::~TabChildGlobal()
 {
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -47,16 +47,20 @@ class RenderFrameChild;
 namespace layers {
 class ActiveElementManager;
 }
 
 namespace widget {
 struct AutoCacheNativeKeyCommands;
 }
 
+namespace plugins {
+class PluginWidgetChild;
+}
+
 namespace dom {
 
 class TabChild;
 class ClonedMessageData;
 class TabChildBase;
 
 class TabChildGlobal : public DOMEventTargetHelper,
                        public nsIContentFrameMessageManager,
@@ -479,16 +483,23 @@ public:
     {
       nsCOMPtr<nsIWebNavigation> webNav = do_GetInterface(aWindow);
       nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(webNav);
       return GetFrom(docShell);
     }
 
     virtual bool RecvUIResolutionChanged() MOZ_OVERRIDE;
 
+    /**
+     * Native widget remoting protocol for use with windowed plugins with e10s.
+     */
+    PPluginWidgetChild* AllocPPluginWidgetChild() MOZ_OVERRIDE;
+    bool DeallocPPluginWidgetChild(PPluginWidgetChild* aActor) MOZ_OVERRIDE;
+    already_AddRefed<nsIWidget> CreatePluginWidget(nsIWidget* aParent);
+
 protected:
     virtual ~TabChild();
 
     virtual PRenderFrameChild* AllocPRenderFrameChild(ScrollingBehavior* aScrolling,
                                                       TextureFactoryIdentifier* aTextureFactoryIdentifier,
                                                       uint64_t* aLayersId,
                                                       bool* aSuccess) MOZ_OVERRIDE;
     virtual bool DeallocPRenderFrameChild(PRenderFrameChild* aFrame) MOZ_OVERRIDE;
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -10,16 +10,17 @@
 
 #include "AppProcessChecker.h"
 #include "mozIApplication.h"
 #include "mozilla/BrowserElementParent.h"
 #include "mozilla/docshell/OfflineCacheUpdateParent.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/PContentPermissionRequestParent.h"
 #include "mozilla/dom/indexedDB/ActorsParent.h"
+#include "mozilla/plugins/PluginWidgetParent.h"
 #include "mozilla/EventStateManager.h"
 #include "mozilla/Hal.h"
 #include "mozilla/ipc/DocumentRendererParent.h"
 #include "mozilla/layers/CompositorParent.h"
 #include "mozilla/layout/RenderFrameParent.h"
 #include "mozilla/MouseEvents.h"
 #include "mozilla/net/NeckoChild.h"
 #include "mozilla/Preferences.h"
@@ -2242,16 +2243,29 @@ TabParent::RecvRemotePaintIsReady()
   event->InitEvent(NS_LITERAL_STRING("MozAfterRemotePaint"), false, false);
   event->SetTrusted(true);
   event->GetInternalNSEvent()->mFlags.mOnlyChromeDispatch = true;
   bool dummy;
   mFrameElement->DispatchEvent(event, &dummy);
   return true;
 }
 
+mozilla::plugins::PPluginWidgetParent*
+TabParent::AllocPPluginWidgetParent()
+{
+  return new mozilla::plugins::PluginWidgetParent();
+}
+
+bool
+TabParent::DeallocPPluginWidgetParent(mozilla::plugins::PPluginWidgetParent* aActor)
+{
+  delete aActor;
+  return true;
+}
+
 class FakeChannel MOZ_FINAL : public nsIChannel,
                               public nsIAuthPromptCallback,
                               public nsIInterfaceRequestor,
                               public nsILoadContext
 {
 public:
   FakeChannel(const nsCString& aUri, uint64_t aCallbackId, Element* aElement)
     : mCallbackId(aCallbackId)
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -342,16 +342,24 @@ public:
 
     already_AddRefed<nsIWidget> GetWidget() const;
 
     const TabId GetTabId() const
     {
       return mTabId;
     }
 
+    nsIntPoint GetChildProcessOffset();
+
+    /**
+     * Native widget remoting protocol for use with windowed plugins with e10s.
+     */
+    virtual PPluginWidgetParent* AllocPPluginWidgetParent() MOZ_OVERRIDE;
+    virtual bool DeallocPPluginWidgetParent(PPluginWidgetParent* aActor) MOZ_OVERRIDE;
+
 protected:
     bool ReceiveMessage(const nsString& aMessage,
                         bool aSync,
                         const StructuredCloneData* aCloneData,
                         CpowHolder* aCpows,
                         nsIPrincipal* aPrincipal,
                         InfallibleTArray<nsString>* aJSONRetVal = nullptr);
 
@@ -362,17 +370,16 @@ protected:
     virtual bool Recv__delete__() MOZ_OVERRIDE;
 
     virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
 
     Element* mFrameElement;
     nsCOMPtr<nsIBrowserDOMWindow> mBrowserDOMWindow;
 
     bool AllowContentIME();
-    nsIntPoint GetChildProcessOffset();
 
     virtual PRenderFrameParent* AllocPRenderFrameParent(ScrollingBehavior* aScrolling,
                                                         TextureFactoryIdentifier* aTextureFactoryIdentifier,
                                                         uint64_t* aLayersId,
                                                         bool* aSuccess) MOZ_OVERRIDE;
     virtual bool DeallocPRenderFrameParent(PRenderFrameParent* aFrame) MOZ_OVERRIDE;
 
     virtual bool RecvRemotePaintIsReady() MOZ_OVERRIDE;
new file mode 100644
--- /dev/null
+++ b/dom/plugins/ipc/PluginWidgetChild.cpp
@@ -0,0 +1,35 @@
+/* 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 "PluginWidgetProxy.h"
+
+namespace mozilla {
+namespace plugins {
+
+PluginWidgetChild::PluginWidgetChild() :
+  mWidget(nullptr)
+{
+  MOZ_COUNT_CTOR(PluginWidgetChild);
+}
+
+PluginWidgetChild::~PluginWidgetChild()
+{
+  MOZ_COUNT_DTOR(PluginWidgetChild);
+}
+
+void
+PluginWidgetChild::ActorDestroy(ActorDestroyReason aWhy)
+{
+  if (mWidget) {
+    mWidget->ChannelDestroyed();
+  }
+  mWidget = nullptr;
+}
+
+} // namespace plugins
+} // namespace mozilla
+
+
+
new file mode 100644
--- /dev/null
+++ b/dom/plugins/ipc/PluginWidgetChild.h
@@ -0,0 +1,31 @@
+/* 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/. */
+
+#ifndef mozilla_plugins_PluginWidgetParent_h
+#define mozilla_plugins_PluginWidgetParent_h
+
+#include "mozilla/plugins/PPluginWidgetChild.h"
+
+namespace mozilla {
+namespace widget {
+class PluginWidgetProxy;
+}
+namespace plugins {
+
+class PluginWidgetChild : public PPluginWidgetChild
+{
+public:
+  PluginWidgetChild();
+  virtual ~PluginWidgetChild();
+
+  virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
+
+  mozilla::widget::PluginWidgetProxy* mWidget;
+};
+
+} // namespace plugins
+} // namespace mozilla
+
+#endif // mozilla_plugins_PluginWidgetParent_h
+
new file mode 100644
--- /dev/null
+++ b/dom/plugins/ipc/PluginWidgetParent.cpp
@@ -0,0 +1,195 @@
+/* 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 "PluginWidgetParent.h"
+#include "mozilla/dom/TabParent.h"
+#include "nsComponentManagerUtils.h"
+#include "nsWidgetsCID.h"
+#include "nsDebug.h"
+
+using namespace mozilla::widget;
+
+#define PWLOG(...)
+// #define PWLOG(...) printf_stderr(__VA_ARGS__)
+
+namespace mozilla {
+namespace plugins {
+
+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;                                              \
+  }                                                           \
+}
+
+PluginWidgetParent::PluginWidgetParent()
+{
+  PWLOG("PluginWidgetParent::PluginWidgetParent()\n");
+  MOZ_COUNT_CTOR(PluginWidgetParent);
+}
+
+PluginWidgetParent::~PluginWidgetParent()
+{
+  PWLOG("PluginWidgetParent::~PluginWidgetParent()\n");
+  MOZ_COUNT_DTOR(PluginWidgetParent);
+  // A destroy call can actually get skipped if a widget is associated
+  // with the last out-of-process page, make sure and cleanup any left
+  // over widgets if we have them.
+  if (mWidget) {
+    mWidget->Destroy();
+    mWidget = nullptr;
+  }
+}
+
+mozilla::dom::TabParent*
+PluginWidgetParent::GetTabParent()
+{
+  return static_cast<mozilla::dom::TabParent*>(Manager());
+}
+
+void
+PluginWidgetParent::ActorDestroy(ActorDestroyReason aWhy)
+{
+  PWLOG("PluginWidgetParent::ActorDestroy()\n");
+}
+
+// When plugins run in chrome, nsPluginNativeWindow(Plat) implements platform
+// specific functionality that wraps plugin widgets. With e10s we currently
+// bypass this code since we can't connect up platform specific bits in the
+// content process. We may need to instantiate nsPluginNativeWindow here and
+// enable some of its logic.
+
+bool
+PluginWidgetParent::RecvCreate()
+{
+  PWLOG("PluginWidgetParent::RecvCreate()\n");
+
+  nsresult rv;
+
+  mWidget = do_CreateInstance(kWidgetCID, &rv);
+
+  // This returns the top level window widget
+  nsCOMPtr<nsIWidget> parentWidget = GetTabParent()->GetWidget();
+
+  nsWidgetInitData initData;
+  initData.mWindowType = eWindowType_plugin_ipc_chrome;
+  initData.mUnicode = false;
+  initData.clipChildren = true;
+  initData.clipSiblings = true;
+  rv = mWidget->Create(parentWidget.get(), nullptr, nsIntRect(0,0,0,0),
+                       nullptr, &initData);
+  if (NS_FAILED(rv)) {
+    mWidget->Destroy();
+    mWidget = nullptr;
+    return false;
+  }
+
+  mWidget->EnableDragDrop(true);
+  mWidget->Show(false);
+  mWidget->Enable(false);
+
+  // Force the initial position down into content. If we miss an
+  // initial position update this insures the widget doesn't overlap
+  // chrome.
+  RecvMove(0, 0);
+
+  return true;
+}
+
+bool
+PluginWidgetParent::RecvDestroy()
+{
+  ENSURE_CHANNEL;
+  PWLOG("PluginWidgetParent::RecvDestroy()\n");
+  mWidget->Destroy();
+  mWidget = nullptr;
+  return true;
+}
+
+bool
+PluginWidgetParent::RecvShow(const bool& aState)
+{
+  ENSURE_CHANNEL;
+  PWLOG("PluginWidgetParent::RecvShow(%d)\n", aState);
+  mWidget->Show(aState);
+  return true;
+}
+
+bool
+PluginWidgetParent::RecvSetFocus(const bool& aRaise)
+{
+  ENSURE_CHANNEL;
+  PWLOG("PluginWidgetParent::RecvSetFocus(%d)\n", aRaise);
+  mWidget->SetFocus(aRaise);
+  return true;
+}
+
+bool
+PluginWidgetParent::RecvInvalidate(const nsIntRect& aRect)
+{
+  ENSURE_CHANNEL;
+  PWLOG("PluginWidgetParent::RecvInvalidate(%d, %d, %d, %d)\n", aRect.x, aRect.y, aRect.width, aRect.height);
+  mWidget->Invalidate(aRect);
+  return true;
+}
+
+bool
+PluginWidgetParent::RecvGetNativePluginPort(uintptr_t* value)
+{
+  ENSURE_CHANNEL;
+  PWLOG("PluginWidgetParent::RecvGetNativeData()\n");
+  *value = (uintptr_t)mWidget->GetNativeData(NS_NATIVE_PLUGIN_PORT);
+  return true;
+}
+
+bool
+PluginWidgetParent::RecvResize(const nsIntRect& aRect)
+{
+  ENSURE_CHANNEL;
+  PWLOG("PluginWidgetParent::RecvResize(%d, %d, %d, %d)\n", aRect.x, aRect.y, aRect.width, aRect.height);
+  mWidget->Resize(aRect.width, aRect.height, true);
+  return true;
+}
+
+bool
+PluginWidgetParent::RecvMove(const double& aX, const double& aY)
+{
+  ENSURE_CHANNEL;
+  PWLOG("PluginWidgetParent::RecvMove(%f, %f)\n", aX, aY);
+
+
+  // This returns the top level window
+  nsCOMPtr<nsIWidget> widget = GetTabParent()->GetWidget();
+  if (!widget) {
+    // return true otherwise ipc will abort the content process, crashing
+    // all tabs.
+    return true;
+  }
+
+  // Passed in coords are at the tab origin, adjust to the main window.
+  nsIntPoint offset = GetTabParent()->GetChildProcessOffset();
+  offset.x = abs(offset.x);
+  offset.y = abs(offset.y);
+  offset += nsIntPoint(ceil(aX), ceil(aY));
+  mWidget->Move(offset.x, offset.y);
+
+  return true;
+}
+
+bool
+PluginWidgetParent::RecvSetWindowClipRegion(const nsTArray<nsIntRect>& Regions,
+                                            const bool& aIntersectWithExisting)
+{
+  ENSURE_CHANNEL;
+  PWLOG("PluginWidgetParent::RecvSetWindowClipRegion()\n");
+  mWidget->SetWindowClipRegion(Regions, aIntersectWithExisting);
+  return true;
+}
+
+} // namespace plugins
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/plugins/ipc/PluginWidgetParent.h
@@ -0,0 +1,49 @@
+/* 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/. */
+
+#ifndef mozilla_plugins_PluginWidgetParent_h
+#define mozilla_plugins_PluginWidgetParent_h
+
+#include "mozilla/plugins/PPluginWidgetParent.h"
+#include "nsIWidget.h"
+#include "nsCOMPtr.h"
+
+namespace mozilla {
+
+namespace dom {
+class TabParent;
+}
+
+namespace plugins {
+
+class PluginWidgetParent : public PPluginWidgetParent
+{
+public:
+  PluginWidgetParent();
+  virtual ~PluginWidgetParent();
+
+  virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
+  virtual bool RecvCreate() MOZ_OVERRIDE;
+  virtual bool RecvDestroy() MOZ_OVERRIDE;
+  virtual bool RecvShow(const bool& aState) MOZ_OVERRIDE;
+  virtual bool RecvSetFocus(const bool& aRaise) MOZ_OVERRIDE;
+  virtual bool RecvInvalidate(const nsIntRect& aRect) MOZ_OVERRIDE;
+  virtual bool RecvGetNativePluginPort(uintptr_t* value) MOZ_OVERRIDE;
+  virtual bool RecvResize(const nsIntRect& aRect) MOZ_OVERRIDE;
+  virtual bool RecvMove(const double& aX, const double& aY) MOZ_OVERRIDE;
+  virtual bool RecvSetWindowClipRegion(const nsTArray<nsIntRect>& Regions,
+                                        const bool& aIntersectWithExisting) MOZ_OVERRIDE;
+
+private:
+  // The tab our connection is associated with.
+  mozilla::dom::TabParent* GetTabParent();
+  // The chrome side native widget.
+  nsCOMPtr<nsIWidget> mWidget;
+};
+
+} // namespace plugins
+} // namespace mozilla
+
+#endif // mozilla_plugins_PluginWidgetParent_h
+
--- a/dom/plugins/ipc/moz.build
+++ b/dom/plugins/ipc/moz.build
@@ -31,16 +31,18 @@ EXPORTS.mozilla.plugins += [
     'PluginProcessParent.h',
     'PluginScriptableObjectChild.h',
     'PluginScriptableObjectParent.h',
     'PluginScriptableObjectUtils-inl.h',
     'PluginScriptableObjectUtils.h',
     'PluginStreamChild.h',
     'PluginStreamParent.h',
     'PluginUtilsOSX.h',
+    'PluginWidgetChild.h',
+    'PluginWidgetParent.h',
     'ScopedMethodFactory.h',
     'StreamNotifyChild.h',
     'StreamNotifyParent.h',
 ]
 
 if CONFIG['OS_ARCH'] == 'WINNT':
     EXPORTS.mozilla.plugins += [
         'PluginSurfaceParent.h',
@@ -87,16 +89,18 @@ UNIFIED_SOURCES += [
     'PluginScriptableObjectParent.cpp',
     'PluginStreamChild.cpp',
     'PluginStreamParent.cpp',
 ]
 
 SOURCES += [
     'PluginInstanceChild.cpp', # 'PluginThreadCallback' : ambiguous symbol
     'PluginModuleChild.cpp',   # Redefinition of mozilla::WindowsDllInterceptor sUser32Intercept
+    'PluginWidgetChild.cpp',
+    'PluginWidgetParent.cpp',
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
     UNIFIED_SOURCES += [
         'PluginInterposeOSX.mm',
         'PluginUtilsOSX.mm',
     ]