Bug 1416878 - Move the implementation of nsIWidgetListener from nsWebBrowser / nsWebShellWindow to a separate object. r=bz
☠☠ backed out by b3c2dd33904f ☠ ☠
authorSamael Wang <freesamael@gmail.com>
Tue, 09 Jan 2018 11:13:46 +0200
changeset 450138 ff8ff4350191790ffd0b2c23b5636eab2d2e4fea
parent 450137 79dbd796c8747d8a70b8669bce06561250241cec
child 450139 b3c2dd33904fda551d7efc121e00f8a54c704bcc
push id8527
push userCallek@gmail.com
push dateThu, 11 Jan 2018 21:05:50 +0000
treeherdermozilla-beta@95342d212a7a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs1416878
milestone59.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 1416878 - Move the implementation of nsIWidgetListener from nsWebBrowser / nsWebShellWindow to a separate object. r=bz MozReview-Commit-ID: 5QV6lkCCGW5
toolkit/components/browser/nsWebBrowser.cpp
toolkit/components/browser/nsWebBrowser.h
xpfe/appshell/nsWebShellWindow.cpp
xpfe/appshell/nsWebShellWindow.h
--- a/toolkit/components/browser/nsWebBrowser.cpp
+++ b/toolkit/components/browser/nsWebBrowser.cpp
@@ -62,16 +62,17 @@ static NS_DEFINE_CID(kChildCID, NS_CHILD
 nsWebBrowser::nsWebBrowser()
   : mInitInfo(new nsWebBrowserInitInfo())
   , mContentType(typeContentWrapper)
   , mActivating(false)
   , mShouldEnableHistory(true)
   , mIsActive(true)
   , mParentNativeWindow(nullptr)
   , mProgressListener(nullptr)
+  , mWidgetListenerDelegate(this)
   , mBackgroundColor(0)
   , mPersistCurrentState(nsIWebBrowserPersist::PERSIST_STATE_READY)
   , mPersistResult(NS_OK)
   , mPersistFlags(nsIWebBrowserPersist::PERSIST_FLAGS_NONE)
   , mParentWidget(nullptr)
 {
   mWWatch = do_GetService(NS_WINDOWWATCHER_CONTRACTID);
   NS_ASSERTION(mWWatch, "failed to get WindowWatcher");
@@ -1195,17 +1196,17 @@ nsWebBrowser::Create()
     nsWidgetInitData widgetInit;
 
     widgetInit.clipChildren = true;
 
     widgetInit.mWindowType = eWindowType_child;
     LayoutDeviceIntRect bounds(mInitInfo->x, mInitInfo->y,
                                mInitInfo->cx, mInitInfo->cy);
 
-    mInternalWidget->SetWidgetListener(this);
+    mInternalWidget->SetWidgetListener(&mWidgetListenerDelegate);
     rv = mInternalWidget->Create(nullptr, mParentNativeWindow, bounds,
                                  &widgetInit);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   nsCOMPtr<nsIDocShell> docShell(
     do_CreateInstance("@mozilla.org/docshell;1", &rv));
   NS_ENSURE_SUCCESS(rv, rv);
@@ -1898,8 +1899,30 @@ nsWebBrowser::GetFocusedElement(nsIDOMEl
 }
 
 NS_IMETHODIMP
 nsWebBrowser::SetFocusedElement(nsIDOMElement* aFocusedElement)
 {
   nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID);
   return fm ? fm->SetFocus(aFocusedElement, 0) : NS_OK;
 }
+
+void
+nsWebBrowser::WidgetListenerDelegate::WindowActivated()
+{
+  RefPtr<nsWebBrowser> holder = mWebBrowser;
+  holder->WindowActivated();
+}
+
+void
+nsWebBrowser::WidgetListenerDelegate::WindowDeactivated()
+{
+  RefPtr<nsWebBrowser> holder = mWebBrowser;
+  holder->WindowDeactivated();
+}
+
+bool
+nsWebBrowser::WidgetListenerDelegate::PaintWindow(
+  nsIWidget* aWidget, mozilla::LayoutDeviceIntRegion aRegion)
+{
+  RefPtr<nsWebBrowser> holder = mWebBrowser;
+  return holder->PaintWindow(aWidget, aRegion);
+}
--- a/toolkit/components/browser/nsWebBrowser.h
+++ b/toolkit/components/browser/nsWebBrowser.h
@@ -77,22 +77,41 @@ class nsWebBrowser final : public nsIWeb
                            public nsIDocShellTreeItem,
                            public nsIBaseWindow,
                            public nsIScrollable,
                            public nsITextScroll,
                            public nsIInterfaceRequestor,
                            public nsIWebBrowserPersist,
                            public nsIWebBrowserFocus,
                            public nsIWebProgressListener,
-                           public nsIWidgetListener,
                            public nsSupportsWeakReference
 {
   friend class nsDocShellTreeOwner;
 
 public:
+
+  // The implementation of non-refcounted nsIWidgetListener, which would hold a
+  // strong reference on stack before calling nsWebBrowser's
+  // MOZ_CAN_RUN_SCRIPT methods.
+  class WidgetListenerDelegate : public nsIWidgetListener
+  {
+  public:
+    WidgetListenerDelegate(nsWebBrowser* aWebBrowser)
+      : mWebBrowser(aWebBrowser) {}
+    MOZ_CAN_RUN_SCRIPT_BOUNDARY virtual void WindowActivated() override;
+    MOZ_CAN_RUN_SCRIPT_BOUNDARY virtual void WindowDeactivated() override;
+    MOZ_CAN_RUN_SCRIPT_BOUNDARY virtual bool PaintWindow(
+      nsIWidget* aWidget, mozilla::LayoutDeviceIntRegion aRegion) override;
+
+  private:
+    // The lifetime of WidgetListenerDelegate is bound to nsWebBrowser so we
+    // just use raw pointer here.
+    nsWebBrowser* mWebBrowser;
+  };
+
   nsWebBrowser();
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsWebBrowser, nsIWebBrowser)
 
   NS_DECL_NSIBASEWINDOW
   NS_DECL_NSIDOCSHELLTREEITEM
   NS_DECL_NSIINTERFACEREQUESTOR
@@ -112,21 +131,21 @@ protected:
 
   // XXXbz why are these NS_IMETHOD?  They're not interface methods!
   NS_IMETHOD SetDocShell(nsIDocShell* aDocShell);
   NS_IMETHOD EnsureDocShellTreeOwner();
   NS_IMETHOD BindListener(nsISupports* aListener, const nsIID& aIID);
   NS_IMETHOD UnBindListener(nsISupports* aListener, const nsIID& aIID);
   NS_IMETHOD EnableGlobalHistory(bool aEnable);
 
-  // nsIWidgetListener
-  virtual void WindowActivated() override;
-  virtual void WindowDeactivated() override;
-  virtual bool PaintWindow(nsIWidget* aWidget,
-                           mozilla::LayoutDeviceIntRegion aRegion) override;
+  // nsIWidgetListener methods for WidgetListenerDelegate.
+  MOZ_CAN_RUN_SCRIPT void WindowActivated();
+  MOZ_CAN_RUN_SCRIPT void WindowDeactivated();
+  MOZ_CAN_RUN_SCRIPT bool PaintWindow(
+    nsIWidget* aWidget, mozilla::LayoutDeviceIntRegion aRegion);
 
 protected:
   RefPtr<nsDocShellTreeOwner> mDocShellTreeOwner;
   nsCOMPtr<nsIDocShell> mDocShell;
   nsCOMPtr<nsIInterfaceRequestor> mDocShellAsReq;
   nsCOMPtr<nsIBaseWindow> mDocShellAsWin;
   nsCOMPtr<nsIWebNavigation> mDocShellAsNav;
   nsCOMPtr<nsIScrollable> mDocShellAsScrollable;
@@ -141,16 +160,18 @@ protected:
   bool mShouldEnableHistory;
   bool mIsActive;
   nativeWindow mParentNativeWindow;
   nsIWebProgressListener* mProgressListener;
   nsCOMPtr<nsIWebProgress> mWebProgress;
 
   nsCOMPtr<nsIPrintSettings> mPrintSettings;
 
+  WidgetListenerDelegate mWidgetListenerDelegate;
+
   // cached background color
   nscolor mBackgroundColor;
 
   // persistence object
   nsCOMPtr<nsIWebBrowserPersist> mPersist;
   uint32_t mPersistCurrentState;
   nsresult mPersistResult;
   uint32_t mPersistFlags;
--- a/xpfe/appshell/nsWebShellWindow.cpp
+++ b/xpfe/appshell/nsWebShellWindow.cpp
@@ -86,16 +86,17 @@ using namespace mozilla::dom;
 /* Define Class IDs */
 static NS_DEFINE_CID(kWindowCID,           NS_WINDOW_CID);
 
 #define SIZE_PERSISTENCE_TIMEOUT 500 // msec
 
 nsWebShellWindow::nsWebShellWindow(uint32_t aChromeFlags)
   : nsXULWindow(aChromeFlags)
   , mSPTimerLock("nsWebShellWindow.mSPTimerLock")
+  , mWidgetListenerDelegate(this)
 {
 }
 
 nsWebShellWindow::~nsWebShellWindow()
 {
   MutexAutoLock lock(mSPTimerLock);
   if (mSPTimer)
     mSPTimer->Cancel();
@@ -175,17 +176,17 @@ nsresult nsWebShellWindow::Initialize(ns
      top-level child windows in OSes that do not. Later.
   */
   nsCOMPtr<nsIBaseWindow> parentAsWin(do_QueryInterface(aParent));
   if (parentAsWin) {
     parentAsWin->GetMainWidget(getter_AddRefs(parentWidget));
     mParentWindow = do_GetWeakReference(aParent);
   }
 
-  mWindow->SetWidgetListener(this);
+  mWindow->SetWidgetListener(&mWidgetListenerDelegate);
   rv = mWindow->Create((nsIWidget *)parentWidget, // Parent nsIWidget
                        nullptr,                   // Native parent widget
                        deskRect,                  // Widget dimensions
                        &widgetInitData);          // Widget initialization data
   NS_ENSURE_SUCCESS(rv, rv);
 
   LayoutDeviceIntRect r = mWindow->GetClientBounds();
   // Match the default background color of content. Important on windows
@@ -777,8 +778,113 @@ NS_IMETHODIMP nsWebShellWindow::Destroy(
     if (mSPTimer) {
       mSPTimer->Cancel();
       SavePersistentAttributes();
       mSPTimer = nullptr;
     }
   }
   return nsXULWindow::Destroy();
 }
+
+nsIXULWindow*
+nsWebShellWindow::WidgetListenerDelegate::GetXULWindow()
+{
+  return mWebShellWindow->GetXULWindow();
+}
+
+nsIPresShell*
+nsWebShellWindow::WidgetListenerDelegate::GetPresShell()
+{
+  return mWebShellWindow->GetPresShell();
+}
+
+bool
+nsWebShellWindow::WidgetListenerDelegate::WindowMoved(
+  nsIWidget* aWidget, int32_t aX, int32_t aY)
+{
+  RefPtr<nsWebShellWindow> holder = mWebShellWindow;
+  return holder->WindowMoved(aWidget, aX, aY);
+}
+
+bool
+nsWebShellWindow::WidgetListenerDelegate::WindowResized(
+  nsIWidget* aWidget, int32_t aWidth, int32_t aHeight)
+{
+  RefPtr<nsWebShellWindow> holder = mWebShellWindow;
+  return holder->WindowResized(aWidget, aWidth, aHeight);
+}
+
+bool
+nsWebShellWindow::WidgetListenerDelegate::RequestWindowClose(nsIWidget* aWidget)
+{
+  RefPtr<nsWebShellWindow> holder = mWebShellWindow;
+  return holder->RequestWindowClose(aWidget);
+}
+
+void
+nsWebShellWindow::WidgetListenerDelegate::SizeModeChanged(nsSizeMode aSizeMode)
+{
+  RefPtr<nsWebShellWindow> holder = mWebShellWindow;
+  holder->SizeModeChanged(aSizeMode);
+}
+
+void
+nsWebShellWindow::WidgetListenerDelegate::UIResolutionChanged()
+{
+  RefPtr<nsWebShellWindow> holder = mWebShellWindow;
+  holder->UIResolutionChanged();
+}
+
+void
+nsWebShellWindow::WidgetListenerDelegate::FullscreenWillChange(
+  bool aInFullscreen)
+{
+  RefPtr<nsWebShellWindow> holder = mWebShellWindow;
+  holder->FullscreenWillChange(aInFullscreen);
+}
+
+void
+nsWebShellWindow::WidgetListenerDelegate::FullscreenChanged(bool aInFullscreen)
+{
+  RefPtr<nsWebShellWindow> holder = mWebShellWindow;
+  holder->FullscreenChanged(aInFullscreen);
+}
+
+void
+nsWebShellWindow::WidgetListenerDelegate::OcclusionStateChanged(
+  bool aIsFullyOccluded)
+{
+  RefPtr<nsWebShellWindow> holder = mWebShellWindow;
+  holder->OcclusionStateChanged(aIsFullyOccluded);
+}
+
+void
+nsWebShellWindow::WidgetListenerDelegate::OSToolbarButtonPressed()
+{
+  RefPtr<nsWebShellWindow> holder = mWebShellWindow;
+  holder->OSToolbarButtonPressed();
+}
+
+bool
+nsWebShellWindow::WidgetListenerDelegate::ZLevelChanged(
+  bool aImmediate, nsWindowZ *aPlacement, nsIWidget* aRequestBelow,
+  nsIWidget** aActualBelow)
+{
+  RefPtr<nsWebShellWindow> holder = mWebShellWindow;
+  return holder->ZLevelChanged(aImmediate,
+                               aPlacement,
+                               aRequestBelow,
+                               aActualBelow);
+}
+
+void
+nsWebShellWindow::WidgetListenerDelegate::WindowActivated()
+{
+  RefPtr<nsWebShellWindow> holder = mWebShellWindow;
+  holder->WindowActivated();
+}
+
+void
+nsWebShellWindow::WidgetListenerDelegate::WindowDeactivated()
+{
+  RefPtr<nsWebShellWindow> holder = mWebShellWindow;
+  holder->WindowDeactivated();
+}
--- a/xpfe/appshell/nsWebShellWindow.h
+++ b/xpfe/appshell/nsWebShellWindow.h
@@ -19,20 +19,67 @@ class nsIURI;
 
 struct nsWidgetInitData;
 
 namespace mozilla {
 class WebShellWindowTimerCallback;
 } // namespace mozilla
 
 class nsWebShellWindow final : public nsXULWindow,
-                               public nsIWebProgressListener,
-                               public nsIWidgetListener
+                               public nsIWebProgressListener
 {
 public:
+
+  // The implementation of non-refcounted nsIWidgetListener, which would hold a
+  // strong reference on stack before calling nsWebShellWindow's
+  // MOZ_CAN_RUN_SCRIPT methods.
+  class WidgetListenerDelegate : public nsIWidgetListener
+  {
+  public:
+    WidgetListenerDelegate(nsWebShellWindow* aWebShellWindow)
+      : mWebShellWindow(aWebShellWindow) {}
+
+    MOZ_CAN_RUN_SCRIPT_BOUNDARY
+    virtual nsIXULWindow* GetXULWindow() override;
+    MOZ_CAN_RUN_SCRIPT_BOUNDARY
+    virtual nsIPresShell* GetPresShell() override;
+    MOZ_CAN_RUN_SCRIPT_BOUNDARY
+    virtual bool WindowMoved(nsIWidget* aWidget, int32_t x, int32_t y) override;
+    MOZ_CAN_RUN_SCRIPT_BOUNDARY
+    virtual bool WindowResized(nsIWidget* aWidget, int32_t aWidth, int32_t aHeight) override;
+    MOZ_CAN_RUN_SCRIPT_BOUNDARY
+    virtual bool RequestWindowClose(nsIWidget* aWidget) override;
+    MOZ_CAN_RUN_SCRIPT_BOUNDARY
+    virtual void SizeModeChanged(nsSizeMode sizeMode) override;
+    MOZ_CAN_RUN_SCRIPT_BOUNDARY
+    virtual void UIResolutionChanged() override;
+    MOZ_CAN_RUN_SCRIPT_BOUNDARY
+    virtual void FullscreenWillChange(bool aInFullscreen) override;
+    MOZ_CAN_RUN_SCRIPT_BOUNDARY
+    virtual void FullscreenChanged(bool aInFullscreen) override;
+    MOZ_CAN_RUN_SCRIPT_BOUNDARY
+    virtual void OcclusionStateChanged(bool aIsFullyOccluded) override;
+    MOZ_CAN_RUN_SCRIPT_BOUNDARY
+    virtual void OSToolbarButtonPressed() override;
+    MOZ_CAN_RUN_SCRIPT_BOUNDARY
+    virtual bool ZLevelChanged(bool aImmediate,
+                               nsWindowZ *aPlacement,
+                               nsIWidget* aRequestBelow,
+                               nsIWidget** aActualBelow) override;
+    MOZ_CAN_RUN_SCRIPT_BOUNDARY
+    virtual void WindowActivated() override;
+    MOZ_CAN_RUN_SCRIPT_BOUNDARY
+    virtual void WindowDeactivated() override;
+
+  private:
+    // The lifetime of WidgetListenerDelegate is bound to nsWebShellWindow so
+    // we just use a raw pointer here.
+    nsWebShellWindow* mWebShellWindow;
+  };
+
   explicit nsWebShellWindow(uint32_t aChromeFlags);
 
   // nsISupports interface...
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsWebShellWindow methods...
   nsresult Initialize(nsIXULWindow * aParent, nsIXULWindow * aOpener,
                       nsIURI* aUrl,
@@ -45,42 +92,45 @@ public:
   nsresult Toolbar();
 
   // nsIWebProgressListener
   NS_DECL_NSIWEBPROGRESSLISTENER
 
   // nsIBaseWindow
   NS_IMETHOD Destroy() override;
 
-  // nsIWidgetListener
-  virtual nsIXULWindow* GetXULWindow() override { return this; }
-  virtual nsIPresShell* GetPresShell() override;
-  virtual bool WindowMoved(nsIWidget* aWidget, int32_t x, int32_t y) override;
-  virtual bool WindowResized(nsIWidget* aWidget, int32_t aWidth, int32_t aHeight) override;
-  virtual bool RequestWindowClose(nsIWidget* aWidget) override;
-  virtual void SizeModeChanged(nsSizeMode sizeMode) override;
-  virtual void UIResolutionChanged() override;
-  virtual void FullscreenWillChange(bool aInFullscreen) override;
-  virtual void FullscreenChanged(bool aInFullscreen) override;
-  virtual void OcclusionStateChanged(bool aIsFullyOccluded) override;
-  virtual void OSToolbarButtonPressed() override;
-  virtual bool ZLevelChanged(bool aImmediate, nsWindowZ *aPlacement,
-                             nsIWidget* aRequestBelow, nsIWidget** aActualBelow) override;
-  virtual void WindowActivated() override;
-  virtual void WindowDeactivated() override;
+  // nsIWidgetListener methods for WidgetListenerDelegate.
+  nsIXULWindow* GetXULWindow() { return this; }
+  nsIPresShell* GetPresShell();
+  MOZ_CAN_RUN_SCRIPT
+  bool WindowMoved(nsIWidget* aWidget, int32_t aX, int32_t aY);
+  MOZ_CAN_RUN_SCRIPT
+  bool WindowResized(nsIWidget* aWidget, int32_t aWidth, int32_t aHeight);
+  MOZ_CAN_RUN_SCRIPT bool RequestWindowClose(nsIWidget* aWidget);
+  MOZ_CAN_RUN_SCRIPT void SizeModeChanged(nsSizeMode aSizeMode);
+  MOZ_CAN_RUN_SCRIPT void UIResolutionChanged();
+  MOZ_CAN_RUN_SCRIPT void FullscreenWillChange(bool aInFullscreen);
+  MOZ_CAN_RUN_SCRIPT void FullscreenChanged(bool aInFullscreen);
+  MOZ_CAN_RUN_SCRIPT void OcclusionStateChanged(bool aIsFullyOccluded);
+  MOZ_CAN_RUN_SCRIPT void OSToolbarButtonPressed();
+  MOZ_CAN_RUN_SCRIPT
+  bool ZLevelChanged(bool aImmediate, nsWindowZ *aPlacement,
+                     nsIWidget* aRequestBelow, nsIWidget** aActualBelow);
+  MOZ_CAN_RUN_SCRIPT void WindowActivated();
+  MOZ_CAN_RUN_SCRIPT void WindowDeactivated();
 
 protected:
   friend class mozilla::WebShellWindowTimerCallback;
 
   virtual ~nsWebShellWindow();
 
   bool                     ExecuteCloseHandler();
   void                     ConstrainToOpenerScreen(int32_t* aX, int32_t* aY);
 
   nsCOMPtr<nsITimer>      mSPTimer;
   mozilla::Mutex          mSPTimerLock;
+  WidgetListenerDelegate  mWidgetListenerDelegate;
 
   void        SetPersistenceTimer(uint32_t aDirtyFlags);
   void        FirePersistenceTimer();
 };
 
-
 #endif /* nsWebShellWindow_h__ */