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

mercurial