123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912 |
- /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- #include "nsWebShellWindow.h"
- #include "nsLayoutCID.h"
- #include "nsContentCID.h"
- #include "nsIWeakReference.h"
- #include "nsIContentViewer.h"
- #include "nsIComponentManager.h"
- #include "nsIServiceManager.h"
- #include "nsIURL.h"
- #include "nsIIOService.h"
- #include "nsIURL.h"
- #include "nsNetCID.h"
- #include "nsIStringBundle.h"
- #include "nsReadableUtils.h"
- #include "nsContentUtils.h"
- #include "nsEscape.h"
- #include "nsPIDOMWindow.h"
- #include "nsIWebNavigation.h"
- #include "nsIWindowWatcher.h"
- #include "nsIDOMXULElement.h"
- #include "nsWidgetInitData.h"
- #include "nsWidgetsCID.h"
- #include "nsIWidget.h"
- #include "nsIWidgetListener.h"
- #include "nsIDOMCharacterData.h"
- #include "nsIDOMNodeList.h"
- #include "nsITimer.h"
- #include "nsXULPopupManager.h"
- #include "nsIDOMXULDocument.h"
- #include "nsFocusManager.h"
- #include "nsIWebProgress.h"
- #include "nsIWebProgressListener.h"
- #include "nsIDocument.h"
- #include "nsIDOMDocument.h"
- #include "nsIDOMNode.h"
- #include "nsIDOMElement.h"
- #include "nsIDocumentLoaderFactory.h"
- #include "nsIObserverService.h"
- #include "prprf.h"
- #include "nsIScreenManager.h"
- #include "nsIScreen.h"
- #include "nsIContent.h" // for menus
- #include "nsIScriptSecurityManager.h"
- // For calculating size
- #include "nsIPresShell.h"
- #include "nsPresContext.h"
- #include "nsIBaseWindow.h"
- #include "nsIDocShellTreeItem.h"
- #include "mozilla/Attributes.h"
- #include "mozilla/DebugOnly.h"
- #include "mozilla/MouseEvents.h"
- #include "nsPIWindowRoot.h"
- #if defined(MOZ_WIDGET_GTK)
- #include "nsINativeMenuService.h"
- #define USE_NATIVE_MENUS
- #endif
- using namespace mozilla;
- using namespace mozilla::dom;
- /* Define Class IDs */
- static NS_DEFINE_CID(kWindowCID, NS_WINDOW_CID);
- #define SIZE_PERSISTENCE_TIMEOUT 500 // msec
- nsWebShellWindow::nsWebShellWindow(uint32_t aChromeFlags)
- : nsXULWindow(aChromeFlags)
- , mSPTimerLock("nsWebShellWindow.mSPTimerLock")
- , mWidgetListenerDelegate(this)
- {
- }
- nsWebShellWindow::~nsWebShellWindow()
- {
- MutexAutoLock lock(mSPTimerLock);
- if (mSPTimer)
- mSPTimer->Cancel();
- }
- NS_IMPL_ADDREF_INHERITED(nsWebShellWindow, nsXULWindow)
- NS_IMPL_RELEASE_INHERITED(nsWebShellWindow, nsXULWindow)
- NS_INTERFACE_MAP_BEGIN(nsWebShellWindow)
- NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)
- NS_INTERFACE_MAP_END_INHERITING(nsXULWindow)
- nsresult nsWebShellWindow::Initialize(nsIXULWindow* aParent,
- nsIXULWindow* aOpener,
- nsIURI* aUrl,
- int32_t aInitialWidth,
- int32_t aInitialHeight,
- bool aIsHiddenWindow,
- nsITabParent *aOpeningTab,
- mozIDOMWindowProxy *aOpenerWindow,
- nsWidgetInitData& widgetInitData)
- {
- nsresult rv;
- nsCOMPtr<nsIWidget> parentWidget;
- mIsHiddenWindow = aIsHiddenWindow;
- int32_t initialX = 0, initialY = 0;
- nsCOMPtr<nsIBaseWindow> base(do_QueryInterface(aOpener));
- if (base) {
- rv = base->GetPositionAndSize(&mOpenerScreenRect.x,
- &mOpenerScreenRect.y,
- &mOpenerScreenRect.width,
- &mOpenerScreenRect.height);
- if (NS_FAILED(rv)) {
- mOpenerScreenRect.SetEmpty();
- } else {
- double scale;
- if (NS_SUCCEEDED(base->GetUnscaledDevicePixelsPerCSSPixel(&scale))) {
- mOpenerScreenRect.x = NSToIntRound(mOpenerScreenRect.x / scale);
- mOpenerScreenRect.y = NSToIntRound(mOpenerScreenRect.y / scale);
- mOpenerScreenRect.width = NSToIntRound(mOpenerScreenRect.width / scale);
- mOpenerScreenRect.height = NSToIntRound(mOpenerScreenRect.height / scale);
- }
- initialX = mOpenerScreenRect.x;
- initialY = mOpenerScreenRect.y;
- ConstrainToOpenerScreen(&initialX, &initialY);
- }
- }
- // XXX: need to get the default window size from prefs...
- // Doesn't come from prefs... will come from CSS/XUL/RDF
- DesktopIntRect deskRect(initialX, initialY, aInitialWidth, aInitialHeight);
- // Create top level window
- mWindow = do_CreateInstance(kWindowCID, &rv);
- if (NS_OK != rv) {
- return rv;
- }
- /* This next bit is troublesome. We carry two different versions of a pointer
- to our parent window. One is the parent window's widget, which is passed
- to our own widget. The other is a weak reference we keep here to our
- parent WebShellWindow. The former is useful to the widget, and we can't
- trust its treatment of the parent reference because they're platform-
- specific. The latter is useful to this class.
- A better implementation would be one in which the parent keeps strong
- references to its children and closes them before it allows itself
- to be closed. This would mimic the behaviour of OSes that support
- top-level child windows in OSes that do not. Later.
- */
- nsCOMPtr<nsIBaseWindow> parentAsWin(do_QueryInterface(aParent));
- if (parentAsWin) {
- parentAsWin->GetMainWidget(getter_AddRefs(parentWidget));
- mParentWindow = do_GetWeakReference(aParent);
- }
- mWindow->SetWidgetListener(&mWidgetListenerDelegate);
- rv = mWindow->Create((nsIWidget *)parentWidget, // Parent nsIWidget
- nullptr, // Native parent widget
- deskRect, // Widget dimensions
- &widgetInitData); // Widget initialization data
- NS_ENSURE_SUCCESS(rv, rv);
- LayoutDeviceIntRect r = mWindow->GetClientBounds();
- // Match the default background color of content. Important on windows
- // since we no longer use content child widgets.
- mWindow->SetBackgroundColor(NS_RGB(255,255,255));
- // Create web shell
- mDocShell = do_CreateInstance("@mozilla.org/docshell;1");
- NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
- mDocShell->SetOpener(aOpeningTab);
- // Make sure to set the item type on the docshell _before_ calling
- // Create() so it knows what type it is.
- nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryInterface(mDocShell));
- NS_ENSURE_TRUE(docShellAsItem, NS_ERROR_FAILURE);
- NS_ENSURE_SUCCESS(EnsureChromeTreeOwner(), NS_ERROR_FAILURE);
- docShellAsItem->SetTreeOwner(mChromeTreeOwner);
- docShellAsItem->SetItemType(nsIDocShellTreeItem::typeChrome);
- r.x = r.y = 0;
- nsCOMPtr<nsIBaseWindow> docShellAsWin(do_QueryInterface(mDocShell));
- NS_ENSURE_SUCCESS(docShellAsWin->InitWindow(nullptr, mWindow,
- r.x, r.y, r.width, r.height), NS_ERROR_FAILURE);
- NS_ENSURE_SUCCESS(docShellAsWin->Create(), NS_ERROR_FAILURE);
- // Attach a WebProgress listener.during initialization...
- nsCOMPtr<nsIWebProgress> webProgress(do_GetInterface(mDocShell, &rv));
- if (webProgress) {
- webProgress->AddProgressListener(this, nsIWebProgress::NOTIFY_STATE_NETWORK);
- }
- if (aOpenerWindow) {
- nsPIDOMWindowOuter* window = mDocShell->GetWindow();
- MOZ_ASSERT(window);
- window->SetOpenerWindow(nsPIDOMWindowOuter::From(aOpenerWindow), true);
- }
- // Eagerly create an about:blank content viewer with the right principal here,
- // rather than letting it happening in the upcoming call to
- // SetInitialPrincipalToSubject. This avoids creating the about:blank document
- // and then blowing it away with a second one, which can cause problems for the
- // top-level chrome window case. See bug 789773.
- // Note that we don't accept expanded principals here, similar to
- // SetInitialPrincipalToSubject.
- if (nsContentUtils::IsInitialized()) { // Sometimes this happens really early See bug 793370.
- MOZ_ASSERT(mDocShell->ItemType() == nsIDocShellTreeItem::typeChrome);
- nsCOMPtr<nsIPrincipal> principal = nsContentUtils::SubjectPrincipalOrSystemIfNativeCaller();
- if (nsContentUtils::IsExpandedPrincipal(principal)) {
- principal = nullptr;
- }
- rv = mDocShell->CreateAboutBlankContentViewer(principal);
- NS_ENSURE_SUCCESS(rv, rv);
- nsCOMPtr<nsIDocument> doc = mDocShell->GetDocument();
- NS_ENSURE_TRUE(!!doc, NS_ERROR_FAILURE);
- doc->SetIsInitialDocument(true);
- }
- if (nullptr != aUrl) {
- nsCString tmpStr;
- rv = aUrl->GetSpec(tmpStr);
- if (NS_FAILED(rv)) return rv;
- NS_ConvertUTF8toUTF16 urlString(tmpStr);
- nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(mDocShell));
- NS_ENSURE_TRUE(webNav, NS_ERROR_FAILURE);
- rv = webNav->LoadURI(urlString.get(),
- nsIWebNavigation::LOAD_FLAGS_NONE,
- nullptr,
- nullptr,
- nullptr);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- return rv;
- }
- nsIPresShell*
- nsWebShellWindow::GetPresShell()
- {
- if (!mDocShell)
- return nullptr;
- return mDocShell->GetPresShell();
- }
- bool
- nsWebShellWindow::WindowMoved(nsIWidget* aWidget, int32_t x, int32_t y)
- {
- nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
- if (pm) {
- nsCOMPtr<nsPIDOMWindowOuter> window =
- mDocShell ? mDocShell->GetWindow() : nullptr;
- pm->AdjustPopupsOnWindowChange(window);
- }
- // Notify all tabs that the widget moved.
- if (mDocShell && mDocShell->GetWindow()) {
- nsCOMPtr<EventTarget> eventTarget = mDocShell->GetWindow()->GetTopWindowRoot();
- nsContentUtils::DispatchChromeEvent(mDocShell->GetDocument(),
- eventTarget,
- NS_LITERAL_STRING("MozUpdateWindowPos"),
- false, false, nullptr);
- }
- // Persist position, but not immediately, in case this OS is firing
- // repeated move events as the user drags the window
- SetPersistenceTimer(PAD_POSITION);
- return false;
- }
- bool
- nsWebShellWindow::WindowResized(nsIWidget* aWidget, int32_t aWidth, int32_t aHeight)
- {
- nsCOMPtr<nsIBaseWindow> shellAsWin(do_QueryInterface(mDocShell));
- if (shellAsWin) {
- shellAsWin->SetPositionAndSize(0, 0, aWidth, aHeight, 0);
- }
- // Persist size, but not immediately, in case this OS is firing
- // repeated size events as the user drags the sizing handle
- if (!IsLocked())
- SetPersistenceTimer(PAD_POSITION | PAD_SIZE | PAD_MISC);
- return true;
- }
- bool
- nsWebShellWindow::RequestWindowClose(nsIWidget* aWidget)
- {
- // Maintain a reference to this as it is about to get destroyed.
- nsCOMPtr<nsIXULWindow> xulWindow(this);
- nsCOMPtr<nsPIDOMWindowOuter> window(mDocShell ? mDocShell->GetWindow() : nullptr);
- nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(window);
- nsCOMPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
- if (!presShell) {
- mozilla::DebugOnly<bool> dying;
- MOZ_ASSERT(NS_SUCCEEDED(mDocShell->IsBeingDestroyed(&dying)) && dying,
- "No presShell, but window is not being destroyed");
- } else if (eventTarget) {
- RefPtr<nsPresContext> presContext = presShell->GetPresContext();
- nsEventStatus status = nsEventStatus_eIgnore;
- WidgetMouseEvent event(true, eClose, nullptr,
- WidgetMouseEvent::eReal);
- if (NS_SUCCEEDED(eventTarget->DispatchDOMEvent(&event, nullptr, presContext, &status)) &&
- status == nsEventStatus_eConsumeNoDefault)
- return false;
- }
- Destroy();
- return false;
- }
- void
- nsWebShellWindow::SizeModeChanged(nsSizeMode sizeMode)
- {
- // An alwaysRaised (or higher) window will hide any newly opened normal
- // browser windows, so here we just drop a raised window to the normal
- // zlevel if it's maximized. We make no provision for automatically
- // re-raising it when restored.
- if (sizeMode == nsSizeMode_Maximized || sizeMode == nsSizeMode_Fullscreen) {
- uint32_t zLevel;
- GetZLevel(&zLevel);
- if (zLevel > nsIXULWindow::normalZ)
- SetZLevel(nsIXULWindow::normalZ);
- }
- mWindow->SetSizeMode(sizeMode);
- // Persist mode, but not immediately, because in many (all?)
- // cases this will merge with the similar call in NS_SIZE and
- // write the attribute values only once.
- SetPersistenceTimer(PAD_MISC);
- nsCOMPtr<nsPIDOMWindowOuter> ourWindow =
- mDocShell ? mDocShell->GetWindow() : nullptr;
- if (ourWindow) {
- MOZ_ASSERT(ourWindow->IsOuterWindow());
- // Ensure that the fullscreen state is synchronized between
- // the widget and the outer window object.
- if (sizeMode == nsSizeMode_Fullscreen) {
- ourWindow->SetFullScreen(true);
- }
- else if (sizeMode != nsSizeMode_Minimized) {
- if (ourWindow->GetFullScreen()) {
- // The first SetFullscreenInternal call below ensures that we do
- // not trigger any fullscreen transition even if the window was
- // put in fullscreen only for the Fullscreen API. The second
- // SetFullScreen call ensures that the window really exit from
- // fullscreen even if it entered fullscreen for both Fullscreen
- // Mode and Fullscreen API.
- ourWindow->SetFullscreenInternal(FullscreenReason::ForForceExitFullscreen, false);
- ourWindow->SetFullScreen(false);
- }
- }
- // And always fire a user-defined sizemodechange event on the window
- ourWindow->DispatchCustomEvent(NS_LITERAL_STRING("sizemodechange"));
- }
- nsIPresShell* presShell;
- if ((presShell = GetPresShell())) {
- presShell->GetPresContext()->SizeModeChanged(sizeMode);
- }
- // Note the current implementation of SetSizeMode just stores
- // the new state; it doesn't actually resize. So here we store
- // the state and pass the event on to the OS. The day is coming
- // when we'll handle the event here, and the return result will
- // then need to be different.
- }
- void
- nsWebShellWindow::UIResolutionChanged()
- {
- nsCOMPtr<nsPIDOMWindowOuter> ourWindow =
- mDocShell ? mDocShell->GetWindow() : nullptr;
- if (ourWindow) {
- MOZ_ASSERT(ourWindow->IsOuterWindow());
- ourWindow->DispatchCustomEvent(NS_LITERAL_STRING("resolutionchange"));
- }
- }
- void
- nsWebShellWindow::FullscreenChanged(bool aInFullscreen)
- {
- if (mDocShell) {
- if (nsCOMPtr<nsPIDOMWindowOuter> ourWindow = mDocShell->GetWindow()) {
- ourWindow->FinishFullscreenChange(aInFullscreen);
- }
- }
- }
- void
- nsWebShellWindow::OSToolbarButtonPressed()
- {
- // Keep a reference as setting the chrome flags can fire events.
- nsCOMPtr<nsIXULWindow> xulWindow(this);
- // rjc: don't use "nsIWebBrowserChrome::CHROME_EXTRA"
- // due to components with multiple sidebar components
- // (such as Mail/News, Addressbook, etc)... and frankly,
- // Mac IE, OmniWeb, and other Mac OS X apps all work this way
- uint32_t chromeMask = (nsIWebBrowserChrome::CHROME_TOOLBAR |
- nsIWebBrowserChrome::CHROME_LOCATIONBAR |
- nsIWebBrowserChrome::CHROME_PERSONAL_TOOLBAR);
- nsCOMPtr<nsIWebBrowserChrome> wbc(do_GetInterface(xulWindow));
- if (!wbc)
- return;
- uint32_t chromeFlags, newChromeFlags = 0;
- wbc->GetChromeFlags(&chromeFlags);
- newChromeFlags = chromeFlags & chromeMask;
- if (!newChromeFlags) chromeFlags |= chromeMask;
- else chromeFlags &= (~newChromeFlags);
- wbc->SetChromeFlags(chromeFlags);
- }
- bool
- nsWebShellWindow::ZLevelChanged(bool aImmediate, nsWindowZ *aPlacement,
- nsIWidget* aRequestBelow, nsIWidget** aActualBelow)
- {
- if (aActualBelow)
- *aActualBelow = nullptr;
- return ConstrainToZLevel(aImmediate, aPlacement, aRequestBelow, aActualBelow);
- }
- void
- nsWebShellWindow::WindowActivated()
- {
- nsCOMPtr<nsIXULWindow> xulWindow(this);
- // focusing the window could cause it to close, so keep a reference to it
- nsCOMPtr<nsPIDOMWindowOuter> window = mDocShell ? mDocShell->GetWindow() : nullptr;
- nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID);
- if (fm && window)
- fm->WindowRaised(window);
- if (mChromeLoaded) {
- PersistentAttributesDirty(PAD_POSITION | PAD_SIZE | PAD_MISC);
- SavePersistentAttributes();
- }
- }
- void
- nsWebShellWindow::WindowDeactivated()
- {
- nsCOMPtr<nsIXULWindow> xulWindow(this);
- nsCOMPtr<nsPIDOMWindowOuter> window =
- mDocShell ? mDocShell->GetWindow() : nullptr;
- nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID);
- if (fm && window)
- fm->WindowLowered(window);
- }
- #ifdef USE_NATIVE_MENUS
- static void LoadNativeMenus(nsIDOMDocument *aDOMDoc, nsIWidget *aParentWindow)
- {
- nsCOMPtr<nsINativeMenuService> nms = do_GetService("@mozilla.org/widget/nativemenuservice;1");
- if (!nms) {
- return;
- }
- // Find the menubar tag (if there is more than one, we ignore all but
- // the first).
- nsCOMPtr<nsIDOMNodeList> menubarElements;
- aDOMDoc->GetElementsByTagNameNS(NS_LITERAL_STRING("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"),
- NS_LITERAL_STRING("menubar"),
- getter_AddRefs(menubarElements));
- nsCOMPtr<nsIDOMNode> menubarNode;
- if (menubarElements)
- menubarElements->Item(0, getter_AddRefs(menubarNode));
- if (menubarNode) {
- nsCOMPtr<nsIContent> menubarContent(do_QueryInterface(menubarNode));
- nms->CreateNativeMenuBar(aParentWindow, menubarContent);
- } else {
- nms->CreateNativeMenuBar(aParentWindow, nullptr);
- }
- }
- #endif
- namespace mozilla {
- class WebShellWindowTimerCallback final : public nsITimerCallback
- {
- public:
- explicit WebShellWindowTimerCallback(nsWebShellWindow* aWindow)
- : mWindow(aWindow)
- {}
- NS_DECL_THREADSAFE_ISUPPORTS
- NS_IMETHOD Notify(nsITimer* aTimer) override
- {
- // Although this object participates in a refcount cycle (this -> mWindow
- // -> mSPTimer -> this), mSPTimer is a one-shot timer and releases this
- // after it fires. So we don't need to release mWindow here.
- mWindow->FirePersistenceTimer();
- return NS_OK;
- }
- private:
- ~WebShellWindowTimerCallback() {}
- RefPtr<nsWebShellWindow> mWindow;
- };
- NS_IMPL_ISUPPORTS(WebShellWindowTimerCallback, nsITimerCallback)
- } // namespace mozilla
- void
- nsWebShellWindow::SetPersistenceTimer(uint32_t aDirtyFlags)
- {
- MutexAutoLock lock(mSPTimerLock);
- if (!mSPTimer) {
- mSPTimer = do_CreateInstance("@mozilla.org/timer;1");
- if (!mSPTimer) {
- NS_WARNING("Couldn't create @mozilla.org/timer;1 instance?");
- return;
- }
- }
- RefPtr<WebShellWindowTimerCallback> callback =
- new WebShellWindowTimerCallback(this);
- mSPTimer->InitWithCallback(callback, SIZE_PERSISTENCE_TIMEOUT,
- nsITimer::TYPE_ONE_SHOT);
- PersistentAttributesDirty(aDirtyFlags);
- }
- void
- nsWebShellWindow::FirePersistenceTimer()
- {
- MutexAutoLock lock(mSPTimerLock);
- SavePersistentAttributes();
- }
- //----------------------------------------
- // nsIWebProgessListener implementation
- //----------------------------------------
- NS_IMETHODIMP
- nsWebShellWindow::OnProgressChange(nsIWebProgress *aProgress,
- nsIRequest *aRequest,
- int32_t aCurSelfProgress,
- int32_t aMaxSelfProgress,
- int32_t aCurTotalProgress,
- int32_t aMaxTotalProgress)
- {
- NS_NOTREACHED("notification excluded in AddProgressListener(...)");
- return NS_OK;
- }
- NS_IMETHODIMP
- nsWebShellWindow::OnStateChange(nsIWebProgress *aProgress,
- nsIRequest *aRequest,
- uint32_t aStateFlags,
- nsresult aStatus)
- {
- // If the notification is not about a document finishing, then just
- // ignore it...
- if (!(aStateFlags & nsIWebProgressListener::STATE_STOP) ||
- !(aStateFlags & nsIWebProgressListener::STATE_IS_NETWORK)) {
- return NS_OK;
- }
- if (mChromeLoaded)
- return NS_OK;
- // If this document notification is for a frame then ignore it...
- nsCOMPtr<mozIDOMWindowProxy> eventWin;
- aProgress->GetDOMWindow(getter_AddRefs(eventWin));
- auto* eventPWin = nsPIDOMWindowOuter::From(eventWin);
- if (eventPWin) {
- nsPIDOMWindowOuter *rootPWin = eventPWin->GetPrivateRoot();
- if (eventPWin != rootPWin)
- return NS_OK;
- }
- mChromeLoaded = true;
- mLockedUntilChromeLoad = false;
- #ifdef USE_NATIVE_MENUS
- ///////////////////////////////
- // Find the Menubar DOM and Load the menus, hooking them up to the loaded commands
- ///////////////////////////////
- nsCOMPtr<nsIContentViewer> cv;
- mDocShell->GetContentViewer(getter_AddRefs(cv));
- if (cv) {
- nsCOMPtr<nsIDOMDocument> menubarDOMDoc(do_QueryInterface(cv->GetDocument()));
- if (menubarDOMDoc)
- LoadNativeMenus(menubarDOMDoc, mWindow);
- }
- #endif // USE_NATIVE_MENUS
- OnChromeLoaded();
- LoadContentAreas();
- return NS_OK;
- }
- NS_IMETHODIMP
- nsWebShellWindow::OnLocationChange(nsIWebProgress *aProgress,
- nsIRequest *aRequest,
- nsIURI *aURI,
- uint32_t aFlags)
- {
- NS_NOTREACHED("notification excluded in AddProgressListener(...)");
- return NS_OK;
- }
- NS_IMETHODIMP
- nsWebShellWindow::OnStatusChange(nsIWebProgress* aWebProgress,
- nsIRequest* aRequest,
- nsresult aStatus,
- const char16_t* aMessage)
- {
- NS_NOTREACHED("notification excluded in AddProgressListener(...)");
- return NS_OK;
- }
- NS_IMETHODIMP
- nsWebShellWindow::OnSecurityChange(nsIWebProgress *aWebProgress,
- nsIRequest *aRequest,
- uint32_t state)
- {
- NS_NOTREACHED("notification excluded in AddProgressListener(...)");
- return NS_OK;
- }
- //----------------------------------------
- // if the main document URL specified URLs for any content areas, start them loading
- void nsWebShellWindow::LoadContentAreas() {
- nsAutoString searchSpec;
- // fetch the chrome document URL
- nsCOMPtr<nsIContentViewer> contentViewer;
- // yes, it's possible for the docshell to be null even this early
- // see bug 57514.
- if (mDocShell)
- mDocShell->GetContentViewer(getter_AddRefs(contentViewer));
- if (contentViewer) {
- nsIDocument* doc = contentViewer->GetDocument();
- if (doc) {
- nsIURI* mainURL = doc->GetDocumentURI();
- nsCOMPtr<nsIURL> url = do_QueryInterface(mainURL);
- if (url) {
- nsAutoCString search;
- url->GetQuery(search);
- AppendUTF8toUTF16(search, searchSpec);
- }
- }
- }
- // content URLs are specified in the search part of the URL
- // as <contentareaID>=<escapedURL>[;(repeat)]
- if (!searchSpec.IsEmpty()) {
- int32_t begPos,
- eqPos,
- endPos;
- nsString contentAreaID,
- contentURL;
- char *urlChar;
- nsresult rv;
- for (endPos = 0; endPos < (int32_t)searchSpec.Length(); ) {
- // extract contentAreaID and URL substrings
- begPos = endPos;
- eqPos = searchSpec.FindChar('=', begPos);
- if (eqPos < 0)
- break;
- endPos = searchSpec.FindChar(';', eqPos);
- if (endPos < 0)
- endPos = searchSpec.Length();
- searchSpec.Mid(contentAreaID, begPos, eqPos-begPos);
- searchSpec.Mid(contentURL, eqPos+1, endPos-eqPos-1);
- endPos++;
- // see if we have a docshell with a matching contentAreaID
- nsCOMPtr<nsIDocShellTreeItem> content;
- rv = GetContentShellById(contentAreaID.get(), getter_AddRefs(content));
- if (NS_SUCCEEDED(rv) && content) {
- nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(content));
- if (webNav) {
- urlChar = ToNewCString(contentURL);
- if (urlChar) {
- nsUnescape(urlChar);
- contentURL.AssignWithConversion(urlChar);
- webNav->LoadURI(contentURL.get(),
- nsIWebNavigation::LOAD_FLAGS_NONE,
- nullptr,
- nullptr,
- nullptr);
- free(urlChar);
- }
- }
- }
- }
- }
- }
- /**
- * ExecuteCloseHandler - Run the close handler, if any.
- * @return true iff we found a close handler to run.
- */
- bool nsWebShellWindow::ExecuteCloseHandler()
- {
- /* If the event handler closes this window -- a likely scenario --
- things get deleted out of order without this death grip.
- (The problem may be the death grip in nsWindow::windowProc,
- which forces this window's widget to remain alive longer
- than it otherwise would.) */
- nsCOMPtr<nsIXULWindow> kungFuDeathGrip(this);
- nsCOMPtr<EventTarget> eventTarget;
- if (mDocShell) {
- eventTarget = do_QueryInterface(mDocShell->GetWindow());
- }
- if (eventTarget) {
- nsCOMPtr<nsIContentViewer> contentViewer;
- mDocShell->GetContentViewer(getter_AddRefs(contentViewer));
- if (contentViewer) {
- RefPtr<nsPresContext> presContext;
- contentViewer->GetPresContext(getter_AddRefs(presContext));
- nsEventStatus status = nsEventStatus_eIgnore;
- WidgetMouseEvent event(true, eClose, nullptr,
- WidgetMouseEvent::eReal);
- nsresult rv =
- eventTarget->DispatchDOMEvent(&event, nullptr, presContext, &status);
- if (NS_SUCCEEDED(rv) && status == nsEventStatus_eConsumeNoDefault)
- return true;
- // else fall through and return false
- }
- }
- return false;
- } // ExecuteCloseHandler
- void nsWebShellWindow::ConstrainToOpenerScreen(int32_t* aX, int32_t* aY)
- {
- if (mOpenerScreenRect.IsEmpty()) {
- *aX = *aY = 0;
- return;
- }
- int32_t left, top, width, height;
- // Constrain initial positions to the same screen as opener
- nsCOMPtr<nsIScreenManager> screenmgr = do_GetService("@mozilla.org/gfx/screenmanager;1");
- if (screenmgr) {
- nsCOMPtr<nsIScreen> screen;
- screenmgr->ScreenForRect(mOpenerScreenRect.x, mOpenerScreenRect.y,
- mOpenerScreenRect.width, mOpenerScreenRect.height,
- getter_AddRefs(screen));
- if (screen) {
- screen->GetAvailRectDisplayPix(&left, &top, &width, &height);
- if (*aX < left || *aX > left + width) {
- *aX = left;
- }
- if (*aY < top || *aY > top + height) {
- *aY = top;
- }
- }
- }
- }
- // nsIBaseWindow
- NS_IMETHODIMP nsWebShellWindow::Destroy()
- {
- nsresult rv;
- nsCOMPtr<nsIWebProgress> webProgress(do_GetInterface(mDocShell, &rv));
- if (webProgress) {
- webProgress->RemoveProgressListener(this);
- }
- nsCOMPtr<nsIXULWindow> kungFuDeathGrip(this);
- {
- MutexAutoLock lock(mSPTimerLock);
- if (mSPTimer) {
- mSPTimer->Cancel();
- SavePersistentAttributes();
- mSPTimer = nullptr;
- }
- }
- return nsXULWindow::Destroy();
- }
- nsIXULWindow*
- nsWebShellWindow::WidgetListenerDelegate::GetXULWindow()
- {
- return mWebShellWindow->GetXULWindow();
- }
- nsIPresShell*
- nsWebShellWindow::WidgetListenerDelegate::GetPresShell()
- {
- return mWebShellWindow->GetPresShell();
- }
- bool
- nsWebShellWindow::WidgetListenerDelegate::WindowMoved(
- nsIWidget* aWidget, int32_t aX, int32_t aY)
- {
- RefPtr<nsWebShellWindow> holder = mWebShellWindow;
- return holder->WindowMoved(aWidget, aX, aY);
- }
- bool
- nsWebShellWindow::WidgetListenerDelegate::WindowResized(
- nsIWidget* aWidget, int32_t aWidth, int32_t aHeight)
- {
- RefPtr<nsWebShellWindow> holder = mWebShellWindow;
- return holder->WindowResized(aWidget, aWidth, aHeight);
- }
- bool
- nsWebShellWindow::WidgetListenerDelegate::RequestWindowClose(nsIWidget* aWidget)
- {
- RefPtr<nsWebShellWindow> holder = mWebShellWindow;
- return holder->RequestWindowClose(aWidget);
- }
- void
- nsWebShellWindow::WidgetListenerDelegate::SizeModeChanged(nsSizeMode aSizeMode)
- {
- RefPtr<nsWebShellWindow> holder = mWebShellWindow;
- holder->SizeModeChanged(aSizeMode);
- }
- void
- nsWebShellWindow::WidgetListenerDelegate::UIResolutionChanged()
- {
- RefPtr<nsWebShellWindow> holder = mWebShellWindow;
- holder->UIResolutionChanged();
- }
- void
- nsWebShellWindow::WidgetListenerDelegate::FullscreenChanged(bool aInFullscreen)
- {
- RefPtr<nsWebShellWindow> holder = mWebShellWindow;
- holder->FullscreenChanged(aInFullscreen);
- }
- void
- nsWebShellWindow::WidgetListenerDelegate::OSToolbarButtonPressed()
- {
- RefPtr<nsWebShellWindow> holder = mWebShellWindow;
- holder->OSToolbarButtonPressed();
- }
- bool
- nsWebShellWindow::WidgetListenerDelegate::ZLevelChanged(
- bool aImmediate, nsWindowZ *aPlacement, nsIWidget* aRequestBelow,
- nsIWidget** aActualBelow)
- {
- RefPtr<nsWebShellWindow> holder = mWebShellWindow;
- return holder->ZLevelChanged(aImmediate,
- aPlacement,
- aRequestBelow,
- aActualBelow);
- }
- void
- nsWebShellWindow::WidgetListenerDelegate::WindowActivated()
- {
- RefPtr<nsWebShellWindow> holder = mWebShellWindow;
- holder->WindowActivated();
- }
- void
- nsWebShellWindow::WidgetListenerDelegate::WindowDeactivated()
- {
- RefPtr<nsWebShellWindow> holder = mWebShellWindow;
- holder->WindowDeactivated();
- }
|