Bug 1267720 - Add methods to nsIDocShellTreeOwner for sizing the primary content. r?smaug draft
authorMike Conley <mconley@mozilla.com>
Thu, 12 May 2016 19:08:27 -0400
changeset 374660 49a88be91c6c3c5d7e5a0e0540160dcc6d275598
parent 374659 f32816044c56ab435ac911022ec61acd5f2c149a
child 374661 e9f79f5c737a7c6635bd6ed4f793a7f8b49c6328
push id20055
push usermconley@mozilla.com
push dateThu, 02 Jun 2016 19:00:42 +0000
reviewerssmaug
bugs1267720
milestone49.0a1
Bug 1267720 - Add methods to nsIDocShellTreeOwner for sizing the primary content. r?smaug MozReview-Commit-ID: CqiRTVd444n
docshell/base/nsIDocShellTreeOwner.idl
embedding/browser/nsDocShellTreeOwner.cpp
embedding/components/windowwatcher/nsWindowWatcher.cpp
embedding/components/windowwatcher/nsWindowWatcher.h
xpfe/appshell/moz.build
xpfe/appshell/nsChromeTreeOwner.cpp
xpfe/appshell/nsContentTreeOwner.cpp
xpfe/appshell/nsXULWindow.cpp
xpfe/appshell/nsXULWindow.h
--- a/docshell/base/nsIDocShellTreeOwner.idl
+++ b/docshell/base/nsIDocShellTreeOwner.idl
@@ -75,16 +75,19 @@ interface nsIDocShellTreeOwner : nsISupp
 	readonly attribute nsITabParent primaryTabParent;
 
 	/*
 	Tells the tree owner to size its window or parent window in such a way
 	that the shell passed along will be the size specified.
 	*/
 	void sizeShellTo(in nsIDocShellTreeItem shell, in long cx, in long cy);
 
+	void getPrimaryContentSize(out long width, out long height);
+	void setPrimaryContentSize(in long width, in long height);
+
 	/*
 	Sets the persistence of different attributes of the window.
 	*/
 	void setPersistence(in boolean aPersistPosition,
                             in boolean aPersistSize,
                             in boolean aPersistSizeMode);
 
 	/*
--- a/embedding/browser/nsDocShellTreeOwner.cpp
+++ b/embedding/browser/nsDocShellTreeOwner.cpp
@@ -439,16 +439,30 @@ nsDocShellTreeOwner::GetPrimaryTabParent
   }
 
   nsCOMPtr<nsITabParent> tab = mPrimaryTabParent;
   tab.forget(aTab);
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsDocShellTreeOwner::GetPrimaryContentSize(int32_t* aWidth,
+                                           int32_t* aHeight)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsDocShellTreeOwner::SetPrimaryContentSize(int32_t aWidth,
+                                           int32_t aHeight)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
 nsDocShellTreeOwner::SizeShellTo(nsIDocShellTreeItem* aShellItem,
                                  int32_t aCX, int32_t aCY)
 {
   nsCOMPtr<nsIWebBrowserChrome> webBrowserChrome = GetWebBrowserChrome();
 
   NS_ENSURE_STATE(mTreeOwner || webBrowserChrome);
 
   if (mTreeOwner) {
--- a/embedding/components/windowwatcher/nsWindowWatcher.cpp
+++ b/embedding/components/windowwatcher/nsWindowWatcher.cpp
@@ -563,18 +563,18 @@ nsWindowWatcher::OpenWindowForTablessCon
   chromeContext->SetPrivateBrowsing(isPrivateBrowsingWindow);
   // Tabs opened from a content process can only open new windows
   // that will also run with out-of-process tabs.
   chromeContext->SetRemoteTabs(true);
 
   SizeSpec sizeSpec;
   CalcSizeSpec(EmptyCString(), sizeSpec);
   float fullZoom = 1.0f;
-  SizeOpenedDocShellItem(chromeTreeItem, parentWindowOuter, false, sizeSpec,
-                         &fullZoom);
+  SizeOpenedWindow(chromeTreeOwner, parentWindowOuter, false, sizeSpec,
+                   &fullZoom);
 
   nsCOMPtr<nsITabParent> newTabParent;
   chromeTreeOwner->GetPrimaryTabParent(getter_AddRefs(newTabParent));
   if (NS_WARN_IF(!newTabParent)) {
     return NS_ERROR_UNEXPECTED;
   }
 
   newTabParent.forget(aResult);
@@ -702,18 +702,18 @@ nsWindowWatcher::OpenWindowForTabContent
   chromeContext->SetPrivateBrowsing(isPrivateBrowsingWindow);
 
   // Tabs opened from a content process can only open new windows
   // that will also run with out-of-process tabs.
   chromeContext->SetRemoteTabs(true);
 
   SizeSpec sizeSpec;
   CalcSizeSpec(features, sizeSpec);
-  SizeOpenedDocShellItem(chromeTreeItem, parentWindowOuter, false, sizeSpec,
-                         &aOpenerFullZoom);
+  SizeOpenedWindow(chromeTreeOwner, parentWindowOuter, false, sizeSpec,
+                   &aOpenerFullZoom);
 
   nsCOMPtr<nsITabParent> newTabParent;
   chromeTreeOwner->GetPrimaryTabParent(getter_AddRefs(newTabParent));
   if (NS_WARN_IF(!newTabParent)) {
     return NS_ERROR_UNEXPECTED;
   }
 
   newTabParent.forget(aResult);
@@ -1296,18 +1296,20 @@ nsWindowWatcher::OpenWindowInternal(mozI
                                        getter_AddRefs(storage));
       if (storage) {
         newStorageManager->CloneStorage(storage);
       }
     }
   }
 
   if (isNewToplevelWindow) {
-    SizeOpenedDocShellItem(newDocShellItem, aParent, isCallerChrome, sizeSpec,
-                           aOpenerFullZoom);
+    nsCOMPtr<nsIDocShellTreeOwner> newTreeOwner;
+    newDocShellItem->GetTreeOwner(getter_AddRefs(newTreeOwner));
+    SizeOpenedWindow(newTreeOwner, aParent, isCallerChrome, sizeSpec,
+                     aOpenerFullZoom);
   }
 
   // XXXbz isn't windowIsModal always true when windowIsModalContentDialog?
   if (windowIsModal || windowIsModalContentDialog) {
     nsCOMPtr<nsIDocShellTreeOwner> newTreeOwner;
     newDocShellItem->GetTreeOwner(getter_AddRefs(newTreeOwner));
     nsCOMPtr<nsIWebBrowserChrome> newChrome(do_GetInterface(newTreeOwner));
 
@@ -2338,33 +2340,35 @@ nsWindowWatcher::CalcSizeSpec(const nsAC
 }
 
 /* Size and position the new window according to aSizeSpec. This method
    is assumed to be called after the window has already been given
    a default position and size; thus its current position and size are
    accurate defaults. The new window is made visible at method end.
 */
 void
-nsWindowWatcher::SizeOpenedDocShellItem(nsIDocShellTreeItem* aDocShellItem,
-                                        mozIDOMWindowProxy* aParent,
-                                        bool aIsCallerChrome,
-                                        const SizeSpec& aSizeSpec,
-                                        float* aOpenerFullZoom)
+nsWindowWatcher::SizeOpenedWindow(nsIDocShellTreeOwner* aTreeOwner,
+                                  mozIDOMWindowProxy* aParent,
+                                  bool aIsCallerChrome,
+                                  const SizeSpec& aSizeSpec,
+                                  float* aOpenerFullZoom)
 {
+  // We should only be sizing top-level windows if we're in the parent
+  // process.
+  MOZ_ASSERT(XRE_IsParentProcess());
+
   // position and size of window
   int32_t left = 0, top = 0, width = 100, height = 100;
   // difference between chrome and content size
   int32_t chromeWidth = 0, chromeHeight = 0;
   // whether the window size spec refers to chrome or content
   bool sizeChromeWidth = true, sizeChromeHeight = true;
 
   // get various interfaces for aDocShellItem, used throughout this method
-  nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
-  aDocShellItem->GetTreeOwner(getter_AddRefs(treeOwner));
-  nsCOMPtr<nsIBaseWindow> treeOwnerAsWin(do_QueryInterface(treeOwner));
+  nsCOMPtr<nsIBaseWindow> treeOwnerAsWin(do_QueryInterface(aTreeOwner));
   if (!treeOwnerAsWin) { // we'll need this to actually size the docshell
     return;
   }
 
   double openerZoom = aOpenerFullZoom ? *aOpenerFullZoom : 1.0;
   if (aParent && !aOpenerFullZoom) {
     nsCOMPtr<nsPIDOMWindowOuter> piWindow = nsPIDOMWindowOuter::From(aParent);
     if (nsIDocument* doc = piWindow->GetDoc()) {
@@ -2387,26 +2391,20 @@ nsWindowWatcher::SizeOpenedDocShellItem(
      back from too far off the right or bottom edges of the screen. */
 
   treeOwnerAsWin->GetPositionAndSize(&left, &top, &width, &height);
   left = NSToIntRound(left / scale);
   top = NSToIntRound(top / scale);
   width = NSToIntRound(width / scale);
   height = NSToIntRound(height / scale);
   {
-    // scope shellWindow why not
-    nsCOMPtr<nsIBaseWindow> shellWindow(do_QueryInterface(aDocShellItem));
-    if (shellWindow) {
-      int32_t cox, coy;
-      double shellScale;
-      shellWindow->GetSize(&cox, &coy);
-      shellWindow->GetUnscaledDevicePixelsPerCSSPixel(&shellScale);
-      chromeWidth = width - NSToIntRound(cox / shellScale);
-      chromeHeight = height - NSToIntRound(coy / shellScale);
-    }
+    int32_t contentWidth, contentHeight;
+    aTreeOwner->GetPrimaryContentSize(&contentWidth, &contentHeight);
+    chromeWidth = width - contentWidth;
+    chromeHeight = height - contentHeight;
   }
 
   // Set up left/top
   if (aSizeSpec.mLeftSpecified) {
     left = NSToIntRound(aSizeSpec.mLeft * openerZoom);
   }
 
   if (aSizeSpec.mTopSpecified) {
@@ -2448,17 +2446,16 @@ nsWindowWatcher::SizeOpenedDocShellItem(
   if (aIsCallerChrome) {
     // Only enable special priveleges for chrome when chrome calls
     // open() on a chrome window
     nsCOMPtr<nsIDOMChromeWindow> chromeWin(do_QueryInterface(aParent));
     enabled = !aParent || chromeWin;
   }
 
   if (!enabled) {
-
     // Security check failed.  Ensure all args meet minimum reqs.
 
     int32_t oldTop = top, oldLeft = left;
 
     // We'll also need the screen dimensions
     nsCOMPtr<nsIScreen> screen;
     nsCOMPtr<nsIScreenManager> screenMgr(
       do_GetService("@mozilla.org/gfx/screenmanager;1"));
@@ -2547,17 +2544,17 @@ nsWindowWatcher::SizeOpenedDocShellItem(
     // wherever it really ended up
     treeOwnerAsWin->GetUnscaledDevicePixelsPerCSSPixel(&scale);
   }
   if (aSizeSpec.SizeSpecified()) {
     /* Prefer to trust the interfaces, which think in terms of pure
        chrome or content sizes. If we have a mix, use the chrome size
        adjusted by the chrome/content differences calculated earlier. */
     if (!sizeChromeWidth && !sizeChromeHeight) {
-      treeOwner->SizeShellTo(aDocShellItem, width * scale, height * scale);
+      aTreeOwner->SetPrimaryContentSize(width * scale, height * scale);
     } else {
       if (!sizeChromeWidth) {
         width += chromeWidth;
       }
       if (!sizeChromeHeight) {
         height += chromeHeight;
       }
       treeOwnerAsWin->SetSize(width * scale, height * scale, false);
--- a/embedding/components/windowwatcher/nsWindowWatcher.h
+++ b/embedding/components/windowwatcher/nsWindowWatcher.h
@@ -102,21 +102,21 @@ protected:
   static int32_t WinHasOption(const nsACString& aOptions, const char* aName,
                               int32_t aDefault, bool* aPresenceFlag);
   /* Compute the right SizeSpec based on aFeatures */
   static void CalcSizeSpec(const nsACString& aFeatures, SizeSpec& aResult);
   static nsresult ReadyOpenedDocShellItem(nsIDocShellTreeItem* aOpenedItem,
                                           nsPIDOMWindowOuter* aParent,
                                           bool aWindowIsNew,
                                           mozIDOMWindowProxy** aOpenedWindow);
-  static void SizeOpenedDocShellItem(nsIDocShellTreeItem* aDocShellItem,
-                                     mozIDOMWindowProxy* aParent,
-                                     bool aIsCallerChrome,
-                                     const SizeSpec& aSizeSpec,
-                                     float* aOpenerFullZoom);
+  static void SizeOpenedWindow(nsIDocShellTreeOwner* aTreeOwner,
+                               mozIDOMWindowProxy* aParent,
+                               bool aIsCallerChrome,
+                               const SizeSpec& aSizeSpec,
+                               float* aOpenerFullZoom);
   static void GetWindowTreeItem(mozIDOMWindowProxy* aWindow,
                                 nsIDocShellTreeItem** aResult);
   static void GetWindowTreeOwner(nsPIDOMWindowOuter* aWindow,
                                  nsIDocShellTreeOwner** aResult);
 
   nsTArray<nsWatcherWindowEnumerator*> mEnumeratorList;
   nsWatcherWindowEntry* mOldestWindow;
   mozilla::Mutex mListLock;
--- a/xpfe/appshell/moz.build
+++ b/xpfe/appshell/moz.build
@@ -33,8 +33,10 @@ UNIFIED_SOURCES += [
     'nsXULWindow.cpp',
 ]
 
 LOCAL_INCLUDES += [
     '/dom/base',
 ]
 
 FINAL_LIBRARY = 'xul'
+
+include('/ipc/chromium/chromium-config.mozbuild')
\ No newline at end of file
--- a/xpfe/appshell/nsChromeTreeOwner.cpp
+++ b/xpfe/appshell/nsChromeTreeOwner.cpp
@@ -264,16 +264,32 @@ nsChromeTreeOwner::TabParentRemoved(nsIT
 
 NS_IMETHODIMP
 nsChromeTreeOwner::GetPrimaryTabParent(nsITabParent** aTab)
 {
   NS_ENSURE_STATE(mXULWindow);
   return mXULWindow->GetPrimaryTabParent(aTab);
 }
 
+NS_IMETHODIMP
+nsChromeTreeOwner::GetPrimaryContentSize(int32_t* aWidth,
+                                         int32_t* aHeight)
+{
+  NS_ENSURE_STATE(mXULWindow);
+  return mXULWindow->GetPrimaryContentSize(aWidth, aHeight);
+}
+
+NS_IMETHODIMP
+nsChromeTreeOwner::SetPrimaryContentSize(int32_t aWidth,
+                                         int32_t aHeight)
+{
+  NS_ENSURE_STATE(mXULWindow);
+  return mXULWindow->SetPrimaryContentSize(aWidth, aHeight);
+}
+
 NS_IMETHODIMP nsChromeTreeOwner::SizeShellTo(nsIDocShellTreeItem* aShellItem,
    int32_t aCX, int32_t aCY)
 {
    NS_ENSURE_STATE(mXULWindow);
    return mXULWindow->SizeShellTo(aShellItem, aCX, aCY);
 }
 
 NS_IMETHODIMP
--- a/xpfe/appshell/nsContentTreeOwner.cpp
+++ b/xpfe/appshell/nsContentTreeOwner.cpp
@@ -329,16 +329,32 @@ nsContentTreeOwner::TabParentRemoved(nsI
 
 NS_IMETHODIMP
 nsContentTreeOwner::GetPrimaryTabParent(nsITabParent** aTab)
 {
   NS_ENSURE_STATE(mXULWindow);
   return mXULWindow->GetPrimaryTabParent(aTab);
 }
 
+NS_IMETHODIMP
+nsContentTreeOwner::GetPrimaryContentSize(int32_t* aWidth,
+                                          int32_t* aHeight)
+{
+  NS_ENSURE_STATE(mXULWindow);
+  return mXULWindow->GetPrimaryContentSize(aWidth, aHeight);
+}
+
+NS_IMETHODIMP
+nsContentTreeOwner::SetPrimaryContentSize(int32_t aWidth,
+                                          int32_t aHeight)
+{
+  NS_ENSURE_STATE(mXULWindow);
+  return mXULWindow->SetPrimaryContentSize(aWidth, aHeight);
+}
+
 NS_IMETHODIMP nsContentTreeOwner::SizeShellTo(nsIDocShellTreeItem* aShellItem,
    int32_t aCX, int32_t aCY)
 {
    NS_ENSURE_STATE(mXULWindow);
    return mXULWindow->SizeShellTo(aShellItem, aCX, aCY);
 }
 
 NS_IMETHODIMP
--- a/xpfe/appshell/nsXULWindow.cpp
+++ b/xpfe/appshell/nsXULWindow.cpp
@@ -56,16 +56,17 @@
 #include "prenv.h"
 #include "mozilla/AutoRestore.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "mozilla/dom/BarProps.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/Event.h"
 #include "mozilla/dom/ScriptSettings.h"
+#include "mozilla/dom/TabParent.h"
 
 using namespace mozilla;
 using dom::AutoNoJSAPI;
 
 #define SIZEMODE_NORMAL     NS_LITERAL_STRING("normal")
 #define SIZEMODE_MAXIMIZED  NS_LITERAL_STRING("maximized")
 #define SIZEMODE_MINIMIZED  NS_LITERAL_STRING("minimized")
 #define SIZEMODE_FULLSCREEN NS_LITERAL_STRING("fullscreen")
@@ -1795,16 +1796,86 @@ nsresult nsXULWindow::ContentShellRemove
     if (!curItem || SameCOMIdentity(curItem, aContentShell)) {
       mTargetableShells.RemoveObjectAt(i);
     }
   }
   
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsXULWindow::GetPrimaryContentSize(int32_t* aWidth,
+                                   int32_t* aHeight)
+{
+  if (mPrimaryTabParent) {
+    return GetPrimaryTabParentSize(aWidth, aHeight);
+  } else if (mPrimaryContentShell) {
+    return GetPrimaryContentShellSize(aWidth, aHeight);
+  }
+  return NS_ERROR_UNEXPECTED;
+}
+
+NS_IMETHODIMP
+nsXULWindow::GetPrimaryTabParentSize(int32_t* aWidth,
+                                     int32_t* aHeight)
+{
+  TabParent* tabParent = TabParent::GetFrom(mPrimaryTabParent);
+  Element* element = tabParent->GetOwnerElement();
+  NS_ENSURE_STATE(element);
+
+  *aWidth = element->ClientWidth();
+  *aHeight = element->ClientHeight();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULWindow::GetPrimaryContentShellSize(int32_t* aWidth,
+                                        int32_t* aHeight)
+{
+  NS_ENSURE_STATE(mPrimaryContentShell);
+
+  nsCOMPtr<nsIBaseWindow> shellWindow(do_QueryInterface(mPrimaryContentShell));
+  NS_ENSURE_STATE(shellWindow);
+
+  int32_t cox, coy;
+  double shellScale = 1.0;
+  shellWindow->GetSize(&cox, &coy);
+  shellWindow->GetUnscaledDevicePixelsPerCSSPixel(&shellScale);
+  *aWidth = NSToIntRound(cox / shellScale);
+  *aHeight = NSToIntRound(coy / shellScale);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULWindow::SetPrimaryContentSize(int32_t aWidth,
+                                   int32_t aHeight)
+{
+  if (mPrimaryTabParent) {
+    return SetPrimaryTabParentSize(aWidth, aHeight);
+  } else if (mPrimaryContentShell) {
+    return SizeShellTo(mPrimaryContentShell, aWidth, aHeight);
+  }
+  return NS_ERROR_UNEXPECTED;
+}
+
+NS_IMETHODIMP
+nsXULWindow::SetPrimaryTabParentSize(int32_t aWidth,
+                                     int32_t aHeight)
+{
+  int32_t shellWidth, shellHeight;
+  GetPrimaryTabParentSize(&shellWidth, &shellHeight);
+
+  double scale = 1.0;
+  GetUnscaledDevicePixelsPerCSSPixel(&scale);
+
+  SizeShellToWithLimit(aWidth, aHeight,
+                       shellWidth * scale, shellHeight * scale);
+  return NS_OK;
+}
+
 NS_IMETHODIMP nsXULWindow::SizeShellTo(nsIDocShellTreeItem* aShellItem,
    int32_t aCX, int32_t aCY)
 {
   // XXXTAB This is wrong, we should actually reflow based on the passed in
   // shell.  For now we are hacking and doing delta sizing.  This is bad
   // because it assumes all size we add will go to the shell which probably
   // won't happen.
 
--- a/xpfe/appshell/nsXULWindow.h
+++ b/xpfe/appshell/nsXULWindow.h
@@ -103,16 +103,20 @@ protected:
    NS_IMETHOD GetWindowDOMWindow(mozIDOMWindowProxy** aDOMWindow);
    mozilla::dom::Element* GetWindowDOMElement() const;
 
    // See nsIDocShellTreeOwner for docs on next two methods
    nsresult ContentShellAdded(nsIDocShellTreeItem* aContentShell,
                                           bool aPrimary, bool aTargetable,
                                           const nsAString& aID);
    nsresult ContentShellRemoved(nsIDocShellTreeItem* aContentShell);
+   NS_IMETHOD GetPrimaryContentSize(int32_t* aWidth,
+                                    int32_t* aHeight);
+   NS_IMETHOD SetPrimaryContentSize(int32_t aWidth,
+                                    int32_t aHeight);
    NS_IMETHOD SizeShellTo(nsIDocShellTreeItem* aShellItem, int32_t aCX, 
       int32_t aCY);
    NS_IMETHOD ExitModalLoop(nsresult aStatus);
    NS_IMETHOD CreateNewChromeWindow(int32_t aChromeFlags, nsITabParent* aOpeningTab, nsIXULWindow **_retval);
    NS_IMETHOD CreateNewContentWindow(int32_t aChromeFlags, nsITabParent* aOpeningTab, nsIXULWindow **_retval);
 
    void       EnableParent(bool aEnable);
    bool       ConstrainToZLevel(bool aImmediate, nsWindowZ *aPlacement,
@@ -156,16 +160,20 @@ protected:
    uint32_t                mPersistentAttributesMask;
    uint32_t                mChromeFlags;
    nsString                mTitle;
    nsIntRect               mOpenerScreenRect; // the screen rect of the opener
 
    nsCOMArray<nsIWeakReference> mTargetableShells; // targetable shells only
 
    nsCOMPtr<nsITabParent> mPrimaryTabParent;
+private:
+   NS_IMETHOD GetPrimaryTabParentSize(int32_t* aWidth, int32_t* aHeight);
+   NS_IMETHOD GetPrimaryContentShellSize(int32_t* aWidth, int32_t* aHeight);
+   NS_IMETHOD SetPrimaryTabParentSize(int32_t aWidth, int32_t aHeight);
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsXULWindow, NS_XULWINDOW_IMPL_CID)
 
 // nsContentShellInfo
 // Used to map shell IDs to nsIDocShellTreeItems.
 
 class nsContentShellInfo