Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/mozilla/RefPtr.h
Warning:line 314, column 5
Undefined or garbage value returned to caller

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name nsGlobalWindowOuter.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dom/base -fcoverage-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dom/base -resource-dir /usr/lib/llvm-18/lib/clang/18 -include /var/lib/jenkins/workspace/firefox-scan-build/config/gcc_hidden.h -include /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D STATIC_EXPORTABLE_JS_API -I /var/lib/jenkins/workspace/firefox-scan-build/dom/base -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dom/base -I /var/lib/jenkins/workspace/firefox-scan-build/dom/battery -I /var/lib/jenkins/workspace/firefox-scan-build/dom/events -I /var/lib/jenkins/workspace/firefox-scan-build/dom/media -I /var/lib/jenkins/workspace/firefox-scan-build/dom/network -I /var/lib/jenkins/workspace/firefox-scan-build/caps -I /var/lib/jenkins/workspace/firefox-scan-build/docshell/base -I /var/lib/jenkins/workspace/firefox-scan-build/dom/base -I /var/lib/jenkins/workspace/firefox-scan-build/dom/file -I /var/lib/jenkins/workspace/firefox-scan-build/dom/geolocation -I /var/lib/jenkins/workspace/firefox-scan-build/dom/html -I /var/lib/jenkins/workspace/firefox-scan-build/dom/ipc -I /var/lib/jenkins/workspace/firefox-scan-build/dom/storage -I /var/lib/jenkins/workspace/firefox-scan-build/dom/svg -I /var/lib/jenkins/workspace/firefox-scan-build/dom/xml -I /var/lib/jenkins/workspace/firefox-scan-build/dom/xslt/xpath -I /var/lib/jenkins/workspace/firefox-scan-build/dom/xul -I /var/lib/jenkins/workspace/firefox-scan-build/extensions/spellcheck/src -I /var/lib/jenkins/workspace/firefox-scan-build/gfx/2d -I /var/lib/jenkins/workspace/firefox-scan-build/image -I /var/lib/jenkins/workspace/firefox-scan-build/js/xpconnect/loader -I /var/lib/jenkins/workspace/firefox-scan-build/js/xpconnect/src -I /var/lib/jenkins/workspace/firefox-scan-build/js/xpconnect/wrappers -I /var/lib/jenkins/workspace/firefox-scan-build/layout/base -I /var/lib/jenkins/workspace/firefox-scan-build/layout/forms -I /var/lib/jenkins/workspace/firefox-scan-build/layout/generic -I /var/lib/jenkins/workspace/firefox-scan-build/layout/style -I /var/lib/jenkins/workspace/firefox-scan-build/layout/xul -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/base -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/url-classifier -I /var/lib/jenkins/workspace/firefox-scan-build/parser/htmlparser -I /var/lib/jenkins/workspace/firefox-scan-build/security/manager/ssl -I /var/lib/jenkins/workspace/firefox-scan-build/third_party/xsimd/include -I /var/lib/jenkins/workspace/firefox-scan-build/widget -I /var/lib/jenkins/workspace/firefox-scan-build/xpcom/ds -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/sctp/datachannel -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /var/lib/jenkins/workspace/firefox-scan-build/ipc/chromium/src -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/gtk-3.0/unix-print -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13 -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/x86_64-linux-gnu/c++/13 -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/backward -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-deprecated-this-capture -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -fdeprecated-macro -ferror-limit 19 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fno-aligned-allocation -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-05-16-034744-15991-1 -x c++ /var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp

/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp

1/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3/* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7#include "mozilla/Assertions.h"
8#include "mozilla/ScopeExit.h"
9#include "nsGlobalWindowOuter.h"
10#include "nsGlobalWindowInner.h"
11
12#include <algorithm>
13
14#include "mozilla/MemoryReporting.h"
15
16// Local Includes
17#include "Navigator.h"
18#include "nsContentSecurityManager.h"
19#include "nsGlobalWindowOuter.h"
20#include "nsScreen.h"
21#include "nsHistory.h"
22#include "nsDOMNavigationTiming.h"
23#include "nsIDOMStorageManager.h"
24#include "nsISecureBrowserUI.h"
25#include "nsIWebProgressListener.h"
26#include "mozilla/AntiTrackingUtils.h"
27#include "mozilla/dom/AutoPrintEventDispatcher.h"
28#include "mozilla/dom/BindingUtils.h"
29#include "mozilla/dom/BrowserChild.h"
30#include "mozilla/dom/BrowsingContextBinding.h"
31#include "mozilla/dom/CanonicalBrowsingContext.h"
32#include "mozilla/dom/ContentChild.h"
33#include "mozilla/dom/ContentFrameMessageManager.h"
34#include "mozilla/dom/DocumentInlines.h"
35#include "mozilla/dom/EventTarget.h"
36#include "mozilla/dom/HTMLIFrameElement.h"
37#include "mozilla/dom/LocalStorage.h"
38#include "mozilla/dom/LSObject.h"
39#include "mozilla/dom/Storage.h"
40#include "mozilla/dom/MaybeCrossOriginObject.h"
41#include "mozilla/dom/Performance.h"
42#include "mozilla/dom/ProxyHandlerUtils.h"
43#include "mozilla/dom/StorageEvent.h"
44#include "mozilla/dom/StorageEventBinding.h"
45#include "mozilla/dom/StorageNotifierService.h"
46#include "mozilla/dom/StorageUtils.h"
47#include "mozilla/dom/Timeout.h"
48#include "mozilla/dom/TimeoutHandler.h"
49#include "mozilla/dom/TimeoutManager.h"
50#include "mozilla/dom/UserActivation.h"
51#include "mozilla/dom/WindowContext.h"
52#include "mozilla/dom/WindowFeatures.h" // WindowFeatures
53#include "mozilla/dom/WindowProxyHolder.h"
54#include "mozilla/IntegerPrintfMacros.h"
55#include "mozilla/StorageAccessAPIHelper.h"
56#include "nsBaseCommandController.h"
57#include "nsError.h"
58#include "nsICookieService.h"
59#include "nsISizeOfEventTarget.h"
60#include "nsDOMJSUtils.h"
61#include "nsArrayUtils.h"
62#include "nsIDocShellTreeOwner.h"
63#include "nsIInterfaceRequestorUtils.h"
64#include "nsIPermissionManager.h"
65#include "nsIScriptContext.h"
66#include "nsWindowMemoryReporter.h"
67#include "nsWindowSizes.h"
68#include "WindowNamedPropertiesHandler.h"
69#include "nsFrameSelection.h"
70#include "nsNetUtil.h"
71#include "nsVariant.h"
72#include "nsPrintfCString.h"
73#include "mozilla/intl/LocaleService.h"
74#include "WindowDestroyedEvent.h"
75#include "nsDocShellLoadState.h"
76#include "mozilla/dom/WindowGlobalChild.h"
77
78// Helper Classes
79#include "nsJSUtils.h"
80#include "jsapi.h"
81#include "jsfriendapi.h"
82#include "js/CallAndConstruct.h" // JS::Call
83#include "js/friend/StackLimits.h" // js::AutoCheckRecursionLimit
84#include "js/friend/WindowProxy.h" // js::IsWindowProxy, js::SetWindowProxy
85#include "js/PropertyAndElement.h" // JS_DefineObject, JS_GetProperty
86#include "js/PropertySpec.h"
87#include "js/RealmIterators.h"
88#include "js/Wrapper.h"
89#include "nsLayoutUtils.h"
90#include "nsReadableUtils.h"
91#include "nsJSEnvironment.h"
92#include "mozilla/dom/ScriptSettings.h"
93#include "mozilla/Preferences.h"
94#include "mozilla/Likely.h"
95#include "mozilla/SchedulerGroup.h"
96#include "mozilla/SpinEventLoopUntil.h"
97#include "mozilla/Sprintf.h"
98#include "mozilla/Unused.h"
99
100// Other Classes
101#include "mozilla/dom/BarProps.h"
102#include "nsLayoutStatics.h"
103#include "nsCCUncollectableMarker.h"
104#include "mozilla/dom/WorkerCommon.h"
105#include "mozilla/dom/ToJSValue.h"
106#include "nsJSPrincipals.h"
107#include "mozilla/Attributes.h"
108#include "mozilla/Components.h"
109#include "mozilla/Debug.h"
110#include "mozilla/EventListenerManager.h"
111#include "mozilla/MouseEvents.h"
112#include "mozilla/PresShell.h"
113#include "mozilla/ProcessHangMonitor.h"
114#include "mozilla/StaticPrefs_dom.h"
115#include "mozilla/StaticPrefs_full_screen_api.h"
116#include "mozilla/StaticPrefs_print.h"
117#include "mozilla/StaticPrefs_fission.h"
118#include "mozilla/ThrottledEventQueue.h"
119#include "AudioChannelService.h"
120#include "nsAboutProtocolUtils.h"
121#include "nsCharTraits.h" // NS_IS_HIGH/LOW_SURROGATE
122#include "PostMessageEvent.h"
123#include "mozilla/dom/DocGroup.h"
124#include "mozilla/net/CookieJarSettings.h"
125
126// Interfaces Needed
127#include "nsIFrame.h"
128#include "nsCanvasFrame.h"
129#include "nsIWidget.h"
130#include "nsIWidgetListener.h"
131#include "nsIBaseWindow.h"
132#include "nsIDeviceSensors.h"
133#include "nsIContent.h"
134#include "nsIDocShell.h"
135#include "mozilla/dom/Document.h"
136#include "Crypto.h"
137#include "nsDOMString.h"
138#include "nsThreadUtils.h"
139#include "nsILoadContext.h"
140#include "nsIScrollableFrame.h"
141#include "nsView.h"
142#include "nsViewManager.h"
143#include "nsIPrompt.h"
144#include "nsIPromptService.h"
145#include "nsIPromptFactory.h"
146#include "nsIWritablePropertyBag2.h"
147#include "nsIWebNavigation.h"
148#include "nsIWebBrowserChrome.h"
149#include "nsIWebBrowserFind.h" // For window.find()
150#include "nsComputedDOMStyle.h"
151#include "nsDOMCID.h"
152#include "nsDOMWindowUtils.h"
153#include "nsIWindowWatcher.h"
154#include "nsPIWindowWatcher.h"
155#include "nsIDocumentViewer.h"
156#include "nsIScriptError.h"
157#include "nsISHistory.h"
158#include "nsIControllers.h"
159#include "nsGlobalWindowCommands.h"
160#include "nsQueryObject.h"
161#include "nsContentUtils.h"
162#include "nsCSSProps.h"
163#include "nsIURIFixup.h"
164#include "nsIURIMutator.h"
165#include "mozilla/EventDispatcher.h"
166#include "mozilla/EventStateManager.h"
167#include "nsIObserverService.h"
168#include "nsFocusManager.h"
169#include "nsIAppWindow.h"
170#include "nsServiceManagerUtils.h"
171#include "mozilla/dom/CustomEvent.h"
172#include "nsIScreenManager.h"
173#include "nsIClassifiedChannel.h"
174#include "nsIXULRuntime.h"
175#include "xpcprivate.h"
176
177#ifdef NS_PRINTING1
178# include "nsIPrintSettings.h"
179# include "nsIPrintSettingsService.h"
180# include "nsIWebBrowserPrint.h"
181#endif
182
183#include "nsWindowRoot.h"
184#include "nsNetCID.h"
185#include "nsIArray.h"
186
187#include "nsIDOMXULCommandDispatcher.h"
188
189#include "mozilla/GlobalKeyListener.h"
190
191#include "nsIDragService.h"
192#include "mozilla/dom/Element.h"
193#include "mozilla/dom/Selection.h"
194#include "nsFrameLoader.h"
195#include "nsFrameLoaderOwner.h"
196#include "nsXPCOMCID.h"
197#include "mozilla/Logging.h"
198#include "mozilla/ProfilerMarkers.h"
199#include "prenv.h"
200
201#include "mozilla/dom/IDBFactory.h"
202#include "mozilla/dom/MessageChannel.h"
203#include "mozilla/dom/Promise.h"
204
205#include "mozilla/dom/Gamepad.h"
206#include "mozilla/dom/GamepadManager.h"
207
208#include "gfxVR.h"
209#include "VRShMem.h"
210#include "FxRWindowManager.h"
211#include "mozilla/dom/VRDisplay.h"
212#include "mozilla/dom/VRDisplayEvent.h"
213#include "mozilla/dom/VRDisplayEventBinding.h"
214#include "mozilla/dom/VREventObserver.h"
215
216#include "nsRefreshDriver.h"
217
218#include "mozilla/extensions/WebExtensionPolicy.h"
219
220#include "mozilla/BasePrincipal.h"
221#include "mozilla/Services.h"
222#include "mozilla/Telemetry.h"
223#include "mozilla/dom/Location.h"
224#include "nsHTMLDocument.h"
225#include "nsWrapperCacheInlines.h"
226#include "mozilla/DOMEventTargetHelper.h"
227#include "prrng.h"
228#include "nsSandboxFlags.h"
229#include "nsXULControllers.h"
230#include "mozilla/dom/AudioContext.h"
231#include "mozilla/dom/BrowserElementDictionariesBinding.h"
232#include "mozilla/dom/BrowsingContextGroup.h"
233#include "mozilla/dom/cache/CacheStorage.h"
234#include "mozilla/dom/Console.h"
235#include "mozilla/dom/Fetch.h"
236#include "mozilla/dom/FunctionBinding.h"
237#include "mozilla/dom/HashChangeEvent.h"
238#include "mozilla/dom/IntlUtils.h"
239#include "mozilla/dom/PopStateEvent.h"
240#include "mozilla/dom/PopupBlockedEvent.h"
241#include "mozilla/dom/PrimitiveConversions.h"
242#include "mozilla/dom/WindowBinding.h"
243#include "nsIBrowserChild.h"
244#include "mozilla/dom/MediaQueryList.h"
245#include "mozilla/dom/NavigatorBinding.h"
246#include "mozilla/dom/ImageBitmap.h"
247#include "mozilla/dom/ImageBitmapBinding.h"
248#include "mozilla/dom/ServiceWorkerRegistration.h"
249#include "mozilla/dom/WebIDLGlobalNameHash.h"
250#include "mozilla/dom/Worklet.h"
251#include "AccessCheck.h"
252
253#ifdef MOZ_WEBSPEECH1
254# include "mozilla/dom/SpeechSynthesis.h"
255#endif
256
257#ifdef ANDROID
258# include <android/log.h>
259#endif
260
261#ifdef XP_WIN
262# include <process.h>
263# define getpid _getpid
264#else
265# include <unistd.h> // for getpid()
266#endif
267
268using namespace mozilla;
269using namespace mozilla::dom;
270using namespace mozilla::dom::ipc;
271using mozilla::BasePrincipal;
272using mozilla::OriginAttributes;
273using mozilla::TimeStamp;
274using mozilla::layout::RemotePrintJobChild;
275
276static inline nsGlobalWindowInner* GetCurrentInnerWindowInternal(
277 const nsGlobalWindowOuter* aOuter) {
278 return nsGlobalWindowInner::Cast(aOuter->GetCurrentInnerWindow());
279}
280
281#define FORWARD_TO_INNER(method, args, err_rval)do { if (!mInnerWindow) { NS_DebugBreak(NS_DEBUG_WARNING, "No inner window available!"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 281); return err_rval; } return GetCurrentInnerWindowInternal
(this)->method args; } while (0)
\
282 PR_BEGIN_MACROdo { \
283 if (!mInnerWindow) { \
284 NS_WARNING("No inner window available!")NS_DebugBreak(NS_DEBUG_WARNING, "No inner window available!",
nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 284)
; \
285 return err_rval; \
286 } \
287 return GetCurrentInnerWindowInternal(this)->method args; \
288 PR_END_MACRO} while (0)
289
290#define FORWARD_TO_INNER_VOID(method, args)do { if (!mInnerWindow) { NS_DebugBreak(NS_DEBUG_WARNING, "No inner window available!"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 290); return; } GetCurrentInnerWindowInternal(this)->method
args; return; } while (0)
\
291 PR_BEGIN_MACROdo { \
292 if (!mInnerWindow) { \
293 NS_WARNING("No inner window available!")NS_DebugBreak(NS_DEBUG_WARNING, "No inner window available!",
nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 293)
; \
294 return; \
295 } \
296 GetCurrentInnerWindowInternal(this)->method args; \
297 return; \
298 PR_END_MACRO} while (0)
299
300// Same as FORWARD_TO_INNER, but this will create a fresh inner if an
301// inner doesn't already exists.
302#define FORWARD_TO_INNER_CREATE(method, args, err_rval)do { if (!mInnerWindow) { if (mIsClosed) { return err_rval; }
nsCOMPtr<Document> kungFuDeathGrip = GetDoc(); ::mozilla
::Unused << kungFuDeathGrip; if (!mInnerWindow) { return
err_rval; } } return GetCurrentInnerWindowInternal(this)->
method args; } while (0)
\
303 PR_BEGIN_MACROdo { \
304 if (!mInnerWindow) { \
305 if (mIsClosed) { \
306 return err_rval; \
307 } \
308 nsCOMPtr<Document> kungFuDeathGrip = GetDoc(); \
309 ::mozilla::Unused << kungFuDeathGrip; \
310 if (!mInnerWindow) { \
311 return err_rval; \
312 } \
313 } \
314 return GetCurrentInnerWindowInternal(this)->method args; \
315 PR_END_MACRO} while (0)
316
317static LazyLogModule gDOMLeakPRLogOuter("DOMLeakOuter");
318extern LazyLogModule gPageCacheLog;
319
320#ifdef DEBUG1
321static LazyLogModule gDocShellAndDOMWindowLeakLogging(
322 "DocShellAndDOMWindowLeak");
323#endif
324
325nsGlobalWindowOuter::OuterWindowByIdTable*
326 nsGlobalWindowOuter::sOuterWindowsById = nullptr;
327
328/* static */
329nsPIDOMWindowOuter* nsPIDOMWindowOuter::GetFromCurrentInner(
330 nsPIDOMWindowInner* aInner) {
331 if (!aInner) {
332 return nullptr;
333 }
334
335 nsPIDOMWindowOuter* outer = aInner->GetOuterWindow();
336 if (!outer || outer->GetCurrentInnerWindow() != aInner) {
337 return nullptr;
338 }
339
340 return outer;
341}
342
343//*****************************************************************************
344// nsOuterWindowProxy: Outer Window Proxy
345//*****************************************************************************
346
347// Give OuterWindowProxyClass 2 reserved slots, like the other wrappers, so
348// JSObject::swap can swap it with CrossCompartmentWrappers without requiring
349// malloc.
350//
351// We store the nsGlobalWindowOuter* in our first slot.
352//
353// We store our holder weakmap in the second slot.
354const JSClass OuterWindowProxyClass = PROXY_CLASS_DEF({ "Proxy", JSClass::NON_NATIVE | JSCLASS_IS_PROXY | JSCLASS_DELAY_METADATA_BUILDER
| js::CheckProxyFlags<JSCLASS_HAS_RESERVED_SLOTS(2)>()
, &js::ProxyClassOps, JS_NULL_CLASS_SPEC, &js::ProxyClassExtension
, &js::ProxyObjectOps }
355 "Proxy", JSCLASS_HAS_RESERVED_SLOTS(2)){ "Proxy", JSClass::NON_NATIVE | JSCLASS_IS_PROXY | JSCLASS_DELAY_METADATA_BUILDER
| js::CheckProxyFlags<JSCLASS_HAS_RESERVED_SLOTS(2)>()
, &js::ProxyClassOps, JS_NULL_CLASS_SPEC, &js::ProxyClassExtension
, &js::ProxyObjectOps }
; /* additional class flags */
356
357static const size_t OUTER_WINDOW_SLOT = 0;
358static const size_t HOLDER_WEAKMAP_SLOT = 1;
359
360class nsOuterWindowProxy : public MaybeCrossOriginObject<js::Wrapper> {
361 using Base = MaybeCrossOriginObject<js::Wrapper>;
362
363 public:
364 constexpr nsOuterWindowProxy() : Base(0) {}
365
366 bool finalizeInBackground(const JS::Value& priv) const override {
367 return false;
368 }
369
370 // Standard internal methods
371 /**
372 * Implementation of [[GetOwnProperty]] as defined at
373 * https://html.spec.whatwg.org/multipage/window-object.html#windowproxy-getownproperty
374 *
375 * "proxy" is the WindowProxy object involved. It may not be same-compartment
376 * with cx.
377 */
378 bool getOwnPropertyDescriptor(
379 JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
380 JS::MutableHandle<Maybe<JS::PropertyDescriptor>> desc) const override;
381
382 /*
383 * Implementation of the same-origin case of
384 * <https://html.spec.whatwg.org/multipage/window-object.html#windowproxy-getownproperty>.
385 */
386 bool definePropertySameOrigin(JSContext* cx, JS::Handle<JSObject*> proxy,
387 JS::Handle<jsid> id,
388 JS::Handle<JS::PropertyDescriptor> desc,
389 JS::ObjectOpResult& result) const override;
390
391 /**
392 * Implementation of [[OwnPropertyKeys]] as defined at
393 *
394 * https://html.spec.whatwg.org/multipage/window-object.html#windowproxy-ownpropertykeys
395 *
396 * "proxy" is the WindowProxy object involved. It may not be same-compartment
397 * with cx.
398 */
399 bool ownPropertyKeys(JSContext* cx, JS::Handle<JSObject*> proxy,
400 JS::MutableHandleVector<jsid> props) const override;
401 /**
402 * Implementation of [[Delete]] as defined at
403 * https://html.spec.whatwg.org/multipage/window-object.html#windowproxy-delete
404 *
405 * "proxy" is the WindowProxy object involved. It may not be same-compartment
406 * with cx.
407 */
408 bool delete_(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
409 JS::ObjectOpResult& result) const override;
410
411 /**
412 * Implementaton of hook for superclass getPrototype() method.
413 */
414 JSObject* getSameOriginPrototype(JSContext* cx) const override;
415
416 /**
417 * Implementation of [[HasProperty]] internal method as defined at
418 * https://tc39.github.io/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-hasproperty-p
419 *
420 * "proxy" is the WindowProxy object involved. It may not be same-compartment
421 * with cx.
422 *
423 * Note that the HTML spec does not define an override for this internal
424 * method, so we just want the "normal object" behavior. We have to override
425 * it, because js::Wrapper also overrides, with "not normal" behavior.
426 */
427 bool has(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
428 bool* bp) const override;
429
430 /**
431 * Implementation of [[Get]] internal method as defined at
432 * <https://html.spec.whatwg.org/multipage/window-object.html#windowproxy-get>.
433 *
434 * "proxy" is the WindowProxy object involved. It may or may not be
435 * same-compartment with "cx".
436 *
437 * "receiver" is the receiver ("this") for the get. It will be
438 * same-compartment with "cx".
439 *
440 * "vp" is the return value. It will be same-compartment with "cx".
441 */
442 bool get(JSContext* cx, JS::Handle<JSObject*> proxy,
443 JS::Handle<JS::Value> receiver, JS::Handle<jsid> id,
444 JS::MutableHandle<JS::Value> vp) const override;
445
446 /**
447 * Implementation of [[Set]] internal method as defined at
448 * <https://html.spec.whatwg.org/multipage/window-object.html#windowproxy-set>.
449 *
450 * "proxy" is the WindowProxy object involved. It may or may not be
451 * same-compartment with "cx".
452 *
453 * "v" is the value being set. It will be same-compartment with "cx".
454 *
455 * "receiver" is the receiver ("this") for the set. It will be
456 * same-compartment with "cx".
457 */
458 bool set(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
459 JS::Handle<JS::Value> v, JS::Handle<JS::Value> receiver,
460 JS::ObjectOpResult& result) const override;
461
462 // SpiderMonkey extensions
463 /**
464 * Implementation of SpiderMonkey extension which just checks whether this
465 * object has the property. Basically Object.getOwnPropertyDescriptor(obj,
466 * prop) !== undefined. but does not require reifying the descriptor.
467 *
468 * We have to override this because js::Wrapper overrides it, but we want
469 * different behavior from js::Wrapper.
470 *
471 * "proxy" is the WindowProxy object involved. It may not be same-compartment
472 * with cx.
473 */
474 bool hasOwn(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
475 bool* bp) const override;
476
477 /**
478 * Implementation of SpiderMonkey extension which is used as a fast path for
479 * enumerating.
480 *
481 * We have to override this because js::Wrapper overrides it, but we want
482 * different behavior from js::Wrapper.
483 *
484 * "proxy" is the WindowProxy object involved. It may not be same-compartment
485 * with cx.
486 */
487 bool getOwnEnumerablePropertyKeys(
488 JSContext* cx, JS::Handle<JSObject*> proxy,
489 JS::MutableHandleVector<jsid> props) const override;
490
491 /**
492 * Hook used by SpiderMonkey to implement Object.prototype.toString.
493 */
494 const char* className(JSContext* cx,
495 JS::Handle<JSObject*> wrapper) const override;
496
497 void finalize(JS::GCContext* gcx, JSObject* proxy) const override;
498 size_t objectMoved(JSObject* proxy, JSObject* old) const override;
499
500 bool isCallable(JSObject* obj) const override { return false; }
501 bool isConstructor(JSObject* obj) const override { return false; }
502
503 static const nsOuterWindowProxy singleton;
504
505 static nsGlobalWindowOuter* GetOuterWindow(JSObject* proxy) {
506 nsGlobalWindowOuter* outerWindow =
507 nsGlobalWindowOuter::FromSupports(static_cast<nsISupports*>(
508 js::GetProxyReservedSlot(proxy, OUTER_WINDOW_SLOT).toPrivate()));
509 return outerWindow;
510 }
511
512 protected:
513 // False return value means we threw an exception. True return value
514 // but false "found" means we didn't have a subframe at that index.
515 bool GetSubframeWindow(JSContext* cx, JS::Handle<JSObject*> proxy,
516 JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp,
517 bool& found) const;
518
519 // Returns a non-null window only if id is an index and we have a
520 // window at that index.
521 Nullable<WindowProxyHolder> GetSubframeWindow(JSContext* cx,
522 JS::Handle<JSObject*> proxy,
523 JS::Handle<jsid> id) const;
524
525 bool AppendIndexedPropertyNames(JSObject* proxy,
526 JS::MutableHandleVector<jsid> props) const;
527
528 using MaybeCrossOriginObjectMixins::EnsureHolder;
529 bool EnsureHolder(JSContext* cx, JS::Handle<JSObject*> proxy,
530 JS::MutableHandle<JSObject*> holder) const override;
531
532 // Helper method for creating a special "print" method that allows printing
533 // our PDF-viewer documents even if you're not same-origin with them.
534 //
535 // aProxy must be our nsOuterWindowProxy. It will not be same-compartment
536 // with aCx, since we only use this on the different-origin codepath!
537 //
538 // Can return true without filling in aDesc, which corresponds to not exposing
539 // a "print" method.
540 static bool MaybeGetPDFJSPrintMethod(
541 JSContext* cx, JS::Handle<JSObject*> proxy,
542 JS::MutableHandle<Maybe<JS::PropertyDescriptor>> desc);
543
544 // The actual "print" method we use for the PDFJS case.
545 static bool PDFJSPrintMethod(JSContext* cx, unsigned argc, JS::Value* vp);
546
547 // Helper method to get the pre-PDF-viewer-messing-with-it principal from an
548 // inner window. Will return null if this is not a PDF-viewer inner or if the
549 // principal could not be found for some reason.
550 static already_AddRefed<nsIPrincipal> GetNoPDFJSPrincipal(
551 nsGlobalWindowInner* inner);
552};
553
554const char* nsOuterWindowProxy::className(JSContext* cx,
555 JS::Handle<JSObject*> proxy) const {
556 MOZ_ASSERT(js::IsProxy(proxy))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(js::IsProxy(proxy))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(js::IsProxy(proxy)))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("js::IsProxy(proxy)"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 556); AnnotateMozCrashReason("MOZ_ASSERT" "(" "js::IsProxy(proxy)"
")"); do { *((volatile int*)__null) = 556; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
557
558 if (!IsPlatformObjectSameOrigin(cx, proxy)) {
559 return "Object";
560 }
561
562 return "Window";
563}
564
565void nsOuterWindowProxy::finalize(JS::GCContext* gcx, JSObject* proxy) const {
566 nsGlobalWindowOuter* outerWindow = GetOuterWindow(proxy);
567 if (outerWindow) {
568 outerWindow->ClearWrapper(proxy);
569 BrowsingContext* bc = outerWindow->GetBrowsingContext();
570 if (bc) {
571 bc->ClearWindowProxy();
572 }
573
574 // Ideally we would use OnFinalize here, but it's possible that
575 // EnsureScriptEnvironment will later be called on the window, and we don't
576 // want to create a new script object in that case. Therefore, we need to
577 // write a non-null value that will reliably crash when dereferenced.
578 outerWindow->PoisonOuterWindowProxy(proxy);
579 }
580}
581
582bool nsOuterWindowProxy::getOwnPropertyDescriptor(
583 JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
584 JS::MutableHandle<Maybe<JS::PropertyDescriptor>> desc) const {
585 // First check for indexed access. This is
586 // https://html.spec.whatwg.org/multipage/window-object.html#windowproxy-getownproperty
587 // step 2, mostly.
588 JS::Rooted<JS::Value> subframe(cx);
589 bool found;
590 if (!GetSubframeWindow(cx, proxy, id, &subframe, found)) {
591 return false;
592 }
593 if (found) {
594 // Step 2.4.
595
596 desc.set(Some(JS::PropertyDescriptor::Data(
597 subframe, {
598 JS::PropertyAttribute::Configurable,
599 JS::PropertyAttribute::Enumerable,
600 })));
601 return true;
602 }
603
604 bool isSameOrigin = IsPlatformObjectSameOrigin(cx, proxy);
605
606 // If we did not find a subframe, we could still have an indexed property
607 // access. In that case we should throw a SecurityError in the cross-origin
608 // case.
609 if (!isSameOrigin && IsArrayIndex(GetArrayIndexFromId(id))) {
610 // Step 2.5.2.
611 return ReportCrossOriginDenial(cx, id, "access"_ns);
612 }
613
614 // Step 2.5.1 is handled via the forwarding to js::Wrapper; it saves us an
615 // IsArrayIndex(GetArrayIndexFromId(id)) here. We'll never have a property on
616 // the Window whose name is an index, because our defineProperty doesn't pass
617 // those on to the Window.
618
619 // Step 3.
620 if (isSameOrigin) {
621 if (StaticPrefs::dom_missing_prop_counters_enabled() && id.isAtom()) {
622 Window_Binding::CountMaybeMissingProperty(proxy, id);
623 }
624
625 // Fall through to js::Wrapper.
626 { // Scope for JSAutoRealm while we are dealing with js::Wrapper.
627 // When forwarding to js::Wrapper, we should just enter the Realm of proxy
628 // for now. That's what js::Wrapper expects, and since we're same-origin
629 // anyway this is not changing any security behavior.
630 JSAutoRealm ar(cx, proxy);
631 JS_MarkCrossZoneId(cx, id);
632 bool ok = js::Wrapper::getOwnPropertyDescriptor(cx, proxy, id, desc);
633 if (!ok) {
634 return false;
635 }
636
637#if 0
638 // See https://github.com/tc39/ecma262/issues/672 for more information.
639 if (desc.isSome() &&
640 !IsNonConfigurableReadonlyPrimitiveGlobalProp(cx, id)) {
641 (*desc).setConfigurable(true);
642 }
643#endif
644 }
645
646 // Now wrap our descriptor back into the Realm that asked for it.
647 return JS_WrapPropertyDescriptor(cx, desc);
648 }
649
650 // Step 4.
651 if (!CrossOriginGetOwnPropertyHelper(cx, proxy, id, desc)) {
652 return false;
653 }
654
655 // Step 5
656 if (desc.isSome()) {
657 return true;
658 }
659
660 // Non-spec step for the PDF viewer's window.print(). This comes before we
661 // check for named subframes, because in the same-origin case print() would
662 // shadow those.
663 if (id == GetJSIDByIndex(cx, XPCJSContext::IDX_PRINT)) {
664 if (!MaybeGetPDFJSPrintMethod(cx, proxy, desc)) {
665 return false;
666 }
667
668 if (desc.isSome()) {
669 return true;
670 }
671 }
672
673 // Step 6 -- check for named subframes.
674 if (id.isString()) {
675 nsAutoJSString name;
676 if (!name.init(cx, id.toString())) {
677 return false;
678 }
679 nsGlobalWindowOuter* win = GetOuterWindow(proxy);
680 if (RefPtr<BrowsingContext> childDOMWin = win->GetChildWindow(name)) {
681 JS::Rooted<JS::Value> childValue(cx);
682 if (!ToJSValue(cx, WindowProxyHolder(childDOMWin), &childValue)) {
683 return false;
684 }
685 desc.set(Some(JS::PropertyDescriptor::Data(
686 childValue, {JS::PropertyAttribute::Configurable})));
687 return true;
688 }
689 }
690
691 // And step 7.
692 return CrossOriginPropertyFallback(cx, proxy, id, desc);
693}
694
695bool nsOuterWindowProxy::definePropertySameOrigin(
696 JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
697 JS::Handle<JS::PropertyDescriptor> desc, JS::ObjectOpResult& result) const {
698 if (IsArrayIndex(GetArrayIndexFromId(id))) {
699 // Spec says to Reject whether this is a supported index or not,
700 // since we have no indexed setter or indexed creator. It is up
701 // to the caller to decide whether to throw a TypeError.
702 return result.failCantDefineWindowElement();
703 }
704
705 JS::ObjectOpResult ourResult;
706 bool ok = js::Wrapper::defineProperty(cx, proxy, id, desc, ourResult);
707 if (!ok) {
708 return false;
709 }
710
711 if (!ourResult.ok()) {
712 // It's possible that this failed because the page got the existing
713 // descriptor (which we force to claim to be configurable) and then tried to
714 // redefine the property with the descriptor it got but a different value.
715 // We want to allow this case to succeed, so check for it and if we're in
716 // that case try again but now with an attempt to define a non-configurable
717 // property.
718 if (!desc.hasConfigurable() || !desc.configurable()) {
719 // The incoming descriptor was not explicitly marked "configurable: true",
720 // so it failed for some other reason. Just propagate that reason out.
721 result = ourResult;
722 return true;
723 }
724
725 JS::Rooted<Maybe<JS::PropertyDescriptor>> existingDesc(cx);
726 ok = js::Wrapper::getOwnPropertyDescriptor(cx, proxy, id, &existingDesc);
727 if (!ok) {
728 return false;
729 }
730 if (existingDesc.isNothing() || existingDesc->configurable()) {
731 // We have no existing property, or its descriptor is already configurable
732 // (on the Window itself, where things really can be non-configurable).
733 // So we failed for some other reason, which we should propagate out.
734 result = ourResult;
735 return true;
736 }
737
738 JS::Rooted<JS::PropertyDescriptor> updatedDesc(cx, desc);
739 updatedDesc.setConfigurable(false);
740
741 JS::ObjectOpResult ourNewResult;
742 ok = js::Wrapper::defineProperty(cx, proxy, id, updatedDesc, ourNewResult);
743 if (!ok) {
744 return false;
745 }
746
747 if (!ourNewResult.ok()) {
748 // Twiddling the configurable flag didn't help. Just return this failure
749 // out to the caller.
750 result = ourNewResult;
751 return true;
752 }
753 }
754
755#if 0
756 // See https://github.com/tc39/ecma262/issues/672 for more information.
757 if (desc.hasConfigurable() && !desc.configurable() &&
758 !IsNonConfigurableReadonlyPrimitiveGlobalProp(cx, id)) {
759 // Give callers a way to detect that they failed to "really" define a
760 // non-configurable property.
761 result.failCantDefineWindowNonConfigurable();
762 return true;
763 }
764#endif
765
766 result.succeed();
767 return true;
768}
769
770bool nsOuterWindowProxy::ownPropertyKeys(
771 JSContext* cx, JS::Handle<JSObject*> proxy,
772 JS::MutableHandleVector<jsid> props) const {
773 // Just our indexed stuff followed by our "normal" own property names.
774 if (!AppendIndexedPropertyNames(proxy, props)) {
775 return false;
776 }
777
778 if (IsPlatformObjectSameOrigin(cx, proxy)) {
779 // When forwarding to js::Wrapper, we should just enter the Realm of proxy
780 // for now. That's what js::Wrapper expects, and since we're same-origin
781 // anyway this is not changing any security behavior.
782 JS::RootedVector<jsid> innerProps(cx);
783 { // Scope for JSAutoRealm so we can mark the ids once we exit it
784 JSAutoRealm ar(cx, proxy);
785 if (!js::Wrapper::ownPropertyKeys(cx, proxy, &innerProps)) {
786 return false;
787 }
788 }
789 for (auto& id : innerProps) {
790 JS_MarkCrossZoneId(cx, id);
791 }
792 return js::AppendUnique(cx, props, innerProps);
793 }
794
795 // In the cross-origin case we purposefully exclude subframe names from the
796 // list of property names we report here.
797 JS::Rooted<JSObject*> holder(cx);
798 if (!EnsureHolder(cx, proxy, &holder)) {
799 return false;
800 }
801
802 JS::RootedVector<jsid> crossOriginProps(cx);
803 if (!js::GetPropertyKeys(cx, holder,
804 JSITER_OWNONLY0x8 | JSITER_HIDDEN0x10 | JSITER_SYMBOLS0x20,
805 &crossOriginProps) ||
806 !js::AppendUnique(cx, props, crossOriginProps)) {
807 return false;
808 }
809
810 // Add the "print" property if needed.
811 nsGlobalWindowOuter* outer = GetOuterWindow(proxy);
812 nsGlobalWindowInner* inner =
813 nsGlobalWindowInner::Cast(outer->GetCurrentInnerWindow());
814 if (inner) {
815 nsCOMPtr<nsIPrincipal> targetPrincipal = GetNoPDFJSPrincipal(inner);
816 if (targetPrincipal &&
817 nsContentUtils::SubjectPrincipal(cx)->Equals(targetPrincipal)) {
818 JS::RootedVector<jsid> printProp(cx);
819 if (!printProp.append(GetJSIDByIndex(cx, XPCJSContext::IDX_PRINT)) ||
820 !js::AppendUnique(cx, props, printProp)) {
821 return false;
822 }
823 }
824 }
825
826 return xpc::AppendCrossOriginWhitelistedPropNames(cx, props);
827}
828
829bool nsOuterWindowProxy::delete_(JSContext* cx, JS::Handle<JSObject*> proxy,
830 JS::Handle<jsid> id,
831 JS::ObjectOpResult& result) const {
832 if (!IsPlatformObjectSameOrigin(cx, proxy)) {
833 return ReportCrossOriginDenial(cx, id, "delete"_ns);
834 }
835
836 if (!GetSubframeWindow(cx, proxy, id).IsNull()) {
837 // Fail (which means throw if strict, else return false).
838 return result.failCantDeleteWindowElement();
839 }
840
841 if (IsArrayIndex(GetArrayIndexFromId(id))) {
842 // Indexed, but not supported. Spec says return true.
843 return result.succeed();
844 }
845
846 // We're same-origin, so it should be safe to enter the Realm of "proxy".
847 // Let's do that, just in case, to avoid cross-compartment issues in our
848 // js::Wrapper caller..
849 JSAutoRealm ar(cx, proxy);
850 JS_MarkCrossZoneId(cx, id);
851 return js::Wrapper::delete_(cx, proxy, id, result);
852}
853
854JSObject* nsOuterWindowProxy::getSameOriginPrototype(JSContext* cx) const {
855 return Window_Binding::GetProtoObjectHandle(cx);
856}
857
858bool nsOuterWindowProxy::has(JSContext* cx, JS::Handle<JSObject*> proxy,
859 JS::Handle<jsid> id, bool* bp) const {
860 // We could just directly forward this method to js::BaseProxyHandler, but
861 // that involves reifying the actual property descriptor, which might be more
862 // work than we have to do for has() on the Window.
863
864 if (!IsPlatformObjectSameOrigin(cx, proxy)) {
865 // In the cross-origin case we only have own properties. Just call hasOwn
866 // directly.
867 return hasOwn(cx, proxy, id, bp);
868 }
869
870 if (!GetSubframeWindow(cx, proxy, id).IsNull()) {
871 *bp = true;
872 return true;
873 }
874
875 // Just to be safe in terms of compartment asserts, enter the Realm of
876 // "proxy". We're same-origin with it, so this should be safe.
877 JSAutoRealm ar(cx, proxy);
878 JS_MarkCrossZoneId(cx, id);
879 return js::Wrapper::has(cx, proxy, id, bp);
880}
881
882bool nsOuterWindowProxy::hasOwn(JSContext* cx, JS::Handle<JSObject*> proxy,
883 JS::Handle<jsid> id, bool* bp) const {
884 // We could just directly forward this method to js::BaseProxyHandler, but
885 // that involves reifying the actual property descriptor, which might be more
886 // work than we have to do for hasOwn() on the Window.
887
888 if (!IsPlatformObjectSameOrigin(cx, proxy)) {
889 // Avoiding reifying the property descriptor here would require duplicating
890 // a bunch of "is this property exposed cross-origin" logic, which is
891 // probably not worth it. Just forward this along to the base
892 // implementation.
893 //
894 // It's very important to not forward this to js::Wrapper, because that will
895 // not do the right security and cross-origin checks and will pass through
896 // the call to the Window.
897 //
898 // The BaseProxyHandler code is OK with this happening without entering the
899 // compartment of "proxy".
900 return js::BaseProxyHandler::hasOwn(cx, proxy, id, bp);
901 }
902
903 if (!GetSubframeWindow(cx, proxy, id).IsNull()) {
904 *bp = true;
905 return true;
906 }
907
908 // Just to be safe in terms of compartment asserts, enter the Realm of
909 // "proxy". We're same-origin with it, so this should be safe.
910 JSAutoRealm ar(cx, proxy);
911 JS_MarkCrossZoneId(cx, id);
912 return js::Wrapper::hasOwn(cx, proxy, id, bp);
913}
914
915bool nsOuterWindowProxy::get(JSContext* cx, JS::Handle<JSObject*> proxy,
916 JS::Handle<JS::Value> receiver,
917 JS::Handle<jsid> id,
918 JS::MutableHandle<JS::Value> vp) const {
919 if (id == GetJSIDByIndex(cx, XPCJSContext::IDX_WRAPPED_JSOBJECT) &&
920 xpc::AccessCheck::isChrome(js::GetContextCompartment(cx))) {
921 vp.set(JS::ObjectValue(*proxy));
922 return MaybeWrapValue(cx, vp);
923 }
924
925 if (!IsPlatformObjectSameOrigin(cx, proxy)) {
926 return CrossOriginGet(cx, proxy, receiver, id, vp);
927 }
928
929 bool found;
930 if (!GetSubframeWindow(cx, proxy, id, vp, found)) {
931 return false;
932 }
933
934 if (found) {
935 return true;
936 }
937
938 if (StaticPrefs::dom_missing_prop_counters_enabled() && id.isAtom()) {
939 Window_Binding::CountMaybeMissingProperty(proxy, id);
940 }
941
942 { // Scope for JSAutoRealm
943 // Enter "proxy"'s Realm. We're in the same-origin case, so this should be
944 // safe.
945 JSAutoRealm ar(cx, proxy);
946
947 JS_MarkCrossZoneId(cx, id);
948
949 JS::Rooted<JS::Value> wrappedReceiver(cx, receiver);
950 if (!MaybeWrapValue(cx, &wrappedReceiver)) {
951 return false;
952 }
953
954 // Fall through to js::Wrapper.
955 if (!js::Wrapper::get(cx, proxy, wrappedReceiver, id, vp)) {
956 return false;
957 }
958 }
959
960 // Make sure our return value is in the caller compartment.
961 return MaybeWrapValue(cx, vp);
962}
963
964bool nsOuterWindowProxy::set(JSContext* cx, JS::Handle<JSObject*> proxy,
965 JS::Handle<jsid> id, JS::Handle<JS::Value> v,
966 JS::Handle<JS::Value> receiver,
967 JS::ObjectOpResult& result) const {
968 if (!IsPlatformObjectSameOrigin(cx, proxy)) {
969 return CrossOriginSet(cx, proxy, id, v, receiver, result);
970 }
971
972 if (IsArrayIndex(GetArrayIndexFromId(id))) {
973 // Reject the set. It's up to the caller to decide whether to throw a
974 // TypeError. If the caller is strict mode JS code, it'll throw.
975 return result.failReadOnly();
976 }
977
978 // Do the rest in the Realm of "proxy", since we're in the same-origin case.
979 JSAutoRealm ar(cx, proxy);
980 JS::Rooted<JS::Value> wrappedArg(cx, v);
981 if (!MaybeWrapValue(cx, &wrappedArg)) {
982 return false;
983 }
984 JS::Rooted<JS::Value> wrappedReceiver(cx, receiver);
985 if (!MaybeWrapValue(cx, &wrappedReceiver)) {
986 return false;
987 }
988
989 JS_MarkCrossZoneId(cx, id);
990
991 return js::Wrapper::set(cx, proxy, id, wrappedArg, wrappedReceiver, result);
992}
993
994bool nsOuterWindowProxy::getOwnEnumerablePropertyKeys(
995 JSContext* cx, JS::Handle<JSObject*> proxy,
996 JS::MutableHandleVector<jsid> props) const {
997 // We could just stop overring getOwnEnumerablePropertyKeys and let our
998 // superclasses deal (by falling back on the BaseProxyHandler implementation
999 // that uses a combination of ownPropertyKeys and getOwnPropertyDescriptor to
1000 // only return the enumerable ones. But maybe there's value in having
1001 // somewhat faster for-in iteration on Window objects...
1002
1003 // Like ownPropertyKeys, our indexed stuff followed by our "normal" enumerable
1004 // own property names.
1005 if (!AppendIndexedPropertyNames(proxy, props)) {
1006 return false;
1007 }
1008
1009 if (!IsPlatformObjectSameOrigin(cx, proxy)) {
1010 // All the cross-origin properties other than the indexed props are
1011 // non-enumerable, so we're done here.
1012 return true;
1013 }
1014
1015 // When forwarding to js::Wrapper, we should just enter the Realm of proxy
1016 // for now. That's what js::Wrapper expects, and since we're same-origin
1017 // anyway this is not changing any security behavior.
1018 JS::RootedVector<jsid> innerProps(cx);
1019 { // Scope for JSAutoRealm so we can mark the ids once we exit it.
1020 JSAutoRealm ar(cx, proxy);
1021 if (!js::Wrapper::getOwnEnumerablePropertyKeys(cx, proxy, &innerProps)) {
1022 return false;
1023 }
1024 }
1025
1026 for (auto& id : innerProps) {
1027 JS_MarkCrossZoneId(cx, id);
1028 }
1029
1030 return js::AppendUnique(cx, props, innerProps);
1031}
1032
1033bool nsOuterWindowProxy::GetSubframeWindow(JSContext* cx,
1034 JS::Handle<JSObject*> proxy,
1035 JS::Handle<jsid> id,
1036 JS::MutableHandle<JS::Value> vp,
1037 bool& found) const {
1038 Nullable<WindowProxyHolder> frame = GetSubframeWindow(cx, proxy, id);
1039 if (frame.IsNull()) {
1040 found = false;
1041 return true;
1042 }
1043
1044 found = true;
1045 return WrapObject(cx, frame.Value(), vp);
1046}
1047
1048Nullable<WindowProxyHolder> nsOuterWindowProxy::GetSubframeWindow(
1049 JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id) const {
1050 uint32_t index = GetArrayIndexFromId(id);
1051 if (!IsArrayIndex(index)) {
1052 return nullptr;
1053 }
1054
1055 nsGlobalWindowOuter* win = GetOuterWindow(proxy);
1056 return win->IndexedGetterOuter(index);
1057}
1058
1059bool nsOuterWindowProxy::AppendIndexedPropertyNames(
1060 JSObject* proxy, JS::MutableHandleVector<jsid> props) const {
1061 uint32_t length = GetOuterWindow(proxy)->Length();
1062 MOZ_ASSERT(int32_t(length) >= 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(int32_t(length) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(length) >= 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(length) >= 0"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 1062); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(length) >= 0"
")"); do { *((volatile int*)__null) = 1062; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1063 if (!props.reserve(props.length() + length)) {
1064 return false;
1065 }
1066 for (int32_t i = 0; i < int32_t(length); ++i) {
1067 if (!props.append(JS::PropertyKey::Int(i))) {
1068 return false;
1069 }
1070 }
1071
1072 return true;
1073}
1074
1075bool nsOuterWindowProxy::EnsureHolder(
1076 JSContext* cx, JS::Handle<JSObject*> proxy,
1077 JS::MutableHandle<JSObject*> holder) const {
1078 return EnsureHolder(cx, proxy, HOLDER_WEAKMAP_SLOT,
1079 Window_Binding::sCrossOriginProperties, holder);
1080}
1081
1082size_t nsOuterWindowProxy::objectMoved(JSObject* obj, JSObject* old) const {
1083 nsGlobalWindowOuter* outerWindow = GetOuterWindow(obj);
1084 if (outerWindow) {
1085 outerWindow->UpdateWrapper(obj, old);
1086 BrowsingContext* bc = outerWindow->GetBrowsingContext();
1087 if (bc) {
1088 bc->UpdateWindowProxy(obj, old);
1089 }
1090 }
1091 return 0;
1092}
1093
1094enum { PDFJS_SLOT_CALLEE = 0 };
1095
1096// static
1097bool nsOuterWindowProxy::MaybeGetPDFJSPrintMethod(
1098 JSContext* cx, JS::Handle<JSObject*> proxy,
1099 JS::MutableHandle<Maybe<JS::PropertyDescriptor>> desc) {
1100 MOZ_ASSERT(proxy)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(proxy)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(proxy))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("proxy", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 1100); AnnotateMozCrashReason("MOZ_ASSERT" "(" "proxy" ")")
; do { *((volatile int*)__null) = 1100; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1101 MOZ_ASSERT(!desc.isSome())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!desc.isSome())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!desc.isSome()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!desc.isSome()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 1101); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!desc.isSome()"
")"); do { *((volatile int*)__null) = 1101; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1102
1103 nsGlobalWindowOuter* outer = GetOuterWindow(proxy);
1104 nsGlobalWindowInner* inner =
1105 nsGlobalWindowInner::Cast(outer->GetCurrentInnerWindow());
1106 if (!inner) {
1107 // No print method to expose.
1108 return true;
1109 }
1110
1111 nsCOMPtr<nsIPrincipal> targetPrincipal = GetNoPDFJSPrincipal(inner);
1112 if (!targetPrincipal) {
1113 // Nothing special to be done.
1114 return true;
1115 }
1116
1117 if (!nsContentUtils::SubjectPrincipal(cx)->Equals(targetPrincipal)) {
1118 // Not our origin's PDF document.
1119 return true;
1120 }
1121
1122 // Get the function we plan to actually call.
1123 JS::Rooted<JSObject*> innerObj(cx, inner->GetGlobalJSObject());
1124 if (!innerObj) {
1125 // Really should not happen, but ok, let's just return.
1126 return true;
1127 }
1128
1129 JS::Rooted<JS::Value> targetFunc(cx);
1130 {
1131 JSAutoRealm ar(cx, innerObj);
1132 if (!JS_GetProperty(cx, innerObj, "print", &targetFunc)) {
1133 return false;
1134 }
1135 }
1136
1137 if (!targetFunc.isObject()) {
1138 // Who knows what's going on. Just return.
1139 return true;
1140 }
1141
1142 // The Realm of cx is the realm our caller is in and the realm we
1143 // should create our function in. Note that we can't use the
1144 // standard XPConnect function forwarder machinery because our
1145 // "this" is cross-origin, so we have to do thus by hand.
1146
1147 // Make sure targetFunc is wrapped into the right compartment.
1148 if (!MaybeWrapValue(cx, &targetFunc)) {
1149 return false;
1150 }
1151
1152 JSFunction* fun =
1153 js::NewFunctionWithReserved(cx, PDFJSPrintMethod, 0, 0, "print");
1154 if (!fun) {
1155 return false;
1156 }
1157
1158 JS::Rooted<JSObject*> funObj(cx, JS_GetFunctionObject(fun));
1159 js::SetFunctionNativeReserved(funObj, PDFJS_SLOT_CALLEE, targetFunc);
1160
1161 // { value: <print>, writable: true, enumerable: true, configurable: true }
1162 // because that's what it would have been in the same-origin case without
1163 // the PDF viewer messing with things.
1164 desc.set(Some(JS::PropertyDescriptor::Data(
1165 JS::ObjectValue(*funObj),
1166 {JS::PropertyAttribute::Configurable, JS::PropertyAttribute::Enumerable,
1167 JS::PropertyAttribute::Writable})));
1168 return true;
1169}
1170
1171// static
1172bool nsOuterWindowProxy::PDFJSPrintMethod(JSContext* cx, unsigned argc,
1173 JS::Value* vp) {
1174 JS::CallArgs args = CallArgsFromVp(argc, vp);
1175
1176 JS::Rooted<JSObject*> realCallee(
1177 cx, &js::GetFunctionNativeReserved(&args.callee(), PDFJS_SLOT_CALLEE)
1178 .toObject());
1179 // Unchecked unwrap, because we want to extract the thing we really had
1180 // before.
1181 realCallee = js::UncheckedUnwrap(realCallee);
1182
1183 JS::Rooted<JS::Value> thisv(cx, args.thisv());
1184 if (thisv.isNullOrUndefined()) {
1185 // Replace it with the global of our stashed callee, simulating the
1186 // global-assuming behavior of DOM methods.
1187 JS::Rooted<JSObject*> global(cx, JS::GetNonCCWObjectGlobal(realCallee));
1188 if (!MaybeWrapObject(cx, &global)) {
1189 return false;
1190 }
1191 thisv.setObject(*global);
1192 } else if (!thisv.isObject()) {
1193 return ThrowInvalidThis(cx, args, false, prototypes::id::Window);
1194 }
1195
1196 // We want to do an UncheckedUnwrap here, because we're going to directly
1197 // examine the principal of the inner window, if we have an inner window.
1198 JS::Rooted<JSObject*> unwrappedObj(cx,
1199 js::UncheckedUnwrap(&thisv.toObject()));
1200 nsGlobalWindowInner* inner = nullptr;
1201 {
1202 // Do the unwrap in the Realm of the object we're looking at.
1203 JSAutoRealm ar(cx, unwrappedObj);
1204 UNWRAP_MAYBE_CROSS_ORIGIN_OBJECT(Window, &unwrappedObj, inner, cx)mozilla::dom::UnwrapObject<mozilla::dom::prototypes::id::Window
, mozilla::dom::Window_Binding::NativeType>( &unwrappedObj
, inner, cx)
;
1205 }
1206 if (!inner) {
1207 return ThrowInvalidThis(cx, args, false, prototypes::id::Window);
1208 }
1209
1210 nsIPrincipal* callerPrincipal = nsContentUtils::SubjectPrincipal(cx);
1211 if (!callerPrincipal->SubsumesConsideringDomain(inner->GetPrincipal())) {
1212 // Check whether it's a PDF viewer from our origin.
1213 nsCOMPtr<nsIPrincipal> pdfPrincipal = GetNoPDFJSPrincipal(inner);
1214 if (!pdfPrincipal || !callerPrincipal->Equals(pdfPrincipal)) {
1215 // Security error.
1216 return ThrowInvalidThis(cx, args, true, prototypes::id::Window);
1217 }
1218 }
1219
1220 // Go ahead and enter the Realm of our real callee to call it. We'll pass it
1221 // our "thisv", just in case someone grabs a "print" method off one PDF
1222 // document and .call()s it on another one.
1223 {
1224 JSAutoRealm ar(cx, realCallee);
1225 if (!MaybeWrapValue(cx, &thisv)) {
1226 return false;
1227 }
1228
1229 // Don't bother passing through the args; they will get ignored anyway.
1230
1231 if (!JS::Call(cx, thisv, realCallee, JS::HandleValueArray::empty(),
1232 args.rval())) {
1233 return false;
1234 }
1235 }
1236
1237 // Wrap the return value (not that there should be any!) into the right
1238 // compartment.
1239 return MaybeWrapValue(cx, args.rval());
1240}
1241
1242// static
1243already_AddRefed<nsIPrincipal> nsOuterWindowProxy::GetNoPDFJSPrincipal(
1244 nsGlobalWindowInner* inner) {
1245 if (!nsContentUtils::IsPDFJS(inner->GetPrincipal())) {
1246 return nullptr;
1247 }
1248
1249 if (Document* doc = inner->GetExtantDoc()) {
1250 if (nsCOMPtr<nsIPropertyBag2> propBag =
1251 do_QueryInterface(doc->GetChannel())) {
1252 nsCOMPtr<nsIPrincipal> principal(
1253 do_GetProperty(propBag, u"noPDFJSPrincipal"_ns));
1254 return principal.forget();
1255 }
1256 }
1257 return nullptr;
1258}
1259
1260const nsOuterWindowProxy nsOuterWindowProxy::singleton;
1261
1262class nsChromeOuterWindowProxy : public nsOuterWindowProxy {
1263 public:
1264 constexpr nsChromeOuterWindowProxy() = default;
1265
1266 const char* className(JSContext* cx,
1267 JS::Handle<JSObject*> wrapper) const override;
1268
1269 static const nsChromeOuterWindowProxy singleton;
1270};
1271
1272const char* nsChromeOuterWindowProxy::className(
1273 JSContext* cx, JS::Handle<JSObject*> proxy) const {
1274 MOZ_ASSERT(js::IsProxy(proxy))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(js::IsProxy(proxy))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(js::IsProxy(proxy)))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("js::IsProxy(proxy)"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 1274); AnnotateMozCrashReason("MOZ_ASSERT" "(" "js::IsProxy(proxy)"
")"); do { *((volatile int*)__null) = 1274; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1275
1276 return "ChromeWindow";
1277}
1278
1279const nsChromeOuterWindowProxy nsChromeOuterWindowProxy::singleton;
1280
1281static JSObject* NewOuterWindowProxy(JSContext* cx,
1282 JS::Handle<JSObject*> global,
1283 bool isChrome) {
1284 MOZ_ASSERT(JS_IsGlobalObject(global))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(JS_IsGlobalObject(global))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(JS_IsGlobalObject(global))))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("JS_IsGlobalObject(global)"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 1284); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JS_IsGlobalObject(global)"
")"); do { *((volatile int*)__null) = 1284; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1285
1286 JSAutoRealm ar(cx, global);
1287
1288 js::WrapperOptions options;
1289 options.setClass(&OuterWindowProxyClass);
1290 JSObject* obj =
1291 js::Wrapper::New(cx, global,
1292 isChrome ? &nsChromeOuterWindowProxy::singleton
1293 : &nsOuterWindowProxy::singleton,
1294 options);
1295 MOZ_ASSERT_IF(obj, js::IsWindowProxy(obj))do { if (obj) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(js::IsWindowProxy(obj))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(js::IsWindowProxy(obj)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("js::IsWindowProxy(obj)"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 1295); AnnotateMozCrashReason("MOZ_ASSERT" "(" "js::IsWindowProxy(obj)"
")"); do { *((volatile int*)__null) = 1295; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1296 return obj;
1297}
1298
1299//*****************************************************************************
1300//*** nsGlobalWindowOuter: Object Management
1301//*****************************************************************************
1302
1303nsGlobalWindowOuter::nsGlobalWindowOuter(uint64_t aWindowID)
1304 : nsPIDOMWindowOuter(aWindowID),
1305 mFullscreenHasChangedDuringProcessing(false),
1306 mForceFullScreenInWidget(false),
1307 mIsClosed(false),
1308 mInClose(false),
1309 mHavePendingClose(false),
1310 mBlockScriptedClosingFlag(false),
1311 mWasOffline(false),
1312 mCreatingInnerWindow(false),
1313 mIsChrome(false),
1314 mAllowScriptsToClose(false),
1315 mTopLevelOuterContentWindow(false),
1316 mDelayedPrintUntilAfterLoad(false),
1317 mDelayedCloseForPrinting(false),
1318 mShouldDelayPrintUntilAfterLoad(false),
1319#ifdef DEBUG1
1320 mSerial(0),
1321 mSetOpenerWindowCalled(false),
1322#endif
1323 mCleanedUp(false),
1324 mCanSkipCCGeneration(0),
1325 mAutoActivateVRDisplayID(0) {
1326 AssertIsOnMainThread();
1327 SetIsOnMainThread();
1328 nsLayoutStatics::AddRef();
1329
1330 // Initialize the PRCList (this).
1331 PR_INIT_CLIST(this)do { (this)->next = (this); (this)->prev = (this); } while
(0)
;
1332
1333 // |this| is an outer window. Outer windows start out frozen and
1334 // remain frozen until they get an inner window.
1335 MOZ_ASSERT(IsFrozen())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsFrozen())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsFrozen()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("IsFrozen()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 1335); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsFrozen()"
")"); do { *((volatile int*)__null) = 1335; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1336
1337 // We could have failed the first time through trying
1338 // to create the entropy collector, so we should
1339 // try to get one until we succeed.
1340
1341#ifdef DEBUG1
1342 mSerial = nsContentUtils::InnerOrOuterWindowCreated();
1343
1344 MOZ_LOG(gDocShellAndDOMWindowLeakLogging, LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "++DOMWINDOW == %d (%p) [pid = %d] [serial = %d] [outer = %p]\n"
, nsContentUtils::GetCurrentInnerOrOuterWindowCount(), static_cast
<void*>(ToCanonicalSupports(this)), getpid(), mSerial, nullptr
); } } while (0)
1345 ("++DOMWINDOW == %d (%p) [pid = %d] [serial = %d] [outer = %p]\n",do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "++DOMWINDOW == %d (%p) [pid = %d] [serial = %d] [outer = %p]\n"
, nsContentUtils::GetCurrentInnerOrOuterWindowCount(), static_cast
<void*>(ToCanonicalSupports(this)), getpid(), mSerial, nullptr
); } } while (0)
1346 nsContentUtils::GetCurrentInnerOrOuterWindowCount(),do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "++DOMWINDOW == %d (%p) [pid = %d] [serial = %d] [outer = %p]\n"
, nsContentUtils::GetCurrentInnerOrOuterWindowCount(), static_cast
<void*>(ToCanonicalSupports(this)), getpid(), mSerial, nullptr
); } } while (0)
1347 static_cast<void*>(ToCanonicalSupports(this)), getpid(), mSerial,do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "++DOMWINDOW == %d (%p) [pid = %d] [serial = %d] [outer = %p]\n"
, nsContentUtils::GetCurrentInnerOrOuterWindowCount(), static_cast
<void*>(ToCanonicalSupports(this)), getpid(), mSerial, nullptr
); } } while (0)
1348 nullptr))do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "++DOMWINDOW == %d (%p) [pid = %d] [serial = %d] [outer = %p]\n"
, nsContentUtils::GetCurrentInnerOrOuterWindowCount(), static_cast
<void*>(ToCanonicalSupports(this)), getpid(), mSerial, nullptr
); } } while (0)
;
1349#endif
1350
1351 MOZ_LOG(gDOMLeakPRLogOuter, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogOuter
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "DOMWINDOW %p created outer=nullptr", this
); } } while (0)
1352 ("DOMWINDOW %p created outer=nullptr", this))do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogOuter
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "DOMWINDOW %p created outer=nullptr", this
); } } while (0)
;
1353
1354 // Add ourselves to the outer windows list.
1355 MOZ_ASSERT(sOuterWindowsById, "Outer Windows hash table must be created!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sOuterWindowsById)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sOuterWindowsById))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("sOuterWindowsById"
" (" "Outer Windows hash table must be created!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 1355); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sOuterWindowsById"
") (" "Outer Windows hash table must be created!" ")"); do {
*((volatile int*)__null) = 1355; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
1356
1357 // |this| is an outer window, add to the outer windows list.
1358 MOZ_ASSERT(!sOuterWindowsById->Contains(mWindowID),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!sOuterWindowsById->Contains(mWindowID))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!sOuterWindowsById->Contains(mWindowID)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!sOuterWindowsById->Contains(mWindowID)"
" (" "This window shouldn't be in the hash table yet!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 1359); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sOuterWindowsById->Contains(mWindowID)"
") (" "This window shouldn't be in the hash table yet!" ")")
; do { *((volatile int*)__null) = 1359; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1359 "This window shouldn't be in the hash table yet!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!sOuterWindowsById->Contains(mWindowID))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!sOuterWindowsById->Contains(mWindowID)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!sOuterWindowsById->Contains(mWindowID)"
" (" "This window shouldn't be in the hash table yet!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 1359); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sOuterWindowsById->Contains(mWindowID)"
") (" "This window shouldn't be in the hash table yet!" ")")
; do { *((volatile int*)__null) = 1359; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1360 // We seem to see crashes in release builds because of null
1361 // |sOuterWindowsById|.
1362 if (sOuterWindowsById) {
1363 sOuterWindowsById->InsertOrUpdate(mWindowID, this);
1364 }
1365}
1366
1367#ifdef DEBUG1
1368
1369/* static */
1370void nsGlobalWindowOuter::AssertIsOnMainThread() {
1371 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 1371); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 1371; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1372}
1373
1374#endif // DEBUG
1375
1376/* static */
1377void nsGlobalWindowOuter::Init() {
1378 AssertIsOnMainThread();
1379
1380 NS_ASSERTION(gDOMLeakPRLogOuter,do { if (!(gDOMLeakPRLogOuter)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "gDOMLeakPRLogOuter should have been initialized!", "gDOMLeakPRLogOuter"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 1381); MOZ_PretendNoReturn(); } } while (0)
1381 "gDOMLeakPRLogOuter should have been initialized!")do { if (!(gDOMLeakPRLogOuter)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "gDOMLeakPRLogOuter should have been initialized!", "gDOMLeakPRLogOuter"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 1381); MOZ_PretendNoReturn(); } } while (0)
;
1382
1383 sOuterWindowsById = new OuterWindowByIdTable();
1384}
1385
1386nsGlobalWindowOuter::~nsGlobalWindowOuter() {
1387 AssertIsOnMainThread();
1388
1389 if (sOuterWindowsById) {
1390 sOuterWindowsById->Remove(mWindowID);
1391 }
1392
1393 nsContentUtils::InnerOrOuterWindowDestroyed();
1394
1395#ifdef DEBUG1
1396 if (MOZ_LOG_TEST(gDocShellAndDOMWindowLeakLogging, LogLevel::Info)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellAndDOMWindowLeakLogging
, LogLevel::Info)), 0))
) {
1397 nsAutoCString url;
1398 if (mLastOpenedURI) {
1399 url = mLastOpenedURI->GetSpecOrDefault();
1400
1401 // Data URLs can be very long, so truncate to avoid flooding the log.
1402 const uint32_t maxURLLength = 1000;
1403 if (url.Length() > maxURLLength) {
1404 url.Truncate(maxURLLength);
1405 }
1406 }
1407
1408 MOZ_LOG(do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "--DOMWINDOW == %d (%p) [pid = %d] [serial = %d] [outer = %p] [url = "
"%s]\n", nsContentUtils::GetCurrentInnerOrOuterWindowCount()
, static_cast<void*>(ToCanonicalSupports(this)), getpid
(), mSerial, nullptr, url.get()); } } while (0)
1409 gDocShellAndDOMWindowLeakLogging, LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "--DOMWINDOW == %d (%p) [pid = %d] [serial = %d] [outer = %p] [url = "
"%s]\n", nsContentUtils::GetCurrentInnerOrOuterWindowCount()
, static_cast<void*>(ToCanonicalSupports(this)), getpid
(), mSerial, nullptr, url.get()); } } while (0)
1410 ("--DOMWINDOW == %d (%p) [pid = %d] [serial = %d] [outer = %p] [url = "do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "--DOMWINDOW == %d (%p) [pid = %d] [serial = %d] [outer = %p] [url = "
"%s]\n", nsContentUtils::GetCurrentInnerOrOuterWindowCount()
, static_cast<void*>(ToCanonicalSupports(this)), getpid
(), mSerial, nullptr, url.get()); } } while (0)
1411 "%s]\n",do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "--DOMWINDOW == %d (%p) [pid = %d] [serial = %d] [outer = %p] [url = "
"%s]\n", nsContentUtils::GetCurrentInnerOrOuterWindowCount()
, static_cast<void*>(ToCanonicalSupports(this)), getpid
(), mSerial, nullptr, url.get()); } } while (0)
1412 nsContentUtils::GetCurrentInnerOrOuterWindowCount(),do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "--DOMWINDOW == %d (%p) [pid = %d] [serial = %d] [outer = %p] [url = "
"%s]\n", nsContentUtils::GetCurrentInnerOrOuterWindowCount()
, static_cast<void*>(ToCanonicalSupports(this)), getpid
(), mSerial, nullptr, url.get()); } } while (0)
1413 static_cast<void*>(ToCanonicalSupports(this)), getpid(), mSerial,do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "--DOMWINDOW == %d (%p) [pid = %d] [serial = %d] [outer = %p] [url = "
"%s]\n", nsContentUtils::GetCurrentInnerOrOuterWindowCount()
, static_cast<void*>(ToCanonicalSupports(this)), getpid
(), mSerial, nullptr, url.get()); } } while (0)
1414 nullptr, url.get()))do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "--DOMWINDOW == %d (%p) [pid = %d] [serial = %d] [outer = %p] [url = "
"%s]\n", nsContentUtils::GetCurrentInnerOrOuterWindowCount()
, static_cast<void*>(ToCanonicalSupports(this)), getpid
(), mSerial, nullptr, url.get()); } } while (0)
;
1415 }
1416#endif
1417
1418 MOZ_LOG(gDOMLeakPRLogOuter, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogOuter
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "DOMWINDOW %p destroyed", this); } } while
(0)
1419 ("DOMWINDOW %p destroyed", this))do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogOuter
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "DOMWINDOW %p destroyed", this); } } while
(0)
;
1420
1421 JSObject* proxy = GetWrapperMaybeDead();
1422 if (proxy) {
1423 if (mBrowsingContext && mBrowsingContext->GetUnbarrieredWindowProxy()) {
1424 nsGlobalWindowOuter* outer = nsOuterWindowProxy::GetOuterWindow(
1425 mBrowsingContext->GetUnbarrieredWindowProxy());
1426 // Check that the current WindowProxy object corresponds to this
1427 // nsGlobalWindowOuter, because we don't want to clear the WindowProxy if
1428 // we've replaced it with a cross-process WindowProxy.
1429 if (outer == this) {
1430 mBrowsingContext->ClearWindowProxy();
1431 }
1432 }
1433 js::SetProxyReservedSlot(proxy, OUTER_WINDOW_SLOT,
1434 JS::PrivateValue(nullptr));
1435 }
1436
1437 // An outer window is destroyed with inner windows still possibly
1438 // alive, iterate through the inner windows and null out their
1439 // back pointer to this outer, and pull them out of the list of
1440 // inner windows.
1441 //
1442 // Our linked list of inner windows both contains (an nsGlobalWindowOuter),
1443 // and our inner windows (nsGlobalWindowInners). This means that we need to
1444 // use PRCList*. We can then compare that PRCList* to `this` to see if its an
1445 // inner or outer window.
1446 PRCList* w;
1447 while ((w = PR_LIST_HEAD(this)(this)->next) != this) {
1448 PR_REMOVE_AND_INIT_LINK(w)do { (w)->prev->next = (w)->next; (w)->next->prev
= (w)->prev; (w)->next = (w); (w)->prev = (w); } while
(0)
;
1449 }
1450
1451 DropOuterWindowDocs();
1452
1453 // Outer windows are always supposed to call CleanUp before letting themselves
1454 // be destroyed.
1455 MOZ_ASSERT(mCleanedUp)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mCleanedUp)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mCleanedUp))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("mCleanedUp", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 1455); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCleanedUp"
")"); do { *((volatile int*)__null) = 1455; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1456
1457 nsCOMPtr<nsIDeviceSensors> ac = do_GetService(NS_DEVICE_SENSORS_CONTRACTID"@mozilla.org/devicesensors;1");
1458 if (ac) ac->RemoveWindowAsListener(this);
1459
1460 nsLayoutStatics::Release();
1461}
1462
1463// static
1464void nsGlobalWindowOuter::ShutDown() {
1465 AssertIsOnMainThread();
1466
1467 delete sOuterWindowsById;
1468 sOuterWindowsById = nullptr;
1469}
1470
1471void nsGlobalWindowOuter::DropOuterWindowDocs() {
1472 MOZ_ASSERT_IF(mDoc, !mDoc->EventHandlingSuppressed())do { if (mDoc) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(!mDoc->EventHandlingSuppressed())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!mDoc->EventHandlingSuppressed()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!mDoc->EventHandlingSuppressed()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 1472); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mDoc->EventHandlingSuppressed()"
")"); do { *((volatile int*)__null) = 1472; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1473 mDoc = nullptr;
1474 mSuspendedDocs.Clear();
1475}
1476
1477void nsGlobalWindowOuter::CleanUp() {
1478 // Guarantee idempotence.
1479 if (mCleanedUp) return;
1480 mCleanedUp = true;
1481
1482 StartDying();
1483
1484 mWindowUtils = nullptr;
1485
1486 ClearControllers();
1487
1488 mContext = nullptr; // Forces Release
1489 mChromeEventHandler = nullptr; // Forces Release
1490 mParentTarget = nullptr;
1491 mMessageManager = nullptr;
1492
1493 mArguments = nullptr;
1494}
1495
1496void nsGlobalWindowOuter::ClearControllers() {
1497 if (mControllers) {
1498 uint32_t count;
1499 mControllers->GetControllerCount(&count);
1500
1501 while (count--) {
1502 nsCOMPtr<nsIController> controller;
1503 mControllers->GetControllerAt(count, getter_AddRefs(controller));
1504
1505 nsCOMPtr<nsIControllerContext> context = do_QueryInterface(controller);
1506 if (context) context->SetCommandContext(nullptr);
1507 }
1508
1509 mControllers = nullptr;
1510 }
1511}
1512
1513//*****************************************************************************
1514// nsGlobalWindowOuter::nsISupports
1515//*****************************************************************************
1516
1517// QueryInterface implementation for nsGlobalWindowOuter
1518NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsGlobalWindowOuter)nsresult nsGlobalWindowOuter::QueryInterface(const nsIID&
aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 1518); MOZ_PretendNoReturn(); } } while (0); nsISupports* foundInterface
; if (TopThreeWordsEquals( aIID, (nsXPCOMCycleCollectionParticipant
::COMTypeInfo<nsXPCOMCycleCollectionParticipant, void>::
kIID), (nsCycleCollectionISupports::COMTypeInfo<nsCycleCollectionISupports
, void>::kIID)) && (LowWordEquals(aIID, (nsXPCOMCycleCollectionParticipant
::COMTypeInfo<nsXPCOMCycleCollectionParticipant, void>::
kIID)) || LowWordEquals(aIID, (nsCycleCollectionISupports::COMTypeInfo
<nsCycleCollectionISupports, void>::kIID)))) { if (LowWordEquals
(aIID, (nsXPCOMCycleCollectionParticipant::COMTypeInfo<nsXPCOMCycleCollectionParticipant
, void>::kIID))) { *aInstancePtr = nsGlobalWindowOuter::cycleCollection
::GetParticipant(); return NS_OK; } if (LowWordEquals(aIID, (
nsCycleCollectionISupports::COMTypeInfo<nsCycleCollectionISupports
, void>::kIID))) { *aInstancePtr = nsGlobalWindowOuter::cycleCollection
::Upcast(this); return NS_OK; } foundInterface = nullptr; } else
1519 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRYif (aIID.Equals((nsWrapperCache::COMTypeInfo<nsWrapperCache
, void>::kIID))) { *aInstancePtr = static_cast<nsWrapperCache
*>(this); return NS_OK; } else
1520 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, EventTarget)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupports>)) foundInterface = static_cast
<nsISupports*>(static_cast<EventTarget*>(this)); else
1521 NS_INTERFACE_MAP_ENTRY(nsIDOMWindow)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIDOMWindow>)) foundInterface = static_cast
<nsIDOMWindow*>(this); else
1522 NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIGlobalObject>)) foundInterface
= static_cast<nsIGlobalObject*>(this); else
1523 NS_INTERFACE_MAP_ENTRY(nsIScriptGlobalObject)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIScriptGlobalObject>)) foundInterface
= static_cast<nsIScriptGlobalObject*>(this); else
1524 NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIScriptObjectPrincipal>)) foundInterface
= static_cast<nsIScriptObjectPrincipal*>(this); else
1525 NS_INTERFACE_MAP_ENTRY(mozilla::dom::EventTarget)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, mozilla::dom::EventTarget>)) foundInterface
= static_cast<mozilla::dom::EventTarget*>(this); else
1526 NS_INTERFACE_MAP_ENTRY(nsPIDOMWindowOuter)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsPIDOMWindowOuter>)) foundInterface
= static_cast<nsPIDOMWindowOuter*>(this); else
1527 NS_INTERFACE_MAP_ENTRY(mozIDOMWindowProxy)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, mozIDOMWindowProxy>)) foundInterface
= static_cast<mozIDOMWindowProxy*>(this); else
1528 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupportsWeakReference>)) foundInterface
= static_cast<nsISupportsWeakReference*>(this); else
1529 NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIInterfaceRequestor>)) foundInterface
= static_cast<nsIInterfaceRequestor*>(this); else
1530NS_INTERFACE_MAP_ENDfoundInterface = 0; nsresult status; if (!foundInterface) { do
{ static_assert( mozilla::detail::AssertionConditionType<
decltype(!aIID.Equals((nsISupports::COMTypeInfo<nsISupports
, void>::kIID)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aIID.Equals((nsISupports::COMTypeInfo
<nsISupports, void>::kIID))))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("!aIID.Equals((nsISupports::COMTypeInfo<nsISupports, void>::kIID))"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 1530); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIID.Equals((nsISupports::COMTypeInfo<nsISupports, void>::kIID))"
")"); do { *((volatile int*)__null) = 1530; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); status = NS_NOINTERFACE
; } else { (foundInterface)->AddRef(); status = NS_OK; } *
aInstancePtr = foundInterface; return status; }
1531
1532NS_IMPL_CYCLE_COLLECTING_ADDREF(nsGlobalWindowOuter)MozExternalRefCountType nsGlobalWindowOuter::AddRef(void) { static_assert
(!std::is_destructible_v<nsGlobalWindowOuter>, "Reference-counted class "
"nsGlobalWindowOuter" " should not have a public destructor. "
"Make this class's destructor non-public"); do { static_assert
( mozilla::detail::AssertionConditionType<decltype(int32_t
(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 1532); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
1532; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); _mOwningThread.AssertOwnership("nsGlobalWindowOuter"
" not thread-safe"); nsISupports* base = nsGlobalWindowOuter
::cycleCollection::Upcast(this); nsrefcnt count = mRefCnt.incr
(base); NS_LogAddRef((this), (count), ("nsGlobalWindowOuter")
, (uint32_t)(sizeof(*this))); return count; }
1533NS_IMPL_CYCLE_COLLECTING_RELEASE(nsGlobalWindowOuter)MozExternalRefCountType nsGlobalWindowOuter::Release(void) { do
{ static_assert( mozilla::detail::AssertionConditionType<
decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 1533); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 1533
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); _mOwningThread.AssertOwnership("nsGlobalWindowOuter"
" not thread-safe"); nsISupports* base = nsGlobalWindowOuter
::cycleCollection::Upcast(this); nsrefcnt count = mRefCnt.decr
(base); NS_LogRelease((this), (count), ("nsGlobalWindowOuter"
)); return count; } void nsGlobalWindowOuter::DeleteCycleCollectable
(void) { delete (this); }
1534
1535NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsGlobalWindowOuter)bool nsGlobalWindowOuter::cycleCollection::CanSkipReal(void* p
, bool aRemovingAllowed) { nsGlobalWindowOuter* tmp = DowncastCCParticipant
<nsGlobalWindowOuter>(p);
1536 if (tmp->IsBlackForCC(false)) {
1537 if (nsCCUncollectableMarker::InGeneration(tmp->mCanSkipCCGeneration)) {
1538 return true;
1539 }
1540 tmp->mCanSkipCCGeneration = nsCCUncollectableMarker::sGeneration;
1541 if (EventListenerManager* elm = tmp->GetExistingListenerManager()) {
1542 elm->MarkForCC();
1543 }
1544 return true;
1545 }
1546NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END(void)tmp; return false; }
1547
1548NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsGlobalWindowOuter)bool nsGlobalWindowOuter::cycleCollection::CanSkipInCCReal(void
* p) { nsGlobalWindowOuter* tmp = DowncastCCParticipant<nsGlobalWindowOuter
>(p);
1549 return tmp->IsBlackForCC(true);
1550NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END(void)tmp; return false; }
1551
1552NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsGlobalWindowOuter)bool nsGlobalWindowOuter::cycleCollection::CanSkipThisReal(void
* p) { nsGlobalWindowOuter* tmp = DowncastCCParticipant<nsGlobalWindowOuter
>(p);
1553 return tmp->IsBlackForCC(false);
1554NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END(void)tmp; return false; }
1555
1556NS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalWindowOuter)nsGlobalWindowOuter::cycleCollection nsGlobalWindowOuter::_cycleCollectorGlobal
;
1557
1558NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGlobalWindowOuter)nsresult nsGlobalWindowOuter::cycleCollection::TraverseNative
( void* p, nsCycleCollectionTraversalCallback& cb) { nsGlobalWindowOuter
* tmp = DowncastCCParticipant<nsGlobalWindowOuter>(p);
1559 if (MOZ_UNLIKELY(cb.WantDebugInfo())(__builtin_expect(!!(cb.WantDebugInfo()), 0))) {
1560 char name[512];
1561 nsAutoCString uri;
1562 if (tmp->mDoc && tmp->mDoc->GetDocumentURI()) {
1563 uri = tmp->mDoc->GetDocumentURI()->GetSpecOrDefault();
1564 }
1565 SprintfLiteral(name, "nsGlobalWindowOuter # %" PRIu64"l" "u" " outer %s",
1566 tmp->mWindowID, uri.get());
1567 cb.DescribeRefCountedNode(tmp->mRefCnt.get(), name);
1568 } else {
1569 NS_IMPL_CYCLE_COLLECTION_DESCRIBE(nsGlobalWindowOuter, tmp->mRefCnt.get())cb.DescribeRefCountedNode(tmp->mRefCnt.get(), "nsGlobalWindowOuter"
);
1570 }
1571
1572 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContext)ImplCycleCollectionTraverse(cb, tmp->mContext, "mContext",
0);
1573
1574 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mControllers)ImplCycleCollectionTraverse(cb, tmp->mControllers, "mControllers"
, 0);
1575 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mArguments)ImplCycleCollectionTraverse(cb, tmp->mArguments, "mArguments"
, 0);
1576
1577 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocalStorage)ImplCycleCollectionTraverse(cb, tmp->mLocalStorage, "mLocalStorage"
, 0);
1578 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSuspendedDocs)ImplCycleCollectionTraverse(cb, tmp->mSuspendedDocs, "mSuspendedDocs"
, 0);
1579 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentPrincipal)ImplCycleCollectionTraverse(cb, tmp->mDocumentPrincipal, "mDocumentPrincipal"
, 0);
1580 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentCookiePrincipal)ImplCycleCollectionTraverse(cb, tmp->mDocumentCookiePrincipal
, "mDocumentCookiePrincipal", 0);
1581 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentStoragePrincipal)ImplCycleCollectionTraverse(cb, tmp->mDocumentStoragePrincipal
, "mDocumentStoragePrincipal", 0);
1582 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentPartitionedPrincipal)ImplCycleCollectionTraverse(cb, tmp->mDocumentPartitionedPrincipal
, "mDocumentPartitionedPrincipal", 0);
1583 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDoc)ImplCycleCollectionTraverse(cb, tmp->mDoc, "mDoc", 0);
1584
1585 // Traverse stuff from nsPIDOMWindow
1586 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeEventHandler)ImplCycleCollectionTraverse(cb, tmp->mChromeEventHandler, "mChromeEventHandler"
, 0);
1587 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParentTarget)ImplCycleCollectionTraverse(cb, tmp->mParentTarget, "mParentTarget"
, 0);
1588 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessageManager)ImplCycleCollectionTraverse(cb, tmp->mMessageManager, "mMessageManager"
, 0);
1589 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFrameElement)ImplCycleCollectionTraverse(cb, tmp->mFrameElement, "mFrameElement"
, 0);
1590
1591 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocShell)ImplCycleCollectionTraverse(cb, tmp->mDocShell, "mDocShell"
, 0);
1592 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowsingContext)ImplCycleCollectionTraverse(cb, tmp->mBrowsingContext, "mBrowsingContext"
, 0);
1593
1594 tmp->TraverseObjectsInGlobal(cb);
1595
1596 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeFields.mBrowserDOMWindow)ImplCycleCollectionTraverse(cb, tmp->mChromeFields.mBrowserDOMWindow
, "mChromeFields.mBrowserDOMWindow", 0);
1597NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END(void)tmp; return NS_OK; }
1598
1599NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindowOuter)void nsGlobalWindowOuter::cycleCollection::Unlink(void* p) { nsGlobalWindowOuter
* tmp = DowncastCCParticipant<nsGlobalWindowOuter>(p);
1600 NS_IMPL_CYCLE_COLLECTION_UNLINK_WEAK_REFERENCEtmp->ClearWeakReferences();
1601 if (sOuterWindowsById) {
1602 sOuterWindowsById->Remove(tmp->mWindowID);
1603 }
1604
1605 NS_IMPL_CYCLE_COLLECTION_UNLINK(mContext)ImplCycleCollectionUnlink(tmp->mContext);
1606
1607 NS_IMPL_CYCLE_COLLECTION_UNLINK(mControllers)ImplCycleCollectionUnlink(tmp->mControllers);
1608 NS_IMPL_CYCLE_COLLECTION_UNLINK(mArguments)ImplCycleCollectionUnlink(tmp->mArguments);
1609
1610 NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocalStorage)ImplCycleCollectionUnlink(tmp->mLocalStorage);
1611 NS_IMPL_CYCLE_COLLECTION_UNLINK(mSuspendedDocs)ImplCycleCollectionUnlink(tmp->mSuspendedDocs);
1612 NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentPrincipal)ImplCycleCollectionUnlink(tmp->mDocumentPrincipal);
1613 NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentCookiePrincipal)ImplCycleCollectionUnlink(tmp->mDocumentCookiePrincipal);
1614 NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentStoragePrincipal)ImplCycleCollectionUnlink(tmp->mDocumentStoragePrincipal);
1615 NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentPartitionedPrincipal)ImplCycleCollectionUnlink(tmp->mDocumentPartitionedPrincipal
);
1616 NS_IMPL_CYCLE_COLLECTION_UNLINK(mDoc)ImplCycleCollectionUnlink(tmp->mDoc);
1617
1618 // Unlink stuff from nsPIDOMWindow
1619 NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeEventHandler)ImplCycleCollectionUnlink(tmp->mChromeEventHandler);
1620 NS_IMPL_CYCLE_COLLECTION_UNLINK(mParentTarget)ImplCycleCollectionUnlink(tmp->mParentTarget);
1621 NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessageManager)ImplCycleCollectionUnlink(tmp->mMessageManager);
1622 NS_IMPL_CYCLE_COLLECTION_UNLINK(mFrameElement)ImplCycleCollectionUnlink(tmp->mFrameElement);
1623
1624 NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocShell)ImplCycleCollectionUnlink(tmp->mDocShell);
1625 if (tmp->mBrowsingContext) {
1626 if (tmp->mBrowsingContext->GetUnbarrieredWindowProxy()) {
1627 nsGlobalWindowOuter* outer = nsOuterWindowProxy::GetOuterWindow(
1628 tmp->mBrowsingContext->GetUnbarrieredWindowProxy());
1629 // Check that the current WindowProxy object corresponds to this
1630 // nsGlobalWindowOuter, because we don't want to clear the WindowProxy if
1631 // we've replaced it with a cross-process WindowProxy.
1632 if (outer == tmp) {
1633 tmp->mBrowsingContext->ClearWindowProxy();
1634 }
1635 }
1636 tmp->mBrowsingContext = nullptr;
1637 }
1638
1639 tmp->UnlinkObjectsInGlobal();
1640
1641 if (tmp->IsChromeWindow()) {
1642 NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeFields.mBrowserDOMWindow)ImplCycleCollectionUnlink(tmp->mChromeFields.mBrowserDOMWindow
);
1643 }
1644
1645 NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPERtmp->ReleaseWrapper(p);
1646NS_IMPL_CYCLE_COLLECTION_UNLINK_END(void)tmp; }
1647
1648NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsGlobalWindowOuter)void nsGlobalWindowOuter::cycleCollection::Trace( void* p, const
TraceCallbacks& aCallbacks, void* aClosure) { nsGlobalWindowOuter
* tmp = DowncastCCParticipant<nsGlobalWindowOuter>(p);
1649 NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPERtmp->TraceWrapper(aCallbacks, aClosure);
1650NS_IMPL_CYCLE_COLLECTION_TRACE_END(void)tmp; }
1651
1652bool nsGlobalWindowOuter::IsBlackForCC(bool aTracingNeeded) {
1653 if (!nsCCUncollectableMarker::sGeneration) {
1654 return false;
1655 }
1656
1657 // Unlike most wrappers, the outer window wrapper is not a wrapper for
1658 // the outer window. Instead, the outer window wrapper holds the inner
1659 // window binding object, which in turn holds the nsGlobalWindowInner, which
1660 // has a strong reference to the nsGlobalWindowOuter. We're using the
1661 // mInnerWindow pointer as a flag for that whole chain.
1662 return (nsCCUncollectableMarker::InGeneration(GetMarkedCCGeneration()) ||
1663 (mInnerWindow && HasKnownLiveWrapper())) &&
1664 (!aTracingNeeded || HasNothingToTrace(ToSupports(this)));
1665}
1666
1667//*****************************************************************************
1668// nsGlobalWindowOuter::nsIScriptGlobalObject
1669//*****************************************************************************
1670
1671bool nsGlobalWindowOuter::ShouldResistFingerprinting(RFPTarget aTarget) const {
1672 if (mDoc) {
1673 return mDoc->ShouldResistFingerprinting(aTarget);
1674 }
1675 return nsContentUtils::ShouldResistFingerprinting(
1676 "If we do not have a document then we do not have any context"
1677 "to make an informed RFP choice, so we fall back to the global pref",
1678 aTarget);
1679}
1680
1681OriginTrials nsGlobalWindowOuter::Trials() const {
1682 return mInnerWindow ? nsGlobalWindowInner::Cast(mInnerWindow)->Trials()
1683 : OriginTrials();
1684}
1685
1686FontFaceSet* nsGlobalWindowOuter::GetFonts() {
1687 if (mDoc) {
1688 return mDoc->Fonts();
1689 }
1690 return nullptr;
1691}
1692
1693nsresult nsGlobalWindowOuter::EnsureScriptEnvironment() {
1694 if (GetWrapperPreserveColor()) {
1695 return NS_OK;
1696 }
1697
1698 NS_ENSURE_STATE(!mCleanedUp)do { if ((__builtin_expect(!!(!(!mCleanedUp)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "!mCleanedUp" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 1698); return NS_ERROR_UNEXPECTED; } } while (false)
;
1699
1700 NS_ASSERTION(!GetCurrentInnerWindowInternal(this),do { if (!(!GetCurrentInnerWindowInternal(this))) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "No cached wrapper, but we have an inner window?"
, "!GetCurrentInnerWindowInternal(this)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 1701); MOZ_PretendNoReturn(); } } while (0)
1701 "No cached wrapper, but we have an inner window?")do { if (!(!GetCurrentInnerWindowInternal(this))) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "No cached wrapper, but we have an inner window?"
, "!GetCurrentInnerWindowInternal(this)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 1701); MOZ_PretendNoReturn(); } } while (0)
;
1702 NS_ASSERTION(!mContext, "Will overwrite mContext!")do { if (!(!mContext)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Will overwrite mContext!"
, "!mContext", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 1702); MOZ_PretendNoReturn(); } } while (0)
;
1703
1704 // If this window is an [i]frame, don't bother GC'ing when the frame's context
1705 // is destroyed since a GC will happen when the frameset or host document is
1706 // destroyed anyway.
1707 mContext = new nsJSContext(mBrowsingContext->IsTop(), this);
1708 return NS_OK;
1709}
1710
1711nsIScriptContext* nsGlobalWindowOuter::GetScriptContext() { return mContext; }
1712
1713bool nsGlobalWindowOuter::WouldReuseInnerWindow(Document* aNewDocument) {
1714 // We reuse the inner window when:
1715 // a. We are currently at our original document.
1716 // b. At least one of the following conditions are true:
1717 // -- The new document is the same as the old document. This means that we're
1718 // getting called from document.open().
1719 // -- The new document has the same origin as what we have loaded right now.
1720
1721 if (!mDoc || !aNewDocument) {
1722 return false;
1723 }
1724
1725 if (!mDoc->IsInitialDocument()) {
1726 return false;
1727 }
1728
1729#ifdef DEBUG1
1730 {
1731 nsCOMPtr<nsIURI> uri;
1732 NS_GetURIWithoutRef(mDoc->GetDocumentURI(), getter_AddRefs(uri));
1733 NS_ASSERTION(NS_IsAboutBlank(uri), "How'd this happen?")do { if (!(NS_IsAboutBlank(uri))) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "How'd this happen?", "NS_IsAboutBlank(uri)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 1733); MOZ_PretendNoReturn(); } } while (0)
;
1734 }
1735#endif
1736
1737 // Great, we're the original document, check for one of the other
1738 // conditions.
1739
1740 if (mDoc == aNewDocument) {
1741 return true;
1742 }
1743
1744 if (aNewDocument->IsStaticDocument()) {
1745 return false;
1746 }
1747
1748 if (BasePrincipal::Cast(mDoc->NodePrincipal())
1749 ->FastEqualsConsideringDomain(aNewDocument->NodePrincipal())) {
1750 // The origin is the same.
1751 return true;
1752 }
1753
1754 return false;
1755}
1756
1757void nsGlobalWindowOuter::SetInitialPrincipal(
1758 nsIPrincipal* aNewWindowPrincipal, nsIContentSecurityPolicy* aCSP,
1759 const Maybe<nsILoadInfo::CrossOriginEmbedderPolicy>& aCOEP) {
1760 // We should never create windows with an expanded principal.
1761 // If we have a system principal, make sure we're not using it for a content
1762 // docshell.
1763 // NOTE: Please keep this logic in sync with
1764 // nsAppShellService::JustCreateTopWindow
1765 if (nsContentUtils::IsExpandedPrincipal(aNewWindowPrincipal) ||
1766 (aNewWindowPrincipal->IsSystemPrincipal() &&
1767 GetBrowsingContext()->IsContent())) {
1768 aNewWindowPrincipal = nullptr;
1769 }
1770
1771 // If there's an existing document, bail if it either:
1772 if (mDoc) {
1773 // (a) is not an initial about:blank document, or
1774 if (!mDoc->IsInitialDocument()) return;
1775 // (b) already has the correct principal.
1776 if (mDoc->NodePrincipal() == aNewWindowPrincipal) return;
1777
1778#ifdef DEBUG1
1779 // If we have a document loaded at this point, it had better be about:blank.
1780 // Otherwise, something is really weird. An about:blank page has a
1781 // NullPrincipal.
1782 bool isNullPrincipal;
1783 MOZ_ASSERT(NS_SUCCEEDED(mDoc->NodePrincipal()->GetIsNullPrincipal(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(mDoc->
NodePrincipal()->GetIsNullPrincipal( &isNullPrincipal)
)), 1))) && isNullPrincipal)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(((bool)(__builtin_expect(!!(
!NS_FAILED_impl(mDoc->NodePrincipal()->GetIsNullPrincipal
( &isNullPrincipal))), 1))) && isNullPrincipal)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("((bool)(__builtin_expect(!!(!NS_FAILED_impl(mDoc->NodePrincipal()->GetIsNullPrincipal( &isNullPrincipal))), 1))) && isNullPrincipal"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 1785); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(mDoc->NodePrincipal()->GetIsNullPrincipal( &isNullPrincipal))), 1))) && isNullPrincipal"
")"); do { *((volatile int*)__null) = 1785; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1784 &isNullPrincipal)) &&do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(mDoc->
NodePrincipal()->GetIsNullPrincipal( &isNullPrincipal)
)), 1))) && isNullPrincipal)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(((bool)(__builtin_expect(!!(
!NS_FAILED_impl(mDoc->NodePrincipal()->GetIsNullPrincipal
( &isNullPrincipal))), 1))) && isNullPrincipal)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("((bool)(__builtin_expect(!!(!NS_FAILED_impl(mDoc->NodePrincipal()->GetIsNullPrincipal( &isNullPrincipal))), 1))) && isNullPrincipal"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 1785); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(mDoc->NodePrincipal()->GetIsNullPrincipal( &isNullPrincipal))), 1))) && isNullPrincipal"
")"); do { *((volatile int*)__null) = 1785; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1785 isNullPrincipal)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(mDoc->
NodePrincipal()->GetIsNullPrincipal( &isNullPrincipal)
)), 1))) && isNullPrincipal)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(((bool)(__builtin_expect(!!(
!NS_FAILED_impl(mDoc->NodePrincipal()->GetIsNullPrincipal
( &isNullPrincipal))), 1))) && isNullPrincipal)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("((bool)(__builtin_expect(!!(!NS_FAILED_impl(mDoc->NodePrincipal()->GetIsNullPrincipal( &isNullPrincipal))), 1))) && isNullPrincipal"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 1785); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(mDoc->NodePrincipal()->GetIsNullPrincipal( &isNullPrincipal))), 1))) && isNullPrincipal"
")"); do { *((volatile int*)__null) = 1785; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1786#endif
1787 }
1788
1789 // Use the subject (or system) principal as the storage principal too until
1790 // the new window finishes navigating and gets a real storage principal.
1791 nsDocShell::Cast(GetDocShell())
1792 ->CreateAboutBlankDocumentViewer(aNewWindowPrincipal, aNewWindowPrincipal,
1793 aCSP, nullptr,
1794 /* aIsInitialDocument */ true, aCOEP);
1795
1796 if (mDoc) {
1797 MOZ_ASSERT(mDoc->IsInitialDocument(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDoc->IsInitialDocument())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mDoc->IsInitialDocument()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mDoc->IsInitialDocument()" " (" "document should be initial document"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 1798); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDoc->IsInitialDocument()"
") (" "document should be initial document" ")"); do { *((volatile
int*)__null) = 1798; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
1798 "document should be initial document")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDoc->IsInitialDocument())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mDoc->IsInitialDocument()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mDoc->IsInitialDocument()" " (" "document should be initial document"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 1798); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDoc->IsInitialDocument()"
") (" "document should be initial document" ")"); do { *((volatile
int*)__null) = 1798; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
1799 }
1800
1801 RefPtr<PresShell> presShell = GetDocShell()->GetPresShell();
1802 if (presShell && !presShell->DidInitialize()) {
1803 // Ensure that if someone plays with this document they will get
1804 // layout happening.
1805 presShell->Initialize();
1806 }
1807}
1808
1809#define WINDOWSTATEHOLDER_IID{ 0x0b917c3e, 0xbd50, 0x4683, { 0xaf, 0xc9, 0xc7, 0x81, 0x07,
0xae, 0x33, 0x26 } }
\
1810 { \
1811 0x0b917c3e, 0xbd50, 0x4683, { \
1812 0xaf, 0xc9, 0xc7, 0x81, 0x07, 0xae, 0x33, 0x26 \
1813 } \
1814 }
1815
1816class WindowStateHolder final : public nsISupports {
1817 public:
1818 NS_DECLARE_STATIC_IID_ACCESSOR(WINDOWSTATEHOLDER_IID)template <typename T, typename U> struct COMTypeInfo;
1819 NS_DECL_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override; using HasThreadSafeRefCnt = std::false_type;
protected: nsAutoRefCnt mRefCnt; nsAutoOwningThread _mOwningThread
; public:
1820
1821 explicit WindowStateHolder(nsGlobalWindowInner* aWindow);
1822
1823 nsGlobalWindowInner* GetInnerWindow() { return mInnerWindow; }
1824
1825 void DidRestoreWindow() {
1826 mInnerWindow = nullptr;
1827 mInnerWindowReflector = nullptr;
1828 }
1829
1830 protected:
1831 ~WindowStateHolder();
1832
1833 nsGlobalWindowInner* mInnerWindow;
1834 // We hold onto this to make sure the inner window doesn't go away. The outer
1835 // window ends up recalculating it anyway.
1836 JS::PersistentRooted<JSObject*> mInnerWindowReflector;
1837};
1838
1839NS_DEFINE_STATIC_IID_ACCESSOR(WindowStateHolder, WINDOWSTATEHOLDER_IID)template <typename T> struct WindowStateHolder::COMTypeInfo
<WindowStateHolder, T> { static const nsIID kIID __attribute__
((visibility("hidden"))); }; template <typename T> const
nsIID WindowStateHolder::COMTypeInfo<WindowStateHolder, T
>::kIID __attribute__((visibility("hidden"))) = { 0x0b917c3e
, 0xbd50, 0x4683, { 0xaf, 0xc9, 0xc7, 0x81, 0x07, 0xae, 0x33,
0x26 } };
1840
1841WindowStateHolder::WindowStateHolder(nsGlobalWindowInner* aWindow)
1842 : mInnerWindow(aWindow),
1843 mInnerWindowReflector(RootingCx(), aWindow->GetWrapper()) {
1844 MOZ_ASSERT(aWindow, "null window")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aWindow)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aWindow))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aWindow" " (" "null window"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 1844); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWindow" ") ("
"null window" ")"); do { *((volatile int*)__null) = 1844; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
1845
1846 aWindow->Suspend();
1847
1848 // When a global goes into the bfcache, we disable script.
1849 xpc::Scriptability::Get(mInnerWindowReflector).SetWindowAllowsScript(false);
1850}
1851
1852WindowStateHolder::~WindowStateHolder() {
1853 if (mInnerWindow) {
1854 // This window was left in the bfcache and is now going away. We need to
1855 // free it up.
1856 // Note that FreeInnerObjects may already have been called on the
1857 // inner window if its outer has already had SetDocShell(null)
1858 // called.
1859 mInnerWindow->FreeInnerObjects();
1860 }
1861}
1862
1863NS_IMPL_ISUPPORTS(WindowStateHolder, WindowStateHolder)MozExternalRefCountType WindowStateHolder::AddRef(void) { static_assert
(!std::is_destructible_v<WindowStateHolder>, "Reference-counted class "
"WindowStateHolder" " should not have a public destructor. "
"Make this class's destructor non-public"); do { static_assert
( mozilla::detail::AssertionConditionType<decltype(int32_t
(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 1863); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
1863; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("WindowStateHolder" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("WindowStateHolder" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"WindowStateHolder\" != nullptr" " (" "Must specify a name"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 1863); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WindowStateHolder\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 1863; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("WindowStateHolder" " not thread-safe"); nsrefcnt
count = ++mRefCnt; NS_LogAddRef((this), (count), ("WindowStateHolder"
), (uint32_t)(sizeof(*this))); return count; } MozExternalRefCountType
WindowStateHolder::Release(void) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(int32_t(mRefCnt)
> 0)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(int32_t(mRefCnt) > 0))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 1863); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 1863
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("WindowStateHolder" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("WindowStateHolder" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"WindowStateHolder\" != nullptr" " (" "Must specify a name"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 1863); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"WindowStateHolder\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 1863; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("WindowStateHolder" " not thread-safe"); const
char* const nametmp = "WindowStateHolder"; nsrefcnt count = --
mRefCnt; NS_LogRelease((this), (count), (nametmp)); if (count
== 0) { mRefCnt = 1; delete (this); return 0; } return count
; } nsresult WindowStateHolder::QueryInterface(const nsIID&
aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 1863); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(1 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<WindowStateHolder, WindowStateHolder>
, int32_t( reinterpret_cast<char*>(static_cast<WindowStateHolder
*>((WindowStateHolder*)0x1000)) - reinterpret_cast<char
*>((WindowStateHolder*)0x1000))}, {&mozilla::detail::kImplementedIID
<WindowStateHolder, nsISupports>, int32_t(reinterpret_cast
<char*>(static_cast<nsISupports*>( static_cast<
WindowStateHolder*>((WindowStateHolder*)0x1000))) - reinterpret_cast
<char*>((WindowStateHolder*)0x1000))}, { nullptr, 0 } }
; static_assert((sizeof(table) / sizeof(table[0])) > 1, "need at least 1 interface"
); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID
, aInstancePtr, table); return rv; }
1864
1865bool nsGlobalWindowOuter::ComputeIsSecureContext(Document* aDocument,
1866 SecureContextFlags aFlags) {
1867 nsCOMPtr<nsIPrincipal> principal = aDocument->NodePrincipal();
1868 if (principal->IsSystemPrincipal()) {
1869 return true;
1870 }
1871
1872 // Implement https://w3c.github.io/webappsec-secure-contexts/#settings-object
1873 // With some modifications to allow for aFlags.
1874
1875 bool hadNonSecureContextCreator = false;
1876
1877 if (WindowContext* parentWindow =
1878 GetBrowsingContext()->GetParentWindowContext()) {
1879 hadNonSecureContextCreator = !parentWindow->GetIsSecureContext();
1880 }
1881
1882 if (hadNonSecureContextCreator) {
1883 return false;
1884 }
1885
1886 if (nsContentUtils::HttpsStateIsModern(aDocument)) {
1887 return true;
1888 }
1889
1890 if (principal->GetIsNullPrincipal()) {
1891 // If the NullPrincipal has a valid precursor URI we want to use it to
1892 // construct the principal otherwise we fall back to the original document
1893 // URI.
1894 nsCOMPtr<nsIPrincipal> precursorPrin = principal->GetPrecursorPrincipal();
1895 nsCOMPtr<nsIURI> uri = precursorPrin ? precursorPrin->GetURI() : nullptr;
1896 if (!uri) {
1897 uri = aDocument->GetOriginalURI();
1898 }
1899 // IsOriginPotentiallyTrustworthy doesn't care about origin attributes so
1900 // it doesn't actually matter what we use here, but reusing the document
1901 // principal's attributes is convenient.
1902 const OriginAttributes& attrs = principal->OriginAttributesRef();
1903 // CreateContentPrincipal correctly gets a useful principal for blob: and
1904 // other URI_INHERITS_SECURITY_CONTEXT URIs.
1905 principal = BasePrincipal::CreateContentPrincipal(uri, attrs);
1906 if (NS_WARN_IF(!principal)NS_warn_if_impl(!principal, "!principal", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 1906)
) {
1907 return false;
1908 }
1909 }
1910
1911 return principal->GetIsOriginPotentiallyTrustworthy();
1912}
1913
1914static bool InitializeLegacyNetscapeObject(JSContext* aCx,
1915 JS::Handle<JSObject*> aGlobal) {
1916 JSAutoRealm ar(aCx, aGlobal);
1917
1918 // Note: MathJax depends on window.netscape being exposed. See bug 791526.
1919 JS::Rooted<JSObject*> obj(aCx);
1920 obj = JS_DefineObject(aCx, aGlobal, "netscape", nullptr);
1921 NS_ENSURE_TRUE(obj, false)do { if ((__builtin_expect(!!(!(obj)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "obj" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 1921); return false; } } while (false)
;
1922
1923 obj = JS_DefineObject(aCx, obj, "security", nullptr);
1924 NS_ENSURE_TRUE(obj, false)do { if ((__builtin_expect(!!(!(obj)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "obj" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 1924); return false; } } while (false)
;
1925
1926 return true;
1927}
1928
1929struct MOZ_STACK_CLASS CompartmentFinderState {
1930 explicit CompartmentFinderState(nsIPrincipal* aPrincipal)
1931 : principal(aPrincipal), compartment(nullptr) {}
1932
1933 // Input: we look for a compartment which is same-origin with the
1934 // given principal.
1935 nsIPrincipal* principal;
1936
1937 // Output: We set this member if we find a compartment.
1938 JS::Compartment* compartment;
1939};
1940
1941static JS::CompartmentIterResult FindSameOriginCompartment(
1942 JSContext* aCx, void* aData, JS::Compartment* aCompartment) {
1943 auto* data = static_cast<CompartmentFinderState*>(aData);
1944 MOZ_ASSERT(!data->compartment, "Why are we getting called?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!data->compartment)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!data->compartment))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("!data->compartment"
" (" "Why are we getting called?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 1944); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!data->compartment"
") (" "Why are we getting called?" ")"); do { *((volatile int
*)__null) = 1944; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
1945
1946 // If this compartment is not safe to share across globals, don't do
1947 // anything with it; in particular we should not be getting a
1948 // CompartmentPrivate from such a compartment, because it may be in
1949 // the middle of being collected and its CompartmentPrivate may no
1950 // longer be valid.
1951 if (!js::IsSharableCompartment(aCompartment)) {
1952 return JS::CompartmentIterResult::KeepGoing;
1953 }
1954
1955 auto* compartmentPrivate = xpc::CompartmentPrivate::Get(aCompartment);
1956 if (!compartmentPrivate->CanShareCompartmentWith(data->principal)) {
1957 // Can't reuse this one, keep going.
1958 return JS::CompartmentIterResult::KeepGoing;
1959 }
1960
1961 // We have a winner!
1962 data->compartment = aCompartment;
1963 return JS::CompartmentIterResult::Stop;
1964}
1965
1966static JS::RealmCreationOptions& SelectZone(
1967 JSContext* aCx, nsIPrincipal* aPrincipal, nsGlobalWindowInner* aNewInner,
1968 JS::RealmCreationOptions& aOptions) {
1969 // Use the shared system compartment for chrome windows.
1970 if (aPrincipal->IsSystemPrincipal()) {
1971 return aOptions.setExistingCompartment(xpc::PrivilegedJunkScope());
1972 }
1973
1974 BrowsingContext* bc = aNewInner->GetBrowsingContext();
1975 if (bc->IsTop()) {
1976 // We're a toplevel load. Use a new zone. This way, when we do
1977 // zone-based compartment sharing we won't share compartments
1978 // across navigations.
1979 return aOptions.setNewCompartmentAndZone();
1980 }
1981
1982 // Find the in-process ancestor highest in the hierarchy.
1983 nsGlobalWindowInner* ancestor = nullptr;
1984 for (WindowContext* wc = bc->GetParentWindowContext(); wc;
1985 wc = wc->GetParentWindowContext()) {
1986 if (nsGlobalWindowInner* win = wc->GetInnerWindow()) {
1987 ancestor = win;
1988 }
1989 }
1990
1991 // If we have an ancestor window, use its zone.
1992 if (ancestor && ancestor->GetGlobalJSObject()) {
1993 JS::Zone* zone = JS::GetObjectZone(ancestor->GetGlobalJSObject());
1994 // Now try to find an existing compartment that's same-origin
1995 // with our principal.
1996 CompartmentFinderState data(aPrincipal);
1997 JS_IterateCompartmentsInZone(aCx, zone, &data, FindSameOriginCompartment);
1998 if (data.compartment) {
1999 return aOptions.setExistingCompartment(data.compartment);
2000 }
2001 return aOptions.setNewCompartmentInExistingZone(
2002 ancestor->GetGlobalJSObject());
2003 }
2004
2005 return aOptions.setNewCompartmentAndZone();
2006}
2007
2008/**
2009 * Create a new global object that will be used for an inner window.
2010 * Return the native global and an nsISupports 'holder' that can be used
2011 * to manage the lifetime of it.
2012 */
2013static nsresult CreateNativeGlobalForInner(
2014 JSContext* aCx, nsGlobalWindowInner* aNewInner, Document* aDocument,
2015 JS::MutableHandle<JSObject*> aGlobal, bool aIsSecureContext,
2016 bool aDefineSharedArrayBufferConstructor) {
2017 MOZ_ASSERT(aCx)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aCx)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aCx))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aCx", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2017); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aCx" ")"); do
{ *((volatile int*)__null) = 2017; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
2018 MOZ_ASSERT(aNewInner)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aNewInner)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aNewInner))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aNewInner", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2018); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNewInner" ")"
); do { *((volatile int*)__null) = 2018; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2019
2020 nsCOMPtr<nsIURI> uri = aDocument->GetDocumentURI();
2021 nsCOMPtr<nsIPrincipal> principal = aDocument->NodePrincipal();
2022 MOZ_ASSERT(principal)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(principal)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(principal))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("principal", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2022); AnnotateMozCrashReason("MOZ_ASSERT" "(" "principal" ")"
); do { *((volatile int*)__null) = 2022; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2023
2024 // DOMWindow with nsEP is not supported, we have to make sure
2025 // no one creates one accidentally.
2026 nsCOMPtr<nsIExpandedPrincipal> nsEP = do_QueryInterface(principal);
2027 MOZ_RELEASE_ASSERT(!nsEP, "DOMWindow with nsEP is not supported")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!nsEP)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(!nsEP))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("!nsEP" " (" "DOMWindow with nsEP is not supported"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2027); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "!nsEP"
") (" "DOMWindow with nsEP is not supported" ")"); do { *((volatile
int*)__null) = 2027; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2028
2029 JS::RealmOptions options;
2030 JS::RealmCreationOptions& creationOptions = options.creationOptions();
2031
2032 SelectZone(aCx, principal, aNewInner, creationOptions);
2033
2034 // Define the SharedArrayBuffer global constructor property only if shared
2035 // memory may be used and structured-cloned (e.g. through postMessage).
2036 //
2037 // When the global constructor property isn't defined, the SharedArrayBuffer
2038 // constructor can still be reached through Web Assembly. Omitting the global
2039 // property just prevents feature-tests from being misled. See bug 1624266.
2040 creationOptions.setDefineSharedArrayBufferConstructor(
2041 aDefineSharedArrayBufferConstructor);
2042
2043 xpc::InitGlobalObjectOptions(
2044 options, principal->IsSystemPrincipal(), aIsSecureContext,
2045 aDocument->ShouldResistFingerprinting(RFPTarget::JSDateTimeUTC),
2046 aDocument->ShouldResistFingerprinting(RFPTarget::JSMathFdlibm),
2047 aDocument->ShouldResistFingerprinting(RFPTarget::JSLocale));
2048
2049 // Determine if we need the Components object.
2050 bool needComponents = principal->IsSystemPrincipal();
2051 uint32_t flags = needComponents ? 0 : xpc::OMIT_COMPONENTS_OBJECT;
2052 flags |= xpc::DONT_FIRE_ONNEWGLOBALHOOK;
2053
2054 if (!Window_Binding::Wrap(aCx, aNewInner, aNewInner, options,
2055 nsJSPrincipals::get(principal), aGlobal) ||
2056 !xpc::InitGlobalObject(aCx, aGlobal, flags)) {
2057 return NS_ERROR_FAILURE;
2058 }
2059
2060 MOZ_ASSERT(aNewInner->GetWrapperPreserveColor() == aGlobal)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aNewInner->GetWrapperPreserveColor() == aGlobal)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aNewInner->GetWrapperPreserveColor() == aGlobal))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aNewInner->GetWrapperPreserveColor() == aGlobal"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2060); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNewInner->GetWrapperPreserveColor() == aGlobal"
")"); do { *((volatile int*)__null) = 2060; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2061
2062 // Set the location information for the new global, so that tools like
2063 // about:memory may use that information
2064 xpc::SetLocationForGlobal(aGlobal, uri);
2065
2066 if (!InitializeLegacyNetscapeObject(aCx, aGlobal)) {
2067 return NS_ERROR_FAILURE;
2068 }
2069
2070 return NS_OK;
2071}
2072
2073nsresult nsGlobalWindowOuter::SetNewDocument(Document* aDocument,
2074 nsISupports* aState,
2075 bool aForceReuseInnerWindow,
2076 WindowGlobalChild* aActor) {
2077 MOZ_ASSERT(mDocumentPrincipal == nullptr,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDocumentPrincipal == nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mDocumentPrincipal == nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mDocumentPrincipal == nullptr" " (" "mDocumentPrincipal prematurely set!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2078); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDocumentPrincipal == nullptr"
") (" "mDocumentPrincipal prematurely set!" ")"); do { *((volatile
int*)__null) = 2078; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
2078 "mDocumentPrincipal prematurely set!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDocumentPrincipal == nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mDocumentPrincipal == nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mDocumentPrincipal == nullptr" " (" "mDocumentPrincipal prematurely set!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2078); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDocumentPrincipal == nullptr"
") (" "mDocumentPrincipal prematurely set!" ")"); do { *((volatile
int*)__null) = 2078; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2079 MOZ_ASSERT(mDocumentCookiePrincipal == nullptr,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDocumentCookiePrincipal == nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mDocumentCookiePrincipal == nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mDocumentCookiePrincipal == nullptr" " (" "mDocumentCookiePrincipal prematurely set!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2080); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDocumentCookiePrincipal == nullptr"
") (" "mDocumentCookiePrincipal prematurely set!" ")"); do {
*((volatile int*)__null) = 2080; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
2080 "mDocumentCookiePrincipal prematurely set!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDocumentCookiePrincipal == nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mDocumentCookiePrincipal == nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mDocumentCookiePrincipal == nullptr" " (" "mDocumentCookiePrincipal prematurely set!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2080); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDocumentCookiePrincipal == nullptr"
") (" "mDocumentCookiePrincipal prematurely set!" ")"); do {
*((volatile int*)__null) = 2080; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
2081 MOZ_ASSERT(mDocumentStoragePrincipal == nullptr,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDocumentStoragePrincipal == nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mDocumentStoragePrincipal ==
nullptr))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mDocumentStoragePrincipal == nullptr" " (" "mDocumentStoragePrincipal prematurely set!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2082); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDocumentStoragePrincipal == nullptr"
") (" "mDocumentStoragePrincipal prematurely set!" ")"); do {
*((volatile int*)__null) = 2082; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
2082 "mDocumentStoragePrincipal prematurely set!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDocumentStoragePrincipal == nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mDocumentStoragePrincipal ==
nullptr))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mDocumentStoragePrincipal == nullptr" " (" "mDocumentStoragePrincipal prematurely set!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2082); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDocumentStoragePrincipal == nullptr"
") (" "mDocumentStoragePrincipal prematurely set!" ")"); do {
*((volatile int*)__null) = 2082; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
2083 MOZ_ASSERT(mDocumentPartitionedPrincipal == nullptr,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDocumentPartitionedPrincipal == nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mDocumentPartitionedPrincipal == nullptr))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("mDocumentPartitionedPrincipal == nullptr"
" (" "mDocumentPartitionedPrincipal prematurely set!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2084); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDocumentPartitionedPrincipal == nullptr"
") (" "mDocumentPartitionedPrincipal prematurely set!" ")");
do { *((volatile int*)__null) = 2084; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2084 "mDocumentPartitionedPrincipal prematurely set!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDocumentPartitionedPrincipal == nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mDocumentPartitionedPrincipal == nullptr))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("mDocumentPartitionedPrincipal == nullptr"
" (" "mDocumentPartitionedPrincipal prematurely set!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2084); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDocumentPartitionedPrincipal == nullptr"
") (" "mDocumentPartitionedPrincipal prematurely set!" ")");
do { *((volatile int*)__null) = 2084; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2085 MOZ_ASSERT(aDocument)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDocument)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDocument))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aDocument", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2085); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocument" ")"
); do { *((volatile int*)__null) = 2085; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2086
2087 // Bail out early if we're in process of closing down the window.
2088 NS_ENSURE_STATE(!mCleanedUp)do { if ((__builtin_expect(!!(!(!mCleanedUp)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "!mCleanedUp" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2088); return NS_ERROR_UNEXPECTED; } } while (false)
;
2089
2090 NS_ASSERTION(!GetCurrentInnerWindow() ||do { if (!(!GetCurrentInnerWindow() || GetCurrentInnerWindow(
)->GetExtantDoc() == mDoc)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Uh, mDoc doesn't match the current inner window " "document!"
, "!GetCurrentInnerWindow() || GetCurrentInnerWindow()->GetExtantDoc() == mDoc"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2093); MOZ_PretendNoReturn(); } } while (0)
2091 GetCurrentInnerWindow()->GetExtantDoc() == mDoc,do { if (!(!GetCurrentInnerWindow() || GetCurrentInnerWindow(
)->GetExtantDoc() == mDoc)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Uh, mDoc doesn't match the current inner window " "document!"
, "!GetCurrentInnerWindow() || GetCurrentInnerWindow()->GetExtantDoc() == mDoc"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2093); MOZ_PretendNoReturn(); } } while (0)
2092 "Uh, mDoc doesn't match the current inner window "do { if (!(!GetCurrentInnerWindow() || GetCurrentInnerWindow(
)->GetExtantDoc() == mDoc)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Uh, mDoc doesn't match the current inner window " "document!"
, "!GetCurrentInnerWindow() || GetCurrentInnerWindow()->GetExtantDoc() == mDoc"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2093); MOZ_PretendNoReturn(); } } while (0)
2093 "document!")do { if (!(!GetCurrentInnerWindow() || GetCurrentInnerWindow(
)->GetExtantDoc() == mDoc)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Uh, mDoc doesn't match the current inner window " "document!"
, "!GetCurrentInnerWindow() || GetCurrentInnerWindow()->GetExtantDoc() == mDoc"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2093); MOZ_PretendNoReturn(); } } while (0)
;
2094 bool wouldReuseInnerWindow = WouldReuseInnerWindow(aDocument);
2095 if (aForceReuseInnerWindow && !wouldReuseInnerWindow && mDoc &&
2096 mDoc->NodePrincipal() != aDocument->NodePrincipal()) {
2097 NS_ERROR("Attempted forced inner window reuse while changing principal")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "Attempted forced inner window reuse while changing principal"
, "Error", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2097); MOZ_PretendNoReturn(); } while (0)
;
2098 return NS_ERROR_UNEXPECTED;
2099 }
2100
2101 if (!mBrowsingContext->AncestorsAreCurrent()) {
2102 return NS_ERROR_NOT_AVAILABLE;
2103 }
2104
2105 RefPtr<Document> oldDoc = mDoc;
2106 MOZ_RELEASE_ASSERT(oldDoc != aDocument)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(oldDoc != aDocument)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(oldDoc != aDocument))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("oldDoc != aDocument"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2106); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "oldDoc != aDocument"
")"); do { *((volatile int*)__null) = 2106; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2107
2108 AutoJSAPI jsapi;
2109 jsapi.Init();
2110 JSContext* cx = jsapi.cx();
2111
2112 // Check if we're anywhere near the stack limit before we reach the
2113 // transplanting code, since it has no good way to handle errors. This uses
2114 // the untrusted script limit, which is not strictly necessary since no
2115 // actual script should run.
2116 js::AutoCheckRecursionLimit recursion(cx);
2117 if (!recursion.checkConservativeDontReport(cx)) {
2118 NS_WARNING("Overrecursion in SetNewDocument")NS_DebugBreak(NS_DEBUG_WARNING, "Overrecursion in SetNewDocument"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2118)
;
2119 return NS_ERROR_FAILURE;
2120 }
2121
2122 if (!mDoc) {
2123 // First document load.
2124
2125 // Get our private root. If it is equal to us, then we need to
2126 // attach our global key bindings that handles browser scrolling
2127 // and other browser commands.
2128 nsPIDOMWindowOuter* privateRoot = GetPrivateRoot();
2129
2130 if (privateRoot == this) {
2131 RootWindowGlobalKeyListener::AttachKeyHandler(mChromeEventHandler);
2132 }
2133 }
2134
2135 MaybeResetWindowName(aDocument);
2136
2137 /* No mDocShell means we're already been partially closed down. When that
2138 happens, setting status isn't a big requirement, so don't. (Doesn't happen
2139 under normal circumstances, but bug 49615 describes a case.) */
2140
2141 nsContentUtils::AddScriptRunner(
2142 NewRunnableMethod("nsGlobalWindowOuter::ClearStatus", this,
2143 &nsGlobalWindowOuter::ClearStatus));
2144
2145 // Sometimes, WouldReuseInnerWindow() returns true even if there's no inner
2146 // window (see bug 776497). Be safe.
2147 bool reUseInnerWindow = (aForceReuseInnerWindow || wouldReuseInnerWindow) &&
2148 GetCurrentInnerWindowInternal(this);
2149
2150 nsresult rv;
2151
2152 // We set mDoc even though this is an outer window to avoid
2153 // having to *always* reach into the inner window to find the
2154 // document.
2155 mDoc = aDocument;
2156
2157 nsDocShell::Cast(mDocShell)->MaybeRestoreWindowName();
2158
2159 // We drop the print request for the old document on the floor, it never made
2160 // it. We don't close the window here either even if we were asked to.
2161 mShouldDelayPrintUntilAfterLoad = true;
2162 mDelayedCloseForPrinting = false;
2163 mDelayedPrintUntilAfterLoad = false;
2164
2165 // Take this opportunity to clear mSuspendedDocs. Our old inner window is now
2166 // responsible for unsuspending it.
2167 mSuspendedDocs.Clear();
2168
2169#ifdef DEBUG1
2170 mLastOpenedURI = aDocument->GetDocumentURI();
2171#endif
2172
2173 RefPtr<nsGlobalWindowInner> currentInner =
2174 GetCurrentInnerWindowInternal(this);
2175
2176 if (currentInner && currentInner->mNavigator) {
2177 currentInner->mNavigator->OnNavigation();
2178 }
2179
2180 RefPtr<nsGlobalWindowInner> newInnerWindow;
2181 bool createdInnerWindow = false;
2182
2183 bool thisChrome = IsChromeWindow();
2184
2185 nsCOMPtr<WindowStateHolder> wsh = do_QueryInterface(aState);
2186 NS_ASSERTION(!aState || wsh,do { if (!(!aState || wsh)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "What kind of weird state are you giving me here?", "!aState || wsh"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2187); MOZ_PretendNoReturn(); } } while (0)
2187 "What kind of weird state are you giving me here?")do { if (!(!aState || wsh)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "What kind of weird state are you giving me here?", "!aState || wsh"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2187); MOZ_PretendNoReturn(); } } while (0)
;
2188
2189 bool doomCurrentInner = false;
2190
2191 // Only non-gray (i.e. exposed to JS) objects should be assigned to
2192 // newInnerGlobal.
2193 JS::Rooted<JSObject*> newInnerGlobal(cx);
2194 if (reUseInnerWindow) {
2195 // We're reusing the current inner window.
2196 NS_ASSERTION(!currentInner->IsFrozen(),do { if (!(!currentInner->IsFrozen())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "We should never be reusing a shared inner window", "!currentInner->IsFrozen()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2197); MOZ_PretendNoReturn(); } } while (0)
2197 "We should never be reusing a shared inner window")do { if (!(!currentInner->IsFrozen())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "We should never be reusing a shared inner window", "!currentInner->IsFrozen()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2197); MOZ_PretendNoReturn(); } } while (0)
;
2198 newInnerWindow = currentInner;
2199 newInnerGlobal = currentInner->GetWrapper();
2200
2201 // We're reusing the inner window, but this still counts as a navigation,
2202 // so all expandos and such defined on the outer window should go away.
2203 // Force all Xray wrappers to be recomputed.
2204 JS::Rooted<JSObject*> rootedObject(cx, GetWrapper());
2205 if (!JS_RefreshCrossCompartmentWrappers(cx, rootedObject)) {
2206 return NS_ERROR_FAILURE;
2207 }
2208
2209 // Inner windows are only reused for same-origin principals, but the
2210 // principals don't necessarily match exactly. Update the principal on the
2211 // realm to match the new document. NB: We don't just call
2212 // currentInner->RefreshRealmPrincipals() here because we haven't yet set
2213 // its mDoc to aDocument.
2214 JS::Realm* realm = js::GetNonCCWObjectRealm(newInnerGlobal);
2215#ifdef DEBUG1
2216 bool sameOrigin = false;
2217 nsIPrincipal* existing = nsJSPrincipals::get(JS::GetRealmPrincipals(realm));
2218 aDocument->NodePrincipal()->Equals(existing, &sameOrigin);
2219 MOZ_ASSERT(sameOrigin)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sameOrigin)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sameOrigin))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("sameOrigin", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2219); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sameOrigin"
")"); do { *((volatile int*)__null) = 2219; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2220#endif
2221 JS::SetRealmPrincipals(realm,
2222 nsJSPrincipals::get(aDocument->NodePrincipal()));
2223 } else {
2224 if (aState) {
2225 newInnerWindow = wsh->GetInnerWindow();
2226 newInnerGlobal = newInnerWindow->GetWrapper();
2227 } else {
2228 newInnerWindow = nsGlobalWindowInner::Create(this, thisChrome, aActor);
2229 if (StaticPrefs::dom_timeout_defer_during_load()) {
2230 // ensure the initial loading state is known
2231 newInnerWindow->SetActiveLoadingState(
2232 aDocument->GetReadyStateEnum() ==
2233 Document::ReadyState::READYSTATE_LOADING);
2234 }
2235
2236 // The outer window is automatically treated as frozen when we
2237 // null out the inner window. As a result, initializing classes
2238 // on the new inner won't end up reaching into the old inner
2239 // window for classes etc.
2240 //
2241 // [This happens with Object.prototype when XPConnect creates
2242 // a temporary global while initializing classes; the reason
2243 // being that xpconnect creates the temp global w/o a parent
2244 // and proto, which makes the JS engine look up classes in
2245 // cx->globalObject, i.e. this outer window].
2246
2247 mInnerWindow = nullptr;
2248
2249 mCreatingInnerWindow = true;
2250
2251 // The SharedArrayBuffer global constructor property should not be present
2252 // in a fresh global object when shared memory objects aren't allowed
2253 // (because COOP/COEP support isn't enabled, or because COOP/COEP don't
2254 // act to isolate this page to a separate process).
2255
2256 // Every script context we are initialized with must create a
2257 // new global.
2258 rv = CreateNativeGlobalForInner(
2259 cx, newInnerWindow, aDocument, &newInnerGlobal,
2260 ComputeIsSecureContext(aDocument),
2261 newInnerWindow->IsSharedMemoryAllowedInternal(
2262 aDocument->NodePrincipal()));
2263 NS_ASSERTION(do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1
))) && newInnerGlobal && newInnerWindow->GetWrapperPreserveColor
() == newInnerGlobal)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Failed to get script global"
, "NS_SUCCEEDED(rv) && newInnerGlobal && newInnerWindow->GetWrapperPreserveColor() == newInnerGlobal"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2266); MOZ_PretendNoReturn(); } } while (0)
2264 NS_SUCCEEDED(rv) && newInnerGlobal &&do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1
))) && newInnerGlobal && newInnerWindow->GetWrapperPreserveColor
() == newInnerGlobal)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Failed to get script global"
, "NS_SUCCEEDED(rv) && newInnerGlobal && newInnerWindow->GetWrapperPreserveColor() == newInnerGlobal"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2266); MOZ_PretendNoReturn(); } } while (0)
2265 newInnerWindow->GetWrapperPreserveColor() == newInnerGlobal,do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1
))) && newInnerGlobal && newInnerWindow->GetWrapperPreserveColor
() == newInnerGlobal)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Failed to get script global"
, "NS_SUCCEEDED(rv) && newInnerGlobal && newInnerWindow->GetWrapperPreserveColor() == newInnerGlobal"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2266); MOZ_PretendNoReturn(); } } while (0)
2266 "Failed to get script global")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1
))) && newInnerGlobal && newInnerWindow->GetWrapperPreserveColor
() == newInnerGlobal)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Failed to get script global"
, "NS_SUCCEEDED(rv) && newInnerGlobal && newInnerWindow->GetWrapperPreserveColor() == newInnerGlobal"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2266); MOZ_PretendNoReturn(); } } while (0)
;
2267
2268 mCreatingInnerWindow = false;
2269 createdInnerWindow = true;
2270
2271 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2271); return rv; } } while (false)
;
2272 }
2273
2274 if (currentInner && currentInner->GetWrapperPreserveColor()) {
2275 // Don't free objects on our current inner window if it's going to be
2276 // held in the bfcache.
2277 if (!currentInner->IsFrozen()) {
2278 doomCurrentInner = true;
2279 }
2280 }
2281
2282 mInnerWindow = newInnerWindow;
2283 MOZ_ASSERT(mInnerWindow)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mInnerWindow)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mInnerWindow))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("mInnerWindow", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2283); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mInnerWindow"
")"); do { *((volatile int*)__null) = 2283; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2284 mInnerWindow->TryToCacheTopInnerWindow();
2285
2286 if (!GetWrapperPreserveColor()) {
2287 JS::Rooted<JSObject*> outer(
2288 cx, NewOuterWindowProxy(cx, newInnerGlobal, thisChrome));
2289 NS_ENSURE_TRUE(outer, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(outer)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "outer" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2289); return NS_ERROR_FAILURE; } } while (false)
;
2290
2291 mBrowsingContext->CleanUpDanglingRemoteOuterWindowProxies(cx, &outer);
2292 MOZ_ASSERT(js::IsWindowProxy(outer))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(js::IsWindowProxy(outer))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(js::IsWindowProxy(outer)))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("js::IsWindowProxy(outer)"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2292); AnnotateMozCrashReason("MOZ_ASSERT" "(" "js::IsWindowProxy(outer)"
")"); do { *((volatile int*)__null) = 2292; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2293
2294 js::SetProxyReservedSlot(outer, OUTER_WINDOW_SLOT,
2295 JS::PrivateValue(ToSupports(this)));
2296
2297 // Inform the nsJSContext, which is the canonical holder of the outer.
2298 mContext->SetWindowProxy(outer);
2299
2300 SetWrapper(mContext->GetWindowProxy());
2301 } else {
2302 JS::Rooted<JSObject*> outerObject(
2303 cx, NewOuterWindowProxy(cx, newInnerGlobal, thisChrome));
2304 if (!outerObject) {
2305 NS_ERROR("out of memory")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "out of memory", "Error"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2305); MOZ_PretendNoReturn(); } while (0)
;
2306 return NS_ERROR_FAILURE;
2307 }
2308
2309 JS::Rooted<JSObject*> obj(cx, GetWrapper());
2310
2311 MOZ_ASSERT(js::IsWindowProxy(obj))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(js::IsWindowProxy(obj))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(js::IsWindowProxy(obj)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("js::IsWindowProxy(obj)"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2311); AnnotateMozCrashReason("MOZ_ASSERT" "(" "js::IsWindowProxy(obj)"
")"); do { *((volatile int*)__null) = 2311; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2312
2313 js::SetProxyReservedSlot(obj, OUTER_WINDOW_SLOT,
2314 JS::PrivateValue(nullptr));
2315 js::SetProxyReservedSlot(outerObject, OUTER_WINDOW_SLOT,
2316 JS::PrivateValue(nullptr));
2317 js::SetProxyReservedSlot(obj, HOLDER_WEAKMAP_SLOT, JS::UndefinedValue());
2318
2319 outerObject = xpc::TransplantObjectNukingXrayWaiver(cx, obj, outerObject);
2320
2321 if (!outerObject) {
2322 mBrowsingContext->ClearWindowProxy();
2323 NS_ERROR("unable to transplant wrappers, probably OOM")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "unable to transplant wrappers, probably OOM"
, "Error", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2323); MOZ_PretendNoReturn(); } while (0)
;
2324 return NS_ERROR_FAILURE;
2325 }
2326
2327 js::SetProxyReservedSlot(outerObject, OUTER_WINDOW_SLOT,
2328 JS::PrivateValue(ToSupports(this)));
2329
2330 SetWrapper(outerObject);
2331
2332 MOZ_ASSERT(JS::GetNonCCWObjectGlobal(outerObject) == newInnerGlobal)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(JS::GetNonCCWObjectGlobal(outerObject) == newInnerGlobal
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(JS::GetNonCCWObjectGlobal(outerObject) == newInnerGlobal
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"JS::GetNonCCWObjectGlobal(outerObject) == newInnerGlobal", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2332); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JS::GetNonCCWObjectGlobal(outerObject) == newInnerGlobal"
")"); do { *((volatile int*)__null) = 2332; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2333
2334 // Inform the nsJSContext, which is the canonical holder of the outer.
2335 mContext->SetWindowProxy(outerObject);
2336 }
2337
2338 // Enter the new global's realm.
2339 JSAutoRealm ar(cx, GetWrapperPreserveColor());
2340
2341 {
2342 JS::Rooted<JSObject*> outer(cx, GetWrapperPreserveColor());
2343 js::SetWindowProxy(cx, newInnerGlobal, outer);
2344 mBrowsingContext->SetWindowProxy(outer);
2345 }
2346
2347 // Set scriptability based on the state of the WindowContext.
2348 WindowContext* wc = mInnerWindow->GetWindowContext();
2349 bool allow =
2350 wc ? wc->CanExecuteScripts() : mBrowsingContext->CanExecuteScripts();
2351 xpc::Scriptability::Get(GetWrapperPreserveColor())
2352 .SetWindowAllowsScript(allow);
2353
2354 if (!aState) {
2355 // Get the "window" property once so it will be cached on our inner. We
2356 // have to do this here, not in binding code, because this has to happen
2357 // after we've created the outer window proxy and stashed it in the outer
2358 // nsGlobalWindowOuter, so GetWrapperPreserveColor() on that outer
2359 // nsGlobalWindowOuter doesn't return null and
2360 // nsGlobalWindowOuter::OuterObject works correctly.
2361 JS::Rooted<JS::Value> unused(cx);
2362 if (!JS_GetProperty(cx, newInnerGlobal, "window", &unused)) {
2363 NS_ERROR("can't create the 'window' property")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "can't create the 'window' property"
, "Error", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2363); MOZ_PretendNoReturn(); } while (0)
;
2364 return NS_ERROR_FAILURE;
2365 }
2366
2367 // And same thing for the "self" property.
2368 if (!JS_GetProperty(cx, newInnerGlobal, "self", &unused)) {
2369 NS_ERROR("can't create the 'self' property")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "can't create the 'self' property"
, "Error", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2369); MOZ_PretendNoReturn(); } while (0)
;
2370 return NS_ERROR_FAILURE;
2371 }
2372 }
2373 }
2374
2375 JSAutoRealm ar(cx, GetWrapperPreserveColor());
2376
2377 if (!aState && !reUseInnerWindow) {
2378 // Loading a new page and creating a new inner window, *not*
2379 // restoring from session history.
2380
2381 // Now that both the the inner and outer windows are initialized
2382 // let the script context do its magic to hook them together.
2383 MOZ_ASSERT(mContext->GetWindowProxy() == GetWrapperPreserveColor())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mContext->GetWindowProxy() == GetWrapperPreserveColor
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mContext->GetWindowProxy() == GetWrapperPreserveColor
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mContext->GetWindowProxy() == GetWrapperPreserveColor()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2383); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mContext->GetWindowProxy() == GetWrapperPreserveColor()"
")"); do { *((volatile int*)__null) = 2383; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2384#ifdef DEBUG1
2385 JS::Rooted<JSObject*> rootedJSObject(cx, GetWrapperPreserveColor());
2386 JS::Rooted<JSObject*> proto1(cx), proto2(cx);
2387 JS_GetPrototype(cx, rootedJSObject, &proto1);
2388 JS_GetPrototype(cx, newInnerGlobal, &proto2);
2389 NS_ASSERTION(proto1 == proto2,do { if (!(proto1 == proto2)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "outer and inner globals should have the same prototype", "proto1 == proto2"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2390); MOZ_PretendNoReturn(); } } while (0)
2390 "outer and inner globals should have the same prototype")do { if (!(proto1 == proto2)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "outer and inner globals should have the same prototype", "proto1 == proto2"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2390); MOZ_PretendNoReturn(); } } while (0)
;
2391#endif
2392
2393 mInnerWindow->SyncStateFromParentWindow();
2394 }
2395
2396 // Add an extra ref in case we release mContext during GC.
2397 nsCOMPtr<nsIScriptContext> kungFuDeathGrip(mContext);
2398
2399 // Make sure the inner's document is set correctly before we call
2400 // SetScriptGlobalObject, because that might try to examine document-dependent
2401 // state. Unfortunately, we can't do some of the other clearing/resetting
2402 // work we do below until after SetScriptGlobalObject(), because it might
2403 // depend on the document having the right scope object.
2404 if (aState) {
2405 MOZ_RELEASE_ASSERT(newInnerWindow->mDoc == aDocument)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(newInnerWindow->mDoc == aDocument)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(newInnerWindow->mDoc == aDocument
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"newInnerWindow->mDoc == aDocument", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2405); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "newInnerWindow->mDoc == aDocument"
")"); do { *((volatile int*)__null) = 2405; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2406 } else {
2407 if (reUseInnerWindow) {
2408 MOZ_RELEASE_ASSERT(newInnerWindow->mDoc != aDocument)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(newInnerWindow->mDoc != aDocument)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(newInnerWindow->mDoc != aDocument
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"newInnerWindow->mDoc != aDocument", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2408); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "newInnerWindow->mDoc != aDocument"
")"); do { *((volatile int*)__null) = 2408; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2409 }
2410 newInnerWindow->mDoc = aDocument;
2411 }
2412
2413 aDocument->SetScriptGlobalObject(newInnerWindow);
2414
2415 MOZ_RELEASE_ASSERT(newInnerWindow->mDoc == aDocument)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(newInnerWindow->mDoc == aDocument)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(newInnerWindow->mDoc == aDocument
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"newInnerWindow->mDoc == aDocument", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2415); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "newInnerWindow->mDoc == aDocument"
")"); do { *((volatile int*)__null) = 2415; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2416
2417 if (mBrowsingContext->IsTopContent()) {
2418 net::CookieJarSettings::Cast(aDocument->CookieJarSettings())
2419 ->SetTopLevelWindowContextId(aDocument->InnerWindowID());
2420 }
2421
2422 newInnerWindow->RefreshReduceTimerPrecisionCallerType();
2423
2424 if (!aState) {
2425 if (reUseInnerWindow) {
2426 // The StorageAccess state may have changed. Invalidate the cached
2427 // StorageAllowed field, so that the next call to StorageAllowedForWindow
2428 // recomputes it.
2429 newInnerWindow->ClearStorageAllowedCache();
2430
2431 // The storage objects contain the URL of the window. We have to
2432 // recreate them when the innerWindow is reused.
2433 newInnerWindow->mLocalStorage = nullptr;
2434 newInnerWindow->mSessionStorage = nullptr;
2435 newInnerWindow->mPerformance = nullptr;
2436
2437 // This must be called after nullifying the internal objects because
2438 // here we could recreate them, calling the getter methods, and store
2439 // them into the JS slots. If we nullify them after, the slot values and
2440 // the objects will be out of sync.
2441 newInnerWindow->ClearDocumentDependentSlots(cx);
2442 } else {
2443 newInnerWindow->InitDocumentDependentState(cx);
2444
2445 // Initialize DOM classes etc on the inner window.
2446 JS::Rooted<JSObject*> obj(cx, newInnerGlobal);
2447 rv = kungFuDeathGrip->InitClasses(obj);
2448 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2448); return rv; } } while (false)
;
2449 }
2450
2451 // When replacing an initial about:blank document we call
2452 // ExecutionReady again to update the client creation URL.
2453 rv = newInnerWindow->ExecutionReady();
2454 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2454); return rv; } } while (false)
;
2455
2456 if (mArguments) {
2457 newInnerWindow->DefineArgumentsProperty(mArguments);
2458 mArguments = nullptr;
2459 }
2460
2461 // Give the new inner window our chrome event handler (since it
2462 // doesn't have one).
2463 newInnerWindow->mChromeEventHandler = mChromeEventHandler;
2464 }
2465
2466 if (!aState && reUseInnerWindow) {
2467 // Notify our WindowGlobalChild that it has a new document. If `aState` was
2468 // passed, we're restoring the window from the BFCache, so the document
2469 // hasn't changed.
2470 // If we didn't have a window global child before, then initializing
2471 // it will have set all the required state, so we don't need to do
2472 // it again.
2473 mInnerWindow->GetWindowGlobalChild()->OnNewDocument(aDocument);
2474 }
2475
2476 // Update the current window for our BrowsingContext.
2477 RefPtr<BrowsingContext> bc = GetBrowsingContext();
2478
2479 if (bc->IsOwnedByProcess()) {
2480 MOZ_ALWAYS_SUCCEEDS(bc->SetCurrentInnerWindowId(mInnerWindow->WindowID()))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(bc->SetCurrentInnerWindowId(mInnerWindow->WindowID()))
), 1)))), 1))) { } else { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(false)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(bc->SetCurrentInnerWindowId(mInnerWindow->WindowID()))"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2480); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(bc->SetCurrentInnerWindowId(mInnerWindow->WindowID()))"
")"); do { *((volatile int*)__null) = 2480; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
2481 }
2482
2483 // We no longer need the old inner window. Start its destruction if
2484 // its not being reused and clear our reference.
2485 if (doomCurrentInner) {
2486 currentInner->FreeInnerObjects();
2487 }
2488 currentInner = nullptr;
2489
2490 // We wait to fire the debugger hook until the window is all set up and hooked
2491 // up with the outer. See bug 969156.
2492 if (createdInnerWindow) {
2493 nsContentUtils::AddScriptRunner(NewRunnableMethod(
2494 "nsGlobalWindowInner::FireOnNewGlobalObject", newInnerWindow,
2495 &nsGlobalWindowInner::FireOnNewGlobalObject));
2496 }
2497
2498 if (!newInnerWindow->mHasNotifiedGlobalCreated && mDoc) {
2499 // We should probably notify. However if this is the, arguably bad,
2500 // situation when we're creating a temporary non-chrome-about-blank
2501 // document in a chrome docshell, don't notify just yet. Instead wait
2502 // until we have a real chrome doc.
2503 const bool isContentAboutBlankInChromeDocshell = [&] {
2504 if (!mDocShell) {
2505 return false;
2506 }
2507
2508 RefPtr<BrowsingContext> bc = mDocShell->GetBrowsingContext();
2509 if (!bc || bc->GetType() != BrowsingContext::Type::Chrome) {
2510 return false;
2511 }
2512
2513 return !mDoc->NodePrincipal()->IsSystemPrincipal();
2514 }();
2515
2516 if (!isContentAboutBlankInChromeDocshell) {
2517 newInnerWindow->mHasNotifiedGlobalCreated = true;
2518 nsContentUtils::AddScriptRunner(NewRunnableMethod(
2519 "nsGlobalWindowOuter::DispatchDOMWindowCreated", this,
2520 &nsGlobalWindowOuter::DispatchDOMWindowCreated));
2521 }
2522 }
2523
2524 PreloadLocalStorage();
2525
2526 // Do this here rather than in say the Document constructor, since
2527 // we need a WindowContext available.
2528 mDoc->InitUseCounters();
2529
2530 return NS_OK;
2531}
2532
2533/* static */
2534void nsGlobalWindowOuter::PrepareForProcessChange(JSObject* aProxy) {
2535 JS::Rooted<JSObject*> localProxy(RootingCx(), aProxy);
2536 MOZ_ASSERT(js::IsWindowProxy(localProxy))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(js::IsWindowProxy(localProxy))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(js::IsWindowProxy(localProxy
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("js::IsWindowProxy(localProxy)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2536); AnnotateMozCrashReason("MOZ_ASSERT" "(" "js::IsWindowProxy(localProxy)"
")"); do { *((volatile int*)__null) = 2536; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2537
2538 RefPtr<nsGlobalWindowOuter> outerWindow =
2539 nsOuterWindowProxy::GetOuterWindow(localProxy);
2540 if (!outerWindow) {
2541 return;
2542 }
2543
2544 AutoJSAPI jsapi;
2545 jsapi.Init();
2546 JSContext* cx = jsapi.cx();
2547
2548 JSAutoRealm ar(cx, localProxy);
2549
2550 // Clear out existing references from the browsing context and outer window to
2551 // the proxy, and from the proxy to the outer window. These references will
2552 // become invalid once the proxy is transplanted. Clearing the window proxy
2553 // from the browsing context is also necessary to indicate that it is for an
2554 // out of process window.
2555 outerWindow->ClearWrapper(localProxy);
2556 RefPtr<BrowsingContext> bc = outerWindow->GetBrowsingContext();
2557 MOZ_ASSERT(bc)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bc)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(bc))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("bc", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2557); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bc" ")"); do
{ *((volatile int*)__null) = 2557; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
2558 MOZ_ASSERT(bc->GetWindowProxy() == localProxy)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bc->GetWindowProxy() == localProxy)>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(bc->GetWindowProxy() == localProxy))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("bc->GetWindowProxy() == localProxy"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2558); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bc->GetWindowProxy() == localProxy"
")"); do { *((volatile int*)__null) = 2558; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2559 bc->ClearWindowProxy();
2560 js::SetProxyReservedSlot(localProxy, OUTER_WINDOW_SLOT,
2561 JS::PrivateValue(nullptr));
2562 js::SetProxyReservedSlot(localProxy, HOLDER_WEAKMAP_SLOT,
2563 JS::UndefinedValue());
2564
2565 // Create a new remote outer window proxy, and transplant to it.
2566 JS::Rooted<JSObject*> remoteProxy(cx);
2567
2568 if (!mozilla::dom::GetRemoteOuterWindowProxy(cx, bc, localProxy,
2569 &remoteProxy)) {
2570 MOZ_CRASH("PrepareForProcessChange GetRemoteOuterWindowProxy")do { do { } while (false); MOZ_ReportCrash("" "PrepareForProcessChange GetRemoteOuterWindowProxy"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2570); AnnotateMozCrashReason("MOZ_CRASH(" "PrepareForProcessChange GetRemoteOuterWindowProxy"
")"); do { *((volatile int*)__null) = 2570; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
2571 }
2572
2573 if (!xpc::TransplantObjectNukingXrayWaiver(cx, localProxy, remoteProxy)) {
2574 MOZ_CRASH("PrepareForProcessChange TransplantObject")do { do { } while (false); MOZ_ReportCrash("" "PrepareForProcessChange TransplantObject"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2574); AnnotateMozCrashReason("MOZ_CRASH(" "PrepareForProcessChange TransplantObject"
")"); do { *((volatile int*)__null) = 2574; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
2575 }
2576}
2577
2578void nsGlobalWindowOuter::PreloadLocalStorage() {
2579 if (!Storage::StoragePrefIsEnabled()) {
2580 return;
2581 }
2582
2583 if (IsChromeWindow()) {
2584 return;
2585 }
2586
2587 nsIPrincipal* principal = GetPrincipal();
2588 nsIPrincipal* storagePrincipal = GetEffectiveStoragePrincipal();
2589 if (!principal || !storagePrincipal) {
2590 return;
2591 }
2592
2593 nsresult rv;
2594
2595 nsCOMPtr<nsIDOMStorageManager> storageManager =
2596 do_GetService("@mozilla.org/dom/localStorage-manager;1", &rv);
2597 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2598 return;
2599 }
2600
2601 // private browsing windows do not persist local storage to disk so we should
2602 // only try to precache storage when we're not a private browsing window.
2603 if (principal->GetPrivateBrowsingId() == 0) {
2604 RefPtr<Storage> storage;
2605 rv = storageManager->PrecacheStorage(principal, storagePrincipal,
2606 getter_AddRefs(storage));
2607 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
2608 mLocalStorage = storage;
2609 }
2610 }
2611}
2612
2613void nsGlobalWindowOuter::DispatchDOMWindowCreated() {
2614 if (!mDoc) {
2615 return;
2616 }
2617
2618 // Fire DOMWindowCreated at chrome event listeners
2619 nsContentUtils::DispatchChromeEvent(mDoc, mDoc, u"DOMWindowCreated"_ns,
2620 CanBubble::eYes, Cancelable::eNo);
2621
2622 nsCOMPtr<nsIObserverService> observerService =
2623 mozilla::services::GetObserverService();
2624
2625 // The event dispatching could possibly cause docshell destory, and
2626 // consequently cause mDoc to be set to nullptr by DropOuterWindowDocs(),
2627 // so check it again here.
2628 if (observerService && mDoc) {
2629 nsAutoString origin;
2630 nsIPrincipal* principal = mDoc->NodePrincipal();
2631 nsContentUtils::GetWebExposedOriginSerialization(principal, origin);
2632 observerService->NotifyObservers(static_cast<nsIDOMWindow*>(this),
2633 principal->IsSystemPrincipal()
2634 ? "chrome-document-global-created"
2635 : "content-document-global-created",
2636 origin.get());
2637 }
2638}
2639
2640void nsGlobalWindowOuter::ClearStatus() { SetStatusOuter(u""_ns); }
2641
2642void nsGlobalWindowOuter::SetDocShell(nsDocShell* aDocShell) {
2643 MOZ_ASSERT(aDocShell)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDocShell)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDocShell))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aDocShell", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2643); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocShell" ")"
); do { *((volatile int*)__null) = 2643; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2644
2645 if (aDocShell == mDocShell) {
2646 return;
2647 }
2648
2649 mDocShell = aDocShell;
2650 mBrowsingContext = aDocShell->GetBrowsingContext();
2651
2652 RefPtr<BrowsingContext> parentContext = mBrowsingContext->GetParent();
2653
2654 MOZ_RELEASE_ASSERT(!parentContext ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!parentContext || GetBrowsingContextGroup() == parentContext
->Group())>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(!parentContext || GetBrowsingContextGroup
() == parentContext->Group()))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("!parentContext || GetBrowsingContextGroup() == parentContext->Group()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2655); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "!parentContext || GetBrowsingContextGroup() == parentContext->Group()"
")"); do { *((volatile int*)__null) = 2655; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2655 GetBrowsingContextGroup() == parentContext->Group())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!parentContext || GetBrowsingContextGroup() == parentContext
->Group())>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(!parentContext || GetBrowsingContextGroup
() == parentContext->Group()))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("!parentContext || GetBrowsingContextGroup() == parentContext->Group()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2655); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "!parentContext || GetBrowsingContextGroup() == parentContext->Group()"
")"); do { *((volatile int*)__null) = 2655; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2656
2657 mTopLevelOuterContentWindow = mBrowsingContext->IsTopContent();
2658
2659 // Get our enclosing chrome shell and retrieve its global window impl, so
2660 // that we can do some forwarding to the chrome document.
2661 RefPtr<EventTarget> chromeEventHandler;
2662 mDocShell->GetChromeEventHandler(getter_AddRefs(chromeEventHandler));
2663 mChromeEventHandler = chromeEventHandler;
2664 if (!mChromeEventHandler) {
2665 // We have no chrome event handler. If we have a parent,
2666 // get our chrome event handler from the parent. If
2667 // we don't have a parent, then we need to make a new
2668 // window root object that will function as a chrome event
2669 // handler and receive all events that occur anywhere inside
2670 // our window.
2671 nsCOMPtr<nsPIDOMWindowOuter> parentWindow = GetInProcessParent();
2672 if (parentWindow.get() != this) {
2673 mChromeEventHandler = parentWindow->GetChromeEventHandler();
2674 } else {
2675 mChromeEventHandler = NS_NewWindowRoot(this);
2676 mIsRootOuterWindow = true;
2677 }
2678 }
2679
2680 SetIsBackgroundInternal(!mBrowsingContext->IsActive());
2681}
2682
2683void nsGlobalWindowOuter::DetachFromDocShell(bool aIsBeingDiscarded) {
2684 // DetachFromDocShell means the window is being torn down. Drop our
2685 // reference to the script context, allowing it to be deleted
2686 // later. Meanwhile, keep our weak reference to the script object
2687 // so that it can be retrieved later (until it is finalized by the JS GC).
2688
2689 // Call FreeInnerObjects on all inner windows, not just the current
2690 // one, since some could be held by WindowStateHolder objects that
2691 // are GC-owned.
2692 RefPtr<nsGlobalWindowInner> inner;
2693 for (PRCList* node = PR_LIST_HEAD(this)(this)->next; node != this;
2694 node = PR_NEXT_LINK(inner)((inner)->next)) {
2695 // This cast is safe because `node != this`. Non-this nodes are inner
2696 // windows.
2697 inner = static_cast<nsGlobalWindowInner*>(node);
2698 MOZ_ASSERT(!inner->mOuterWindow || inner->mOuterWindow == this)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!inner->mOuterWindow || inner->mOuterWindow ==
this)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!inner->mOuterWindow || inner->mOuterWindow ==
this))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!inner->mOuterWindow || inner->mOuterWindow == this",
"/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2698); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inner->mOuterWindow || inner->mOuterWindow == this"
")"); do { *((volatile int*)__null) = 2698; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2699 inner->FreeInnerObjects();
2700 }
2701
2702 // Don't report that we were detached to the nsWindowMemoryReporter, as it
2703 // only tracks inner windows.
2704
2705 NotifyWindowIDDestroyed("outer-window-destroyed");
2706
2707 nsGlobalWindowInner* currentInner = GetCurrentInnerWindowInternal(this);
2708
2709 if (currentInner) {
2710 NS_ASSERTION(mDoc, "Must have doc!")do { if (!(mDoc)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Must have doc!"
, "mDoc", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2710); MOZ_PretendNoReturn(); } } while (0)
;
2711
2712 // Remember the document's principal and URI.
2713 mDocumentPrincipal = mDoc->NodePrincipal();
2714 mDocumentCookiePrincipal = mDoc->EffectiveCookiePrincipal();
2715 mDocumentStoragePrincipal = mDoc->EffectiveStoragePrincipal();
2716 mDocumentPartitionedPrincipal = mDoc->PartitionedPrincipal();
2717 mDocumentURI = mDoc->GetDocumentURI();
2718
2719 // Release our document reference
2720 DropOuterWindowDocs();
2721 }
2722
2723 ClearControllers();
2724
2725 mChromeEventHandler = nullptr; // force release now
2726
2727 if (mContext) {
2728 // When we're about to destroy a top level content window
2729 // (for example a tab), we trigger a full GC by passing null as the last
2730 // param. We also trigger a full GC for chrome windows.
2731 nsJSContext::PokeGC(JS::GCReason::SET_DOC_SHELL,
2732 (mTopLevelOuterContentWindow || mIsChrome)
2733 ? nullptr
2734 : GetWrapperPreserveColor());
2735 mContext = nullptr;
2736 }
2737
2738 if (aIsBeingDiscarded) {
2739 // If our BrowsingContext is being discarded, make a note that our current
2740 // inner window was active at the time it went away.
2741 if (nsGlobalWindowInner* currentInner =
2742 GetCurrentInnerWindowInternal(this)) {
2743 currentInner->SetWasCurrentInnerWindow();
2744 }
2745 }
2746
2747 mDocShell = nullptr;
2748 mBrowsingContext->ClearDocShell();
2749
2750 CleanUp();
2751}
2752
2753void nsGlobalWindowOuter::UpdateParentTarget() {
2754 // NOTE: This method is nearly identical to
2755 // nsGlobalWindowInner::UpdateParentTarget(). IF YOU UPDATE THIS METHOD,
2756 // UPDATE THE OTHER ONE TOO! The one difference is that this method updates
2757 // mMessageManager as well, which inner windows don't have.
2758
2759 // Try to get our frame element's tab child global (its in-process message
2760 // manager). If that fails, fall back to the chrome event handler's tab
2761 // child global, and if it doesn't have one, just use the chrome event
2762 // handler itself.
2763
2764 nsCOMPtr<Element> frameElement = GetFrameElementInternal();
2765 mMessageManager = nsContentUtils::TryGetBrowserChildGlobal(frameElement);
2766
2767 if (!mMessageManager) {
2768 nsGlobalWindowOuter* topWin = GetInProcessScriptableTopInternal();
2769 if (topWin) {
2770 frameElement = topWin->GetFrameElementInternal();
2771 mMessageManager = nsContentUtils::TryGetBrowserChildGlobal(frameElement);
2772 }
2773 }
2774
2775 if (!mMessageManager) {
2776 mMessageManager =
2777 nsContentUtils::TryGetBrowserChildGlobal(mChromeEventHandler);
2778 }
2779
2780 if (mMessageManager) {
2781 mParentTarget = mMessageManager;
2782 } else {
2783 mParentTarget = mChromeEventHandler;
2784 }
2785}
2786
2787EventTarget* nsGlobalWindowOuter::GetTargetForEventTargetChain() {
2788 return GetCurrentInnerWindowInternal(this);
2789}
2790
2791void nsGlobalWindowOuter::GetEventTargetParent(EventChainPreVisitor& aVisitor) {
2792 MOZ_CRASH("The outer window should not be part of an event path")do { do { } while (false); MOZ_ReportCrash("" "The outer window should not be part of an event path"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2792); AnnotateMozCrashReason("MOZ_CRASH(" "The outer window should not be part of an event path"
")"); do { *((volatile int*)__null) = 2792; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
2793}
2794
2795bool nsGlobalWindowOuter::ShouldPromptToBlockDialogs() {
2796 if (!nsContentUtils::GetCurrentJSContext()) {
2797 return false; // non-scripted caller.
2798 }
2799
2800 BrowsingContextGroup* group = GetBrowsingContextGroup();
2801 if (!group) {
2802 return true;
2803 }
2804
2805 return group->DialogsAreBeingAbused();
2806}
2807
2808bool nsGlobalWindowOuter::AreDialogsEnabled() {
2809 BrowsingContextGroup* group = mBrowsingContext->Group();
2810 if (!group) {
2811 NS_ERROR("AreDialogsEnabled() called without a browsing context group?")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "AreDialogsEnabled() called without a browsing context group?"
, "Error", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2811); MOZ_PretendNoReturn(); } while (0)
;
2812 return false;
2813 }
2814
2815 // Dialogs are blocked if the content viewer is hidden
2816 if (mDocShell) {
2817 nsCOMPtr<nsIDocumentViewer> viewer;
2818 mDocShell->GetDocViewer(getter_AddRefs(viewer));
2819
2820 bool isHidden;
2821 viewer->GetIsHidden(&isHidden);
2822 if (isHidden) {
2823 return false;
2824 }
2825 }
2826
2827 // Dialogs are also blocked if the document is sandboxed with SANDBOXED_MODALS
2828 // (or if we have no document, of course). Which document? Who knows; the
2829 // spec is daft. See <https://github.com/whatwg/html/issues/1206>. For now
2830 // just go ahead and check mDoc, since in everything except edge cases in
2831 // which a frame is allow-same-origin but not allow-scripts and is being poked
2832 // at by some other window this should be the right thing anyway.
2833 if (!mDoc || (mDoc->GetSandboxFlags() & SANDBOXED_MODALS)) {
2834 return false;
2835 }
2836
2837 return group->GetAreDialogsEnabled();
2838}
2839
2840bool nsGlobalWindowOuter::ConfirmDialogIfNeeded() {
2841 NS_ENSURE_TRUE(mDocShell, false)do { if ((__builtin_expect(!!(!(mDocShell)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocShell" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2841); return false; } } while (false)
;
2842 nsCOMPtr<nsIPromptService> promptSvc =
2843 do_GetService("@mozilla.org/prompter;1");
2844
2845 if (!promptSvc) {
2846 return true;
2847 }
2848
2849 // Reset popup state while opening a modal dialog, and firing events
2850 // about the dialog, to prevent the current state from being active
2851 // the whole time a modal dialog is open.
2852 AutoPopupStatePusherAutoPopupStatePusherInternal popupStatePusher(PopupBlocker::openAbused, true);
2853
2854 bool disableDialog = false;
2855 nsAutoString label, title;
2856 nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES,
2857 "ScriptDialogLabel", label);
2858 nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES,
2859 "ScriptDialogPreventTitle", title);
2860 promptSvc->Confirm(this, title.get(), label.get(), &disableDialog);
2861 if (disableDialog) {
2862 DisableDialogs();
2863 return false;
2864 }
2865
2866 return true;
2867}
2868
2869void nsGlobalWindowOuter::DisableDialogs() {
2870 BrowsingContextGroup* group = mBrowsingContext->Group();
2871 if (!group) {
2872 NS_ERROR("DisableDialogs() called without a browsing context group?")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "DisableDialogs() called without a browsing context group?"
, "Error", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2872); MOZ_PretendNoReturn(); } while (0)
;
2873 return;
2874 }
2875
2876 if (group) {
2877 group->SetAreDialogsEnabled(false);
2878 }
2879}
2880
2881void nsGlobalWindowOuter::EnableDialogs() {
2882 BrowsingContextGroup* group = mBrowsingContext->Group();
2883 if (!group) {
2884 NS_ERROR("EnableDialogs() called without a browsing context group?")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "EnableDialogs() called without a browsing context group?"
, "Error", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2884); MOZ_PretendNoReturn(); } while (0)
;
2885 return;
2886 }
2887
2888 if (group) {
2889 group->SetAreDialogsEnabled(true);
2890 }
2891}
2892
2893nsresult nsGlobalWindowOuter::PostHandleEvent(EventChainPostVisitor& aVisitor) {
2894 MOZ_CRASH("The outer window should not be part of an event path")do { do { } while (false); MOZ_ReportCrash("" "The outer window should not be part of an event path"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2894); AnnotateMozCrashReason("MOZ_CRASH(" "The outer window should not be part of an event path"
")"); do { *((volatile int*)__null) = 2894; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
2895}
2896
2897void nsGlobalWindowOuter::PoisonOuterWindowProxy(JSObject* aObject) {
2898 if (aObject == GetWrapperMaybeDead()) {
2899 PoisonWrapper();
2900 }
2901}
2902
2903nsresult nsGlobalWindowOuter::SetArguments(nsIArray* aArguments) {
2904 nsresult rv;
2905
2906 // We've now mostly separated them, but the difference is still opaque to
2907 // nsWindowWatcher (the caller of SetArguments in this little back-and-forth
2908 // embedding waltz we do here).
2909 //
2910 // So we need to demultiplex the two cases here.
2911 nsGlobalWindowInner* currentInner = GetCurrentInnerWindowInternal(this);
2912
2913 mArguments = aArguments;
2914 rv = currentInner->DefineArgumentsProperty(aArguments);
2915 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 2915); return rv; } } while (false)
;
2916
2917 return NS_OK;
2918}
2919
2920//*****************************************************************************
2921// nsGlobalWindowOuter::nsIScriptObjectPrincipal
2922//*****************************************************************************
2923
2924nsIPrincipal* nsGlobalWindowOuter::GetPrincipal() {
2925 if (mDoc) {
2926 // If we have a document, get the principal from the document
2927 return mDoc->NodePrincipal();
2928 }
2929
2930 if (mDocumentPrincipal) {
2931 return mDocumentPrincipal;
2932 }
2933
2934 // If we don't have a principal and we don't have a document we
2935 // ask the parent window for the principal. This can happen when
2936 // loading a frameset that has a <frame src="javascript:xxx">, in
2937 // that case the global window is used in JS before we've loaded
2938 // a document into the window.
2939
2940 nsCOMPtr<nsIScriptObjectPrincipal> objPrincipal =
2941 do_QueryInterface(GetInProcessParentInternal());
2942
2943 if (objPrincipal) {
2944 return objPrincipal->GetPrincipal();
2945 }
2946
2947 return nullptr;
2948}
2949
2950nsIPrincipal* nsGlobalWindowOuter::GetEffectiveCookiePrincipal() {
2951 if (mDoc) {
2952 // If we have a document, get the principal from the document
2953 return mDoc->EffectiveCookiePrincipal();
2954 }
2955
2956 if (mDocumentCookiePrincipal) {
2957 return mDocumentCookiePrincipal;
2958 }
2959
2960 // If we don't have a cookie principal and we don't have a document we ask
2961 // the parent window for the cookie principal.
2962
2963 nsCOMPtr<nsIScriptObjectPrincipal> objPrincipal =
2964 do_QueryInterface(GetInProcessParentInternal());
2965
2966 if (objPrincipal) {
2967 return objPrincipal->GetEffectiveCookiePrincipal();
2968 }
2969
2970 return nullptr;
2971}
2972
2973nsIPrincipal* nsGlobalWindowOuter::GetEffectiveStoragePrincipal() {
2974 if (mDoc) {
2975 // If we have a document, get the principal from the document
2976 return mDoc->EffectiveStoragePrincipal();
2977 }
2978
2979 if (mDocumentStoragePrincipal) {
2980 return mDocumentStoragePrincipal;
2981 }
2982
2983 // If we don't have a storage principal and we don't have a document we ask
2984 // the parent window for the storage principal.
2985
2986 nsCOMPtr<nsIScriptObjectPrincipal> objPrincipal =
2987 do_QueryInterface(GetInProcessParentInternal());
2988
2989 if (objPrincipal) {
2990 return objPrincipal->GetEffectiveStoragePrincipal();
2991 }
2992
2993 return nullptr;
2994}
2995
2996nsIPrincipal* nsGlobalWindowOuter::PartitionedPrincipal() {
2997 if (mDoc) {
2998 // If we have a document, get the principal from the document
2999 return mDoc->PartitionedPrincipal();
3000 }
3001
3002 if (mDocumentPartitionedPrincipal) {
3003 return mDocumentPartitionedPrincipal;
3004 }
3005
3006 // If we don't have a partitioned principal and we don't have a document we
3007 // ask the parent window for the partitioned principal.
3008
3009 nsCOMPtr<nsIScriptObjectPrincipal> objPrincipal =
3010 do_QueryInterface(GetInProcessParentInternal());
3011
3012 if (objPrincipal) {
3013 return objPrincipal->PartitionedPrincipal();
3014 }
3015
3016 return nullptr;
3017}
3018
3019//*****************************************************************************
3020// nsGlobalWindowOuter::nsIDOMWindow
3021//*****************************************************************************
3022
3023Element* nsPIDOMWindowOuter::GetFrameElementInternal() const {
3024 return mFrameElement;
3025}
3026
3027void nsPIDOMWindowOuter::SetFrameElementInternal(Element* aFrameElement) {
3028 mFrameElement = aFrameElement;
3029}
3030
3031Navigator* nsGlobalWindowOuter::GetNavigator() {
3032 FORWARD_TO_INNER(Navigator, (), nullptr)do { if (!mInnerWindow) { NS_DebugBreak(NS_DEBUG_WARNING, "No inner window available!"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 3032); return nullptr; } return GetCurrentInnerWindowInternal
(this)->Navigator (); } while (0)
;
3033}
3034
3035nsScreen* nsGlobalWindowOuter::GetScreen() {
3036 FORWARD_TO_INNER(Screen, (), nullptr)do { if (!mInnerWindow) { NS_DebugBreak(NS_DEBUG_WARNING, "No inner window available!"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 3036); return nullptr; } return GetCurrentInnerWindowInternal
(this)->Screen (); } while (0)
;
3037}
3038
3039void nsPIDOMWindowOuter::ActivateMediaComponents() {
3040 if (!ShouldDelayMediaFromStart()) {
3041 return;
3042 }
3043 MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = AudioChannelService
::GetAudioChannelLog(); if ((__builtin_expect(!!(mozilla::detail
::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, LogLevel::Debug, "nsPIDOMWindowOuter, ActiveMediaComponents, "
"no longer to delay media from start, this = %p\n", this); }
} while (0)
3044 ("nsPIDOMWindowOuter, ActiveMediaComponents, "do { const ::mozilla::LogModule* moz_real_module = AudioChannelService
::GetAudioChannelLog(); if ((__builtin_expect(!!(mozilla::detail
::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, LogLevel::Debug, "nsPIDOMWindowOuter, ActiveMediaComponents, "
"no longer to delay media from start, this = %p\n", this); }
} while (0)
3045 "no longer to delay media from start, this = %p\n",do { const ::mozilla::LogModule* moz_real_module = AudioChannelService
::GetAudioChannelLog(); if ((__builtin_expect(!!(mozilla::detail
::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, LogLevel::Debug, "nsPIDOMWindowOuter, ActiveMediaComponents, "
"no longer to delay media from start, this = %p\n", this); }
} while (0)
3046 this))do { const ::mozilla::LogModule* moz_real_module = AudioChannelService
::GetAudioChannelLog(); if ((__builtin_expect(!!(mozilla::detail
::log_test(moz_real_module, LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, LogLevel::Debug, "nsPIDOMWindowOuter, ActiveMediaComponents, "
"no longer to delay media from start, this = %p\n", this); }
} while (0)
;
3047 if (BrowsingContext* bc = GetBrowsingContext()) {
3048 Unused << bc->Top()->SetShouldDelayMediaFromStart(false);
3049 }
3050 NotifyResumingDelayedMedia();
3051}
3052
3053bool nsPIDOMWindowOuter::ShouldDelayMediaFromStart() const {
3054 BrowsingContext* bc = GetBrowsingContext();
3055 return bc && bc->Top()->GetShouldDelayMediaFromStart();
3056}
3057
3058void nsPIDOMWindowOuter::NotifyResumingDelayedMedia() {
3059 RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
3060 if (service) {
3061 service->NotifyResumingDelayedMedia(this);
3062 }
3063}
3064
3065bool nsPIDOMWindowOuter::GetAudioMuted() const {
3066 BrowsingContext* bc = GetBrowsingContext();
3067 return bc && bc->Top()->GetMuted();
3068}
3069
3070void nsPIDOMWindowOuter::RefreshMediaElementsVolume() {
3071 RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
3072 if (service) {
3073 // TODO: RefreshAgentsVolume can probably be simplified further.
3074 service->RefreshAgentsVolume(this, 1.0f, GetAudioMuted());
3075 }
3076}
3077
3078mozilla::dom::BrowsingContextGroup*
3079nsPIDOMWindowOuter::GetBrowsingContextGroup() const {
3080 return mBrowsingContext ? mBrowsingContext->Group() : nullptr;
3081}
3082
3083Nullable<WindowProxyHolder> nsGlobalWindowOuter::GetParentOuter() {
3084 BrowsingContext* bc = GetBrowsingContext();
3085 return bc ? bc->GetParent(IgnoreErrors()) : nullptr;
3086}
3087
3088/**
3089 * GetInProcessScriptableParent used to be called when a script read
3090 * window.parent. Under Fission, that is now handled by
3091 * BrowsingContext::GetParent, and the result is a WindowProxyHolder rather than
3092 * an actual global window. This method still exists for legacy callers which
3093 * relied on the old logic, and require in-process windows. However, it only
3094 * works correctly when no out-of-process frames exist between this window and
3095 * the top-level window, so it should not be used in new code.
3096 *
3097 * In contrast to GetRealParent, GetInProcessScriptableParent respects <iframe
3098 * mozbrowser> boundaries, so if |this| is contained by an <iframe
3099 * mozbrowser>, we will return |this| as its own parent.
3100 */
3101nsPIDOMWindowOuter* nsGlobalWindowOuter::GetInProcessScriptableParent() {
3102 if (!mDocShell) {
3103 return nullptr;
3104 }
3105
3106 if (BrowsingContext* parentBC = GetBrowsingContext()->GetParent()) {
3107 if (nsCOMPtr<nsPIDOMWindowOuter> parent = parentBC->GetDOMWindow()) {
3108 return parent;
3109 }
3110 }
3111 return this;
3112}
3113
3114/**
3115 * Behavies identically to GetInProcessScriptableParent extept that it returns
3116 * null if GetInProcessScriptableParent would return this window.
3117 */
3118nsPIDOMWindowOuter* nsGlobalWindowOuter::GetInProcessScriptableParentOrNull() {
3119 nsPIDOMWindowOuter* parent = GetInProcessScriptableParent();
3120 return (nsGlobalWindowOuter::Cast(parent) == this) ? nullptr : parent;
3121}
3122
3123already_AddRefed<nsPIDOMWindowOuter> nsGlobalWindowOuter::GetInProcessParent() {
3124 if (!mDocShell) {
3125 return nullptr;
3126 }
3127
3128 if (auto* parentBC = GetBrowsingContext()->GetParent()) {
3129 if (auto* parent = parentBC->GetDOMWindow()) {
3130 return do_AddRef(parent);
3131 }
3132 }
3133 return do_AddRef(this);
3134}
3135
3136static nsresult GetTopImpl(nsGlobalWindowOuter* aWin, nsIURI* aURIBeingLoaded,
3137 nsPIDOMWindowOuter** aTop, bool aScriptable,
3138 bool aExcludingExtensionAccessibleContentFrames) {
3139 *aTop = nullptr;
3140
3141 MOZ_ASSERT_IF(aExcludingExtensionAccessibleContentFrames, !aScriptable)do { if (aExcludingExtensionAccessibleContentFrames) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(!aScriptable
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aScriptable))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aScriptable", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 3141); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aScriptable"
")"); do { *((volatile int*)__null) = 3141; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3142
3143 // Walk up the parent chain.
3144
3145 nsCOMPtr<nsPIDOMWindowOuter> prevParent = aWin;
3146 nsCOMPtr<nsPIDOMWindowOuter> parent = aWin;
3147 do {
3148 if (!parent) {
3149 break;
3150 }
3151
3152 prevParent = parent;
3153
3154 if (aScriptable) {
3155 parent = parent->GetInProcessScriptableParent();
3156 } else {
3157 parent = parent->GetInProcessParent();
3158 }
3159
3160 if (aExcludingExtensionAccessibleContentFrames) {
3161 if (auto* p = nsGlobalWindowOuter::Cast(parent)) {
3162 nsGlobalWindowInner* currentInner = GetCurrentInnerWindowInternal(p);
3163 nsIURI* uri = prevParent->GetDocumentURI();
3164 if (!uri) {
3165 // If our parent doesn't have a URI yet, we have a document that is in
3166 // the process of being loaded. In that case, our caller is
3167 // responsible for passing in the URI for the document that is being
3168 // loaded, so we fall back to using that URI here.
3169 uri = aURIBeingLoaded;
3170 }
3171
3172 if (currentInner && uri) {
3173 // If we find an inner window, we better find the uri for the current
3174 // window we're looking at. If we can't find it directly, it is the
3175 // responsibility of our caller to provide it to us.
3176 MOZ_DIAGNOSTIC_ASSERT(uri)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(uri)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(uri))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("uri", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 3176); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "uri"
")"); do { *((volatile int*)__null) = 3176; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3177
3178 // If the new parent has permission to load the current page, we're
3179 // at a moz-extension:// frame which has a host permission that allows
3180 // it to load the document that we've loaded. In that case, stop at
3181 // this frame and consider it the top-level frame.
3182 //
3183 // Note that it's possible for the set of URIs accepted by
3184 // AddonAllowsLoad() to change at runtime, but we don't need to cache
3185 // the result of this check, since the important consumer of this code
3186 // (which is nsIHttpChannelInternal.topWindowURI) already caches the
3187 // result after computing it the first time.
3188 if (BasePrincipal::Cast(p->GetPrincipal())
3189 ->AddonAllowsLoad(uri, true)) {
3190 parent = prevParent;
3191 break;
3192 }
3193 }
3194 }
3195 }
3196
3197 } while (parent != prevParent);
3198
3199 if (parent) {
3200 parent.swap(*aTop);
3201 }
3202
3203 return NS_OK;
3204}
3205
3206/**
3207 * GetInProcessScriptableTop used to be called when a script read window.top.
3208 * Under Fission, that is now handled by BrowsingContext::Top, and the result is
3209 * a WindowProxyHolder rather than an actual global window. This method still
3210 * exists for legacy callers which relied on the old logic, and require
3211 * in-process windows. However, it only works correctly when no out-of-process
3212 * frames exist between this window and the top-level window, so it should not
3213 * be used in new code.
3214 *
3215 * In contrast to GetRealTop, GetInProcessScriptableTop respects <iframe
3216 * mozbrowser> boundaries. If we encounter a window owned by an <iframe
3217 * mozbrowser> while walking up the window hierarchy, we'll stop and return that
3218 * window.
3219 */
3220nsPIDOMWindowOuter* nsGlobalWindowOuter::GetInProcessScriptableTop() {
3221 nsCOMPtr<nsPIDOMWindowOuter> window;
3222 GetTopImpl(this, /* aURIBeingLoaded = */ nullptr, getter_AddRefs(window),
3223 /* aScriptable = */ true,
3224 /* aExcludingExtensionAccessibleContentFrames = */ false);
3225 return window.get();
3226}
3227
3228already_AddRefed<nsPIDOMWindowOuter> nsGlobalWindowOuter::GetInProcessTop() {
3229 nsCOMPtr<nsPIDOMWindowOuter> window;
3230 GetTopImpl(this, /* aURIBeingLoaded = */ nullptr, getter_AddRefs(window),
3231 /* aScriptable = */ false,
3232 /* aExcludingExtensionAccessibleContentFrames = */ false);
3233 return window.forget();
3234}
3235
3236already_AddRefed<nsPIDOMWindowOuter>
3237nsGlobalWindowOuter::GetTopExcludingExtensionAccessibleContentFrames(
3238 nsIURI* aURIBeingLoaded) {
3239 // There is a parent-process equivalent of this in DocumentLoadListener.cpp
3240 // GetTopWindowExcludingExtensionAccessibleContentFrames
3241 nsCOMPtr<nsPIDOMWindowOuter> window;
3242 GetTopImpl(this, aURIBeingLoaded, getter_AddRefs(window),
3243 /* aScriptable = */ false,
3244 /* aExcludingExtensionAccessibleContentFrames = */ true);
3245 return window.forget();
3246}
3247
3248void nsGlobalWindowOuter::GetContentOuter(JSContext* aCx,
3249 JS::MutableHandle<JSObject*> aRetval,
3250 CallerType aCallerType,
3251 ErrorResult& aError) {
3252 RefPtr<BrowsingContext> content = GetContentInternal(aCallerType, aError);
3253 if (aError.Failed()) {
3254 return;
3255 }
3256
3257 if (!content) {
3258 aRetval.set(nullptr);
3259 return;
3260 }
3261
3262 JS::Rooted<JS::Value> val(aCx);
3263 if (!ToJSValue(aCx, WindowProxyHolder{content}, &val)) {
3264 aError.Throw(NS_ERROR_UNEXPECTED);
3265 return;
3266 }
3267
3268 MOZ_ASSERT(val.isObjectOrNull())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(val.isObjectOrNull())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(val.isObjectOrNull()))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("val.isObjectOrNull()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 3268); AnnotateMozCrashReason("MOZ_ASSERT" "(" "val.isObjectOrNull()"
")"); do { *((volatile int*)__null) = 3268; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3269 aRetval.set(val.toObjectOrNull());
3270}
3271
3272already_AddRefed<BrowsingContext> nsGlobalWindowOuter::GetContentInternal(
3273 CallerType aCallerType, ErrorResult& aError) {
3274 // First check for a named frame named "content"
3275 if (RefPtr<BrowsingContext> named = GetChildWindow(u"content"_ns)) {
3276 return named.forget();
3277 }
3278
3279 // If we're in the parent process, and being called by system code, `content`
3280 // should return the current primary content frame (if it's in-process).
3281 //
3282 // We return `nullptr` if the current primary content frame is out-of-process,
3283 // rather than a remote window proxy, as that is the existing behaviour as of
3284 // bug 1597437.
3285 if (XRE_IsParentProcess() && aCallerType == CallerType::System) {
3286 nsCOMPtr<nsIDocShellTreeOwner> treeOwner = GetTreeOwner();
3287 if (!treeOwner) {
3288 aError.Throw(NS_ERROR_FAILURE);
3289 return nullptr;
3290 }
3291
3292 nsCOMPtr<nsIDocShellTreeItem> primaryContent;
3293 treeOwner->GetPrimaryContentShell(getter_AddRefs(primaryContent));
3294 if (!primaryContent) {
3295 return nullptr;
3296 }
3297
3298 return do_AddRef(primaryContent->GetBrowsingContext());
3299 }
3300
3301 // For legacy untrusted callers we always return the same value as
3302 // `window.top`
3303 if (mDoc && aCallerType != CallerType::System) {
3304 mDoc->WarnOnceAbout(DeprecatedOperations::eWindowContentUntrusted);
3305 }
3306
3307 MOZ_ASSERT(mBrowsingContext->IsContent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mBrowsingContext->IsContent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mBrowsingContext->IsContent
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mBrowsingContext->IsContent()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 3307); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->IsContent()"
")"); do { *((volatile int*)__null) = 3307; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3308 return do_AddRef(mBrowsingContext->Top());
3309}
3310
3311nsresult nsGlobalWindowOuter::GetPrompter(nsIPrompt** aPrompt) {
3312 if (!mDocShell) return NS_ERROR_FAILURE;
3313
3314 nsCOMPtr<nsIPrompt> prompter(do_GetInterface(mDocShell));
3315 NS_ENSURE_TRUE(prompter, NS_ERROR_NO_INTERFACE)do { if ((__builtin_expect(!!(!(prompter)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "prompter" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 3315); return NS_ERROR_NO_INTERFACE; } } while (false)
;
3316
3317 prompter.forget(aPrompt);
3318 return NS_OK;
3319}
3320
3321bool nsGlobalWindowOuter::GetClosedOuter() {
3322 // If someone called close(), or if we don't have a docshell, we're closed.
3323 return mIsClosed || !mDocShell;
3324}
3325
3326bool nsGlobalWindowOuter::Closed() { return GetClosedOuter(); }
3327
3328Nullable<WindowProxyHolder> nsGlobalWindowOuter::IndexedGetterOuter(
3329 uint32_t aIndex) {
3330 BrowsingContext* bc = GetBrowsingContext();
3331 NS_ENSURE_TRUE(bc, nullptr)do { if ((__builtin_expect(!!(!(bc)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "bc" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 3331); return nullptr; } } while (false)
;
3332
3333 Span<RefPtr<BrowsingContext>> children = bc->NonSyntheticChildren();
3334
3335 if (aIndex < children.Length()) {
3336 return WindowProxyHolder(children[aIndex]);
3337 }
3338 return nullptr;
3339}
3340
3341nsIControllers* nsGlobalWindowOuter::GetControllersOuter(ErrorResult& aError) {
3342 if (!mControllers) {
3343 mControllers = new nsXULControllers();
3344 if (!mControllers) {
3345 aError.Throw(NS_ERROR_FAILURE);
3346 return nullptr;
3347 }
3348
3349 // Add in the default controller
3350 RefPtr<nsBaseCommandController> commandController =
3351 nsBaseCommandController::CreateWindowController();
3352 if (!commandController) {
3353 aError.Throw(NS_ERROR_FAILURE);
3354 return nullptr;
3355 }
3356
3357 mControllers->InsertControllerAt(0, commandController);
3358 commandController->SetCommandContext(static_cast<nsIDOMWindow*>(this));
3359 }
3360
3361 return mControllers;
3362}
3363
3364nsresult nsGlobalWindowOuter::GetControllers(nsIControllers** aResult) {
3365 FORWARD_TO_INNER(GetControllers, (aResult), NS_ERROR_UNEXPECTED)do { if (!mInnerWindow) { NS_DebugBreak(NS_DEBUG_WARNING, "No inner window available!"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 3365); return NS_ERROR_UNEXPECTED; } return GetCurrentInnerWindowInternal
(this)->GetControllers (aResult); } while (0)
;
3366}
3367
3368already_AddRefed<BrowsingContext>
3369nsGlobalWindowOuter::GetOpenerBrowsingContext() {
3370 RefPtr<BrowsingContext> opener = GetBrowsingContext()->GetOpener();
3371 MOZ_DIAGNOSTIC_ASSERT(!opener ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!opener || opener->Group() == GetBrowsingContext(
)->Group())>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(!opener || opener->Group() == GetBrowsingContext
()->Group()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!opener || opener->Group() == GetBrowsingContext()->Group()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 3372); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!opener || opener->Group() == GetBrowsingContext()->Group()"
")"); do { *((volatile int*)__null) = 3372; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3372 opener->Group() == GetBrowsingContext()->Group())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!opener || opener->Group() == GetBrowsingContext(
)->Group())>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(!opener || opener->Group() == GetBrowsingContext
()->Group()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!opener || opener->Group() == GetBrowsingContext()->Group()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 3372); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!opener || opener->Group() == GetBrowsingContext()->Group()"
")"); do { *((volatile int*)__null) = 3372; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3373 if (!opener || opener->Group() != GetBrowsingContext()->Group()) {
3374 return nullptr;
3375 }
3376
3377 // Catch the case where we're chrome but the opener is not...
3378 if (nsContentUtils::LegacyIsCallerChromeOrNativeCode() &&
3379 GetPrincipal() == nsContentUtils::GetSystemPrincipal()) {
3380 auto* openerWin = nsGlobalWindowOuter::Cast(opener->GetDOMWindow());
3381 if (!openerWin ||
3382 openerWin->GetPrincipal() != nsContentUtils::GetSystemPrincipal()) {
3383 return nullptr;
3384 }
3385 }
3386
3387 return opener.forget();
3388}
3389
3390nsPIDOMWindowOuter* nsGlobalWindowOuter::GetSameProcessOpener() {
3391 if (RefPtr<BrowsingContext> opener = GetOpenerBrowsingContext()) {
3392 return opener->GetDOMWindow();
3393 }
3394 return nullptr;
3395}
3396
3397Nullable<WindowProxyHolder> nsGlobalWindowOuter::GetOpenerWindowOuter() {
3398 if (RefPtr<BrowsingContext> opener = GetOpenerBrowsingContext()) {
3399 return WindowProxyHolder(std::move(opener));
3400 }
3401 return nullptr;
3402}
3403
3404Nullable<WindowProxyHolder> nsGlobalWindowOuter::GetOpener() {
3405 return GetOpenerWindowOuter();
3406}
3407
3408void nsGlobalWindowOuter::GetStatusOuter(nsAString& aStatus) {
3409 aStatus = mStatus;
3410}
3411
3412void nsGlobalWindowOuter::SetStatusOuter(const nsAString& aStatus) {
3413 mStatus = aStatus;
3414
3415 // We don't support displaying window.status in the UI, so there's nothing
3416 // left to do here.
3417}
3418
3419void nsGlobalWindowOuter::GetNameOuter(nsAString& aName) {
3420 if (mDocShell) {
3421 mDocShell->GetName(aName);
3422 }
3423}
3424
3425void nsGlobalWindowOuter::SetNameOuter(const nsAString& aName,
3426 mozilla::ErrorResult& aError) {
3427 if (mDocShell) {
3428 aError = mDocShell->SetName(aName);
3429 }
3430}
3431
3432// NOTE: The idea of this function is that it should return the same as
3433// nsPresContext::CSSToDeviceScale() if it was in aWindow synchronously. For
3434// that, we use the UnscaledDevicePixelsPerCSSPixel() (which contains the device
3435// scale and the OS zoom scale) and then account for the browsing context full
3436// zoom. See the declaration of this function for context about why this is
3437// needed.
3438CSSToLayoutDeviceScale nsGlobalWindowOuter::CSSToDevScaleForBaseWindow(
3439 nsIBaseWindow* aWindow) {
3440 MOZ_ASSERT(aWindow)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aWindow)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aWindow))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aWindow", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 3440); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWindow" ")"
); do { *((volatile int*)__null) = 3440; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3441 auto scale = aWindow->UnscaledDevicePixelsPerCSSPixel();
3442 if (mBrowsingContext) {
3443 scale.scale *= mBrowsingContext->FullZoom();
3444 }
3445 return scale;
3446}
3447
3448nsresult nsGlobalWindowOuter::GetInnerSize(CSSSize& aSize) {
3449 EnsureSizeAndPositionUpToDate();
3450
3451 NS_ENSURE_STATE(mDocShell)do { if ((__builtin_expect(!!(!(mDocShell)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocShell" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 3451); return NS_ERROR_UNEXPECTED; } } while (false)
;
3452
3453 RefPtr<nsPresContext> presContext = mDocShell->GetPresContext();
3454 PresShell* presShell = mDocShell->GetPresShell();
3455
3456 if (!presContext || !presShell) {
3457 aSize = {};
3458 return NS_OK;
3459 }
3460
3461 // Whether or not the css viewport has been overridden, we can get the
3462 // correct value by looking at the visible area of the presContext.
3463 if (RefPtr<nsViewManager> viewManager = presShell->GetViewManager()) {
3464 viewManager->FlushDelayedResize();
3465 }
3466
3467 // FIXME: Bug 1598487 - Return the layout viewport instead of the ICB.
3468 nsSize viewportSize = presContext->GetVisibleArea().Size();
3469 if (presContext->GetDynamicToolbarState() == DynamicToolbarState::Collapsed) {
3470 viewportSize =
3471 nsLayoutUtils::ExpandHeightForViewportUnits(presContext, viewportSize);
3472 }
3473
3474 aSize = CSSPixel::FromAppUnits(viewportSize);
3475
3476 switch (StaticPrefs::dom_innerSize_rounding()) {
3477 case 1:
3478 aSize.width = std::roundf(aSize.width);
3479 aSize.height = std::roundf(aSize.height);
3480 break;
3481 case 2:
3482 aSize.width = std::truncf(aSize.width);
3483 aSize.height = std::truncf(aSize.height);
3484 break;
3485 default:
3486 break;
3487 }
3488
3489 return NS_OK;
3490}
3491
3492double nsGlobalWindowOuter::GetInnerWidthOuter(ErrorResult& aError) {
3493 CSSSize size;
3494 aError = GetInnerSize(size);
3495 return size.width;
3496}
3497
3498nsresult nsGlobalWindowOuter::GetInnerWidth(double* aInnerWidth) {
3499 FORWARD_TO_INNER(GetInnerWidth, (aInnerWidth), NS_ERROR_UNEXPECTED)do { if (!mInnerWindow) { NS_DebugBreak(NS_DEBUG_WARNING, "No inner window available!"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 3499); return NS_ERROR_UNEXPECTED; } return GetCurrentInnerWindowInternal
(this)->GetInnerWidth (aInnerWidth); } while (0)
;
3500}
3501
3502double nsGlobalWindowOuter::GetInnerHeightOuter(ErrorResult& aError) {
3503 CSSSize size;
3504 aError = GetInnerSize(size);
3505 return size.height;
3506}
3507
3508nsresult nsGlobalWindowOuter::GetInnerHeight(double* aInnerHeight) {
3509 FORWARD_TO_INNER(GetInnerHeight, (aInnerHeight), NS_ERROR_UNEXPECTED)do { if (!mInnerWindow) { NS_DebugBreak(NS_DEBUG_WARNING, "No inner window available!"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 3509); return NS_ERROR_UNEXPECTED; } return GetCurrentInnerWindowInternal
(this)->GetInnerHeight (aInnerHeight); } while (0)
;
3510}
3511
3512CSSIntSize nsGlobalWindowOuter::GetOuterSize(CallerType aCallerType,
3513 ErrorResult& aError) {
3514 if (nsIGlobalObject::ShouldResistFingerprinting(aCallerType,
3515 RFPTarget::WindowOuterSize)) {
3516 CSSSize size;
3517 aError = GetInnerSize(size);
3518 return RoundedToInt(size);
3519 }
3520
3521 // Windows showing documents in RDM panes and any subframes within them
3522 // return the simulated device size.
3523 if (mDoc) {
3524 Maybe<CSSIntSize> deviceSize = GetRDMDeviceSize(*mDoc);
3525 if (deviceSize.isSome()) {
3526 return *deviceSize;
3527 }
3528 }
3529
3530 nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
3531 if (!treeOwnerAsWin) {
3532 aError.Throw(NS_ERROR_FAILURE);
3533 return {};
3534 }
3535
3536 return RoundedToInt(treeOwnerAsWin->GetSize() /
3537 CSSToDevScaleForBaseWindow(treeOwnerAsWin));
3538}
3539
3540int32_t nsGlobalWindowOuter::GetOuterWidthOuter(CallerType aCallerType,
3541 ErrorResult& aError) {
3542 return GetOuterSize(aCallerType, aError).width;
3543}
3544
3545int32_t nsGlobalWindowOuter::GetOuterHeightOuter(CallerType aCallerType,
3546 ErrorResult& aError) {
3547 return GetOuterSize(aCallerType, aError).height;
3548}
3549
3550CSSPoint nsGlobalWindowOuter::ScreenEdgeSlop() {
3551 if (NS_WARN_IF(!mDocShell)NS_warn_if_impl(!mDocShell, "!mDocShell", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 3551)
) {
3552 return {};
3553 }
3554 RefPtr<nsPresContext> pc = mDocShell->GetPresContext();
3555 if (NS_WARN_IF(!pc)NS_warn_if_impl(!pc, "!pc", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 3555)
) {
3556 return {};
3557 }
3558 nsCOMPtr<nsIWidget> widget = GetMainWidget();
3559 if (NS_WARN_IF(!widget)NS_warn_if_impl(!widget, "!widget", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 3559)
) {
3560 return {};
3561 }
3562 LayoutDeviceIntPoint pt = widget->GetScreenEdgeSlop();
3563 auto auPoint =
3564 LayoutDeviceIntPoint::ToAppUnits(pt, pc->AppUnitsPerDevPixel());
3565 return CSSPoint::FromAppUnits(auPoint);
3566}
3567
3568CSSIntPoint nsGlobalWindowOuter::GetScreenXY(CallerType aCallerType,
3569 ErrorResult& aError) {
3570 // When resisting fingerprinting, always return (0,0)
3571 if (nsIGlobalObject::ShouldResistFingerprinting(aCallerType,
3572 RFPTarget::WindowScreenXY)) {
3573 return CSSIntPoint(0, 0);
3574 }
3575
3576 nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
3577 if (!treeOwnerAsWin) {
3578 aError.Throw(NS_ERROR_FAILURE);
3579 return CSSIntPoint(0, 0);
3580 }
3581
3582 LayoutDeviceIntPoint windowPos;
3583 aError = treeOwnerAsWin->GetPosition(&windowPos.x.value, &windowPos.y.value);
3584
3585 RefPtr<nsPresContext> presContext = mDocShell->GetPresContext();
3586 if (!presContext) {
3587 // XXX Fishy LayoutDevice to CSS conversion?
3588 return CSSIntPoint(windowPos.x, windowPos.y);
3589 }
3590
3591 nsDeviceContext* context = presContext->DeviceContext();
3592 auto windowPosAppUnits = LayoutDeviceIntPoint::ToAppUnits(
3593 windowPos, context->AppUnitsPerDevPixel());
3594 return CSSIntPoint::FromAppUnitsRounded(windowPosAppUnits);
3595}
3596
3597int32_t nsGlobalWindowOuter::GetScreenXOuter(CallerType aCallerType,
3598 ErrorResult& aError) {
3599 return GetScreenXY(aCallerType, aError).x;
3600}
3601
3602nsRect nsGlobalWindowOuter::GetInnerScreenRect() {
3603 if (!mDocShell) {
3604 return nsRect();
3605 }
3606
3607 EnsureSizeAndPositionUpToDate();
3608
3609 if (!mDocShell) {
3610 return nsRect();
3611 }
3612
3613 PresShell* presShell = mDocShell->GetPresShell();
3614 if (!presShell) {
3615 return nsRect();
3616 }
3617 nsIFrame* rootFrame = presShell->GetRootFrame();
3618 if (!rootFrame) {
3619 return nsRect();
3620 }
3621
3622 return rootFrame->GetScreenRectInAppUnits();
3623}
3624
3625Maybe<CSSIntSize> nsGlobalWindowOuter::GetRDMDeviceSize(
3626 const Document& aDocument) {
3627 // RDM device size should reflect the simulated device resolution, and
3628 // be independent of any full zoom or resolution zoom applied to the
3629 // content. To get this value, we get the "unscaled" browser child size,
3630 // and divide by the full zoom. "Unscaled" in this case means unscaled
3631 // from device to screen but it has been affected (multiplied) by the
3632 // full zoom and we need to compensate for that.
3633 MOZ_RELEASE_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 3633); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 3633; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3634
3635 // Bug 1576256: This does not work for cross-process subframes.
3636 const Document* topInProcessContentDoc =
3637 aDocument.GetTopLevelContentDocumentIfSameProcess();
3638 BrowsingContext* bc = topInProcessContentDoc
3639 ? topInProcessContentDoc->GetBrowsingContext()
3640 : nullptr;
3641 if (bc && bc->InRDMPane()) {
3642 nsIDocShell* docShell = topInProcessContentDoc->GetDocShell();
3643 if (docShell) {
3644 nsPresContext* presContext = docShell->GetPresContext();
3645 if (presContext) {
3646 nsCOMPtr<nsIBrowserChild> child = docShell->GetBrowserChild();
3647 if (child) {
3648 // We intentionally use GetFullZoom here instead of
3649 // GetDeviceFullZoom, because the unscaledInnerSize is based
3650 // on the full zoom and not the device full zoom (which is
3651 // rounded to result in integer device pixels).
3652 float zoom = presContext->GetFullZoom();
3653 BrowserChild* bc = static_cast<BrowserChild*>(child.get());
3654 CSSSize unscaledSize = bc->GetUnscaledInnerSize();
3655 return Some(CSSIntSize(gfx::RoundedToInt(unscaledSize / zoom)));
3656 }
3657 }
3658 }
3659 }
3660 return Nothing();
3661}
3662
3663float nsGlobalWindowOuter::GetMozInnerScreenXOuter(CallerType aCallerType) {
3664 // When resisting fingerprinting, always return 0.
3665 if (nsIGlobalObject::ShouldResistFingerprinting(
3666 aCallerType, RFPTarget::WindowInnerScreenXY)) {
3667 return 0.0;
3668 }
3669
3670 nsRect r = GetInnerScreenRect();
3671 return nsPresContext::AppUnitsToFloatCSSPixels(r.x);
3672}
3673
3674float nsGlobalWindowOuter::GetMozInnerScreenYOuter(CallerType aCallerType) {
3675 // Return 0 to prevent fingerprinting.
3676 if (nsIGlobalObject::ShouldResistFingerprinting(
3677 aCallerType, RFPTarget::WindowInnerScreenXY)) {
3678 return 0.0;
3679 }
3680
3681 nsRect r = GetInnerScreenRect();
3682 return nsPresContext::AppUnitsToFloatCSSPixels(r.y);
3683}
3684
3685int32_t nsGlobalWindowOuter::GetScreenYOuter(CallerType aCallerType,
3686 ErrorResult& aError) {
3687 return GetScreenXY(aCallerType, aError).y;
3688}
3689
3690// NOTE: Arguments to this function should have values scaled to
3691// CSS pixels, not device pixels.
3692void nsGlobalWindowOuter::CheckSecurityWidthAndHeight(int32_t* aWidth,
3693 int32_t* aHeight,
3694 CallerType aCallerType) {
3695 if (aCallerType != CallerType::System) {
3696 // if attempting to resize the window, hide any open popups
3697 nsContentUtils::HidePopupsInDocument(mDoc);
3698 }
3699
3700 // This one is easy. Just ensure the variable is greater than 100;
3701 if ((aWidth && *aWidth < 100) || (aHeight && *aHeight < 100)) {
3702 // Check security state for use in determing window dimensions
3703
3704 if (aCallerType != CallerType::System) {
3705 // sec check failed
3706 if (aWidth && *aWidth < 100) {
3707 *aWidth = 100;
3708 }
3709 if (aHeight && *aHeight < 100) {
3710 *aHeight = 100;
3711 }
3712 }
3713 }
3714}
3715
3716// NOTE: Arguments to this function should have values in app units
3717void nsGlobalWindowOuter::SetCSSViewportWidthAndHeight(nscoord aInnerWidth,
3718 nscoord aInnerHeight) {
3719 RefPtr<nsPresContext> presContext = mDocShell->GetPresContext();
3720
3721 nsRect shellArea = presContext->GetVisibleArea();
3722 shellArea.SetHeight(aInnerHeight);
3723 shellArea.SetWidth(aInnerWidth);
3724
3725 // FIXME(emilio): This doesn't seem to be ok, this doesn't reflow or
3726 // anything... Should go through PresShell::ResizeReflow.
3727 //
3728 // But I don't think this can be reached by content, as we don't allow to set
3729 // inner{Width,Height}.
3730 presContext->SetVisibleArea(shellArea);
3731}
3732
3733// NOTE: Arguments to this function should have values scaled to
3734// CSS pixels, not device pixels.
3735void nsGlobalWindowOuter::CheckSecurityLeftAndTop(int32_t* aLeft, int32_t* aTop,
3736 CallerType aCallerType) {
3737 // This one is harder. We have to get the screen size and window dimensions.
3738
3739 // Check security state for use in determing window dimensions
3740
3741 if (aCallerType != CallerType::System) {
3742 // if attempting to move the window, hide any open popups
3743 nsContentUtils::HidePopupsInDocument(mDoc);
3744
3745 if (nsGlobalWindowOuter* rootWindow =
3746 nsGlobalWindowOuter::Cast(GetPrivateRoot())) {
3747 rootWindow->FlushPendingNotifications(FlushType::Layout);
3748 }
3749
3750 nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
3751
3752 RefPtr<nsScreen> screen = GetScreen();
3753
3754 if (treeOwnerAsWin && screen) {
3755 CSSToLayoutDeviceScale scale = CSSToDevScaleForBaseWindow(treeOwnerAsWin);
3756 CSSIntRect winRect =
3757 CSSIntRect::Round(treeOwnerAsWin->GetPositionAndSize() / scale);
3758
3759 // Get the screen dimensions
3760 // XXX This should use nsIScreenManager once it's fully fleshed out.
3761 int32_t screenLeft = screen->AvailLeft();
3762 int32_t screenWidth = screen->AvailWidth();
3763 int32_t screenHeight = screen->AvailHeight();
3764#if defined(XP_MACOSX)
3765 /* The mac's coordinate system is different from the assumed Windows'
3766 system. It offsets by the height of the menubar so that a window
3767 placed at (0,0) will be entirely visible. Unfortunately that
3768 correction is made elsewhere (in Widget) and the meaning of
3769 the Avail... coordinates is overloaded. Here we allow a window
3770 to be placed at (0,0) because it does make sense to do so.
3771 */
3772 int32_t screenTop = screen->Top();
3773#else
3774 int32_t screenTop = screen->AvailTop();
3775#endif
3776
3777 if (aLeft) {
3778 if (screenLeft + screenWidth < *aLeft + winRect.width)
3779 *aLeft = screenLeft + screenWidth - winRect.width;
3780 if (screenLeft > *aLeft) *aLeft = screenLeft;
3781 }
3782 if (aTop) {
3783 if (screenTop + screenHeight < *aTop + winRect.height)
3784 *aTop = screenTop + screenHeight - winRect.height;
3785 if (screenTop > *aTop) *aTop = screenTop;
3786 }
3787 } else {
3788 if (aLeft) *aLeft = 0;
3789 if (aTop) *aTop = 0;
3790 }
3791 }
3792}
3793
3794int32_t nsGlobalWindowOuter::GetScrollBoundaryOuter(Side aSide) {
3795 FlushPendingNotifications(FlushType::Layout);
3796 if (nsIScrollableFrame* sf = GetScrollFrame()) {
3797 return nsPresContext::AppUnitsToIntCSSPixels(
3798 sf->GetScrollRange().Edge(aSide));
3799 }
3800 return 0;
3801}
3802
3803CSSPoint nsGlobalWindowOuter::GetScrollXY(bool aDoFlush) {
3804 if (aDoFlush) {
3805 FlushPendingNotifications(FlushType::Layout);
3806 } else {
3807 EnsureSizeAndPositionUpToDate();
3808 }
3809
3810 nsIScrollableFrame* sf = GetScrollFrame();
3811 if (!sf) {
3812 return CSSIntPoint(0, 0);
3813 }
3814
3815 nsPoint scrollPos = sf->GetScrollPosition();
3816 if (scrollPos != nsPoint(0, 0) && !aDoFlush) {
3817 // Oh, well. This is the expensive case -- the window is scrolled and we
3818 // didn't actually flush yet. Repeat, but with a flush, since the content
3819 // may get shorter and hence our scroll position may decrease.
3820 return GetScrollXY(true);
3821 }
3822
3823 return CSSPoint::FromAppUnits(scrollPos);
3824}
3825
3826double nsGlobalWindowOuter::GetScrollXOuter() { return GetScrollXY(false).x; }
3827
3828double nsGlobalWindowOuter::GetScrollYOuter() { return GetScrollXY(false).y; }
3829
3830uint32_t nsGlobalWindowOuter::Length() {
3831 BrowsingContext* bc = GetBrowsingContext();
3832 return bc ? bc->NonSyntheticChildren().Length() : 0;
3833}
3834
3835Nullable<WindowProxyHolder> nsGlobalWindowOuter::GetTopOuter() {
3836 BrowsingContext* bc = GetBrowsingContext();
3837 return bc ? bc->GetTop(IgnoreErrors()) : nullptr;
3838}
3839
3840already_AddRefed<BrowsingContext> nsGlobalWindowOuter::GetChildWindow(
3841 const nsAString& aName) {
3842 NS_ENSURE_TRUE(mBrowsingContext, nullptr)do { if ((__builtin_expect(!!(!(mBrowsingContext)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mBrowsingContext" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 3842); return nullptr; } } while (false)
;
3843 NS_ENSURE_TRUE(mInnerWindow, nullptr)do { if ((__builtin_expect(!!(!(mInnerWindow)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mInnerWindow" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 3843); return nullptr; } } while (false)
;
3844 NS_ENSURE_TRUE(mInnerWindow->GetWindowGlobalChild(), nullptr)do { if ((__builtin_expect(!!(!(mInnerWindow->GetWindowGlobalChild
())), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE("
"mInnerWindow->GetWindowGlobalChild()" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 3844); return nullptr; } } while (false)
;
3845
3846 return do_AddRef(mBrowsingContext->FindChildWithName(
3847 aName, *mInnerWindow->GetWindowGlobalChild()));
3848}
3849
3850bool nsGlobalWindowOuter::DispatchCustomEvent(
3851 const nsAString& aEventName, ChromeOnlyDispatch aChromeOnlyDispatch) {
3852 bool defaultActionEnabled = true;
3853
3854 if (aChromeOnlyDispatch == ChromeOnlyDispatch::eYes) {
3855 nsContentUtils::DispatchEventOnlyToChrome(mDoc, this, aEventName,
3856 CanBubble::eYes, Cancelable::eYes,
3857 &defaultActionEnabled);
3858 } else {
3859 nsContentUtils::DispatchTrustedEvent(mDoc, this, aEventName,
3860 CanBubble::eYes, Cancelable::eYes,
3861 &defaultActionEnabled);
3862 }
3863
3864 return defaultActionEnabled;
3865}
3866
3867bool nsGlobalWindowOuter::DispatchResizeEvent(const CSSIntSize& aSize) {
3868 ErrorResult res;
3869 RefPtr<Event> domEvent =
3870 mDoc->CreateEvent(u"CustomEvent"_ns, CallerType::System, res);
3871 if (res.Failed()) {
3872 return false;
3873 }
3874
3875 // We don't init the AutoJSAPI with ourselves because we don't want it
3876 // reporting errors to our onerror handlers.
3877 AutoJSAPI jsapi;
3878 jsapi.Init();
3879 JSContext* cx = jsapi.cx();
3880 JSAutoRealm ar(cx, GetWrapperPreserveColor());
3881
3882 DOMWindowResizeEventDetail detail;
3883 detail.mWidth = aSize.width;
3884 detail.mHeight = aSize.height;
3885 JS::Rooted<JS::Value> detailValue(cx);
3886 if (!ToJSValue(cx, detail, &detailValue)) {
3887 return false;
3888 }
3889
3890 CustomEvent* customEvent = static_cast<CustomEvent*>(domEvent.get());
3891 customEvent->InitCustomEvent(cx, u"DOMWindowResize"_ns,
3892 /* aCanBubble = */ true,
3893 /* aCancelable = */ true, detailValue);
3894
3895 domEvent->SetTrusted(true);
3896 domEvent->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = true;
3897
3898 nsCOMPtr<EventTarget> target = this;
3899 domEvent->SetTarget(target);
3900
3901 return target->DispatchEvent(*domEvent, CallerType::System, IgnoreErrors());
3902}
3903
3904bool nsGlobalWindowOuter::WindowExists(const nsAString& aName,
3905 bool aForceNoOpener,
3906 bool aLookForCallerOnJSStack) {
3907 MOZ_ASSERT(mDocShell, "Must have docshell")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDocShell)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mDocShell))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mDocShell" " (" "Must have docshell"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 3907); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDocShell" ") ("
"Must have docshell" ")"); do { *((volatile int*)__null) = 3907
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
3908
3909 if (aForceNoOpener) {
3910 return aName.LowerCaseEqualsLiteral("_self") ||
3911 aName.LowerCaseEqualsLiteral("_top") ||
3912 aName.LowerCaseEqualsLiteral("_parent");
3913 }
3914
3915 if (WindowGlobalChild* wgc = mInnerWindow->GetWindowGlobalChild()) {
3916 return wgc->FindBrowsingContextWithName(aName, aLookForCallerOnJSStack);
3917 }
3918 return false;
3919}
3920
3921already_AddRefed<nsIWidget> nsGlobalWindowOuter::GetMainWidget() {
3922 nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
3923
3924 nsCOMPtr<nsIWidget> widget;
3925
3926 if (treeOwnerAsWin) {
3927 treeOwnerAsWin->GetMainWidget(getter_AddRefs(widget));
3928 }
3929
3930 return widget.forget();
3931}
3932
3933nsIWidget* nsGlobalWindowOuter::GetNearestWidget() const {
3934 nsIDocShell* docShell = GetDocShell();
3935 if (!docShell) {
3936 return nullptr;
3937 }
3938 PresShell* presShell = docShell->GetPresShell();
3939 if (!presShell) {
3940 return nullptr;
3941 }
3942 nsIFrame* rootFrame = presShell->GetRootFrame();
3943 if (!rootFrame) {
3944 return nullptr;
3945 }
3946 return rootFrame->GetView()->GetNearestWidget(nullptr);
3947}
3948
3949void nsGlobalWindowOuter::SetFullscreenOuter(bool aFullscreen,
3950 mozilla::ErrorResult& aError) {
3951 aError =
3952 SetFullscreenInternal(FullscreenReason::ForFullscreenMode, aFullscreen);
3953}
3954
3955nsresult nsGlobalWindowOuter::SetFullScreen(bool aFullscreen) {
3956 return SetFullscreenInternal(FullscreenReason::ForFullscreenMode,
3957 aFullscreen);
3958}
3959
3960static void FinishDOMFullscreenChange(Document* aDoc, bool aInDOMFullscreen) {
3961 if (aInDOMFullscreen) {
3962 // Ask the document to handle any pending DOM fullscreen change.
3963 if (!Document::HandlePendingFullscreenRequests(aDoc)) {
3964 // If we don't end up having anything in fullscreen,
3965 // async request exiting fullscreen.
3966 Document::AsyncExitFullscreen(aDoc);
3967 }
3968 } else {
3969 // If the window is leaving fullscreen state, also ask the document
3970 // to exit from DOM Fullscreen.
3971 Document::ExitFullscreenInDocTree(aDoc);
3972 }
3973}
3974
3975struct FullscreenTransitionDuration {
3976 // The unit of the durations is millisecond
3977 uint16_t mFadeIn = 0;
3978 uint16_t mFadeOut = 0;
3979 bool IsSuppressed() const { return mFadeIn == 0 && mFadeOut == 0; }
3980};
3981
3982static void GetFullscreenTransitionDuration(
3983 bool aEnterFullscreen, FullscreenTransitionDuration* aDuration) {
3984 const char* pref = aEnterFullscreen
3985 ? "full-screen-api.transition-duration.enter"
3986 : "full-screen-api.transition-duration.leave";
3987 nsAutoCString prefValue;
3988 Preferences::GetCString(pref, prefValue);
3989 if (!prefValue.IsEmpty()) {
3990 sscanf(prefValue.get(), "%hu%hu", &aDuration->mFadeIn,
3991 &aDuration->mFadeOut);
3992 }
3993}
3994
3995class FullscreenTransitionTask : public Runnable {
3996 public:
3997 FullscreenTransitionTask(const FullscreenTransitionDuration& aDuration,
3998 nsGlobalWindowOuter* aWindow, bool aFullscreen,
3999 nsIWidget* aWidget, nsISupports* aTransitionData)
4000 : mozilla::Runnable("FullscreenTransitionTask"),
4001 mWindow(aWindow),
4002 mWidget(aWidget),
4003 mTransitionData(aTransitionData),
4004 mDuration(aDuration),
4005 mStage(eBeforeToggle),
4006 mFullscreen(aFullscreen) {}
4007
4008 NS_IMETHODvirtual nsresult Run() override;
4009
4010 private:
4011 ~FullscreenTransitionTask() override = default;
4012
4013 /**
4014 * The flow of fullscreen transition:
4015 *
4016 * parent process | child process
4017 * ----------------------------------------------------------------
4018 *
4019 * | request/exit fullscreen
4020 * <-----|
4021 * BeforeToggle stage |
4022 * |
4023 * ToggleFullscreen stage *1 |----->
4024 * | HandleFullscreenRequests
4025 * |
4026 * <-----| MozAfterPaint event
4027 * AfterToggle stage *2 |
4028 * |
4029 * End stage |
4030 *
4031 * Note we also start a timer at *1 so that if we don't get MozAfterPaint
4032 * from the child process in time, we continue going to *2.
4033 */
4034 enum Stage {
4035 // BeforeToggle stage happens before we enter or leave fullscreen
4036 // state. In this stage, the task triggers the pre-toggle fullscreen
4037 // transition on the widget.
4038 eBeforeToggle,
4039 // ToggleFullscreen stage actually executes the fullscreen toggle,
4040 // and wait for the next paint on the content to continue.
4041 eToggleFullscreen,
4042 // AfterToggle stage happens after we toggle the fullscreen state.
4043 // In this stage, the task triggers the post-toggle fullscreen
4044 // transition on the widget.
4045 eAfterToggle,
4046 // End stage is triggered after the final transition finishes.
4047 eEnd
4048 };
4049
4050 class Observer final : public nsIObserver, public nsINamed {
4051 public:
4052 NS_DECL_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override; using HasThreadSafeRefCnt = std::false_type;
protected: nsAutoRefCnt mRefCnt; nsAutoOwningThread _mOwningThread
; public:
4053 NS_DECL_NSIOBSERVERvirtual nsresult Observe(nsISupports *aSubject, const char * aTopic
, const char16_t * aData) override;
4054 NS_DECL_NSINAMEDvirtual nsresult GetName(nsACString& aName) override;
4055
4056 explicit Observer(FullscreenTransitionTask* aTask) : mTask(aTask) {}
4057
4058 private:
4059 ~Observer() = default;
4060
4061 RefPtr<FullscreenTransitionTask> mTask;
4062 };
4063
4064 static const char* const kPaintedTopic;
4065
4066 RefPtr<nsGlobalWindowOuter> mWindow;
4067 nsCOMPtr<nsIWidget> mWidget;
4068 nsCOMPtr<nsITimer> mTimer;
4069 nsCOMPtr<nsISupports> mTransitionData;
4070
4071 TimeStamp mFullscreenChangeStartTime;
4072 FullscreenTransitionDuration mDuration;
4073 Stage mStage;
4074 bool mFullscreen;
4075};
4076
4077const char* const FullscreenTransitionTask::kPaintedTopic =
4078 "fullscreen-painted";
4079
4080NS_IMETHODIMPnsresult
4081FullscreenTransitionTask::Run() {
4082 Stage stage = mStage;
4083 mStage = Stage(mStage + 1);
4084 if (MOZ_UNLIKELY(mWidget->Destroyed())(__builtin_expect(!!(mWidget->Destroyed()), 0))) {
4085 // If the widget has been destroyed before we get here, don't try to
4086 // do anything more. Just let it go and release ourselves.
4087 NS_WARNING("The widget to fullscreen has been destroyed")NS_DebugBreak(NS_DEBUG_WARNING, "The widget to fullscreen has been destroyed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4087)
;
4088 mWindow->mIsInFullScreenTransition = false;
4089 return NS_OK;
4090 }
4091 if (stage == eBeforeToggle) {
4092 PROFILER_MARKER_UNTYPED("Fullscreen transition start", DOM)do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Fullscreen transition start", ::geckoprofiler::category::DOM
); } } while (false); } while (false)
;
4093
4094 mWindow->mIsInFullScreenTransition = true;
4095
4096 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
4097 NS_ENSURE_TRUE(obs, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(obs)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "obs" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4097); return NS_ERROR_FAILURE; } } while (false)
;
4098 obs->NotifyObservers(nullptr, "fullscreen-transition-start", nullptr);
4099
4100 mWidget->PerformFullscreenTransition(nsIWidget::eBeforeFullscreenToggle,
4101 mDuration.mFadeIn, mTransitionData,
4102 this);
4103 } else if (stage == eToggleFullscreen) {
4104 PROFILER_MARKER_UNTYPED("Fullscreen toggle start", DOM)do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Fullscreen toggle start", ::geckoprofiler::category::DOM); }
} while (false); } while (false)
;
4105 mFullscreenChangeStartTime = TimeStamp::Now();
4106 // Toggle the fullscreen state on the widget
4107 if (!mWindow->SetWidgetFullscreen(FullscreenReason::ForFullscreenAPI,
4108 mFullscreen, mWidget)) {
4109 // Fail to setup the widget, call FinishFullscreenChange to
4110 // complete fullscreen change directly.
4111 mWindow->FinishFullscreenChange(mFullscreen);
4112 }
4113 // Set observer for the next content paint.
4114 nsCOMPtr<nsIObserver> observer = new Observer(this);
4115 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
4116 obs->AddObserver(observer, kPaintedTopic, false);
4117 // There are several edge cases where we may never get the paint
4118 // notification, including:
4119 // 1. the window/tab is closed before the next paint;
4120 // 2. the user has switched to another tab before we get here.
4121 // Completely fixing those cases seems to be tricky, and since they
4122 // should rarely happen, it probably isn't worth to fix. Hence we
4123 // simply add a timeout here to ensure we never hang forever.
4124 // In addition, if the page is complicated or the machine is less
4125 // powerful, layout could take a long time, in which case, staying
4126 // in black screen for that long could hurt user experience even
4127 // more than exposing an intermediate state.
4128 uint32_t timeout =
4129 Preferences::GetUint("full-screen-api.transition.timeout", 1000);
4130 NS_NewTimerWithObserver(getter_AddRefs(mTimer), observer, timeout,
4131 nsITimer::TYPE_ONE_SHOT);
4132 } else if (stage == eAfterToggle) {
4133 Telemetry::AccumulateTimeDelta(Telemetry::FULLSCREEN_TRANSITION_BLACK_MS,
4134 mFullscreenChangeStartTime);
4135 mWidget->PerformFullscreenTransition(nsIWidget::eAfterFullscreenToggle,
4136 mDuration.mFadeOut, mTransitionData,
4137 this);
4138 } else if (stage == eEnd) {
4139 PROFILER_MARKER_UNTYPED("Fullscreen transition end", DOM)do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Fullscreen transition end", ::geckoprofiler::category::DOM)
; } } while (false); } while (false)
;
4140
4141 mWindow->mIsInFullScreenTransition = false;
4142
4143 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
4144 NS_ENSURE_TRUE(obs, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(obs)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "obs" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4144); return NS_ERROR_FAILURE; } } while (false)
;
4145 obs->NotifyObservers(nullptr, "fullscreen-transition-end", nullptr);
4146
4147 mWidget->CleanupFullscreenTransition();
4148 }
4149 return NS_OK;
4150}
4151
4152NS_IMPL_ISUPPORTS(FullscreenTransitionTask::Observer, nsIObserver, nsINamed)MozExternalRefCountType FullscreenTransitionTask::Observer::AddRef
(void) { static_assert(!std::is_destructible_v<FullscreenTransitionTask
::Observer>, "Reference-counted class " "FullscreenTransitionTask::Observer"
" should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4152); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
4152; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("FullscreenTransitionTask::Observer" != nullptr)
>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!("FullscreenTransitionTask::Observer" != nullptr))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("\"FullscreenTransitionTask::Observer\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4152); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"FullscreenTransitionTask::Observer\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 4152; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("FullscreenTransitionTask::Observer" " not thread-safe"
); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), (
"FullscreenTransitionTask::Observer"), (uint32_t)(sizeof(*this
))); return count; } MozExternalRefCountType FullscreenTransitionTask
::Observer::Release(void) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(int32_t(mRefCnt) > 0)
>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(int32_t(mRefCnt) > 0))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4152); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 4152
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("FullscreenTransitionTask::Observer" != nullptr)
>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!("FullscreenTransitionTask::Observer" != nullptr))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("\"FullscreenTransitionTask::Observer\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4152); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"FullscreenTransitionTask::Observer\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 4152; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("FullscreenTransitionTask::Observer" " not thread-safe"
); const char* const nametmp = "FullscreenTransitionTask::Observer"
; nsrefcnt count = --mRefCnt; NS_LogRelease((this), (count), (
nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return
0; } return count; } nsresult FullscreenTransitionTask::Observer
::QueryInterface(const nsIID& aIID, void** aInstancePtr) {
do { if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "QueryInterface requires a non-NULL destination!", "aInstancePtr"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4152); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(2 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<FullscreenTransitionTask::Observer, nsIObserver
>, int32_t( reinterpret_cast<char*>(static_cast<nsIObserver
*>((FullscreenTransitionTask::Observer*)0x1000)) - reinterpret_cast
<char*>((FullscreenTransitionTask::Observer*)0x1000))},
{&mozilla::detail::kImplementedIID<FullscreenTransitionTask
::Observer, nsINamed>, int32_t( reinterpret_cast<char*>
(static_cast<nsINamed*>((FullscreenTransitionTask::Observer
*)0x1000)) - reinterpret_cast<char*>((FullscreenTransitionTask
::Observer*)0x1000))}, {&mozilla::detail::kImplementedIID
<FullscreenTransitionTask::Observer, nsISupports>, int32_t
(reinterpret_cast<char*>(static_cast<nsISupports*>
( static_cast<nsIObserver*>((FullscreenTransitionTask::
Observer*)0x1000))) - reinterpret_cast<char*>((FullscreenTransitionTask
::Observer*)0x1000))}, { nullptr, 0 } } ; static_assert((sizeof
(table) / sizeof(table[0])) > 1, "need at least 1 interface"
); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID
, aInstancePtr, table); return rv; }
4153
4154NS_IMETHODIMPnsresult
4155FullscreenTransitionTask::Observer::Observe(nsISupports* aSubject,
4156 const char* aTopic,
4157 const char16_t* aData) {
4158 bool shouldContinue = false;
4159 if (strcmp(aTopic, FullscreenTransitionTask::kPaintedTopic) == 0) {
4160 nsCOMPtr<nsPIDOMWindowInner> win(do_QueryInterface(aSubject));
4161 nsCOMPtr<nsIWidget> widget =
4162 win ? nsGlobalWindowInner::Cast(win)->GetMainWidget() : nullptr;
4163 if (widget == mTask->mWidget) {
4164 // The paint notification arrives first. Cancel the timer.
4165 mTask->mTimer->Cancel();
4166 shouldContinue = true;
4167 PROFILER_MARKER_UNTYPED("Fullscreen toggle end", DOM)do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Fullscreen toggle end", ::geckoprofiler::category::DOM); } }
while (false); } while (false)
;
4168 }
4169 } else {
4170#ifdef DEBUG1
4171 MOZ_ASSERT(strcmp(aTopic, NS_TIMER_CALLBACK_TOPIC) == 0,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(strcmp(aTopic, "timer-callback") == 0)>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(strcmp(aTopic, "timer-callback") == 0))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("strcmp(aTopic, \"timer-callback\") == 0"
" (" "Should only get fullscreen-painted or timer-callback" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4172); AnnotateMozCrashReason("MOZ_ASSERT" "(" "strcmp(aTopic, \"timer-callback\") == 0"
") (" "Should only get fullscreen-painted or timer-callback"
")"); do { *((volatile int*)__null) = 4172; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4172 "Should only get fullscreen-painted or timer-callback")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(strcmp(aTopic, "timer-callback") == 0)>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(strcmp(aTopic, "timer-callback") == 0))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("strcmp(aTopic, \"timer-callback\") == 0"
" (" "Should only get fullscreen-painted or timer-callback" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4172); AnnotateMozCrashReason("MOZ_ASSERT" "(" "strcmp(aTopic, \"timer-callback\") == 0"
") (" "Should only get fullscreen-painted or timer-callback"
")"); do { *((volatile int*)__null) = 4172; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4173 nsCOMPtr<nsITimer> timer(do_QueryInterface(aSubject));
4174 MOZ_ASSERT(timer && timer == mTask->mTimer,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(timer && timer == mTask->mTimer)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(timer && timer == mTask->mTimer))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("timer && timer == mTask->mTimer"
" (" "Should only trigger this with the timer the task created"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4175); AnnotateMozCrashReason("MOZ_ASSERT" "(" "timer && timer == mTask->mTimer"
") (" "Should only trigger this with the timer the task created"
")"); do { *((volatile int*)__null) = 4175; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4175 "Should only trigger this with the timer the task created")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(timer && timer == mTask->mTimer)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(timer && timer == mTask->mTimer))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("timer && timer == mTask->mTimer"
" (" "Should only trigger this with the timer the task created"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4175); AnnotateMozCrashReason("MOZ_ASSERT" "(" "timer && timer == mTask->mTimer"
") (" "Should only trigger this with the timer the task created"
")"); do { *((volatile int*)__null) = 4175; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4176#endif
4177 shouldContinue = true;
4178 PROFILER_MARKER_UNTYPED("Fullscreen toggle timeout", DOM)do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Fullscreen toggle timeout", ::geckoprofiler::category::DOM)
; } } while (false); } while (false)
;
4179 }
4180 if (shouldContinue) {
4181 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
4182 obs->RemoveObserver(this, kPaintedTopic);
4183 mTask->mTimer = nullptr;
4184 mTask->Run();
4185 }
4186 return NS_OK;
4187}
4188
4189NS_IMETHODIMPnsresult
4190FullscreenTransitionTask::Observer::GetName(nsACString& aName) {
4191 aName.AssignLiteral("FullscreenTransitionTask");
4192 return NS_OK;
4193}
4194
4195static bool MakeWidgetFullscreen(nsGlobalWindowOuter* aWindow,
4196 FullscreenReason aReason, bool aFullscreen) {
4197 nsCOMPtr<nsIWidget> widget = aWindow->GetMainWidget();
4198 if (!widget) {
4199 return false;
4200 }
4201
4202 FullscreenTransitionDuration duration;
4203 bool performTransition = false;
4204 nsCOMPtr<nsISupports> transitionData;
4205 if (aReason == FullscreenReason::ForFullscreenAPI) {
4206 GetFullscreenTransitionDuration(aFullscreen, &duration);
4207 if (!duration.IsSuppressed()) {
4208 performTransition = widget->PrepareForFullscreenTransition(
4209 getter_AddRefs(transitionData));
4210 }
4211 }
4212
4213 if (!performTransition) {
4214 return aWindow->SetWidgetFullscreen(aReason, aFullscreen, widget);
4215 }
4216
4217 nsCOMPtr<nsIRunnable> task = new FullscreenTransitionTask(
4218 duration, aWindow, aFullscreen, widget, transitionData);
4219 task->Run();
4220 return true;
4221}
4222
4223nsresult nsGlobalWindowOuter::ProcessWidgetFullscreenRequest(
4224 FullscreenReason aReason, bool aFullscreen) {
4225 mInProcessFullscreenRequest.emplace(aReason, aFullscreen);
4226
4227 // Prevent chrome documents which are still loading from resizing
4228 // the window after we set fullscreen mode.
4229 nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
4230 nsCOMPtr<nsIAppWindow> appWin(do_GetInterface(treeOwnerAsWin));
4231 if (aFullscreen && appWin) {
4232 appWin->SetIntrinsicallySized(false);
4233 }
4234
4235 // Sometimes we don't want the top-level widget to actually go fullscreen:
4236 // - in the B2G desktop client, we don't want the emulated screen dimensions
4237 // to appear to increase when entering fullscreen mode; we just want the
4238 // content to fill the entire client area of the emulator window.
4239 // - in FxR Desktop, we don't want fullscreen to take over the monitor, but
4240 // instead we want fullscreen to fill the FxR window in the the headset.
4241 if (!StaticPrefs::full_screen_api_ignore_widgets() &&
4242 !mForceFullScreenInWidget) {
4243 if (MakeWidgetFullscreen(this, aReason, aFullscreen)) {
4244 // The rest of code for switching fullscreen is in nsGlobalWindowOuter::
4245 // FinishFullscreenChange() which will be called after sizemodechange
4246 // event is dispatched.
4247 return NS_OK;
4248 }
4249 }
4250
4251#if defined(NIGHTLY_BUILD1) && defined(XP_WIN)
4252 if (FxRWindowManager::GetInstance()->IsFxRWindow(mWindowID)) {
4253 mozilla::gfx::VRShMem shmem(nullptr, true /*aRequiresMutex*/);
4254 shmem.SendFullscreenState(mWindowID, aFullscreen);
4255 }
4256#endif // NIGHTLY_BUILD && XP_WIN
4257 FinishFullscreenChange(aFullscreen);
4258 return NS_OK;
4259}
4260
4261nsresult nsGlobalWindowOuter::SetFullscreenInternal(FullscreenReason aReason,
4262 bool aFullscreen) {
4263 MOZ_ASSERT(nsContentUtils::IsSafeToRunScript(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(nsContentUtils::IsSafeToRunScript())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(nsContentUtils::IsSafeToRunScript
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("nsContentUtils::IsSafeToRunScript()" " (" "Requires safe to run script as it "
"may call FinishDOMFullscreenChange" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4265); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nsContentUtils::IsSafeToRunScript()"
") (" "Requires safe to run script as it " "may call FinishDOMFullscreenChange"
")"); do { *((volatile int*)__null) = 4265; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4264 "Requires safe to run script as it "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(nsContentUtils::IsSafeToRunScript())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(nsContentUtils::IsSafeToRunScript
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("nsContentUtils::IsSafeToRunScript()" " (" "Requires safe to run script as it "
"may call FinishDOMFullscreenChange" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4265); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nsContentUtils::IsSafeToRunScript()"
") (" "Requires safe to run script as it " "may call FinishDOMFullscreenChange"
")"); do { *((volatile int*)__null) = 4265; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4265 "may call FinishDOMFullscreenChange")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(nsContentUtils::IsSafeToRunScript())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(nsContentUtils::IsSafeToRunScript
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("nsContentUtils::IsSafeToRunScript()" " (" "Requires safe to run script as it "
"may call FinishDOMFullscreenChange" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4265); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nsContentUtils::IsSafeToRunScript()"
") (" "Requires safe to run script as it " "may call FinishDOMFullscreenChange"
")"); do { *((volatile int*)__null) = 4265; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4266
4267 NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mDocShell)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocShell" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4267); return NS_ERROR_FAILURE; } } while (false)
;
4268
4269 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aReason != FullscreenReason::ForForceExitFullscreen ||
!aFullscreen)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aReason != FullscreenReason::ForForceExitFullscreen
|| !aFullscreen))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aReason != FullscreenReason::ForForceExitFullscreen || !aFullscreen"
" (" "FullscreenReason::ForForceExitFullscreen can " "only be used with exiting fullscreen"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4272); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aReason != FullscreenReason::ForForceExitFullscreen || !aFullscreen"
") (" "FullscreenReason::ForForceExitFullscreen can " "only be used with exiting fullscreen"
")"); do { *((volatile int*)__null) = 4272; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4270 aReason != FullscreenReason::ForForceExitFullscreen || !aFullscreen,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aReason != FullscreenReason::ForForceExitFullscreen ||
!aFullscreen)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aReason != FullscreenReason::ForForceExitFullscreen
|| !aFullscreen))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aReason != FullscreenReason::ForForceExitFullscreen || !aFullscreen"
" (" "FullscreenReason::ForForceExitFullscreen can " "only be used with exiting fullscreen"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4272); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aReason != FullscreenReason::ForForceExitFullscreen || !aFullscreen"
") (" "FullscreenReason::ForForceExitFullscreen can " "only be used with exiting fullscreen"
")"); do { *((volatile int*)__null) = 4272; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4271 "FullscreenReason::ForForceExitFullscreen can "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aReason != FullscreenReason::ForForceExitFullscreen ||
!aFullscreen)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aReason != FullscreenReason::ForForceExitFullscreen
|| !aFullscreen))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aReason != FullscreenReason::ForForceExitFullscreen || !aFullscreen"
" (" "FullscreenReason::ForForceExitFullscreen can " "only be used with exiting fullscreen"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4272); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aReason != FullscreenReason::ForForceExitFullscreen || !aFullscreen"
") (" "FullscreenReason::ForForceExitFullscreen can " "only be used with exiting fullscreen"
")"); do { *((volatile int*)__null) = 4272; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4272 "only be used with exiting fullscreen")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aReason != FullscreenReason::ForForceExitFullscreen ||
!aFullscreen)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aReason != FullscreenReason::ForForceExitFullscreen
|| !aFullscreen))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aReason != FullscreenReason::ForForceExitFullscreen || !aFullscreen"
" (" "FullscreenReason::ForForceExitFullscreen can " "only be used with exiting fullscreen"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4272); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aReason != FullscreenReason::ForForceExitFullscreen || !aFullscreen"
") (" "FullscreenReason::ForForceExitFullscreen can " "only be used with exiting fullscreen"
")"); do { *((volatile int*)__null) = 4272; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4273
4274 // Only chrome can change our fullscreen mode. Otherwise, the state
4275 // can only be changed for DOM fullscreen.
4276 if (aReason == FullscreenReason::ForFullscreenMode &&
4277 !nsContentUtils::LegacyIsCallerChromeOrNativeCode()) {
4278 return NS_OK;
4279 }
4280
4281 // SetFullscreen needs to be called on the root window, so get that
4282 // via the DocShell tree, and if we are not already the root,
4283 // call SetFullscreen on that window instead.
4284 nsCOMPtr<nsIDocShellTreeItem> rootItem;
4285 mDocShell->GetInProcessRootTreeItem(getter_AddRefs(rootItem));
4286 nsCOMPtr<nsPIDOMWindowOuter> window =
4287 rootItem ? rootItem->GetWindow() : nullptr;
4288 if (!window) return NS_ERROR_FAILURE;
4289 if (rootItem != mDocShell)
4290 return window->SetFullscreenInternal(aReason, aFullscreen);
4291
4292 // make sure we don't try to set full screen on a non-chrome window,
4293 // which might happen in embedding world
4294 if (mDocShell->ItemType() != nsIDocShellTreeItem::typeChrome)
4295 return NS_ERROR_FAILURE;
4296
4297 // FullscreenReason::ForForceExitFullscreen can only be used with exiting
4298 // fullscreen
4299 MOZ_ASSERT_IF(do { if (mFullscreen.isSome()) { do { static_assert( mozilla::
detail::AssertionConditionType<decltype(mFullscreen.value(
) != FullscreenReason::ForForceExitFullscreen)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mFullscreen.value() != FullscreenReason
::ForForceExitFullscreen))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mFullscreen.value() != FullscreenReason::ForForceExitFullscreen"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4301); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFullscreen.value() != FullscreenReason::ForForceExitFullscreen"
")"); do { *((volatile int*)__null) = 4301; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4300 mFullscreen.isSome(),do { if (mFullscreen.isSome()) { do { static_assert( mozilla::
detail::AssertionConditionType<decltype(mFullscreen.value(
) != FullscreenReason::ForForceExitFullscreen)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mFullscreen.value() != FullscreenReason
::ForForceExitFullscreen))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mFullscreen.value() != FullscreenReason::ForForceExitFullscreen"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4301); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFullscreen.value() != FullscreenReason::ForForceExitFullscreen"
")"); do { *((volatile int*)__null) = 4301; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4301 mFullscreen.value() != FullscreenReason::ForForceExitFullscreen)do { if (mFullscreen.isSome()) { do { static_assert( mozilla::
detail::AssertionConditionType<decltype(mFullscreen.value(
) != FullscreenReason::ForForceExitFullscreen)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mFullscreen.value() != FullscreenReason
::ForForceExitFullscreen))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mFullscreen.value() != FullscreenReason::ForForceExitFullscreen"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4301); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFullscreen.value() != FullscreenReason::ForForceExitFullscreen"
")"); do { *((volatile int*)__null) = 4301; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4302
4303 // If we are already in full screen mode, just return, we don't care about the
4304 // reason here, because,
4305 // - If we are in fullscreen mode due to browser fullscreen mode, requesting
4306 // DOM fullscreen does not change anything.
4307 // - If we are in fullscreen mode due to DOM fullscreen, requesting browser
4308 // fullscreen should not change anything, either. Note that we should not
4309 // update reason to ForFullscreenMode, otherwise the subsequent DOM
4310 // fullscreen exit will be ignored and user will be confused. And ideally
4311 // this should never happen as `window.fullscreen` returns `true` for DOM
4312 // fullscreen as well.
4313 if (mFullscreen.isSome() == aFullscreen) {
4314 // How come we get browser fullscreen request while we are already in DOM
4315 // fullscreen?
4316 MOZ_ASSERT_IF(aFullscreen && aReason == FullscreenReason::ForFullscreenMode,do { if (aFullscreen && aReason == FullscreenReason::
ForFullscreenMode) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(mFullscreen.value() != FullscreenReason::ForFullscreenAPI
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mFullscreen.value() != FullscreenReason::ForFullscreenAPI
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mFullscreen.value() != FullscreenReason::ForFullscreenAPI", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4317); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFullscreen.value() != FullscreenReason::ForFullscreenAPI"
")"); do { *((volatile int*)__null) = 4317; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4317 mFullscreen.value() != FullscreenReason::ForFullscreenAPI)do { if (aFullscreen && aReason == FullscreenReason::
ForFullscreenMode) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(mFullscreen.value() != FullscreenReason::ForFullscreenAPI
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mFullscreen.value() != FullscreenReason::ForFullscreenAPI
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mFullscreen.value() != FullscreenReason::ForFullscreenAPI", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4317); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFullscreen.value() != FullscreenReason::ForFullscreenAPI"
")"); do { *((volatile int*)__null) = 4317; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4318 return NS_OK;
4319 }
4320
4321 // Note that although entering DOM fullscreen could also cause
4322 // consequential calls to this method, those calls will be skipped
4323 // at the condition above.
4324 if (aReason == FullscreenReason::ForFullscreenMode) {
4325 if (!aFullscreen && mFullscreen &&
4326 mFullscreen.value() == FullscreenReason::ForFullscreenAPI) {
4327 // If we are exiting fullscreen mode, but we actually didn't
4328 // entered browser fullscreen mode, the fullscreen state was only for
4329 // the Fullscreen API. Change the reason here so that we can
4330 // perform transition for it.
4331 aReason = FullscreenReason::ForFullscreenAPI;
4332 }
4333 } else {
4334 // If we are exiting from DOM fullscreen while we initially make
4335 // the window fullscreen because of browser fullscreen mode, don't restore
4336 // the window. But we still need to exit the DOM fullscreen state.
4337 if (!aFullscreen && mFullscreen &&
4338 mFullscreen.value() == FullscreenReason::ForFullscreenMode) {
4339 // If there is a in-process fullscreen request, FinishDOMFullscreenChange
4340 // will be called when the request is finished.
4341 if (!mInProcessFullscreenRequest.isSome()) {
4342 FinishDOMFullscreenChange(mDoc, false);
4343 }
4344 return NS_OK;
4345 }
4346 }
4347
4348 // Set this before so if widget sends an event indicating its
4349 // gone full screen, the state trap above works.
4350 if (aFullscreen) {
4351 mFullscreen.emplace(aReason);
4352 } else {
4353 mFullscreen.reset();
4354 }
4355
4356 // If we are in process of fullscreen request, only keep the latest fullscreen
4357 // state, we will sync up later while the processing request is finished.
4358 if (mInProcessFullscreenRequest.isSome()) {
4359 mFullscreenHasChangedDuringProcessing = true;
4360 return NS_OK;
4361 }
4362
4363 return ProcessWidgetFullscreenRequest(aReason, aFullscreen);
4364}
4365
4366// Support a per-window, dynamic equivalent of enabling
4367// full-screen-api.ignore-widgets
4368void nsGlobalWindowOuter::ForceFullScreenInWidget() {
4369 MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4369); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { *((volatile int*)__null) = 4369; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4370
4371 mForceFullScreenInWidget = true;
4372}
4373
4374bool nsGlobalWindowOuter::SetWidgetFullscreen(FullscreenReason aReason,
4375 bool aIsFullscreen,
4376 nsIWidget* aWidget) {
4377 MOZ_ASSERT(this == GetInProcessTopInternal(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(this == GetInProcessTopInternal())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(this == GetInProcessTopInternal
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("this == GetInProcessTopInternal()" " (" "Only topmost window should call this"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4378); AnnotateMozCrashReason("MOZ_ASSERT" "(" "this == GetInProcessTopInternal()"
") (" "Only topmost window should call this" ")"); do { *((volatile
int*)__null) = 4378; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
4378 "Only topmost window should call this")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(this == GetInProcessTopInternal())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(this == GetInProcessTopInternal
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("this == GetInProcessTopInternal()" " (" "Only topmost window should call this"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4378); AnnotateMozCrashReason("MOZ_ASSERT" "(" "this == GetInProcessTopInternal()"
") (" "Only topmost window should call this" ")"); do { *((volatile
int*)__null) = 4378; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
4379 MOZ_ASSERT(!GetFrameElementInternal(), "Content window should not call this")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!GetFrameElementInternal())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!GetFrameElementInternal()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!GetFrameElementInternal()"
" (" "Content window should not call this" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4379); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!GetFrameElementInternal()"
") (" "Content window should not call this" ")"); do { *((volatile
int*)__null) = 4379; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
4380 MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_GetProcessType() == GeckoProcessType_Default)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(XRE_GetProcessType() == GeckoProcessType_Default))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("XRE_GetProcessType() == GeckoProcessType_Default"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4380); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_GetProcessType() == GeckoProcessType_Default"
")"); do { *((volatile int*)__null) = 4380; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4381
4382 if (!NS_WARN_IF(!IsChromeWindow())NS_warn_if_impl(!IsChromeWindow(), "!IsChromeWindow()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4382)
) {
4383 if (!NS_WARN_IF(mChromeFields.mFullscreenPresShell)NS_warn_if_impl(mChromeFields.mFullscreenPresShell, "mChromeFields.mFullscreenPresShell"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4383)
) {
4384 if (PresShell* presShell = mDocShell->GetPresShell()) {
4385 if (nsRefreshDriver* rd = presShell->GetRefreshDriver()) {
4386 mChromeFields.mFullscreenPresShell = do_GetWeakReference(presShell);
4387 MOZ_ASSERT(mChromeFields.mFullscreenPresShell)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mChromeFields.mFullscreenPresShell)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mChromeFields.mFullscreenPresShell
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mChromeFields.mFullscreenPresShell", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4387); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mChromeFields.mFullscreenPresShell"
")"); do { *((volatile int*)__null) = 4387; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4388 rd->SetIsResizeSuppressed();
4389 rd->Freeze();
4390 }
4391 }
4392 }
4393 }
4394 nsresult rv = aReason == FullscreenReason::ForFullscreenMode
4395 ?
4396 // If we enter fullscreen for fullscreen mode, we want
4397 // the native system behavior.
4398 aWidget->MakeFullScreenWithNativeTransition(aIsFullscreen)
4399 : aWidget->MakeFullScreen(aIsFullscreen);
4400 return NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)));
4401}
4402
4403/* virtual */
4404void nsGlobalWindowOuter::FullscreenWillChange(bool aIsFullscreen) {
4405 if (!mInProcessFullscreenRequest.isSome()) {
4406 // If there is no in-process fullscreen request, the fullscreen state change
4407 // is triggered from the OS directly, e.g. user use built-in window button
4408 // to enter/exit fullscreen on macOS.
4409 mInProcessFullscreenRequest.emplace(FullscreenReason::ForFullscreenMode,
4410 aIsFullscreen);
4411 if (mFullscreen.isSome() != aIsFullscreen) {
4412 if (aIsFullscreen) {
4413 mFullscreen.emplace(FullscreenReason::ForFullscreenMode);
4414 } else {
4415 mFullscreen.reset();
4416 }
4417 } else {
4418 // It is possible that FullscreenWillChange is notified with current
4419 // fullscreen state, e.g. browser goes into fullscreen when widget
4420 // fullscreen is prevented, and then user triggers fullscreen from the OS
4421 // directly again.
4422 MOZ_ASSERT(StaticPrefs::full_screen_api_ignore_widgets() ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(StaticPrefs::full_screen_api_ignore_widgets() || mForceFullScreenInWidget
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(StaticPrefs::full_screen_api_ignore_widgets() || mForceFullScreenInWidget
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"StaticPrefs::full_screen_api_ignore_widgets() || mForceFullScreenInWidget"
" (" "This should only happen when widget fullscreen is prevented"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4424); AnnotateMozCrashReason("MOZ_ASSERT" "(" "StaticPrefs::full_screen_api_ignore_widgets() || mForceFullScreenInWidget"
") (" "This should only happen when widget fullscreen is prevented"
")"); do { *((volatile int*)__null) = 4424; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4423 mForceFullScreenInWidget,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(StaticPrefs::full_screen_api_ignore_widgets() || mForceFullScreenInWidget
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(StaticPrefs::full_screen_api_ignore_widgets() || mForceFullScreenInWidget
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"StaticPrefs::full_screen_api_ignore_widgets() || mForceFullScreenInWidget"
" (" "This should only happen when widget fullscreen is prevented"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4424); AnnotateMozCrashReason("MOZ_ASSERT" "(" "StaticPrefs::full_screen_api_ignore_widgets() || mForceFullScreenInWidget"
") (" "This should only happen when widget fullscreen is prevented"
")"); do { *((volatile int*)__null) = 4424; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4424 "This should only happen when widget fullscreen is prevented")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(StaticPrefs::full_screen_api_ignore_widgets() || mForceFullScreenInWidget
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(StaticPrefs::full_screen_api_ignore_widgets() || mForceFullScreenInWidget
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"StaticPrefs::full_screen_api_ignore_widgets() || mForceFullScreenInWidget"
" (" "This should only happen when widget fullscreen is prevented"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4424); AnnotateMozCrashReason("MOZ_ASSERT" "(" "StaticPrefs::full_screen_api_ignore_widgets() || mForceFullScreenInWidget"
") (" "This should only happen when widget fullscreen is prevented"
")"); do { *((volatile int*)__null) = 4424; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4425 }
4426 }
4427 if (aIsFullscreen) {
4428 DispatchCustomEvent(u"willenterfullscreen"_ns, ChromeOnlyDispatch::eYes);
4429 } else {
4430 DispatchCustomEvent(u"willexitfullscreen"_ns, ChromeOnlyDispatch::eYes);
4431 }
4432}
4433
4434/* virtual */
4435void nsGlobalWindowOuter::FinishFullscreenChange(bool aIsFullscreen) {
4436 mozilla::Maybe<FullscreenRequest> currentInProcessRequest =
4437 std::move(mInProcessFullscreenRequest);
4438 if (!mFullscreenHasChangedDuringProcessing &&
4439 aIsFullscreen != mFullscreen.isSome()) {
4440 NS_WARNING("Failed to toggle fullscreen state of the widget")NS_DebugBreak(NS_DEBUG_WARNING, "Failed to toggle fullscreen state of the widget"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4440)
;
4441 // We failed to make the widget enter fullscreen.
4442 // Stop further changes and restore the state.
4443 if (!aIsFullscreen) {
4444 mFullscreen.reset();
4445 } else {
4446#ifndef XP_MACOSX
4447 MOZ_ASSERT_UNREACHABLE("Failed to exit fullscreen?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Failed to exit fullscreen?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4447); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Failed to exit fullscreen?" ")")
; do { *((volatile int*)__null) = 4447; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4448#endif
4449 // Restore fullscreen state with FullscreenReason::ForFullscreenAPI reason
4450 // in order to make subsequent DOM fullscreen exit request can exit
4451 // browser fullscreen mode.
4452 mFullscreen.emplace(FullscreenReason::ForFullscreenAPI);
4453 }
4454 return;
4455 }
4456
4457 // Note that we must call this to toggle the DOM fullscreen state
4458 // of the document before dispatching the "fullscreen" event, so
4459 // that the chrome can distinguish between browser fullscreen mode
4460 // and DOM fullscreen.
4461 FinishDOMFullscreenChange(mDoc, aIsFullscreen);
4462
4463 // dispatch a "fullscreen" DOM event so that XUL apps can
4464 // respond visually if we are kicked into full screen mode
4465 DispatchCustomEvent(u"fullscreen"_ns, ChromeOnlyDispatch::eYes);
4466
4467 if (!NS_WARN_IF(!IsChromeWindow())NS_warn_if_impl(!IsChromeWindow(), "!IsChromeWindow()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4467)
) {
4468 if (RefPtr<PresShell> presShell =
4469 do_QueryReferent(mChromeFields.mFullscreenPresShell)) {
4470 if (nsRefreshDriver* rd = presShell->GetRefreshDriver()) {
4471 rd->Thaw();
4472 }
4473 mChromeFields.mFullscreenPresShell = nullptr;
4474 }
4475 }
4476
4477 // If fullscreen state has changed during processing fullscreen request, we
4478 // need to ensure widget matches our latest fullscreen state here.
4479 if (mFullscreenHasChangedDuringProcessing) {
4480 mFullscreenHasChangedDuringProcessing = false;
4481 // Widget doesn't care about the reason that makes it entering/exiting
4482 // fullscreen, so here we just need to ensure the fullscreen state is
4483 // matched.
4484 if (aIsFullscreen != mFullscreen.isSome()) {
4485 // If we end up need to exit fullscreen, use the same reason that brings
4486 // us into fullscreen mode, so that we will perform the same fullscreen
4487 // transistion effect for exiting.
4488 ProcessWidgetFullscreenRequest(
4489 mFullscreen.isSome() ? mFullscreen.value()
4490 : currentInProcessRequest.value().mReason,
4491 mFullscreen.isSome());
4492 }
4493 }
4494}
4495
4496/* virtual */
4497void nsGlobalWindowOuter::MacFullscreenMenubarOverlapChanged(
4498 mozilla::DesktopCoord aOverlapAmount) {
4499 ErrorResult res;
4500 RefPtr<Event> domEvent =
4501 mDoc->CreateEvent(u"CustomEvent"_ns, CallerType::System, res);
4502 if (res.Failed()) {
4503 return;
4504 }
4505
4506 AutoJSAPI jsapi;
4507 jsapi.Init();
4508 JSContext* cx = jsapi.cx();
4509 JSAutoRealm ar(cx, GetWrapperPreserveColor());
4510
4511 JS::Rooted<JS::Value> detailValue(cx);
4512 if (!ToJSValue(cx, aOverlapAmount, &detailValue)) {
4513 return;
4514 }
4515
4516 CustomEvent* customEvent = static_cast<CustomEvent*>(domEvent.get());
4517 customEvent->InitCustomEvent(cx, u"MacFullscreenMenubarRevealUpdate"_ns,
4518 /* aCanBubble = */ true,
4519 /* aCancelable = */ true, detailValue);
4520 domEvent->SetTrusted(true);
4521 domEvent->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = true;
4522
4523 nsCOMPtr<EventTarget> target = this;
4524 domEvent->SetTarget(target);
4525
4526 target->DispatchEvent(*domEvent, CallerType::System, IgnoreErrors());
4527}
4528
4529bool nsGlobalWindowOuter::Fullscreen() const {
4530 NS_ENSURE_TRUE(mDocShell, mFullscreen.isSome())do { if ((__builtin_expect(!!(!(mDocShell)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocShell" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4530); return mFullscreen.isSome(); } } while (false)
;
4531
4532 // Get the fullscreen value of the root window, to always have the value
4533 // accurate, even when called from content.
4534 nsCOMPtr<nsIDocShellTreeItem> rootItem;
4535 mDocShell->GetInProcessRootTreeItem(getter_AddRefs(rootItem));
4536 if (rootItem == mDocShell) {
4537 if (!XRE_IsContentProcess()) {
4538 // We are the root window. Return our internal value.
4539 return mFullscreen.isSome();
4540 }
4541 if (nsCOMPtr<nsIWidget> widget = GetNearestWidget()) {
4542 // We are in content process, figure out the value from
4543 // the sizemode of the puppet widget.
4544 return widget->SizeMode() == nsSizeMode_Fullscreen;
4545 }
4546 return false;
4547 }
4548
4549 nsCOMPtr<nsPIDOMWindowOuter> window = rootItem->GetWindow();
4550 NS_ENSURE_TRUE(window, mFullscreen.isSome())do { if ((__builtin_expect(!!(!(window)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "window" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4550); return mFullscreen.isSome(); } } while (false)
;
4551
4552 return nsGlobalWindowOuter::Cast(window)->Fullscreen();
4553}
4554
4555bool nsGlobalWindowOuter::GetFullscreenOuter() { return Fullscreen(); }
4556
4557bool nsGlobalWindowOuter::GetFullScreen() {
4558 FORWARD_TO_INNER(GetFullScreen, (), false)do { if (!mInnerWindow) { NS_DebugBreak(NS_DEBUG_WARNING, "No inner window available!"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4558); return false; } return GetCurrentInnerWindowInternal
(this)->GetFullScreen (); } while (0)
;
4559}
4560
4561void nsGlobalWindowOuter::EnsureReflowFlushAndPaint() {
4562 NS_ASSERTION(mDocShell,do { if (!(mDocShell)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "EnsureReflowFlushAndPaint() called with no "
"docshell!", "mDocShell", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4564); MOZ_PretendNoReturn(); } } while (0)
4563 "EnsureReflowFlushAndPaint() called with no "do { if (!(mDocShell)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "EnsureReflowFlushAndPaint() called with no "
"docshell!", "mDocShell", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4564); MOZ_PretendNoReturn(); } } while (0)
4564 "docshell!")do { if (!(mDocShell)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "EnsureReflowFlushAndPaint() called with no "
"docshell!", "mDocShell", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4564); MOZ_PretendNoReturn(); } } while (0)
;
4565
4566 if (!mDocShell) return;
4567
4568 RefPtr<PresShell> presShell = mDocShell->GetPresShell();
4569 if (!presShell) {
4570 return;
4571 }
4572
4573 // Flush pending reflows.
4574 if (mDoc) {
4575 mDoc->FlushPendingNotifications(FlushType::Layout);
4576 }
4577
4578 // Unsuppress painting.
4579 presShell->UnsuppressPainting();
4580}
4581
4582// static
4583void nsGlobalWindowOuter::MakeMessageWithPrincipal(
4584 nsAString& aOutMessage, nsIPrincipal* aSubjectPrincipal, bool aUseHostPort,
4585 const char* aNullMessage, const char* aContentMessage,
4586 const char* aFallbackMessage) {
4587 MOZ_ASSERT(aSubjectPrincipal)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aSubjectPrincipal)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aSubjectPrincipal))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("aSubjectPrincipal"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4587); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSubjectPrincipal"
")"); do { *((volatile int*)__null) = 4587; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4588
4589 aOutMessage.Truncate();
4590
4591 // Try to get a host from the running principal -- this will do the
4592 // right thing for javascript: and data: documents.
4593
4594 nsAutoCString contentDesc;
4595
4596 if (aSubjectPrincipal->GetIsNullPrincipal()) {
4597 nsContentUtils::GetLocalizedString(
4598 nsContentUtils::eCOMMON_DIALOG_PROPERTIES, aNullMessage, aOutMessage);
4599 } else {
4600 auto* addonPolicy = BasePrincipal::Cast(aSubjectPrincipal)->AddonPolicy();
4601 if (addonPolicy) {
4602 nsContentUtils::FormatLocalizedString(
4603 aOutMessage, nsContentUtils::eCOMMON_DIALOG_PROPERTIES,
4604 aContentMessage, addonPolicy->Name());
4605 } else {
4606 nsresult rv = NS_ERROR_FAILURE;
4607 if (aUseHostPort) {
4608 nsCOMPtr<nsIURI> uri = aSubjectPrincipal->GetURI();
4609 if (uri) {
4610 rv = uri->GetDisplayHostPort(contentDesc);
4611 }
4612 }
4613 if (!aUseHostPort || NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4614 rv = aSubjectPrincipal->GetExposablePrePath(contentDesc);
4615 }
4616 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !contentDesc.IsEmpty()) {
4617 NS_ConvertUTF8toUTF16 ucsPrePath(contentDesc);
4618 nsContentUtils::FormatLocalizedString(
4619 aOutMessage, nsContentUtils::eCOMMON_DIALOG_PROPERTIES,
4620 aContentMessage, ucsPrePath);
4621 }
4622 }
4623 }
4624
4625 if (aOutMessage.IsEmpty()) {
4626 // We didn't find a host so use the generic heading
4627 nsContentUtils::GetLocalizedString(
4628 nsContentUtils::eCOMMON_DIALOG_PROPERTIES, aFallbackMessage,
4629 aOutMessage);
4630 }
4631
4632 // Just in case
4633 if (aOutMessage.IsEmpty()) {
4634 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "could not get ScriptDlgGenericHeading string from string bundle"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4635)
4635 "could not get ScriptDlgGenericHeading string from string bundle")NS_DebugBreak(NS_DEBUG_WARNING, "could not get ScriptDlgGenericHeading string from string bundle"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4635)
;
4636 aOutMessage.AssignLiteral("[Script]");
4637 }
4638}
4639
4640bool nsGlobalWindowOuter::CanMoveResizeWindows(CallerType aCallerType) {
4641 // When called from chrome, we can avoid the following checks.
4642 if (aCallerType != CallerType::System) {
4643 // Don't allow scripts to move or resize windows that were not opened by a
4644 // script.
4645 if (!mBrowsingContext->HadOriginalOpener()) {
4646 return false;
4647 }
4648
4649 if (!CanSetProperty("dom.disable_window_move_resize")) {
4650 return false;
4651 }
4652
4653 // Ignore the request if we have more than one tab in the window.
4654 if (mBrowsingContext->Top()->HasSiblings()) {
4655 return false;
4656 }
4657 }
4658
4659 if (mDocShell) {
4660 bool allow;
4661 nsresult rv = mDocShell->GetAllowWindowControl(&allow);
4662 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !allow) return false;
4663 }
4664
4665 if (nsGlobalWindowInner::sMouseDown &&
4666 !nsGlobalWindowInner::sDragServiceDisabled) {
4667 nsCOMPtr<nsIDragService> ds =
4668 do_GetService("@mozilla.org/widget/dragservice;1");
4669 if (ds) {
4670 nsGlobalWindowInner::sDragServiceDisabled = true;
4671 ds->Suppress();
4672 }
4673 }
4674 return true;
4675}
4676
4677bool nsGlobalWindowOuter::AlertOrConfirm(bool aAlert, const nsAString& aMessage,
4678 nsIPrincipal& aSubjectPrincipal,
4679 ErrorResult& aError) {
4680 // XXX This method is very similar to nsGlobalWindowOuter::Prompt, make
4681 // sure any modifications here don't need to happen over there!
4682 if (!AreDialogsEnabled()) {
4683 // Just silently return. In the case of alert(), the return value is
4684 // ignored. In the case of confirm(), returning false is the same thing as
4685 // would happen if the user cancels.
4686 return false;
4687 }
4688
4689 // Reset popup state while opening a modal dialog, and firing events
4690 // about the dialog, to prevent the current state from being active
4691 // the whole time a modal dialog is open.
4692 AutoPopupStatePusherAutoPopupStatePusherInternal popupStatePusher(PopupBlocker::openAbused, true);
4693
4694 // Before bringing up the window, unsuppress painting and flush
4695 // pending reflows.
4696 EnsureReflowFlushAndPaint();
4697
4698 nsAutoString title;
4699 MakeMessageWithPrincipal(title, &aSubjectPrincipal, false,
4700 "ScriptDlgNullPrincipalHeading", "ScriptDlgHeading",
4701 "ScriptDlgGenericHeading");
4702
4703 // Remove non-terminating null characters from the
4704 // string. See bug #310037.
4705 nsAutoString final;
4706 nsContentUtils::StripNullChars(aMessage, final);
4707 nsContentUtils::PlatformToDOMLineBreaks(final);
4708
4709 nsresult rv;
4710 nsCOMPtr<nsIPromptFactory> promptFac =
4711 do_GetService("@mozilla.org/prompter;1", &rv);
4712 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4713 aError.Throw(rv);
4714 return false;
4715 }
4716
4717 nsCOMPtr<nsIPrompt> prompt;
4718 aError =
4719 promptFac->GetPrompt(this, NS_GET_IID(nsIPrompt)(nsIPrompt::COMTypeInfo<nsIPrompt, void>::kIID), getter_AddRefs(prompt));
4720 if (aError.Failed()) {
4721 return false;
4722 }
4723
4724 // Always allow content modal prompts for alert and confirm.
4725 if (nsCOMPtr<nsIWritablePropertyBag2> promptBag = do_QueryInterface(prompt)) {
4726 promptBag->SetPropertyAsUint32(u"modalType"_ns,
4727 nsIPrompt::MODAL_TYPE_CONTENT);
4728 }
4729
4730 bool result = false;
4731 nsAutoSyncOperation sync(mDoc, SyncOperationBehavior::eSuspendInput);
4732 if (ShouldPromptToBlockDialogs()) {
4733 bool disallowDialog = false;
4734 nsAutoString label;
4735 MakeMessageWithPrincipal(
4736 label, &aSubjectPrincipal, true, "ScriptDialogLabelNullPrincipal",
4737 "ScriptDialogLabelContentPrincipal", "ScriptDialogLabelNullPrincipal");
4738
4739 aError = aAlert
4740 ? prompt->AlertCheck(title.get(), final.get(), label.get(),
4741 &disallowDialog)
4742 : prompt->ConfirmCheck(title.get(), final.get(), label.get(),
4743 &disallowDialog, &result);
4744
4745 if (disallowDialog) {
4746 DisableDialogs();
4747 }
4748 } else {
4749 aError = aAlert ? prompt->Alert(title.get(), final.get())
4750 : prompt->Confirm(title.get(), final.get(), &result);
4751 }
4752
4753 return result;
4754}
4755
4756void nsGlobalWindowOuter::AlertOuter(const nsAString& aMessage,
4757 nsIPrincipal& aSubjectPrincipal,
4758 ErrorResult& aError) {
4759 AlertOrConfirm(/* aAlert = */ true, aMessage, aSubjectPrincipal, aError);
4760}
4761
4762bool nsGlobalWindowOuter::ConfirmOuter(const nsAString& aMessage,
4763 nsIPrincipal& aSubjectPrincipal,
4764 ErrorResult& aError) {
4765 return AlertOrConfirm(/* aAlert = */ false, aMessage, aSubjectPrincipal,
4766 aError);
4767}
4768
4769void nsGlobalWindowOuter::PromptOuter(const nsAString& aMessage,
4770 const nsAString& aInitial,
4771 nsAString& aReturn,
4772 nsIPrincipal& aSubjectPrincipal,
4773 ErrorResult& aError) {
4774 // XXX This method is very similar to nsGlobalWindowOuter::AlertOrConfirm,
4775 // make sure any modifications here don't need to happen over there!
4776 SetDOMStringToNull(aReturn);
4777
4778 if (!AreDialogsEnabled()) {
4779 // Return null, as if the user just canceled the prompt.
4780 return;
4781 }
4782
4783 // Reset popup state while opening a modal dialog, and firing events
4784 // about the dialog, to prevent the current state from being active
4785 // the whole time a modal dialog is open.
4786 AutoPopupStatePusherAutoPopupStatePusherInternal popupStatePusher(PopupBlocker::openAbused, true);
4787
4788 // Before bringing up the window, unsuppress painting and flush
4789 // pending reflows.
4790 EnsureReflowFlushAndPaint();
4791
4792 nsAutoString title;
4793 MakeMessageWithPrincipal(title, &aSubjectPrincipal, false,
4794 "ScriptDlgNullPrincipalHeading", "ScriptDlgHeading",
4795 "ScriptDlgGenericHeading");
4796
4797 // Remove non-terminating null characters from the
4798 // string. See bug #310037.
4799 nsAutoString fixedMessage, fixedInitial;
4800 nsContentUtils::StripNullChars(aMessage, fixedMessage);
4801 nsContentUtils::PlatformToDOMLineBreaks(fixedMessage);
4802 nsContentUtils::StripNullChars(aInitial, fixedInitial);
4803
4804 nsresult rv;
4805 nsCOMPtr<nsIPromptFactory> promptFac =
4806 do_GetService("@mozilla.org/prompter;1", &rv);
4807 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4808 aError.Throw(rv);
4809 return;
4810 }
4811
4812 nsCOMPtr<nsIPrompt> prompt;
4813 aError =
4814 promptFac->GetPrompt(this, NS_GET_IID(nsIPrompt)(nsIPrompt::COMTypeInfo<nsIPrompt, void>::kIID), getter_AddRefs(prompt));
4815 if (aError.Failed()) {
4816 return;
4817 }
4818
4819 // Always allow content modal prompts for prompt.
4820 if (nsCOMPtr<nsIWritablePropertyBag2> promptBag = do_QueryInterface(prompt)) {
4821 promptBag->SetPropertyAsUint32(u"modalType"_ns,
4822 nsIPrompt::MODAL_TYPE_CONTENT);
4823 }
4824
4825 // Pass in the default value, if any.
4826 char16_t* inoutValue = ToNewUnicode(fixedInitial);
4827 bool disallowDialog = false;
4828
4829 nsAutoString label;
4830 label.SetIsVoid(true);
4831 if (ShouldPromptToBlockDialogs()) {
4832 nsContentUtils::GetLocalizedString(
4833 nsContentUtils::eCOMMON_DIALOG_PROPERTIES, "ScriptDialogLabel", label);
4834 }
4835
4836 nsAutoSyncOperation sync(mDoc, SyncOperationBehavior::eSuspendInput);
4837 bool ok;
4838 aError = prompt->Prompt(title.get(), fixedMessage.get(), &inoutValue,
4839 label.IsVoid() ? nullptr : label.get(),
4840 &disallowDialog, &ok);
4841
4842 if (disallowDialog) {
4843 DisableDialogs();
4844 }
4845
4846 // XXX Doesn't this leak inoutValue?
4847 if (aError.Failed()) {
4848 return;
4849 }
4850
4851 nsString outValue;
4852 outValue.Adopt(inoutValue);
4853 if (ok && inoutValue) {
4854 aReturn = std::move(outValue);
4855 }
4856}
4857
4858void nsGlobalWindowOuter::FocusOuter(CallerType aCallerType,
4859 bool aFromOtherProcess,
4860 uint64_t aActionId) {
4861 RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager();
4862 if (MOZ_UNLIKELY(!fm)(__builtin_expect(!!(!fm), 0))) {
4863 return;
4864 }
4865
4866 auto [canFocus, isActive] = GetBrowsingContext()->CanFocusCheck(aCallerType);
4867 if (aFromOtherProcess) {
4868 // We trust that the check passed in a process that's, in principle,
4869 // untrusted, because we don't have the required caller context available
4870 // here. Also, the worst that the other process can do in this case is to
4871 // raise a window it's not supposed to be allowed to raise.
4872 // https://bugzilla.mozilla.org/show_bug.cgi?id=1677899
4873 MOZ_ASSERT(XRE_IsContentProcess(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsContentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsContentProcess()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsContentProcess()"
" (" "Parent should not trust other processes." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4874); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsContentProcess()"
") (" "Parent should not trust other processes." ")"); do { *
((volatile int*)__null) = 4874; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
4874 "Parent should not trust other processes.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsContentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsContentProcess()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsContentProcess()"
" (" "Parent should not trust other processes." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4874); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsContentProcess()"
") (" "Parent should not trust other processes." ")"); do { *
((volatile int*)__null) = 4874; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
4875 canFocus = true;
4876 }
4877
4878 nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
4879 if (treeOwnerAsWin && (canFocus || isActive)) {
4880 bool isEnabled = true;
4881 if (NS_SUCCEEDED(treeOwnerAsWin->GetEnabled(&isEnabled))((bool)(__builtin_expect(!!(!NS_FAILED_impl(treeOwnerAsWin->
GetEnabled(&isEnabled))), 1)))
&& !isEnabled) {
4882 NS_WARNING("Should not try to set the focus on a disabled window")NS_DebugBreak(NS_DEBUG_WARNING, "Should not try to set the focus on a disabled window"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4882)
;
4883 return;
4884 }
4885 }
4886
4887 if (!mDocShell) {
4888 return;
4889 }
4890
4891 // If the window has a child frame focused, clear the focus. This
4892 // ensures that focus will be in this frame and not in a child.
4893 if (nsIContent* content = GetFocusedElement()) {
4894 if (HTMLIFrameElement::FromNode(content)) {
4895 fm->ClearFocus(this);
4896 }
4897 }
4898
4899 RefPtr<BrowsingContext> parent;
4900 BrowsingContext* bc = GetBrowsingContext();
4901 if (bc) {
4902 parent = bc->GetParent();
4903 if (!parent && XRE_IsParentProcess()) {
4904 parent = bc->Canonical()->GetParentCrossChromeBoundary();
4905 }
4906 }
4907 if (parent) {
4908 if (!parent->IsInProcess()) {
4909 if (isActive) {
4910 OwningNonNull<nsGlobalWindowOuter> kungFuDeathGrip(*this);
4911 fm->WindowRaised(kungFuDeathGrip, aActionId);
4912 } else {
4913 ContentChild* contentChild = ContentChild::GetSingleton();
4914 MOZ_ASSERT(contentChild)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(contentChild)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(contentChild))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("contentChild", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4914); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentChild"
")"); do { *((volatile int*)__null) = 4914; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4915 contentChild->SendFinalizeFocusOuter(bc, canFocus, aCallerType);
4916 }
4917 return;
4918 }
4919
4920 MOZ_ASSERT(mDoc, "Call chain should have ensured document creation.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDoc)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(mDoc))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("mDoc" " (" "Call chain should have ensured document creation."
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4920); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDoc" ") ("
"Call chain should have ensured document creation." ")"); do
{ *((volatile int*)__null) = 4920; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
4921 if (mDoc) {
4922 if (Element* frame = mDoc->GetEmbedderElement()) {
4923 nsContentUtils::RequestFrameFocus(*frame, canFocus, aCallerType);
4924 }
4925 }
4926 return;
4927 }
4928
4929 if (canFocus) {
4930 // if there is no parent, this must be a toplevel window, so raise the
4931 // window if canFocus is true. If this is a child process, the raise
4932 // window request will get forwarded to the parent by the puppet widget.
4933 OwningNonNull<nsGlobalWindowOuter> kungFuDeathGrip(*this);
4934 fm->RaiseWindow(kungFuDeathGrip, aCallerType, aActionId);
4935 }
4936}
4937
4938nsresult nsGlobalWindowOuter::Focus(CallerType aCallerType) {
4939 FORWARD_TO_INNER(Focus, (aCallerType), NS_ERROR_UNEXPECTED)do { if (!mInnerWindow) { NS_DebugBreak(NS_DEBUG_WARNING, "No inner window available!"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4939); return NS_ERROR_UNEXPECTED; } return GetCurrentInnerWindowInternal
(this)->Focus (aCallerType); } while (0)
;
4940}
4941
4942void nsGlobalWindowOuter::BlurOuter(CallerType aCallerType) {
4943 if (!GetBrowsingContext()->CanBlurCheck(aCallerType)) {
4944 return;
4945 }
4946
4947 nsCOMPtr<nsIWebBrowserChrome> chrome = GetWebBrowserChrome();
4948 if (chrome) {
4949 chrome->Blur();
4950 }
4951}
4952
4953void nsGlobalWindowOuter::StopOuter(ErrorResult& aError) {
4954 // IsNavigationAllowed checks are usually done in nsDocShell directly,
4955 // however nsDocShell::Stop has a bunch of internal users that would fail
4956 // the IsNavigationAllowed check.
4957 if (!mDocShell || !nsDocShell::Cast(mDocShell)->IsNavigationAllowed()) {
4958 return;
4959 }
4960
4961 nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(mDocShell));
4962 if (webNav) {
4963 aError = webNav->Stop(nsIWebNavigation::STOP_ALL);
4964 }
4965}
4966
4967void nsGlobalWindowOuter::PrintOuter(ErrorResult& aError) {
4968 if (!AreDialogsEnabled()) {
4969 // Per spec, silently return. https://github.com/whatwg/html/commit/21a1de1
4970 return;
4971 }
4972
4973 // Printing is disabled, silently return.
4974 if (!StaticPrefs::print_enabled()) {
4975 return;
4976 }
4977
4978 // If we're loading, queue the print for later. This is a special-case that
4979 // only applies to the window.print() call, for compat with other engines and
4980 // pre-existing behavior.
4981 if (mShouldDelayPrintUntilAfterLoad) {
4982 if (nsIDocShell* docShell = GetDocShell()) {
4983 if (docShell->GetBusyFlags() & nsIDocShell::BUSY_FLAGS_PAGE_LOADING) {
4984 mDelayedPrintUntilAfterLoad = true;
4985 return;
4986 }
4987 }
4988 }
4989
4990#ifdef NS_PRINTING1
4991 RefPtr<BrowsingContext> top =
4992 mBrowsingContext ? mBrowsingContext->Top() : nullptr;
4993 if (NS_WARN_IF(top && top->GetIsPrinting())NS_warn_if_impl(top && top->GetIsPrinting(), "top && top->GetIsPrinting()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 4993)
) {
4994 return;
4995 }
4996
4997 if (top) {
4998 Unused << top->SetIsPrinting(true);
4999 }
5000
5001 auto unset = MakeScopeExit([&] {
5002 if (top) {
5003 Unused << top->SetIsPrinting(false);
5004 }
5005 });
5006
5007 const bool forPreview = !StaticPrefs::print_always_print_silent();
5008 Print(nullptr, nullptr, nullptr, nullptr, IsPreview(forPreview),
5009 IsForWindowDotPrint::Yes, nullptr, nullptr, aError);
5010#endif
5011}
5012
5013class MOZ_RAII AutoModalState {
5014 public:
5015 explicit AutoModalState(nsGlobalWindowOuter& aWin)
5016 : mModalStateWin(aWin.EnterModalState()) {}
5017
5018 ~AutoModalState() {
5019 if (mModalStateWin) {
5020 mModalStateWin->LeaveModalState();
5021 }
5022 }
5023
5024 RefPtr<nsGlobalWindowOuter> mModalStateWin;
5025};
5026
5027Nullable<WindowProxyHolder> nsGlobalWindowOuter::Print(
5028 nsIPrintSettings* aPrintSettings, RemotePrintJobChild* aRemotePrintJob,
5029 nsIWebProgressListener* aListener, nsIDocShell* aDocShellToCloneInto,
5030 IsPreview aIsPreview, IsForWindowDotPrint aForWindowDotPrint,
5031 PrintPreviewResolver&& aPrintPreviewCallback,
5032 RefPtr<BrowsingContext>* aCachedBrowsingContext, ErrorResult& aError) {
5033#ifdef NS_PRINTING1
5034 nsCOMPtr<nsIPrintSettingsService> printSettingsService =
5035 do_GetService("@mozilla.org/gfx/printsettings-service;1");
5036 if (!printSettingsService) {
5037 // we currently return here in headless mode - should we?
5038 aError.ThrowNotSupportedError("No print settings service");
5039 return nullptr;
5040 }
5041
5042 nsCOMPtr<nsIPrintSettings> ps = aPrintSettings;
5043 if (!ps) {
5044 // We shouldn't need this once bug 1776169 is fixed.
5045 printSettingsService->GetDefaultPrintSettingsForPrinting(
5046 getter_AddRefs(ps));
5047 }
5048
5049 RefPtr<Document> docToPrint = mDoc;
5050 if (NS_WARN_IF(!docToPrint)NS_warn_if_impl(!docToPrint, "!docToPrint", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 5050)
) {
5051 aError.ThrowNotSupportedError("Document is gone");
5052 return nullptr;
5053 }
5054
5055 RefPtr<BrowsingContext> sourceBC = docToPrint->GetBrowsingContext();
5056 MOZ_DIAGNOSTIC_ASSERT(sourceBC)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sourceBC)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sourceBC))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("sourceBC", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 5056); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "sourceBC"
")"); do { *((volatile int*)__null) = 5056; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5057 if (!sourceBC) {
5058 aError.ThrowNotSupportedError("No browsing context for source document");
5059 return nullptr;
5060 }
5061
5062 nsAutoSyncOperation sync(docToPrint, SyncOperationBehavior::eAllowInput);
5063 AutoModalState modalState(*this);
5064
5065 nsCOMPtr<nsIDocumentViewer> viewer;
5066 RefPtr<BrowsingContext> bc;
5067 bool hasPrintCallbacks = false;
5068 bool wasStaticDocument = docToPrint->IsStaticDocument();
5069 bool usingCachedBrowsingContext = false;
5070 if (aCachedBrowsingContext && *aCachedBrowsingContext) {
5071 MOZ_ASSERT(!wasStaticDocument,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!wasStaticDocument)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!wasStaticDocument))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!wasStaticDocument"
" (" "Why pass in non-empty aCachedBrowsingContext if original "
"document is already static?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 5073); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!wasStaticDocument"
") (" "Why pass in non-empty aCachedBrowsingContext if original "
"document is already static?" ")"); do { *((volatile int*)__null
) = 5073; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
5072 "Why pass in non-empty aCachedBrowsingContext if original "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!wasStaticDocument)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!wasStaticDocument))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!wasStaticDocument"
" (" "Why pass in non-empty aCachedBrowsingContext if original "
"document is already static?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 5073); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!wasStaticDocument"
") (" "Why pass in non-empty aCachedBrowsingContext if original "
"document is already static?" ")"); do { *((volatile int*)__null
) = 5073; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
5073 "document is already static?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!wasStaticDocument)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!wasStaticDocument))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!wasStaticDocument"
" (" "Why pass in non-empty aCachedBrowsingContext if original "
"document is already static?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 5073); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!wasStaticDocument"
") (" "Why pass in non-empty aCachedBrowsingContext if original "
"document is already static?" ")"); do { *((volatile int*)__null
) = 5073; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
5074 if (!wasStaticDocument) {
5075 // The passed in document is not a static clone and the caller passed in a
5076 // static clone to reuse, so swap it in.
5077 docToPrint = (*aCachedBrowsingContext)->GetDocument();
5078 MOZ_ASSERT(docToPrint)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(docToPrint)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(docToPrint))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("docToPrint", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 5078); AnnotateMozCrashReason("MOZ_ASSERT" "(" "docToPrint"
")"); do { *((volatile int*)__null) = 5078; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5079 MOZ_ASSERT(docToPrint->IsStaticDocument())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(docToPrint->IsStaticDocument())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(docToPrint->IsStaticDocument
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("docToPrint->IsStaticDocument()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 5079); AnnotateMozCrashReason("MOZ_ASSERT" "(" "docToPrint->IsStaticDocument()"
")"); do { *((volatile int*)__null) = 5079; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5080 wasStaticDocument = true;
5081 usingCachedBrowsingContext = true;
5082 }
5083 }
5084 if (wasStaticDocument) {
5085 if (aForWindowDotPrint == IsForWindowDotPrint::Yes) {
5086 aError.ThrowNotSupportedError(
5087 "Calling print() from a print preview is unsupported, did you intend "
5088 "to call printPreview() instead?");
5089 return nullptr;
5090 }
5091 if (usingCachedBrowsingContext) {
5092 bc = docToPrint->GetBrowsingContext();
5093 } else {
5094 // We're already a print preview window, just reuse our browsing context /
5095 // content viewer.
5096 bc = sourceBC;
5097 }
5098 nsCOMPtr<nsIDocShell> docShell = bc->GetDocShell();
5099 if (!docShell) {
5100 aError.ThrowNotSupportedError("No docshell");
5101 return nullptr;
5102 }
5103 // We could handle this if needed.
5104 if (aDocShellToCloneInto && aDocShellToCloneInto != docShell) {
5105 aError.ThrowNotSupportedError(
5106 "We don't handle cloning a print preview doc into a different "
5107 "docshell");
5108 return nullptr;
5109 }
5110 docShell->GetDocViewer(getter_AddRefs(viewer));
5111 MOZ_DIAGNOSTIC_ASSERT(viewer)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(viewer)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(viewer))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("viewer", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 5111); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "viewer"
")"); do { *((volatile int*)__null) = 5111; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5112 } else {
5113 if (aDocShellToCloneInto) {
5114 // Ensure the content viewer is created if needed.
5115 Unused << aDocShellToCloneInto->GetDocument();
5116 bc = aDocShellToCloneInto->GetBrowsingContext();
5117 } else {
5118 AutoNoJSAPI nojsapi;
5119 auto printKind = aForWindowDotPrint == IsForWindowDotPrint::Yes
5120 ? PrintKind::WindowDotPrint
5121 : PrintKind::InternalPrint;
5122 // For PrintKind::WindowDotPrint, this call will not only make the parent
5123 // process create a CanonicalBrowsingContext for the returned `bc`, but
5124 // it will also make the parent process initiate the print/print preview.
5125 // See the handling of OPEN_PRINT_BROWSER in browser.js.
5126 aError = OpenInternal(u""_ns, u""_ns, u""_ns,
5127 false, // aDialog
5128 false, // aContentModal
5129 true, // aCalledNoScript
5130 false, // aDoJSFixups
5131 true, // aNavigate
5132 nullptr, nullptr, // No args
5133 nullptr, // aLoadState
5134 false, // aForceNoOpener
5135 printKind, getter_AddRefs(bc));
5136 if (NS_WARN_IF(aError.Failed())NS_warn_if_impl(aError.Failed(), "aError.Failed()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 5136)
) {
5137 return nullptr;
5138 }
5139 if (aCachedBrowsingContext) {
5140 MOZ_ASSERT(!*aCachedBrowsingContext)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!*aCachedBrowsingContext)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!*aCachedBrowsingContext))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("!*aCachedBrowsingContext"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 5140); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!*aCachedBrowsingContext"
")"); do { *((volatile int*)__null) = 5140; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5141 *aCachedBrowsingContext = bc;
5142 }
5143 }
5144 if (!bc) {
5145 aError.ThrowNotAllowedError("No browsing context");
5146 return nullptr;
5147 }
5148
5149 Unused << bc->Top()->SetIsPrinting(true);
5150 nsCOMPtr<nsIDocShell> cloneDocShell = bc->GetDocShell();
5151 MOZ_DIAGNOSTIC_ASSERT(cloneDocShell)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(cloneDocShell)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(cloneDocShell))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("cloneDocShell",
"/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 5151); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "cloneDocShell"
")"); do { *((volatile int*)__null) = 5151; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5152 cloneDocShell->GetDocViewer(getter_AddRefs(viewer));
5153 MOZ_DIAGNOSTIC_ASSERT(viewer)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(viewer)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(viewer))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("viewer", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 5153); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "viewer"
")"); do { *((volatile int*)__null) = 5153; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5154 if (!viewer) {
5155 aError.ThrowNotSupportedError("Didn't end up with a content viewer");
5156 return nullptr;
5157 }
5158
5159 if (bc != sourceBC) {
5160 MOZ_ASSERT(bc->IsTopContent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bc->IsTopContent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(bc->IsTopContent()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("bc->IsTopContent()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 5160); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bc->IsTopContent()"
")"); do { *((volatile int*)__null) = 5160; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5161 // If we are cloning from a document in a different BrowsingContext, we
5162 // need to make sure to copy over our opener policy information from that
5163 // BrowsingContext. In the case where the source is an iframe, this
5164 // information needs to be copied from the toplevel source
5165 // BrowsingContext, as we may be making a static clone of a single
5166 // subframe.
5167 MOZ_ALWAYS_SUCCEEDS(do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(bc->SetOpenerPolicy(sourceBC->Top()->GetOpenerPolicy
()))), 1)))), 1))) { } else { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(false)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(bc->SetOpenerPolicy(sourceBC->Top()->GetOpenerPolicy()))"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 5168); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(bc->SetOpenerPolicy(sourceBC->Top()->GetOpenerPolicy()))"
")"); do { *((volatile int*)__null) = 5168; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
5168 bc->SetOpenerPolicy(sourceBC->Top()->GetOpenerPolicy()))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(bc->SetOpenerPolicy(sourceBC->Top()->GetOpenerPolicy
()))), 1)))), 1))) { } else { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(false)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(bc->SetOpenerPolicy(sourceBC->Top()->GetOpenerPolicy()))"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 5168); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(bc->SetOpenerPolicy(sourceBC->Top()->GetOpenerPolicy()))"
")"); do { *((volatile int*)__null) = 5168; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
5169 MOZ_DIAGNOSTIC_ASSERT(bc->Group() == sourceBC->Group())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bc->Group() == sourceBC->Group())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(bc->Group() == sourceBC->Group()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("bc->Group() == sourceBC->Group()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowOuter.cpp"
, 5169); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "bc->Group() == sourceBC->Group()"
")"); do { *((volatile int*)__null) = 5169; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5170 }
5171
5172 if (RefPtr<Document> doc = viewer->GetDocument()) {
5173 if (doc->IsShowing()) {
5174 // We're going to drop this document on the floor, in the SetDocument
5175 // call below. Make sure to run OnPageHide() to keep state consistent
5176 // and avoids assertions in the document destructor.
5177 doc->OnPageHide(false, nullptr);
5178 }
5179 }
5180
5181 AutoPrintEventDispatcher dispatcher(*docToPrint);
5182
5183 nsAutoScriptBlocker blockScripts;
5184 RefPtr<Document> clone = docToPrint->CreateStaticClone(
5185 cloneDocShell, viewer, ps, &hasPrintCallbacks);
5186 if (!clone) {
5187 aError.ThrowNotSupportedError("Clone operation for printing failed");
5188 return nullptr;
5189 }
5190 }
5191
5192 nsCOMPtr<nsIWebBrowserPrint> webBrowserPrint = do_QueryInterface(viewer);
5193 if (!webBrowserPrint) {
5194 aError.ThrowNotSupportedError(
5195 "Content viewer didn't implement nsIWebBrowserPrint");
5196 return nullptr;
5197 }
5198 bool closeWindowAfterPrint;
5199 if (wasStaticDocument) {
5200 // Here the document was a static clone to begin with that this code did not
5201 // create, so we should not clean it up.
5202 // The exception is if we're using the passed-in aCachedBrowsingContext, in
5203 // which case this is the second print with this static document clone that
5204 // we created the first time through, and we are responsible for cleaning it
5205 // up.
5206 closeWindowAfterPrint = usingCachedBrowsingContext;
5207 } else {
5208 // In this case the document was not a static clone, so we made a static
5209 // clone for printing purposes and must clean it up after the print is done.
5210 // The exception is if aCachedBrowsingContext is non-NULL, meaning the
5211 // caller is intending to print this document again, so we need to defer the
5212 // cleanup until after the second print.
5213 closeWindowAfterPrint = !aCachedBrowsingContext;
5214 }
5215 webBrowserPrint->SetCloseWindowAfterPrint(closeWindowAfterPrint);
5216
5217 // For window.print(), we postpone making these calls until the round-trip to
5218 // the parent process (triggered by the OpenInternal call above) calls us
5219 // again. Only a call from the parent can provide a valid nsPrintSettings
5220 // object and RemotePrintJobChild object.
5221 if (aForWindowDotPrint == IsForWindowDotPrint::No) {
5222 if (aIsPreview == IsPreview::Yes) {
5223 aError = webBrowserPrint->PrintPreview(ps, aListener,
5224 std::move(aPrintPreviewCallback));
5225 if (aError.Failed()) {
5226 return nullptr;
5227 }
5228 } else {
5229 // Historically we've eaten this error.
5230 webBrowserPrint->Print(ps, aRemotePrintJob, aListener);
5231 }
5232 }
5233
5234 // When using window.print() with the new UI, we usually want to block until
5235 // the print dialog is hidden. But we can't really do that if we have print
5236 // callbacks, because we are inside a sync operation, and we want to run
5237 // microtasks / etc that the print callbacks may create. It is really awkward
5238 // to have this subtle behavior difference...
5239 //
5240 // We also want to do this for fuzzing, so that they can test window.print().
5241 const bool shouldBlock = [&] {
5242 if (aForWindowDotPrint == IsForWindowDotPrint::No) {
5243 return false;
5244 }
5245 if (aIsPreview == IsPreview::Yes) {
5246 return !hasPrintCallbacks;
5247 }
5248 return StaticPrefs::dom_window_print_fuzzing_block_while_printing();
5249 }();
5250
5251 if (shouldBlock) {
5252 SpinEventLoopUntil("nsGlobalWindowOuter::Print"_ns,
5253 [&] { return bc->IsDiscarded(); });
5254 }
5255
5256 return WindowProxyHolder(std::move(bc));
5257#else
5258 return nullptr;
5259#endif // NS_PRINTING
5260}
5261
5262void nsGlobalWindowOuter::MoveToOuter(int32_t aXPos, int32_t aYPos,
5263 CallerType aCallerType,
5264 ErrorResult& aError) {
5265 /*
5266 * If caller is not chrome and the user has not explicitly exempted the site,
5267 * prevent window.moveTo() by exiting early
5268 */
5269
5270 if (!CanMoveResizeWindows(aCallerType) || mBrowsingContext->IsSubframe()) {
5271 return;
5272 }
5273
5274 nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
5275 if (!treeOwnerAsWin) {
5276 aError.Throw(NS_ERROR_FAILURE);
5277 return;
5278 }
5279
5280 // We need to do the same transformation GetScreenXY does.
5281 RefPtr<nsPresContext> presContext = mDocShell->GetPresContext();
5282 if (!presContext) {
5283 return;
5284 }
5285
5286 CSSIntPoint cssPos(aXPos, aYPos);
5287 CheckSecurityLeftAndTop(&cssPos.x.value, &cssPos.y.value, aCallerType);
5288
5289 nsDeviceContext* context = presContext->DeviceContext();
5290
5291 auto devPos = LayoutDeviceIntPoint::FromAppUnitsRounded(
5292 CSSIntPoint::ToAppUnits(cssPos), context->AppUnitsPerDevPixel());
5293
5294 aError = treeOwnerAsWin->SetPosition(devPos.x, devPos.y);
5295 CheckForDPIChange();
5296}
5297
5298void nsGlobalWindowOuter::MoveByOuter(int32_t aXDif, int32_t aYDif,
5299 CallerType aCallerType,
5300 ErrorResult& aError) {
5301 /*
5302 * If caller is not chrome and the user has not explicitly exempted the site,
5303 * prevent window.moveBy() by exiting early
5304 */
5305
5306 if (!CanMoveResizeWindows(aCallerType) || mBrowsingContext->IsSubframe()) {
5307 return;
5308 }
5309
5310 nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
5311 if (!treeOwnerAsWin) {
5312 aError.Throw(NS_ERROR_FAILURE);
5313 return;
5314 }
5315
5316 // To do this correctly we have to convert what we get from GetPosition
5317 // into CSS pixels, add the arguments, do the security check, and
5318 // then convert back to device pixels for the call to SetPosition.
5319
5320 int32_t x, y;
5321 aError = treeOwnerAsWin->GetPosition(&x, &y);
5322 if (aError.Failed()) {
5323 return;
5324 }
5325
5326 auto cssScale = CSSToDevScaleForBaseWindow(treeOwnerAsWin);
5327 CSSIntPoint cssPos = RoundedToInt(treeOwnerAsWin->GetPosition() / cssScale);
5328
5329 cssPos.x += aXDif;
5330 cssPos.y += aYDif;
5331
5332 CheckSecurityLeftAndTop(&cssPos.x.value, &cssPos.y.value, aCallerType);
5333
5334 LayoutDeviceIntPoint newDevPos = RoundedToInt(cssPos * cssScale);
5335 aError = treeOwnerAsWin->SetPosition(newDevPos.x, newDevPos.y);
5336
5337 CheckForDPIChange();
5338}
5339
5340nsresult nsGlobalWindowOuter::MoveBy(int32_t aXDif, int32_t aYDif) {
5341 ErrorResult rv;
5342 MoveByOuter(aXDif, aYDif, CallerType::System, rv);
5343
5344 return rv.StealNSResult();
5345}
5346
5347void nsGlobalWindowOuter::ResizeToOuter(int32_t aWidth, int32_t aHeight,
5348 CallerType aCallerType,
5349 ErrorResult& aError) {
5350 /*
5351 * If caller is not chrome and the user has not explicitly exempted the site,
5352 * prevent window.resizeTo() by exiting early
5353 */
5354
5355 if (!CanMoveResizeWindows(aCallerType) || mBrowsingContext->IsSubframe()) {
5356 return;
5357 }
5358
5359 nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
5360 if (!treeOwnerAsWin) {
5361 aError.Throw(NS_ERROR_FAILURE);
5362 return;
5363 }
5364
5365 CSSIntSize cssSize(aWidth, aHeight);
5366 CheckSecurityWidthAndHeight(&cssSize.width, &cssSize.height, aCallerType);
5367
5368 LayoutDeviceIntSize devSize =
5369 RoundedToInt(cssSize * CSSToDevScaleForBaseWindow(treeOwnerAsWin));
5370 aError = treeOwnerAsWin->SetSize(devSize.width, devSize.height, true);
5371
5372 CheckForDPIChange();
5373}
5374
5375void nsGlobalWindowOuter::ResizeByOuter(int32_t aWidthDif, int32_t aHeightDif,
5376 CallerType aCallerType,
5377 ErrorResult& aError) {
5378 /*
5379 * If caller is not chrome and the user has not explicitly exempted the site,
5380 * prevent window.resizeBy() by exiting early
5381 */
5382
5383 if (!CanMoveResizeWindows(aCallerType) || mBrowsingContext->IsSubframe()) {
5384 return;
5385 }
5386
5387 nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
5388 if (!treeOwnerAsWin) {
5389 aError.Throw(NS_ERROR_FAILURE);
5390 return;
5391 }
5392
5393 LayoutDeviceIntSize size = treeOwnerAsWin->GetSize();