Bug 827976: Part 1 - Create hidden windows lazily on non-Mac platforms. r=bzbarsky
authorVladan Djeric <vdjeric@mozilla.com>
Wed, 20 Feb 2013 00:11:54 -0500
changeset 132890 9bee7d808f97a08de30044dee9d4abbf0dab6a1a
parent 132889 e27e1c6fe079dfcb92e2011f6c10ce2933842281
child 132891 bb4938013af5d92e1f4229b3b91937a6fef76d0c
push id2452
push userlsblakk@mozilla.com
push dateMon, 13 May 2013 16:59:38 +0000
treeherdermozilla-beta@d4b152d29d8d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbzbarsky
bugs827976
milestone22.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 827976: Part 1 - Create hidden windows lazily on non-Mac platforms. r=bzbarsky
content/base/src/nsCCUncollectableMarker.cpp
toolkit/xre/nsAppRunner.cpp
xpfe/appshell/public/nsIAppShellService.idl
xpfe/appshell/src/nsAppShellService.cpp
xpfe/appshell/src/nsAppShellService.h
--- a/content/base/src/nsCCUncollectableMarker.cpp
+++ b/content/base/src/nsCCUncollectableMarker.cpp
@@ -354,22 +354,26 @@ nsCCUncollectableMarker::Observe(nsISupp
 
     MarkWindowList(windowList, cleanupJS, prepareForCC);
   }
 
   nsCOMPtr<nsIAppShellService> appShell = 
     do_GetService(NS_APPSHELLSERVICE_CONTRACTID);
   if (appShell) {
     nsCOMPtr<nsIXULWindow> hw;
-    appShell->GetHiddenWindow(getter_AddRefs(hw));
-    if (hw) {
-      nsCOMPtr<nsIDocShell> shell;
-      hw->GetDocShell(getter_AddRefs(shell));
-      nsCOMPtr<nsIDocShellTreeNode> shellTreeNode = do_QueryInterface(shell);
-      MarkDocShell(shellTreeNode, cleanupJS, prepareForCC);
+    bool hasHiddenWindow = false;
+    appShell->GetHasHiddenWindow(&hasHiddenWindow);
+    if (hasHiddenWindow) {
+      appShell->GetHiddenWindow(getter_AddRefs(hw));
+      if (hw) {
+        nsCOMPtr<nsIDocShell> shell;
+        hw->GetDocShell(getter_AddRefs(shell));
+        nsCOMPtr<nsIDocShellTreeNode> shellTreeNode = do_QueryInterface(shell);
+        MarkDocShell(shellTreeNode, cleanupJS, prepareForCC);
+      }
     }
     bool hasHiddenPrivateWindow = false;
     appShell->GetHasHiddenPrivateWindow(&hasHiddenPrivateWindow);
     if (hasHiddenPrivateWindow) {
       appShell->GetHiddenPrivateWindow(getter_AddRefs(hw));
       if (hw) {
         nsCOMPtr<nsIDocShell> shell;
         hw->GetDocShell(getter_AddRefs(shell));
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -3798,18 +3798,22 @@ XREMain::XRE_mainRun()
   SaveToEnv("XRE_PROFILE_LOCAL_PATH=");
   SaveToEnv("XRE_PROFILE_NAME=");
   SaveToEnv("XRE_START_OFFLINE=");
   SaveToEnv("NO_EM_RESTART=");
   SaveToEnv("XUL_APP_FILE=");
   SaveToEnv("XRE_BINARY_PATH=");
 
   if (!mShuttingDown) {
+#ifdef XP_MACOSX
+    // The hidden window is always needed on Mac to provide the menu bar
+    // when no other windows are open.
     rv = appStartup->CreateHiddenWindow();
     NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
+#endif
 
 #if defined(HAVE_DESKTOP_STARTUP_ID) && defined(MOZ_WIDGET_GTK)
     nsGTKToolkit* toolkit = nsGTKToolkit::GetToolkit();
     if (toolkit && !mDesktopStartupID.IsEmpty()) {
       toolkit->SetDesktopStartupID(mDesktopStartupID);
     }
     // Clear the environment variable so it won't be inherited by
     // child processes and confuse things.
--- a/xpfe/appshell/public/nsIAppShellService.idl
+++ b/xpfe/appshell/public/nsIAppShellService.idl
@@ -11,17 +11,17 @@ interface nsIDOMWindow;
 interface nsIAppShell;
 
 [ptr] native JSContext(JSContext);
 
 %{C++
 struct JSContext;
 %}
 
-[scriptable, uuid(5c19ab54-67bf-46d0-ac5b-21abd9050c3b)]
+[scriptable, uuid(1ae1e51a-cd69-4c18-805e-ad09b39b1f4c)]
 interface nsIAppShellService : nsISupports
 {
   /**
    * Create a window, which will be initially invisible.
    * @param aParent the parent window.  Can be null.
    * @param aUrl the contents of the new window.
    * @param aChromeMask chrome flags affecting the kind of OS border
    *                    given to the window. see nsIBrowserWindow for
@@ -114,13 +114,19 @@ interface nsIAppShellService : nsISuppor
    * Remove a window from the application's window registry. Note that
    * this method won't automatically attempt to quit the app when
    * the last window is unregistered. For that, see Quit().
    * @param aWindow you see the pattern
    */
   void unregisterTopLevelWindow(in nsIXULWindow aWindow);
 
   /**
+   * Whether the hidden non-private window has been lazily created.
+   */
+  [noscript]
+  readonly attribute boolean hasHiddenWindow;
+
+  /**
    * Whether the hidden private window has been lazily created.
    */
   [noscript]
   readonly attribute boolean hasHiddenPrivateWindow;
 };
--- a/xpfe/appshell/src/nsAppShellService.cpp
+++ b/xpfe/appshell/src/nsAppShellService.cpp
@@ -82,16 +82,22 @@ NS_IMPL_ISUPPORTS2(nsAppShellService,
 
 NS_IMETHODIMP
 nsAppShellService::CreateHiddenWindow()
 {
   return CreateHiddenWindowHelper(false);
 }
 
 void
+nsAppShellService::EnsureHiddenWindow()
+{
+  CreateHiddenWindow();
+}
+
+void
 nsAppShellService::EnsurePrivateHiddenWindow()
 {
   if (!mHiddenPrivateWindow) {
     CreateHiddenWindowHelper(true);
   }
 }
 
 nsresult
@@ -432,24 +438,28 @@ nsAppShellService::JustCreateTopWindow(n
   return rv;
 }
 
 NS_IMETHODIMP
 nsAppShellService::GetHiddenWindow(nsIXULWindow **aWindow)
 {
   NS_ENSURE_ARG_POINTER(aWindow);
 
+  EnsureHiddenWindow();
+
   *aWindow = mHiddenWindow;
   NS_IF_ADDREF(*aWindow);
   return *aWindow ? NS_OK : NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
 nsAppShellService::GetHiddenDOMWindow(nsIDOMWindow **aWindow)
 {
+  EnsureHiddenWindow();
+
   nsresult rv;
   nsCOMPtr<nsIDocShell> docShell;
   NS_ENSURE_TRUE(mHiddenWindow, NS_ERROR_FAILURE);
 
   rv = mHiddenWindow->GetDocShell(getter_AddRefs(docShell));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIDOMWindow> hiddenDOMWindow(do_GetInterface(docShell, &rv));
@@ -468,16 +478,25 @@ nsAppShellService::GetHiddenPrivateWindo
   EnsurePrivateHiddenWindow();
 
   *aWindow = mHiddenPrivateWindow;
   NS_IF_ADDREF(*aWindow);
   return *aWindow ? NS_OK : NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
+nsAppShellService::GetHasHiddenWindow(bool* aHasHiddenWindow)
+{
+  NS_ENSURE_ARG_POINTER(aHasHiddenWindow);
+
+  *aHasHiddenWindow = !!mHiddenWindow;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsAppShellService::GetHiddenPrivateDOMWindow(nsIDOMWindow **aWindow)
 {
   EnsurePrivateHiddenWindow();
 
   nsresult rv;
   nsCOMPtr<nsIDocShell> docShell;
   NS_ENSURE_TRUE(mHiddenPrivateWindow, NS_ERROR_FAILURE);
 
--- a/xpfe/appshell/src/nsAppShellService.h
+++ b/xpfe/appshell/src/nsAppShellService.h
@@ -28,16 +28,17 @@ public:
   NS_DECL_NSIOBSERVER
 
   nsAppShellService();
 
 protected:
   ~nsAppShellService();
 
   nsresult CreateHiddenWindowHelper(bool aIsPrivate);
+  void EnsureHiddenWindow();
   void EnsurePrivateHiddenWindow();
 
   nsresult JustCreateTopWindow(nsIXULWindow *aParent,
                                nsIURI *aUrl, 
                                uint32_t aChromeMask,
                                int32_t aInitialWidth, int32_t aInitialHeight,
                                bool aIsHiddenWindow,
                                nsWebShellWindow **aResult);