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 227618 bcaebd09531ca0c862f92d5e2ff80ffb22741419
parent 227617 dcc233b91a99e7d8cfaa39b508d2eb2c2496fab6
child 227619 ad862fdf75cd2be6681f713f051ea9150e4f76f5
push id4311
push userraliiev@mozilla.com
push dateMon, 12 Jan 2015 19:37:41 +0000
treeherdermozilla-esr52@150c9fed433b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbillm
bugs669200
milestone36.0a1
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',
     ]