LCOV - code coverage report
Current view: top level - xpfe/appshell - nsWebShellWindow.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 146 294 49.7 %
Date: 2017-07-14 16:53:18 Functions: 19 35 54.3 %
Legend: Lines: hit not hit

          Line data    Source code
       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/. */
       5             : 
       6             : 
       7             : #include "nsWebShellWindow.h"
       8             : 
       9             : #include "nsLayoutCID.h"
      10             : #include "nsContentCID.h"
      11             : #include "nsIWeakReference.h"
      12             : #include "nsIContentViewer.h"
      13             : #include "nsIComponentManager.h"
      14             : #include "nsIServiceManager.h"
      15             : #include "nsIURL.h"
      16             : #include "nsIIOService.h"
      17             : #include "nsIURL.h"
      18             : #include "nsNetCID.h"
      19             : #include "nsIStringBundle.h"
      20             : #include "nsReadableUtils.h"
      21             : 
      22             : #include "nsContentUtils.h"
      23             : #include "nsEscape.h"
      24             : #include "nsPIDOMWindow.h"
      25             : #include "nsIWebNavigation.h"
      26             : #include "nsIWindowWatcher.h"
      27             : 
      28             : #include "nsIDOMXULElement.h"
      29             : 
      30             : #include "nsWidgetInitData.h"
      31             : #include "nsWidgetsCID.h"
      32             : #include "nsIWidget.h"
      33             : #include "nsIWidgetListener.h"
      34             : 
      35             : #include "nsIDOMCharacterData.h"
      36             : #include "nsIDOMNodeList.h"
      37             : 
      38             : #include "nsITimer.h"
      39             : #include "nsXULPopupManager.h"
      40             : 
      41             : 
      42             : #include "nsIDOMXULDocument.h"
      43             : 
      44             : #include "nsFocusManager.h"
      45             : 
      46             : #include "nsIWebProgress.h"
      47             : #include "nsIWebProgressListener.h"
      48             : 
      49             : #include "nsIDocument.h"
      50             : #include "nsIDOMDocument.h"
      51             : #include "nsIDOMNode.h"
      52             : #include "nsIDOMElement.h"
      53             : #include "nsIDocumentLoaderFactory.h"
      54             : #include "nsIObserverService.h"
      55             : 
      56             : #include "nsIScreenManager.h"
      57             : #include "nsIScreen.h"
      58             : 
      59             : #include "nsIContent.h" // for menus
      60             : #include "nsIScriptSecurityManager.h"
      61             : 
      62             : // For calculating size
      63             : #include "nsIPresShell.h"
      64             : #include "nsPresContext.h"
      65             : 
      66             : #include "nsIBaseWindow.h"
      67             : #include "nsIDocShellTreeItem.h"
      68             : 
      69             : #include "mozilla/Attributes.h"
      70             : #include "mozilla/DebugOnly.h"
      71             : #include "mozilla/MouseEvents.h"
      72             : 
      73             : #include "nsPIWindowRoot.h"
      74             : 
      75             : #include "gfxPlatform.h"
      76             : 
      77             : #ifdef XP_MACOSX
      78             : #include "nsINativeMenuService.h"
      79             : #define USE_NATIVE_MENUS
      80             : #endif
      81             : 
      82             : using namespace mozilla;
      83             : using namespace mozilla::dom;
      84             : 
      85             : /* Define Class IDs */
      86             : static NS_DEFINE_CID(kWindowCID,           NS_WINDOW_CID);
      87             : 
      88             : #define SIZE_PERSISTENCE_TIMEOUT 500 // msec
      89             : 
      90           2 : nsWebShellWindow::nsWebShellWindow(uint32_t aChromeFlags)
      91             :   : nsXULWindow(aChromeFlags)
      92           2 :   , mSPTimerLock("nsWebShellWindow.mSPTimerLock")
      93             : {
      94           2 : }
      95             : 
      96           0 : nsWebShellWindow::~nsWebShellWindow()
      97             : {
      98           0 :   MutexAutoLock lock(mSPTimerLock);
      99           0 :   if (mSPTimer)
     100           0 :     mSPTimer->Cancel();
     101           0 : }
     102             : 
     103          44 : NS_IMPL_ADDREF_INHERITED(nsWebShellWindow, nsXULWindow)
     104          40 : NS_IMPL_RELEASE_INHERITED(nsWebShellWindow, nsXULWindow)
     105             : 
     106          37 : NS_INTERFACE_MAP_BEGIN(nsWebShellWindow)
     107          37 :   NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)
     108          29 : NS_INTERFACE_MAP_END_INHERITING(nsXULWindow)
     109             : 
     110           2 : nsresult nsWebShellWindow::Initialize(nsIXULWindow* aParent,
     111             :                                       nsIXULWindow* aOpener,
     112             :                                       nsIURI* aUrl,
     113             :                                       int32_t aInitialWidth,
     114             :                                       int32_t aInitialHeight,
     115             :                                       bool aIsHiddenWindow,
     116             :                                       nsITabParent *aOpeningTab,
     117             :                                       mozIDOMWindowProxy *aOpenerWindow,
     118             :                                       nsWidgetInitData& widgetInitData)
     119             : {
     120             :   nsresult rv;
     121           4 :   nsCOMPtr<nsIWidget> parentWidget;
     122             : 
     123           2 :   mIsHiddenWindow = aIsHiddenWindow;
     124             : 
     125           2 :   int32_t initialX = 0, initialY = 0;
     126           4 :   nsCOMPtr<nsIBaseWindow> base(do_QueryInterface(aOpener));
     127           2 :   if (base) {
     128           0 :     rv = base->GetPositionAndSize(&mOpenerScreenRect.x,
     129             :                                   &mOpenerScreenRect.y,
     130             :                                   &mOpenerScreenRect.width,
     131           0 :                                   &mOpenerScreenRect.height);
     132           0 :     if (NS_FAILED(rv)) {
     133           0 :       mOpenerScreenRect.SetEmpty();
     134             :     } else {
     135             :       double scale;
     136           0 :       if (NS_SUCCEEDED(base->GetUnscaledDevicePixelsPerCSSPixel(&scale))) {
     137           0 :         mOpenerScreenRect.x = NSToIntRound(mOpenerScreenRect.x / scale);
     138           0 :         mOpenerScreenRect.y = NSToIntRound(mOpenerScreenRect.y / scale);
     139           0 :         mOpenerScreenRect.width = NSToIntRound(mOpenerScreenRect.width / scale);
     140           0 :         mOpenerScreenRect.height = NSToIntRound(mOpenerScreenRect.height / scale);
     141             :       }
     142           0 :       initialX = mOpenerScreenRect.x;
     143           0 :       initialY = mOpenerScreenRect.y;
     144           0 :       ConstrainToOpenerScreen(&initialX, &initialY);
     145             :     }
     146             :   }
     147             : 
     148             :   // XXX: need to get the default window size from prefs...
     149             :   // Doesn't come from prefs... will come from CSS/XUL/RDF
     150           2 :   DesktopIntRect deskRect(initialX, initialY, aInitialWidth, aInitialHeight);
     151             : 
     152             :   // Create top level window
     153           2 :   if (gfxPlatform::IsHeadless()) {
     154           0 :     mWindow = nsIWidget::CreateHeadlessWidget();
     155           0 :     if (!mWindow) {
     156           0 :       return NS_ERROR_FAILURE;
     157             :     }
     158             :   } else {
     159           2 :     mWindow = do_CreateInstance(kWindowCID, &rv);
     160           2 :     if (NS_OK != rv) {
     161           0 :       return rv;
     162             :     }
     163             :   }
     164             : 
     165             :   /* This next bit is troublesome. We carry two different versions of a pointer
     166             :      to our parent window. One is the parent window's widget, which is passed
     167             :      to our own widget. The other is a weak reference we keep here to our
     168             :      parent WebShellWindow. The former is useful to the widget, and we can't
     169             :      trust its treatment of the parent reference because they're platform-
     170             :      specific. The latter is useful to this class.
     171             :        A better implementation would be one in which the parent keeps strong
     172             :      references to its children and closes them before it allows itself
     173             :      to be closed. This would mimic the behaviour of OSes that support
     174             :      top-level child windows in OSes that do not. Later.
     175             :   */
     176           4 :   nsCOMPtr<nsIBaseWindow> parentAsWin(do_QueryInterface(aParent));
     177           2 :   if (parentAsWin) {
     178           0 :     parentAsWin->GetMainWidget(getter_AddRefs(parentWidget));
     179           0 :     mParentWindow = do_GetWeakReference(aParent);
     180             :   }
     181             : 
     182           2 :   mWindow->SetWidgetListener(this);
     183           4 :   rv = mWindow->Create((nsIWidget *)parentWidget, // Parent nsIWidget
     184             :                        nullptr,                   // Native parent widget
     185             :                        deskRect,                  // Widget dimensions
     186           2 :                        &widgetInitData);          // Widget initialization data
     187           2 :   NS_ENSURE_SUCCESS(rv, rv);
     188             : 
     189           2 :   LayoutDeviceIntRect r = mWindow->GetClientBounds();
     190             :   // Match the default background color of content. Important on windows
     191             :   // since we no longer use content child widgets.
     192           2 :   mWindow->SetBackgroundColor(NS_RGB(255,255,255));
     193             : 
     194             :   // Create web shell
     195           2 :   mDocShell = do_CreateInstance("@mozilla.org/docshell;1");
     196           2 :   NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
     197             : 
     198           2 :   mDocShell->SetOpener(aOpeningTab);
     199             : 
     200             :   // Make sure to set the item type on the docshell _before_ calling
     201             :   // Create() so it knows what type it is.
     202           4 :   nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryInterface(mDocShell));
     203           2 :   NS_ENSURE_TRUE(docShellAsItem, NS_ERROR_FAILURE);
     204           2 :   NS_ENSURE_SUCCESS(EnsureChromeTreeOwner(), NS_ERROR_FAILURE);
     205             : 
     206           2 :   docShellAsItem->SetTreeOwner(mChromeTreeOwner);
     207           2 :   docShellAsItem->SetItemType(nsIDocShellTreeItem::typeChrome);
     208             : 
     209           2 :   r.x = r.y = 0;
     210           4 :   nsCOMPtr<nsIBaseWindow> docShellAsWin(do_QueryInterface(mDocShell));
     211           2 :   NS_ENSURE_SUCCESS(docShellAsWin->InitWindow(nullptr, mWindow,
     212             :    r.x, r.y, r.width, r.height), NS_ERROR_FAILURE);
     213           2 :   NS_ENSURE_SUCCESS(docShellAsWin->Create(), NS_ERROR_FAILURE);
     214             : 
     215             :   // Attach a WebProgress listener.during initialization...
     216           4 :   nsCOMPtr<nsIWebProgress> webProgress(do_GetInterface(mDocShell, &rv));
     217           2 :   if (webProgress) {
     218           2 :     webProgress->AddProgressListener(this, nsIWebProgress::NOTIFY_STATE_NETWORK);
     219             :   }
     220             : 
     221           2 :   if (aOpenerWindow) {
     222           0 :     nsPIDOMWindowOuter* window = mDocShell->GetWindow();
     223           0 :     MOZ_ASSERT(window);
     224           0 :     window->SetOpenerWindow(nsPIDOMWindowOuter::From(aOpenerWindow), true);
     225             :   }
     226             : 
     227             :   // Eagerly create an about:blank content viewer with the right principal here,
     228             :   // rather than letting it happening in the upcoming call to
     229             :   // SetInitialPrincipalToSubject. This avoids creating the about:blank document
     230             :   // and then blowing it away with a second one, which can cause problems for the
     231             :   // top-level chrome window case. See bug 789773.
     232             :   // Note that we don't accept expanded principals here, similar to
     233             :   // SetInitialPrincipalToSubject.
     234           2 :   if (nsContentUtils::IsInitialized()) { // Sometimes this happens really early  See bug 793370.
     235           2 :     MOZ_ASSERT(mDocShell->ItemType() == nsIDocShellTreeItem::typeChrome);
     236           4 :     nsCOMPtr<nsIPrincipal> principal = nsContentUtils::SubjectPrincipalOrSystemIfNativeCaller();
     237           2 :     if (nsContentUtils::IsExpandedPrincipal(principal)) {
     238           0 :       principal = nullptr;
     239             :     }
     240           2 :     rv = mDocShell->CreateAboutBlankContentViewer(principal);
     241           2 :     NS_ENSURE_SUCCESS(rv, rv);
     242           4 :     nsCOMPtr<nsIDocument> doc = mDocShell->GetDocument();
     243           2 :     NS_ENSURE_TRUE(!!doc, NS_ERROR_FAILURE);
     244           2 :     doc->SetIsInitialDocument(true);
     245             :   }
     246             : 
     247           2 :   if (nullptr != aUrl)  {
     248           2 :     nsCString tmpStr;
     249             : 
     250           1 :     rv = aUrl->GetSpec(tmpStr);
     251           1 :     if (NS_FAILED(rv)) return rv;
     252             : 
     253           2 :     NS_ConvertUTF8toUTF16 urlString(tmpStr);
     254           2 :     nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(mDocShell));
     255           1 :     NS_ENSURE_TRUE(webNav, NS_ERROR_FAILURE);
     256           2 :     rv = webNav->LoadURI(urlString.get(),
     257             :                          nsIWebNavigation::LOAD_FLAGS_NONE,
     258             :                          nullptr,
     259             :                          nullptr,
     260             :                          nullptr,
     261           1 :                          nsContentUtils::GetSystemPrincipal());
     262           1 :     NS_ENSURE_SUCCESS(rv, rv);
     263             :   }
     264             : 
     265           2 :   return rv;
     266             : }
     267             : 
     268             : nsIPresShell*
     269           1 : nsWebShellWindow::GetPresShell()
     270             : {
     271           1 :   if (!mDocShell)
     272           0 :     return nullptr;
     273             : 
     274           1 :   return mDocShell->GetPresShell();
     275             : }
     276             : 
     277             : bool
     278           5 : nsWebShellWindow::WindowMoved(nsIWidget* aWidget, int32_t x, int32_t y)
     279             : {
     280           5 :   nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
     281           5 :   if (pm) {
     282             :     nsCOMPtr<nsPIDOMWindowOuter> window =
     283          10 :       mDocShell ? mDocShell->GetWindow() : nullptr;
     284           5 :     pm->AdjustPopupsOnWindowChange(window);
     285             :   }
     286             : 
     287             :   // Notify all tabs that the widget moved.
     288           5 :   if (mDocShell && mDocShell->GetWindow()) {
     289          10 :     nsCOMPtr<EventTarget> eventTarget = mDocShell->GetWindow()->GetTopWindowRoot();
     290          10 :     nsContentUtils::DispatchChromeEvent(mDocShell->GetDocument(),
     291             :                                         eventTarget,
     292          10 :                                         NS_LITERAL_STRING("MozUpdateWindowPos"),
     293          15 :                                         false, false, nullptr);
     294             :   }
     295             : 
     296             :   // Persist position, but not immediately, in case this OS is firing
     297             :   // repeated move events as the user drags the window
     298           5 :   SetPersistenceTimer(PAD_POSITION);
     299           5 :   return false;
     300             : }
     301             : 
     302             : bool
     303           2 : nsWebShellWindow::WindowResized(nsIWidget* aWidget, int32_t aWidth, int32_t aHeight)
     304             : {
     305           4 :   nsCOMPtr<nsIBaseWindow> shellAsWin(do_QueryInterface(mDocShell));
     306           2 :   if (shellAsWin) {
     307           2 :     shellAsWin->SetPositionAndSize(0, 0, aWidth, aHeight, 0);
     308             :   }
     309             :   // Persist size, but not immediately, in case this OS is firing
     310             :   // repeated size events as the user drags the sizing handle
     311           2 :   if (!IsLocked())
     312           2 :     SetPersistenceTimer(PAD_POSITION | PAD_SIZE | PAD_MISC);
     313           4 :   return true;
     314             : }
     315             : 
     316             : bool
     317           0 : nsWebShellWindow::RequestWindowClose(nsIWidget* aWidget)
     318             : {
     319             :   // Maintain a reference to this as it is about to get destroyed.
     320           0 :   nsCOMPtr<nsIXULWindow> xulWindow(this);
     321             : 
     322           0 :   nsCOMPtr<nsPIDOMWindowOuter> window(mDocShell ? mDocShell->GetWindow() : nullptr);
     323           0 :   nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(window);
     324             : 
     325           0 :   nsCOMPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
     326           0 :   if (!presShell) {
     327           0 :     mozilla::DebugOnly<bool> dying;
     328           0 :     MOZ_ASSERT(NS_SUCCEEDED(mDocShell->IsBeingDestroyed(&dying)) && dying,
     329             :                "No presShell, but window is not being destroyed");
     330           0 :   } else if (eventTarget) {
     331           0 :     RefPtr<nsPresContext> presContext = presShell->GetPresContext();
     332             : 
     333           0 :     nsEventStatus status = nsEventStatus_eIgnore;
     334             :     WidgetMouseEvent event(true, eClose, nullptr,
     335           0 :                            WidgetMouseEvent::eReal);
     336           0 :     if (NS_SUCCEEDED(eventTarget->DispatchDOMEvent(&event, nullptr, presContext, &status)) &&
     337           0 :         status == nsEventStatus_eConsumeNoDefault)
     338           0 :       return false;
     339             :   }
     340             : 
     341           0 :   Destroy();
     342           0 :   return false;
     343             : }
     344             : 
     345             : void
     346           1 : nsWebShellWindow::SizeModeChanged(nsSizeMode sizeMode)
     347             : {
     348             :   // An alwaysRaised (or higher) window will hide any newly opened normal
     349             :   // browser windows, so here we just drop a raised window to the normal
     350             :   // zlevel if it's maximized. We make no provision for automatically
     351             :   // re-raising it when restored.
     352           1 :   if (sizeMode == nsSizeMode_Maximized || sizeMode == nsSizeMode_Fullscreen) {
     353             :     uint32_t zLevel;
     354           1 :     GetZLevel(&zLevel);
     355           1 :     if (zLevel > nsIXULWindow::normalZ)
     356           0 :       SetZLevel(nsIXULWindow::normalZ);
     357             :   }
     358           1 :   mWindow->SetSizeMode(sizeMode);
     359             : 
     360             :   // Persist mode, but not immediately, because in many (all?)
     361             :   // cases this will merge with the similar call in NS_SIZE and
     362             :   // write the attribute values only once.
     363           1 :   SetPersistenceTimer(PAD_MISC);
     364             :   nsCOMPtr<nsPIDOMWindowOuter> ourWindow =
     365           2 :     mDocShell ? mDocShell->GetWindow() : nullptr;
     366           1 :   if (ourWindow) {
     367           1 :     MOZ_ASSERT(ourWindow->IsOuterWindow());
     368             : 
     369             :     // Ensure that the fullscreen state is synchronized between
     370             :     // the widget and the outer window object.
     371           1 :     if (sizeMode == nsSizeMode_Fullscreen) {
     372           0 :       ourWindow->SetFullScreen(true);
     373             :     }
     374           1 :     else if (sizeMode != nsSizeMode_Minimized) {
     375           1 :       if (ourWindow->GetFullScreen()) {
     376             :         // The first SetFullscreenInternal call below ensures that we do
     377             :         // not trigger any fullscreen transition even if the window was
     378             :         // put in fullscreen only for the Fullscreen API. The second
     379             :         // SetFullScreen call ensures that the window really exit from
     380             :         // fullscreen even if it entered fullscreen for both Fullscreen
     381             :         // Mode and Fullscreen API.
     382           0 :         ourWindow->SetFullscreenInternal(FullscreenReason::ForForceExitFullscreen, false);
     383           0 :         ourWindow->SetFullScreen(false);
     384             :       }
     385             :     }
     386             : 
     387             :     // And always fire a user-defined sizemodechange event on the window
     388           1 :     ourWindow->DispatchCustomEvent(NS_LITERAL_STRING("sizemodechange"));
     389             :   }
     390             : 
     391             :   nsIPresShell* presShell;
     392           1 :   if ((presShell = GetPresShell())) {
     393           1 :     presShell->GetPresContext()->SizeModeChanged(sizeMode);
     394             :   }
     395             : 
     396             :   // Note the current implementation of SetSizeMode just stores
     397             :   // the new state; it doesn't actually resize. So here we store
     398             :   // the state and pass the event on to the OS. The day is coming
     399             :   // when we'll handle the event here, and the return result will
     400             :   // then need to be different.
     401           1 : }
     402             : 
     403             : void
     404           0 : nsWebShellWindow::UIResolutionChanged()
     405             : {
     406             :   nsCOMPtr<nsPIDOMWindowOuter> ourWindow =
     407           0 :     mDocShell ? mDocShell->GetWindow() : nullptr;
     408           0 :   if (ourWindow) {
     409           0 :     MOZ_ASSERT(ourWindow->IsOuterWindow());
     410           0 :     ourWindow->DispatchCustomEvent(NS_LITERAL_STRING("resolutionchange"));
     411             :   }
     412           0 : }
     413             : 
     414             : void
     415           0 : nsWebShellWindow::FullscreenChanged(bool aInFullscreen)
     416             : {
     417           0 :   if (mDocShell) {
     418           0 :     if (nsCOMPtr<nsPIDOMWindowOuter> ourWindow = mDocShell->GetWindow()) {
     419           0 :       ourWindow->FinishFullscreenChange(aInFullscreen);
     420             :     }
     421             :   }
     422           0 : }
     423             : 
     424             : void
     425           0 : nsWebShellWindow::OcclusionStateChanged(bool aIsFullyOccluded)
     426             : {
     427             :   nsCOMPtr<nsPIDOMWindowOuter> ourWindow =
     428           0 :     mDocShell ? mDocShell->GetWindow() : nullptr;
     429           0 :   if (ourWindow) {
     430           0 :     MOZ_ASSERT(ourWindow->IsOuterWindow());
     431             :     // And always fire a user-defined occlusionstatechange event on the window
     432           0 :     ourWindow->DispatchCustomEvent(NS_LITERAL_STRING("occlusionstatechange"));
     433             :   }
     434           0 : }
     435             : 
     436             : void
     437           0 : nsWebShellWindow::OSToolbarButtonPressed()
     438             : {
     439             :   // Keep a reference as setting the chrome flags can fire events.
     440           0 :   nsCOMPtr<nsIXULWindow> xulWindow(this);
     441             : 
     442             :   // rjc: don't use "nsIWebBrowserChrome::CHROME_EXTRA"
     443             :   //      due to components with multiple sidebar components
     444             :   //      (such as Mail/News, Addressbook, etc)... and frankly,
     445             :   //      Mac IE, OmniWeb, and other Mac OS X apps all work this way
     446             :   uint32_t    chromeMask = (nsIWebBrowserChrome::CHROME_TOOLBAR |
     447             :                             nsIWebBrowserChrome::CHROME_LOCATIONBAR |
     448           0 :                             nsIWebBrowserChrome::CHROME_PERSONAL_TOOLBAR);
     449             : 
     450           0 :   nsCOMPtr<nsIWebBrowserChrome> wbc(do_GetInterface(xulWindow));
     451           0 :   if (!wbc)
     452           0 :     return;
     453             : 
     454           0 :   uint32_t    chromeFlags, newChromeFlags = 0;
     455           0 :   wbc->GetChromeFlags(&chromeFlags);
     456           0 :   newChromeFlags = chromeFlags & chromeMask;
     457           0 :   if (!newChromeFlags)    chromeFlags |= chromeMask;
     458           0 :   else                    chromeFlags &= (~newChromeFlags);
     459           0 :   wbc->SetChromeFlags(chromeFlags);
     460             : }
     461             : 
     462             : bool
     463           0 : nsWebShellWindow::ZLevelChanged(bool aImmediate, nsWindowZ *aPlacement,
     464             :                                 nsIWidget* aRequestBelow, nsIWidget** aActualBelow)
     465             : {
     466           0 :   if (aActualBelow)
     467           0 :     *aActualBelow = nullptr;
     468             : 
     469           0 :   return ConstrainToZLevel(aImmediate, aPlacement, aRequestBelow, aActualBelow);
     470             : }
     471             : 
     472             : void
     473           1 : nsWebShellWindow::WindowActivated()
     474             : {
     475           2 :   nsCOMPtr<nsIXULWindow> xulWindow(this);
     476             : 
     477             :   // focusing the window could cause it to close, so keep a reference to it
     478           2 :   nsCOMPtr<nsPIDOMWindowOuter> window = mDocShell ? mDocShell->GetWindow() : nullptr;
     479           2 :   nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID);
     480           1 :   if (fm && window)
     481           1 :     fm->WindowRaised(window);
     482             : 
     483           1 :   if (mChromeLoaded) {
     484           1 :     PersistentAttributesDirty(PAD_POSITION | PAD_SIZE | PAD_MISC);
     485           1 :     SavePersistentAttributes();
     486             :    }
     487           1 : }
     488             : 
     489             : void
     490           0 : nsWebShellWindow::WindowDeactivated()
     491             : {
     492           0 :   nsCOMPtr<nsIXULWindow> xulWindow(this);
     493             : 
     494             :   nsCOMPtr<nsPIDOMWindowOuter> window =
     495           0 :     mDocShell ? mDocShell->GetWindow() : nullptr;
     496           0 :   nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID);
     497           0 :   if (fm && window)
     498           0 :     fm->WindowLowered(window);
     499           0 : }
     500             : 
     501             : #ifdef USE_NATIVE_MENUS
     502             : static void LoadNativeMenus(nsIDOMDocument *aDOMDoc, nsIWidget *aParentWindow)
     503             : {
     504             :   nsCOMPtr<nsINativeMenuService> nms = do_GetService("@mozilla.org/widget/nativemenuservice;1");
     505             :   if (!nms) {
     506             :     return;
     507             :   }
     508             : 
     509             :   // Find the menubar tag (if there is more than one, we ignore all but
     510             :   // the first).
     511             :   nsCOMPtr<nsIDOMNodeList> menubarElements;
     512             :   aDOMDoc->GetElementsByTagNameNS(NS_LITERAL_STRING("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"),
     513             :                                   NS_LITERAL_STRING("menubar"),
     514             :                                   getter_AddRefs(menubarElements));
     515             : 
     516             :   nsCOMPtr<nsIDOMNode> menubarNode;
     517             :   if (menubarElements)
     518             :     menubarElements->Item(0, getter_AddRefs(menubarNode));
     519             : 
     520             :   if (menubarNode) {
     521             :     nsCOMPtr<nsIContent> menubarContent(do_QueryInterface(menubarNode));
     522             :     nms->CreateNativeMenuBar(aParentWindow, menubarContent);
     523             :   } else {
     524             :     nms->CreateNativeMenuBar(aParentWindow, nullptr);
     525             :   }
     526             : }
     527             : #endif
     528             : 
     529             : namespace mozilla {
     530             : 
     531             : class WebShellWindowTimerCallback final : public nsITimerCallback
     532             : {
     533             : public:
     534           8 :   explicit WebShellWindowTimerCallback(nsWebShellWindow* aWindow)
     535           8 :     : mWindow(aWindow)
     536           8 :   {}
     537             : 
     538             :   NS_DECL_THREADSAFE_ISUPPORTS
     539             : 
     540           1 :   NS_IMETHOD Notify(nsITimer* aTimer) override
     541             :   {
     542             :     // Although this object participates in a refcount cycle (this -> mWindow
     543             :     // -> mSPTimer -> this), mSPTimer is a one-shot timer and releases this
     544             :     // after it fires.  So we don't need to release mWindow here.
     545             : 
     546           1 :     mWindow->FirePersistenceTimer();
     547           1 :     return NS_OK;
     548             :   }
     549             : 
     550             : private:
     551           8 :   ~WebShellWindowTimerCallback() {}
     552             : 
     553             :   RefPtr<nsWebShellWindow> mWindow;
     554             : };
     555             : 
     556          42 : NS_IMPL_ISUPPORTS(WebShellWindowTimerCallback, nsITimerCallback)
     557             : 
     558             : } // namespace mozilla
     559             : 
     560             : void
     561           8 : nsWebShellWindow::SetPersistenceTimer(uint32_t aDirtyFlags)
     562             : {
     563          16 :   MutexAutoLock lock(mSPTimerLock);
     564           8 :   if (!mSPTimer) {
     565           1 :     mSPTimer = do_CreateInstance("@mozilla.org/timer;1");
     566           1 :     if (!mSPTimer) {
     567           0 :       NS_WARNING("Couldn't create @mozilla.org/timer;1 instance?");
     568           0 :       return;
     569             :     }
     570             :   }
     571             : 
     572             :   RefPtr<WebShellWindowTimerCallback> callback =
     573          16 :     new WebShellWindowTimerCallback(this);
     574           8 :   mSPTimer->InitWithCallback(callback, SIZE_PERSISTENCE_TIMEOUT,
     575           8 :                              nsITimer::TYPE_ONE_SHOT);
     576             : 
     577           8 :   PersistentAttributesDirty(aDirtyFlags);
     578             : }
     579             : 
     580             : void
     581           1 : nsWebShellWindow::FirePersistenceTimer()
     582             : {
     583           2 :   MutexAutoLock lock(mSPTimerLock);
     584           1 :   SavePersistentAttributes();
     585           1 : }
     586             : 
     587             : 
     588             : //----------------------------------------
     589             : // nsIWebProgessListener implementation
     590             : //----------------------------------------
     591             : NS_IMETHODIMP
     592           0 : nsWebShellWindow::OnProgressChange(nsIWebProgress *aProgress,
     593             :                                    nsIRequest *aRequest,
     594             :                                    int32_t aCurSelfProgress,
     595             :                                    int32_t aMaxSelfProgress,
     596             :                                    int32_t aCurTotalProgress,
     597             :                                    int32_t aMaxTotalProgress)
     598             : {
     599           0 :   NS_NOTREACHED("notification excluded in AddProgressListener(...)");
     600           0 :   return NS_OK;
     601             : }
     602             : 
     603             : NS_IMETHODIMP
     604           4 : nsWebShellWindow::OnStateChange(nsIWebProgress *aProgress,
     605             :                                 nsIRequest *aRequest,
     606             :                                 uint32_t aStateFlags,
     607             :                                 nsresult aStatus)
     608             : {
     609             :   // If the notification is not about a document finishing, then just
     610             :   // ignore it...
     611           6 :   if (!(aStateFlags & nsIWebProgressListener::STATE_STOP) ||
     612           2 :       !(aStateFlags & nsIWebProgressListener::STATE_IS_NETWORK)) {
     613           2 :     return NS_OK;
     614             :   }
     615             : 
     616           2 :   if (mChromeLoaded)
     617           0 :     return NS_OK;
     618             : 
     619             :   // If this document notification is for a frame then ignore it...
     620           4 :   nsCOMPtr<mozIDOMWindowProxy> eventWin;
     621           2 :   aProgress->GetDOMWindow(getter_AddRefs(eventWin));
     622           2 :   auto* eventPWin = nsPIDOMWindowOuter::From(eventWin);
     623           2 :   if (eventPWin) {
     624           2 :     nsPIDOMWindowOuter *rootPWin = eventPWin->GetPrivateRoot();
     625           2 :     if (eventPWin != rootPWin)
     626           0 :       return NS_OK;
     627             :   }
     628             : 
     629           2 :   mChromeLoaded = true;
     630           2 :   mLockedUntilChromeLoad = false;
     631             : 
     632             : #ifdef USE_NATIVE_MENUS
     633             :   ///////////////////////////////
     634             :   // Find the Menubar DOM  and Load the menus, hooking them up to the loaded commands
     635             :   ///////////////////////////////
     636             :   nsCOMPtr<nsIContentViewer> cv;
     637             :   mDocShell->GetContentViewer(getter_AddRefs(cv));
     638             :   if (cv) {
     639             :     nsCOMPtr<nsIDOMDocument> menubarDOMDoc(do_QueryInterface(cv->GetDocument()));
     640             :     if (menubarDOMDoc)
     641             :       LoadNativeMenus(menubarDOMDoc, mWindow);
     642             :   }
     643             : #endif // USE_NATIVE_MENUS
     644             : 
     645           2 :   OnChromeLoaded();
     646             : 
     647           2 :   return NS_OK;
     648             : }
     649             : 
     650             : NS_IMETHODIMP
     651           0 : nsWebShellWindow::OnLocationChange(nsIWebProgress *aProgress,
     652             :                                    nsIRequest *aRequest,
     653             :                                    nsIURI *aURI,
     654             :                                    uint32_t aFlags)
     655             : {
     656           0 :   NS_NOTREACHED("notification excluded in AddProgressListener(...)");
     657           0 :   return NS_OK;
     658             : }
     659             : 
     660             : NS_IMETHODIMP
     661           0 : nsWebShellWindow::OnStatusChange(nsIWebProgress* aWebProgress,
     662             :                                  nsIRequest* aRequest,
     663             :                                  nsresult aStatus,
     664             :                                  const char16_t* aMessage)
     665             : {
     666           0 :   NS_NOTREACHED("notification excluded in AddProgressListener(...)");
     667           0 :   return NS_OK;
     668             : }
     669             : 
     670             : NS_IMETHODIMP
     671           0 : nsWebShellWindow::OnSecurityChange(nsIWebProgress *aWebProgress,
     672             :                                    nsIRequest *aRequest,
     673             :                                    uint32_t state)
     674             : {
     675           0 :   NS_NOTREACHED("notification excluded in AddProgressListener(...)");
     676           0 :   return NS_OK;
     677             : }
     678             : 
     679             : 
     680             : /**
     681             :  * ExecuteCloseHandler - Run the close handler, if any.
     682             :  * @return true iff we found a close handler to run.
     683             :  */
     684           0 : bool nsWebShellWindow::ExecuteCloseHandler()
     685             : {
     686             :   /* If the event handler closes this window -- a likely scenario --
     687             :      things get deleted out of order without this death grip.
     688             :      (The problem may be the death grip in nsWindow::windowProc,
     689             :      which forces this window's widget to remain alive longer
     690             :      than it otherwise would.) */
     691           0 :   nsCOMPtr<nsIXULWindow> kungFuDeathGrip(this);
     692             : 
     693           0 :   nsCOMPtr<EventTarget> eventTarget;
     694           0 :   if (mDocShell) {
     695           0 :     eventTarget = do_QueryInterface(mDocShell->GetWindow());
     696             :   }
     697             : 
     698           0 :   if (eventTarget) {
     699           0 :     nsCOMPtr<nsIContentViewer> contentViewer;
     700           0 :     mDocShell->GetContentViewer(getter_AddRefs(contentViewer));
     701           0 :     if (contentViewer) {
     702           0 :       RefPtr<nsPresContext> presContext;
     703           0 :       contentViewer->GetPresContext(getter_AddRefs(presContext));
     704             : 
     705           0 :       nsEventStatus status = nsEventStatus_eIgnore;
     706             :       WidgetMouseEvent event(true, eClose, nullptr,
     707           0 :                              WidgetMouseEvent::eReal);
     708             : 
     709             :       nsresult rv =
     710           0 :         eventTarget->DispatchDOMEvent(&event, nullptr, presContext, &status);
     711           0 :       if (NS_SUCCEEDED(rv) && status == nsEventStatus_eConsumeNoDefault)
     712           0 :         return true;
     713             :       // else fall through and return false
     714             :     }
     715             :   }
     716             : 
     717           0 :   return false;
     718             : } // ExecuteCloseHandler
     719             : 
     720           0 : void nsWebShellWindow::ConstrainToOpenerScreen(int32_t* aX, int32_t* aY)
     721             : {
     722           0 :   if (mOpenerScreenRect.IsEmpty()) {
     723           0 :     *aX = *aY = 0;
     724           0 :     return;
     725             :   }
     726             : 
     727             :   int32_t left, top, width, height;
     728             :   // Constrain initial positions to the same screen as opener
     729           0 :   nsCOMPtr<nsIScreenManager> screenmgr = do_GetService("@mozilla.org/gfx/screenmanager;1");
     730           0 :   if (screenmgr) {
     731           0 :     nsCOMPtr<nsIScreen> screen;
     732           0 :     screenmgr->ScreenForRect(mOpenerScreenRect.x, mOpenerScreenRect.y,
     733             :                              mOpenerScreenRect.width, mOpenerScreenRect.height,
     734           0 :                              getter_AddRefs(screen));
     735           0 :     if (screen) {
     736           0 :       screen->GetAvailRectDisplayPix(&left, &top, &width, &height);
     737           0 :       if (*aX < left || *aX > left + width) {
     738           0 :         *aX = left;
     739             :       }
     740           0 :       if (*aY < top || *aY > top + height) {
     741           0 :         *aY = top;
     742             :       }
     743             :     }
     744             :   }
     745             : }
     746             : 
     747             : // nsIBaseWindow
     748           0 : NS_IMETHODIMP nsWebShellWindow::Destroy()
     749             : {
     750             :   nsresult rv;
     751           0 :   nsCOMPtr<nsIWebProgress> webProgress(do_GetInterface(mDocShell, &rv));
     752           0 :   if (webProgress) {
     753           0 :     webProgress->RemoveProgressListener(this);
     754             :   }
     755             : 
     756           0 :   nsCOMPtr<nsIXULWindow> kungFuDeathGrip(this);
     757             :   {
     758           0 :     MutexAutoLock lock(mSPTimerLock);
     759           0 :     if (mSPTimer) {
     760           0 :       mSPTimer->Cancel();
     761           0 :       SavePersistentAttributes();
     762           0 :       mSPTimer = nullptr;
     763             :     }
     764             :   }
     765           0 :   return nsXULWindow::Destroy();
     766             : }

Generated by: LCOV version 1.13