xpfe/appshell/src/nsAppShellService.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #include "nsIAppShellService.h"
     8 #include "nsIComponentManager.h"
     9 #include "nsIURL.h"
    10 #include "nsNetUtil.h"
    11 #include "nsIServiceManager.h"
    12 #include "nsIObserverService.h"
    13 #include "nsIObserver.h"
    14 #include "nsIXPConnect.h"
    16 #include "nsIWindowMediator.h"
    17 #include "nsIWindowWatcher.h"
    18 #include "nsPIWindowWatcher.h"
    19 #include "nsIDOMWindow.h"
    20 #include "nsPIDOMWindow.h"
    21 #include "nsWebShellWindow.h"
    23 #include "nsCRT.h"
    24 #include "prprf.h"
    26 #include "nsWidgetInitData.h"
    27 #include "nsWidgetsCID.h"
    28 #include "nsIWidget.h"
    29 #include "nsIRequestObserver.h"
    31 /* For implementing GetHiddenWindowAndJSContext */
    32 #include "nsIScriptGlobalObject.h"
    33 #include "nsIScriptContext.h"
    35 #include "nsAppShellService.h"
    36 #include "nsISupportsPrimitives.h"
    37 #include "nsIChromeRegistry.h"
    38 #include "nsILoadContext.h"
    39 #include "nsIWebNavigation.h"
    41 #include "mozilla/Attributes.h"
    42 #include "mozilla/Preferences.h"
    43 #include "mozilla/StartupTimeline.h"
    45 #include "nsEmbedCID.h"
    46 #include "nsIWebBrowser.h"
    47 #include "nsIDocShell.h"
    49 #ifdef MOZ_INSTRUMENT_EVENT_LOOP
    50 #include "EventTracer.h"
    51 #endif
    53 using namespace mozilla;
    55 // Default URL for the hidden window, can be overridden by a pref on Mac
    56 #define DEFAULT_HIDDENWINDOW_URL "resource://gre-resources/hiddenWindow.html"
    58 class nsIAppShell;
    60 nsAppShellService::nsAppShellService() : 
    61   mXPCOMWillShutDown(false),
    62   mXPCOMShuttingDown(false),
    63   mModalWindowCount(0),
    64   mApplicationProvidedHiddenWindow(false)
    65 {
    66   nsCOMPtr<nsIObserverService> obs
    67     (do_GetService("@mozilla.org/observer-service;1"));
    69   if (obs) {
    70     obs->AddObserver(this, "xpcom-will-shutdown", false);
    71     obs->AddObserver(this, "xpcom-shutdown", false);
    72   }
    73 }
    75 nsAppShellService::~nsAppShellService()
    76 {
    77 }
    80 /*
    81  * Implement the nsISupports methods...
    82  */
    83 NS_IMPL_ISUPPORTS(nsAppShellService,
    84                   nsIAppShellService,
    85                   nsIObserver)
    87 NS_IMETHODIMP
    88 nsAppShellService::CreateHiddenWindow()
    89 {
    90   return CreateHiddenWindowHelper(false);
    91 }
    93 void
    94 nsAppShellService::EnsurePrivateHiddenWindow()
    95 {
    96   if (!mHiddenPrivateWindow) {
    97     CreateHiddenWindowHelper(true);
    98   }
    99 }
   101 nsresult
   102 nsAppShellService::CreateHiddenWindowHelper(bool aIsPrivate)
   103 {
   104   nsresult rv;
   105   int32_t initialHeight = 100, initialWidth = 100;
   107 #ifdef XP_MACOSX
   108   uint32_t    chromeMask = 0;
   109   nsAdoptingCString prefVal =
   110       Preferences::GetCString("browser.hiddenWindowChromeURL");
   111   const char* hiddenWindowURL = prefVal.get() ? prefVal.get() : DEFAULT_HIDDENWINDOW_URL;
   112   if (aIsPrivate) {
   113     hiddenWindowURL = DEFAULT_HIDDENWINDOW_URL;
   114   } else {
   115     mApplicationProvidedHiddenWindow = prefVal.get() ? true : false;
   116   }
   117 #else
   118   static const char hiddenWindowURL[] = DEFAULT_HIDDENWINDOW_URL;
   119   uint32_t    chromeMask =  nsIWebBrowserChrome::CHROME_ALL;
   120 #endif
   122   nsCOMPtr<nsIURI> url;
   123   rv = NS_NewURI(getter_AddRefs(url), hiddenWindowURL);
   124   NS_ENSURE_SUCCESS(rv, rv);
   126   nsRefPtr<nsWebShellWindow> newWindow;
   127   if (!aIsPrivate) {
   128     rv = JustCreateTopWindow(nullptr, url,
   129                              chromeMask, initialWidth, initialHeight,
   130                              true, getter_AddRefs(newWindow));
   131     NS_ENSURE_SUCCESS(rv, rv);
   133     mHiddenWindow.swap(newWindow);
   134   } else {
   135     // Create the hidden private window
   136     chromeMask |= nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW;
   138     rv = JustCreateTopWindow(nullptr, url,
   139                              chromeMask, initialWidth, initialHeight,
   140                              true, getter_AddRefs(newWindow));
   141     NS_ENSURE_SUCCESS(rv, rv);
   143     nsCOMPtr<nsIDocShell> docShell;
   144     newWindow->GetDocShell(getter_AddRefs(docShell));
   145     if (docShell) {
   146       docShell->SetAffectPrivateSessionLifetime(false);
   147     }
   149     mHiddenPrivateWindow.swap(newWindow);
   150   }
   152   // RegisterTopLevelWindow(newWindow); -- Mac only
   154   return NS_OK;
   155 }
   157 NS_IMETHODIMP
   158 nsAppShellService::DestroyHiddenWindow()
   159 {
   160   if (mHiddenWindow) {
   161     mHiddenWindow->Destroy();
   163     mHiddenWindow = nullptr;
   164   }
   166   if (mHiddenPrivateWindow) {
   167     mHiddenPrivateWindow->Destroy();
   169     mHiddenPrivateWindow = nullptr;
   170   }
   172   return NS_OK;
   173 }
   175 /*
   176  * Create a new top level window and display the given URL within it...
   177  */
   178 NS_IMETHODIMP
   179 nsAppShellService::CreateTopLevelWindow(nsIXULWindow *aParent,
   180                                         nsIURI *aUrl, 
   181                                         uint32_t aChromeMask,
   182                                         int32_t aInitialWidth,
   183                                         int32_t aInitialHeight,
   184                                         nsIXULWindow **aResult)
   186 {
   187   nsresult rv;
   189   StartupTimeline::RecordOnce(StartupTimeline::CREATE_TOP_LEVEL_WINDOW);
   191   nsWebShellWindow *newWindow = nullptr;
   192   rv = JustCreateTopWindow(aParent, aUrl,
   193                            aChromeMask, aInitialWidth, aInitialHeight,
   194                            false, &newWindow);  // addrefs
   196   *aResult = newWindow; // transfer ref
   198   if (NS_SUCCEEDED(rv)) {
   199     // the addref resulting from this is the owning addref for this window
   200     RegisterTopLevelWindow(*aResult);
   201     nsCOMPtr<nsIXULWindow> parent;
   202     if (aChromeMask & nsIWebBrowserChrome::CHROME_DEPENDENT)
   203       parent = aParent;
   204     (*aResult)->SetZLevel(CalculateWindowZLevel(parent, aChromeMask));
   205   }
   207   return rv;
   208 }
   210 /*
   211  * This class provides a stub implementation of nsIWebBrowserChrome2, as needed
   212  * by nsAppShellService::CreateWindowlessBrowser
   213  */
   214 class WebBrowserChrome2Stub : public nsIWebBrowserChrome2,
   215                               public nsIInterfaceRequestor,
   216                               public nsSupportsWeakReference {
   217 public:
   218     virtual ~WebBrowserChrome2Stub() {}
   219     NS_DECL_ISUPPORTS
   220     NS_DECL_NSIWEBBROWSERCHROME
   221     NS_DECL_NSIWEBBROWSERCHROME2
   222     NS_DECL_NSIINTERFACEREQUESTOR
   223 };
   225 NS_INTERFACE_MAP_BEGIN(WebBrowserChrome2Stub)
   226   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebBrowserChrome)
   227   NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome)
   228   NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome2)
   229   NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
   230   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
   231 NS_INTERFACE_MAP_END
   233 NS_IMPL_ADDREF(WebBrowserChrome2Stub)
   234 NS_IMPL_RELEASE(WebBrowserChrome2Stub)
   236 NS_IMETHODIMP
   237 WebBrowserChrome2Stub::SetStatus(uint32_t aStatusType, const char16_t* aStatus)
   238 {
   239   return NS_OK;
   240 }
   242 NS_IMETHODIMP
   243 WebBrowserChrome2Stub::GetWebBrowser(nsIWebBrowser** aWebBrowser)
   244 {
   245   NS_NOTREACHED("WebBrowserChrome2Stub::GetWebBrowser is not supported");
   246   return NS_ERROR_NOT_IMPLEMENTED;
   247 }
   249 NS_IMETHODIMP
   250 WebBrowserChrome2Stub::SetWebBrowser(nsIWebBrowser* aWebBrowser)
   251 {
   252   NS_NOTREACHED("WebBrowserChrome2Stub::SetWebBrowser is not supported");
   253   return NS_ERROR_NOT_IMPLEMENTED;
   254 }
   256 NS_IMETHODIMP
   257 WebBrowserChrome2Stub::GetChromeFlags(uint32_t* aChromeFlags)
   258 {
   259   *aChromeFlags = 0;
   260   return NS_OK;
   261 }
   263 NS_IMETHODIMP
   264 WebBrowserChrome2Stub::SetChromeFlags(uint32_t aChromeFlags)
   265 {
   266   NS_NOTREACHED("WebBrowserChrome2Stub::SetChromeFlags is not supported");
   267   return NS_ERROR_NOT_IMPLEMENTED;
   268 }
   270 NS_IMETHODIMP
   271 WebBrowserChrome2Stub::DestroyBrowserWindow()
   272 {
   273   NS_NOTREACHED("WebBrowserChrome2Stub::DestroyBrowserWindow is not supported");
   274   return NS_ERROR_NOT_IMPLEMENTED;
   275 }
   277 NS_IMETHODIMP
   278 WebBrowserChrome2Stub::SizeBrowserTo(int32_t aCX, int32_t aCY)
   279 {
   280   NS_NOTREACHED("WebBrowserChrome2Stub::SizeBrowserTo is not supported");
   281   return NS_ERROR_NOT_IMPLEMENTED;
   282 }
   284 NS_IMETHODIMP
   285 WebBrowserChrome2Stub::ShowAsModal()
   286 {
   287   NS_NOTREACHED("WebBrowserChrome2Stub::ShowAsModal is not supported");
   288   return NS_ERROR_NOT_IMPLEMENTED;
   289 }
   291 NS_IMETHODIMP
   292 WebBrowserChrome2Stub::IsWindowModal(bool* aResult)
   293 {
   294   *aResult = false;
   295   return NS_OK;
   296 }
   298 NS_IMETHODIMP
   299 WebBrowserChrome2Stub::ExitModalEventLoop(nsresult aStatus)
   300 {
   301   NS_NOTREACHED("WebBrowserChrome2Stub::ExitModalEventLoop is not supported");
   302   return NS_ERROR_NOT_IMPLEMENTED;
   303 }
   305 NS_IMETHODIMP
   306 WebBrowserChrome2Stub::SetStatusWithContext(uint32_t aStatusType,
   307                                             const nsAString& aStatusText,
   308                                             nsISupports* aStatusContext)
   309 {
   310   return NS_OK;
   311 }
   313 NS_IMETHODIMP
   314 WebBrowserChrome2Stub::GetInterface(const nsIID & aIID, void **aSink)
   315 {
   316     return QueryInterface(aIID, aSink);
   317 }
   319 // This is the "stub" we return from CreateWindowlessBrowser - it exists
   320 // purely to keep a strong reference to the browser and the container to
   321 // prevent the container being collected while the stub remains alive.
   322 class WindowlessBrowserStub MOZ_FINAL : public nsIWebNavigation,
   323                                         public nsIInterfaceRequestor {
   324 public:
   325   WindowlessBrowserStub(nsIWebBrowser *aBrowser, nsISupports *aContainer) {
   326     mBrowser = aBrowser;
   327     mWebNavigation = do_QueryInterface(aBrowser);
   328     mInterfaceRequestor = do_QueryInterface(aBrowser);
   329     mContainer = aContainer;
   330   }
   331   NS_DECL_ISUPPORTS
   332   NS_FORWARD_NSIWEBNAVIGATION(mWebNavigation->)
   333   NS_FORWARD_NSIINTERFACEREQUESTOR(mInterfaceRequestor->)
   334 private:
   335   nsCOMPtr<nsIWebBrowser> mBrowser;
   336   nsCOMPtr<nsIWebNavigation> mWebNavigation;
   337   nsCOMPtr<nsIInterfaceRequestor> mInterfaceRequestor;
   338   // we don't use the container but just hold a reference to it.
   339   nsCOMPtr<nsISupports> mContainer;
   340 };
   342 NS_INTERFACE_MAP_BEGIN(WindowlessBrowserStub)
   343   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebNavigation)
   344   NS_INTERFACE_MAP_ENTRY(nsIWebNavigation)
   345   NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
   346 NS_INTERFACE_MAP_END
   348 NS_IMPL_ADDREF(WindowlessBrowserStub)
   349 NS_IMPL_RELEASE(WindowlessBrowserStub)
   352 NS_IMETHODIMP
   353 nsAppShellService::CreateWindowlessBrowser(bool aIsChrome, nsIWebNavigation **aResult)
   354 {
   355   /* First, we create an instance of nsWebBrowser. Instances of this class have
   356    * an associated doc shell, which is what we're interested in.
   357    */
   358   nsCOMPtr<nsIWebBrowser> browser = do_CreateInstance(NS_WEBBROWSER_CONTRACTID);
   359   if (!browser) {
   360     NS_ERROR("Couldn't create instance of nsWebBrowser!");
   361     return NS_ERROR_FAILURE;
   362   }
   364   /* Next, we set the container window for our instance of nsWebBrowser. Since
   365    * we don't actually have a window, we instead set the container window to be
   366    * an instance of WebBrowserChrome2Stub, which provides a stub implementation
   367    * of nsIWebBrowserChrome2.
   368    */
   369   nsRefPtr<WebBrowserChrome2Stub> stub = new WebBrowserChrome2Stub();
   370   if (!stub) {
   371     NS_ERROR("Couldn't create instance of WebBrowserChrome2Stub!");
   372     return NS_ERROR_FAILURE;
   373   }
   374   browser->SetContainerWindow(stub);
   376   nsCOMPtr<nsIWebNavigation> navigation = do_QueryInterface(browser);
   378   nsCOMPtr<nsIDocShellTreeItem> item = do_QueryInterface(navigation);
   379   item->SetItemType(aIsChrome ? nsIDocShellTreeItem::typeChromeWrapper
   380                               : nsIDocShellTreeItem::typeContentWrapper);
   382   /* A windowless web browser doesn't have an associated OS level window. To
   383    * accomplish this, we initialize the window associated with our instance of
   384    * nsWebBrowser with an instance of PuppetWidget, which provides a stub
   385    * implementation of nsIWidget.
   386    */
   387   nsCOMPtr<nsIWidget> widget = nsIWidget::CreatePuppetWidget(nullptr);
   388   if (!widget) {
   389     NS_ERROR("Couldn't create instance of PuppetWidget");
   390     return NS_ERROR_FAILURE;
   391   }
   392   widget->Create(nullptr, 0, nsIntRect(nsIntPoint(0, 0), nsIntSize(0, 0)),
   393                  nullptr, nullptr);
   394   nsCOMPtr<nsIBaseWindow> window = do_QueryInterface(navigation);
   395   window->InitWindow(0, widget, 0, 0, 0, 0);
   396   window->Create();
   398   nsISupports *isstub = NS_ISUPPORTS_CAST(nsIWebBrowserChrome2*, stub);
   399   nsRefPtr<nsIWebNavigation> result = new WindowlessBrowserStub(browser, isstub);
   400   nsCOMPtr<nsIDocShell> docshell = do_GetInterface(result);
   401   docshell->SetInvisible(true);
   403   result.forget(aResult);
   404   return NS_OK;
   405 }
   407 uint32_t
   408 nsAppShellService::CalculateWindowZLevel(nsIXULWindow *aParent,
   409                                          uint32_t      aChromeMask)
   410 {
   411   uint32_t zLevel;
   413   zLevel = nsIXULWindow::normalZ;
   414   if (aChromeMask & nsIWebBrowserChrome::CHROME_WINDOW_RAISED)
   415     zLevel = nsIXULWindow::raisedZ;
   416   else if (aChromeMask & nsIWebBrowserChrome::CHROME_WINDOW_LOWERED)
   417     zLevel = nsIXULWindow::loweredZ;
   419 #ifdef XP_MACOSX
   420   /* Platforms on which modal windows are always application-modal, not
   421      window-modal (that's just the Mac, right?) want modal windows to
   422      be stacked on top of everyone else.
   424      On Mac OS X, bind modality to parent window instead of app (ala Mac OS 9)
   425   */
   426   uint32_t modalDepMask = nsIWebBrowserChrome::CHROME_MODAL |
   427                           nsIWebBrowserChrome::CHROME_DEPENDENT;
   428   if (aParent && (aChromeMask & modalDepMask)) {
   429     aParent->GetZLevel(&zLevel);
   430   }
   431 #else
   432   /* Platforms with native support for dependent windows (that's everyone
   433       but pre-Mac OS X, right?) know how to stack dependent windows. On these
   434       platforms, give the dependent window the same level as its parent,
   435       so we won't try to override the normal platform behaviour. */
   436   if ((aChromeMask & nsIWebBrowserChrome::CHROME_DEPENDENT) && aParent)
   437     aParent->GetZLevel(&zLevel);
   438 #endif
   440   return zLevel;
   441 }
   443 #ifdef XP_WIN
   444 /*
   445  * Checks to see if any existing window is currently in fullscreen mode.
   446  */
   447 static bool
   448 CheckForFullscreenWindow()
   449 {
   450   nsCOMPtr<nsIWindowMediator> wm(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
   451   if (!wm)
   452     return false;
   454   nsCOMPtr<nsISimpleEnumerator> windowList;
   455   wm->GetXULWindowEnumerator(nullptr, getter_AddRefs(windowList));
   456   if (!windowList)
   457     return false;
   459   for (;;) {
   460     bool more = false;
   461     windowList->HasMoreElements(&more);
   462     if (!more)
   463       return false;
   465     nsCOMPtr<nsISupports> supportsWindow;
   466     windowList->GetNext(getter_AddRefs(supportsWindow));
   467     nsCOMPtr<nsIBaseWindow> baseWin(do_QueryInterface(supportsWindow));
   468     if (baseWin) {
   469       nsCOMPtr<nsIWidget> widget;
   470       baseWin->GetMainWidget(getter_AddRefs(widget));
   471       if (widget && widget->SizeMode() == nsSizeMode_Fullscreen) {
   472         return true;
   473       }
   474     }
   475   }
   476   return false;
   477 }
   478 #endif
   480 /*
   481  * Just do the window-making part of CreateTopLevelWindow
   482  */
   483 nsresult
   484 nsAppShellService::JustCreateTopWindow(nsIXULWindow *aParent,
   485                                        nsIURI *aUrl, 
   486                                        uint32_t aChromeMask,
   487                                        int32_t aInitialWidth,
   488                                        int32_t aInitialHeight,
   489                                        bool aIsHiddenWindow,
   490                                        nsWebShellWindow **aResult)
   491 {
   492   *aResult = nullptr;
   493   NS_ENSURE_STATE(!mXPCOMWillShutDown);
   495   nsCOMPtr<nsIXULWindow> parent;
   496   if (aChromeMask & nsIWebBrowserChrome::CHROME_DEPENDENT)
   497     parent = aParent;
   499   nsRefPtr<nsWebShellWindow> window = new nsWebShellWindow(aChromeMask);
   500   NS_ENSURE_TRUE(window, NS_ERROR_OUT_OF_MEMORY);
   502 #ifdef XP_WIN
   503   // If the parent is currently fullscreen, tell the child to ignore persisted
   504   // full screen states. This way new browser windows open on top of fullscreen
   505   // windows normally.
   506   if (window && CheckForFullscreenWindow())
   507     window->IgnoreXULSizeMode(true);
   508 #endif
   510   nsWidgetInitData widgetInitData;
   512   if (aIsHiddenWindow)
   513     widgetInitData.mWindowType = eWindowType_invisible;
   514   else
   515     widgetInitData.mWindowType = aChromeMask & nsIWebBrowserChrome::CHROME_OPENAS_DIALOG ?
   516       eWindowType_dialog : eWindowType_toplevel;
   518   if (aChromeMask & nsIWebBrowserChrome::CHROME_WINDOW_POPUP)
   519     widgetInitData.mWindowType = eWindowType_popup;
   521   if (aChromeMask & nsIWebBrowserChrome::CHROME_MAC_SUPPRESS_ANIMATION)
   522     widgetInitData.mIsAnimationSuppressed = true;
   524   if (aChromeMask & nsIWebBrowserChrome::CHROME_REMOTE_WINDOW)
   525     widgetInitData.mRequireOffMainThreadCompositing = true;
   527 #ifdef XP_MACOSX
   528   // Mac OS X sheet support
   529   // Adding CHROME_OPENAS_CHROME to sheetMask makes modal windows opened from
   530   // nsGlobalWindow::ShowModalDialog() be dialogs (not sheets), while modal
   531   // windows opened from nsPromptService::DoDialog() still are sheets.  This
   532   // fixes bmo bug 395465 (see nsCocoaWindow::StandardCreate() and
   533   // nsCocoaWindow::SetModal()).
   534   uint32_t sheetMask = nsIWebBrowserChrome::CHROME_OPENAS_DIALOG |
   535                        nsIWebBrowserChrome::CHROME_MODAL |
   536                        nsIWebBrowserChrome::CHROME_OPENAS_CHROME;
   537   if (parent &&
   538       (parent != mHiddenWindow && parent != mHiddenPrivateWindow) &&
   539       ((aChromeMask & sheetMask) == sheetMask)) {
   540     widgetInitData.mWindowType = eWindowType_sheet;
   541   }
   542 #endif
   544 #if defined(XP_WIN)
   545   if (widgetInitData.mWindowType == eWindowType_toplevel ||
   546       widgetInitData.mWindowType == eWindowType_dialog)
   547     widgetInitData.clipChildren = true;
   548 #endif
   550   // note default chrome overrides other OS chrome settings, but
   551   // not internal chrome
   552   if (aChromeMask & nsIWebBrowserChrome::CHROME_DEFAULT)
   553     widgetInitData.mBorderStyle = eBorderStyle_default;
   554   else if ((aChromeMask & nsIWebBrowserChrome::CHROME_ALL) == nsIWebBrowserChrome::CHROME_ALL)
   555     widgetInitData.mBorderStyle = eBorderStyle_all;
   556   else {
   557     widgetInitData.mBorderStyle = eBorderStyle_none; // assumes none == 0x00
   558     if (aChromeMask & nsIWebBrowserChrome::CHROME_WINDOW_BORDERS)
   559       widgetInitData.mBorderStyle = static_cast<enum nsBorderStyle>(widgetInitData.mBorderStyle | eBorderStyle_border);
   560     if (aChromeMask & nsIWebBrowserChrome::CHROME_TITLEBAR)
   561       widgetInitData.mBorderStyle = static_cast<enum nsBorderStyle>(widgetInitData.mBorderStyle | eBorderStyle_title);
   562     if (aChromeMask & nsIWebBrowserChrome::CHROME_WINDOW_CLOSE)
   563       widgetInitData.mBorderStyle = static_cast<enum nsBorderStyle>(widgetInitData.mBorderStyle | eBorderStyle_close);
   564     if (aChromeMask & nsIWebBrowserChrome::CHROME_WINDOW_RESIZE) {
   565       widgetInitData.mBorderStyle = static_cast<enum nsBorderStyle>(widgetInitData.mBorderStyle | eBorderStyle_resizeh);
   566       // only resizable windows get the maximize button (but not dialogs)
   567       if (!(aChromeMask & nsIWebBrowserChrome::CHROME_OPENAS_DIALOG))
   568         widgetInitData.mBorderStyle = static_cast<enum nsBorderStyle>(widgetInitData.mBorderStyle | eBorderStyle_maximize);
   569     }
   570     // all windows (except dialogs) get minimize buttons and the system menu
   571     if (!(aChromeMask & nsIWebBrowserChrome::CHROME_OPENAS_DIALOG))
   572       widgetInitData.mBorderStyle = static_cast<enum nsBorderStyle>(widgetInitData.mBorderStyle | eBorderStyle_minimize | eBorderStyle_menu);
   573     // but anyone can explicitly ask for a minimize button
   574     if (aChromeMask & nsIWebBrowserChrome::CHROME_WINDOW_MIN) {
   575       widgetInitData.mBorderStyle = static_cast<enum nsBorderStyle>(widgetInitData.mBorderStyle | eBorderStyle_minimize);
   576     }  
   577   }
   579   if (aInitialWidth == nsIAppShellService::SIZE_TO_CONTENT ||
   580       aInitialHeight == nsIAppShellService::SIZE_TO_CONTENT) {
   581     aInitialWidth = 1;
   582     aInitialHeight = 1;
   583     window->SetIntrinsicallySized(true);
   584   }
   586   bool center = aChromeMask & nsIWebBrowserChrome::CHROME_CENTER_SCREEN;
   588   nsCOMPtr<nsIXULChromeRegistry> reg =
   589     mozilla::services::GetXULChromeRegistryService();
   590   if (reg) {
   591     nsAutoCString package;
   592     package.AssignLiteral("global");
   593     bool isRTL = false;
   594     reg->IsLocaleRTL(package, &isRTL);
   595     widgetInitData.mRTL = isRTL;
   596   }
   598   nsresult rv = window->Initialize(parent, center ? aParent : nullptr,
   599                                    aUrl, aInitialWidth, aInitialHeight,
   600                                    aIsHiddenWindow, widgetInitData);
   602   NS_ENSURE_SUCCESS(rv, rv);
   604   // Enforce the Private Browsing autoStart pref first.
   605   bool isPrivateBrowsingWindow =
   606     Preferences::GetBool("browser.privatebrowsing.autostart");
   607   if (aChromeMask & nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW) {
   608     // Caller requested a private window
   609     isPrivateBrowsingWindow = true;
   610   }
   611   if (!isPrivateBrowsingWindow) {
   612     // Ensure that we propagate any existing private browsing status
   613     // from the parent, even if it will not actually be used
   614     // as a parent value.
   615     nsCOMPtr<nsIDOMWindow> domWin = do_GetInterface(aParent);
   616     nsCOMPtr<nsIWebNavigation> webNav = do_GetInterface(domWin);
   617     nsCOMPtr<nsILoadContext> parentContext = do_QueryInterface(webNav);
   618     if (parentContext) {
   619       isPrivateBrowsingWindow = parentContext->UsePrivateBrowsing();
   620     }
   621   }
   622   nsCOMPtr<nsIDOMWindow> newDomWin =
   623       do_GetInterface(NS_ISUPPORTS_CAST(nsIBaseWindow*, window));
   624   nsCOMPtr<nsIWebNavigation> newWebNav = do_GetInterface(newDomWin);
   625   nsCOMPtr<nsILoadContext> thisContext = do_GetInterface(newWebNav);
   626   if (thisContext) {
   627     thisContext->SetPrivateBrowsing(isPrivateBrowsingWindow);
   628   }
   630   window.swap(*aResult); // transfer reference
   631   if (parent)
   632     parent->AddChildWindow(*aResult);
   634   if (center)
   635     rv = (*aResult)->Center(parent, parent ? false : true, false);
   637   return rv;
   638 }
   640 NS_IMETHODIMP
   641 nsAppShellService::GetHiddenWindow(nsIXULWindow **aWindow)
   642 {
   643   NS_ENSURE_ARG_POINTER(aWindow);
   645   *aWindow = mHiddenWindow;
   646   NS_IF_ADDREF(*aWindow);
   647   return *aWindow ? NS_OK : NS_ERROR_FAILURE;
   648 }
   650 NS_IMETHODIMP
   651 nsAppShellService::GetHiddenDOMWindow(nsIDOMWindow **aWindow)
   652 {
   653   nsresult rv;
   654   nsCOMPtr<nsIDocShell> docShell;
   655   NS_ENSURE_TRUE(mHiddenWindow, NS_ERROR_FAILURE);
   657   rv = mHiddenWindow->GetDocShell(getter_AddRefs(docShell));
   658   NS_ENSURE_SUCCESS(rv, rv);
   660   nsCOMPtr<nsIDOMWindow> hiddenDOMWindow(do_GetInterface(docShell, &rv));
   661   NS_ENSURE_SUCCESS(rv, rv);
   663   *aWindow = hiddenDOMWindow;
   664   NS_IF_ADDREF(*aWindow);
   665   return NS_OK;
   666 }
   668 NS_IMETHODIMP
   669 nsAppShellService::GetHiddenPrivateWindow(nsIXULWindow **aWindow)
   670 {
   671   NS_ENSURE_ARG_POINTER(aWindow);
   673   EnsurePrivateHiddenWindow();
   675   *aWindow = mHiddenPrivateWindow;
   676   NS_IF_ADDREF(*aWindow);
   677   return *aWindow ? NS_OK : NS_ERROR_FAILURE;
   678 }
   680 NS_IMETHODIMP
   681 nsAppShellService::GetHiddenPrivateDOMWindow(nsIDOMWindow **aWindow)
   682 {
   683   EnsurePrivateHiddenWindow();
   685   nsresult rv;
   686   nsCOMPtr<nsIDocShell> docShell;
   687   NS_ENSURE_TRUE(mHiddenPrivateWindow, NS_ERROR_FAILURE);
   689   rv = mHiddenPrivateWindow->GetDocShell(getter_AddRefs(docShell));
   690   NS_ENSURE_SUCCESS(rv, rv);
   692   nsCOMPtr<nsIDOMWindow> hiddenPrivateDOMWindow(do_GetInterface(docShell, &rv));
   693   NS_ENSURE_SUCCESS(rv, rv);
   695   *aWindow = hiddenPrivateDOMWindow;
   696   NS_IF_ADDREF(*aWindow);
   697   return NS_OK;
   698 }
   700 NS_IMETHODIMP
   701 nsAppShellService::GetHasHiddenPrivateWindow(bool* aHasPrivateWindow)
   702 {
   703   NS_ENSURE_ARG_POINTER(aHasPrivateWindow);
   705   *aHasPrivateWindow = !!mHiddenPrivateWindow;
   706   return NS_OK;
   707 }
   709 NS_IMETHODIMP
   710 nsAppShellService::GetHiddenWindowAndJSContext(nsIDOMWindow **aWindow,
   711                                                JSContext    **aJSContext)
   712 {
   713     nsresult rv = NS_OK;
   714     if ( aWindow && aJSContext ) {
   715         *aWindow    = nullptr;
   716         *aJSContext = nullptr;
   718         if ( mHiddenWindow ) {
   719             // Convert hidden window to nsIDOMWindow and extract its JSContext.
   720             do {
   721                 // 1. Get doc for hidden window.
   722                 nsCOMPtr<nsIDocShell> docShell;
   723                 rv = mHiddenWindow->GetDocShell(getter_AddRefs(docShell));
   724                 if (NS_FAILED(rv)) break;
   726                 // 2. Convert that to an nsIDOMWindow.
   727                 nsCOMPtr<nsIDOMWindow> hiddenDOMWindow(do_GetInterface(docShell));
   728                 if(!hiddenDOMWindow) break;
   730                 // 3. Get script global object for the window.
   731                 nsCOMPtr<nsIScriptGlobalObject> sgo;
   732                 sgo = do_QueryInterface( hiddenDOMWindow );
   733                 if (!sgo) { rv = NS_ERROR_FAILURE; break; }
   735                 // 4. Get script context from that.
   736                 nsIScriptContext *scriptContext = sgo->GetContext();
   737                 if (!scriptContext) { rv = NS_ERROR_FAILURE; break; }
   739                 // 5. Get JSContext from the script context.
   740                 JSContext *jsContext = scriptContext->GetNativeContext();
   741                 if (!jsContext) { rv = NS_ERROR_FAILURE; break; }
   743                 // Now, give results to caller.
   744                 *aWindow    = hiddenDOMWindow.get();
   745                 NS_IF_ADDREF( *aWindow );
   746                 *aJSContext = jsContext;
   747             } while (0);
   748         } else {
   749             rv = NS_ERROR_FAILURE;
   750         }
   751     } else {
   752         rv = NS_ERROR_NULL_POINTER;
   753     }
   754     return rv;
   755 }
   757 NS_IMETHODIMP
   758 nsAppShellService::GetApplicationProvidedHiddenWindow(bool* aAPHW)
   759 {
   760     *aAPHW = mApplicationProvidedHiddenWindow;
   761     return NS_OK;
   762 }
   764 /*
   765  * Register a new top level window (created elsewhere)
   766  */
   767 NS_IMETHODIMP
   768 nsAppShellService::RegisterTopLevelWindow(nsIXULWindow* aWindow)
   769 {
   770   NS_ENSURE_ARG_POINTER(aWindow);
   772   nsCOMPtr<nsIDocShell> docShell;
   773   aWindow->GetDocShell(getter_AddRefs(docShell));
   774   nsCOMPtr<nsPIDOMWindow> domWindow(do_GetInterface(docShell));
   775   NS_ENSURE_TRUE(domWindow, NS_ERROR_FAILURE);
   776   domWindow->SetInitialPrincipalToSubject();
   778   // tell the window mediator about the new window
   779   nsCOMPtr<nsIWindowMediator> mediator
   780     ( do_GetService(NS_WINDOWMEDIATOR_CONTRACTID) );
   781   NS_ASSERTION(mediator, "Couldn't get window mediator.");
   783   if (mediator)
   784     mediator->RegisterWindow(aWindow);
   786   // tell the window watcher about the new window
   787   nsCOMPtr<nsPIWindowWatcher> wwatcher ( do_GetService(NS_WINDOWWATCHER_CONTRACTID) );
   788   NS_ASSERTION(wwatcher, "No windowwatcher?");
   789   if (wwatcher && domWindow) {
   790     wwatcher->AddWindow(domWindow, 0);
   791   }
   793   // an ongoing attempt to quit is stopped by a newly opened window
   794   nsCOMPtr<nsIObserverService> obssvc =
   795     do_GetService("@mozilla.org/observer-service;1");
   796   NS_ASSERTION(obssvc, "Couldn't get observer service.");
   798   if (obssvc)
   799     obssvc->NotifyObservers(aWindow, "xul-window-registered", nullptr);
   801   return NS_OK;
   802 }
   805 NS_IMETHODIMP
   806 nsAppShellService::UnregisterTopLevelWindow(nsIXULWindow* aWindow)
   807 {
   808   if (mXPCOMShuttingDown) {
   809     /* return an error code in order to:
   810        - avoid doing anything with other member variables while we are in
   811          the destructor
   812        - notify the caller not to release the AppShellService after
   813          unregistering the window
   814          (we don't want to be deleted twice consecutively to
   815          mHiddenWindow->Destroy() in our destructor)
   816     */
   817     return NS_ERROR_FAILURE;
   818   }
   820   NS_ENSURE_ARG_POINTER(aWindow);
   822   if (aWindow == mHiddenWindow) {
   823     // CreateHiddenWindow() does not register the window, so we're done.
   824     return NS_OK;
   825   }
   826   if (aWindow == mHiddenPrivateWindow) {
   827     // CreateHiddenWindow() does not register the window, so we're done.
   828     return NS_OK;
   829   }
   831   // tell the window mediator
   832   nsCOMPtr<nsIWindowMediator> mediator
   833     ( do_GetService(NS_WINDOWMEDIATOR_CONTRACTID) );
   834   NS_ASSERTION(mediator, "Couldn't get window mediator. Doing xpcom shutdown?");
   836   if (mediator)
   837     mediator->UnregisterWindow(aWindow);
   839   // tell the window watcher
   840   nsCOMPtr<nsPIWindowWatcher> wwatcher ( do_GetService(NS_WINDOWWATCHER_CONTRACTID) );
   841   NS_ASSERTION(wwatcher, "Couldn't get windowwatcher, doing xpcom shutdown?");
   842   if (wwatcher) {
   843     nsCOMPtr<nsIDocShell> docShell;
   844     aWindow->GetDocShell(getter_AddRefs(docShell));
   845     if (docShell) {
   846       nsCOMPtr<nsIDOMWindow> domWindow(do_GetInterface(docShell));
   847       if (domWindow)
   848         wwatcher->RemoveWindow(domWindow);
   849     }
   850   }
   852   return NS_OK;
   853 }
   856 NS_IMETHODIMP
   857 nsAppShellService::Observe(nsISupports* aSubject, const char *aTopic,
   858                            const char16_t *aData)
   859 {
   860   if (!strcmp(aTopic, "xpcom-will-shutdown")) {
   861     mXPCOMWillShutDown = true;
   862   } else if (!strcmp(aTopic, "xpcom-shutdown")) {
   863     mXPCOMShuttingDown = true;
   864     if (mHiddenWindow) {
   865       mHiddenWindow->Destroy();
   866     }
   867     if (mHiddenPrivateWindow) {
   868       mHiddenPrivateWindow->Destroy();
   869     }
   870   } else {
   871     NS_ERROR("Unexpected observer topic!");
   872   }
   874   return NS_OK;
   875 }
   877 NS_IMETHODIMP
   878 nsAppShellService::StartEventLoopLagTracking(bool* aResult)
   879 {
   880 #ifdef MOZ_INSTRUMENT_EVENT_LOOP
   881     *aResult = mozilla::InitEventTracing(true);
   882 #endif
   883     return NS_OK;
   884 }
   886 NS_IMETHODIMP
   887 nsAppShellService::StopEventLoopLagTracking()
   888 {
   889 #ifdef MOZ_INSTRUMENT_EVENT_LOOP
   890     mozilla::ShutdownEventTracing();
   891 #endif
   892     return NS_OK;
   893 }

mercurial