Bug 1414974 - Part 1: Add the nsGlobalWindowInner/Outer classes, r=smaug
authorNika Layzell <nika@thelayzells.com>
Fri, 03 Nov 2017 15:32:16 -0400
changeset 444268 e71c83eb16f68be36a10ebe1be36a282e0bbe458
parent 444267 9ae742527820a5c0735dd17b0a2bbade6cc593ef
child 444269 ff6e961b87dc1163c5efe35da2e334c6723a14e1
push id1618
push userCallek@gmail.com
push dateThu, 11 Jan 2018 17:45:48 +0000
treeherdermozilla-release@882ca853e05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1414974
milestone58.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 1414974 - Part 1: Add the nsGlobalWindowInner/Outer classes, r=smaug MozReview-Commit-ID: 5fLoC23MuNE
dom/base/nsGlobalWindow.cpp
dom/base/nsGlobalWindow.h
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -9071,17 +9071,17 @@ nsGlobalWindow::GetFramesOuter()
 }
 
 already_AddRefed<nsPIDOMWindowOuter>
 nsGlobalWindow::GetFrames(ErrorResult& aError)
 {
   FORWARD_TO_OUTER_OR_THROW(GetFramesOuter, (), aError, nullptr);
 }
 
-nsGlobalWindow*
+nsGlobalWindowInner*
 nsGlobalWindow::CallerInnerWindow()
 {
   JSContext *cx = nsContentUtils::GetCurrentJSContext();
   NS_ENSURE_TRUE(cx, nullptr);
   nsIGlobalObject* global = GetIncumbentGlobal();
   NS_ENSURE_TRUE(global, nullptr);
   JS::Rooted<JSObject*> scope(cx, global->GetGlobalJSObject());
   NS_ENSURE_TRUE(scope, nullptr);
@@ -9103,17 +9103,17 @@ nsGlobalWindow::CallerInnerWindow()
       global = xpc::NativeGlobal(scopeProto);
       NS_ENSURE_TRUE(global, nullptr);
     }
   }
 
   // The calling window must be holding a reference, so we can return a weak
   // pointer.
   nsCOMPtr<nsPIDOMWindowInner> win = do_QueryInterface(global);
-  return nsGlobalWindow::Cast(win);
+  return nsGlobalWindowInner::Cast(win);
 }
 
 void
 nsGlobalWindow::PostMessageMozOuter(JSContext* aCx, JS::Handle<JS::Value> aMessage,
                                     const nsAString& aTargetOrigin,
                                     JS::Handle<JS::Value> aTransfer,
                                     nsIPrincipal& aSubjectPrincipal,
                                     ErrorResult& aError)
@@ -12990,17 +12990,17 @@ nsGlobalWindow::OpenInternal(const nsASt
 
   return rv;
 }
 
 //*****************************************************************************
 // nsGlobalWindow: Timeout Functions
 //*****************************************************************************
 
-nsGlobalWindow*
+nsGlobalWindowInner*
 nsGlobalWindow::InnerForSetTimeoutOrInterval(ErrorResult& aError)
 {
   nsGlobalWindow* currentInner;
   nsGlobalWindow* forwardTo;
   if (IsInnerWindow()) {
     nsGlobalWindow* outer = GetOuterWindowInternal();
     currentInner = outer ? outer->GetCurrentInnerWindowInternal() : this;
 
@@ -13030,24 +13030,26 @@ nsGlobalWindow::InnerForSetTimeoutOrInte
     if (forwardTo->GetOuterWindow() != AsOuter() ||
         !forwardTo->IsInnerWindow()) {
       if (!currentInner) {
         NS_WARNING("No inner window available!");
         aError.Throw(NS_ERROR_NOT_INITIALIZED);
         return nullptr;
       }
 
-      return currentInner;
+      return static_cast<nsGlobalWindowInner*>(currentInner);
     }
   }
 
   // If forwardTo is not the window with an active document then we want the
   // call to setTimeout/Interval to be a noop, so return null but don't set an
   // error.
-  return forwardTo->AsInner()->HasActiveDocument() ? currentInner : nullptr;
+  return forwardTo->AsInner()->HasActiveDocument()
+    ? static_cast<nsGlobalWindowInner*>(currentInner)
+    : nullptr;
 }
 
 int32_t
 nsGlobalWindow::SetTimeout(JSContext* aCx, Function& aFunction,
                            int32_t aTimeout,
                            const Sequence<JS::Value>& aArguments,
                            ErrorResult& aError)
 {
@@ -14003,17 +14005,23 @@ nsGlobalWindow::DispatchVRDisplayPresent
       return;
     }
   }
 }
 
 /* static */ already_AddRefed<nsGlobalWindow>
 nsGlobalWindow::CreateChrome(nsGlobalWindow *aOuterWindow)
 {
-  RefPtr<nsGlobalWindow> window = new nsGlobalWindow(aOuterWindow);
+  RefPtr<nsGlobalWindow> window;
+  if (aOuterWindow) {
+    window = new nsGlobalWindowInner(
+      static_cast<nsGlobalWindowOuter*>(aOuterWindow));
+  } else {
+    window = new nsGlobalWindowOuter();
+  }
   window->mIsChrome = true;
   window->mCleanMessageManager = true;
 
   window->InitWasOffline();
   return window.forget();
 }
 
 enum WindowState {
@@ -14394,17 +14402,23 @@ nsGlobalWindow::TakeOpenerForInitialCont
   // Intentionally forget our own member
   mChromeFields.mOpenerForInitialContentBrowser.forget(aOpenerWindow);
   return NS_OK;
 }
 
 /* static */ already_AddRefed<nsGlobalWindow>
 nsGlobalWindow::Create(nsGlobalWindow *aOuterWindow)
 {
-  RefPtr<nsGlobalWindow> window = new nsGlobalWindow(aOuterWindow);
+  RefPtr<nsGlobalWindow> window;
+  if (aOuterWindow) {
+    window = new nsGlobalWindowInner(
+      static_cast<nsGlobalWindowOuter*>(aOuterWindow));
+  } else {
+    window = new nsGlobalWindowOuter();
+  }
   window->InitWasOffline();
   return window.forget();
 }
 
 void
 nsGlobalWindow::InitWasOffline()
 {
   mWasOffline = NS_IsOffline();
@@ -15051,11 +15065,19 @@ nsGlobalWindow::GetIntlUtils(ErrorResult
 
   if (!mIntlUtils) {
     mIntlUtils = new IntlUtils(AsInner());
   }
 
   return mIntlUtils;
 }
 
+nsGlobalWindowOuter::nsGlobalWindowOuter()
+  : nsGlobalWindow(nullptr)
+{}
+
+nsGlobalWindowInner::nsGlobalWindowInner(nsGlobalWindowOuter* aOuterWindow)
+  : nsGlobalWindow(aOuterWindow)
+{}
+
 template class nsPIDOMWindow<mozIDOMWindowProxy>;
 template class nsPIDOMWindow<mozIDOMWindow>;
 template class nsPIDOMWindow<nsISupports>;
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -223,16 +223,19 @@ public:
            JS::MutableHandle<JS::Value> aResult, mozilla::ErrorResult& aError);
 private:
   virtual ~DialogValueHolder() {}
 
   nsCOMPtr<nsIPrincipal> mOrigin;
   nsCOMPtr<nsIVariant> mValue;
 };
 
+class nsGlobalWindowInner;
+class nsGlobalWindowOuter;
+
 //*****************************************************************************
 // nsGlobalWindow: Global Object for Scripting
 //*****************************************************************************
 // Beware that all scriptable interfaces implemented by
 // nsGlobalWindow will be reachable from JS, if you make this class
 // implement new interfaces you better know what you're
 // doing. Security wise this is very sensitive code. --
 // jst@netscape.com
@@ -368,24 +371,17 @@ public:
   using mozilla::dom::EventTarget::RemoveEventListener;
   virtual void AddEventListener(const nsAString& aType,
                                 mozilla::dom::EventListener* aListener,
                                 const mozilla::dom::AddEventListenerOptionsOrBoolean& aOptions,
                                 const mozilla::dom::Nullable<bool>& aWantsUntrusted,
                                 mozilla::ErrorResult& aRv) override;
   virtual nsPIDOMWindowOuter* GetOwnerGlobalForBindings() override;
 
-  virtual nsIGlobalObject* GetOwnerGlobal() const override
-  {
-    if (IsOuterWindow()) {
-      return GetCurrentInnerWindowInternal();
-    }
-
-    return const_cast<nsGlobalWindow*>(this);
-  }
+  virtual nsIGlobalObject* GetOwnerGlobal() const override;
 
   // nsPIDOMWindow
   virtual nsPIDOMWindowOuter* GetPrivateRoot() override;
 
   // Outer windows only.
   virtual void ActivateOrDeactivate(bool aActivate) override;
   virtual void SetActive(bool aActive) override;
   virtual bool IsTopLevelWindowActive() override;
@@ -501,31 +497,19 @@ public:
     return (nsGlobalWindow *)(mozilla::dom::EventTarget *)supports;
   }
   static nsGlobalWindow *FromWrapper(nsIXPConnectWrappedNative *wrapper)
   {
     return FromSupports(wrapper->Native());
   }
   already_AddRefed<nsPIDOMWindowOuter> GetTop() override;
   nsPIDOMWindowOuter* GetScriptableTop() override;
-  inline nsGlobalWindow *GetTopInternal()
-  {
-    nsGlobalWindow* outer = IsOuterWindow() ? this : GetOuterWindowInternal();
-    nsCOMPtr<nsPIDOMWindowOuter> top = outer ? outer->GetTop() : nullptr;
-    if (top) {
-      return nsGlobalWindow::Cast(top);
-    }
-    return nullptr;
-  }
+  inline nsGlobalWindowOuter *GetTopInternal();
 
-  inline nsGlobalWindow* GetScriptableTopInternal()
-  {
-    nsPIDOMWindowOuter* top = GetScriptableTop();
-    return nsGlobalWindow::Cast(top);
-  }
+  inline nsGlobalWindowOuter* GetScriptableTopInternal();
 
   nsPIDOMWindowOuter* GetChildWindow(const nsAString& aName);
 
   // These return true if we've reached the state in this top level window
   // where we ask the user if further dialogs should be blocked.
   //
   // DialogsAreBeingAbused must be called on the scriptable top inner window.
   //
@@ -564,40 +548,23 @@ public:
     RefPtr<nsGlobalWindow> mTopWindow;
     // This is not a AutoRestore<bool> because that would require careful
     // member destructor ordering, which is a bit fragile.  This way we can
     // explicitly restore things before we drop our ref to mTopWindow.
     bool mSavedDialogsEnabled;
   };
   friend class TemporarilyDisableDialogs;
 
-  nsIScriptContext *GetContextInternal()
-  {
-    if (mOuterWindow) {
-      return GetOuterWindowInternal()->mContext;
-    }
+  nsIScriptContext *GetContextInternal();
 
-    return mContext;
-  }
+  nsGlobalWindowOuter *GetOuterWindowInternal();
 
-  nsGlobalWindow *GetOuterWindowInternal()
-  {
-    return nsGlobalWindow::Cast(GetOuterWindow());
-  }
+  nsGlobalWindowInner* GetCurrentInnerWindowInternal() const;
 
-  nsGlobalWindow* GetCurrentInnerWindowInternal() const
-  {
-    MOZ_ASSERT(IsOuterWindow());
-    return nsGlobalWindow::Cast(mInnerWindow);
-  }
-
-  nsGlobalWindow* EnsureInnerWindowInternal()
-  {
-    return nsGlobalWindow::Cast(AsOuter()->EnsureInnerWindow());
-  }
+  nsGlobalWindowInner* EnsureInnerWindowInternal();
 
   bool IsCreatingInnerWindow() const
   {
     return mCreatingInnerWindow;
   }
 
   bool IsChromeWindow() const
   {
@@ -677,55 +644,31 @@ public:
 
   bool
   HadOriginalOpener() const
   {
     MOZ_ASSERT(IsOuterWindow());
     return mHadOriginalOpener;
   }
 
-  bool
-  IsTopLevelWindow()
-  {
-    MOZ_ASSERT(IsOuterWindow());
-    nsPIDOMWindowOuter* parentWindow = GetScriptableTop();
-    return parentWindow == this->AsOuter();
-  }
+  bool IsTopLevelWindow();
 
   virtual void
   FirePopupBlockedEvent(nsIDocument* aDoc,
                         nsIURI* aPopupURI,
                         const nsAString& aPopupWindowName,
                         const nsAString& aPopupWindowFeatures) override;
 
   virtual uint32_t GetSerial() override {
     return mSerial;
   }
 
-  static nsGlobalWindow* GetOuterWindowWithId(uint64_t aWindowID) {
-    AssertIsOnMainThread();
-
-    if (!sWindowsById) {
-      return nullptr;
-    }
-
-    nsGlobalWindow* outerWindow = sWindowsById->Get(aWindowID);
-    return outerWindow && !outerWindow->IsInnerWindow() ? outerWindow : nullptr;
-  }
+  static nsGlobalWindowOuter* GetOuterWindowWithId(uint64_t aWindowID);
 
-  static nsGlobalWindow* GetInnerWindowWithId(uint64_t aInnerWindowID) {
-    AssertIsOnMainThread();
-
-    if (!sWindowsById) {
-      return nullptr;
-    }
-
-    nsGlobalWindow* innerWindow = sWindowsById->Get(aInnerWindowID);
-    return innerWindow && innerWindow->IsInnerWindow() ? innerWindow : nullptr;
-  }
+  static nsGlobalWindowInner* GetInnerWindowWithId(uint64_t aInnerWindowID);
 
   static WindowByIdTable* GetWindowsTable() {
     AssertIsOnMainThread();
 
     return sWindowsById;
   }
 
   void AddSizeOfIncludingThis(nsWindowSizes& aWindowSizes) const;
@@ -1468,38 +1411,31 @@ protected:
   inline void MaybeClearInnerWindow(nsGlobalWindow* aExpectedInner)
   {
     if(mInnerWindow == aExpectedInner->AsInner()) {
       mInnerWindow = nullptr;
     }
   }
 
   void FreeInnerObjects();
-  nsGlobalWindow *CallerInnerWindow();
+  nsGlobalWindowInner *CallerInnerWindow();
 
   // Only to be called on an inner window.
   // aDocument must not be null.
   void InnerSetNewDocument(JSContext* aCx, nsIDocument* aDocument);
 
   // Inner windows only.
   nsresult DefineArgumentsProperty(nsIArray *aArguments);
 
   // Get the parent, returns null if this is a toplevel window
   nsPIDOMWindowOuter* GetParentInternal();
 
 public:
   // popup tracking
-  bool IsPopupSpamWindow()
-  {
-    if (IsInnerWindow() && !mOuterWindow) {
-      return false;
-    }
-
-    return GetOuterWindowInternal()->mIsPopupSpam;
-  }
+  bool IsPopupSpamWindow();
 
   // Outer windows only.
   void SetIsPopupSpamWindow(bool aIsPopupSpam);
 
 protected:
   // Window Control Functions
 
   // Outer windows only.
@@ -1664,20 +1600,17 @@ public:
   void SetOuterSize(int32_t aLengthCSSPixels, bool aIsWidth,
                     mozilla::dom::CallerType aCallerType,
                     mozilla::ErrorResult& aError);
   nsRect GetInnerScreenRect();
 
   void ScrollTo(const mozilla::CSSIntPoint& aScroll,
                 const mozilla::dom::ScrollOptions& aOptions);
 
-  bool IsFrame()
-  {
-    return GetParentInternal() != nullptr;
-  }
+  bool IsFrame();
 
   // Outer windows only.
   // If aLookForCallerOnJSStack is true, this method will look at the JS stack
   // to determine who the caller is.  If it's false, it'll use |this| as the
   // caller.
   bool WindowExists(const nsAString& aName, bool aForceNoOpener,
                     bool aLookForCallerOnJSStack);
 
@@ -1754,17 +1687,17 @@ protected:
 
   // Outer windows only.
   void PreloadLocalStorage();
 
   // Returns CSS pixels based on primary screen.  Outer windows only.
   mozilla::CSSIntPoint GetScreenXY(mozilla::dom::CallerType aCallerType,
                                    mozilla::ErrorResult& aError);
 
-  nsGlobalWindow* InnerForSetTimeoutOrInterval(mozilla::ErrorResult& aError);
+  nsGlobalWindowInner* InnerForSetTimeoutOrInterval(mozilla::ErrorResult& aError);
 
   void PostMessageMozOuter(JSContext* aCx, JS::Handle<JS::Value> aMessage,
                            const nsAString& aTargetOrigin,
                            JS::Handle<JS::Value> aTransfer,
                            nsIPrincipal& aSubjectPrincipal,
                            mozilla::ErrorResult& aError);
   void PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
                       const nsAString& aTargetOrigin,
@@ -2099,24 +2032,177 @@ ToSupports(nsGlobalWindow *p)
 }
 
 inline nsISupports*
 ToCanonicalSupports(nsGlobalWindow *p)
 {
     return static_cast<nsIDOMEventTarget*>(p);
 }
 
+class nsGlobalWindowOuter : public nsGlobalWindow
+{
+public:
+  friend class nsGlobalWindow;
+
+  static nsGlobalWindowOuter* Cast(nsPIDOMWindowOuter* aPIWin) {
+    return static_cast<nsGlobalWindowOuter*>(
+                        reinterpret_cast<nsPIDOMWindow<nsISupports>*>(aPIWin));
+  }
+  static const nsGlobalWindowOuter* Cast(const nsPIDOMWindowOuter* aPIWin) {
+    return static_cast<const nsGlobalWindowOuter*>(
+                        reinterpret_cast<const nsPIDOMWindow<nsISupports>*>(aPIWin));
+  }
+  static nsGlobalWindowOuter* Cast(mozIDOMWindowProxy* aWin) {
+    return Cast(nsPIDOMWindowOuter::From(aWin));
+  }
+
+private:
+  nsGlobalWindowOuter();
+};
+
+class nsGlobalWindowInner : public nsGlobalWindow
+{
+public:
+  friend class nsGlobalWindow;
+
+  static nsGlobalWindowInner* Cast(nsPIDOMWindowInner* aPIWin) {
+    return static_cast<nsGlobalWindowInner*>(
+                        reinterpret_cast<nsPIDOMWindow<nsISupports>*>(aPIWin));
+  }
+  static const nsGlobalWindowInner* Cast(const nsPIDOMWindowInner* aPIWin) {
+    return static_cast<const nsGlobalWindowInner*>(
+                        reinterpret_cast<const nsPIDOMWindow<nsISupports>*>(aPIWin));
+  }
+  static nsGlobalWindowInner* Cast(mozIDOMWindow* aWin) {
+    return Cast(nsPIDOMWindowInner::From(aWin));
+  }
+
+private:
+  explicit nsGlobalWindowInner(nsGlobalWindowOuter* aOuter);
+};
+
+inline nsIGlobalObject*
+nsGlobalWindow::GetOwnerGlobal() const
+{
+  if (IsOuterWindow()) {
+    return GetCurrentInnerWindowInternal();
+  }
+
+  return const_cast<nsGlobalWindow*>(this);
+}
+
+inline nsGlobalWindowOuter*
+nsGlobalWindow::GetTopInternal()
+{
+  nsGlobalWindow* outer = IsOuterWindow() ? this : GetOuterWindowInternal();
+  nsCOMPtr<nsPIDOMWindowOuter> top = outer ? outer->GetTop() : nullptr;
+  if (top) {
+    return nsGlobalWindowOuter::Cast(top);
+  }
+  return nullptr;
+}
+
+inline nsGlobalWindowOuter*
+nsGlobalWindow::GetScriptableTopInternal()
+{
+  nsPIDOMWindowOuter* top = GetScriptableTop();
+  return nsGlobalWindowOuter::Cast(top);
+}
+
+inline nsIScriptContext*
+nsGlobalWindow::GetContextInternal()
+  {
+    if (mOuterWindow) {
+      return GetOuterWindowInternal()->mContext;
+    }
+
+    return mContext;
+  }
+
+inline nsGlobalWindowOuter*
+nsGlobalWindow::GetOuterWindowInternal()
+{
+  return nsGlobalWindowOuter::Cast(GetOuterWindow());
+}
+
+inline nsGlobalWindowInner*
+nsGlobalWindow::GetCurrentInnerWindowInternal() const
+{
+  MOZ_ASSERT(IsOuterWindow());
+  return nsGlobalWindowInner::Cast(mInnerWindow);
+}
+
+inline nsGlobalWindowInner*
+nsGlobalWindow::EnsureInnerWindowInternal()
+{
+  return nsGlobalWindowInner::Cast(AsOuter()->EnsureInnerWindow());
+}
+
+inline bool
+nsGlobalWindow::IsTopLevelWindow()
+{
+  MOZ_ASSERT(IsOuterWindow());
+  nsPIDOMWindowOuter* parentWindow = GetScriptableTop();
+  return parentWindow == this->AsOuter();
+}
+
+inline nsGlobalWindowOuter*
+nsGlobalWindow::GetOuterWindowWithId(uint64_t aWindowID)
+{
+  AssertIsOnMainThread();
+
+  if (!sWindowsById) {
+    return nullptr;
+  }
+
+  nsGlobalWindow* outerWindow = sWindowsById->Get(aWindowID);
+  return outerWindow && !outerWindow->IsInnerWindow()
+    ? static_cast<nsGlobalWindowOuter*>(outerWindow)
+    : nullptr;
+}
+
+inline nsGlobalWindowInner*
+nsGlobalWindow::GetInnerWindowWithId(uint64_t aInnerWindowID)
+{
+  AssertIsOnMainThread();
+
+  if (!sWindowsById) {
+    return nullptr;
+  }
+
+  nsGlobalWindow* innerWindow = sWindowsById->Get(aInnerWindowID);
+  return innerWindow && innerWindow->IsInnerWindow()
+    ? static_cast<nsGlobalWindowInner*>(innerWindow)
+    : nullptr;
+}
+
+inline bool
+nsGlobalWindow::IsPopupSpamWindow()
+{
+  if (IsInnerWindow() && !mOuterWindow) {
+    return false;
+  }
+
+  return GetOuterWindowInternal()->mIsPopupSpam;
+}
+
+inline bool
+nsGlobalWindow::IsFrame()
+{
+  return GetParentInternal() != nullptr;
+}
+
 /* factory function */
-inline already_AddRefed<nsGlobalWindow>
+inline already_AddRefed<nsGlobalWindowOuter>
 NS_NewScriptGlobalObject(bool aIsChrome)
 {
   RefPtr<nsGlobalWindow> global;
 
   if (aIsChrome) {
     global = nsGlobalWindow::CreateChrome(nullptr);
   } else {
     global = nsGlobalWindow::Create(nullptr);
   }
 
-  return global.forget();
+  return global.forget().downcast<nsGlobalWindowOuter>();
 }
 
 #endif /* nsGlobalWindow_h___ */