Files
palemoon27/xpfe/appshell/nsWebShellWindow.cpp
T
roytam1 0af135f24d import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1249212 part 3 - Fix active duration calculation when iteration duration is infinity; r=boris (acc98b1948)
- Bug 1249212 part 4 - Add tests for activeDuration; r=boris (354da323ef)
- Bug 1249212 part 5 - Remove max() clamping from endTime calculation; r=boris (613cd6f5b7)
- Bug 1249212 part 6 - Add tests for endTime calculation; r=boris (583a09f942)
- Bug 1249212 part 7 - Calculate the endTime in GetComputedTimingAt; r=boris (ac73c4a853)
- No bug - Fix whitespace and four test descriptions in keyframe-effect tests; r=whitespace-only DONTBUILD (844a12ba4d)
- Bug 1249212 part 1 - Simplify various keyframe-effect tests; r=boris (58c7f5ef19)
- Bug 1241929 - remove PurgeActiveWorker() from install job when skip waiting is set. r=bkelly (248aadb430)
- Bug 1238954 P1 Purge potentially controlled document entries when evicting service worker registrations. r=ehsan (094bb54de1)
- Bug 1238954 P2 Fix csp service worker tests to register and unregister separate scopes. r=ehsan (71f0237c11)
- Bug 1227015 P2 Move mScriptSpec from registration job into script job base. r=ehsan (754753f0f6)
- Bug 1227015 P3 Require a script spec on install jobs. r=ehsan (ebdbf860b9)
- Bug 1227015 P4 Make register job always require an explicit script spec. r=ehsan (b97ec80a56)
- Bug 1227015 P5 Remove ServiceWorkerRegistrationInfo mScriptSpec. r=ehsan (4410fd9fd0)
- Bug 1227015 P6 Abort updates if the script spec has changed. r=ehsan (01962f2915)
- Bug 1232444 Only store service worker registrations after install is successful. r=baku (f773638ec6)
- Bug 1231974 P1 Remove unneeded ServiceWorkerScriptJobBase abstract class. r=baku (c514e53d82)
- Bug 1231974 P2 Store scope on ServiceWorkerJobBase. r=baku (d723846d45)
- Bug 1231974 P3 Store the principal on the ServiceWorkerJobBase. r=baku (550fa7f1d4)
- Bug 1231974 P4 Lazy load registration and verify it does not change in service worker jobs. r=baku (db44008f8f)
- Bug 1231974 P6 Abort update-triggered install jobs if the service worker script has changed. r=baku (3e7572968f)
- Bug 1237992 - service worker activate should be executed after install onstatechange events are fired. r=bkelly (58de5a2e57)
- No bug - Correct the order of two newly added web-platform tests in manifest. DONTBUILD (e14b162237)
- Bug 1189581 - Make service-workers/service-worker/fetch-cors-xhr.https.html pass; r=bkelly (e1dbe77c87)
- Bug 1243942 - Bypass service workers for WebSocket handshake channels; r=bkelly (845fd17110)
- Bug 1217089 - Remove fetch-request-html-imports.https.html; r=bkelly (528ea318b6)
- Bug 1188545 - Update expected results for some service worker tests. a=testonly (ba29add4a5)
- Bug 1213119 Lengthen timeout in test checking for failure to load iframes and windows. r=ehsan (d25f8f9b01)
- Bug 1189671 - Fix getregistrations test. r=jgraham (2407499bc5)
- Bug 1217367 - Add a wpt test that verified coalesced .update() calls resolve properly. r=bkelly (7e3f4a92e1)
- Bug 1200677 - Import navigation-redirect.https.html for non-e10s. r=jdm (6e6d98a255)
- Bug 1251498: Implement IDBKeyRange.includes(). r=baku (89c839adaf)
- Bug 1248338 - Implement iterationStart; r=birtles (5dcb1341c3)
- Bug 1244635 - Part1 Add enddelay implementation in dom/animation/AnimationEffectTiming.cpp r=bz,hiro (e0a9f3a798)
- Bug 1244635 - Part2 Add enddelay tests in dom/animation/test/chrome r=hiro (98d2f5ada5)
- Bug 1244635 - Part3 Add enddelay tests in testing/web-platform/tests/web-animations r=hiro (bb10a41382)
- Bug 1244635 - Part4 Add enddelay tests in layout/style/test r=hiro (ceda978f3e)
- Bug 1237173 - Part1: Move TimingParam struct to a new file. r=birtles (ad46be831b)
- Bug 1251804 - Use the ImageContainer's size and not the intrinsic size when computing the transform in nsDisplayImage::ConfigureLayer. r=tn (23bd3774ff)
- Bug 1247554 - Budget creation of AGRs by frame area; r=mattwoodrow (c68183c77e)
- Require mix-blend mode support in all compositors and layer managers. (bug 1209278 part 1, r=mstange) (e00752064f)
- Remove lazy scrollinfo hoisting introduced in bug 1193557. (bug 1209278 part 2, r=mstange) (394c117b8d)
- Bug 1152049 - Apply all scroll clips when computing plugin clips in content. r=tn (9c44108dda)
- Bug 1238564 - Anticipate async scrolling when computing the scroll clipped bounds of a display list. r=roc (4c28888eb6)
- Bug 1238564 - Allow constructing nsDisplayWrapList with a given scroll clip. r=roc (dd6d6d1a02)
- Fold nsDisplayBlendContainer constructors. (bug 1209278 part 3, r=mstange) (e28cb8d062)
- Bug 1253052. Only schedule paint when apz aware event listener is added if event regions/apz are enabled. r=kats (4a2dcd2e31)
- Bug 1252929: Next.1. Make layers.max-active preference not need a restart. r=mstange (412d52ff81)
- Bug 1247554 - Mark nsPresContext::GetVisibleArea as const; r=mattwoodrow (8ad99e89a2)
- Bug 1104916 - Implement CSS media query display-mode. r=cam (6bf38de62c)
- Bug 1247098 - Mark nsIPresShell::GetResolution and nsPresContext::IsRootContentDocument as const. r=tnikkel (2514fe01c2)
- Bug 1253078 - Switch MOZ_STYLO environmental variable to MOZ_DISABLE_STYLO. r=dholbert (8c6dfe008e)
- Bug 1232181 - Notify plugins about scroll state. r=roc (1eccaad547)
- Bug 1198663. Tolerate null Image in Android NPAPI plugins. r=snorp (bfceeacbe8)
- Bug 1232181 - Add an image layer for plugin frames that represent windowed plugins on platforms that support scroll capture. r=roc (c064e01b19)
- Bug 1171182 - Browser Zoom Query for NPAPI; r=bsmedberg r=jaas (95c60d2190)
- Bug 1243639 - Remove Honeycomb flash-related code. r=snorp (437bdfa5e8)
- Bug 1177367 - Don't fall through to non-e10s plugin widget creation when e10s creation fails. r=aklotz (7fb106e260)
- Bug 1250634 - Part 0: Fix MacroAssembler support for store16(). r=jandem (99fdf6fd42)
- Bug 1250634 - Part 1: Refactor FreeSpan management to be less indirect and confusing. r=terrence, r=jandem (50f57a129c)
- Bug 1253094, part 5 - Stop using DebugOnly for class/struct members in layout/. r=mats (bcb94cc110)
- Bug 1238564 - Set the innermost possible scroll clip on opacity items during creation. r=mattwoodrow (da5072cb75)
- Bug 1192910 - Ensure we flush paints on the main thread during an APZ flush. r=mstange (ff4631bcd8)
- Bug 1254263 - Add a flag to allow disabling paint-skipping. r=mstange (90375f4f31)
- Bug 1248913 - nsDisplayListBuilder doesn't need to know what blend modes it contains, just whether it contains any. r=mattwoodrow (92c987df65)
- Bug 1248913 - Add a constructor argument to nsDisplayMixBlendMode that lets you specify the blend mode. r=mattwoodrow (66234cc69c)
- Bug 1238564 - When building a fixed/sticky display item, don't restore the clip until we're ready to build that item so that inner items aren't unnecessarily clipped. r=roc (752f531f08)
- Bug 1238564 - Include mIsAsyncScrollable information in DisplayItemScrollClip::ToString. r=roc (b6ac4899eb)
- Bug 1238564 - Don't do another pass over the display list to figure out ancestor scroll clips. r=mattwoodrow (12ad134528)
- Bug 1238564 - Get rid of cross stacking context parent scroll clip. r=mattwoodrow (536faa6ba6)
- Bug 1248913 - Rename nsDisplayMixBlendMode to nsDisplayBlendMode. r=mattwoodrow (34a0704841)
- Bug 1248913 - Let nsDisplayBackgroundImage specify the background blend mode. r=mattwoodrow (cc671af9e3)
- Bug 619500: Part 1. Default sizing for specified size of SVG images which have no constraints; r=dholbert r=seth (b0f7ec56a8)
- Bug 619500: Part 2. When drawing an SVG image as a CSS border-image, use preverveAspectRatio="none"; r=dholbert (1dad64f38c)
- Bug 619500: Part 3. svg-as-borderimage test cases; r=dholbert (896d339cf9)
- Bug 619500: Part 4. Remove one unused data member in SVGDrawingParameters; r=dholbert (f16e9a5927)
- Bug 1230415 - Use DrawTarget instead of gfxContext in PaintBorderWithStyleBorder(). r=roc. (f00cccb284)
- Bug 1248913 - Build nsDisplayBlendMode items for background-blend-mode. r=mattwoodrow (105515a553)
- Bug 1248913 - Remove mCanBeActive and second nsDisplayBlendContainer constructor. r=mattwoodrow (d984db61f5)
- Bug 1248913 - Make nsDisplayBlendContainer active or inactive based on its contents. r=mattwoodrow (f44fa4f479)
- Bug 1248913 - Reftest. (58a1507343)
- Bug 1251833 - Part 1: Move allocation into FreeSpan and move firstFreeSpan to the top of Arenas. r=terrence (3f4d239785)
- Bug 1251833 - Part 2: Clean up the various iterators a bit. r=terrence (300aa5673d)
- Bug 1251527 - Don't override visible regions for background-attachment:fixed. r=mstange (ee2d53334d)
- Backout e00a02282951 (bug 1232229) as we no longer need the diagnostics. (22f0063541)
- Bug 1250718 - Don't flatten opacity to an intermediate surface when used in the middle of preserve-3d. r=thinker (9df994b834)
- Bug 1196114 - Part 1: Add SetPerformanceWarning. r=birtles (165f9cbcfc)
- Bug 1196114 - Part 2: Add AnimationPropertyStatus interface and KeyframeEffectReadOnly.runningStatus(). r=birtles,smaug (4e3d2d55e0)
- Bug 1196114 - Part 3: Set AnimationPerformanceWarning messages. r=birtles (cd3497e128)
- Bug 1196114 - Part 4: Localize messages for animation performance warnings. r=birtles (1b1676b7b6)
- Bug 1196114 - Part 5: Store performce warning information as enum type. r=birtles (d2ec6643d3)
- Bug 1221378: Properly root object passed to the allocation metadata callback. r=fitzgen (37831b769c)
- Bug 1225005 - Clamp negative values in containing block size. r=roc (8e525d5265)
- Bug 1192245 - Fix tests that fail with incremental zeal r=terrence (6ca6f63135)
- Bug 1249367 - Make background finalization a GC phase (and clean up Zones properly); r=jonco (43d9a1fafe)
- Bug 1119537 - Make decommit a proper GC phase; r=jonco (638492711e)
- Bug 1232229 - Add assertions to prevent nursery allocation when setting up OMT parse tasks r=terrence (e12cd405c2)
- Backed out changeset 2a613f5a5866 (bug 1119537) for hazard failures (623123a764)
- Bug 1249896 - Part 6: Add gc namespace for Arena::thingsSpan. r=terrence (ba1e1d41b0)
- Bug 1251833 - Part 3: Merge ArenaHeader into Arena. r=terrence (e8bd53b44e)
- Bug 1232181 - Plugin module plumbing for retrieving scroll captures and updating plugin instance content scroll state. r=roc (2309d423cc)
- Bug 1232181 - Add a few win resource helpers. r=aklotz (1421a9695a)
- Bug 1232181 - Add support for capturing plugin windows on Windows. r=aklotz (4ccbfeb19e)
2024-02-06 10:15:07 +08:00

778 lines
24 KiB
C++

/* -*- 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"
#ifdef XP_MACOSX
#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")
{
}
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,
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(this);
mWindow->Create((nsIWidget *)parentWidget, // Parent nsIWidget
nullptr, // Native parent widget
deskRect, // Widget dimensions
&widgetInitData); // Widget initialization data
LayoutDeviceIntRect r;
mWindow->GetClientBounds(r);
// 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);
}
// 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.
if (nsContentUtils::IsInitialized()) { // Sometimes this happens really early See bug 793370.
rv = mDocShell->CreateAboutBlankContentViewer(nsContentUtils::SubjectPrincipalOrSystemIfNativeCaller());
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDocument> doc = mDocShell ? mDocShell->GetDocument() : nullptr;
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<nsPIDOMWindow> 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, false);
}
// 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<nsPIDOMWindow> 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, eWindowClose, 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<nsPIDOMWindow> ourWindow =
mDocShell ? mDocShell->GetWindow() : nullptr;
if (ourWindow) {
MOZ_ASSERT(ourWindow->IsOuterWindow());
// Let the application know if it's in fullscreen mode so it
// can update its UI.
if (sizeMode == nsSizeMode_Fullscreen) {
ourWindow->SetFullScreen(true);
}
else if (sizeMode != nsSizeMode_Minimized) {
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::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<nsIDOMWindow> 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<nsPIDOMWindow> 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<nsIDOMWindow> eventWin;
aProgress->GetDOMWindow(getter_AddRefs(eventWin));
nsCOMPtr<nsPIDOMWindow> eventPWin(do_QueryInterface(eventWin));
if (eventPWin) {
nsPIDOMWindow *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, eWindowClose, 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();
}