Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp
Warning:line 5205, column 7
1st function call argument is an uninitialized value

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 nsGlobalWindowInner.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 MOZ_SUPPORT_LEAKCHECKING -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/build -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/sysprof-6 -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/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/backward -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../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-07-30-004816-4182763-1 -x c++ /var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.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 "nsGlobalWindowInner.h"
8
9#include <inttypes.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <cstdint>
14#include <new>
15#include <type_traits>
16#include <utility>
17#include "AudioChannelService.h"
18#include "AutoplayPolicy.h"
19#include "Crypto.h"
20#include "MainThreadUtils.h"
21#include "Navigator.h"
22#include "PaintWorkletImpl.h"
23#include "SessionStorageCache.h"
24#include "Units.h"
25#include "VRManagerChild.h"
26#include "WindowDestroyedEvent.h"
27#include "WindowNamedPropertiesHandler.h"
28#include "js/ComparisonOperators.h"
29#include "js/CompileOptions.h"
30#include "js/friend/PerformanceHint.h"
31#include "js/Id.h"
32#include "js/loader/LoadedScript.h"
33#include "js/PropertyAndElement.h" // JS_DefineProperty, JS_GetProperty
34#include "js/PropertyDescriptor.h"
35#include "js/RealmOptions.h"
36#include "js/RootingAPI.h"
37#include "js/TypeDecls.h"
38#include "js/Value.h"
39#include "js/Warnings.h"
40#include "js/shadow/String.h"
41#include "jsapi.h"
42#include "jsfriendapi.h"
43#include "mozIDOMWindow.h"
44#include "moz_external_vr.h"
45#include "mozilla/AlreadyAddRefed.h"
46#include "mozilla/ArrayIterator.h"
47#include "mozilla/ArrayUtils.h"
48#include "mozilla/Attributes.h"
49#include "mozilla/BaseProfilerMarkersPrerequisites.h"
50#include "mozilla/BasicEvents.h"
51#include "mozilla/BounceTrackingStorageObserver.h"
52#include "mozilla/CallState.h"
53#include "mozilla/CycleCollectedJSContext.h"
54#include "mozilla/DOMEventTargetHelper.h"
55#include "mozilla/ErrorResult.h"
56#include "mozilla/EventDispatcher.h"
57#include "mozilla/EventListenerManager.h"
58#include "mozilla/EventQueue.h"
59#include "mozilla/ExtensionPolicyService.h"
60#include "mozilla/FloatingPoint.h"
61#include "mozilla/FlushType.h"
62#include "mozilla/Likely.h"
63#include "mozilla/LinkedList.h"
64#include "mozilla/LookAndFeel.h"
65#include "mozilla/Logging.h"
66#include "mozilla/MacroForEach.h"
67#include "mozilla/Maybe.h"
68#include "mozilla/OwningNonNull.h"
69#include "mozilla/PermissionDelegateHandler.h"
70#include "mozilla/Preferences.h"
71#include "mozilla/PresShell.h"
72#include "mozilla/ProcessHangMonitor.h"
73#include "mozilla/RefPtr.h"
74#include "mozilla/Result.h"
75#include "mozilla/ScrollContainerFrame.h"
76#include "mozilla/ScrollTypes.h"
77#include "mozilla/Components.h"
78#include "mozilla/SizeOfState.h"
79#include "mozilla/Span.h"
80#include "mozilla/SpinEventLoopUntil.h"
81#include "mozilla/Sprintf.h"
82#include "mozilla/StaticPrefs_browser.h"
83#include "mozilla/StaticPrefs_docshell.h"
84#include "mozilla/StaticPrefs_dom.h"
85#include "mozilla/StaticPrefs_extensions.h"
86#include "mozilla/StaticPrefs_privacy.h"
87#include "mozilla/StorageAccess.h"
88#include "mozilla/StoragePrincipalHelper.h"
89#include "mozilla/Telemetry.h"
90#include "mozilla/TelemetryHistogramEnums.h"
91#include "mozilla/TimeStamp.h"
92#include "mozilla/UniquePtr.h"
93#include "mozilla/Unused.h"
94#include "mozilla/dom/AudioContext.h"
95#include "mozilla/dom/AutoEntryScript.h"
96#include "mozilla/dom/BarProps.h"
97#include "mozilla/dom/BindingDeclarations.h"
98#include "mozilla/dom/BindingUtils.h"
99#include "mozilla/dom/BrowserChild.h"
100#include "mozilla/dom/BrowsingContext.h"
101#include "mozilla/dom/Credential.h"
102#include "mozilla/dom/CSPEvalChecker.h"
103#include "mozilla/dom/CallbackDebuggerNotification.h"
104#include "mozilla/dom/ChromeMessageBroadcaster.h"
105#include "mozilla/dom/ClientInfo.h"
106#include "mozilla/dom/ClientManager.h"
107#include "mozilla/dom/ClientSource.h"
108#include "mozilla/dom/ClientState.h"
109#include "mozilla/dom/ClientsBinding.h"
110#include "mozilla/dom/Console.h"
111#include "mozilla/dom/ContentChild.h"
112#include "mozilla/dom/ContentFrameMessageManager.h"
113#include "mozilla/dom/ContentMediaController.h"
114#include "mozilla/dom/CustomElementRegistry.h"
115#include "mozilla/dom/DebuggerNotification.h"
116#include "mozilla/dom/DebuggerNotificationBinding.h"
117#include "mozilla/dom/DebuggerNotificationManager.h"
118#include "mozilla/dom/DocGroup.h"
119#include "mozilla/dom/Document.h"
120#include "mozilla/dom/DocumentInlines.h"
121#include "mozilla/dom/Element.h"
122#include "mozilla/dom/Event.h"
123#include "mozilla/dom/EventTarget.h"
124#include "mozilla/dom/External.h"
125#include "mozilla/dom/Fetch.h"
126#include "mozilla/dom/Gamepad.h"
127#include "mozilla/dom/GamepadHandle.h"
128#include "mozilla/dom/GamepadManager.h"
129#include "mozilla/dom/HashChangeEvent.h"
130#include "mozilla/dom/HashChangeEventBinding.h"
131#include "mozilla/dom/IDBFactory.h"
132#include "mozilla/dom/IdleRequest.h"
133#include "mozilla/dom/ImageBitmap.h"
134#include "mozilla/dom/ImageBitmapSource.h"
135#include "mozilla/dom/InstallTriggerBinding.h"
136#include "mozilla/dom/IntlUtils.h"
137#include "mozilla/dom/JSExecutionContext.h"
138#include "mozilla/dom/LSObject.h"
139#include "mozilla/dom/LocalStorage.h"
140#include "mozilla/dom/LocalStorageCommon.h"
141#include "mozilla/dom/Location.h"
142#include "mozilla/dom/MediaDevices.h"
143#include "mozilla/dom/MediaKeys.h"
144#include "mozilla/dom/Navigation.h"
145#include "mozilla/dom/NavigatorBinding.h"
146#include "mozilla/dom/Nullable.h"
147#include "mozilla/dom/PartitionedLocalStorage.h"
148#include "mozilla/dom/Performance.h"
149#include "mozilla/dom/PerformanceMainThread.h"
150#include "mozilla/dom/PopStateEvent.h"
151#include "mozilla/dom/PopStateEventBinding.h"
152#include "mozilla/dom/PopupBlocker.h"
153#include "mozilla/dom/PrimitiveConversions.h"
154#include "mozilla/dom/Promise.h"
155#include "mozilla/dom/RootedDictionary.h"
156#include "mozilla/dom/WebTaskSchedulerMainThread.h"
157#include "mozilla/dom/ScriptLoader.h"
158#include "mozilla/dom/ScriptSettings.h"
159#include "mozilla/dom/ServiceWorker.h"
160#include "mozilla/dom/ServiceWorkerDescriptor.h"
161#include "mozilla/dom/ServiceWorkerRegistration.h"
162#include "mozilla/dom/SessionStorageManager.h"
163#include "mozilla/dom/SharedWorker.h"
164#include "mozilla/dom/Storage.h"
165#include "mozilla/dom/StorageEvent.h"
166#include "mozilla/dom/StorageEventBinding.h"
167#include "mozilla/dom/StorageNotifierService.h"
168#include "mozilla/dom/StorageUtils.h"
169#include "mozilla/dom/TabMessageTypes.h"
170#include "mozilla/dom/Timeout.h"
171#include "mozilla/dom/TimeoutHandler.h"
172#include "mozilla/dom/TimeoutManager.h"
173#include "mozilla/dom/ToJSValue.h"
174#include "mozilla/dom/TrustedTypePolicyFactory.h"
175#include "mozilla/dom/VRDisplay.h"
176#include "mozilla/dom/VRDisplayEvent.h"
177#include "mozilla/dom/VRDisplayEventBinding.h"
178#include "mozilla/dom/VREventObserver.h"
179#include "mozilla/dom/VisualViewport.h"
180#include "mozilla/dom/WebIDLGlobalNameHash.h"
181#include "mozilla/dom/WindowBinding.h"
182#include "mozilla/dom/WindowContext.h"
183#include "mozilla/dom/WindowGlobalChild.h"
184#include "mozilla/dom/WindowProxyHolder.h"
185#include "mozilla/dom/WorkerCommon.h"
186#include "mozilla/dom/Worklet.h"
187#include "mozilla/dom/XRPermissionRequest.h"
188#include "mozilla/dom/cache/CacheStorage.h"
189#include "mozilla/dom/cache/Types.h"
190#include "mozilla/glean/bindings/Glean.h"
191#include "mozilla/glean/bindings/GleanPings.h"
192#include "mozilla/extensions/WebExtensionPolicy.h"
193#include "mozilla/fallible.h"
194#include "mozilla/gfx/BasePoint.h"
195#include "mozilla/gfx/BaseRect.h"
196#include "mozilla/gfx/BaseSize.h"
197#include "mozilla/gfx/Rect.h"
198#include "mozilla/gfx/Types.h"
199#include "mozilla/intl/LocaleService.h"
200#include "mozilla/ipc/BackgroundUtils.h"
201#include "mozilla/ipc/PBackgroundSharedTypes.h"
202#include "mozilla/net/CookieJarSettings.h"
203#include "nsAtom.h"
204#include "nsBaseHashtable.h"
205#include "nsCCUncollectableMarker.h"
206#include "nsCOMPtr.h"
207#include "nsCRT.h"
208#include "nsCRTGlue.h"
209#include "nsCanvasFrame.h"
210#include "nsCharTraits.h"
211#include "nsCheapSets.h"
212#include "nsContentUtils.h"
213#include "nsCoord.h"
214#include "nsCycleCollectionNoteChild.h"
215#include "nsCycleCollectionTraversalCallback.h"
216#include "nsDOMNavigationTiming.h"
217#include "nsDebug.h"
218#include "nsDeviceContext.h"
219#include "nsDocShell.h"
220#include "nsFocusManager.h"
221#include "nsFrameMessageManager.h"
222#include "nsGkAtoms.h"
223#include "nsGlobalWindowOuter.h"
224#include "nsHashKeys.h"
225#include "nsHistory.h"
226#include "nsIAddonPolicyService.h"
227#include "nsIArray.h"
228#include "nsIBaseWindow.h"
229#include "nsIBrowserChild.h"
230#include "nsICancelableRunnable.h"
231#include "nsIChannel.h"
232#include "nsIClipboard.h"
233#include "nsIContentSecurityPolicy.h"
234#include "nsIControllers.h"
235#include "nsICookieJarSettings.h"
236#include "nsICookieService.h"
237#include "nsID.h"
238#include "nsIDOMStorageManager.h"
239#include "nsIDeviceSensors.h"
240#include "nsIDocShell.h"
241#include "nsIDocShellTreeItem.h"
242#include "nsIDocShellTreeOwner.h"
243#include "nsIDocumentLoader.h"
244#include "nsIDragService.h"
245#include "nsIFocusManager.h"
246#include "nsIFrame.h"
247#include "nsIGlobalObject.h"
248#include "nsIIOService.h"
249#include "nsIIdleRunnable.h"
250#include "nsIInterfaceRequestorUtils.h"
251#include "nsILoadContext.h"
252#include "nsILoadGroup.h"
253#include "nsILoadInfo.h"
254#include "nsINamed.h"
255#include "nsINode.h"
256#include "nsIObserver.h"
257#include "nsIObserverService.h"
258#include "nsIPermission.h"
259#include "nsIPermissionManager.h"
260#include "nsIPrefBranch.h"
261#include "nsIPrincipal.h"
262#include "nsIPrompt.h"
263#include "nsIRunnable.h"
264#include "nsIScreen.h"
265#include "nsIScreenManager.h"
266#include "nsIScriptContext.h"
267#include "nsIScriptGlobalObject.h"
268#include "nsIScriptObjectPrincipal.h"
269#include "nsISerialEventTarget.h"
270#include "nsISimpleEnumerator.h"
271#include "nsISizeOfEventTarget.h"
272#include "nsISlowScriptDebug.h"
273#include "nsISupportsUtils.h"
274#include "nsIThread.h"
275#include "nsITimedChannel.h"
276#include "nsIURI.h"
277#include "nsIWeakReference.h"
278#include "nsIWebBrowserChrome.h"
279#include "nsIWebNavigation.h"
280#include "nsIWebProgressListener.h"
281#include "nsIWidget.h"
282#include "nsIWidgetListener.h"
283#include "nsIXULRuntime.h"
284#include "nsJSPrincipals.h"
285#include "nsJSUtils.h"
286#include "nsLayoutStatics.h"
287#include "nsLiteralString.h"
288#include "nsNetUtil.h"
289#include "nsPIDOMWindow.h"
290#include "nsPIDOMWindowInlines.h"
291#include "nsPIWindowRoot.h"
292#include "nsPoint.h"
293#include "nsPresContext.h"
294#include "nsQueryObject.h"
295#include "nsSandboxFlags.h"
296#include "nsScreen.h"
297#include "nsServiceManagerUtils.h"
298#include "nsString.h"
299#include "nsStringFlags.h"
300#include "nsStringFwd.h"
301#include "nsTArray.h"
302#include "nsTLiteralString.h"
303#include "nsTObserverArray.h"
304#include "nsTStringRepr.h"
305#include "nsThreadUtils.h"
306#include "nsWeakReference.h"
307#include "nsWindowMemoryReporter.h"
308#include "nsWindowSizes.h"
309#include "nsWrapperCache.h"
310#include "nsWrapperCacheInlines.h"
311#include "nsXULAppAPI.h"
312#include "nsrootidl.h"
313#include "prclist.h"
314#include "prtypes.h"
315#include "xpcprivate.h"
316#include "xpcpublic.h"
317
318#include "nsIDOMXULControlElement.h"
319
320#ifdef NS_PRINTING1
321# include "nsIPrintSettings.h"
322#endif
323
324#ifdef MOZ_WEBSPEECH1
325# include "mozilla/dom/SpeechSynthesis.h"
326#endif
327
328#ifdef ANDROID
329# include <android/log.h>
330#endif
331
332#ifdef XP_WIN
333# include "mozilla/Debug.h"
334# include <process.h>
335# define getpid _getpid
336#else
337# include <unistd.h> // for getpid()
338#endif
339
340using namespace mozilla;
341using namespace mozilla::dom;
342using namespace mozilla::dom::ipc;
343using mozilla::TimeDuration;
344using mozilla::TimeStamp;
345using mozilla::dom::GamepadHandle;
346using mozilla::dom::cache::CacheStorage;
347
348#define FORWARD_TO_OUTER(method, args, err_rval) \
349 PR_BEGIN_MACROdo { \
350 RefPtr<nsGlobalWindowOuter> outer = GetOuterWindowInternal(); \
351 if (!HasActiveDocument()) { \
352 NS_WARNING(outer ? "Inner window does not have active document." \NS_DebugBreak(NS_DEBUG_WARNING, outer ? "Inner window does not have active document."
: "No outer window available!", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 353)
353 : "No outer window available!")NS_DebugBreak(NS_DEBUG_WARNING, outer ? "Inner window does not have active document."
: "No outer window available!", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 353)
; \
354 return err_rval; \
355 } \
356 return outer->method args; \
357 PR_END_MACRO} while (0)
358
359static nsGlobalWindowOuter* GetOuterWindowForForwarding(
360 nsGlobalWindowInner* aInner, ErrorResult& aError) {
361 nsGlobalWindowOuter* outer = aInner->GetOuterWindowInternal();
362 if (MOZ_LIKELY(aInner->HasActiveDocument())(__builtin_expect(!!(aInner->HasActiveDocument()), 1))) {
363 return outer;
364 }
365 if (!outer) {
366 NS_WARNING("No outer window available!")NS_DebugBreak(NS_DEBUG_WARNING, "No outer window available!",
nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 366)
;
367 aError.Throw(NS_ERROR_NOT_INITIALIZED);
368 } else {
369 aError.Throw(NS_ERROR_XPC_SECURITY_MANAGER_VETO);
370 }
371 return nullptr;
372}
373
374#define FORWARD_TO_OUTER_OR_THROW(method, args, rv, err_rval) \
375 PR_BEGIN_MACROdo { \
376 RefPtr<nsGlobalWindowOuter> outer = GetOuterWindowForForwarding(this, rv); \
377 if (MOZ_LIKELY(outer)(__builtin_expect(!!(outer), 1))) { \
378 return outer->method args; \
379 } \
380 return err_rval; \
381 PR_END_MACRO} while (0)
382
383#define FORWARD_TO_OUTER_VOID(method, args) \
384 PR_BEGIN_MACROdo { \
385 RefPtr<nsGlobalWindowOuter> outer = GetOuterWindowInternal(); \
386 if (!HasActiveDocument()) { \
387 NS_WARNING(outer ? "Inner window does not have active document." \NS_DebugBreak(NS_DEBUG_WARNING, outer ? "Inner window does not have active document."
: "No outer window available!", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 388)
388 : "No outer window available!")NS_DebugBreak(NS_DEBUG_WARNING, outer ? "Inner window does not have active document."
: "No outer window available!", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 388)
; \
389 return; \
390 } \
391 outer->method args; \
392 return; \
393 PR_END_MACRO} while (0)
394
395#define ENSURE_ACTIVE_DOCUMENT(errorresult, err_rval)do { if ((__builtin_expect(!!(!HasActiveDocument()), 0))) { aError
.Throw(NS_ERROR_XPC_SECURITY_MANAGER_VETO); return err_rval; }
} while (0)
\
396 PR_BEGIN_MACROdo { \
397 if (MOZ_UNLIKELY(!HasActiveDocument())(__builtin_expect(!!(!HasActiveDocument()), 0))) { \
398 aError.Throw(NS_ERROR_XPC_SECURITY_MANAGER_VETO); \
399 return err_rval; \
400 } \
401 PR_END_MACRO} while (0)
402
403#define DOM_TOUCH_LISTENER_ADDED"dom-touch-listener-added" "dom-touch-listener-added"
404#define MEMORY_PRESSURE_OBSERVER_TOPIC"memory-pressure" "memory-pressure"
405#define PERMISSION_CHANGED_TOPIC"perm-changed" "perm-changed"
406
407static LazyLogModule gDOMLeakPRLogInner("DOMLeakInner");
408extern mozilla::LazyLogModule gTimeoutLog;
409
410#ifdef DEBUG1
411static LazyLogModule gDocShellAndDOMWindowLeakLogging(
412 "DocShellAndDOMWindowLeak");
413#endif
414
415static FILE* gDumpFile = nullptr;
416
417nsGlobalWindowInner::InnerWindowByIdTable*
418 nsGlobalWindowInner::sInnerWindowsById = nullptr;
419
420bool nsGlobalWindowInner::sDragServiceDisabled = false;
421bool nsGlobalWindowInner::sMouseDown = false;
422
423/**
424 * An indirect observer object that means we don't have to implement nsIObserver
425 * on nsGlobalWindow, where any script could see it.
426 */
427class nsGlobalWindowObserver final : public nsIObserver,
428 public nsIInterfaceRequestor,
429 public StorageNotificationObserver {
430 public:
431 explicit nsGlobalWindowObserver(nsGlobalWindowInner* aWindow)
432 : mWindow(aWindow) {}
433 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:
434 NS_IMETHODvirtual nsresult Observe(nsISupports* aSubject, const char* aTopic,
435 const char16_t* aData) override {
436 if (!mWindow) return NS_OK;
437 return mWindow->Observe(aSubject, aTopic, aData);
438 }
439 void Forget() { mWindow = nullptr; }
440 NS_IMETHODvirtual nsresult GetInterface(const nsIID& aIID, void** aResult) override {
441 if (mWindow && aIID.Equals(NS_GET_IID(nsIDOMWindow)(nsIDOMWindow::COMTypeInfo<nsIDOMWindow, void>::kIID)) && mWindow) {
442 return mWindow->QueryInterface(aIID, aResult);
443 }
444 return NS_NOINTERFACE;
445 }
446
447 void ObserveStorageNotification(StorageEvent* aEvent,
448 const char16_t* aStorageType,
449 bool aPrivateBrowsing) override {
450 if (mWindow) {
451 mWindow->ObserveStorageNotification(aEvent, aStorageType,
452 aPrivateBrowsing);
453 }
454 }
455
456 nsIPrincipal* GetEffectiveCookiePrincipal() const override {
457 return mWindow ? mWindow->GetEffectiveCookiePrincipal() : nullptr;
458 }
459
460 nsIPrincipal* GetEffectiveStoragePrincipal() const override {
461 return mWindow ? mWindow->GetEffectiveStoragePrincipal() : nullptr;
462 }
463
464 bool IsPrivateBrowsing() const override {
465 return mWindow ? mWindow->IsPrivateBrowsing() : false;
466 }
467
468 nsIEventTarget* GetEventTarget() const override {
469 return mWindow ? mWindow->SerialEventTarget() : nullptr;
470 }
471
472 private:
473 ~nsGlobalWindowObserver() = default;
474
475 // This reference is non-owning and safe because it's cleared by
476 // nsGlobalWindowInner::FreeInnerObjects().
477 nsGlobalWindowInner* MOZ_NON_OWNING_REF mWindow;
478};
479
480NS_IMPL_ISUPPORTS(nsGlobalWindowObserver, nsIObserver, nsIInterfaceRequestor)MozExternalRefCountType nsGlobalWindowObserver::AddRef(void) {
static_assert(!std::is_destructible_v<nsGlobalWindowObserver
>, "Reference-counted class " "nsGlobalWindowObserver" " 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/nsGlobalWindowInner.cpp"
, 480); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
480; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsGlobalWindowObserver" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("nsGlobalWindowObserver" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"nsGlobalWindowObserver\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 480); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsGlobalWindowObserver\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 480; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsGlobalWindowObserver" " not thread-safe")
; nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), (
"nsGlobalWindowObserver"), (uint32_t)(sizeof(*this))); return
count; } MozExternalRefCountType nsGlobalWindowObserver::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/nsGlobalWindowInner.cpp"
, 480); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 480
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsGlobalWindowObserver" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("nsGlobalWindowObserver" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"nsGlobalWindowObserver\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 480); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsGlobalWindowObserver\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 480; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsGlobalWindowObserver" " not thread-safe")
; const char* const nametmp = "nsGlobalWindowObserver"; nsrefcnt
count = --mRefCnt; NS_LogRelease((this), (count), (nametmp))
; if (count == 0) { mRefCnt = 1; delete (this); return 0; } return
count; } nsresult nsGlobalWindowObserver::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/nsGlobalWindowInner.cpp"
, 480); 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<nsGlobalWindowObserver, nsIObserver>,
int32_t( reinterpret_cast<char*>(static_cast<nsIObserver
*>((nsGlobalWindowObserver*)0x1000)) - reinterpret_cast<
char*>((nsGlobalWindowObserver*)0x1000))}, {&mozilla::
detail::kImplementedIID<nsGlobalWindowObserver, nsIInterfaceRequestor
>, int32_t( reinterpret_cast<char*>(static_cast<nsIInterfaceRequestor
*>((nsGlobalWindowObserver*)0x1000)) - reinterpret_cast<
char*>((nsGlobalWindowObserver*)0x1000))}, {&mozilla::
detail::kImplementedIID<nsGlobalWindowObserver, nsISupports
>, int32_t(reinterpret_cast<char*>(static_cast<nsISupports
*>( static_cast<nsIObserver*>((nsGlobalWindowObserver
*)0x1000))) - reinterpret_cast<char*>((nsGlobalWindowObserver
*)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; }
481
482class IdleRequestExecutor;
483
484class IdleRequestExecutorTimeoutHandler final : public TimeoutHandler {
485 public:
486 explicit IdleRequestExecutorTimeoutHandler(IdleRequestExecutor* aExecutor)
487 : mExecutor(aExecutor) {}
488
489 NS_DECL_CYCLE_COLLECTING_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: nsCycleCollectingAutoRefCnt mRefCnt; nsAutoOwningThread
_mOwningThread; public: virtual void DeleteCycleCollectable(
void); public:
490 NS_DECL_CYCLE_COLLECTION_CLASS(IdleRequestExecutorTimeoutHandler)class cycleCollection : public nsXPCOMCycleCollectionParticipant
{ public: constexpr explicit cycleCollection(Flags aFlags = 0
) : nsXPCOMCycleCollectionParticipant(aFlags) {} private: public
: virtual nsresult TraverseNative(void* p, nsCycleCollectionTraversalCallback
& cb) override; virtual const char* ClassName() override {
return "IdleRequestExecutorTimeoutHandler"; }; virtual void DeleteCycleCollectable
(void* p) override { DowncastCCParticipant<IdleRequestExecutorTimeoutHandler
>(p)->DeleteCycleCollectable(); } static IdleRequestExecutorTimeoutHandler
* Downcast(nsISupports* s) { return static_cast<IdleRequestExecutorTimeoutHandler
*>(static_cast<IdleRequestExecutorTimeoutHandler*>(s
)); } static nsISupports* Upcast(IdleRequestExecutorTimeoutHandler
* p) { return static_cast<nsISupports*>(static_cast<
IdleRequestExecutorTimeoutHandler*>(p)); } template <typename
T> friend nsISupports* ToSupports(T* p, cycleCollection* dummy
); virtual void Unlink(void* p) override; static constexpr nsXPCOMCycleCollectionParticipant
* GetParticipant() { return &IdleRequestExecutorTimeoutHandler
::_cycleCollectorGlobal; } }; virtual void CheckForRightParticipant
() { nsXPCOMCycleCollectionParticipant* p; CallQueryInterface
(this, &p); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(p == &_cycleCollectorGlobal)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(p == &_cycleCollectorGlobal
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"p == &_cycleCollectorGlobal" " (" "IdleRequestExecutorTimeoutHandler"
" should QI to its own CC participant" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 490); AnnotateMozCrashReason("MOZ_ASSERT" "(" "p == &_cycleCollectorGlobal"
") (" "IdleRequestExecutorTimeoutHandler" " should QI to its own CC participant"
")"); do { *((volatile int*)__null) = 490; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } static cycleCollection
_cycleCollectorGlobal; virtual void BaseCycleCollectable() final
{}
491
492 bool Call(const char* /* unused */) override;
493
494 private:
495 ~IdleRequestExecutorTimeoutHandler() override = default;
496 RefPtr<IdleRequestExecutor> mExecutor;
497};
498
499NS_IMPL_CYCLE_COLLECTION(IdleRequestExecutorTimeoutHandler, mExecutor)IdleRequestExecutorTimeoutHandler::cycleCollection IdleRequestExecutorTimeoutHandler
::_cycleCollectorGlobal; void IdleRequestExecutorTimeoutHandler
::cycleCollection::Unlink(void* p) { IdleRequestExecutorTimeoutHandler
* tmp = DowncastCCParticipant<IdleRequestExecutorTimeoutHandler
>(p); ImplCycleCollectionUnlink(tmp->mExecutor); (void)
tmp; } nsresult IdleRequestExecutorTimeoutHandler::cycleCollection
::TraverseNative( void* p, nsCycleCollectionTraversalCallback
& cb) { IdleRequestExecutorTimeoutHandler* tmp = DowncastCCParticipant
<IdleRequestExecutorTimeoutHandler>(p); cb.DescribeRefCountedNode
(tmp->mRefCnt.get(), "IdleRequestExecutorTimeoutHandler");
ImplCycleCollectionTraverse(cb, tmp->mExecutor, "mExecutor"
, 0); (void)tmp; return NS_OK; }
500
501NS_IMPL_CYCLE_COLLECTING_ADDREF(IdleRequestExecutorTimeoutHandler)MozExternalRefCountType IdleRequestExecutorTimeoutHandler::AddRef
(void) { static_assert(!std::is_destructible_v<IdleRequestExecutorTimeoutHandler
>, "Reference-counted class " "IdleRequestExecutorTimeoutHandler"
" 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/nsGlobalWindowInner.cpp"
, 501); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
501; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); _mOwningThread.AssertOwnership("IdleRequestExecutorTimeoutHandler"
" not thread-safe"); nsISupports* base = IdleRequestExecutorTimeoutHandler
::cycleCollection::Upcast(this); nsrefcnt count = mRefCnt.incr
(base); NS_LogAddRef((this), (count), ("IdleRequestExecutorTimeoutHandler"
), (uint32_t)(sizeof(*this))); return count; }
502NS_IMPL_CYCLE_COLLECTING_RELEASE(IdleRequestExecutorTimeoutHandler)MozExternalRefCountType IdleRequestExecutorTimeoutHandler::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/nsGlobalWindowInner.cpp"
, 502); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 502
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); _mOwningThread.AssertOwnership("IdleRequestExecutorTimeoutHandler"
" not thread-safe"); nsISupports* base = IdleRequestExecutorTimeoutHandler
::cycleCollection::Upcast(this); nsrefcnt count = mRefCnt.decr
(base); NS_LogRelease((this), (count), ("IdleRequestExecutorTimeoutHandler"
)); return count; } void IdleRequestExecutorTimeoutHandler::DeleteCycleCollectable
(void) { delete (this); }
503
504NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IdleRequestExecutorTimeoutHandler)nsresult IdleRequestExecutorTimeoutHandler::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/nsGlobalWindowInner.cpp"
, 504); 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 = IdleRequestExecutorTimeoutHandler
::cycleCollection::GetParticipant(); return NS_OK; } if (LowWordEquals
(aIID, (nsCycleCollectionISupports::COMTypeInfo<nsCycleCollectionISupports
, void>::kIID))) { *aInstancePtr = IdleRequestExecutorTimeoutHandler
::cycleCollection::Upcast(this); return NS_OK; } foundInterface
= nullptr; } else
505 NS_INTERFACE_MAP_ENTRY(nsISupports)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupports>)) foundInterface = static_cast
<nsISupports*>(this); else
506NS_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/nsGlobalWindowInner.cpp"
, 506); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIID.Equals((nsISupports::COMTypeInfo<nsISupports, void>::kIID))"
")"); do { *((volatile int*)__null) = 506; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); status = NS_NOINTERFACE
; } else { (foundInterface)->AddRef(); status = NS_OK; } *
aInstancePtr = foundInterface; return status; }
507
508class IdleRequestExecutor final : public nsIRunnable,
509 public nsICancelableRunnable,
510 public nsINamed,
511 public nsIIdleRunnable {
512 public:
513 explicit IdleRequestExecutor(nsGlobalWindowInner* aWindow)
514 : mDispatched(false), mDeadline(TimeStamp::Now()), mWindow(aWindow) {
515 MOZ_DIAGNOSTIC_ASSERT(mWindow)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mWindow)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mWindow))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mWindow", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 515); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mWindow"
")"); do { *((volatile int*)__null) = 515; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
516
517 mIdlePeriodLimit = {mDeadline, mWindow->LastIdleRequestHandle()};
518 mDelayedExecutorDispatcher = new IdleRequestExecutorTimeoutHandler(this);
519 }
520
521 NS_DECL_CYCLE_COLLECTING_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: nsCycleCollectingAutoRefCnt mRefCnt; nsAutoOwningThread
_mOwningThread; public: virtual void DeleteCycleCollectable(
void); public:
522 NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(IdleRequestExecutor, nsIRunnable)class cycleCollection : public nsXPCOMCycleCollectionParticipant
{ public: constexpr explicit cycleCollection(Flags aFlags = 0
) : nsXPCOMCycleCollectionParticipant(aFlags) {} private: public
: virtual nsresult TraverseNative(void* p, nsCycleCollectionTraversalCallback
& cb) override; virtual const char* ClassName() override {
return "IdleRequestExecutor"; }; virtual void DeleteCycleCollectable
(void* p) override { DowncastCCParticipant<IdleRequestExecutor
>(p)->DeleteCycleCollectable(); } static IdleRequestExecutor
* Downcast(nsISupports* s) { return static_cast<IdleRequestExecutor
*>(static_cast<nsIRunnable*>(s)); } static nsISupports
* Upcast(IdleRequestExecutor* p) { return static_cast<nsISupports
*>(static_cast<nsIRunnable*>(p)); } template <typename
T> friend nsISupports* ToSupports(T* p, cycleCollection* dummy
); virtual void Unlink(void* p) override; static constexpr nsXPCOMCycleCollectionParticipant
* GetParticipant() { return &IdleRequestExecutor::_cycleCollectorGlobal
; } }; virtual void CheckForRightParticipant() { nsXPCOMCycleCollectionParticipant
* p; CallQueryInterface(this, &p); do { static_assert( mozilla
::detail::AssertionConditionType<decltype(p == &_cycleCollectorGlobal
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(p == &_cycleCollectorGlobal))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("p == &_cycleCollectorGlobal"
" (" "IdleRequestExecutor" " should QI to its own CC participant"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 522); AnnotateMozCrashReason("MOZ_ASSERT" "(" "p == &_cycleCollectorGlobal"
") (" "IdleRequestExecutor" " should QI to its own CC participant"
")"); do { *((volatile int*)__null) = 522; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } static cycleCollection
_cycleCollectorGlobal; virtual void BaseCycleCollectable() final
{}
523
524 NS_DECL_NSIRUNNABLEvirtual nsresult Run(void) override;
525 NS_DECL_NSINAMEDvirtual nsresult GetName(nsACString& aName) override;
526 nsresult Cancel() override;
527 void SetDeadline(TimeStamp aDeadline) override;
528
529 bool IsCancelled() const { return !mWindow || mWindow->IsDying(); }
530 // Checks if aRequest shouldn't execute in the current idle period
531 // since it has been queued from a chained call to
532 // requestIdleCallback from within a running idle callback.
533 bool IneligibleForCurrentIdlePeriod(IdleRequest* aRequest) const {
534 return aRequest->Handle() >= mIdlePeriodLimit.mLastRequestIdInIdlePeriod &&
535 TimeStamp::Now() <= mIdlePeriodLimit.mEndOfIdlePeriod;
536 }
537
538 void MaybeUpdateIdlePeriodLimit();
539
540 // Maybe dispatch the IdleRequestExecutor. MabyeDispatch will
541 // schedule a delayed dispatch if the associated window is in the
542 // background or if given a time to wait until dispatching.
543 void MaybeDispatch(TimeStamp aDelayUntil = TimeStamp());
544 void ScheduleDispatch();
545
546 private:
547 struct IdlePeriodLimit {
548 TimeStamp mEndOfIdlePeriod;
549 uint32_t mLastRequestIdInIdlePeriod;
550 };
551
552 void DelayedDispatch(uint32_t aDelay);
553
554 ~IdleRequestExecutor() override = default;
555
556 bool mDispatched;
557 TimeStamp mDeadline;
558 IdlePeriodLimit mIdlePeriodLimit;
559 RefPtr<nsGlobalWindowInner> mWindow;
560 // The timeout handler responsible for dispatching this executor in
561 // the case of immediate dispatch to the idle queue isn't
562 // desirable. This is used if we've dispatched all idle callbacks
563 // that are allowed to run in the current idle period, or if the
564 // associated window is currently in the background.
565 RefPtr<TimeoutHandler> mDelayedExecutorDispatcher;
566 // If not Nothing() then this value is the handle to the currently
567 // scheduled delayed executor dispatcher. This is needed to be able
568 // to cancel the timeout handler in case of the executor being
569 // cancelled.
570 Maybe<int32_t> mDelayedExecutorHandle;
571};
572
573NS_IMPL_CYCLE_COLLECTION(IdleRequestExecutor, mWindow,IdleRequestExecutor::cycleCollection IdleRequestExecutor::_cycleCollectorGlobal
; void IdleRequestExecutor::cycleCollection::Unlink(void* p) {
IdleRequestExecutor* tmp = DowncastCCParticipant<IdleRequestExecutor
>(p); ImplCycleCollectionUnlink(tmp->mWindow); ImplCycleCollectionUnlink
(tmp->mDelayedExecutorDispatcher); (void)tmp; } nsresult IdleRequestExecutor
::cycleCollection::TraverseNative( void* p, nsCycleCollectionTraversalCallback
& cb) { IdleRequestExecutor* tmp = DowncastCCParticipant<
IdleRequestExecutor>(p); cb.DescribeRefCountedNode(tmp->
mRefCnt.get(), "IdleRequestExecutor"); ImplCycleCollectionTraverse
(cb, tmp->mWindow, "mWindow", 0); ImplCycleCollectionTraverse
(cb, tmp->mDelayedExecutorDispatcher, "mDelayedExecutorDispatcher"
, 0); (void)tmp; return NS_OK; }
574 mDelayedExecutorDispatcher)IdleRequestExecutor::cycleCollection IdleRequestExecutor::_cycleCollectorGlobal
; void IdleRequestExecutor::cycleCollection::Unlink(void* p) {
IdleRequestExecutor* tmp = DowncastCCParticipant<IdleRequestExecutor
>(p); ImplCycleCollectionUnlink(tmp->mWindow); ImplCycleCollectionUnlink
(tmp->mDelayedExecutorDispatcher); (void)tmp; } nsresult IdleRequestExecutor
::cycleCollection::TraverseNative( void* p, nsCycleCollectionTraversalCallback
& cb) { IdleRequestExecutor* tmp = DowncastCCParticipant<
IdleRequestExecutor>(p); cb.DescribeRefCountedNode(tmp->
mRefCnt.get(), "IdleRequestExecutor"); ImplCycleCollectionTraverse
(cb, tmp->mWindow, "mWindow", 0); ImplCycleCollectionTraverse
(cb, tmp->mDelayedExecutorDispatcher, "mDelayedExecutorDispatcher"
, 0); (void)tmp; return NS_OK; }
575
576NS_IMPL_CYCLE_COLLECTING_ADDREF(IdleRequestExecutor)MozExternalRefCountType IdleRequestExecutor::AddRef(void) { static_assert
(!std::is_destructible_v<IdleRequestExecutor>, "Reference-counted class "
"IdleRequestExecutor" " 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/nsGlobalWindowInner.cpp"
, 576); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
576; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); _mOwningThread.AssertOwnership("IdleRequestExecutor"
" not thread-safe"); nsISupports* base = IdleRequestExecutor
::cycleCollection::Upcast(this); nsrefcnt count = mRefCnt.incr
(base); NS_LogAddRef((this), (count), ("IdleRequestExecutor")
, (uint32_t)(sizeof(*this))); return count; }
577NS_IMPL_CYCLE_COLLECTING_RELEASE(IdleRequestExecutor)MozExternalRefCountType IdleRequestExecutor::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/nsGlobalWindowInner.cpp"
, 577); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 577
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); _mOwningThread.AssertOwnership("IdleRequestExecutor"
" not thread-safe"); nsISupports* base = IdleRequestExecutor
::cycleCollection::Upcast(this); nsrefcnt count = mRefCnt.decr
(base); NS_LogRelease((this), (count), ("IdleRequestExecutor"
)); return count; } void IdleRequestExecutor::DeleteCycleCollectable
(void) { delete (this); }
578
579NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IdleRequestExecutor)nsresult IdleRequestExecutor::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/nsGlobalWindowInner.cpp"
, 579); 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 = IdleRequestExecutor::cycleCollection
::GetParticipant(); return NS_OK; } if (LowWordEquals(aIID, (
nsCycleCollectionISupports::COMTypeInfo<nsCycleCollectionISupports
, void>::kIID))) { *aInstancePtr = IdleRequestExecutor::cycleCollection
::Upcast(this); return NS_OK; } foundInterface = nullptr; } else
580 NS_INTERFACE_MAP_ENTRY(nsIRunnable)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIRunnable>)) foundInterface = static_cast
<nsIRunnable*>(this); else
581 NS_INTERFACE_MAP_ENTRY(nsICancelableRunnable)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsICancelableRunnable>)) foundInterface
= static_cast<nsICancelableRunnable*>(this); else
582 NS_INTERFACE_MAP_ENTRY(nsINamed)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsINamed>)) foundInterface = static_cast
<nsINamed*>(this); else
583 NS_INTERFACE_MAP_ENTRY(nsIIdleRunnable)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIIdleRunnable>)) foundInterface
= static_cast<nsIIdleRunnable*>(this); else
584 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIRunnable)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupports>)) foundInterface = static_cast
<nsISupports*>(static_cast<nsIRunnable*>(this)); else
585NS_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/nsGlobalWindowInner.cpp"
, 585); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIID.Equals((nsISupports::COMTypeInfo<nsISupports, void>::kIID))"
")"); do { *((volatile int*)__null) = 585; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); status = NS_NOINTERFACE
; } else { (foundInterface)->AddRef(); status = NS_OK; } *
aInstancePtr = foundInterface; return status; }
586
587NS_IMETHODIMPnsresult
588IdleRequestExecutor::GetName(nsACString& aName) {
589 aName.AssignLiteral("IdleRequestExecutor");
590 return NS_OK;
591}
592
593// MOZ_CAN_RUN_SCRIPT_BOUNDARY until nsIRunnable::Run is MOZ_CAN_RUN_SCRIPT.
594// See bug 1535398.
595MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHODIMPnsresult IdleRequestExecutor::Run() {
596 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/nsGlobalWindowInner.cpp"
, 596); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 596; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
597
598 mDispatched = false;
599 if (mWindow) {
600 RefPtr<nsGlobalWindowInner> window(mWindow);
601 window->ExecuteIdleRequest(mDeadline);
602 }
603
604 return NS_OK;
605}
606
607nsresult IdleRequestExecutor::Cancel() {
608 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/nsGlobalWindowInner.cpp"
, 608); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 608; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
609
610 if (mDelayedExecutorHandle && mWindow) {
611 mWindow->GetTimeoutManager()->ClearTimeout(
612 mDelayedExecutorHandle.value(), Timeout::Reason::eIdleCallbackTimeout);
613 }
614
615 mWindow = nullptr;
616 return NS_OK;
617}
618
619void IdleRequestExecutor::SetDeadline(TimeStamp aDeadline) {
620 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/nsGlobalWindowInner.cpp"
, 620); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 620; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
621
622 if (!mWindow) {
623 return;
624 }
625
626 mDeadline = aDeadline;
627}
628
629void IdleRequestExecutor::MaybeUpdateIdlePeriodLimit() {
630 if (TimeStamp::Now() > mIdlePeriodLimit.mEndOfIdlePeriod) {
631 mIdlePeriodLimit = {mDeadline, mWindow->LastIdleRequestHandle()};
632 }
633}
634
635void IdleRequestExecutor::MaybeDispatch(TimeStamp aDelayUntil) {
636 // If we've already dispatched the executor we don't want to do it
637 // again. Also, if we've called IdleRequestExecutor::Cancel mWindow
638 // will be null, which indicates that we shouldn't dispatch this
639 // executor either.
640 if (mDispatched || IsCancelled()) {
641 return;
642 }
643
644 mDispatched = true;
645
646 nsPIDOMWindowOuter* outer = mWindow->GetOuterWindow();
647 if (outer && outer->IsBackground()) {
648 // Set a timeout handler with a timeout of 0 ms to throttle idle
649 // callback requests coming from a backround window using
650 // background timeout throttling.
651 DelayedDispatch(0);
652 return;
653 }
654
655 TimeStamp now = TimeStamp::Now();
656 if (!aDelayUntil || aDelayUntil < now) {
657 ScheduleDispatch();
658 return;
659 }
660
661 TimeDuration delay = aDelayUntil - now;
662 DelayedDispatch(static_cast<uint32_t>(delay.ToMilliseconds()));
663}
664
665void IdleRequestExecutor::ScheduleDispatch() {
666 MOZ_ASSERT(mWindow)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mWindow)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mWindow))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mWindow", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 666); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mWindow" ")"
); do { *((volatile int*)__null) = 666; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
667 mDelayedExecutorHandle = Nothing();
668 RefPtr<IdleRequestExecutor> request = this;
669 NS_DispatchToCurrentThreadQueue(request.forget(), EventQueuePriority::Idle);
670}
671
672void IdleRequestExecutor::DelayedDispatch(uint32_t aDelay) {
673 MOZ_ASSERT(mWindow)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mWindow)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mWindow))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mWindow", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 673); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mWindow" ")"
); do { *((volatile int*)__null) = 673; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
674 MOZ_ASSERT(mDelayedExecutorHandle.isNothing())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDelayedExecutorHandle.isNothing())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mDelayedExecutorHandle.isNothing
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mDelayedExecutorHandle.isNothing()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 674); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDelayedExecutorHandle.isNothing()"
")"); do { *((volatile int*)__null) = 674; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
675 int32_t handle;
676 mWindow->GetTimeoutManager()->SetTimeout(
677 mDelayedExecutorDispatcher, aDelay, false,
678 Timeout::Reason::eIdleCallbackTimeout, &handle);
679 mDelayedExecutorHandle = Some(handle);
680}
681
682bool IdleRequestExecutorTimeoutHandler::Call(const char* /* unused */) {
683 if (!mExecutor->IsCancelled()) {
684 mExecutor->ScheduleDispatch();
685 }
686 return true;
687}
688
689void nsGlobalWindowInner::ScheduleIdleRequestDispatch() {
690 AssertIsOnMainThread();
691
692 if (!mIdleRequestExecutor) {
693 mIdleRequestExecutor = new IdleRequestExecutor(this);
694 }
695
696 mIdleRequestExecutor->MaybeDispatch();
697}
698
699void nsGlobalWindowInner::SuspendIdleRequests() {
700 if (mIdleRequestExecutor) {
701 mIdleRequestExecutor->Cancel();
702 mIdleRequestExecutor = nullptr;
703 }
704}
705
706void nsGlobalWindowInner::ResumeIdleRequests() {
707 MOZ_ASSERT(!mIdleRequestExecutor)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIdleRequestExecutor)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mIdleRequestExecutor))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("!mIdleRequestExecutor"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 707); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIdleRequestExecutor"
")"); do { *((volatile int*)__null) = 707; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
708
709 ScheduleIdleRequestDispatch();
710}
711
712void nsGlobalWindowInner::RemoveIdleCallback(
713 mozilla::dom::IdleRequest* aRequest) {
714 AssertIsOnMainThread();
715
716 if (aRequest->HasTimeout()) {
717 mTimeoutManager->ClearTimeout(aRequest->GetTimeoutHandle(),
718 Timeout::Reason::eIdleCallbackTimeout);
719 }
720
721 aRequest->removeFrom(mIdleRequestCallbacks);
722}
723
724void nsGlobalWindowInner::RunIdleRequest(IdleRequest* aRequest,
725 DOMHighResTimeStamp aDeadline,
726 bool aDidTimeout) {
727 AssertIsOnMainThread();
728 // XXXbz Do we still need this RefPtr? MOZ_CAN_RUN_SCRIPT should
729 // guarantee that caller is holding a strong ref on the stack.
730 RefPtr<IdleRequest> request(aRequest);
731 RemoveIdleCallback(request);
732 request->IdleRun(this, aDeadline, aDidTimeout);
733}
734
735void nsGlobalWindowInner::ExecuteIdleRequest(TimeStamp aDeadline) {
736 AssertIsOnMainThread();
737 RefPtr<IdleRequest> request = mIdleRequestCallbacks.getFirst();
738
739 if (!request) {
740 // There are no more idle requests, so stop scheduling idle
741 // request callbacks.
742 return;
743 }
744
745 // If the request that we're trying to execute has been queued
746 // during the current idle period, then dispatch it again at the end
747 // of the idle period.
748 if (mIdleRequestExecutor->IneligibleForCurrentIdlePeriod(request)) {
749 mIdleRequestExecutor->MaybeDispatch(aDeadline);
750 return;
751 }
752
753 DOMHighResTimeStamp deadline = 0.0;
754
755 if (Performance* perf = GetPerformance()) {
756 deadline = perf->GetDOMTiming()->TimeStampToDOMHighRes(aDeadline);
757 }
758
759 mIdleRequestExecutor->MaybeUpdateIdlePeriodLimit();
760 RunIdleRequest(request, deadline, false);
761
762 // Running the idle callback could've suspended the window, in which
763 // case mIdleRequestExecutor will be null.
764 if (mIdleRequestExecutor) {
765 mIdleRequestExecutor->MaybeDispatch();
766 }
767}
768
769class IdleRequestTimeoutHandler final : public TimeoutHandler {
770 public:
771 IdleRequestTimeoutHandler(JSContext* aCx, IdleRequest* aIdleRequest,
772 nsPIDOMWindowInner* aWindow)
773 : TimeoutHandler(aCx), mIdleRequest(aIdleRequest), mWindow(aWindow) {}
774
775 NS_DECL_CYCLE_COLLECTING_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: nsCycleCollectingAutoRefCnt mRefCnt; nsAutoOwningThread
_mOwningThread; public: virtual void DeleteCycleCollectable(
void); public:
776 NS_DECL_CYCLE_COLLECTION_CLASS(IdleRequestTimeoutHandler)class cycleCollection : public nsXPCOMCycleCollectionParticipant
{ public: constexpr explicit cycleCollection(Flags aFlags = 0
) : nsXPCOMCycleCollectionParticipant(aFlags) {} private: public
: virtual nsresult TraverseNative(void* p, nsCycleCollectionTraversalCallback
& cb) override; virtual const char* ClassName() override {
return "IdleRequestTimeoutHandler"; }; virtual void DeleteCycleCollectable
(void* p) override { DowncastCCParticipant<IdleRequestTimeoutHandler
>(p)->DeleteCycleCollectable(); } static IdleRequestTimeoutHandler
* Downcast(nsISupports* s) { return static_cast<IdleRequestTimeoutHandler
*>(static_cast<IdleRequestTimeoutHandler*>(s)); } static
nsISupports* Upcast(IdleRequestTimeoutHandler* p) { return static_cast
<nsISupports*>(static_cast<IdleRequestTimeoutHandler
*>(p)); } template <typename T> friend nsISupports* ToSupports
(T* p, cycleCollection* dummy); virtual void Unlink(void* p) override
; static constexpr nsXPCOMCycleCollectionParticipant* GetParticipant
() { return &IdleRequestTimeoutHandler::_cycleCollectorGlobal
; } }; virtual void CheckForRightParticipant() { nsXPCOMCycleCollectionParticipant
* p; CallQueryInterface(this, &p); do { static_assert( mozilla
::detail::AssertionConditionType<decltype(p == &_cycleCollectorGlobal
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(p == &_cycleCollectorGlobal))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("p == &_cycleCollectorGlobal"
" (" "IdleRequestTimeoutHandler" " should QI to its own CC participant"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 776); AnnotateMozCrashReason("MOZ_ASSERT" "(" "p == &_cycleCollectorGlobal"
") (" "IdleRequestTimeoutHandler" " should QI to its own CC participant"
")"); do { *((volatile int*)__null) = 776; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } static cycleCollection
_cycleCollectorGlobal; virtual void BaseCycleCollectable() final
{}
777
778 MOZ_CAN_RUN_SCRIPT bool Call(const char* /* unused */) override {
779 RefPtr<nsGlobalWindowInner> window(nsGlobalWindowInner::Cast(mWindow));
780 RefPtr<IdleRequest> request(mIdleRequest);
781 window->RunIdleRequest(request, 0.0, true);
782 return true;
783 }
784
785 private:
786 ~IdleRequestTimeoutHandler() override = default;
787
788 RefPtr<IdleRequest> mIdleRequest;
789 nsCOMPtr<nsPIDOMWindowInner> mWindow;
790};
791
792NS_IMPL_CYCLE_COLLECTION(IdleRequestTimeoutHandler, mIdleRequest, mWindow)IdleRequestTimeoutHandler::cycleCollection IdleRequestTimeoutHandler
::_cycleCollectorGlobal; void IdleRequestTimeoutHandler::cycleCollection
::Unlink(void* p) { IdleRequestTimeoutHandler* tmp = DowncastCCParticipant
<IdleRequestTimeoutHandler>(p); ImplCycleCollectionUnlink
(tmp->mIdleRequest); ImplCycleCollectionUnlink(tmp->mWindow
); (void)tmp; } nsresult IdleRequestTimeoutHandler::cycleCollection
::TraverseNative( void* p, nsCycleCollectionTraversalCallback
& cb) { IdleRequestTimeoutHandler* tmp = DowncastCCParticipant
<IdleRequestTimeoutHandler>(p); cb.DescribeRefCountedNode
(tmp->mRefCnt.get(), "IdleRequestTimeoutHandler"); ImplCycleCollectionTraverse
(cb, tmp->mIdleRequest, "mIdleRequest", 0); ImplCycleCollectionTraverse
(cb, tmp->mWindow, "mWindow", 0); (void)tmp; return NS_OK;
}
793
794NS_IMPL_CYCLE_COLLECTING_ADDREF(IdleRequestTimeoutHandler)MozExternalRefCountType IdleRequestTimeoutHandler::AddRef(void
) { static_assert(!std::is_destructible_v<IdleRequestTimeoutHandler
>, "Reference-counted class " "IdleRequestTimeoutHandler" " 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/nsGlobalWindowInner.cpp"
, 794); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
794; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); _mOwningThread.AssertOwnership("IdleRequestTimeoutHandler"
" not thread-safe"); nsISupports* base = IdleRequestTimeoutHandler
::cycleCollection::Upcast(this); nsrefcnt count = mRefCnt.incr
(base); NS_LogAddRef((this), (count), ("IdleRequestTimeoutHandler"
), (uint32_t)(sizeof(*this))); return count; }
795NS_IMPL_CYCLE_COLLECTING_RELEASE(IdleRequestTimeoutHandler)MozExternalRefCountType IdleRequestTimeoutHandler::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/nsGlobalWindowInner.cpp"
, 795); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 795
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); _mOwningThread.AssertOwnership("IdleRequestTimeoutHandler"
" not thread-safe"); nsISupports* base = IdleRequestTimeoutHandler
::cycleCollection::Upcast(this); nsrefcnt count = mRefCnt.decr
(base); NS_LogRelease((this), (count), ("IdleRequestTimeoutHandler"
)); return count; } void IdleRequestTimeoutHandler::DeleteCycleCollectable
(void) { delete (this); }
796
797NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IdleRequestTimeoutHandler)nsresult IdleRequestTimeoutHandler::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/nsGlobalWindowInner.cpp"
, 797); 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 = IdleRequestTimeoutHandler
::cycleCollection::GetParticipant(); return NS_OK; } if (LowWordEquals
(aIID, (nsCycleCollectionISupports::COMTypeInfo<nsCycleCollectionISupports
, void>::kIID))) { *aInstancePtr = IdleRequestTimeoutHandler
::cycleCollection::Upcast(this); return NS_OK; } foundInterface
= nullptr; } else
798 NS_INTERFACE_MAP_ENTRY(nsISupports)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupports>)) foundInterface = static_cast
<nsISupports*>(this); else
799NS_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/nsGlobalWindowInner.cpp"
, 799); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIID.Equals((nsISupports::COMTypeInfo<nsISupports, void>::kIID))"
")"); do { *((volatile int*)__null) = 799; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); status = NS_NOINTERFACE
; } else { (foundInterface)->AddRef(); status = NS_OK; } *
aInstancePtr = foundInterface; return status; }
800
801uint32_t nsGlobalWindowInner::RequestIdleCallback(
802 JSContext* aCx, IdleRequestCallback& aCallback,
803 const IdleRequestOptions& aOptions, ErrorResult& aError) {
804 AssertIsOnMainThread();
805
806 if (IsDying()) {
807 return 0;
808 }
809
810 uint32_t handle = mIdleRequestCallbackCounter++;
811
812 RefPtr<IdleRequest> request = new IdleRequest(&aCallback, handle);
813
814 if (aOptions.mTimeout.WasPassed()) {
815 int32_t timeoutHandle;
816 RefPtr<TimeoutHandler> handler(
817 new IdleRequestTimeoutHandler(aCx, request, this));
818
819 nsresult rv = mTimeoutManager->SetTimeout(
820 handler, aOptions.mTimeout.Value(), false,
821 Timeout::Reason::eIdleCallbackTimeout, &timeoutHandle);
822
823 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 823)
) {
824 return 0;
825 }
826
827 request->SetTimeoutHandle(timeoutHandle);
828 }
829
830 mIdleRequestCallbacks.insertBack(request);
831
832 if (!IsSuspended()) {
833 ScheduleIdleRequestDispatch();
834 }
835
836 return handle;
837}
838
839void nsGlobalWindowInner::CancelIdleCallback(uint32_t aHandle) {
840 for (IdleRequest* r : mIdleRequestCallbacks) {
841 if (r->Handle() == aHandle) {
842 RemoveIdleCallback(r);
843 break;
844 }
845 }
846}
847
848void nsGlobalWindowInner::DisableIdleCallbackRequests() {
849 if (mIdleRequestExecutor) {
850 mIdleRequestExecutor->Cancel();
851 mIdleRequestExecutor = nullptr;
852 }
853
854 while (!mIdleRequestCallbacks.isEmpty()) {
855 RefPtr<IdleRequest> request = mIdleRequestCallbacks.getFirst();
856 RemoveIdleCallback(request);
857 }
858}
859
860bool nsGlobalWindowInner::IsBackgroundInternal() const {
861 return !mOuterWindow || mOuterWindow->IsBackground();
862}
863
864class PromiseDocumentFlushedResolver final {
865 public:
866 PromiseDocumentFlushedResolver(Promise* aPromise,
867 PromiseDocumentFlushedCallback& aCallback)
868 : mPromise(aPromise), mCallback(&aCallback) {}
869
870 virtual ~PromiseDocumentFlushedResolver() = default;
871
872 void Call() {
873 nsMutationGuard guard;
874 ErrorResult error;
875 JS::Rooted<JS::Value> returnVal(RootingCx());
876 mCallback->Call(&returnVal, error);
877
878 if (error.Failed()) {
879 mPromise->MaybeReject(std::move(error));
880 } else if (guard.Mutated(0)) {
881 // Something within the callback mutated the DOM.
882 mPromise->MaybeRejectWithNoModificationAllowedError(
883 "DOM mutated from promiseDocumentFlushed callbacks");
884 } else {
885 mPromise->MaybeResolve(returnVal);
886 }
887 }
888
889 RefPtr<Promise> mPromise;
890 RefPtr<PromiseDocumentFlushedCallback> mCallback;
891};
892
893//*****************************************************************************
894//*** nsGlobalWindowInner: Object Management
895//*****************************************************************************
896
897nsGlobalWindowInner::nsGlobalWindowInner(nsGlobalWindowOuter* aOuterWindow,
898 WindowGlobalChild* aActor)
899 : nsPIDOMWindowInner(aOuterWindow, aActor),
900 mHasOrientationChangeListeners(false),
901 mWasOffline(false),
902 mHasHadSlowScript(false),
903 mIsChrome(false),
904 mCleanMessageManager(false),
905 mNeedsFocus(true),
906 mHasFocus(false),
907 mFocusByKeyOccurred(false),
908 mDidFireDocElemInserted(false),
909 mHasGamepad(false),
910 mHasXRSession(false),
911 mHasVRDisplayActivateEvents(false),
912 mXRRuntimeDetectionInFlight(false),
913 mXRPermissionRequestInFlight(false),
914 mXRPermissionGranted(false),
915 mWasCurrentInnerWindow(false),
916 mHasSeenGamepadInput(false),
917 mHintedWasLoading(false),
918 mHasOpenedExternalProtocolFrame(false),
919 mScrollMarksOnHScrollbar(false),
920 mStorageAllowedReasonCache(0),
921 mSuspendDepth(0),
922 mFreezeDepth(0),
923#ifdef DEBUG1
924 mSerial(0),
925#endif
926 mFocusMethod(0),
927 mIdleRequestCallbackCounter(1),
928 mIdleRequestExecutor(nullptr),
929 mObservingRefresh(false),
930 mIteratingDocumentFlushedResolvers(false),
931 mCanSkipCCGeneration(0) {
932 mIsInnerWindow = true;
933
934 AssertIsOnMainThread();
935 SetIsOnMainThread();
936 nsLayoutStatics::AddRef();
937
938 // Initialize the PRCList (this).
939 PR_INIT_CLIST(this)do { (this)->next = (this); (this)->prev = (this); } while
(0)
;
940
941 // add this inner window to the outer window list of inners.
942 PR_INSERT_AFTER(this, aOuterWindow)do { (this)->next = (aOuterWindow)->next; (this)->prev
= (aOuterWindow); (aOuterWindow)->next->prev = (this);
(aOuterWindow)->next = (this); } while (0)
;
943
944 mTimeoutManager = MakeUnique<dom::TimeoutManager>(
945 *this, StaticPrefs::dom_timeout_max_idle_defer_ms());
946
947 mObserver = new nsGlobalWindowObserver(this);
948 if (nsCOMPtr<nsIObserverService> os = services::GetObserverService()) {
949 // Watch for online/offline status changes so we can fire events. Use
950 // a strong reference.
951 os->AddObserver(mObserver, NS_IOSERVICE_OFFLINE_STATUS_TOPIC"network:offline-status-changed", false);
952 os->AddObserver(mObserver, MEMORY_PRESSURE_OBSERVER_TOPIC"memory-pressure", false);
953 os->AddObserver(mObserver, PERMISSION_CHANGED_TOPIC"perm-changed", false);
954 os->AddObserver(mObserver, "screen-information-changed", false);
955 }
956
957 Preferences::AddStrongObserver(mObserver, "intl.accept_languages");
958
959 // Watch for storage notifications so we can fire storage events.
960 RefPtr<StorageNotifierService> sns = StorageNotifierService::GetOrCreate();
961 if (sns) {
962 sns->Register(mObserver);
963 }
964
965 if (XRE_IsContentProcess()) {
966 nsCOMPtr<nsIDocShell> docShell = GetDocShell();
967 if (docShell) {
968 mBrowserChild = docShell->GetBrowserChild();
969 }
970 }
971
972 if (gDumpFile == nullptr) {
973 nsAutoCString fname;
974 Preferences::GetCString("browser.dom.window.dump.file", fname);
975 if (!fname.IsEmpty()) {
976 // If this fails to open, Dump() knows to just go to stdout on null.
977 gDumpFile = fopen(fname.get(), "wb+");
978 } else {
979 gDumpFile = stdoutstdout;
980 }
981 }
982
983#ifdef DEBUG1
984 mSerial = nsContentUtils::InnerOrOuterWindowCreated();
985
986 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, static_cast
<void*>(ToCanonicalSupports(aOuterWindow))); } } while (
0)
987 ("++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, static_cast
<void*>(ToCanonicalSupports(aOuterWindow))); } } while (
0)
988 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, static_cast
<void*>(ToCanonicalSupports(aOuterWindow))); } } while (
0)
989 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, static_cast
<void*>(ToCanonicalSupports(aOuterWindow))); } } while (
0)
990 static_cast<void*>(ToCanonicalSupports(aOuterWindow))))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, static_cast
<void*>(ToCanonicalSupports(aOuterWindow))); } } while (
0)
;
991#endif
992
993 MOZ_LOG(gDOMLeakPRLogInner, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogInner
; 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=%p", this, aOuterWindow
); } } while (0)
994 ("DOMWINDOW %p created outer=%p", this, aOuterWindow))do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogInner
; 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=%p", this, aOuterWindow
); } } while (0)
;
995
996 // Add ourselves to the inner windows list.
997 MOZ_ASSERT(sInnerWindowsById, "Inner Windows hash table must be created!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sInnerWindowsById)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sInnerWindowsById))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("sInnerWindowsById"
" (" "Inner Windows hash table must be created!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 997); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sInnerWindowsById"
") (" "Inner Windows hash table must be created!" ")"); do {
*((volatile int*)__null) = 997; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
998 MOZ_ASSERT(!sInnerWindowsById->Contains(mWindowID),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!sInnerWindowsById->Contains(mWindowID))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!sInnerWindowsById->Contains(mWindowID)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!sInnerWindowsById->Contains(mWindowID)"
" (" "This window shouldn't be in the hash table yet!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 999); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sInnerWindowsById->Contains(mWindowID)"
") (" "This window shouldn't be in the hash table yet!" ")")
; do { *((volatile int*)__null) = 999; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
999 "This window shouldn't be in the hash table yet!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!sInnerWindowsById->Contains(mWindowID))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!sInnerWindowsById->Contains(mWindowID)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!sInnerWindowsById->Contains(mWindowID)"
" (" "This window shouldn't be in the hash table yet!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 999); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sInnerWindowsById->Contains(mWindowID)"
") (" "This window shouldn't be in the hash table yet!" ")")
; do { *((volatile int*)__null) = 999; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1000 // We seem to see crashes in release builds because of null
1001 // |sInnerWindowsById|.
1002 if (sInnerWindowsById) {
1003 sInnerWindowsById->InsertOrUpdate(mWindowID, this);
1004 }
1005}
1006
1007#ifdef DEBUG1
1008
1009/* static */
1010void nsGlobalWindowInner::AssertIsOnMainThread() {
1011 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/nsGlobalWindowInner.cpp"
, 1011); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 1011; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1012}
1013
1014#endif // DEBUG
1015
1016/* static */
1017void nsGlobalWindowInner::Init() {
1018 AssertIsOnMainThread();
1019
1020 NS_ASSERTION(gDOMLeakPRLogInner,do { if (!(gDOMLeakPRLogInner)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "gDOMLeakPRLogInner should have been initialized!", "gDOMLeakPRLogInner"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 1021); MOZ_PretendNoReturn(); } } while (0)
1021 "gDOMLeakPRLogInner should have been initialized!")do { if (!(gDOMLeakPRLogInner)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "gDOMLeakPRLogInner should have been initialized!", "gDOMLeakPRLogInner"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 1021); MOZ_PretendNoReturn(); } } while (0)
;
1022
1023 sInnerWindowsById = new InnerWindowByIdTable();
1024}
1025
1026nsGlobalWindowInner::~nsGlobalWindowInner() {
1027 AssertIsOnMainThread();
1028 MOZ_ASSERT(!mHintedWasLoading)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mHintedWasLoading)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mHintedWasLoading))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!mHintedWasLoading"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 1028); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mHintedWasLoading"
")"); do { *((volatile int*)__null) = 1028; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1029
1030 if (IsChromeWindow()) {
1031 MOZ_ASSERT(mCleanMessageManager,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mCleanMessageManager)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mCleanMessageManager))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("mCleanMessageManager"
" (" "chrome windows may always disconnect the msg manager" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 1032); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCleanMessageManager"
") (" "chrome windows may always disconnect the msg manager"
")"); do { *((volatile int*)__null) = 1032; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1032 "chrome windows may always disconnect the msg manager")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mCleanMessageManager)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mCleanMessageManager))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("mCleanMessageManager"
" (" "chrome windows may always disconnect the msg manager" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 1032); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCleanMessageManager"
") (" "chrome windows may always disconnect the msg manager"
")"); do { *((volatile int*)__null) = 1032; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1033
1034 DisconnectAndClearGroupMessageManagers();
1035
1036 if (mChromeFields.mMessageManager) {
1037 static_cast<nsFrameMessageManager*>(mChromeFields.mMessageManager.get())
1038 ->Disconnect();
1039 }
1040
1041 mCleanMessageManager = false;
1042 }
1043
1044 // In most cases this should already have been called, but call it again
1045 // here to catch any corner cases.
1046 FreeInnerObjects();
1047
1048 if (sInnerWindowsById) {
1049 sInnerWindowsById->Remove(mWindowID);
1050 }
1051
1052 nsContentUtils::InnerOrOuterWindowDestroyed();
1053
1054#ifdef DEBUG1
1055 if (MOZ_LOG_TEST(gDocShellAndDOMWindowLeakLogging, LogLevel::Info)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellAndDOMWindowLeakLogging
, LogLevel::Info)), 0))
) {
1056 nsAutoCString url;
1057 if (mLastOpenedURI) {
1058 url = mLastOpenedURI->GetSpecOrDefault();
1059
1060 // Data URLs can be very long, so truncate to avoid flooding the log.
1061 const uint32_t maxURLLength = 1000;
1062 if (url.Length() > maxURLLength) {
1063 url.Truncate(maxURLLength);
1064 }
1065 }
1066
1067 nsGlobalWindowOuter* outer = nsGlobalWindowOuter::Cast(mOuterWindow);
1068 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, static_cast<void*>(ToCanonicalSupports(outer
)), url.get()); } } while (0)
1069 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, static_cast<void*>(ToCanonicalSupports(outer
)), url.get()); } } while (0)
1070 ("--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, static_cast<void*>(ToCanonicalSupports(outer
)), url.get()); } } while (0)
1071 "%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, static_cast<void*>(ToCanonicalSupports(outer
)), url.get()); } } while (0)
1072 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, static_cast<void*>(ToCanonicalSupports(outer
)), url.get()); } } while (0)
1073 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, static_cast<void*>(ToCanonicalSupports(outer
)), url.get()); } } while (0)
1074 static_cast<void*>(ToCanonicalSupports(outer)), 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, static_cast<void*>(ToCanonicalSupports(outer
)), url.get()); } } while (0)
;
1075 }
1076#endif
1077 MOZ_LOG(gDOMLeakPRLogInner, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogInner
; 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)
1078 ("DOMWINDOW %p destroyed", this))do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogInner
; 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)
;
1079
1080 Telemetry::Accumulate(Telemetry::INNERWINDOWS_WITH_MUTATION_LISTENERS,
1081 mMutationBits ? 1 : 0);
1082
1083 // An inner window is destroyed, pull it out of the outer window's
1084 // list if inner windows.
1085
1086 PR_REMOVE_LINK(this)do { (this)->prev->next = (this)->next; (this)->next
->prev = (this)->prev; } while (0)
;
1087
1088 // If our outer window's inner window is this window, null out the
1089 // outer window's reference to this window that's being deleted.
1090 nsGlobalWindowOuter* outer = GetOuterWindowInternal();
1091 if (outer) {
1092 outer->MaybeClearInnerWindow(this);
1093 }
1094
1095 // We don't have to leave the tab group if we are an inner window.
1096
1097 nsCOMPtr<nsIDeviceSensors> ac = do_GetService(NS_DEVICE_SENSORS_CONTRACTID"@mozilla.org/devicesensors;1");
1098 if (ac) ac->RemoveWindowAsListener(this);
1099
1100 nsLayoutStatics::Release();
1101}
1102
1103// static
1104void nsGlobalWindowInner::ShutDown() {
1105 AssertIsOnMainThread();
1106
1107 if (gDumpFile && gDumpFile != stdoutstdout) {
1108 fclose(gDumpFile);
1109 }
1110 gDumpFile = nullptr;
1111
1112 delete sInnerWindowsById;
1113 sInnerWindowsById = nullptr;
1114}
1115
1116void nsGlobalWindowInner::FreeInnerObjects() {
1117 if (IsDying()) {
1118 return;
1119 }
1120 StartDying();
1121
1122 if (mDoc && mDoc->GetWindowContext()) {
1123 // The document is about to lose its window, so this is a good time to send
1124 // our page use counters.
1125 //
1126 // (We also do this in Document::SetScriptGlobalObject(nullptr), which
1127 // catches most cases of documents losing their window, but not all.)
1128 mDoc->SendPageUseCounters();
1129 }
1130
1131 // Make sure that this is called before we null out the document and
1132 // other members that the window destroyed observers could
1133 // re-create.
1134 NotifyDOMWindowDestroyed(this);
1135 if (auto* reporter = nsWindowMemoryReporter::Get()) {
1136 reporter->ObserveDOMWindowDetached(this);
1137 }
1138
1139 // Kill all of the workers for this window.
1140 CancelWorkersForWindow(*this);
1141
1142 for (RefPtr<mozilla::dom::SharedWorker> pinnedWorker :
1143 mSharedWorkers.ForwardRange()) {
1144 pinnedWorker->Close();
1145 }
1146
1147 if (mTimeoutManager) {
1148 mTimeoutManager->ClearAllTimeouts();
1149 }
1150
1151 DisableIdleCallbackRequests();
1152
1153 mChromeEventHandler = nullptr;
1154
1155 if (mListenerManager) {
1156 mListenerManager->RemoveAllListeners();
1157 mListenerManager->Disconnect();
1158 mListenerManager = nullptr;
1159 }
1160
1161 mHistory = nullptr;
1162
1163 if (mNavigator) {
1164 mNavigator->OnNavigation();
1165 mNavigator->Invalidate();
1166 mNavigator = nullptr;
1167 }
1168
1169 mScreen = nullptr;
1170
1171 if (mDoc) {
1172 // Remember the document's principal, URI, and CSP.
1173 mDocumentPrincipal = mDoc->NodePrincipal();
1174 mDocumentCookiePrincipal = mDoc->EffectiveCookiePrincipal();
1175 mDocumentStoragePrincipal = mDoc->EffectiveStoragePrincipal();
1176 mDocumentPartitionedPrincipal = mDoc->PartitionedPrincipal();
1177 mDocumentURI = mDoc->GetDocumentURI();
1178 mDocBaseURI = mDoc->GetDocBaseURI();
1179 mDocumentCsp = mDoc->GetCsp();
1180
1181 while (mDoc->EventHandlingSuppressed()) {
1182 mDoc->UnsuppressEventHandlingAndFireEvents(false);
1183 }
1184 }
1185
1186 // Remove our reference to the document and the document principal.
1187 mFocusedElement = nullptr;
1188
1189 nsIGlobalObject::UnlinkObjectsInGlobal();
1190
1191 NotifyWindowIDDestroyed("inner-window-destroyed");
1192
1193 for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) {
1194 mAudioContexts[i]->OnWindowDestroy();
1195 }
1196 mAudioContexts.Clear();
1197
1198 for (MediaKeys* mediaKeys : mMediaKeysInstances) {
1199 mediaKeys->OnInnerWindowDestroy();
1200 }
1201 mMediaKeysInstances.Clear();
1202
1203 DisableGamepadUpdates();
1204 mHasGamepad = false;
1205 mGamepads.Clear();
1206 DisableVRUpdates();
1207 mHasXRSession = false;
1208 mHasVRDisplayActivateEvents = false;
1209 mXRRuntimeDetectionInFlight = false;
1210 mXRPermissionRequestInFlight = false;
1211 mXRPermissionGranted = false;
1212 mVRDisplays.Clear();
1213
1214 // This breaks a cycle between the window and the ClientSource object.
1215 mClientSource.reset();
1216
1217 if (mWindowGlobalChild) {
1218 // Remove any remaining listeners.
1219 int64_t nListeners = mWindowGlobalChild->BeforeUnloadListeners();
1220 for (int64_t i = 0; i < nListeners; ++i) {
1221 mWindowGlobalChild->BeforeUnloadRemoved();
1222 }
1223 MOZ_ASSERT(mWindowGlobalChild->BeforeUnloadListeners() == 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mWindowGlobalChild->BeforeUnloadListeners() == 0)
>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mWindowGlobalChild->BeforeUnloadListeners() == 0)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mWindowGlobalChild->BeforeUnloadListeners() == 0"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 1223); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mWindowGlobalChild->BeforeUnloadListeners() == 0"
")"); do { *((volatile int*)__null) = 1223; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1224 }
1225
1226 // If we have any promiseDocumentFlushed callbacks, fire them now so
1227 // that the Promises can resolve.
1228 CallDocumentFlushedResolvers(/* aUntilExhaustion = */ true);
1229
1230 DisconnectGlobalTeardownObservers();
1231
1232#ifdef MOZ_WIDGET_ANDROID
1233 DisableOrientationChangeListener();
1234#endif
1235
1236 if (mObserver) {
1237 if (nsCOMPtr<nsIObserverService> os = services::GetObserverService()) {
1238 os->RemoveObserver(mObserver, NS_IOSERVICE_OFFLINE_STATUS_TOPIC"network:offline-status-changed");
1239 os->RemoveObserver(mObserver, MEMORY_PRESSURE_OBSERVER_TOPIC"memory-pressure");
1240 os->RemoveObserver(mObserver, PERMISSION_CHANGED_TOPIC"perm-changed");
1241 os->RemoveObserver(mObserver, "screen-information-changed");
1242 }
1243
1244 RefPtr<StorageNotifierService> sns = StorageNotifierService::GetOrCreate();
1245 if (sns) {
1246 sns->Unregister(mObserver);
1247 }
1248
1249 Preferences::RemoveObserver(mObserver, "intl.accept_languages");
1250
1251 // Drop its reference to this dying window, in case for some bogus reason
1252 // the object stays around.
1253 mObserver->Forget();
1254 }
1255
1256 mMenubar = nullptr;
1257 mToolbar = nullptr;
1258 mLocationbar = nullptr;
1259 mPersonalbar = nullptr;
1260 mStatusbar = nullptr;
1261 mScrollbars = nullptr;
1262
1263 mConsole = nullptr;
1264
1265 mPaintWorklet = nullptr;
1266
1267 mExternal = nullptr;
1268 mInstallTrigger = nullptr;
1269
1270 if (mLocalStorage) {
1271 mLocalStorage->Disconnect();
1272 mLocalStorage = nullptr;
1273 }
1274 mSessionStorage = nullptr;
1275 if (mPerformance) {
1276 // Since window is dying, nothing is going to be painted
1277 // with meaningful sizes, so these temp data for LCP is
1278 // no longer needed.
1279 static_cast<PerformanceMainThread*>(mPerformance.get())
1280 ->ClearGeneratedTempDataForLCP();
1281 }
1282 mPerformance = nullptr;
1283
1284 mContentMediaController = nullptr;
1285
1286 if (mWebTaskScheduler) {
1287 mWebTaskScheduler->Disconnect();
1288 mWebTaskScheduler = nullptr;
1289 }
1290
1291 mTrustedTypePolicyFactory = nullptr;
1292
1293 mSharedWorkers.Clear();
1294
1295#ifdef MOZ_WEBSPEECH1
1296 mSpeechSynthesis = nullptr;
1297#endif
1298
1299 mGlean = nullptr;
1300 mGleanPings = nullptr;
1301
1302 mParentTarget = nullptr;
1303
1304 if (mCleanMessageManager) {
1305 MOZ_ASSERT(mIsChrome, "only chrome should have msg manager cleaned")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mIsChrome)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mIsChrome))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mIsChrome" " (" "only chrome should have msg manager cleaned"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 1305); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIsChrome" ") ("
"only chrome should have msg manager cleaned" ")"); do { *((
volatile int*)__null) = 1305; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
1306 if (mChromeFields.mMessageManager) {
1307 mChromeFields.mMessageManager->Disconnect();
1308 }
1309 }
1310
1311 if (mWindowGlobalChild && !mWindowGlobalChild->IsClosed()) {
1312 mWindowGlobalChild->Destroy();
1313 }
1314
1315 mIntlUtils = nullptr;
1316
1317 HintIsLoading(false);
1318}
1319
1320//*****************************************************************************
1321// nsGlobalWindowInner::nsISupports
1322//*****************************************************************************
1323
1324// QueryInterface implementation for nsGlobalWindowInner
1325NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsGlobalWindowInner)nsresult nsGlobalWindowInner::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/nsGlobalWindowInner.cpp"
, 1325); 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 = nsGlobalWindowInner::cycleCollection
::GetParticipant(); return NS_OK; } if (LowWordEquals(aIID, (
nsCycleCollectionISupports::COMTypeInfo<nsCycleCollectionISupports
, void>::kIID))) { *aInstancePtr = nsGlobalWindowInner::cycleCollection
::Upcast(this); return NS_OK; } foundInterface = nullptr; } else
1326 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRYif (aIID.Equals((nsWrapperCache::COMTypeInfo<nsWrapperCache
, void>::kIID))) { *aInstancePtr = static_cast<nsWrapperCache
*>(this); return NS_OK; } else
1327 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
1328 NS_INTERFACE_MAP_ENTRY(nsIDOMWindow)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIDOMWindow>)) foundInterface = static_cast
<nsIDOMWindow*>(this); else
1329 NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIGlobalObject>)) foundInterface
= static_cast<nsIGlobalObject*>(this); else
1330 NS_INTERFACE_MAP_ENTRY(nsIScriptGlobalObject)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIScriptGlobalObject>)) foundInterface
= static_cast<nsIScriptGlobalObject*>(this); else
1331 NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIScriptObjectPrincipal>)) foundInterface
= static_cast<nsIScriptObjectPrincipal*>(this); else
1332 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
1333 NS_INTERFACE_MAP_ENTRY(nsPIDOMWindowInner)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsPIDOMWindowInner>)) foundInterface
= static_cast<nsPIDOMWindowInner*>(this); else
1334 NS_INTERFACE_MAP_ENTRY(mozIDOMWindow)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, mozIDOMWindow>)) foundInterface =
static_cast<mozIDOMWindow*>(this); else
1335 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupportsWeakReference>)) foundInterface
= static_cast<nsISupportsWeakReference*>(this); else
1336 NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIInterfaceRequestor>)) foundInterface
= static_cast<nsIInterfaceRequestor*>(this); else
1337NS_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/nsGlobalWindowInner.cpp"
, 1337); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIID.Equals((nsISupports::COMTypeInfo<nsISupports, void>::kIID))"
")"); do { *((volatile int*)__null) = 1337; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); status = NS_NOINTERFACE
; } else { (foundInterface)->AddRef(); status = NS_OK; } *
aInstancePtr = foundInterface; return status; }
1338
1339NS_IMPL_CYCLE_COLLECTING_ADDREF(nsGlobalWindowInner)MozExternalRefCountType nsGlobalWindowInner::AddRef(void) { static_assert
(!std::is_destructible_v<nsGlobalWindowInner>, "Reference-counted class "
"nsGlobalWindowInner" " 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/nsGlobalWindowInner.cpp"
, 1339); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
1339; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); _mOwningThread.AssertOwnership("nsGlobalWindowInner"
" not thread-safe"); nsISupports* base = nsGlobalWindowInner
::cycleCollection::Upcast(this); nsrefcnt count = mRefCnt.incr
(base); NS_LogAddRef((this), (count), ("nsGlobalWindowInner")
, (uint32_t)(sizeof(*this))); return count; }
1340NS_IMPL_CYCLE_COLLECTING_RELEASE(nsGlobalWindowInner)MozExternalRefCountType nsGlobalWindowInner::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/nsGlobalWindowInner.cpp"
, 1340); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 1340
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); _mOwningThread.AssertOwnership("nsGlobalWindowInner"
" not thread-safe"); nsISupports* base = nsGlobalWindowInner
::cycleCollection::Upcast(this); nsrefcnt count = mRefCnt.decr
(base); NS_LogRelease((this), (count), ("nsGlobalWindowInner"
)); return count; } void nsGlobalWindowInner::DeleteCycleCollectable
(void) { delete (this); }
1341
1342NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsGlobalWindowInner)bool nsGlobalWindowInner::cycleCollection::CanSkipReal(void* p
, bool aRemovingAllowed) { nsGlobalWindowInner* tmp = DowncastCCParticipant
<nsGlobalWindowInner>(p);
1343 if (tmp->IsBlackForCC(false)) {
1344 if (nsCCUncollectableMarker::InGeneration(tmp->mCanSkipCCGeneration)) {
1345 return true;
1346 }
1347 tmp->mCanSkipCCGeneration = nsCCUncollectableMarker::sGeneration;
1348 if (EventListenerManager* elm = tmp->GetExistingListenerManager()) {
1349 elm->MarkForCC();
1350 }
1351 if (tmp->mTimeoutManager) {
1352 tmp->mTimeoutManager->UnmarkGrayTimers();
1353 }
1354 return true;
1355 }
1356NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END(void)tmp; return false; }
1357
1358NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsGlobalWindowInner)bool nsGlobalWindowInner::cycleCollection::CanSkipInCCReal(void
* p) { nsGlobalWindowInner* tmp = DowncastCCParticipant<nsGlobalWindowInner
>(p);
1359 return tmp->IsBlackForCC(true);
1360NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END(void)tmp; return false; }
1361
1362NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsGlobalWindowInner)bool nsGlobalWindowInner::cycleCollection::CanSkipThisReal(void
* p) { nsGlobalWindowInner* tmp = DowncastCCParticipant<nsGlobalWindowInner
>(p);
1363 return tmp->IsBlackForCC(false);
1364NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END(void)tmp; return false; }
1365
1366NS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalWindowInner)nsGlobalWindowInner::cycleCollection nsGlobalWindowInner::_cycleCollectorGlobal
;
1367
1368NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGlobalWindowInner)nsresult nsGlobalWindowInner::cycleCollection::TraverseNative
( void* p, nsCycleCollectionTraversalCallback& cb) { nsGlobalWindowInner
* tmp = DowncastCCParticipant<nsGlobalWindowInner>(p);
1369 if (MOZ_UNLIKELY(cb.WantDebugInfo())(__builtin_expect(!!(cb.WantDebugInfo()), 0))) {
1370 char name[512];
1371 nsAutoCString uri;
1372 if (tmp->mDoc && tmp->mDoc->GetDocumentURI()) {
1373 uri = tmp->mDoc->GetDocumentURI()->GetSpecOrDefault();
1374 }
1375 SprintfLiteral(name, "nsGlobalWindowInner # %" PRIu64"l" "u" " inner %s",
1376 tmp->mWindowID, uri.get());
1377 cb.DescribeRefCountedNode(tmp->mRefCnt.get(), name);
1378 } else {
1379 NS_IMPL_CYCLE_COLLECTION_DESCRIBE(nsGlobalWindowInner, tmp->mRefCnt.get())cb.DescribeRefCountedNode(tmp->mRefCnt.get(), "nsGlobalWindowInner"
);
1380 }
1381
1382 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNavigator)ImplCycleCollectionTraverse(cb, tmp->mNavigator, "mNavigator"
, 0);
1383
1384 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPerformance)ImplCycleCollectionTraverse(cb, tmp->mPerformance, "mPerformance"
, 0);
1385
1386 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWebTaskScheduler)ImplCycleCollectionTraverse(cb, tmp->mWebTaskScheduler, "mWebTaskScheduler"
, 0);
1387
1388 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTrustedTypePolicyFactory)ImplCycleCollectionTraverse(cb, tmp->mTrustedTypePolicyFactory
, "mTrustedTypePolicyFactory", 0);
1389
1390#ifdef MOZ_WEBSPEECH1
1391 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSpeechSynthesis)ImplCycleCollectionTraverse(cb, tmp->mSpeechSynthesis, "mSpeechSynthesis"
, 0);
1392#endif
1393
1394 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlean)ImplCycleCollectionTraverse(cb, tmp->mGlean, "mGlean", 0);
1395 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGleanPings)ImplCycleCollectionTraverse(cb, tmp->mGleanPings, "mGleanPings"
, 0);
1396
1397 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOuterWindow)ImplCycleCollectionTraverse(cb, tmp->mOuterWindow, "mOuterWindow"
, 0);
1398
1399 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTopInnerWindow)ImplCycleCollectionTraverse(cb, tmp->mTopInnerWindow, "mTopInnerWindow"
, 0);
1400
1401 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mListenerManager)ImplCycleCollectionTraverse(cb, tmp->mListenerManager, "mListenerManager"
, 0);
1402
1403 if (tmp->mTimeoutManager) {
1404 tmp->mTimeoutManager->ForEachUnorderedTimeout([&cb](Timeout* timeout) {
1405 cb.NoteNativeChild(timeout, NS_CYCLE_COLLECTION_PARTICIPANT(Timeout)Timeout::cycleCollection::GetParticipant());
1406 });
1407 }
1408
1409 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocation)ImplCycleCollectionTraverse(cb, tmp->mLocation, "mLocation"
, 0);
1410 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mHistory)ImplCycleCollectionTraverse(cb, tmp->mHistory, "mHistory",
0);
1411 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNavigation)ImplCycleCollectionTraverse(cb, tmp->mNavigation, "mNavigation"
, 0);
1412 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCustomElements)ImplCycleCollectionTraverse(cb, tmp->mCustomElements, "mCustomElements"
, 0);
1413 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSharedWorkers)ImplCycleCollectionTraverse(cb, tmp->mSharedWorkers, "mSharedWorkers"
, 0);
1414 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocalStorage)ImplCycleCollectionTraverse(cb, tmp->mLocalStorage, "mLocalStorage"
, 0);
1415 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSessionStorage)ImplCycleCollectionTraverse(cb, tmp->mSessionStorage, "mSessionStorage"
, 0);
1416 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIndexedDB)ImplCycleCollectionTraverse(cb, tmp->mIndexedDB, "mIndexedDB"
, 0);
1417 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentPrincipal)ImplCycleCollectionTraverse(cb, tmp->mDocumentPrincipal, "mDocumentPrincipal"
, 0);
1418 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentCookiePrincipal)ImplCycleCollectionTraverse(cb, tmp->mDocumentCookiePrincipal
, "mDocumentCookiePrincipal", 0);
1419 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentStoragePrincipal)ImplCycleCollectionTraverse(cb, tmp->mDocumentStoragePrincipal
, "mDocumentStoragePrincipal", 0);
1420 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentPartitionedPrincipal)ImplCycleCollectionTraverse(cb, tmp->mDocumentPartitionedPrincipal
, "mDocumentPartitionedPrincipal", 0);
1421 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentCsp)ImplCycleCollectionTraverse(cb, tmp->mDocumentCsp, "mDocumentCsp"
, 0);
1422 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowserChild)ImplCycleCollectionTraverse(cb, tmp->mBrowserChild, "mBrowserChild"
, 0);
1423 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDoc)ImplCycleCollectionTraverse(cb, tmp->mDoc, "mDoc", 0);
1424
1425 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIdleRequestExecutor)ImplCycleCollectionTraverse(cb, tmp->mIdleRequestExecutor,
"mIdleRequestExecutor", 0);
1426 for (IdleRequest* request : tmp->mIdleRequestCallbacks) {
1427 cb.NoteNativeChild(request, NS_CYCLE_COLLECTION_PARTICIPANT(IdleRequest)IdleRequest::cycleCollection::GetParticipant());
1428 }
1429
1430 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mClientSource)ImplCycleCollectionTraverse(cb, tmp->mClientSource, "mClientSource"
, 0);
1431
1432 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGamepads)ImplCycleCollectionTraverse(cb, tmp->mGamepads, "mGamepads"
, 0);
1433
1434 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCacheStorage)ImplCycleCollectionTraverse(cb, tmp->mCacheStorage, "mCacheStorage"
, 0);
1435 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVRDisplays)ImplCycleCollectionTraverse(cb, tmp->mVRDisplays, "mVRDisplays"
, 0);
1436
1437 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDebuggerNotificationManager)ImplCycleCollectionTraverse(cb, tmp->mDebuggerNotificationManager
, "mDebuggerNotificationManager", 0);
1438
1439 // Traverse stuff from nsPIDOMWindow
1440 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeEventHandler)ImplCycleCollectionTraverse(cb, tmp->mChromeEventHandler, "mChromeEventHandler"
, 0);
1441 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParentTarget)ImplCycleCollectionTraverse(cb, tmp->mParentTarget, "mParentTarget"
, 0);
1442 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFocusedElement)ImplCycleCollectionTraverse(cb, tmp->mFocusedElement, "mFocusedElement"
, 0);
1443 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowsingContext)ImplCycleCollectionTraverse(cb, tmp->mBrowsingContext, "mBrowsingContext"
, 0);
1444 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindowGlobalChild)ImplCycleCollectionTraverse(cb, tmp->mWindowGlobalChild, "mWindowGlobalChild"
, 0);
1445
1446 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMenubar)ImplCycleCollectionTraverse(cb, tmp->mMenubar, "mMenubar",
0);
1447 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mToolbar)ImplCycleCollectionTraverse(cb, tmp->mToolbar, "mToolbar",
0);
1448 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocationbar)ImplCycleCollectionTraverse(cb, tmp->mLocationbar, "mLocationbar"
, 0);
1449 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPersonalbar)ImplCycleCollectionTraverse(cb, tmp->mPersonalbar, "mPersonalbar"
, 0);
1450 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStatusbar)ImplCycleCollectionTraverse(cb, tmp->mStatusbar, "mStatusbar"
, 0);
1451 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mScrollbars)ImplCycleCollectionTraverse(cb, tmp->mScrollbars, "mScrollbars"
, 0);
1452 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCrypto)ImplCycleCollectionTraverse(cb, tmp->mCrypto, "mCrypto", 0
);
1453 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConsole)ImplCycleCollectionTraverse(cb, tmp->mConsole, "mConsole",
0);
1454 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPaintWorklet)ImplCycleCollectionTraverse(cb, tmp->mPaintWorklet, "mPaintWorklet"
, 0);
1455 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mExternal)ImplCycleCollectionTraverse(cb, tmp->mExternal, "mExternal"
, 0);
1456 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mInstallTrigger)ImplCycleCollectionTraverse(cb, tmp->mInstallTrigger, "mInstallTrigger"
, 0);
1457 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIntlUtils)ImplCycleCollectionTraverse(cb, tmp->mIntlUtils, "mIntlUtils"
, 0);
1458 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVisualViewport)ImplCycleCollectionTraverse(cb, tmp->mVisualViewport, "mVisualViewport"
, 0);
1459 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCurrentPasteDataTransfer)ImplCycleCollectionTraverse(cb, tmp->mCurrentPasteDataTransfer
, "mCurrentPasteDataTransfer", 0);
1460
1461 tmp->TraverseObjectsInGlobal(cb);
1462
1463 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeFields.mMessageManager)ImplCycleCollectionTraverse(cb, tmp->mChromeFields.mMessageManager
, "mChromeFields.mMessageManager", 0);
1464 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeFields.mGroupMessageManagers)ImplCycleCollectionTraverse(cb, tmp->mChromeFields.mGroupMessageManagers
, "mChromeFields.mGroupMessageManagers", 0);
1465
1466 for (size_t i = 0; i < tmp->mDocumentFlushedResolvers.Length(); i++) {
1467 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentFlushedResolvers[i]->mPromise)ImplCycleCollectionTraverse(cb, tmp->mDocumentFlushedResolvers
[i]->mPromise, "mDocumentFlushedResolvers[i]->mPromise"
, 0);
;
1468 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentFlushedResolvers[i]->mCallback)ImplCycleCollectionTraverse(cb, tmp->mDocumentFlushedResolvers
[i]->mCallback, "mDocumentFlushedResolvers[i]->mCallback"
, 0);
;
1469 }
1470
1471NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END(void)tmp; return NS_OK; }
1472
1473NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindowInner)void nsGlobalWindowInner::cycleCollection::Unlink(void* p) { nsGlobalWindowInner
* tmp = DowncastCCParticipant<nsGlobalWindowInner>(p);
1474 NS_IMPL_CYCLE_COLLECTION_UNLINK_WEAK_REFERENCEtmp->ClearWeakReferences();
1475 if (sInnerWindowsById) {
1476 sInnerWindowsById->Remove(tmp->mWindowID);
1477 }
1478
1479 JSObject* wrapper = tmp->GetWrapperPreserveColor();
1480 if (wrapper) {
1481 // Mark our realm as dead, so the JS engine won't hand out our
1482 // global after this point.
1483 JS::SetRealmNonLive(js::GetNonCCWObjectRealm(wrapper));
1484 }
1485
1486 NS_IMPL_CYCLE_COLLECTION_UNLINK(mNavigator)ImplCycleCollectionUnlink(tmp->mNavigator);
1487
1488 NS_IMPL_CYCLE_COLLECTION_UNLINK(mPerformance)ImplCycleCollectionUnlink(tmp->mPerformance);
1489
1490 if (tmp->mWebTaskScheduler) {
1491 tmp->mWebTaskScheduler->Disconnect();
1492 NS_IMPL_CYCLE_COLLECTION_UNLINK(mWebTaskScheduler)ImplCycleCollectionUnlink(tmp->mWebTaskScheduler);
1493 }
1494
1495 NS_IMPL_CYCLE_COLLECTION_UNLINK(mTrustedTypePolicyFactory)ImplCycleCollectionUnlink(tmp->mTrustedTypePolicyFactory);
1496
1497#ifdef MOZ_WEBSPEECH1
1498 NS_IMPL_CYCLE_COLLECTION_UNLINK(mSpeechSynthesis)ImplCycleCollectionUnlink(tmp->mSpeechSynthesis);
1499#endif
1500
1501 NS_IMPL_CYCLE_COLLECTION_UNLINK(mGlean)ImplCycleCollectionUnlink(tmp->mGlean);
1502 NS_IMPL_CYCLE_COLLECTION_UNLINK(mGleanPings)ImplCycleCollectionUnlink(tmp->mGleanPings);
1503
1504 if (tmp->mOuterWindow) {
1505 nsGlobalWindowOuter::Cast(tmp->mOuterWindow)->MaybeClearInnerWindow(tmp);
1506 NS_IMPL_CYCLE_COLLECTION_UNLINK(mOuterWindow)ImplCycleCollectionUnlink(tmp->mOuterWindow);
1507 }
1508
1509 if (tmp->mListenerManager) {
1510 tmp->mListenerManager->Disconnect();
1511 NS_IMPL_CYCLE_COLLECTION_UNLINK(mListenerManager)ImplCycleCollectionUnlink(tmp->mListenerManager);
1512 }
1513
1514 // Here the Timeouts list would've been unlinked, but we rely on
1515 // that Timeout objects have been traced and will remove themselves
1516 // while unlinking.
1517
1518 tmp->UpdateTopInnerWindow();
1519 NS_IMPL_CYCLE_COLLECTION_UNLINK(mTopInnerWindow)ImplCycleCollectionUnlink(tmp->mTopInnerWindow);
1520
1521 NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocation)ImplCycleCollectionUnlink(tmp->mLocation);
1522 NS_IMPL_CYCLE_COLLECTION_UNLINK(mHistory)ImplCycleCollectionUnlink(tmp->mHistory);
1523 NS_IMPL_CYCLE_COLLECTION_UNLINK(mNavigation)ImplCycleCollectionUnlink(tmp->mNavigation);
1524 NS_IMPL_CYCLE_COLLECTION_UNLINK(mCustomElements)ImplCycleCollectionUnlink(tmp->mCustomElements);
1525 NS_IMPL_CYCLE_COLLECTION_UNLINK(mSharedWorkers)ImplCycleCollectionUnlink(tmp->mSharedWorkers);
1526 if (tmp->mLocalStorage) {
1527 tmp->mLocalStorage->Disconnect();
1528 NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocalStorage)ImplCycleCollectionUnlink(tmp->mLocalStorage);
1529 }
1530 NS_IMPL_CYCLE_COLLECTION_UNLINK(mSessionStorage)ImplCycleCollectionUnlink(tmp->mSessionStorage);
1531 NS_IMPL_CYCLE_COLLECTION_UNLINK(mIndexedDB)ImplCycleCollectionUnlink(tmp->mIndexedDB);
1532 NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentPrincipal)ImplCycleCollectionUnlink(tmp->mDocumentPrincipal);
1533 NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentCookiePrincipal)ImplCycleCollectionUnlink(tmp->mDocumentCookiePrincipal);
1534 NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentStoragePrincipal)ImplCycleCollectionUnlink(tmp->mDocumentStoragePrincipal);
1535 NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentPartitionedPrincipal)ImplCycleCollectionUnlink(tmp->mDocumentPartitionedPrincipal
);
1536 NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentCsp)ImplCycleCollectionUnlink(tmp->mDocumentCsp);
1537 NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowserChild)ImplCycleCollectionUnlink(tmp->mBrowserChild);
1538 NS_IMPL_CYCLE_COLLECTION_UNLINK(mDoc)ImplCycleCollectionUnlink(tmp->mDoc);
1539
1540 NS_IMPL_CYCLE_COLLECTION_UNLINK(mGamepads)ImplCycleCollectionUnlink(tmp->mGamepads);
1541
1542 NS_IMPL_CYCLE_COLLECTION_UNLINK(mCacheStorage)ImplCycleCollectionUnlink(tmp->mCacheStorage);
1543 NS_IMPL_CYCLE_COLLECTION_UNLINK(mVRDisplays)ImplCycleCollectionUnlink(tmp->mVRDisplays);
1544
1545 NS_IMPL_CYCLE_COLLECTION_UNLINK(mDebuggerNotificationManager)ImplCycleCollectionUnlink(tmp->mDebuggerNotificationManager
);
1546
1547 // Unlink stuff from nsPIDOMWindow
1548 NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeEventHandler)ImplCycleCollectionUnlink(tmp->mChromeEventHandler);
1549 NS_IMPL_CYCLE_COLLECTION_UNLINK(mParentTarget)ImplCycleCollectionUnlink(tmp->mParentTarget);
1550 NS_IMPL_CYCLE_COLLECTION_UNLINK(mFocusedElement)ImplCycleCollectionUnlink(tmp->mFocusedElement);
1551 NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowsingContext)ImplCycleCollectionUnlink(tmp->mBrowsingContext);
1552
1553 MOZ_DIAGNOSTIC_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!tmp->mWindowGlobalChild || tmp->mWindowGlobalChild
->IsClosed())>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(!tmp->mWindowGlobalChild ||
tmp->mWindowGlobalChild->IsClosed()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!tmp->mWindowGlobalChild || tmp->mWindowGlobalChild->IsClosed()"
" (" "How are we unlinking a window before its actor has been destroyed?"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 1555); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!tmp->mWindowGlobalChild || tmp->mWindowGlobalChild->IsClosed()"
") (" "How are we unlinking a window before its actor has been destroyed?"
")"); do { *((volatile int*)__null) = 1555; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1554 !tmp->mWindowGlobalChild || tmp->mWindowGlobalChild->IsClosed(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!tmp->mWindowGlobalChild || tmp->mWindowGlobalChild
->IsClosed())>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(!tmp->mWindowGlobalChild ||
tmp->mWindowGlobalChild->IsClosed()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!tmp->mWindowGlobalChild || tmp->mWindowGlobalChild->IsClosed()"
" (" "How are we unlinking a window before its actor has been destroyed?"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 1555); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!tmp->mWindowGlobalChild || tmp->mWindowGlobalChild->IsClosed()"
") (" "How are we unlinking a window before its actor has been destroyed?"
")"); do { *((volatile int*)__null) = 1555; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1555 "How are we unlinking a window before its actor has been destroyed?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!tmp->mWindowGlobalChild || tmp->mWindowGlobalChild
->IsClosed())>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(!tmp->mWindowGlobalChild ||
tmp->mWindowGlobalChild->IsClosed()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!tmp->mWindowGlobalChild || tmp->mWindowGlobalChild->IsClosed()"
" (" "How are we unlinking a window before its actor has been destroyed?"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 1555); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!tmp->mWindowGlobalChild || tmp->mWindowGlobalChild->IsClosed()"
") (" "How are we unlinking a window before its actor has been destroyed?"
")"); do { *((volatile int*)__null) = 1555; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1556 NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindowGlobalChild)ImplCycleCollectionUnlink(tmp->mWindowGlobalChild);
1557
1558 NS_IMPL_CYCLE_COLLECTION_UNLINK(mMenubar)ImplCycleCollectionUnlink(tmp->mMenubar);
1559 NS_IMPL_CYCLE_COLLECTION_UNLINK(mToolbar)ImplCycleCollectionUnlink(tmp->mToolbar);
1560 NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocationbar)ImplCycleCollectionUnlink(tmp->mLocationbar);
1561 NS_IMPL_CYCLE_COLLECTION_UNLINK(mPersonalbar)ImplCycleCollectionUnlink(tmp->mPersonalbar);
1562 NS_IMPL_CYCLE_COLLECTION_UNLINK(mStatusbar)ImplCycleCollectionUnlink(tmp->mStatusbar);
1563 NS_IMPL_CYCLE_COLLECTION_UNLINK(mScrollbars)ImplCycleCollectionUnlink(tmp->mScrollbars);
1564 NS_IMPL_CYCLE_COLLECTION_UNLINK(mCrypto)ImplCycleCollectionUnlink(tmp->mCrypto);
1565 NS_IMPL_CYCLE_COLLECTION_UNLINK(mConsole)ImplCycleCollectionUnlink(tmp->mConsole);
1566 NS_IMPL_CYCLE_COLLECTION_UNLINK(mPaintWorklet)ImplCycleCollectionUnlink(tmp->mPaintWorklet);
1567 NS_IMPL_CYCLE_COLLECTION_UNLINK(mExternal)ImplCycleCollectionUnlink(tmp->mExternal);
1568 NS_IMPL_CYCLE_COLLECTION_UNLINK(mInstallTrigger)ImplCycleCollectionUnlink(tmp->mInstallTrigger);
1569 NS_IMPL_CYCLE_COLLECTION_UNLINK(mIntlUtils)ImplCycleCollectionUnlink(tmp->mIntlUtils);
1570 NS_IMPL_CYCLE_COLLECTION_UNLINK(mVisualViewport)ImplCycleCollectionUnlink(tmp->mVisualViewport);
1571 NS_IMPL_CYCLE_COLLECTION_UNLINK(mCurrentPasteDataTransfer)ImplCycleCollectionUnlink(tmp->mCurrentPasteDataTransfer);
1572
1573 tmp->UnlinkObjectsInGlobal();
1574
1575 NS_IMPL_CYCLE_COLLECTION_UNLINK(mIdleRequestExecutor)ImplCycleCollectionUnlink(tmp->mIdleRequestExecutor);
1576
1577 // Here the IdleRequest list would've been unlinked, but we rely on
1578 // that IdleRequest objects have been traced and will remove
1579 // themselves while unlinking.
1580
1581 NS_IMPL_CYCLE_COLLECTION_UNLINK(mClientSource)ImplCycleCollectionUnlink(tmp->mClientSource);
1582
1583 if (tmp->IsChromeWindow()) {
1584 if (tmp->mChromeFields.mMessageManager) {
1585 static_cast<nsFrameMessageManager*>(
1586 tmp->mChromeFields.mMessageManager.get())
1587 ->Disconnect();
1588 NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeFields.mMessageManager)ImplCycleCollectionUnlink(tmp->mChromeFields.mMessageManager
);
1589 }
1590 tmp->DisconnectAndClearGroupMessageManagers();
1591 NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeFields.mGroupMessageManagers)ImplCycleCollectionUnlink(tmp->mChromeFields.mGroupMessageManagers
);
1592 }
1593
1594 for (size_t i = 0; i < tmp->mDocumentFlushedResolvers.Length(); i++) {
1595 NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentFlushedResolvers[i]->mPromise)ImplCycleCollectionUnlink(tmp->mDocumentFlushedResolvers[i
]->mPromise);
;
1596 NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentFlushedResolvers[i]->mCallback)ImplCycleCollectionUnlink(tmp->mDocumentFlushedResolvers[i
]->mCallback);
;
1597 }
1598 tmp->mDocumentFlushedResolvers.Clear();
1599
1600 NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPERtmp->ReleaseWrapper(p);
1601NS_IMPL_CYCLE_COLLECTION_UNLINK_END(void)tmp; }
1602
1603#ifdef DEBUG1
1604void nsGlobalWindowInner::RiskyUnlink() {
1605 NS_CYCLE_COLLECTION_INNERNAME_cycleCollectorGlobal.Unlink(this);
1606}
1607#endif
1608
1609NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsGlobalWindowInner)void nsGlobalWindowInner::cycleCollection::Trace( void* p, const
TraceCallbacks& aCallbacks, void* aClosure) { nsGlobalWindowInner
* tmp = DowncastCCParticipant<nsGlobalWindowInner>(p);
1610 NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPERtmp->TraceWrapper(aCallbacks, aClosure);
1611NS_IMPL_CYCLE_COLLECTION_TRACE_END(void)tmp; }
1612
1613bool nsGlobalWindowInner::IsBlackForCC(bool aTracingNeeded) {
1614 if (!nsCCUncollectableMarker::sGeneration) {
1615 return false;
1616 }
1617
1618 return (nsCCUncollectableMarker::InGeneration(GetMarkedCCGeneration()) ||
1619 HasKnownLiveWrapper()) &&
1620 (!aTracingNeeded || HasNothingToTrace(ToSupports(this)));
1621}
1622
1623//*****************************************************************************
1624// nsGlobalWindowInner::nsIScriptGlobalObject
1625//*****************************************************************************
1626
1627bool nsGlobalWindowInner::ShouldResistFingerprinting(RFPTarget aTarget) const {
1628 if (mDoc) {
1629 return mDoc->ShouldResistFingerprinting(aTarget);
1630 }
1631 return nsContentUtils::ShouldResistFingerprinting(
1632 "If we do not have a document then we do not have any context"
1633 "to make an informed RFP choice, so we fall back to the global pref",
1634 aTarget);
1635}
1636
1637OriginTrials nsGlobalWindowInner::Trials() const {
1638 return OriginTrials::FromWindow(this);
1639}
1640
1641FontFaceSet* nsGlobalWindowInner::GetFonts() {
1642 if (mDoc) {
1643 return mDoc->Fonts();
1644 }
1645 return nullptr;
1646}
1647
1648mozilla::Result<mozilla::ipc::PrincipalInfo, nsresult>
1649nsGlobalWindowInner::GetStorageKey() {
1650 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/nsGlobalWindowInner.cpp"
, 1650); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 1650; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1651
1652 nsIPrincipal* principal = GetEffectiveStoragePrincipal();
1653 if (!principal) {
1654 return mozilla::Err(NS_ERROR_FAILURE);
1655 }
1656
1657 mozilla::ipc::PrincipalInfo principalInfo;
1658 nsresult rv = PrincipalToPrincipalInfo(principal, &principalInfo);
1659 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1660 return mozilla::Err(rv);
1661 }
1662
1663 // Block expanded and null principals, let content and system through.
1664 if (principalInfo.type() !=
1665 mozilla::ipc::PrincipalInfo::TContentPrincipalInfo &&
1666 principalInfo.type() !=
1667 mozilla::ipc::PrincipalInfo::TSystemPrincipalInfo) {
1668 return Err(NS_ERROR_DOM_SECURITY_ERR);
1669 }
1670
1671 return std::move(principalInfo);
1672}
1673
1674mozilla::dom::StorageManager* nsGlobalWindowInner::GetStorageManager() {
1675 return Navigator()->Storage();
1676}
1677
1678// https://html.spec.whatwg.org/multipage/web-messaging.html#eligible-for-messaging
1679// * a Window object whose associated Document is fully active
1680bool nsGlobalWindowInner::IsEligibleForMessaging() { return IsFullyActive(); }
1681
1682nsresult nsGlobalWindowInner::EnsureScriptEnvironment() {
1683 // NOTE: We can't use FORWARD_TO_OUTER here because we don't want to fail if
1684 // we're called on an inactive inner window.
1685 nsGlobalWindowOuter* outer = GetOuterWindowInternal();
1686 if (!outer) {
1687 NS_WARNING("No outer window available!")NS_DebugBreak(NS_DEBUG_WARNING, "No outer window available!",
nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 1687)
;
1688 return NS_ERROR_FAILURE;
1689 }
1690 return outer->EnsureScriptEnvironment();
1691}
1692
1693nsIScriptContext* nsGlobalWindowInner::GetScriptContext() {
1694 nsGlobalWindowOuter* outer = GetOuterWindowInternal();
1695 if (!outer) {
1696 return nullptr;
1697 }
1698 return outer->GetScriptContext();
1699}
1700
1701void nsGlobalWindowInner::TraceGlobalJSObject(JSTracer* aTrc) {
1702 TraceWrapper(aTrc, "active window global");
1703}
1704
1705void nsGlobalWindowInner::UpdateAutoplayPermission() {
1706 if (!GetWindowContext()) {
1707 return;
1708 }
1709 uint32_t perm =
1710 media::AutoplayPolicy::GetSiteAutoplayPermission(GetPrincipal());
1711 if (GetWindowContext()->GetAutoplayPermission() == perm) {
1712 return;
1713 }
1714
1715 // Setting autoplay permission on a discarded context has no effect.
1716 Unused << GetWindowContext()->SetAutoplayPermission(perm);
1717}
1718
1719void nsGlobalWindowInner::UpdateShortcutsPermission() {
1720 if (!GetWindowContext() ||
1721 !GetWindowContext()->GetBrowsingContext()->IsTop()) {
1722 // We only cache the shortcuts permission on top-level WindowContexts
1723 // since we always check the top-level principal for the permission.
1724 return;
1725 }
1726
1727 uint32_t perm = GetShortcutsPermission(GetPrincipal());
1728
1729 if (GetWindowContext()->GetShortcutsPermission() == perm) {
1730 return;
1731 }
1732
1733 // If the WindowContext is discarded this has no effect.
1734 Unused << GetWindowContext()->SetShortcutsPermission(perm);
1735}
1736
1737/* static */
1738uint32_t nsGlobalWindowInner::GetShortcutsPermission(nsIPrincipal* aPrincipal) {
1739 uint32_t perm = nsIPermissionManager::DENY_ACTION;
1740 nsCOMPtr<nsIPermissionManager> permMgr =
1741 mozilla::components::PermissionManager::Service();
1742 if (aPrincipal && permMgr) {
1743 permMgr->TestExactPermissionFromPrincipal(aPrincipal, "shortcuts"_ns,
1744 &perm);
1745 }
1746 return perm;
1747}
1748
1749void nsGlobalWindowInner::UpdatePopupPermission() {
1750 if (!GetWindowContext()) {
1751 return;
1752 }
1753
1754 uint32_t perm = PopupBlocker::GetPopupPermission(GetPrincipal());
1755 if (GetWindowContext()->GetPopupPermission() == perm) {
1756 return;
1757 }
1758
1759 // If the WindowContext is discarded this has no effect.
1760 Unused << GetWindowContext()->SetPopupPermission(perm);
1761}
1762
1763void nsGlobalWindowInner::UpdatePermissions() {
1764 if (!GetWindowContext()) {
1765 return;
1766 }
1767
1768 nsCOMPtr<nsIPrincipal> principal = GetPrincipal();
1769 RefPtr<WindowContext> windowContext = GetWindowContext();
1770
1771 WindowContext::Transaction txn;
1772 txn.SetAutoplayPermission(
1773 media::AutoplayPolicy::GetSiteAutoplayPermission(principal));
1774 txn.SetPopupPermission(PopupBlocker::GetPopupPermission(principal));
1775
1776 if (windowContext->IsTop()) {
1777 txn.SetShortcutsPermission(GetShortcutsPermission(principal));
1778 }
1779
1780 // Setting permissions on a discarded WindowContext has no effect
1781 Unused << txn.Commit(windowContext);
1782}
1783
1784void nsGlobalWindowInner::InitDocumentDependentState(JSContext* aCx) {
1785 MOZ_ASSERT(mDoc)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDoc)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(mDoc))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("mDoc", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 1785); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDoc" ")");
do { *((volatile int*)__null) = 1785; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1786
1787 if (MOZ_LOG_TEST(gDOMLeakPRLogInner, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gDOMLeakPRLogInner
, LogLevel::Debug)), 0))
) {
1788 nsIURI* uri = mDoc->GetDocumentURI();
1789 MOZ_LOG(gDOMLeakPRLogInner, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogInner
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "DOMWINDOW %p SetNewDocument %s", this, uri
? uri->GetSpecOrDefault().get() : ""); } } while (0)
1790 ("DOMWINDOW %p SetNewDocument %s", this,do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogInner
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "DOMWINDOW %p SetNewDocument %s", this, uri
? uri->GetSpecOrDefault().get() : ""); } } while (0)
1791 uri ? uri->GetSpecOrDefault().get() : ""))do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogInner
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "DOMWINDOW %p SetNewDocument %s", this, uri
? uri->GetSpecOrDefault().get() : ""); } } while (0)
;
1792 }
1793
1794 mFocusedElement = nullptr;
1795 mLocalStorage = nullptr;
1796 mSessionStorage = nullptr;
1797 mPerformance = nullptr;
1798 if (mWebTaskScheduler) {
1799 mWebTaskScheduler->Disconnect();
1800 mWebTaskScheduler = nullptr;
1801 }
1802
1803 // This must be called after nullifying the internal objects because here we
1804 // could recreate them, calling the getter methods, and store them into the JS
1805 // slots. If we nullify them after, the slot values and the objects will be
1806 // out of sync.
1807 ClearDocumentDependentSlots(aCx);
1808
1809 if (!mWindowGlobalChild) {
1810 mWindowGlobalChild = WindowGlobalChild::Create(this);
1811 }
1812 MOZ_ASSERT(!GetWindowContext()->HasBeenUserGestureActivated(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!GetWindowContext()->HasBeenUserGestureActivated(
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!GetWindowContext()->HasBeenUserGestureActivated(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!GetWindowContext()->HasBeenUserGestureActivated()" " ("
"WindowContext should always not have user gesture activation at "
"this point." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 1814); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!GetWindowContext()->HasBeenUserGestureActivated()"
") (" "WindowContext should always not have user gesture activation at "
"this point." ")"); do { *((volatile int*)__null) = 1814; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
1813 "WindowContext should always not have user gesture activation at "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!GetWindowContext()->HasBeenUserGestureActivated(
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!GetWindowContext()->HasBeenUserGestureActivated(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!GetWindowContext()->HasBeenUserGestureActivated()" " ("
"WindowContext should always not have user gesture activation at "
"this point." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 1814); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!GetWindowContext()->HasBeenUserGestureActivated()"
") (" "WindowContext should always not have user gesture activation at "
"this point." ")"); do { *((volatile int*)__null) = 1814; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
1814 "this point.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!GetWindowContext()->HasBeenUserGestureActivated(
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!GetWindowContext()->HasBeenUserGestureActivated(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!GetWindowContext()->HasBeenUserGestureActivated()" " ("
"WindowContext should always not have user gesture activation at "
"this point." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 1814); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!GetWindowContext()->HasBeenUserGestureActivated()"
") (" "WindowContext should always not have user gesture activation at "
"this point." ")"); do { *((volatile int*)__null) = 1814; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
1815
1816 UpdatePermissions();
1817
1818 RefPtr<PermissionDelegateHandler> permDelegateHandler =
1819 mDoc->GetPermissionDelegateHandler();
1820
1821 if (permDelegateHandler) {
1822 permDelegateHandler->PopulateAllDelegatedPermissions();
1823 }
1824
1825#if defined(MOZ_WIDGET_ANDROID)
1826 // When we insert the new document to the window in the top-level browsing
1827 // context, we should reset the status of the request which is used for the
1828 // previous document.
1829 if (mWindowGlobalChild && GetBrowsingContext() &&
1830 !GetBrowsingContext()->GetParent()) {
1831 // Return value of setting synced field should be checked. See bug 1656492.
1832 Unused << GetBrowsingContext()->ResetGVAutoplayRequestStatus();
1833 }
1834#endif
1835
1836#ifdef DEBUG1
1837 mLastOpenedURI = mDoc->GetDocumentURI();
1838#endif
1839
1840 Telemetry::Accumulate(Telemetry::INNERWINDOWS_WITH_MUTATION_LISTENERS,
1841 mMutationBits ? 1 : 0);
1842
1843 // Clear our mutation bitfield.
1844 mMutationBits = 0;
1845}
1846
1847nsresult nsGlobalWindowInner::EnsureClientSource() {
1848 MOZ_DIAGNOSTIC_ASSERT(mDoc)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDoc)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(mDoc))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("mDoc", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 1848); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mDoc"
")"); do { *((volatile int*)__null) = 1848; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1849
1850 bool newClientSource = false;
1851
1852 // Get the load info for the document if we performed a load. Be careful not
1853 // to look at local URLs, though. Local URLs are those that have a scheme of:
1854 // * about:
1855 // * data:
1856 // * blob:
1857 // We also do an additional check here so that we only treat about:blank
1858 // and about:srcdoc as local URLs. Other internal firefox about: URLs should
1859 // not be treated this way.
1860 nsCOMPtr<nsILoadInfo> loadInfo;
1861 nsCOMPtr<nsIChannel> channel = mDoc->GetChannel();
1862 if (channel) {
1863 nsCOMPtr<nsIURI> uri;
1864 Unused << channel->GetURI(getter_AddRefs(uri));
1865
1866 bool ignoreLoadInfo = false;
1867
1868 if (uri->SchemeIs("about")) {
1869 ignoreLoadInfo =
1870 NS_IsAboutBlankAllowQueryAndFragment(uri) || NS_IsAboutSrcdoc(uri);
1871 } else {
1872 // Its not an about: URL, so now check for our other URL types.
1873 ignoreLoadInfo = uri->SchemeIs("data") || uri->SchemeIs("blob");
1874 }
1875
1876 if (!ignoreLoadInfo) {
1877 loadInfo = channel->LoadInfo();
1878 }
1879 }
1880
1881 // Take the initial client source from the docshell immediately. Even if we
1882 // don't end up using it here we should consume it.
1883 UniquePtr<ClientSource> initialClientSource;
1884 nsIDocShell* docshell = GetDocShell();
1885 if (docshell) {
1886 initialClientSource = docshell->TakeInitialClientSource();
1887 }
1888
1889 // Try to get the reserved client from the LoadInfo. A Client is
1890 // reserved at the start of the channel load if there is not an
1891 // initial about:blank document that will be reused. It is also
1892 // created if the channel load encounters a cross-origin redirect.
1893 if (loadInfo) {
1894 UniquePtr<ClientSource> reservedClient =
1895 loadInfo->TakeReservedClientSource();
1896 if (reservedClient) {
1897 mClientSource.reset();
1898 mClientSource = std::move(reservedClient);
1899 newClientSource = true;
1900 }
1901 }
1902
1903 // We don't have a LoadInfo reserved client, but maybe we should
1904 // be inheriting an initial one from the docshell. This means
1905 // that the docshell started the channel load before creating the
1906 // initial about:blank document. This is an optimization, though,
1907 // and it created an initial Client as a placeholder for the document.
1908 // In this case we want to inherit this placeholder Client here.
1909 if (!mClientSource) {
1910 mClientSource = std::move(initialClientSource);
1911 if (mClientSource) {
1912 newClientSource = true;
1913 }
1914 }
1915
1916 nsCOMPtr<nsIPrincipal> foreignPartitionedPrincipal;
1917
1918 nsresult rv = StoragePrincipalHelper::GetPrincipal(
1919 this,
1920 StaticPrefs::privacy_partition_serviceWorkers()
1921 ? StoragePrincipalHelper::eForeignPartitionedPrincipal
1922 : StoragePrincipalHelper::eRegularPrincipal,
1923 getter_AddRefs(foreignPartitionedPrincipal));
1924 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/nsGlobalWindowInner.cpp"
, 1924); return rv; } } while (false)
;
1925
1926 // Verify the final ClientSource principal matches the final document
1927 // principal. The ClientChannelHelper handles things like network
1928 // redirects, but there are other ways the document principal can change.
1929 // For example, if something sets the nsIChannel.owner property, then
1930 // the final channel principal can be anything. Unfortunately there is
1931 // no good way to detect this until after the channel completes loading.
1932 //
1933 // For now we handle this just by reseting the ClientSource. This will
1934 // result in a new ClientSource with the correct principal being created.
1935 // To APIs like ServiceWorker and Clients API it will look like there was
1936 // an initial content page created that was then immediately replaced.
1937 // This is pretty close to what we are actually doing.
1938 if (mClientSource) {
1939 auto principalOrErr = mClientSource->Info().GetPrincipal();
1940 nsCOMPtr<nsIPrincipal> clientPrincipal =
1941 principalOrErr.isOk() ? principalOrErr.unwrap() : nullptr;
1942 if (!clientPrincipal ||
1943 !clientPrincipal->Equals(foreignPartitionedPrincipal)) {
1944 mClientSource.reset();
1945 }
1946 }
1947
1948 // If we don't have a reserved client or an initial client, then create
1949 // one now. This can happen in certain cases where we avoid preallocating
1950 // the client in the docshell. This mainly occurs in situations where
1951 // the principal is not clearly inherited from the parent; e.g. sandboxed
1952 // iframes, window.open(), etc.
1953 //
1954 // We also do this late ClientSource creation if the final document ended
1955 // up with a different principal.
1956 //
1957 // TODO: We may not be marking initial about:blank documents created
1958 // this way as controlled by a service worker properly. The
1959 // controller should be coming from the same place as the inheritted
1960 // principal. We do this in docshell, but as mentioned we aren't
1961 // smart enough to handle all cases yet. For example, a
1962 // window.open() with new URL should inherit the controller from
1963 // the opener, but we probably don't handle that yet.
1964 if (!mClientSource) {
1965 mClientSource = ClientManager::CreateSource(
1966 ClientType::Window, SerialEventTarget(), foreignPartitionedPrincipal);
1967 MOZ_DIAGNOSTIC_ASSERT(mClientSource)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mClientSource)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mClientSource))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("mClientSource",
"/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 1967); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mClientSource"
")"); do { *((volatile int*)__null) = 1967; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1968 newClientSource = true;
1969
1970 // Note, we don't apply the loadinfo controller below if we create
1971 // the ClientSource here.
1972 }
1973
1974 // The load may have started controlling the Client as well. If
1975 // so, mark it as controlled immediately here. The actor may
1976 // or may not have been notified by the parent side about being
1977 // controlled yet.
1978 //
1979 // Note: We should be careful not to control a client that was created late.
1980 // These clients were not seen by the ServiceWorkerManager when it
1981 // marked the LoadInfo controlled and it won't know about them. Its
1982 // also possible we are creating the client late due to the final
1983 // principal changing and these clients should definitely not be
1984 // controlled by a service worker with a different principal.
1985 else if (loadInfo) {
1986 const Maybe<ServiceWorkerDescriptor> controller = loadInfo->GetController();
1987 if (controller.isSome()) {
1988 mClientSource->SetController(controller.ref());
1989 }
1990
1991 // We also have to handle the case where te initial about:blank is
1992 // controlled due to inheritting the service worker from its parent,
1993 // but the actual nsIChannel load is not covered by any service worker.
1994 // In this case we want the final page to be uncontrolled. There is
1995 // an open spec issue about how exactly this should be handled, but for
1996 // now we just force creation of a new ClientSource to clear the
1997 // controller.
1998 //
1999 // https://github.com/w3c/ServiceWorker/issues/1232
2000 //
2001 else if (mClientSource->GetController().isSome()) {
2002 mClientSource.reset();
2003 mClientSource = ClientManager::CreateSource(
2004 ClientType::Window, SerialEventTarget(), foreignPartitionedPrincipal);
2005 MOZ_DIAGNOSTIC_ASSERT(mClientSource)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mClientSource)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mClientSource))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("mClientSource",
"/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 2005); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mClientSource"
")"); do { *((volatile int*)__null) = 2005; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2006 newClientSource = true;
2007 }
2008 }
2009
2010 if (mClientSource) {
2011 // Generally the CSP is stored within the Client and cached on the document.
2012 // At the time of CSP parsing however, the Client has not been created yet,
2013 // hence we store the CSP on the document and propagate/sync the CSP with
2014 // Client here when we create the Client.
2015 mClientSource->SetCsp(mDoc->GetCsp());
2016
2017 DocGroup* docGroup = GetDocGroup();
2018 MOZ_DIAGNOSTIC_ASSERT(docGroup)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(docGroup)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(docGroup))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("docGroup", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 2018); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "docGroup"
")"); do { *((volatile int*)__null) = 2018; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2019 mClientSource->SetAgentClusterId(docGroup->AgentClusterId());
2020
2021 if (mWindowGlobalChild) {
2022 mWindowGlobalChild->SendSetClientInfo(mClientSource->Info().ToIPC());
2023 }
2024 }
2025
2026 // Its possible that we got a client just after being frozen in
2027 // the bfcache. In that case freeze the client immediately.
2028 if (newClientSource && IsFrozen()) {
2029 mClientSource->Freeze();
2030 }
2031
2032 return NS_OK;
2033}
2034
2035nsresult nsGlobalWindowInner::ExecutionReady() {
2036 nsresult rv = EnsureClientSource();
2037 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/nsGlobalWindowInner.cpp"
, 2037); return rv; } } while (false)
;
2038
2039 rv = mClientSource->WindowExecutionReady(this);
2040 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/nsGlobalWindowInner.cpp"
, 2040); return rv; } } while (false)
;
2041
2042 return NS_OK;
2043}
2044
2045void nsGlobalWindowInner::UpdateParentTarget() {
2046 // NOTE: This method is identical to
2047 // nsGlobalWindowOuter::UpdateParentTarget(). IF YOU UPDATE THIS METHOD,
2048 // UPDATE THE OTHER ONE TOO!
2049
2050 // Try to get our frame element's tab child global (its in-process message
2051 // manager). If that fails, fall back to the chrome event handler's tab
2052 // child global, and if it doesn't have one, just use the chrome event
2053 // handler itself.
2054
2055 nsPIDOMWindowOuter* outer = GetOuterWindow();
2056 if (!outer) {
2057 return;
2058 }
2059 nsCOMPtr<Element> frameElement = outer->GetFrameElementInternal();
2060 nsCOMPtr<EventTarget> eventTarget =
2061 nsContentUtils::TryGetBrowserChildGlobal(frameElement);
2062
2063 if (!eventTarget) {
2064 nsGlobalWindowOuter* topWin = GetInProcessScriptableTopInternal();
2065 if (topWin) {
2066 frameElement = topWin->GetFrameElementInternal();
2067 eventTarget = nsContentUtils::TryGetBrowserChildGlobal(frameElement);
2068 }
2069 }
2070
2071 if (!eventTarget) {
2072 eventTarget = nsContentUtils::TryGetBrowserChildGlobal(mChromeEventHandler);
2073 }
2074
2075 if (!eventTarget) {
2076 eventTarget = mChromeEventHandler;
2077 }
2078
2079 mParentTarget = eventTarget;
2080}
2081
2082EventTarget* nsGlobalWindowInner::GetTargetForDOMEvent() {
2083 return GetOuterWindowInternal();
2084}
2085
2086void nsGlobalWindowInner::GetEventTargetParent(EventChainPreVisitor& aVisitor) {
2087 EventMessage msg = aVisitor.mEvent->mMessage;
2088
2089 aVisitor.mCanHandle = true;
2090 aVisitor.mForceContentDispatch = true; // FIXME! Bug 329119
2091 if (msg == eResize && aVisitor.mEvent->IsTrusted()) {
2092 // Checking whether the event target is an inner window or not, so we can
2093 // keep the old behavior also in case a child window is handling resize.
2094 if (aVisitor.mEvent->mOriginalTarget &&
2095 aVisitor.mEvent->mOriginalTarget->IsInnerWindow()) {
2096 mIsHandlingResizeEvent = true;
2097 }
2098 } else if (msg == eMouseDown && aVisitor.mEvent->IsTrusted()) {
2099 sMouseDown = true;
2100 } else if ((msg == eMouseUp || msg == eDragEnd) &&
2101 aVisitor.mEvent->IsTrusted()) {
2102 sMouseDown = false;
2103 if (sDragServiceDisabled) {
2104 nsCOMPtr<nsIDragService> ds =
2105 do_GetService("@mozilla.org/widget/dragservice;1");
2106 if (ds) {
2107 sDragServiceDisabled = false;
2108 ds->Unsuppress();
2109 }
2110 }
2111 }
2112
2113 aVisitor.SetParentTarget(GetParentTarget(), true);
2114}
2115
2116void nsGlobalWindowInner::FireFrameLoadEvent() {
2117 // If we're not in a content frame, or are at a BrowsingContext tree boundary,
2118 // such as the content-chrome boundary, don't fire the "load" event.
2119 if (GetBrowsingContext()->IsTopContent() ||
2120 GetBrowsingContext()->IsChrome()) {
2121 return;
2122 }
2123
2124 // If embedder is same-process, fire the event on our embedder element.
2125 //
2126 // XXX: Bug 1440212 is looking into potentially changing this behaviour to act
2127 // more like the remote case when in-process.
2128 RefPtr<Element> element = GetBrowsingContext()->GetEmbedderElement();
2129 if (element) {
2130 nsEventStatus status = nsEventStatus_eIgnore;
2131 WidgetEvent event(/* aIsTrusted = */ true, eLoad);
2132 event.mFlags.mBubbles = false;
2133 event.mFlags.mCancelable = false;
2134
2135 // Most of the time we could get a pres context to pass in here, but not
2136 // always (i.e. if this window is not shown there won't be a pres context
2137 // available). Since we're not firing a GUI event we don't need a pres
2138 // context anyway so we just pass null as the pres context all the time.
2139 EventDispatcher::Dispatch(element, nullptr, &event, nullptr, &status);
2140 return;
2141 }
2142
2143 // We don't have an in-process embedder. Try to get our `BrowserChild` actor
2144 // to send a message to that embedder. We want to double-check that our outer
2145 // window is actually the one at the root of this browserChild though, just in
2146 // case.
2147 RefPtr<BrowserChild> browserChild =
2148 BrowserChild::GetFrom(static_cast<nsPIDOMWindowInner*>(this));
2149 if (browserChild &&
2150 !GetBrowsingContext()->GetParentWindowContext()->IsInProcess()) {
2151 // Double-check that our outer window is actually at the root of this
2152 // `BrowserChild`, in case we're in an odd maybe-unhosted situation like a
2153 // print preview dialog.
2154 nsCOMPtr<nsPIDOMWindowOuter> rootOuter =
2155 do_GetInterface(browserChild->WebNavigation());
2156 if (!rootOuter || rootOuter != GetOuterWindow()) {
2157 return;
2158 }
2159
2160 mozilla::Unused << browserChild->SendMaybeFireEmbedderLoadEvents(
2161 EmbedderElementEventType::LoadEvent);
2162 }
2163}
2164
2165nsresult nsGlobalWindowInner::PostHandleEvent(EventChainPostVisitor& aVisitor) {
2166 // Return early if there is nothing to do.
2167 switch (aVisitor.mEvent->mMessage) {
2168 case eResize:
2169 case eUnload:
2170 case eLoad:
2171 break;
2172 default:
2173 return NS_OK;
2174 }
2175
2176 /* mChromeEventHandler and mContext go dangling in the middle of this
2177 function under some circumstances (events that destroy the window)
2178 without this addref. */
2179 RefPtr<EventTarget> kungFuDeathGrip1(mChromeEventHandler);
2180 mozilla::Unused
2181 << kungFuDeathGrip1; // These aren't referred to through the function
2182 nsCOMPtr<nsIScriptContext> kungFuDeathGrip2(GetContextInternal());
2183 mozilla::Unused
2184 << kungFuDeathGrip2; // These aren't referred to through the function
2185
2186 if (aVisitor.mEvent->mMessage == eResize) {
2187 mIsHandlingResizeEvent = false;
2188 } else if (aVisitor.mEvent->mMessage == eUnload &&
2189 aVisitor.mEvent->IsTrusted()) {
2190 // If any VR display presentation is active at unload, the next page
2191 // will receive a vrdisplayactive event to indicate that it should
2192 // immediately begin vr presentation. This should occur when navigating
2193 // forwards, navigating backwards, and on page reload.
2194 for (const auto& display : mVRDisplays) {
2195 if (display->IsPresenting()) {
2196 display->StartVRNavigation();
2197 // Save this VR display ID to trigger vrdisplayactivate event
2198 // after the next load event.
2199 nsGlobalWindowOuter* outer = GetOuterWindowInternal();
2200 if (outer) {
2201 outer->SetAutoActivateVRDisplayID(display->DisplayId());
2202 }
2203
2204 // XXX The WebVR 1.1 spec does not define which of multiple VR
2205 // presenting VR displays will be chosen during navigation.
2206 // As the underlying platform VR API's currently only allow a single
2207 // VR display, it is safe to choose the first VR display for now.
2208 break;
2209 }
2210 }
2211 mIsDocumentLoaded = false;
2212 // Tell the parent process that the document is not loaded.
2213 if (mWindowGlobalChild) {
2214 mWindowGlobalChild->SendUpdateDocumentHasLoaded(mIsDocumentLoaded);
2215 }
2216 } else if (aVisitor.mEvent->mMessage == eLoad &&
2217 aVisitor.mEvent->IsTrusted()) {
2218 // This is page load event since load events don't propagate to |window|.
2219 // @see Document::GetEventTargetParent.
2220 mIsDocumentLoaded = true;
2221 // Tell the parent process that the document is loaded.
2222 if (mWindowGlobalChild) {
2223 mWindowGlobalChild->SendUpdateDocumentHasLoaded(mIsDocumentLoaded);
2224 }
2225
2226 mTimeoutManager->OnDocumentLoaded();
2227
2228 MOZ_ASSERT(aVisitor.mEvent->IsTrusted())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aVisitor.mEvent->IsTrusted())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aVisitor.mEvent->IsTrusted
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aVisitor.mEvent->IsTrusted()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 2228); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aVisitor.mEvent->IsTrusted()"
")"); do { *((volatile int*)__null) = 2228; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2229 FireFrameLoadEvent();
2230
2231 if (mVREventObserver) {
2232 mVREventObserver->NotifyAfterLoad();
2233 }
2234
2235 uint32_t autoActivateVRDisplayID = 0;
2236 nsGlobalWindowOuter* outer = GetOuterWindowInternal();
2237 if (outer) {
2238 autoActivateVRDisplayID = outer->GetAutoActivateVRDisplayID();
2239 }
2240 if (autoActivateVRDisplayID) {
2241 DispatchVRDisplayActivate(autoActivateVRDisplayID,
2242 VRDisplayEventReason::Navigation);
2243 }
2244 }
2245
2246 return NS_OK;
2247}
2248
2249nsresult nsGlobalWindowInner::DefineArgumentsProperty(nsIArray* aArguments) {
2250 nsIScriptContext* ctx = GetOuterWindowInternal()->mContext;
2251 NS_ENSURE_TRUE(aArguments && ctx, NS_ERROR_NOT_INITIALIZED)do { if ((__builtin_expect(!!(!(aArguments && ctx)), 0
))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aArguments && ctx"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 2251); return NS_ERROR_NOT_INITIALIZED; } } while (false)
;
2252
2253 JS::Rooted<JSObject*> obj(RootingCx(), GetWrapperPreserveColor());
2254 return ctx->SetProperty(obj, "arguments", aArguments);
2255}
2256
2257//*****************************************************************************
2258// nsGlobalWindowInner::nsIScriptObjectPrincipal
2259//*****************************************************************************
2260
2261nsIPrincipal* nsGlobalWindowInner::GetPrincipal() {
2262 if (mDoc) {
2263 // If we have a document, get the principal from the document
2264 return mDoc->NodePrincipal();
2265 }
2266
2267 if (mDocumentPrincipal) {
2268 return mDocumentPrincipal;
2269 }
2270
2271 // If we don't have a principal and we don't have a document we
2272 // ask the parent window for the principal. This can happen when
2273 // loading a frameset that has a <frame src="javascript:xxx">, in
2274 // that case the global window is used in JS before we've loaded
2275 // a document into the window.
2276
2277 nsCOMPtr<nsIScriptObjectPrincipal> objPrincipal =
2278 do_QueryInterface(GetInProcessParentInternal());
2279
2280 if (objPrincipal) {
2281 return objPrincipal->GetPrincipal();
2282 }
2283
2284 return nullptr;
2285}
2286
2287nsIPrincipal* nsGlobalWindowInner::GetEffectiveCookiePrincipal() {
2288 if (mDoc) {
2289 // If we have a document, get the principal from the document
2290 return mDoc->EffectiveCookiePrincipal();
2291 }
2292
2293 if (mDocumentCookiePrincipal) {
2294 return mDocumentCookiePrincipal;
2295 }
2296
2297 // If we don't have a cookie principal and we don't have a document we ask
2298 // the parent window for the cookie principal.
2299
2300 nsCOMPtr<nsIScriptObjectPrincipal> objPrincipal =
2301 do_QueryInterface(GetInProcessParentInternal());
2302
2303 if (objPrincipal) {
2304 return objPrincipal->GetEffectiveCookiePrincipal();
2305 }
2306
2307 return nullptr;
2308}
2309
2310nsIPrincipal* nsGlobalWindowInner::GetEffectiveStoragePrincipal() {
2311 if (mDoc) {
2312 // If we have a document, get the principal from the document
2313 return mDoc->EffectiveStoragePrincipal();
2314 }
2315
2316 if (mDocumentStoragePrincipal) {
2317 return mDocumentStoragePrincipal;
2318 }
2319
2320 // If we don't have a cookie principal and we don't have a document we ask
2321 // the parent window for the cookie principal.
2322
2323 nsCOMPtr<nsIScriptObjectPrincipal> objPrincipal =
2324 do_QueryInterface(GetInProcessParentInternal());
2325
2326 if (objPrincipal) {
2327 return objPrincipal->GetEffectiveStoragePrincipal();
2328 }
2329
2330 return nullptr;
2331}
2332
2333nsIPrincipal* nsGlobalWindowInner::PartitionedPrincipal() {
2334 if (mDoc) {
2335 // If we have a document, get the principal from the document
2336 return mDoc->PartitionedPrincipal();
2337 }
2338
2339 if (mDocumentPartitionedPrincipal) {
2340 return mDocumentPartitionedPrincipal;
2341 }
2342
2343 // If we don't have a partitioned principal and we don't have a document we
2344 // ask the parent window for the partitioned principal.
2345
2346 nsCOMPtr<nsIScriptObjectPrincipal> objPrincipal =
2347 do_QueryInterface(GetInProcessParentInternal());
2348
2349 if (objPrincipal) {
2350 return objPrincipal->PartitionedPrincipal();
2351 }
2352
2353 return nullptr;
2354}
2355
2356//*****************************************************************************
2357// nsGlobalWindowInner::nsIDOMWindow
2358//*****************************************************************************
2359
2360bool nsPIDOMWindowInner::AddAudioContext(AudioContext* aAudioContext) {
2361 mAudioContexts.AppendElement(aAudioContext);
2362
2363 // Return true if the context should be muted and false if not.
2364 nsIDocShell* docShell = GetDocShell();
2365 return docShell && !docShell->GetAllowMedia() && !aAudioContext->IsOffline();
2366}
2367
2368void nsPIDOMWindowInner::RemoveAudioContext(AudioContext* aAudioContext) {
2369 mAudioContexts.RemoveElement(aAudioContext);
2370}
2371
2372void nsPIDOMWindowInner::MuteAudioContexts() {
2373 for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) {
2374 if (!mAudioContexts[i]->IsOffline()) {
2375 mAudioContexts[i]->Mute();
2376 }
2377 }
2378}
2379
2380void nsPIDOMWindowInner::UnmuteAudioContexts() {
2381 for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) {
2382 if (!mAudioContexts[i]->IsOffline()) {
2383 mAudioContexts[i]->Unmute();
2384 }
2385 }
2386}
2387
2388WindowProxyHolder nsGlobalWindowInner::Window() {
2389 return WindowProxyHolder(GetBrowsingContext());
2390}
2391
2392Navigator* nsPIDOMWindowInner::Navigator() {
2393 if (!mNavigator) {
2394 mNavigator = new mozilla::dom::Navigator(this);
2395 }
2396
2397 return mNavigator;
2398}
2399
2400MediaDevices* nsPIDOMWindowInner::GetExtantMediaDevices() const {
2401 return mNavigator ? mNavigator->GetExtantMediaDevices() : nullptr;
2402}
2403
2404VisualViewport* nsGlobalWindowInner::VisualViewport() {
2405 if (!mVisualViewport) {
2406 mVisualViewport = new mozilla::dom::VisualViewport(this);
2407 }
2408 return mVisualViewport;
2409}
2410
2411nsScreen* nsGlobalWindowInner::Screen() {
2412 if (!mScreen) {
2413 mScreen = new nsScreen(this);
2414 }
2415 return mScreen;
2416}
2417
2418nsHistory* nsGlobalWindowInner::GetHistory(ErrorResult& aError) {
2419 if (!mHistory) {
2420 mHistory = new nsHistory(this);
2421 }
2422 return mHistory;
2423}
2424
2425Navigation* nsGlobalWindowInner::Navigation() {
2426 if (!mNavigation && Navigation::IsAPIEnabled(nullptr, nullptr)) {
2427 mNavigation = new mozilla::dom::Navigation();
2428 }
2429
2430 return mNavigation;
2431}
2432
2433CustomElementRegistry* nsGlobalWindowInner::CustomElements() {
2434 if (!mCustomElements) {
2435 mCustomElements = new CustomElementRegistry(this);
2436 }
2437
2438 return mCustomElements;
2439}
2440
2441CustomElementRegistry* nsGlobalWindowInner::GetExistingCustomElements() {
2442 return mCustomElements;
2443}
2444
2445Performance* nsPIDOMWindowInner::GetPerformance() {
2446 CreatePerformanceObjectIfNeeded();
2447 return mPerformance;
2448}
2449
2450void nsPIDOMWindowInner::QueuePerformanceNavigationTiming() {
2451 CreatePerformanceObjectIfNeeded();
2452 if (mPerformance) {
2453 mPerformance->QueueNavigationTimingEntry();
2454 }
2455}
2456
2457void nsPIDOMWindowInner::CreatePerformanceObjectIfNeeded() {
2458 if (mPerformance || !mDoc) {
2459 return;
2460 }
2461 RefPtr<nsDOMNavigationTiming> timing = mDoc->GetNavigationTiming();
2462 nsCOMPtr<nsITimedChannel> timedChannel(do_QueryInterface(mDoc->GetChannel()));
2463 bool timingEnabled = false;
2464 if (!timedChannel ||
2465 !NS_SUCCEEDED(timedChannel->GetTimingEnabled(&timingEnabled))((bool)(__builtin_expect(!!(!NS_FAILED_impl(timedChannel->
GetTimingEnabled(&timingEnabled))), 1)))
||
2466 !timingEnabled) {
2467 timedChannel = nullptr;
2468 }
2469 if (timing) {
2470 mPerformance = Performance::CreateForMainThread(this, mDoc->NodePrincipal(),
2471 timing, timedChannel);
2472 }
2473}
2474
2475bool nsPIDOMWindowInner::IsSecureContext() const {
2476 return nsGlobalWindowInner::Cast(this)->IsSecureContext();
2477}
2478
2479void nsPIDOMWindowInner::Suspend(bool aIncludeSubWindows) {
2480 nsGlobalWindowInner::Cast(this)->Suspend(aIncludeSubWindows);
2481}
2482
2483void nsPIDOMWindowInner::Resume(bool aIncludeSubWindows) {
2484 nsGlobalWindowInner::Cast(this)->Resume(aIncludeSubWindows);
2485}
2486
2487void nsPIDOMWindowInner::SyncStateFromParentWindow() {
2488 nsGlobalWindowInner::Cast(this)->SyncStateFromParentWindow();
2489}
2490
2491Maybe<ClientInfo> nsPIDOMWindowInner::GetClientInfo() const {
2492 return nsGlobalWindowInner::Cast(this)->GetClientInfo();
2493}
2494
2495Maybe<ClientState> nsPIDOMWindowInner::GetClientState() const {
2496 return nsGlobalWindowInner::Cast(this)->GetClientState();
2497}
2498
2499Maybe<ServiceWorkerDescriptor> nsPIDOMWindowInner::GetController() const {
2500 return nsGlobalWindowInner::Cast(this)->GetController();
2501}
2502
2503void nsPIDOMWindowInner::SetCsp(nsIContentSecurityPolicy* aCsp) {
2504 return nsGlobalWindowInner::Cast(this)->SetCsp(aCsp);
2505}
2506
2507void nsPIDOMWindowInner::SetPreloadCsp(nsIContentSecurityPolicy* aPreloadCsp) {
2508 return nsGlobalWindowInner::Cast(this)->SetPreloadCsp(aPreloadCsp);
2509}
2510
2511nsIContentSecurityPolicy* nsPIDOMWindowInner::GetCsp() {
2512 return nsGlobalWindowInner::Cast(this)->GetCsp();
2513}
2514
2515void nsPIDOMWindowInner::NoteCalledRegisterForServiceWorkerScope(
2516 const nsACString& aScope) {
2517 nsGlobalWindowInner::Cast(this)->NoteCalledRegisterForServiceWorkerScope(
2518 aScope);
2519}
2520
2521void nsPIDOMWindowInner::NoteDOMContentLoaded() {
2522 nsGlobalWindowInner::Cast(this)->NoteDOMContentLoaded();
2523}
2524
2525bool nsGlobalWindowInner::ShouldReportForServiceWorkerScope(
2526 const nsAString& aScope) {
2527 bool result = false;
2528
2529 nsPIDOMWindowOuter* topOuter = GetInProcessScriptableTop();
2530 NS_ENSURE_TRUE(topOuter, false)do { if ((__builtin_expect(!!(!(topOuter)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "topOuter" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 2530); return false; } } while (false)
;
2531
2532 nsGlobalWindowInner* topInner =
2533 nsGlobalWindowInner::Cast(topOuter->GetCurrentInnerWindow());
2534 NS_ENSURE_TRUE(topInner, false)do { if ((__builtin_expect(!!(!(topInner)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "topInner" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 2534); return false; } } while (false)
;
2535
2536 topInner->ShouldReportForServiceWorkerScopeInternal(
2537 NS_ConvertUTF16toUTF8(aScope), &result);
2538 return result;
2539}
2540
2541InstallTriggerImpl* nsGlobalWindowInner::GetInstallTrigger() {
2542 if (!mInstallTrigger &&
2543 !StaticPrefs::extensions_InstallTriggerImpl_enabled()) {
2544 // Return nullptr when InstallTriggerImpl is disabled by pref,
2545 // which does not yet break the "typeof InstallTrigger !== 'undefined"
2546 // "UA detection" use case, but prevents access to the InstallTriggerImpl
2547 // methods and properties.
2548 //
2549 // NOTE: a separate pref ("extensions.InstallTrigger.enabled"), associated
2550 // to this property using the [Pref] extended attribute in Window.webidl,
2551 // does instead hide the entire InstallTrigger property.
2552 //
2553 // See Bug 1754441 for more details about this deprecation.
2554 return nullptr;
2555 }
2556 if (!mInstallTrigger) {
2557 ErrorResult rv;
2558 mInstallTrigger = ConstructJSImplementation<InstallTriggerImpl>(
2559 "@mozilla.org/addons/installtrigger;1", this, rv);
2560 if (rv.Failed()) {
2561 rv.SuppressException();
2562 return nullptr;
2563 }
2564 }
2565
2566 return mInstallTrigger;
2567}
2568
2569nsIDOMWindowUtils* nsGlobalWindowInner::GetWindowUtils(ErrorResult& aRv) {
2570 FORWARD_TO_OUTER_OR_THROW(WindowUtils, (), aRv, nullptr);
2571}
2572
2573CallState nsGlobalWindowInner::ShouldReportForServiceWorkerScopeInternal(
2574 const nsACString& aScope, bool* aResultOut) {
2575 MOZ_DIAGNOSTIC_ASSERT(aResultOut)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aResultOut)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aResultOut))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aResultOut", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 2575); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aResultOut"
")"); do { *((volatile int*)__null) = 2575; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2576
2577 // First check to see if this window is controlled. If so, then we have
2578 // found a match and are done.
2579 const Maybe<ServiceWorkerDescriptor> swd = GetController();
2580 if (swd.isSome() && swd.ref().Scope() == aScope) {
2581 *aResultOut = true;
2582 return CallState::Stop;
2583 }
2584
2585 // Next, check to see if this window has called
2586 // navigator.serviceWorker.register() for this scope. If so, then treat this
2587 // as a match so console reports appear in the devtools console.
2588 if (mClientSource &&
2589 mClientSource->CalledRegisterForServiceWorkerScope(aScope)) {
2590 *aResultOut = true;
2591 return CallState::Stop;
2592 }
2593
2594 // Finally check the current docshell nsILoadGroup to see if there are any
2595 // outstanding navigation requests. If so, match the scope against the
2596 // channel's URL. We want to show console reports during the FetchEvent
2597 // intercepting the navigation itself.
2598 nsCOMPtr<nsIDocumentLoader> loader(do_QueryInterface(GetDocShell()));
2599 if (loader) {
2600 nsCOMPtr<nsILoadGroup> loadgroup;
2601 Unused << loader->GetLoadGroup(getter_AddRefs(loadgroup));
2602 if (loadgroup) {
2603 nsCOMPtr<nsISimpleEnumerator> iter;
2604 Unused << loadgroup->GetRequests(getter_AddRefs(iter));
2605 if (iter) {
2606 nsCOMPtr<nsISupports> tmp;
2607 bool hasMore = true;
2608 // Check each network request in the load group.
2609 while (NS_SUCCEEDED(iter->HasMoreElements(&hasMore))((bool)(__builtin_expect(!!(!NS_FAILED_impl(iter->HasMoreElements
(&hasMore))), 1)))
&& hasMore) {
2610 iter->GetNext(getter_AddRefs(tmp));
2611 nsCOMPtr<nsIChannel> loadingChannel(do_QueryInterface(tmp));
2612 // Ignore subresource requests. Logging for a subresource
2613 // FetchEvent should be handled above since the client is
2614 // already controlled.
2615 if (!loadingChannel ||
2616 !nsContentUtils::IsNonSubresourceRequest(loadingChannel)) {
2617 continue;
2618 }
2619 nsCOMPtr<nsIURI> loadingURL;
2620 Unused << loadingChannel->GetURI(getter_AddRefs(loadingURL));
2621 if (!loadingURL) {
2622 continue;
2623 }
2624 nsAutoCString loadingSpec;
2625 Unused << loadingURL->GetSpec(loadingSpec);
2626 // Perform a simple substring comparison to match the scope
2627 // against the channel URL.
2628 if (StringBeginsWith(loadingSpec, aScope)) {
2629 *aResultOut = true;
2630 return CallState::Stop;
2631 }
2632 }
2633 }
2634 }
2635 }
2636
2637 // The current window doesn't care about this service worker, but maybe
2638 // one of our child frames does.
2639 return CallOnInProcessChildren(
2640 &nsGlobalWindowInner::ShouldReportForServiceWorkerScopeInternal, aScope,
2641 aResultOut);
2642}
2643
2644void nsGlobalWindowInner::NoteCalledRegisterForServiceWorkerScope(
2645 const nsACString& aScope) {
2646 if (!mClientSource) {
2647 return;
2648 }
2649
2650 mClientSource->NoteCalledRegisterForServiceWorkerScope(aScope);
2651}
2652
2653void nsGlobalWindowInner::NoteDOMContentLoaded() {
2654 if (!mClientSource) {
2655 return;
2656 }
2657
2658 mClientSource->NoteDOMContentLoaded();
2659}
2660
2661void nsGlobalWindowInner::UpdateTopInnerWindow() {
2662 if (IsTopInnerWindow() || !mTopInnerWindow) {
2663 return;
2664 }
2665
2666 mTopInnerWindow->UpdateWebSocketCount(-(int32_t)mNumOfOpenWebSockets);
2667}
2668
2669bool nsGlobalWindowInner::IsInSyncOperation() {
2670 return GetExtantDoc() && GetExtantDoc()->IsInSyncOperation();
2671}
2672
2673bool nsGlobalWindowInner::IsSharedMemoryAllowedInternal(
2674 nsIPrincipal* aPrincipal) const {
2675 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/nsGlobalWindowInner.cpp"
, 2675); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 2675; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2676
2677 if (StaticPrefs::
2678 dom_postMessage_sharedArrayBuffer_bypassCOOP_COEP_insecure_enabled()) {
2679 return true;
2680 }
2681
2682 if (ExtensionPolicyService::GetSingleton().IsExtensionProcess()) {
2683 if (auto* basePrincipal = BasePrincipal::Cast(aPrincipal)) {
2684 if (auto* policy = basePrincipal->AddonPolicy()) {
2685 return policy->IsPrivileged();
2686 }
2687 }
2688 }
2689
2690 return CrossOriginIsolated();
2691}
2692
2693bool nsGlobalWindowInner::CrossOriginIsolated() const {
2694 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/nsGlobalWindowInner.cpp"
, 2694); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 2694; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2695
2696 RefPtr<BrowsingContext> bc = GetBrowsingContext();
2697 MOZ_DIAGNOSTIC_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/nsGlobalWindowInner.cpp"
, 2697); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "bc"
")"); do { *((volatile int*)__null) = 2697; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2698 return bc->CrossOriginIsolated();
2699}
2700
2701WindowContext* TopWindowContext(nsPIDOMWindowInner& aWindow) {
2702 WindowContext* wc = aWindow.GetWindowContext();
2703 if (!wc) {
2704 return nullptr;
2705 }
2706
2707 return wc->TopWindowContext();
2708}
2709
2710void nsPIDOMWindowInner::AddPeerConnection() {
2711 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/nsGlobalWindowInner.cpp"
, 2711); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 2711; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2712 ++mActivePeerConnections;
2713 if (mActivePeerConnections == 1 && mWindowGlobalChild) {
2714 mWindowGlobalChild->SendUpdateActivePeerConnectionStatus(
2715 /*aIsAdded*/ true);
2716
2717 // We need to present having active peer connections immediately. If we need
2718 // to wait for the parent process to come back with this information we
2719 // might start throttling.
2720 if (WindowContext* top = TopWindowContext(*this)) {
2721 top->TransientSetHasActivePeerConnections();
2722 }
2723 }
2724}
2725
2726void nsPIDOMWindowInner::RemovePeerConnection() {
2727 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/nsGlobalWindowInner.cpp"
, 2727); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 2727; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2728 MOZ_ASSERT(mActivePeerConnections > 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mActivePeerConnections > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mActivePeerConnections > 0
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mActivePeerConnections > 0", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 2728); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mActivePeerConnections > 0"
")"); do { *((volatile int*)__null) = 2728; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2729 --mActivePeerConnections;
2730 if (mActivePeerConnections == 0 && mWindowGlobalChild) {
2731 mWindowGlobalChild->SendUpdateActivePeerConnectionStatus(
2732 /*aIsAdded*/ false);
2733 }
2734}
2735
2736bool nsPIDOMWindowInner::HasActivePeerConnections() {
2737 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/nsGlobalWindowInner.cpp"
, 2737); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 2737; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2738
2739 WindowContext* topWindowContext = TopWindowContext(*this);
2740 return topWindowContext && topWindowContext->GetHasActivePeerConnections();
2741}
2742
2743void nsPIDOMWindowInner::AddMediaKeysInstance(MediaKeys* aMediaKeys) {
2744 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/nsGlobalWindowInner.cpp"
, 2744); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 2744; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2745 mMediaKeysInstances.AppendElement(aMediaKeys);
2746 if (mWindowGlobalChild && mMediaKeysInstances.Length() == 1) {
2747 mWindowGlobalChild->BlockBFCacheFor(BFCacheStatus::CONTAINS_EME_CONTENT);
2748 }
2749}
2750
2751void nsPIDOMWindowInner::RemoveMediaKeysInstance(MediaKeys* aMediaKeys) {
2752 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/nsGlobalWindowInner.cpp"
, 2752); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 2752; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2753 mMediaKeysInstances.RemoveElement(aMediaKeys);
2754 if (mWindowGlobalChild && mMediaKeysInstances.IsEmpty()) {
2755 mWindowGlobalChild->UnblockBFCacheFor(BFCacheStatus::CONTAINS_EME_CONTENT);
2756 }
2757}
2758
2759bool nsPIDOMWindowInner::HasActiveMediaKeysInstance() {
2760 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/nsGlobalWindowInner.cpp"
, 2760); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 2760; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2761 return !mMediaKeysInstances.IsEmpty();
2762}
2763
2764bool nsPIDOMWindowInner::IsPlayingAudio() {
2765 for (uint32_t i = 0; i < mAudioContexts.Length(); i++) {
2766 if (mAudioContexts[i]->IsRunning()) {
2767 return true;
2768 }
2769 }
2770 RefPtr<AudioChannelService> acs = AudioChannelService::Get();
2771 if (!acs) {
2772 return false;
2773 }
2774 auto outer = GetOuterWindow();
2775 if (!outer) {
2776 // We've been unlinked and are about to die. Not a good time to pretend to
2777 // be playing audio.
2778 return false;
2779 }
2780 return acs->IsWindowActive(outer);
2781}
2782
2783bool nsPIDOMWindowInner::IsDocumentLoaded() const { return mIsDocumentLoaded; }
2784
2785mozilla::dom::TimeoutManager* nsGlobalWindowInner::GetTimeoutManager() {
2786 return mTimeoutManager.get();
2787}
2788
2789bool nsGlobalWindowInner::IsRunningTimeout() {
2790 return GetTimeoutManager()->IsRunningTimeout();
2791}
2792
2793void nsPIDOMWindowInner::TryToCacheTopInnerWindow() {
2794 if (mHasTriedToCacheTopInnerWindow) {
2795 return;
2796 }
2797
2798 nsGlobalWindowInner* window = nsGlobalWindowInner::Cast(this);
2799
2800 MOZ_ASSERT(!window->IsDying())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!window->IsDying())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!window->IsDying()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("!window->IsDying()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 2800); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!window->IsDying()"
")"); do { *((volatile int*)__null) = 2800; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2801
2802 mHasTriedToCacheTopInnerWindow = true;
2803
2804 MOZ_ASSERT(window)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(window)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(window))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("window", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 2804); AnnotateMozCrashReason("MOZ_ASSERT" "(" "window" ")"
); do { *((volatile int*)__null) = 2804; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2805
2806 if (nsCOMPtr<nsPIDOMWindowOuter> topOutter =
2807 window->GetInProcessScriptableTop()) {
2808 mTopInnerWindow = topOutter->GetCurrentInnerWindow();
2809 }
2810}
2811
2812void nsPIDOMWindowInner::UpdateActiveIndexedDBDatabaseCount(int32_t aDelta) {
2813 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/nsGlobalWindowInner.cpp"
, 2813); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 2813; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2814
2815 if (aDelta == 0) {
2816 return;
2817 }
2818
2819 // We count databases but not transactions because only active databases
2820 // could block throttling.
2821 uint32_t& counter = mTopInnerWindow
2822 ? mTopInnerWindow->mNumOfIndexedDBDatabases
2823 : mNumOfIndexedDBDatabases;
2824
2825 counter += aDelta;
2826}
2827
2828bool nsPIDOMWindowInner::HasActiveIndexedDBDatabases() {
2829 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/nsGlobalWindowInner.cpp"
, 2829); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 2829; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2830
2831 return mTopInnerWindow ? mTopInnerWindow->mNumOfIndexedDBDatabases > 0
2832 : mNumOfIndexedDBDatabases > 0;
2833}
2834
2835void nsPIDOMWindowInner::UpdateWebSocketCount(int32_t aDelta) {
2836 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/nsGlobalWindowInner.cpp"
, 2836); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 2836; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2837
2838 if (aDelta == 0) {
2839 return;
2840 }
2841
2842 if (mTopInnerWindow && !IsTopInnerWindow()) {
2843 mTopInnerWindow->UpdateWebSocketCount(aDelta);
2844 }
2845
2846 MOZ_DIAGNOSTIC_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDelta > 0 || ((aDelta + mNumOfOpenWebSockets) <
mNumOfOpenWebSockets))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDelta > 0 || ((aDelta + mNumOfOpenWebSockets
) < mNumOfOpenWebSockets)))), 0))) { do { } while (false);
MOZ_ReportAssertionFailure("aDelta > 0 || ((aDelta + mNumOfOpenWebSockets) < mNumOfOpenWebSockets)"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 2847); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aDelta > 0 || ((aDelta + mNumOfOpenWebSockets) < mNumOfOpenWebSockets)"
")"); do { *((volatile int*)__null) = 2847; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2847 aDelta > 0 || ((aDelta + mNumOfOpenWebSockets) < mNumOfOpenWebSockets))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDelta > 0 || ((aDelta + mNumOfOpenWebSockets) <
mNumOfOpenWebSockets))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDelta > 0 || ((aDelta + mNumOfOpenWebSockets
) < mNumOfOpenWebSockets)))), 0))) { do { } while (false);
MOZ_ReportAssertionFailure("aDelta > 0 || ((aDelta + mNumOfOpenWebSockets) < mNumOfOpenWebSockets)"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 2847); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aDelta > 0 || ((aDelta + mNumOfOpenWebSockets) < mNumOfOpenWebSockets)"
")"); do { *((volatile int*)__null) = 2847; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2848
2849 mNumOfOpenWebSockets += aDelta;
2850}
2851
2852bool nsPIDOMWindowInner::HasOpenWebSockets() const {
2853 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/nsGlobalWindowInner.cpp"
, 2853); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 2853; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2854
2855 return mNumOfOpenWebSockets ||
2856 (mTopInnerWindow && mTopInnerWindow->mNumOfOpenWebSockets);
2857}
2858
2859bool nsPIDOMWindowInner::IsCurrentInnerWindow() const {
2860 if (mozilla::SessionHistoryInParent() && mBrowsingContext &&
2861 mBrowsingContext->IsInBFCache()) {
2862 return false;
2863 }
2864
2865 if (!mBrowsingContext || mBrowsingContext->IsDiscarded()) {
2866 // If our BrowsingContext has been discarded, we consider ourselves
2867 // still-current if we were current at the time it was discarded.
2868 return mOuterWindow && WasCurrentInnerWindow();
2869 }
2870
2871 nsPIDOMWindowOuter* outer = mBrowsingContext->GetDOMWindow();
2872 return outer && outer->GetCurrentInnerWindow() == this;
2873}
2874
2875bool nsPIDOMWindowInner::IsFullyActive() const {
2876 WindowContext* wc = GetWindowContext();
2877 if (!wc || wc->IsDiscarded() || !wc->IsCurrent()) {
2878 return false;
2879 }
2880 return GetBrowsingContext()->AncestorsAreCurrent();
2881}
2882
2883void nsPIDOMWindowInner::SetAudioCapture(bool aCapture) {
2884 RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
2885 if (service) {
2886 service->SetWindowAudioCaptured(GetOuterWindow(), mWindowID, aCapture);
2887 }
2888}
2889
2890void nsGlobalWindowInner::SetActiveLoadingState(bool aIsLoading) {
2891 MOZ_LOG(do { const ::mozilla::LogModule* moz_real_module = gTimeoutLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "SetActiveLoadingState innerwindow %p: %d"
, (void*)this, aIsLoading); } } while (0)
2892 gTimeoutLog, mozilla::LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gTimeoutLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "SetActiveLoadingState innerwindow %p: %d"
, (void*)this, aIsLoading); } } while (0)
2893 ("SetActiveLoadingState innerwindow %p: %d", (void*)this, aIsLoading))do { const ::mozilla::LogModule* moz_real_module = gTimeoutLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "SetActiveLoadingState innerwindow %p: %d"
, (void*)this, aIsLoading); } } while (0)
;
2894 if (GetBrowsingContext()) {
2895 // Setting loading on a discarded context has no effect.
2896 Unused << GetBrowsingContext()->SetLoading(aIsLoading);
2897 }
2898
2899 if (!nsGlobalWindowInner::Cast(this)->IsChromeWindow()) {
2900 mTimeoutManager->SetLoading(aIsLoading);
2901 }
2902
2903 HintIsLoading(aIsLoading);
2904}
2905
2906void nsGlobalWindowInner::HintIsLoading(bool aIsLoading) {
2907 // Hint to tell the JS GC to use modified triggers during pageload.
2908 if (mHintedWasLoading != aIsLoading) {
2909 using namespace js::gc;
2910 SetPerformanceHint(danger::GetJSContext(), aIsLoading
2911 ? PerformanceHint::InPageLoad
2912 : PerformanceHint::Normal);
2913 mHintedWasLoading = aIsLoading;
2914 }
2915}
2916
2917// nsISpeechSynthesisGetter
2918
2919#ifdef MOZ_WEBSPEECH1
2920SpeechSynthesis* nsGlobalWindowInner::GetSpeechSynthesis(ErrorResult& aError) {
2921 if (!mSpeechSynthesis) {
2922 mSpeechSynthesis = new SpeechSynthesis(this);
2923 }
2924
2925 return mSpeechSynthesis;
2926}
2927
2928bool nsGlobalWindowInner::HasActiveSpeechSynthesis() {
2929 if (mSpeechSynthesis) {
2930 return !mSpeechSynthesis->HasEmptyQueue();
2931 }
2932
2933 return false;
2934}
2935
2936#endif
2937
2938mozilla::glean::Glean* nsGlobalWindowInner::Glean() {
2939 if (!mGlean) {
2940 mGlean = new mozilla::glean::Glean(this);
2941 }
2942
2943 return mGlean;
2944}
2945
2946mozilla::glean::GleanPings* nsGlobalWindowInner::GleanPings() {
2947 if (!mGleanPings) {
2948 mGleanPings = new mozilla::glean::GleanPings();
2949 }
2950
2951 return mGleanPings;
2952}
2953
2954Nullable<WindowProxyHolder> nsGlobalWindowInner::GetParent(
2955 ErrorResult& aError) {
2956 FORWARD_TO_OUTER_OR_THROW(GetParentOuter, (), aError, nullptr);
2957}
2958
2959/**
2960 * GetInProcessScriptableParent used to be called when a script read
2961 * window.parent. Under Fission, that is now handled by
2962 * BrowsingContext::GetParent, and the result is a WindowProxyHolder rather than
2963 * an actual global window. This method still exists for legacy callers which
2964 * relied on the old logic, and require in-process windows. However, it only
2965 * works correctly when no out-of-process frames exist between this window and
2966 * the top-level window, so it should not be used in new code.
2967 *
2968 * In contrast to GetRealParent, GetInProcessScriptableParent respects <iframe
2969 * mozbrowser> boundaries, so if |this| is contained by an <iframe
2970 * mozbrowser>, we will return |this| as its own parent.
2971 */
2972nsPIDOMWindowOuter* nsGlobalWindowInner::GetInProcessScriptableParent() {
2973 FORWARD_TO_OUTER(GetInProcessScriptableParent, (), nullptr);
2974}
2975
2976/**
2977 * GetInProcessScriptableTop used to be called when a script read window.top.
2978 * Under Fission, that is now handled by BrowsingContext::Top, and the result is
2979 * a WindowProxyHolder rather than an actual global window. This method still
2980 * exists for legacy callers which relied on the old logic, and require
2981 * in-process windows. However, it only works correctly when no out-of-process
2982 * frames exist between this window and the top-level window, so it should not
2983 * be used in new code.
2984 *
2985 * In contrast to GetRealTop, GetInProcessScriptableTop respects <iframe
2986 * mozbrowser> boundaries. If we encounter a window owned by an <iframe
2987 * mozbrowser> while walking up the window hierarchy, we'll stop and return that
2988 * window.
2989 */
2990nsPIDOMWindowOuter* nsGlobalWindowInner::GetInProcessScriptableTop() {
2991 FORWARD_TO_OUTER(GetInProcessScriptableTop, (), nullptr);
2992}
2993
2994void nsGlobalWindowInner::GetContent(JSContext* aCx,
2995 JS::MutableHandle<JSObject*> aRetval,
2996 CallerType aCallerType,
2997 ErrorResult& aError) {
2998 FORWARD_TO_OUTER_OR_THROW(GetContentOuter,
2999 (aCx, aRetval, aCallerType, aError), aError, );
3000}
3001
3002BarProp* nsGlobalWindowInner::GetMenubar(ErrorResult& aError) {
3003 if (!mMenubar) {
3004 mMenubar = new MenubarProp(this);
3005 }
3006
3007 return mMenubar;
3008}
3009
3010BarProp* nsGlobalWindowInner::GetToolbar(ErrorResult& aError) {
3011 if (!mToolbar) {
3012 mToolbar = new ToolbarProp(this);
3013 }
3014
3015 return mToolbar;
3016}
3017
3018BarProp* nsGlobalWindowInner::GetLocationbar(ErrorResult& aError) {
3019 if (!mLocationbar) {
3020 mLocationbar = new LocationbarProp(this);
3021 }
3022 return mLocationbar;
3023}
3024
3025BarProp* nsGlobalWindowInner::GetPersonalbar(ErrorResult& aError) {
3026 if (!mPersonalbar) {
3027 mPersonalbar = new PersonalbarProp(this);
3028 }
3029 return mPersonalbar;
3030}
3031
3032BarProp* nsGlobalWindowInner::GetStatusbar(ErrorResult& aError) {
3033 if (!mStatusbar) {
3034 mStatusbar = new StatusbarProp(this);
3035 }
3036 return mStatusbar;
3037}
3038
3039BarProp* nsGlobalWindowInner::GetScrollbars(ErrorResult& aError) {
3040 if (!mScrollbars) {
3041 mScrollbars = new ScrollbarsProp(this);
3042 }
3043
3044 return mScrollbars;
3045}
3046
3047bool nsGlobalWindowInner::GetClosed(ErrorResult& aError) {
3048 // If we're called from JS (which is the only way we should be getting called
3049 // here) and we reach this point, that means our JS global is the current
3050 // target of the WindowProxy, which means that we are the "current inner"
3051 // of our outer. So if FORWARD_TO_OUTER fails to forward, that means the
3052 // outer is already torn down, which corresponds to the closed state.
3053 FORWARD_TO_OUTER(GetClosedOuter, (), true);
3054}
3055
3056Nullable<WindowProxyHolder> nsGlobalWindowInner::IndexedGetter(
3057 uint32_t aIndex) {
3058 FORWARD_TO_OUTER(IndexedGetterOuter, (aIndex), nullptr);
3059}
3060
3061namespace {
3062
3063struct InterfaceShimEntry {
3064 const char* geckoName;
3065 const char* domName;
3066};
3067
3068} // anonymous namespace
3069
3070// We add shims from Components.interfaces.nsIDOMFoo to window.Foo for each
3071// interface that has interface constants that sites might be getting off
3072// of Ci.
3073const InterfaceShimEntry kInterfaceShimMap[] = {
3074 {"nsIXMLHttpRequest", "XMLHttpRequest"},
3075 {"nsIDOMDOMException", "DOMException"},
3076 {"nsIDOMNode", "Node"},
3077 {"nsIDOMCSSRule", "CSSRule"},
3078 {"nsIDOMEvent", "Event"},
3079 {"nsIDOMNSEvent", "Event"},
3080 {"nsIDOMKeyEvent", "KeyEvent"},
3081 {"nsIDOMMouseEvent", "MouseEvent"},
3082 {"nsIDOMMouseScrollEvent", "MouseScrollEvent"},
3083 {"nsIDOMMutationEvent", "MutationEvent"},
3084 {"nsIDOMUIEvent", "UIEvent"},
3085 {"nsIDOMHTMLMediaElement", "HTMLMediaElement"},
3086 {"nsIDOMRange", "Range"},
3087 // Think about whether Ci.nsINodeFilter can just go away for websites!
3088 {"nsIDOMNodeFilter", "NodeFilter"},
3089 {"nsIDOMXPathResult", "XPathResult"}};
3090
3091bool nsGlobalWindowInner::ResolveComponentsShim(
3092 JSContext* aCx, JS::Handle<JSObject*> aGlobal,
3093 JS::MutableHandle<mozilla::Maybe<JS::PropertyDescriptor>> aDesc) {
3094 // Keep track of how often this happens.
3095 Telemetry::Accumulate(Telemetry::COMPONENTS_SHIM_ACCESSED_BY_CONTENT, true);
3096
3097 // Warn once.
3098 nsCOMPtr<Document> doc = GetExtantDoc();
3099 if (doc) {
3100 doc->WarnOnceAbout(DeprecatedOperations::eComponents, /* asError = */ true);
3101 }
3102
3103 // Create a fake Components object.
3104 AssertSameCompartment(aCx, aGlobal);
3105 JS::Rooted<JSObject*> components(aCx, JS_NewPlainObject(aCx));
3106 if (NS_WARN_IF(!components)NS_warn_if_impl(!components, "!components", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 3106)
) {
3107 return false;
3108 }
3109
3110 // Create a fake interfaces object.
3111 JS::Rooted<JSObject*> interfaces(aCx, JS_NewPlainObject(aCx));
3112 if (NS_WARN_IF(!interfaces)NS_warn_if_impl(!interfaces, "!interfaces", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 3112)
) {
3113 return false;
3114 }
3115 bool ok =
3116 JS_DefineProperty(aCx, components, "interfaces", interfaces,
3117 JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY);
3118 if (NS_WARN_IF(!ok)NS_warn_if_impl(!ok, "!ok", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 3118)
) {
3119 return false;
3120 }
3121
3122 // Define a bunch of shims from the Ci.nsIDOMFoo to window.Foo for DOM
3123 // interfaces with constants.
3124 for (uint32_t i = 0; i < ArrayLength(kInterfaceShimMap); ++i) {
3125 // Grab the names from the table.
3126 const char* geckoName = kInterfaceShimMap[i].geckoName;
3127 const char* domName = kInterfaceShimMap[i].domName;
3128
3129 // Look up the appopriate interface object on the global.
3130 JS::Rooted<JS::Value> v(aCx, JS::UndefinedValue());
3131 ok = JS_GetProperty(aCx, aGlobal, domName, &v);
3132 if (NS_WARN_IF(!ok)NS_warn_if_impl(!ok, "!ok", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 3132)
) {
3133 return false;
3134 }
3135 if (!v.isObject()) {
3136 NS_WARNING("Unable to find interface object on global")NS_DebugBreak(NS_DEBUG_WARNING, "Unable to find interface object on global"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 3136)
;
3137 continue;
3138 }
3139
3140 // Define the shim on the interfaces object.
3141 ok = JS_DefineProperty(
3142 aCx, interfaces, geckoName, v,
3143 JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY);
3144 if (NS_WARN_IF(!ok)NS_warn_if_impl(!ok, "!ok", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 3144)
) {
3145 return false;
3146 }
3147 }
3148
3149 aDesc.set(mozilla::Some(JS::PropertyDescriptor::Data(
3150 JS::ObjectValue(*components),
3151 {JS::PropertyAttribute::Configurable, JS::PropertyAttribute::Enumerable,
3152 JS::PropertyAttribute::Writable})));
3153 return true;
3154}
3155
3156#ifdef RELEASE_OR_BETA
3157# define USE_CONTROLLERS_SHIM
3158#endif
3159
3160#ifdef USE_CONTROLLERS_SHIM
3161static const JSClass ControllersShimClass = {"Controllers", 0};
3162static const JSClass XULControllersShimClass = {"XULControllers", 0};
3163#endif
3164
3165bool nsGlobalWindowInner::DoResolve(
3166 JSContext* aCx, JS::Handle<JSObject*> aObj, JS::Handle<jsid> aId,
3167 JS::MutableHandle<mozilla::Maybe<JS::PropertyDescriptor>> aDesc) {
3168 // Note: Keep this in sync with MayResolve.
3169
3170 // Note: The infallibleInit call in GlobalResolve depends on this check.
3171 if (!aId.isString()) {
3172 return true;
3173 }
3174
3175 bool found;
3176 if (!WebIDLGlobalNameHash::DefineIfEnabled(aCx, aObj, aId, aDesc, &found)) {
3177 return false;
3178 }
3179
3180 if (found) {
3181 return true;
3182 }
3183
3184 // We support a cut-down Components.interfaces in case websites are
3185 // using Components.interfaces.nsIFoo.CONSTANT_NAME for the ones
3186 // that have constants.
3187 if (StaticPrefs::dom_use_components_shim() &&
3188 aId == XPCJSRuntime::Get()->GetStringID(XPCJSContext::IDX_COMPONENTS)) {
3189 return ResolveComponentsShim(aCx, aObj, aDesc);
3190 }
3191
3192 // We also support a "window.controllers" thing; apparently some
3193 // sites use it for browser-sniffing. See bug 1010577.
3194#ifdef USE_CONTROLLERS_SHIM
3195 // Note: We use |aObj| rather than |this| to get the principal here, because
3196 // this is called during Window setup when the Document isn't necessarily
3197 // hooked up yet.
3198 if ((aId == XPCJSRuntime::Get()->GetStringID(XPCJSContext::IDX_CONTROLLERS) ||
3199 aId == XPCJSRuntime::Get()->GetStringID(
3200 XPCJSContext::IDX_CONTROLLERS_CLASS)) &&
3201 !xpc::IsXrayWrapper(aObj) &&
3202 !nsContentUtils::ObjectPrincipal(aObj)->IsSystemPrincipal()) {
3203 if (GetExtantDoc()) {
3204 GetExtantDoc()->WarnOnceAbout(
3205 DeprecatedOperations::eWindow_Cc_ontrollers);
3206 }
3207 const JSClass* clazz;
3208 if (aId ==
3209 XPCJSRuntime::Get()->GetStringID(XPCJSContext::IDX_CONTROLLERS)) {
3210 clazz = &XULControllersShimClass;
3211 } else {
3212 clazz = &ControllersShimClass;
3213 }
3214 MOZ_ASSERT(JS_IsGlobalObject(aObj))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(JS_IsGlobalObject(aObj))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(JS_IsGlobalObject(aObj)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("JS_IsGlobalObject(aObj)"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 3214); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JS_IsGlobalObject(aObj)"
")"); do { *((volatile int*)__null) = 3214; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3215 JS::Rooted<JSObject*> shim(aCx, JS_NewObject(aCx, clazz));
3216 if (NS_WARN_IF(!shim)NS_warn_if_impl(!shim, "!shim", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 3216)
) {
3217 return false;
3218 }
3219
3220 aDesc.set(mozilla::Some(JS::PropertyDescriptor::Data(
3221 JS::ObjectValue(*shim),
3222 {JS::PropertyAttribute::Configurable, JS::PropertyAttribute::Enumerable,
3223 JS::PropertyAttribute::Writable})));
3224 return true;
3225 }
3226#endif
3227
3228 return true;
3229}
3230
3231/* static */
3232bool nsGlobalWindowInner::MayResolve(jsid aId) {
3233 // Note: This function does not fail and may not have any side-effects.
3234 // Note: Keep this in sync with DoResolve.
3235 if (!aId.isString()) {
3236 return false;
3237 }
3238
3239 if (aId == XPCJSRuntime::Get()->GetStringID(XPCJSContext::IDX_COMPONENTS)) {
3240 return true;
3241 }
3242
3243 if (aId == XPCJSRuntime::Get()->GetStringID(XPCJSContext::IDX_CONTROLLERS) ||
3244 aId == XPCJSRuntime::Get()->GetStringID(
3245 XPCJSContext::IDX_CONTROLLERS_CLASS)) {
3246 // We only resolve .controllers/.Controllers in release builds and on
3247 // non-chrome windows, but let's not worry about any of that stuff.
3248 return true;
3249 }
3250
3251 return WebIDLGlobalNameHash::MayResolve(aId);
3252}
3253
3254void nsGlobalWindowInner::GetOwnPropertyNames(
3255 JSContext* aCx, JS::MutableHandleVector<jsid> aNames, bool aEnumerableOnly,
3256 ErrorResult& aRv) {
3257 if (aEnumerableOnly) {
3258 // The names we would return from here get defined on the window via one of
3259 // two codepaths. The ones coming from the WebIDLGlobalNameHash will end up
3260 // in the DefineConstructor function in BindingUtils, which always defines
3261 // things as non-enumerable. The ones coming from the script namespace
3262 // manager get defined by our resolve hook using FillPropertyDescriptor with
3263 // 0 for the property attributes, so non-enumerable as well.
3264 //
3265 // So in the aEnumerableOnly case we have nothing to do.
3266 return;
3267 }
3268
3269 // "Components" is marked as enumerable but only resolved on demand :-/.
3270 // aNames.AppendElement(u"Components"_ns);
3271
3272 JS::Rooted<JSObject*> wrapper(aCx, GetWrapper());
3273
3274 // There are actually two ways we can get called here: For normal
3275 // enumeration or for Xray enumeration. In the latter case, we want to
3276 // return all possible WebIDL names, because we don't really support
3277 // deleting these names off our Xray; trying to resolve them will just make
3278 // them come back. In the former case, we want to avoid returning deleted
3279 // names. But the JS engine already knows about the non-deleted
3280 // already-resolved names, so we can just return the so-far-unresolved ones.
3281 //
3282 // We can tell which case we're in by whether aCx is in our wrapper's
3283 // compartment. If not, we're in the Xray case.
3284 WebIDLGlobalNameHash::NameType nameType =
3285 js::IsObjectInContextCompartment(wrapper, aCx)
3286 ? WebIDLGlobalNameHash::UnresolvedNamesOnly
3287 : WebIDLGlobalNameHash::AllNames;
3288 if (!WebIDLGlobalNameHash::GetNames(aCx, wrapper, nameType, aNames)) {
3289 aRv.NoteJSContextException(aCx);
3290 }
3291}
3292
3293/* static */
3294bool nsGlobalWindowInner::IsPrivilegedChromeWindow(JSContext*, JSObject* aObj) {
3295 // For now, have to deal with XPConnect objects here.
3296 nsGlobalWindowInner* win = xpc::WindowOrNull(aObj);
3297 return win && win->IsChromeWindow() &&
3298 nsContentUtils::ObjectPrincipal(aObj) ==
3299 nsContentUtils::GetSystemPrincipal();
3300}
3301
3302/* static */
3303bool nsGlobalWindowInner::DeviceSensorsEnabled(JSContext*, JSObject*) {
3304 return Preferences::GetBool("device.sensors.enabled");
3305}
3306
3307/* static */
3308bool nsGlobalWindowInner::CachesEnabled(JSContext* aCx, JSObject* aObj) {
3309 if (!IsSecureContextOrObjectIsFromSecureContext(aCx, aObj)) {
3310 return StaticPrefs::dom_caches_testing_enabled() ||
3311 StaticPrefs::dom_serviceWorkers_testing_enabled();
3312 }
3313 return true;
3314}
3315
3316/* static */
3317bool nsGlobalWindowInner::IsSizeToContentEnabled(JSContext* aCx, JSObject*) {
3318 return StaticPrefs::dom_window_sizeToContent_enabled() ||
3319 nsContentUtils::IsSystemCaller(aCx);
3320}
3321
3322/* static */
3323bool nsGlobalWindowInner::IsGleanNeeded(JSContext* aCx, JSObject* aObj) {
3324 // Glean is needed in ChromeOnly contexts and also in privileged about pages.
3325 nsIPrincipal* principal = nsContentUtils::SubjectPrincipal(aCx);
3326 if (principal->IsSystemPrincipal()) {
3327 return true;
3328 }
3329
3330 uint32_t flags = 0;
3331 if (NS_FAILED(principal->GetAboutModuleFlags(&flags))((bool)(__builtin_expect(!!(NS_FAILED_impl(principal->GetAboutModuleFlags
(&flags))), 0)))
) {
3332 return false;
3333 }
3334 return flags & nsIAboutModule::IS_SECURE_CHROME_UI;
3335}
3336
3337Crypto* nsGlobalWindowInner::GetCrypto(ErrorResult& aError) {
3338 if (!mCrypto) {
3339 mCrypto = new Crypto(this);
3340 }
3341 return mCrypto;
3342}
3343
3344nsIControllers* nsGlobalWindowInner::GetControllers(ErrorResult& aError) {
3345 FORWARD_TO_OUTER_OR_THROW(GetControllersOuter, (aError), aError, nullptr);
3346}
3347
3348nsresult nsGlobalWindowInner::GetControllers(nsIControllers** aResult) {
3349 ErrorResult rv;
3350 nsCOMPtr<nsIControllers> controllers = GetControllers(rv);
3351 controllers.forget(aResult);
3352
3353 return rv.StealNSResult();
3354}
3355
3356Nullable<WindowProxyHolder> nsGlobalWindowInner::GetOpenerWindow(
3357 ErrorResult& aError) {
3358 FORWARD_TO_OUTER_OR_THROW(GetOpenerWindowOuter, (), aError, nullptr);
3359}
3360
3361void nsGlobalWindowInner::GetOpener(JSContext* aCx,
3362 JS::MutableHandle<JS::Value> aRetval,
3363 ErrorResult& aError) {
3364 Nullable<WindowProxyHolder> opener = GetOpenerWindow(aError);
3365 if (aError.Failed() || opener.IsNull()) {
3366 aRetval.setNull();
3367 return;
3368 }
3369
3370 if (!ToJSValue(aCx, opener.Value(), aRetval)) {
3371 aError.NoteJSContextException(aCx);
3372 }
3373}
3374
3375void nsGlobalWindowInner::SetOpener(JSContext* aCx,
3376 JS::Handle<JS::Value> aOpener,
3377 ErrorResult& aError) {
3378 if (aOpener.isNull()) {
3379 RefPtr<BrowsingContext> bc(GetBrowsingContext());
3380 if (!bc->IsDiscarded()) {
3381 bc->SetOpener(nullptr);
3382 }
3383 return;
3384 }
3385
3386 // If something other than null is passed, just define aOpener on our inner
3387 // window's JS object, wrapped into the current compartment so that for Xrays
3388 // we define on the Xray expando object, but don't set it on the outer window,
3389 // so that it'll get reset on navigation. This is just like replaceable
3390 // properties, but we're not quite readonly.
3391 RedefineProperty(aCx, "opener", aOpener, aError);
3392}
3393
3394void nsGlobalWindowInner::GetEvent(OwningEventOrUndefined& aRetval) {
3395 if (mEvent) {
3396 aRetval.SetAsEvent() = mEvent;
3397 } else {
3398 aRetval.SetUndefined();
3399 }
3400}
3401
3402void nsGlobalWindowInner::GetStatus(nsAString& aStatus, ErrorResult& aError) {
3403 FORWARD_TO_OUTER_OR_THROW(GetStatusOuter, (aStatus), aError, );
3404}
3405
3406void nsGlobalWindowInner::SetStatus(const nsAString& aStatus,
3407 ErrorResult& aError) {
3408 FORWARD_TO_OUTER_OR_THROW(SetStatusOuter, (aStatus), aError, );
3409}
3410
3411void nsGlobalWindowInner::GetName(nsAString& aName, ErrorResult& aError) {
3412 FORWARD_TO_OUTER_OR_THROW(GetNameOuter, (aName), aError, );
3413}
3414
3415void nsGlobalWindowInner::SetName(const nsAString& aName,
3416 mozilla::ErrorResult& aError) {
3417 FORWARD_TO_OUTER_OR_THROW(SetNameOuter, (aName, aError), aError, );
3418}
3419
3420double nsGlobalWindowInner::GetInnerWidth(ErrorResult& aError) {
3421 FORWARD_TO_OUTER_OR_THROW(GetInnerWidthOuter, (aError), aError, 0);
3422}
3423
3424nsresult nsGlobalWindowInner::GetInnerWidth(double* aWidth) {
3425 ErrorResult rv;
3426 // Callee doesn't care about the caller type, but play it safe.
3427 *aWidth = GetInnerWidth(rv);
3428 return rv.StealNSResult();
3429}
3430
3431double nsGlobalWindowInner::GetInnerHeight(ErrorResult& aError) {
3432 // We ignore aCallerType; we only have that argument because some other things
3433 // called by GetReplaceableWindowCoord need it. If this ever changes, fix
3434 // nsresult nsGlobalWindowInner::GetInnerHeight(double* aInnerWidth)
3435 // to actually take a useful CallerType and pass it in here.
3436 FORWARD_TO_OUTER_OR_THROW(GetInnerHeightOuter, (aError), aError, 0);
3437}
3438
3439nsresult nsGlobalWindowInner::GetInnerHeight(double* aHeight) {
3440 ErrorResult rv;
3441 // Callee doesn't care about the caller type, but play it safe.
3442 *aHeight = GetInnerHeight(rv);
3443 return rv.StealNSResult();
3444}
3445
3446int32_t nsGlobalWindowInner::GetOuterWidth(CallerType aCallerType,
3447 ErrorResult& aError) {
3448 FORWARD_TO_OUTER_OR_THROW(GetOuterWidthOuter, (aCallerType, aError), aError,
3449 0);
3450}
3451
3452int32_t nsGlobalWindowInner::GetOuterHeight(CallerType aCallerType,
3453 ErrorResult& aError) {
3454 FORWARD_TO_OUTER_OR_THROW(GetOuterHeightOuter, (aCallerType, aError), aError,
3455 0);
3456}
3457
3458double nsGlobalWindowInner::ScreenEdgeSlopX() const {
3459 FORWARD_TO_OUTER(ScreenEdgeSlopX, (), 0);
3460}
3461
3462double nsGlobalWindowInner::ScreenEdgeSlopY() const {
3463 FORWARD_TO_OUTER(ScreenEdgeSlopY, (), 0);
3464}
3465
3466int32_t nsGlobalWindowInner::GetScreenX(CallerType aCallerType,
3467 ErrorResult& aError) {
3468 FORWARD_TO_OUTER_OR_THROW(GetScreenXOuter, (aCallerType, aError), aError, 0);
3469}
3470
3471int32_t nsGlobalWindowInner::GetScreenY(CallerType aCallerType,
3472 ErrorResult& aError) {
3473 FORWARD_TO_OUTER_OR_THROW(GetScreenYOuter, (aCallerType, aError), aError, 0);
3474}
3475
3476float nsGlobalWindowInner::GetMozInnerScreenX(CallerType aCallerType,
3477 ErrorResult& aError) {
3478 FORWARD_TO_OUTER_OR_THROW(GetMozInnerScreenXOuter, (aCallerType), aError, 0);
3479}
3480
3481float nsGlobalWindowInner::GetMozInnerScreenY(CallerType aCallerType,
3482 ErrorResult& aError) {
3483 FORWARD_TO_OUTER_OR_THROW(GetMozInnerScreenYOuter, (aCallerType), aError, 0);
3484}
3485
3486static nsPresContext* GetPresContextForRatio(Document* aDoc) {
3487 if (nsPresContext* presContext = aDoc->GetPresContext()) {
3488 return presContext;
3489 }
3490 // We're in an undisplayed subdocument... There's not really an awesome way
3491 // to tell what the right DPI is from here, so we try to walk up our parent
3492 // document chain to the extent that the docs can observe each other.
3493 Document* doc = aDoc;
3494 while (doc->StyleOrLayoutObservablyDependsOnParentDocumentLayout()) {
3495 doc = doc->GetInProcessParentDocument();
3496 if (nsPresContext* presContext = doc->GetPresContext()) {
3497 return presContext;
3498 }
3499 }
3500 return nullptr;
3501}
3502
3503double nsGlobalWindowInner::GetDevicePixelRatio(CallerType aCallerType,
3504 ErrorResult& aError) {
3505 ENSURE_ACTIVE_DOCUMENT(aError, 0.0)do { if ((__builtin_expect(!!(!HasActiveDocument()), 0))) { aError
.Throw(NS_ERROR_XPC_SECURITY_MANAGER_VETO); return 0.0; } } while
(0)
;
3506
3507 RefPtr<nsPresContext> presContext = GetPresContextForRatio(mDoc);
3508 if (NS_WARN_IF(!presContext)NS_warn_if_impl(!presContext, "!presContext", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 3508)
) {
3509 // Still nothing, oh well.
3510 return 1.0;
3511 }
3512
3513 if (nsIGlobalObject::ShouldResistFingerprinting(
3514 aCallerType, RFPTarget::WindowDevicePixelRatio)) {
3515 return 2.0;
3516 }
3517
3518 if (aCallerType == CallerType::NonSystem) {
3519 float overrideDPPX = presContext->GetOverrideDPPX();
3520 if (overrideDPPX > 0.0f) {
3521 return overrideDPPX;
3522 }
3523 }
3524
3525 return double(AppUnitsPerCSSPixel()) /
3526 double(presContext->AppUnitsPerDevPixel());
3527}
3528
3529double nsGlobalWindowInner::GetDesktopToDeviceScale(ErrorResult& aError) {
3530 ENSURE_ACTIVE_DOCUMENT(aError, 0.0)do { if ((__builtin_expect(!!(!HasActiveDocument()), 0))) { aError
.Throw(NS_ERROR_XPC_SECURITY_MANAGER_VETO); return 0.0; } } while
(0)
;
3531 nsPresContext* presContext = GetPresContextForRatio(mDoc);
3532 if (!presContext) {
3533 return 1.0;
3534 }
3535 return presContext->DeviceContext()->GetDesktopToDeviceScale().scale;
3536}
3537
3538uint32_t nsGlobalWindowInner::RequestAnimationFrame(
3539 FrameRequestCallback& aCallback, ErrorResult& aError) {
3540 if (!mDoc) {
3541 return 0;
3542 }
3543
3544 if (GetWrapperPreserveColor()) {
3545 js::NotifyAnimationActivity(GetWrapperPreserveColor());
3546 }
3547
3548 DebuggerNotificationDispatch(this,
3549 DebuggerNotificationType::RequestAnimationFrame);
3550
3551 uint32_t handle;
3552 aError = mDoc->ScheduleFrameRequestCallback(aCallback, &handle);
3553 return handle;
3554}
3555
3556void nsGlobalWindowInner::CancelAnimationFrame(uint32_t aHandle,
3557 ErrorResult& aError) {
3558 if (!mDoc) {
3559 return;
3560 }
3561
3562 DebuggerNotificationDispatch(this,
3563 DebuggerNotificationType::CancelAnimationFrame);
3564
3565 mDoc->CancelFrameRequestCallback(aHandle);
3566}
3567
3568already_AddRefed<MediaQueryList> nsGlobalWindowInner::MatchMedia(
3569 const nsACString& aMediaQueryList, CallerType aCallerType,
3570 ErrorResult& aError) {
3571 ENSURE_ACTIVE_DOCUMENT(aError, nullptr)do { if ((__builtin_expect(!!(!HasActiveDocument()), 0))) { aError
.Throw(NS_ERROR_XPC_SECURITY_MANAGER_VETO); return nullptr; }
} while (0)
;
3572 return mDoc->MatchMedia(aMediaQueryList, aCallerType);
3573}
3574
3575int32_t nsGlobalWindowInner::GetScrollMinX(ErrorResult& aError) {
3576 FORWARD_TO_OUTER_OR_THROW(GetScrollBoundaryOuter, (eSideLeft), aError, 0);
3577}
3578
3579int32_t nsGlobalWindowInner::GetScrollMinY(ErrorResult& aError) {
3580 FORWARD_TO_OUTER_OR_THROW(GetScrollBoundaryOuter, (eSideTop), aError, 0);
3581}
3582
3583int32_t nsGlobalWindowInner::GetScrollMaxX(ErrorResult& aError) {
3584 FORWARD_TO_OUTER_OR_THROW(GetScrollBoundaryOuter, (eSideRight), aError, 0);
3585}
3586
3587int32_t nsGlobalWindowInner::GetScrollMaxY(ErrorResult& aError) {
3588 FORWARD_TO_OUTER_OR_THROW(GetScrollBoundaryOuter, (eSideBottom), aError, 0);
3589}
3590
3591double nsGlobalWindowInner::GetScrollX(ErrorResult& aError) {
3592 FORWARD_TO_OUTER_OR_THROW(GetScrollXOuter, (), aError, 0);
3593}
3594
3595double nsGlobalWindowInner::GetScrollY(ErrorResult& aError) {
3596 FORWARD_TO_OUTER_OR_THROW(GetScrollYOuter, (), aError, 0);
3597}
3598
3599uint32_t nsGlobalWindowInner::Length() { FORWARD_TO_OUTER(Length, (), 0); }
3600
3601Nullable<WindowProxyHolder> nsGlobalWindowInner::GetTop(
3602 mozilla::ErrorResult& aError) {
3603 FORWARD_TO_OUTER_OR_THROW(GetTopOuter, (), aError, nullptr);
3604}
3605
3606already_AddRefed<BrowsingContext> nsGlobalWindowInner::GetChildWindow(
3607 const nsAString& aName) {
3608 if (GetOuterWindowInternal()) {
3609 return GetOuterWindowInternal()->GetChildWindow(aName);
3610 }
3611 return nullptr;
3612}
3613
3614void nsGlobalWindowInner::RefreshRealmPrincipal() {
3615 JS::SetRealmPrincipals(js::GetNonCCWObjectRealm(GetWrapperPreserveColor()),
3616 nsJSPrincipals::get(mDoc->NodePrincipal()));
3617}
3618
3619void nsGlobalWindowInner::RefreshReduceTimerPrecisionCallerType() {
3620 JS::SetRealmReduceTimerPrecisionCallerType(
3621 js::GetNonCCWObjectRealm(GetWrapperPreserveColor()),
3622 RTPCallerTypeToToken(GetRTPCallerType()));
3623}
3624
3625already_AddRefed<nsIWidget> nsGlobalWindowInner::GetMainWidget() {
3626 FORWARD_TO_OUTER(GetMainWidget, (), nullptr);
3627}
3628
3629nsIWidget* nsGlobalWindowInner::GetNearestWidget() const {
3630 if (GetOuterWindowInternal()) {
3631 return GetOuterWindowInternal()->GetNearestWidget();
3632 }
3633 return nullptr;
3634}
3635
3636void nsGlobalWindowInner::SetFullScreen(bool aFullscreen,
3637 mozilla::ErrorResult& aError) {
3638 FORWARD_TO_OUTER_OR_THROW(SetFullscreenOuter, (aFullscreen, aError), aError,
3639 /* void */);
3640}
3641
3642bool nsGlobalWindowInner::GetFullScreen(ErrorResult& aError) {
3643 FORWARD_TO_OUTER_OR_THROW(GetFullscreenOuter, (), aError, false);
3644}
3645
3646bool nsGlobalWindowInner::GetFullScreen() {
3647 ErrorResult dummy;
3648 bool fullscreen = GetFullScreen(dummy);
3649 dummy.SuppressException();
3650 return fullscreen;
3651}
3652
3653void nsGlobalWindowInner::Dump(const nsAString& aStr) {
3654 if (!nsJSUtils::DumpEnabled()) {
3655 return;
3656 }
3657
3658 char* cstr = ToNewUTF8String(aStr);
3659
3660#if defined(XP_MACOSX)
3661 // have to convert \r to \n so that printing to the console works
3662 char *c = cstr, *cEnd = cstr + strlen(cstr);
3663 while (c < cEnd) {
3664 if (*c == '\r') *c = '\n';
3665 c++;
3666 }
3667#endif
3668
3669 if (cstr) {
3670 MOZ_LOG(nsContentUtils::DOMDumpLog(), LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::DOMDumpLog(); if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::
log_print(moz_real_module, LogLevel::Debug, "[Window.Dump] %s"
, cstr); } } while (0)
3671 ("[Window.Dump] %s", cstr))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::DOMDumpLog(); if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail::
log_print(moz_real_module, LogLevel::Debug, "[Window.Dump] %s"
, cstr); } } while (0)
;
3672#ifdef XP_WIN
3673 PrintToDebugger(cstr);
3674#endif
3675#ifdef ANDROID
3676 __android_log_write(ANDROID_LOG_INFO, "GeckoDump", cstr);
3677#endif
3678 FILE* fp = gDumpFile ? gDumpFile : stdoutstdout;
3679 fputs(cstr, fp);
3680 fflush(fp);
3681 free(cstr);
3682 }
3683}
3684
3685void nsGlobalWindowInner::Alert(nsIPrincipal& aSubjectPrincipal,
3686 ErrorResult& aError) {
3687 Alert(u""_ns, aSubjectPrincipal, aError);
3688}
3689
3690void nsGlobalWindowInner::Alert(const nsAString& aMessage,
3691 nsIPrincipal& aSubjectPrincipal,
3692 ErrorResult& aError) {
3693 FORWARD_TO_OUTER_OR_THROW(AlertOuter, (aMessage, aSubjectPrincipal, aError),
3694 aError, );
3695}
3696
3697bool nsGlobalWindowInner::Confirm(const nsAString& aMessage,
3698 nsIPrincipal& aSubjectPrincipal,
3699 ErrorResult& aError) {
3700 FORWARD_TO_OUTER_OR_THROW(ConfirmOuter, (aMessage, aSubjectPrincipal, aError),
3701 aError, false);
3702}
3703
3704already_AddRefed<Promise> nsGlobalWindowInner::Fetch(
3705 const RequestOrUTF8String& aInput, const RequestInit& aInit,
3706 CallerType aCallerType, ErrorResult& aRv) {
3707 return FetchRequest(this, aInput, aInit, aCallerType, aRv);
3708}
3709
3710void nsGlobalWindowInner::Prompt(const nsAString& aMessage,
3711 const nsAString& aInitial, nsAString& aReturn,
3712 nsIPrincipal& aSubjectPrincipal,
3713 ErrorResult& aError) {
3714 FORWARD_TO_OUTER_OR_THROW(
3715 PromptOuter, (aMessage, aInitial, aReturn, aSubjectPrincipal, aError),
3716 aError, );
3717}
3718
3719void nsGlobalWindowInner::Focus(CallerType aCallerType, ErrorResult& aError) {
3720 FORWARD_TO_OUTER_OR_THROW(FocusOuter,
3721 (aCallerType, /* aFromOtherProcess */ false,
3722 nsFocusManager::GenerateFocusActionId()),
3723 aError, );
3724}
3725
3726nsresult nsGlobalWindowInner::Focus(CallerType aCallerType) {
3727 ErrorResult rv;
3728 Focus(aCallerType, rv);
3729
3730 return rv.StealNSResult();
3731}
3732
3733void nsGlobalWindowInner::Blur(CallerType aCallerType, ErrorResult& aError) {
3734 FORWARD_TO_OUTER_OR_THROW(BlurOuter, (aCallerType), aError, );
3735}
3736
3737void nsGlobalWindowInner::Stop(ErrorResult& aError) {
3738 FORWARD_TO_OUTER_OR_THROW(StopOuter, (aError), aError, );
3739}
3740
3741void nsGlobalWindowInner::Print(ErrorResult& aError) {
3742 FORWARD_TO_OUTER_OR_THROW(PrintOuter, (aError), aError, );
3743}
3744
3745Nullable<WindowProxyHolder> nsGlobalWindowInner::PrintPreview(
3746 nsIPrintSettings* aSettings, nsIWebProgressListener* aListener,
3747 nsIDocShell* aDocShellToCloneInto, ErrorResult& aError) {
3748 FORWARD_TO_OUTER_OR_THROW(
3749 Print,
3750 (aSettings,
3751 /* aRemotePrintJob = */ nullptr, aListener, aDocShellToCloneInto,
3752 nsGlobalWindowOuter::IsPreview::Yes,
3753 nsGlobalWindowOuter::IsForWindowDotPrint::No,
3754 /* aPrintPreviewCallback = */ nullptr, nullptr, aError),
3755 aError, nullptr);
3756}
3757
3758void nsGlobalWindowInner::MoveTo(int32_t aXPos, int32_t aYPos,
3759 CallerType aCallerType, ErrorResult& aError) {
3760 FORWARD_TO_OUTER_OR_THROW(MoveToOuter, (aXPos, aYPos, aCallerType, aError),
3761 aError, );
3762}
3763
3764void nsGlobalWindowInner::MoveBy(int32_t aXDif, int32_t aYDif,
3765 CallerType aCallerType, ErrorResult& aError) {
3766 FORWARD_TO_OUTER_OR_THROW(MoveByOuter, (aXDif, aYDif, aCallerType, aError),
3767 aError, );
3768}
3769
3770void nsGlobalWindowInner::ResizeTo(int32_t aWidth, int32_t aHeight,
3771 CallerType aCallerType,
3772 ErrorResult& aError) {
3773 FORWARD_TO_OUTER_OR_THROW(ResizeToOuter,
3774 (aWidth, aHeight, aCallerType, aError), aError, );
3775}
3776
3777void nsGlobalWindowInner::ResizeBy(int32_t aWidthDif, int32_t aHeightDif,
3778 CallerType aCallerType,
3779 ErrorResult& aError) {
3780 FORWARD_TO_OUTER_OR_THROW(
3781 ResizeByOuter, (aWidthDif, aHeightDif, aCallerType, aError), aError, );
3782}
3783
3784void nsGlobalWindowInner::SizeToContent(CallerType aCallerType,
3785 ErrorResult& aError) {
3786 FORWARD_TO_OUTER_OR_THROW(SizeToContentOuter, (aCallerType, {}, aError),
3787 aError, );
3788}
3789
3790void nsGlobalWindowInner::SizeToContentConstrained(
3791 const SizeToContentConstraints& aConstraints, ErrorResult& aError) {
3792 FORWARD_TO_OUTER_OR_THROW(
3793 SizeToContentOuter, (CallerType::System, aConstraints, aError), aError, );
3794}
3795
3796already_AddRefed<nsPIWindowRoot> nsGlobalWindowInner::GetTopWindowRoot() {
3797 nsGlobalWindowOuter* outer = GetOuterWindowInternal();
3798 if (!outer) {
3799 return nullptr;
3800 }
3801 return outer->GetTopWindowRoot();
3802}
3803
3804void nsGlobalWindowInner::ScrollTo(double aXScroll, double aYScroll) {
3805 ScrollToOptions options;
3806 options.mLeft.Construct(aXScroll);
3807 options.mTop.Construct(aYScroll);
3808 ScrollTo(options);
3809}
3810
3811void nsGlobalWindowInner::ScrollTo(const ScrollToOptions& aOptions) {
3812 Maybe<int32_t> left;
3813 Maybe<int32_t> top;
3814 if (aOptions.mLeft.WasPassed()) {
3815 left.emplace(static_cast<int32_t>(
3816 mozilla::ToZeroIfNonfinite(aOptions.mLeft.Value())));
3817 }
3818 if (aOptions.mTop.WasPassed()) {
3819 top.emplace(static_cast<int32_t>(
3820 mozilla::ToZeroIfNonfinite(aOptions.mTop.Value())));
3821 }
3822
3823 // When scrolling to a non-zero offset, we need to determine whether that
3824 // position is within our scrollable range, so we need updated layout
3825 // information.
3826 if ((top && *top != 0) || (left && *left != 0)) {
3827 FlushPendingNotifications(FlushType::Layout);
3828 }
3829
3830 ScrollContainerFrame* sf = GetScrollContainerFrame();
3831 if (!sf) {
3832 return;
3833 }
3834 CSSIntPoint scrollPos = sf->GetRoundedScrollPositionCSSPixels();
3835 if (left) {
3836 scrollPos.x = *left;
3837 }
3838 if (top) {
3839 scrollPos.y = *top;
3840 }
3841 // Here we calculate what the max pixel value is that we can
3842 // scroll to, we do this by dividing maxint with the pixel to
3843 // twips conversion factor, and subtracting 4, the 4 comes from
3844 // experimenting with this value, anything less makes the view
3845 // code not scroll correctly, I have no idea why. -- jst
3846 const int32_t maxpx = nsPresContext::AppUnitsToIntCSSPixels(0x7fffffff) - 4;
3847 if (scrollPos.x > maxpx) {
3848 scrollPos.x = maxpx;
3849 }
3850 if (scrollPos.y > maxpx) {
3851 scrollPos.y = maxpx;
3852 }
3853 auto scrollMode = sf->IsSmoothScroll(aOptions.mBehavior)
3854 ? ScrollMode::SmoothMsd
3855 : ScrollMode::Instant;
3856 sf->ScrollToCSSPixels(scrollPos, scrollMode);
3857}
3858
3859void nsGlobalWindowInner::ScrollBy(double aXScrollDif, double aYScrollDif) {
3860 ScrollToOptions options;
3861 options.mLeft.Construct(aXScrollDif);
3862 options.mTop.Construct(aYScrollDif);
3863 // It seems like it would make more sense for ScrollBy to use
3864 // SMOOTH mode, but tests seem to depend on the synchronous behaviour.
3865 // Perhaps Web content does too.
3866 ScrollBy(options);
3867}
3868
3869void nsGlobalWindowInner::ScrollBy(const ScrollToOptions& aOptions) {
3870 CSSIntPoint scrollDelta;
3871 if (aOptions.mLeft.WasPassed()) {
3872 scrollDelta.x = static_cast<int32_t>(
3873 mozilla::ToZeroIfNonfinite(aOptions.mLeft.Value()));
3874 }
3875 if (aOptions.mTop.WasPassed()) {
3876 scrollDelta.y =
3877 static_cast<int32_t>(mozilla::ToZeroIfNonfinite(aOptions.mTop.Value()));
3878 }
3879
3880 if (!scrollDelta.x && !scrollDelta.y) {
3881 return;
3882 }
3883
3884 FlushPendingNotifications(FlushType::Layout);
3885 ScrollContainerFrame* sf = GetScrollContainerFrame();
3886 if (!sf) {
3887 return;
3888 }
3889
3890 auto scrollMode = sf->IsSmoothScroll(aOptions.mBehavior)
3891 ? ScrollMode::SmoothMsd
3892 : ScrollMode::Instant;
3893 sf->ScrollByCSSPixels(scrollDelta, scrollMode);
3894}
3895
3896void nsGlobalWindowInner::ScrollByLines(int32_t numLines,
3897 const ScrollOptions& aOptions) {
3898 if (!numLines) {
3899 return;
3900 }
3901 FlushPendingNotifications(FlushType::Layout);
3902 ScrollContainerFrame* sf = GetScrollContainerFrame();
3903 if (!sf) {
3904 return;
3905 }
3906 // It seems like it would make more sense for ScrollByLines to use
3907 // SMOOTH mode, but tests seem to depend on the synchronous behaviour.
3908 // Perhaps Web content does too.
3909 ScrollMode scrollMode = sf->IsSmoothScroll(aOptions.mBehavior)
3910 ? ScrollMode::SmoothMsd
3911 : ScrollMode::Instant;
3912 sf->ScrollBy(nsIntPoint(0, numLines), ScrollUnit::LINES, scrollMode);
3913}
3914
3915void nsGlobalWindowInner::ScrollByPages(int32_t numPages,
3916 const ScrollOptions& aOptions) {
3917 if (!numPages) {
3918 return;
3919 }
3920 FlushPendingNotifications(FlushType::Layout);
3921 ScrollContainerFrame* sf = GetScrollContainerFrame();
3922 if (!sf) {
3923 return;
3924 }
3925 // It seems like it would make more sense for ScrollByPages to use
3926 // SMOOTH mode, but tests seem to depend on the synchronous behaviour.
3927 // Perhaps Web content does too.
3928 ScrollMode scrollMode = sf->IsSmoothScroll(aOptions.mBehavior)
3929 ? ScrollMode::SmoothMsd
3930 : ScrollMode::Instant;
3931
3932 sf->ScrollBy(nsIntPoint(0, numPages), ScrollUnit::PAGES, scrollMode);
3933}
3934
3935void nsGlobalWindowInner::MozScrollSnap() {
3936 FlushPendingNotifications(FlushType::Layout);
3937 if (ScrollContainerFrame* sf = GetScrollContainerFrame()) {
3938 sf->ScrollSnap();
3939 }
3940}
3941
3942void nsGlobalWindowInner::ClearTimeout(int32_t aHandle) {
3943 DebuggerNotificationDispatch(this, DebuggerNotificationType::ClearTimeout);
3944
3945 if (aHandle > 0) {
3946 mTimeoutManager->ClearTimeout(aHandle, Timeout::Reason::eTimeoutOrInterval);
3947 }
3948}
3949
3950void nsGlobalWindowInner::ClearInterval(int32_t aHandle) {
3951 DebuggerNotificationDispatch(this, DebuggerNotificationType::ClearInterval);
3952
3953 if (aHandle > 0) {
3954 mTimeoutManager->ClearTimeout(aHandle, Timeout::Reason::eTimeoutOrInterval);
3955 }
3956}
3957
3958void nsGlobalWindowInner::SetResizable(bool aResizable) const {
3959 // nop
3960}
3961
3962void nsGlobalWindowInner::CaptureEvents() {
3963 if (mDoc) {
3964 mDoc->WarnOnceAbout(DeprecatedOperations::eUseOfCaptureEvents);
3965 }
3966}
3967
3968void nsGlobalWindowInner::ReleaseEvents() {
3969 if (mDoc) {
3970 mDoc->WarnOnceAbout(DeprecatedOperations::eUseOfReleaseEvents);
3971 }
3972}
3973
3974Nullable<WindowProxyHolder> nsGlobalWindowInner::Open(const nsAString& aUrl,
3975 const nsAString& aName,
3976 const nsAString& aOptions,
3977 ErrorResult& aError) {
3978 FORWARD_TO_OUTER_OR_THROW(OpenOuter, (aUrl, aName, aOptions, aError), aError,
3979 nullptr);
3980}
3981
3982Nullable<WindowProxyHolder> nsGlobalWindowInner::OpenDialog(
3983 JSContext* aCx, const nsAString& aUrl, const nsAString& aName,
3984 const nsAString& aOptions, const Sequence<JS::Value>& aExtraArgument,
3985 ErrorResult& aError) {
3986 FORWARD_TO_OUTER_OR_THROW(
3987 OpenDialogOuter, (aCx, aUrl, aName, aOptions, aExtraArgument, aError),
3988 aError, nullptr);
3989}
3990
3991WindowProxyHolder nsGlobalWindowInner::GetFrames(ErrorResult& aError) {
3992 FORWARD_TO_OUTER_OR_THROW(GetFramesOuter, (), aError, Window());
3993}
3994
3995void nsGlobalWindowInner::PostMessageMoz(JSContext* aCx,
3996 JS::Handle<JS::Value> aMessage,
3997 const nsAString& aTargetOrigin,
3998 JS::Handle<JS::Value> aTransfer,
3999 nsIPrincipal& aSubjectPrincipal,
4000 ErrorResult& aError) {
4001 FORWARD_TO_OUTER_OR_THROW(
4002 PostMessageMozOuter,
4003 (aCx, aMessage, aTargetOrigin, aTransfer, aSubjectPrincipal, aError),
4004 aError, );
4005}
4006
4007void nsGlobalWindowInner::PostMessageMoz(JSContext* aCx,
4008 JS::Handle<JS::Value> aMessage,
4009 const nsAString& aTargetOrigin,
4010 const Sequence<JSObject*>& aTransfer,
4011 nsIPrincipal& aSubjectPrincipal,
4012 ErrorResult& aRv) {
4013 JS::Rooted<JS::Value> transferArray(aCx, JS::UndefinedValue());
4014
4015 aRv = nsContentUtils::CreateJSValueFromSequenceOfObject(aCx, aTransfer,
4016 &transferArray);
4017 if (NS_WARN_IF(aRv.Failed())NS_warn_if_impl(aRv.Failed(), "aRv.Failed()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 4017)
) {
4018 return;
4019 }
4020
4021 PostMessageMoz(aCx, aMessage, aTargetOrigin, transferArray, aSubjectPrincipal,
4022 aRv);
4023}
4024
4025void nsGlobalWindowInner::PostMessageMoz(
4026 JSContext* aCx, JS::Handle<JS::Value> aMessage,
4027 const WindowPostMessageOptions& aOptions, nsIPrincipal& aSubjectPrincipal,
4028 ErrorResult& aRv) {
4029 JS::Rooted<JS::Value> transferArray(aCx, JS::UndefinedValue());
4030
4031 aRv = nsContentUtils::CreateJSValueFromSequenceOfObject(
4032 aCx, aOptions.mTransfer, &transferArray);
4033 if (NS_WARN_IF(aRv.Failed())NS_warn_if_impl(aRv.Failed(), "aRv.Failed()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 4033)
) {
4034 return;
4035 }
4036
4037 PostMessageMoz(aCx, aMessage, aOptions.mTargetOrigin, transferArray,
4038 aSubjectPrincipal, aRv);
4039}
4040
4041void nsGlobalWindowInner::Close(CallerType aCallerType, ErrorResult& aError) {
4042 FORWARD_TO_OUTER_OR_THROW(CloseOuter, (aCallerType == CallerType::System),
4043 aError, );
4044}
4045
4046nsresult nsGlobalWindowInner::Close() {
4047 FORWARD_TO_OUTER(Close, (), NS_ERROR_UNEXPECTED);
4048}
4049
4050bool nsGlobalWindowInner::IsInModalState() {
4051 FORWARD_TO_OUTER(IsInModalState, (), false);
4052}
4053
4054// static
4055void nsGlobalWindowInner::NotifyDOMWindowDestroyed(
4056 nsGlobalWindowInner* aWindow) {
4057 nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
4058 if (observerService) {
4059 observerService->NotifyObservers(ToSupports(aWindow),
4060 DOM_WINDOW_DESTROYED_TOPIC"dom-window-destroyed", nullptr);
4061 }
4062}
4063
4064void nsGlobalWindowInner::NotifyWindowIDDestroyed(const char* aTopic) {
4065 nsCOMPtr<nsIRunnable> runnable =
4066 new WindowDestroyedEvent(this, mWindowID, aTopic);
4067 Dispatch(runnable.forget());
4068}
4069
4070// static
4071void nsGlobalWindowInner::NotifyDOMWindowFrozen(nsGlobalWindowInner* aWindow) {
4072 if (aWindow) {
4073 nsCOMPtr<nsIObserverService> observerService =
4074 services::GetObserverService();
4075 if (observerService) {
4076 observerService->NotifyObservers(ToSupports(aWindow),
4077 DOM_WINDOW_FROZEN_TOPIC"dom-window-frozen", nullptr);
4078 }
4079 }
4080}
4081
4082// static
4083void nsGlobalWindowInner::NotifyDOMWindowThawed(nsGlobalWindowInner* aWindow) {
4084 if (aWindow) {
4085 nsCOMPtr<nsIObserverService> observerService =
4086 services::GetObserverService();
4087 if (observerService) {
4088 observerService->NotifyObservers(ToSupports(aWindow),
4089 DOM_WINDOW_THAWED_TOPIC"dom-window-thawed", nullptr);
4090 }
4091 }
4092}
4093
4094Element* nsGlobalWindowInner::GetFrameElement(nsIPrincipal& aSubjectPrincipal,
4095 ErrorResult& aError) {
4096 FORWARD_TO_OUTER_OR_THROW(GetFrameElement, (aSubjectPrincipal), aError,
4097 nullptr);
4098}
4099
4100Element* nsGlobalWindowInner::GetRealFrameElement(ErrorResult& aError) {
4101 FORWARD_TO_OUTER_OR_THROW(GetFrameElement, (), aError, nullptr);
4102}
4103
4104void nsGlobalWindowInner::UpdateCommands(const nsAString& anAction) {
4105 if (GetOuterWindowInternal()) {
4106 GetOuterWindowInternal()->UpdateCommands(anAction);
4107 }
4108}
4109
4110Selection* nsGlobalWindowInner::GetSelection(ErrorResult& aError) {
4111 FORWARD_TO_OUTER_OR_THROW(GetSelectionOuter, (), aError, nullptr);
4112}
4113
4114WebTaskScheduler* nsGlobalWindowInner::Scheduler() {
4115 if (!mWebTaskScheduler) {
4116 mWebTaskScheduler = WebTaskScheduler::CreateForMainThread(this);
4117 }
4118 MOZ_ASSERT(mWebTaskScheduler)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mWebTaskScheduler)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mWebTaskScheduler))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("mWebTaskScheduler"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 4118); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mWebTaskScheduler"
")"); do { *((volatile int*)__null) = 4118; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4119 return mWebTaskScheduler;
4120}
4121
4122bool nsGlobalWindowInner::Find(const nsAString& aString, bool aCaseSensitive,
4123 bool aBackwards, bool aWrapAround,
4124 bool aWholeWord, bool aSearchInFrames,
4125 bool aShowDialog, ErrorResult& aError) {
4126 FORWARD_TO_OUTER_OR_THROW(FindOuter,
4127 (aString, aCaseSensitive, aBackwards, aWrapAround,
4128 aWholeWord, aSearchInFrames, aShowDialog, aError),
4129 aError, false);
4130}
4131
4132void nsGlobalWindowInner::GetOrigin(nsAString& aOrigin) {
4133 nsContentUtils::GetWebExposedOriginSerialization(GetPrincipal(), aOrigin);
4134}
4135
4136// See also AutoJSAPI::ReportException
4137void nsGlobalWindowInner::ReportError(JSContext* aCx,
4138 JS::Handle<JS::Value> aError,
4139 CallerType aCallerType,
4140 ErrorResult& aRv) {
4141 if (MOZ_UNLIKELY(!HasActiveDocument())(__builtin_expect(!!(!HasActiveDocument()), 0))) {
4142 return aRv.Throw(NS_ERROR_XPC_SECURITY_MANAGER_VETO);
4143 }
4144
4145 JS::ErrorReportBuilder jsReport(aCx);
4146 JS::ExceptionStack exnStack(aCx, aError, nullptr);
4147 if (!jsReport.init(aCx, exnStack, JS::ErrorReportBuilder::NoSideEffects)) {
4148 return aRv.NoteJSContextException(aCx);
4149 }
4150
4151 RefPtr<xpc::ErrorReport> xpcReport = new xpc::ErrorReport();
4152 bool isChrome = aCallerType == CallerType::System;
4153 xpcReport->Init(jsReport.report(), jsReport.toStringResult().c_str(),
4154 isChrome, WindowID());
4155
4156 JS::RootingContext* rcx = JS::RootingContext::get(aCx);
4157 DispatchScriptErrorEvent(this, rcx, xpcReport, exnStack.exception(),
4158 exnStack.stack());
4159}
4160
4161void nsGlobalWindowInner::Atob(const nsAString& aAsciiBase64String,
4162 nsAString& aBinaryData, ErrorResult& aError) {
4163 aError = nsContentUtils::Atob(aAsciiBase64String, aBinaryData);
4164}
4165
4166void nsGlobalWindowInner::Btoa(const nsAString& aBinaryData,
4167 nsAString& aAsciiBase64String,
4168 ErrorResult& aError) {
4169 aError = nsContentUtils::Btoa(aBinaryData, aAsciiBase64String);
4170}
4171
4172//*****************************************************************************
4173// EventTarget
4174//*****************************************************************************
4175
4176nsPIDOMWindowOuter* nsGlobalWindowInner::GetOwnerGlobalForBindingsInternal() {
4177 return nsPIDOMWindowOuter::GetFromCurrentInner(this);
4178}
4179
4180bool nsGlobalWindowInner::DispatchEvent(Event& aEvent, CallerType aCallerType,
4181 ErrorResult& aRv) {
4182 if (!IsCurrentInnerWindow()) {
4183 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "DispatchEvent called on non-current inner window, dropping. "
"Please check the window in the caller instead.", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 4185)
4184 "DispatchEvent called on non-current inner window, dropping. "NS_DebugBreak(NS_DEBUG_WARNING, "DispatchEvent called on non-current inner window, dropping. "
"Please check the window in the caller instead.", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 4185)
4185 "Please check the window in the caller instead.")NS_DebugBreak(NS_DEBUG_WARNING, "DispatchEvent called on non-current inner window, dropping. "
"Please check the window in the caller instead.", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 4185)
;
4186 aRv.Throw(NS_ERROR_FAILURE);
4187 return false;
4188 }
4189
4190 if (!mDoc) {
4191 aRv.Throw(NS_ERROR_FAILURE);
4192 return false;
4193 }
4194
4195 // Obtain a presentation shell
4196 RefPtr<nsPresContext> presContext = mDoc->GetPresContext();
4197
4198 nsEventStatus status = nsEventStatus_eIgnore;
4199 nsresult rv = EventDispatcher::DispatchDOMEvent(this, nullptr, &aEvent,
4200 presContext, &status);
4201 bool retval = !aEvent.DefaultPrevented(aCallerType);
4202 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4203 aRv.Throw(rv);
4204 }
4205 return retval;
4206}
4207
4208mozilla::Maybe<mozilla::dom::EventCallbackDebuggerNotificationType>
4209nsGlobalWindowInner::GetDebuggerNotificationType() const {
4210 return mozilla::Some(
4211 mozilla::dom::EventCallbackDebuggerNotificationType::Global);
4212}
4213
4214bool nsGlobalWindowInner::ComputeDefaultWantsUntrusted(ErrorResult& aRv) {
4215 return !nsContentUtils::IsChromeDoc(mDoc);
4216}
4217
4218EventListenerManager* nsGlobalWindowInner::GetOrCreateListenerManager() {
4219 if (!mListenerManager) {
4220 mListenerManager =
4221 new EventListenerManager(static_cast<EventTarget*>(this));
4222 }
4223
4224 return mListenerManager;
4225}
4226
4227EventListenerManager* nsGlobalWindowInner::GetExistingListenerManager() const {
4228 return mListenerManager;
4229}
4230
4231mozilla::dom::DebuggerNotificationManager*
4232nsGlobalWindowInner::GetOrCreateDebuggerNotificationManager() {
4233 if (!mDebuggerNotificationManager) {
4234 mDebuggerNotificationManager = new DebuggerNotificationManager(this);
4235 }
4236
4237 return mDebuggerNotificationManager;
4238}
4239
4240mozilla::dom::DebuggerNotificationManager*
4241nsGlobalWindowInner::GetExistingDebuggerNotificationManager() {
4242 return mDebuggerNotificationManager;
4243}
4244
4245//*****************************************************************************
4246// nsGlobalWindowInner::nsPIDOMWindow
4247//*****************************************************************************
4248
4249Location* nsGlobalWindowInner::Location() {
4250 if (!mLocation) {
4251 mLocation = new dom::Location(this);
4252 }
4253
4254 return mLocation;
4255}
4256
4257void nsGlobalWindowInner::MaybeUpdateTouchState() {
4258 if (mMayHaveTouchEventListener) {
4259 nsCOMPtr<nsIObserverService> observerService =
4260 services::GetObserverService();
4261
4262 if (observerService) {
4263 observerService->NotifyObservers(static_cast<nsIDOMWindow*>(this),
4264 DOM_TOUCH_LISTENER_ADDED"dom-touch-listener-added", nullptr);
4265 }
4266 }
4267}
4268
4269void nsGlobalWindowInner::EnableGamepadUpdates() {
4270 if (mHasGamepad) {
4271 RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService());
4272 if (gamepadManager) {
4273 gamepadManager->AddListener(this);
4274 }
4275 }
4276}
4277
4278void nsGlobalWindowInner::DisableGamepadUpdates() {
4279 if (mHasGamepad) {
4280 RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService());
4281 if (gamepadManager) {
4282 gamepadManager->RemoveListener(this);
4283 }
4284 }
4285}
4286
4287void nsGlobalWindowInner::EnableVRUpdates() {
4288 // We need to create a VREventObserver before we can either detect XR runtimes
4289 // or start an XR session
4290 if (!mVREventObserver && (mHasXRSession || mXRRuntimeDetectionInFlight)) {
4291 // Assert that we are not creating the observer while IsDying() as
4292 // that would result in a leak. VREventObserver holds a RefPtr to
4293 // this nsGlobalWindowInner and would prevent it from being deallocated.
4294 MOZ_ASSERT(!IsDying(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsDying())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsDying()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("!IsDying()" " (" "Creating a VREventObserver for an nsGlobalWindow that is "
"dying would cause it to leak." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 4296); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDying()"
") (" "Creating a VREventObserver for an nsGlobalWindow that is "
"dying would cause it to leak." ")"); do { *((volatile int*)
__null) = 4296; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
4295 "Creating a VREventObserver for an nsGlobalWindow that is "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsDying())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsDying()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("!IsDying()" " (" "Creating a VREventObserver for an nsGlobalWindow that is "
"dying would cause it to leak." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 4296); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDying()"
") (" "Creating a VREventObserver for an nsGlobalWindow that is "
"dying would cause it to leak." ")"); do { *((volatile int*)
__null) = 4296; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
4296 "dying would cause it to leak.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsDying())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsDying()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("!IsDying()" " (" "Creating a VREventObserver for an nsGlobalWindow that is "
"dying would cause it to leak." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 4296); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDying()"
") (" "Creating a VREventObserver for an nsGlobalWindow that is "
"dying would cause it to leak." ")"); do { *((volatile int*)
__null) = 4296; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4297 mVREventObserver = new VREventObserver(this);
4298 }
4299 // If the content has an XR session, then we need to tell
4300 // VREventObserver that there is VR activity.
4301 if (mHasXRSession) {
4302 nsPIDOMWindowOuter* outer = GetOuterWindow();
4303 if (outer && !outer->IsBackground()) {
4304 StartVRActivity();
4305 }
4306 }
4307}
4308
4309void nsGlobalWindowInner::DisableVRUpdates() {
4310 if (mVREventObserver) {
4311 mVREventObserver->DisconnectFromOwner();
4312 mVREventObserver = nullptr;
4313 }
4314}
4315
4316void nsGlobalWindowInner::ResetVRTelemetry(bool aUpdate) {
4317 if (mVREventObserver) {
4318 mVREventObserver->UpdateSpentTimeIn2DTelemetry(aUpdate);
4319 }
4320}
4321
4322void nsGlobalWindowInner::StartVRActivity() {
4323 /**
4324 * If the content has an XR session, tell
4325 * the VREventObserver that the window is accessing
4326 * VR devices.
4327 *
4328 * It's possible to have a VREventObserver without
4329 * and XR session, if we are using it to get updates
4330 * about XR runtime enumeration. In this case,
4331 * we would not tell the VREventObserver that
4332 * we are accessing VR devices.
4333 */
4334 if (mVREventObserver && mHasXRSession) {
4335 mVREventObserver->StartActivity();
4336 }
4337}
4338
4339void nsGlobalWindowInner::StopVRActivity() {
4340 /**
4341 * If the content has an XR session, tell
4342 * the VReventObserver that the window is no longer
4343 * accessing VR devices. This does not stop the
4344 * XR session itself, which may be resumed with
4345 * EnableVRUpdates.
4346 * It's possible to have a VREventObserver without
4347 * and XR session, if we are using it to get updates
4348 * about XR runtime enumeration. In this case,
4349 * we would not tell the VREventObserver that
4350 * we ending an activity that accesses VR devices.
4351 */
4352 if (mVREventObserver && mHasXRSession) {
4353 mVREventObserver->StopActivity();
4354 }
4355}
4356
4357void nsGlobalWindowInner::SetFocusedElement(Element* aElement,
4358 uint32_t aFocusMethod,
4359 bool aNeedsFocus) {
4360 if (aElement && aElement->GetComposedDoc() != mDoc) {
4361 NS_WARNING("Trying to set focus to a node from a wrong document")NS_DebugBreak(NS_DEBUG_WARNING, "Trying to set focus to a node from a wrong document"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 4361)
;
4362 return;
4363 }
4364
4365 if (IsDying()) {
4366 NS_ASSERTION(!aElement, "Trying to focus cleaned up window!")do { if (!(!aElement)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Trying to focus cleaned up window!"
, "!aElement", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 4366); MOZ_PretendNoReturn(); } } while (0)
;
4367 aElement = nullptr;
4368 aNeedsFocus = false;
4369 }
4370 if (mFocusedElement != aElement) {
4371 UpdateCanvasFocus(false, aElement);
4372 mFocusedElement = aElement;
4373 // TODO: Maybe this should be set on refocus too?
4374 mFocusMethod = aFocusMethod & nsIFocusManager::METHOD_MASK;
4375 }
4376
4377 if (mFocusedElement) {
4378 // if a node was focused by a keypress, turn on focus rings for the
4379 // window.
4380 if (mFocusMethod & nsIFocusManager::FLAG_BYKEY) {
4381 mUnknownFocusMethodShouldShowOutline = true;
4382 mFocusByKeyOccurred = true;
4383 } else if (nsFocusManager::GetFocusMoveActionCause(mFocusMethod) !=
4384 widget::InputContextAction::CAUSE_UNKNOWN) {
4385 mUnknownFocusMethodShouldShowOutline = false;
4386 } else if (aFocusMethod & nsIFocusManager::FLAG_NOSHOWRING) {
4387 // If we get focused via script, and script has explicitly opted out of
4388 // outlines via FLAG_NOSHOWRING, we don't want to make a refocus start
4389 // showing outlines.
4390 mUnknownFocusMethodShouldShowOutline = false;
4391 }
4392 }
4393
4394 if (aNeedsFocus) {
4395 mNeedsFocus = aNeedsFocus;
4396 }
4397}
4398
4399uint32_t nsGlobalWindowInner::GetFocusMethod() { return mFocusMethod; }
4400
4401bool nsGlobalWindowInner::ShouldShowFocusRing() {
4402 if (mFocusByKeyOccurred &&
4403 StaticPrefs::browser_display_always_show_rings_after_key_focus()) {
4404 return true;
4405 }
4406 return StaticPrefs::browser_display_show_focus_rings();
4407}
4408
4409bool nsGlobalWindowInner::TakeFocus(bool aFocus, uint32_t aFocusMethod) {
4410 if (IsDying()) {
4411 return false;
4412 }
4413
4414 if (aFocus) {
4415 mFocusMethod = aFocusMethod & nsIFocusManager::METHOD_MASK;
4416 }
4417
4418 if (mHasFocus != aFocus) {
4419 mHasFocus = aFocus;
4420 UpdateCanvasFocus(true, mFocusedElement);
4421 }
4422
4423 // if mNeedsFocus is true, then the document has not yet received a
4424 // document-level focus event. If there is a root content node, then return
4425 // true to tell the calling focus manager that a focus event is expected. If
4426 // there is no root content node, the document hasn't loaded enough yet, or
4427 // there isn't one and there is no point in firing a focus event.
4428 if (aFocus && mNeedsFocus && mDoc && mDoc->GetRootElement() != nullptr) {
4429 mNeedsFocus = false;
4430 return true;
4431 }
4432
4433 mNeedsFocus = false;
4434 return false;
4435}
4436
4437void nsGlobalWindowInner::SetReadyForFocus() {
4438 bool oldNeedsFocus = mNeedsFocus;
4439 mNeedsFocus = false;
4440
4441 if (RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager()) {
4442 nsCOMPtr<nsPIDOMWindowOuter> outerWindow = GetOuterWindow();
4443 fm->WindowShown(outerWindow, oldNeedsFocus);
4444 }
4445}
4446
4447void nsGlobalWindowInner::PageHidden() {
4448 // the window is being hidden, so tell the focus manager that the frame is
4449 // no longer valid. Use the persisted field to determine if the document
4450 // is being destroyed.
4451
4452 if (RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager()) {
4453 nsCOMPtr<nsPIDOMWindowOuter> outerWindow = GetOuterWindow();
4454 fm->WindowHidden(outerWindow, nsFocusManager::GenerateFocusActionId());
4455 }
4456
4457 mNeedsFocus = true;
4458}
4459
4460class HashchangeCallback : public Runnable {
4461 public:
4462 HashchangeCallback(const nsAString& aOldURL, const nsAString& aNewURL,
4463 nsGlobalWindowInner* aWindow)
4464 : mozilla::Runnable("HashchangeCallback"), mWindow(aWindow) {
4465 MOZ_ASSERT(mWindow)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mWindow)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mWindow))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mWindow", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 4465); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mWindow" ")"
); do { *((volatile int*)__null) = 4465; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4466 mOldURL.Assign(aOldURL);
4467 mNewURL.Assign(aNewURL);
4468 }
4469
4470 NS_IMETHODvirtual nsresult Run() override {
4471 MOZ_ASSERT(NS_IsMainThread(), "Should be called on the main thread.")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()"
" (" "Should be called on the main thread." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 4471); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Should be called on the main thread." ")"); do { *((volatile
int*)__null) = 4471; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
4472 return mWindow->FireHashchange(mOldURL, mNewURL);
4473 }
4474
4475 private:
4476 nsString mOldURL;
4477 nsString mNewURL;
4478 RefPtr<nsGlobalWindowInner> mWindow;
4479};
4480
4481nsresult nsGlobalWindowInner::DispatchAsyncHashchange(nsIURI* aOldURI,
4482 nsIURI* aNewURI) {
4483 // Make sure that aOldURI and aNewURI are identical up to the '#', and that
4484 // their hashes are different.
4485 bool equal = false;
4486 NS_ENSURE_STATE(NS_SUCCEEDED(aOldURI->EqualsExceptRef(aNewURI, &equal)) &&do { if ((__builtin_expect(!!(!(((bool)(__builtin_expect(!!(!
NS_FAILED_impl(aOldURI->EqualsExceptRef(aNewURI, &equal
))), 1))) && equal)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aOldURI->EqualsExceptRef(aNewURI, &equal))), 1))) && equal"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 4487); return NS_ERROR_UNEXPECTED; } } while (false)
4487 equal)do { if ((__builtin_expect(!!(!(((bool)(__builtin_expect(!!(!
NS_FAILED_impl(aOldURI->EqualsExceptRef(aNewURI, &equal
))), 1))) && equal)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aOldURI->EqualsExceptRef(aNewURI, &equal))), 1))) && equal"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 4487); return NS_ERROR_UNEXPECTED; } } while (false)
;
4488 nsAutoCString oldHash, newHash;
4489 bool oldHasHash, newHasHash;
4490 NS_ENSURE_STATE(NS_SUCCEEDED(aOldURI->GetRef(oldHash)) &&do { if ((__builtin_expect(!!(!(((bool)(__builtin_expect(!!(!
NS_FAILED_impl(aOldURI->GetRef(oldHash))), 1))) &&
((bool)(__builtin_expect(!!(!NS_FAILED_impl(aNewURI->GetRef
(newHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl
(aOldURI->GetHasRef(&oldHasHash))), 1))) && ((
bool)(__builtin_expect(!!(!NS_FAILED_impl(aNewURI->GetHasRef
(&newHasHash))), 1))) && (oldHasHash != newHasHash
|| !oldHash.Equals(newHash)))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aOldURI->GetRef(oldHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl(aNewURI->GetRef(newHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl(aOldURI->GetHasRef(&oldHasHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl(aNewURI->GetHasRef(&newHasHash))), 1))) && (oldHasHash != newHasHash || !oldHash.Equals(newHash))"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 4494); return NS_ERROR_UNEXPECTED; } } while (false)
4491 NS_SUCCEEDED(aNewURI->GetRef(newHash)) &&do { if ((__builtin_expect(!!(!(((bool)(__builtin_expect(!!(!
NS_FAILED_impl(aOldURI->GetRef(oldHash))), 1))) &&
((bool)(__builtin_expect(!!(!NS_FAILED_impl(aNewURI->GetRef
(newHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl
(aOldURI->GetHasRef(&oldHasHash))), 1))) && ((
bool)(__builtin_expect(!!(!NS_FAILED_impl(aNewURI->GetHasRef
(&newHasHash))), 1))) && (oldHasHash != newHasHash
|| !oldHash.Equals(newHash)))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aOldURI->GetRef(oldHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl(aNewURI->GetRef(newHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl(aOldURI->GetHasRef(&oldHasHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl(aNewURI->GetHasRef(&newHasHash))), 1))) && (oldHasHash != newHasHash || !oldHash.Equals(newHash))"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 4494); return NS_ERROR_UNEXPECTED; } } while (false)
4492 NS_SUCCEEDED(aOldURI->GetHasRef(&oldHasHash)) &&do { if ((__builtin_expect(!!(!(((bool)(__builtin_expect(!!(!
NS_FAILED_impl(aOldURI->GetRef(oldHash))), 1))) &&
((bool)(__builtin_expect(!!(!NS_FAILED_impl(aNewURI->GetRef
(newHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl
(aOldURI->GetHasRef(&oldHasHash))), 1))) && ((
bool)(__builtin_expect(!!(!NS_FAILED_impl(aNewURI->GetHasRef
(&newHasHash))), 1))) && (oldHasHash != newHasHash
|| !oldHash.Equals(newHash)))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aOldURI->GetRef(oldHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl(aNewURI->GetRef(newHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl(aOldURI->GetHasRef(&oldHasHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl(aNewURI->GetHasRef(&newHasHash))), 1))) && (oldHasHash != newHasHash || !oldHash.Equals(newHash))"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 4494); return NS_ERROR_UNEXPECTED; } } while (false)
4493 NS_SUCCEEDED(aNewURI->GetHasRef(&newHasHash)) &&do { if ((__builtin_expect(!!(!(((bool)(__builtin_expect(!!(!
NS_FAILED_impl(aOldURI->GetRef(oldHash))), 1))) &&
((bool)(__builtin_expect(!!(!NS_FAILED_impl(aNewURI->GetRef
(newHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl
(aOldURI->GetHasRef(&oldHasHash))), 1))) && ((
bool)(__builtin_expect(!!(!NS_FAILED_impl(aNewURI->GetHasRef
(&newHasHash))), 1))) && (oldHasHash != newHasHash
|| !oldHash.Equals(newHash)))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aOldURI->GetRef(oldHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl(aNewURI->GetRef(newHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl(aOldURI->GetHasRef(&oldHasHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl(aNewURI->GetHasRef(&newHasHash))), 1))) && (oldHasHash != newHasHash || !oldHash.Equals(newHash))"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 4494); return NS_ERROR_UNEXPECTED; } } while (false)
4494 (oldHasHash != newHasHash || !oldHash.Equals(newHash)))do { if ((__builtin_expect(!!(!(((bool)(__builtin_expect(!!(!
NS_FAILED_impl(aOldURI->GetRef(oldHash))), 1))) &&
((bool)(__builtin_expect(!!(!NS_FAILED_impl(aNewURI->GetRef
(newHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl
(aOldURI->GetHasRef(&oldHasHash))), 1))) && ((
bool)(__builtin_expect(!!(!NS_FAILED_impl(aNewURI->GetHasRef
(&newHasHash))), 1))) && (oldHasHash != newHasHash
|| !oldHash.Equals(newHash)))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aOldURI->GetRef(oldHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl(aNewURI->GetRef(newHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl(aOldURI->GetHasRef(&oldHasHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl(aNewURI->GetHasRef(&newHasHash))), 1))) && (oldHasHash != newHasHash || !oldHash.Equals(newHash))"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 4494); return NS_ERROR_UNEXPECTED; } } while (false)
;
4495
4496 nsAutoCString oldSpec, newSpec;
4497 nsresult rv = aOldURI->GetSpec(oldSpec);
4498 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/nsGlobalWindowInner.cpp"
, 4498); return rv; } } while (false)
;
4499 rv = aNewURI->GetSpec(newSpec);
4500 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/nsGlobalWindowInner.cpp"
, 4500); return rv; } } while (false)
;
4501
4502 NS_ConvertUTF8toUTF16 oldWideSpec(oldSpec);
4503 NS_ConvertUTF8toUTF16 newWideSpec(newSpec);
4504
4505 nsCOMPtr<nsIRunnable> callback =
4506 new HashchangeCallback(oldWideSpec, newWideSpec, this);
4507 return Dispatch(callback.forget());
4508}
4509
4510nsresult nsGlobalWindowInner::FireHashchange(const nsAString& aOldURL,
4511 const nsAString& aNewURL) {
4512 // Don't do anything if the window is frozen.
4513 if (IsFrozen()) {
4514 return NS_OK;
4515 }
4516
4517 // Get a presentation shell for use in creating the hashchange event.
4518 NS_ENSURE_STATE(IsCurrentInnerWindow())do { if ((__builtin_expect(!!(!(IsCurrentInnerWindow())), 0))
) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "IsCurrentInnerWindow()"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 4518); return NS_ERROR_UNEXPECTED; } } while (false)
;
4519
4520 HashChangeEventInit init;
4521 init.mNewURL = aNewURL;
4522 init.mOldURL = aOldURL;
4523
4524 RefPtr<HashChangeEvent> event =
4525 HashChangeEvent::Constructor(this, u"hashchange"_ns, init);
4526
4527 event->SetTrusted(true);
4528
4529 ErrorResult rv;
4530 DispatchEvent(*event, rv);
4531 return rv.StealNSResult();
4532}
4533
4534nsresult nsGlobalWindowInner::DispatchSyncPopState() {
4535 NS_ASSERTION(nsContentUtils::IsSafeToRunScript(),do { if (!(nsContentUtils::IsSafeToRunScript())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Must be safe to run script here.", "nsContentUtils::IsSafeToRunScript()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 4536); MOZ_PretendNoReturn(); } } while (0)
4536 "Must be safe to run script here.")do { if (!(nsContentUtils::IsSafeToRunScript())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Must be safe to run script here.", "nsContentUtils::IsSafeToRunScript()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 4536); MOZ_PretendNoReturn(); } } while (0)
;
4537
4538 // Bail if the window is frozen.
4539 if (IsFrozen()) {
4540 return NS_OK;
4541 }
4542
4543 AutoJSAPI jsapi;
4544 bool result = jsapi.Init(this);
4545 NS_ENSURE_TRUE(result, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(result)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "result" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 4545); return NS_ERROR_FAILURE; } } while (false)
;
4546
4547 JSContext* cx = jsapi.cx();
4548
4549 // Get the document's pending state object -- it contains the data we're
4550 // going to send along with the popstate event. The object is serialized
4551 // using structured clone.
4552 JS::Rooted<JS::Value> stateJSValue(cx);
4553 nsresult rv = mDoc->GetStateObject(&stateJSValue);
4554 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/nsGlobalWindowInner.cpp"
, 4554); return rv; } } while (false)
;
4555
4556 if (!JS_WrapValue(cx, &stateJSValue)) {
4557 return NS_ERROR_OUT_OF_MEMORY;
4558 }
4559
4560 RootedDictionary<PopStateEventInit> init(cx);
4561 init.mState = stateJSValue;
4562
4563 RefPtr<PopStateEvent> event =
4564 PopStateEvent::Constructor(this, u"popstate"_ns, init);
4565 event->SetTrusted(true);
4566 event->SetTarget(this);
4567
4568 ErrorResult err;
4569 DispatchEvent(*event, err);
4570 return err.StealNSResult();
4571}
4572
4573//-------------------------------------------------------
4574// Tells the HTMLFrame/CanvasFrame that is now has focus
4575void nsGlobalWindowInner::UpdateCanvasFocus(bool aFocusChanged,
4576 nsIContent* aNewContent) {
4577 // this is called from the inner window so use GetDocShell
4578 nsIDocShell* docShell = GetDocShell();
4579 if (!docShell) return;
4580
4581 bool editable;
4582 docShell->GetEditable(&editable);
4583 if (editable) return;
4584
4585 PresShell* presShell = docShell->GetPresShell();
4586 if (!presShell || !mDoc) {
4587 return;
4588 }
4589
4590 Element* rootElement = mDoc->GetRootElement();
4591 if (rootElement) {
4592 if ((mHasFocus || aFocusChanged) &&
4593 (mFocusedElement == rootElement || aNewContent == rootElement)) {
4594 nsCanvasFrame* canvasFrame = presShell->GetCanvasFrame();
4595 if (canvasFrame) {
4596 canvasFrame->SetHasFocus(mHasFocus && rootElement == aNewContent);
4597 }
4598 }
4599 } else {
4600 // XXXbz I would expect that there is never a canvasFrame in this case...
4601 nsCanvasFrame* canvasFrame = presShell->GetCanvasFrame();
4602 if (canvasFrame) {
4603 canvasFrame->SetHasFocus(false);
4604 }
4605 }
4606}
4607
4608already_AddRefed<nsICSSDeclaration> nsGlobalWindowInner::GetComputedStyle(
4609 Element& aElt, const nsAString& aPseudoElt, ErrorResult& aError) {
4610 return GetComputedStyleHelper(aElt, aPseudoElt, false, aError);
4611}
4612
4613already_AddRefed<nsICSSDeclaration>
4614nsGlobalWindowInner::GetDefaultComputedStyle(Element& aElt,
4615 const nsAString& aPseudoElt,
4616 ErrorResult& aError) {
4617 return GetComputedStyleHelper(aElt, aPseudoElt, true, aError);
4618}
4619
4620already_AddRefed<nsICSSDeclaration> nsGlobalWindowInner::GetComputedStyleHelper(
4621 Element& aElt, const nsAString& aPseudoElt, bool aDefaultStylesOnly,
4622 ErrorResult& aError) {
4623 FORWARD_TO_OUTER_OR_THROW(GetComputedStyleHelperOuter,
4624 (aElt, aPseudoElt, aDefaultStylesOnly, aError),
4625 aError, nullptr);
4626}
4627
4628void nsGlobalWindowInner::MaybeNotifyStorageKeyUsed() {
4629 // Only notify once per window lifetime.
4630 if (hasNotifiedStorageKeyUsed) {
4631 return;
4632 }
4633 nsresult rv =
4634 BounceTrackingStorageObserver::OnInitialStorageAccess(GetWindowContext());
4635 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 4635)
) {
4636 return;
4637 }
4638 hasNotifiedStorageKeyUsed = true;
4639}
4640
4641Storage* nsGlobalWindowInner::GetSessionStorage(ErrorResult& aError) {
4642 nsIPrincipal* principal = GetPrincipal();
4643 nsIPrincipal* storagePrincipal;
4644 if (StaticPrefs::
4645 privacy_partition_always_partition_third_party_non_cookie_storage_exempt_sessionstorage()) {
4646 storagePrincipal = GetEffectiveCookiePrincipal();
4647 } else {
4648 storagePrincipal = GetEffectiveStoragePrincipal();
4649 }
4650 BrowsingContext* browsingContext = GetBrowsingContext();
4651
4652 if (!principal || !storagePrincipal || !browsingContext ||
4653 !Storage::StoragePrefIsEnabled()) {
4654 return nullptr;
4655 }
4656
4657 if (mSessionStorage) {
4658 MOZ_LOG(gDOMLeakPRLogInner, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogInner
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsGlobalWindowInner %p has %p sessionStorage"
, this, mSessionStorage.get()); } } while (0)
4659 ("nsGlobalWindowInner %p has %p sessionStorage", this,do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogInner
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsGlobalWindowInner %p has %p sessionStorage"
, this, mSessionStorage.get()); } } while (0)
4660 mSessionStorage.get()))do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogInner
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsGlobalWindowInner %p has %p sessionStorage"
, this, mSessionStorage.get()); } } while (0)
;
4661 bool canAccess =
4662 principal->Subsumes(mSessionStorage->Principal()) &&
4663 storagePrincipal->Subsumes(mSessionStorage->StoragePrincipal());
4664 if (!canAccess) {
4665 mSessionStorage = nullptr;
4666 }
4667 }
4668
4669 if (!mSessionStorage) {
4670 nsString documentURI;
4671 if (mDoc) {
4672 aError = mDoc->GetDocumentURI(documentURI);
4673 if (NS_WARN_IF(aError.Failed())NS_warn_if_impl(aError.Failed(), "aError.Failed()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 4673)
) {
4674 return nullptr;
4675 }
4676 }
4677
4678 if (!mDoc) {
4679 aError.Throw(NS_ERROR_FAILURE);
4680 return nullptr;
4681 }
4682
4683 // If the document's sandboxed origin flag is set, then accessing
4684 // sessionStorage is prohibited.
4685 if (mDoc->GetSandboxFlags() & SANDBOXED_ORIGIN) {
4686 aError.ThrowSecurityError(
4687 "Forbidden in a sandboxed document without the 'allow-same-origin' "
4688 "flag.");
4689 return nullptr;
4690 }
4691
4692 uint32_t rejectedReason = 0;
4693 StorageAccess access = StorageAllowedForWindow(this, &rejectedReason);
4694
4695 // SessionStorage is an ephemeral per-tab per-origin storage that only lives
4696 // as long as the tab is open, although it may survive browser restarts
4697 // thanks to the session store. So we interpret storage access differently
4698 // than we would for persistent per-origin storage like LocalStorage and so
4699 // it may be okay to provide SessionStorage even when we receive a value of
4700 // eDeny.
4701 //
4702 // ContentBlocking::ShouldAllowAccessFor will return false for 3 main
4703 // reasons.
4704 //
4705 // 1. Cookies are entirely blocked due to a per-origin permission
4706 // (nsICookiePermission::ACCESS_DENY for the top-level principal or this
4707 // window's principal) or the very broad BEHAVIOR_REJECT. This will return
4708 // eDeny with a reason of STATE_COOKIES_BLOCKED_BY_PERMISSION or
4709 // STATE_COOKIES_BLOCKED_ALL.
4710 //
4711 // 2. Third-party cookies are limited via BEHAVIOR_REJECT_FOREIGN and
4712 // BEHAVIOR_LIMIT_FOREIGN and this is a third-party window. This will return
4713 // eDeny with a reason of STATE_COOKIES_BLOCKED_FOREIGN.
4714 //
4715 // 3. Tracking protection (BEHAVIOR_REJECT_TRACKER and
4716 // BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN) is in effect and
4717 // IsThirdPartyTrackingResourceWindow() returned true and there wasn't a
4718 // permission that allows it. This will return ePartitionTrackersOrDeny with
4719 // a reason of STATE_COOKIES_BLOCKED_TRACKER or
4720 // STATE_COOKIES_BLOCKED_SOCIALTRACKER.
4721 //
4722 // In the 1st case, the user has explicitly indicated that they don't want
4723 // to allow any storage to the origin or all origins and so we throw an
4724 // error and deny access to SessionStorage. In the 2nd case, a legacy
4725 // decision reasoned that there's no harm in providing SessionStorage
4726 // because the information is not durable and cannot escape the current tab.
4727 // The rationale is similar for the 3rd case.
4728 if (access == StorageAccess::eDeny &&
4729 rejectedReason !=
4730 nsIWebProgressListener::STATE_COOKIES_BLOCKED_FOREIGN) {
4731 aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
4732 return nullptr;
4733 }
4734
4735 const RefPtr<SessionStorageManager> storageManager =
4736 browsingContext->GetSessionStorageManager();
4737 if (!storageManager) {
4738 aError.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
4739 return nullptr;
4740 }
4741
4742 RefPtr<Storage> storage;
4743 aError = storageManager->CreateStorage(this, principal, storagePrincipal,
4744 documentURI, IsPrivateBrowsing(),
4745 getter_AddRefs(storage));
4746 if (aError.Failed()) {
4747 return nullptr;
4748 }
4749
4750 mSessionStorage = storage;
4751 MOZ_ASSERT(mSessionStorage)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mSessionStorage)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mSessionStorage))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("mSessionStorage"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 4751); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mSessionStorage"
")"); do { *((volatile int*)__null) = 4751; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4752
4753 MOZ_LOG(gDOMLeakPRLogInner, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogInner
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsGlobalWindowInner %p tried to get a new sessionStorage %p"
, this, mSessionStorage.get()); } } while (0)
4754 ("nsGlobalWindowInner %p tried to get a new sessionStorage %p",do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogInner
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsGlobalWindowInner %p tried to get a new sessionStorage %p"
, this, mSessionStorage.get()); } } while (0)
4755 this, mSessionStorage.get()))do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogInner
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsGlobalWindowInner %p tried to get a new sessionStorage %p"
, this, mSessionStorage.get()); } } while (0)
;
4756
4757 if (!mSessionStorage) {
4758 aError.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
4759 return nullptr;
4760 }
4761 }
4762
4763 MaybeNotifyStorageKeyUsed();
4764
4765 MOZ_LOG(gDOMLeakPRLogInner, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogInner
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsGlobalWindowInner %p returns %p sessionStorage"
, this, mSessionStorage.get()); } } while (0)
4766 ("nsGlobalWindowInner %p returns %p sessionStorage", this,do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogInner
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsGlobalWindowInner %p returns %p sessionStorage"
, this, mSessionStorage.get()); } } while (0)
4767 mSessionStorage.get()))do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogInner
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsGlobalWindowInner %p returns %p sessionStorage"
, this, mSessionStorage.get()); } } while (0)
;
4768
4769 return mSessionStorage;
4770}
4771
4772Storage* nsGlobalWindowInner::GetLocalStorage(ErrorResult& aError) {
4773 if (!Storage::StoragePrefIsEnabled()) {
4774 return nullptr;
4775 }
4776
4777 // If the document's sandboxed origin flag is set, then accessing localStorage
4778 // is prohibited.
4779 if (mDoc && mDoc->GetSandboxFlags() & SANDBOXED_ORIGIN) {
4780 aError.ThrowSecurityError(
4781 "Forbidden in a sandboxed document without the 'allow-same-origin' "
4782 "flag.");
4783 return nullptr;
4784 }
4785
4786 // LocalStorage needs to be exposed in every context except for sandboxes and
4787 // NullPrincipals (data: URLs, for instance). But we need to keep data
4788 // separate in some scenarios: private-browsing and partitioned trackers.
4789 // In private-browsing, LocalStorage keeps data in memory, and it shares
4790 // StorageEvents just with other origins in the same private-browsing
4791 // environment.
4792 // For Partitioned Trackers, we expose a partitioned LocalStorage, which
4793 // doesn't share data with other contexts, and it's just in memory.
4794 // Partitioned localStorage is available only for trackers listed in the
4795 // privacy.restrict3rdpartystorage.partitionedHosts pref. See
4796 // nsContentUtils::IsURIInPrefList to know the syntax for the pref value.
4797 // This is a temporary web-compatibility hack.
4798
4799 StorageAccess access = StorageAllowedForWindow(this);
4800
4801 // We allow partitioned localStorage only to some hosts.
4802 bool isolated = false;
4803 if (ShouldPartitionStorage(access)) {
4804 if (!mDoc) {
4805 access = StorageAccess::eDeny;
4806 } else if (!StoragePartitioningEnabled(access, mDoc->CookieJarSettings())) {
4807 static const char* kPrefName =
4808 "privacy.restrict3rdpartystorage.partitionedHosts";
4809
4810 bool isInList = false;
4811 mDoc->NodePrincipal()->IsURIInPrefList(kPrefName, &isInList);
4812 if (!isInList) {
4813 access = StorageAccess::eDeny;
4814 } else {
4815 isolated = true;
4816 }
4817 }
4818 }
4819
4820 if (access == StorageAccess::eDeny) {
4821 aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
4822 return nullptr;
4823 }
4824
4825 nsCOMPtr<nsICookieJarSettings> cookieJarSettings;
4826 if (mDoc) {
4827 cookieJarSettings = mDoc->CookieJarSettings();
4828 } else {
4829 cookieJarSettings = net::CookieJarSettings::GetBlockingAll(
4830 ShouldResistFingerprinting(RFPTarget::IsAlwaysEnabledForPrecompute));
4831 }
4832
4833 // Note that this behavior is observable: if we grant storage permission to a
4834 // tracker, we pass from the partitioned LocalStorage (or a partitioned cookie
4835 // jar) to the 'normal' one. The previous data is lost and the 2
4836 // window.localStorage objects, before and after the permission granted, will
4837 // be different.
4838 if (mLocalStorage) {
4839 if ((mLocalStorage->Type() == (isolated ? Storage::ePartitionedLocalStorage
4840 : Storage::eLocalStorage)) &&
4841 (mLocalStorage->StoragePrincipal() == GetEffectiveStoragePrincipal())) {
4842 return mLocalStorage;
4843 }
4844
4845 // storage needs change
4846 mLocalStorage = nullptr;
4847 }
4848
4849 MOZ_ASSERT(!mLocalStorage)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mLocalStorage)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mLocalStorage))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!mLocalStorage"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 4849); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mLocalStorage"
")"); do { *((volatile int*)__null) = 4849; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4850
4851 if (!isolated) {
4852 RefPtr<Storage> storage;
4853
4854 if (NextGenLocalStorageEnabled()) {
4855 aError = LSObject::CreateForWindow(this, getter_AddRefs(storage));
4856 } else {
4857 nsresult rv;
4858 nsCOMPtr<nsIDOMStorageManager> storageManager =
4859 do_GetService("@mozilla.org/dom/localStorage-manager;1", &rv);
4860 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4861 aError.Throw(rv);
4862 return nullptr;
4863 }
4864
4865 nsString documentURI;
4866 if (mDoc) {
4867 aError = mDoc->GetDocumentURI(documentURI);
4868 if (NS_WARN_IF(aError.Failed())NS_warn_if_impl(aError.Failed(), "aError.Failed()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 4868)
) {
4869 return nullptr;
4870 }
4871 }
4872
4873 nsIPrincipal* principal = GetPrincipal();
4874 if (!principal) {
4875 aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
4876 return nullptr;
4877 }
4878
4879 nsIPrincipal* storagePrincipal = GetEffectiveStoragePrincipal();
4880 if (!storagePrincipal) {
4881 aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
4882 return nullptr;
4883 }
4884
4885 aError = storageManager->CreateStorage(this, principal, storagePrincipal,
4886 documentURI, IsPrivateBrowsing(),
4887 getter_AddRefs(storage));
4888 }
4889
4890 if (aError.Failed()) {
4891 return nullptr;
4892 }
4893
4894 mLocalStorage = storage;
4895 } else {
4896 nsresult rv;
4897 nsCOMPtr<nsIDOMSessionStorageManager> storageManager =
4898 do_GetService("@mozilla.org/dom/sessionStorage-manager;1", &rv);
4899 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4900 aError.Throw(rv);
4901 return nullptr;
4902 }
4903
4904 nsIPrincipal* principal = GetPrincipal();
4905 if (!principal) {
4906 aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
4907 return nullptr;
4908 }
4909
4910 nsIPrincipal* storagePrincipal = GetEffectiveStoragePrincipal();
4911 if (!storagePrincipal) {
4912 aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
4913 return nullptr;
4914 }
4915
4916 RefPtr<SessionStorageCache> cache;
4917 if (isolated) {
4918 cache = new SessionStorageCache();
4919 } else {
4920 // This will clone the session storage if it exists.
4921 rv = storageManager->GetSessionStorageCache(principal, storagePrincipal,
4922 &cache);
4923 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4924 aError.Throw(rv);
4925 return nullptr;
4926 }
4927 }
4928
4929 mLocalStorage =
4930 new PartitionedLocalStorage(this, principal, storagePrincipal, cache);
4931 }
4932
4933 MaybeNotifyStorageKeyUsed();
4934
4935 MOZ_ASSERT(mLocalStorage)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLocalStorage)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mLocalStorage))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("mLocalStorage",
"/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 4935); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLocalStorage"
")"); do { *((volatile int*)__null) = 4935; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4936 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLocalStorage->Type() == (isolated ? Storage::ePartitionedLocalStorage
: Storage::eLocalStorage))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mLocalStorage->Type() == (
isolated ? Storage::ePartitionedLocalStorage : Storage::eLocalStorage
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mLocalStorage->Type() == (isolated ? Storage::ePartitionedLocalStorage : Storage::eLocalStorage)"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 4938); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLocalStorage->Type() == (isolated ? Storage::ePartitionedLocalStorage : Storage::eLocalStorage)"
")"); do { *((volatile int*)__null) = 4938; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4937 mLocalStorage->Type() ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLocalStorage->Type() == (isolated ? Storage::ePartitionedLocalStorage
: Storage::eLocalStorage))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mLocalStorage->Type() == (
isolated ? Storage::ePartitionedLocalStorage : Storage::eLocalStorage
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mLocalStorage->Type() == (isolated ? Storage::ePartitionedLocalStorage : Storage::eLocalStorage)"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 4938); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLocalStorage->Type() == (isolated ? Storage::ePartitionedLocalStorage : Storage::eLocalStorage)"
")"); do { *((volatile int*)__null) = 4938; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4938 (isolated ? Storage::ePartitionedLocalStorage : Storage::eLocalStorage))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLocalStorage->Type() == (isolated ? Storage::ePartitionedLocalStorage
: Storage::eLocalStorage))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mLocalStorage->Type() == (
isolated ? Storage::ePartitionedLocalStorage : Storage::eLocalStorage
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mLocalStorage->Type() == (isolated ? Storage::ePartitionedLocalStorage : Storage::eLocalStorage)"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 4938); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLocalStorage->Type() == (isolated ? Storage::ePartitionedLocalStorage : Storage::eLocalStorage)"
")"); do { *((volatile int*)__null) = 4938; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4939 return mLocalStorage;
4940}
4941
4942IDBFactory* nsGlobalWindowInner::GetIndexedDB(JSContext* aCx,
4943 ErrorResult& aError) {
4944 if (!mIndexedDB) {
4945 // This may keep mIndexedDB null without setting an error.
4946 auto res = IDBFactory::CreateForWindow(this);
4947 if (res.isErr()) {
4948 aError = res.unwrapErr();
4949 } else {
4950 mIndexedDB = res.unwrap();
4951 }
4952 }
4953
4954 MaybeNotifyStorageKeyUsed();
4955
4956 return mIndexedDB;
4957}
4958
4959//*****************************************************************************
4960// nsGlobalWindowInner::nsIInterfaceRequestor
4961//*****************************************************************************
4962
4963NS_IMETHODIMPnsresult
4964nsGlobalWindowInner::GetInterface(const nsIID& aIID, void** aSink) {
4965 nsGlobalWindowOuter* outer = GetOuterWindowInternal();
4966 NS_ENSURE_TRUE(outer, NS_ERROR_NOT_INITIALIZED)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/nsGlobalWindowInner.cpp"
, 4966); return NS_ERROR_NOT_INITIALIZED; } } while (false)
;
4967
4968 nsresult rv = outer->GetInterfaceInternal(aIID, aSink);
4969 if (rv == NS_ERROR_NO_INTERFACE) {
4970 return QueryInterface(aIID, aSink);
4971 }
4972 return rv;
4973}
4974
4975void nsGlobalWindowInner::GetInterface(JSContext* aCx,
4976 JS::Handle<JS::Value> aIID,
4977 JS::MutableHandle<JS::Value> aRetval,
4978 ErrorResult& aError) {
4979 dom::GetInterface(aCx, this, aIID, aRetval, aError);
4980}
4981
4982already_AddRefed<CacheStorage> nsGlobalWindowInner::GetCaches(
4983 ErrorResult& aRv) {
4984 if (!mCacheStorage) {
4985 bool forceTrustedOrigin =
4986 GetBrowsingContext() &&
4987 GetBrowsingContext()->Top()->GetServiceWorkersTestingEnabled();
4988 mCacheStorage = CacheStorage::CreateOnMainThread(
4989 cache::DEFAULT_NAMESPACE, this, GetEffectiveStoragePrincipal(),
4990 forceTrustedOrigin, aRv);
4991 }
4992
4993 RefPtr<CacheStorage> ref = mCacheStorage;
4994 return ref.forget();
4995}
4996
4997void nsGlobalWindowInner::FireOfflineStatusEventIfChanged() {
4998 if (!IsCurrentInnerWindow()) return;
4999
5000 // Don't fire an event if the status hasn't changed
5001 if (mWasOffline == NS_IsOffline()) {
5002 return;
5003 }
5004
5005 mWasOffline = !mWasOffline;
5006
5007 nsAutoString name;
5008 if (mWasOffline) {
5009 name.AssignLiteral("offline");
5010 } else {
5011 name.AssignLiteral("online");
5012 }
5013 nsContentUtils::DispatchTrustedEvent(mDoc, this, name, CanBubble::eNo,
5014 Cancelable::eNo);
5015}
5016
5017nsGlobalWindowInner::SlowScriptResponse
5018nsGlobalWindowInner::ShowSlowScriptDialog(JSContext* aCx,
5019 const nsString& aAddonId,
5020 const double aDuration) {
5021 nsresult rv;
5022
5023 if (Preferences::GetBool("dom.always_stop_slow_scripts")) {
1
Assuming the condition is false
2
Taking false branch
5024 return KillSlowScript;
5025 }
5026
5027 // If it isn't safe to run script, then it isn't safe to bring up the prompt
5028 // (since that spins the event loop). In that (rare) case, we just kill the
5029 // script and report a warning.
5030 if (!nsContentUtils::IsSafeToRunScript()) {
3
Assuming the condition is false
4
Taking false branch
5031 JS::WarnASCII(aCx, "A long running script was terminated");
5032 return KillSlowScript;
5033 }
5034
5035 // If our document is not active, just kill the script: we've been unloaded
5036 if (!HasActiveDocument()) {
5
Assuming the condition is false
6
Taking false branch
5037 return KillSlowScript;
5038 }
5039
5040 // Check if we should offer the option to debug
5041 JS::AutoFilename filename;
5042 uint32_t lineno;
7
'lineno' declared without an initial value
5043 // Computing the line number can be very expensive (see bug 1330231 for
5044 // example), and we don't use the line number anywhere except than in the
5045 // parent process, so we avoid computing it elsewhere. This gives us most of
5046 // the wins we are interested in, since the source of the slowness here is
5047 // minified scripts which is more common in Web content that is loaded in the
5048 // content process.
5049 uint32_t* linenop = XRE_IsParentProcess() ? &lineno : nullptr;
8
Assuming the condition is false
9
'?' condition is false
5050 bool hasFrame = JS::DescribeScriptedCaller(aCx, &filename, linenop);
5051
5052 // Record the slow script event if we haven't done so already for this inner
5053 // window (which represents a particular page to the user).
5054 if (!mHasHadSlowScript) {
10
Assuming field 'mHasHadSlowScript' is true
11
Taking false branch
5055 Telemetry::Accumulate(Telemetry::SLOW_SCRIPT_PAGE_COUNT, 1);
5056 }
5057 mHasHadSlowScript = true;
5058
5059 // Override the cursor to something that we're sure the user can see.
5060 SetCursor("auto"_ns, IgnoreErrors());
5061
5062 if (XRE_IsContentProcess() && ProcessHangMonitor::Get()) {
12
Assuming the condition is false
5063 ProcessHangMonitor::SlowScriptAction action;
5064 RefPtr<ProcessHangMonitor> monitor = ProcessHangMonitor::Get();
5065 nsIDocShell* docShell = GetDocShell();
5066 nsCOMPtr<nsIBrowserChild> child =
5067 docShell ? docShell->GetBrowserChild() : nullptr;
5068 action =
5069 monitor->NotifySlowScript(child, filename.get(), aAddonId, aDuration);
5070 if (action == ProcessHangMonitor::Terminate) {
5071 return KillSlowScript;
5072 }
5073
5074 if (action == ProcessHangMonitor::StartDebugger) {
5075 // Spin a nested event loop so that the debugger in the parent can fetch
5076 // any information it needs. Once the debugger has started, return to the
5077 // script.
5078 RefPtr<nsGlobalWindowOuter> outer = GetOuterWindowInternal();
5079 outer->EnterModalState();
5080 SpinEventLoopUntil("nsGlobalWindowInner::ShowSlowScriptDialog"_ns, [&]() {
5081 return monitor->IsDebuggerStartupComplete();
5082 });
5083 outer->LeaveModalState();
5084 return ContinueSlowScript;
5085 }
5086
5087 return ContinueSlowScriptAndKeepNotifying;
5088 }
5089
5090 // Reached only on non-e10s - once per slow script dialog.
5091 // On e10s - we probe once at ProcessHangsMonitor.sys.mjs
5092 Telemetry::Accumulate(Telemetry::SLOW_SCRIPT_NOTICE_COUNT, 1);
5093
5094 // Get the nsIPrompt interface from the docshell
5095 nsCOMPtr<nsIDocShell> ds = GetDocShell();
5096 NS_ENSURE_TRUE(ds, KillSlowScript)do { if ((__builtin_expect(!!(!(ds)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "ds" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 5096); return KillSlowScript; } } while (false)
;
13
Taking false branch
14
Loop condition is false. Exiting loop
5097 nsCOMPtr<nsIPrompt> prompt = do_GetInterface(ds);
5098 NS_ENSURE_TRUE(prompt, KillSlowScript)do { if ((__builtin_expect(!!(!(prompt)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "prompt" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 5098); return KillSlowScript; } } while (false)
;
15
Taking false branch
16
Loop condition is false. Exiting loop
5099
5100 // Prioritize the SlowScriptDebug interface over JSD1.
5101 nsCOMPtr<nsISlowScriptDebugCallback> debugCallback;
5102
5103 if (hasFrame) {
17
Assuming 'hasFrame' is false
18
Taking false branch
5104 const char* debugCID = "@mozilla.org/dom/slow-script-debug;1";
5105 nsCOMPtr<nsISlowScriptDebug> debugService = do_GetService(debugCID, &rv);
5106 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5107 debugService->GetActivationHandler(getter_AddRefs(debugCallback));
5108 }
5109 }
5110
5111 bool failed = false;
5112 auto getString = [&](const char* name,
5113 nsContentUtils::PropertiesFile propFile =
5114 nsContentUtils::eDOM_PROPERTIES) {
5115 nsAutoString result;
5116 nsresult rv = nsContentUtils::GetLocalizedString(propFile, name, result);
5117
5118 // GetStringFromName can return NS_OK and still give nullptr string
5119 failed = failed || NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || result.IsEmpty();
23
Assuming 'failed' is false
24
Assuming the condition is true
25
Value assigned to 'failed', which participates in a condition later
5120 return result;
5121 };
5122
5123 bool isAddonScript = !aAddonId.IsEmpty();
19
Assuming the condition is false
5124 bool showDebugButton = debugCallback && !isAddonScript;
5125
5126 // Get localizable strings
5127
5128 nsAutoString title, checkboxMsg, debugButton, msg;
5129 if (isAddonScript
19.1
'isAddonScript' is false
) {
20
Taking false branch
5130 title = getString("KillAddonScriptTitle");
5131 checkboxMsg = getString("KillAddonScriptGlobalMessage");
5132
5133 auto appName =
5134 getString("brandShortName", nsContentUtils::eBRAND_PROPERTIES);
5135
5136 nsCOMPtr<nsIAddonPolicyService> aps =
5137 do_GetService("@mozilla.org/addons/policy-service;1");
5138 nsString addonName;
5139 if (!aps || NS_FAILED(aps->GetExtensionName(aAddonId, addonName))((bool)(__builtin_expect(!!(NS_FAILED_impl(aps->GetExtensionName
(aAddonId, addonName))), 0)))
) {
5140 addonName = aAddonId;
5141 }
5142
5143 rv = nsContentUtils::FormatLocalizedString(
5144 msg, nsContentUtils::eDOM_PROPERTIES, "KillAddonScriptMessage",
5145 addonName, appName);
5146
5147 failed = failed || NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)));
5148 } else {
5149 title = getString("KillScriptTitle");
5150 checkboxMsg = getString("DontAskAgain");
5151
5152 if (showDebugButton
20.1
'showDebugButton' is false
) {
21
Taking false branch
5153 debugButton = getString("DebugScriptButton");
5154 msg = getString("KillScriptWithDebugMessage");
5155 } else {
5156 msg = getString("KillScriptMessage");
5157 }
5158 }
5159
5160 auto stopButton = getString("StopScriptButton");
5161 auto waitButton = getString("WaitForScriptButton");
22
Calling 'operator()'
26
Returning from 'operator()'
5162
5163 if (failed) {
27
Assuming 'failed' is false
28
Taking false branch
5164 NS_ERROR("Failed to get localized strings.")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "Failed to get localized strings."
, "Error", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 5164); MOZ_PretendNoReturn(); } while (0)
;
5165 return ContinueSlowScript;
5166 }
5167
5168 // Append file and line number information, if available
5169 if (filename.get()) {
29
Assuming the condition is true
30
Taking true branch
5170 nsAutoString scriptLocation;
5171 // We want to drop the middle part of too-long locations. We'll
5172 // define "too-long" as longer than 60 UTF-16 code units. Just
5173 // have to be a bit careful about unpaired surrogates.
5174 NS_ConvertUTF8toUTF16 filenameUTF16(filename.get());
5175 if (filenameUTF16.Length() > 60) {
31
Assuming the condition is false
32
Taking false branch
5176 // XXXbz Do we need to insert any bidi overrides here?
5177 size_t cutStart = 30;
5178 size_t cutLength = filenameUTF16.Length() - 60;
5179 MOZ_ASSERT(cutLength > 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(cutLength > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(cutLength > 0))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("cutLength > 0"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 5179); AnnotateMozCrashReason("MOZ_ASSERT" "(" "cutLength > 0"
")"); do { *((volatile int*)__null) = 5179; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5180 if (NS_IS_LOW_SURROGATE(filenameUTF16[cutStart])((uint32_t(filenameUTF16[cutStart]) & 0xFFFFFC00) == 0xDC00
)
) {
5181 // Don't truncate before the low surrogate, in case it's preceded by a
5182 // high surrogate and forms a single Unicode character. Instead, just
5183 // include the low surrogate.
5184 ++cutStart;
5185 --cutLength;
5186 }
5187 if (NS_IS_LOW_SURROGATE(filenameUTF16[cutStart + cutLength])((uint32_t(filenameUTF16[cutStart + cutLength]) & 0xFFFFFC00
) == 0xDC00)
) {
5188 // Likewise, don't drop a trailing low surrogate here. We want to
5189 // increase cutLength, since it might be 0 already so we can't very well
5190 // decrease it.
5191 ++cutLength;
5192 }
5193
5194 // Insert U+2026 HORIZONTAL ELLIPSIS
5195 filenameUTF16.ReplaceLiteral(cutStart, cutLength, u"\x2026");
5196 }
5197 rv = nsContentUtils::FormatLocalizedString(
5198 scriptLocation, nsContentUtils::eDOM_PROPERTIES, "KillScriptLocation",
5199 filenameUTF16);
5200
5201 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
33
Assuming the condition is true
34
Taking true branch
5202 msg.AppendLiteral("\n\n");
5203 msg.Append(scriptLocation);
5204 msg.Append(':');
5205 msg.AppendInt(lineno);
35
1st function call argument is an uninitialized value
5206 }
5207 }
5208
5209 uint32_t buttonFlags = nsIPrompt::BUTTON_POS_1_DEFAULT +
5210 (nsIPrompt::BUTTON_TITLE_IS_STRING *
5211 (nsIPrompt::BUTTON_POS_0 + nsIPrompt::BUTTON_POS_1));
5212
5213 // Add a third button if necessary.
5214 if (showDebugButton)
5215 buttonFlags += nsIPrompt::BUTTON_TITLE_IS_STRING * nsIPrompt::BUTTON_POS_2;
5216
5217 bool checkboxValue = false;
5218 int32_t buttonPressed = 0; // In case the user exits dialog by clicking X.
5219 {
5220 // Null out the operation callback while we're re-entering JS here.
5221 AutoDisableJSInterruptCallback disabler(aCx);
5222
5223 // Open the dialog.
5224 rv = prompt->ConfirmEx(
5225 title.get(), msg.get(), buttonFlags, waitButton.get(), stopButton.get(),
5226 debugButton.get(), checkboxMsg.get(), &checkboxValue, &buttonPressed);
5227 }
5228
5229 if (buttonPressed == 0) {
5230 if (checkboxValue && !isAddonScript && NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))))
5231 return AlwaysContinueSlowScript;
5232 return ContinueSlowScript;
5233 }
5234
5235 if (buttonPressed == 2) {
5236 MOZ_RELEASE_ASSERT(debugCallback)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(debugCallback)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(debugCallback))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("debugCallback",
"/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 5236); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "debugCallback"
")"); do { *((volatile int*)__null) = 5236; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5237
5238 rv = debugCallback->HandleSlowScriptDebug(this);
5239 return NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) ? ContinueSlowScript : KillSlowScript;
5240 }
5241
5242 JS_ClearPendingException(aCx);
5243
5244 return KillSlowScript;
5245}
5246
5247nsresult nsGlobalWindowInner::Observe(nsISupports* aSubject, const char* aTopic,
5248 const char16_t* aData) {
5249 if (!nsCRT::strcmp(aTopic, NS_IOSERVICE_OFFLINE_STATUS_TOPIC"network:offline-status-changed")) {
5250 if (!IsFrozen()) {
5251 // Fires an offline status event if the offline status has changed
5252 FireOfflineStatusEventIfChanged();
5253 }
5254 return NS_OK;
5255 }
5256
5257 if (!nsCRT::strcmp(aTopic, MEMORY_PRESSURE_OBSERVER_TOPIC"memory-pressure")) {
5258 if (mPerformance) {
5259 mPerformance->MemoryPressure();
5260 }
5261 RemoveReportRecords();
5262 return NS_OK;
5263 }
5264
5265 if (!nsCRT::strcmp(aTopic, PERMISSION_CHANGED_TOPIC"perm-changed")) {
5266 nsCOMPtr<nsIPermission> perm(do_QueryInterface(aSubject));
5267 if (!perm) {
5268 // A null permission indicates that the entire permission list
5269 // was cleared.
5270 MOZ_ASSERT(!nsCRT::strcmp(aData, u"cleared"))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!nsCRT::strcmp(aData, u"cleared"))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!nsCRT::strcmp(aData, u"cleared"
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!nsCRT::strcmp(aData, u\"cleared\")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 5270); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!nsCRT::strcmp(aData, u\"cleared\")"
")"); do { *((volatile int*)__null) = 5270; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5271 UpdatePermissions();
5272 return NS_OK;
5273 }
5274
5275 nsAutoCString type;
5276 perm->GetType(type);
5277 if (type == "autoplay-media"_ns) {
5278 UpdateAutoplayPermission();
5279 } else if (type == "shortcuts"_ns) {
5280 UpdateShortcutsPermission();
5281 } else if (type == "popup"_ns) {
5282 UpdatePopupPermission();
5283 }
5284
5285 if (!mDoc) {
5286 return NS_OK;
5287 }
5288
5289 RefPtr<PermissionDelegateHandler> permDelegateHandler =
5290 mDoc->GetPermissionDelegateHandler();
5291
5292 if (permDelegateHandler) {
5293 permDelegateHandler->UpdateDelegatedPermission(type);
5294 }
5295
5296 return NS_OK;
5297 }
5298
5299 if (!nsCRT::strcmp(aTopic, "screen-information-changed")) {
5300 if (mScreen) {
5301 if (RefPtr<ScreenOrientation> orientation =
5302 mScreen->GetOrientationIfExists()) {
5303 orientation->MaybeChanged();
5304 }
5305 }
5306 if (mHasOrientationChangeListeners) {
5307 int32_t oldAngle = mOrientationAngle;
5308 mOrientationAngle = Orientation(CallerType::System);
5309 if (mOrientationAngle != oldAngle && IsCurrentInnerWindow()) {
5310 nsCOMPtr<nsPIDOMWindowOuter> outer = GetOuterWindow();
5311 outer->DispatchCustomEvent(u"orientationchange"_ns);
5312 }
5313 }
5314 return NS_OK;
5315 }
5316
5317 if (!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID"nsPref:changed")) {
5318 MOZ_ASSERT(!NS_strcmp(aData, u"intl.accept_languages"))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!NS_strcmp(aData, u"intl.accept_languages"))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!NS_strcmp(aData, u"intl.accept_languages")))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!NS_strcmp(aData, u\"intl.accept_languages\")"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 5318); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_strcmp(aData, u\"intl.accept_languages\")"
")"); do { *((volatile int*)__null) = 5318; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5319
5320 // The user preferred languages have changed, we need to fire an event on
5321 // Window object and invalidate the cache for navigator.languages. It is
5322 // done for every change which can be a waste of cycles but those should be
5323 // fairly rare.
5324 // We MUST invalidate navigator.languages before sending the event in the
5325 // very likely situation where an event handler will try to read its value.
5326
5327 if (mNavigator) {
5328 Navigator_Binding::ClearCachedLanguageValue(mNavigator);
5329 Navigator_Binding::ClearCachedLanguagesValue(mNavigator);
5330 }
5331
5332 // The event has to be dispatched only to the current inner window.
5333 if (!IsCurrentInnerWindow()) {
5334 return NS_OK;
5335 }
5336
5337 RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
5338 event->InitEvent(u"languagechange"_ns, false, false);
5339 event->SetTrusted(true);
5340
5341 ErrorResult rv;
5342 DispatchEvent(*event, rv);
5343 return rv.StealNSResult();
5344 }
5345
5346 NS_WARNING("unrecognized topic in nsGlobalWindowInner::Observe")NS_DebugBreak(NS_DEBUG_WARNING, "unrecognized topic in nsGlobalWindowInner::Observe"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 5346)
;
5347 return NS_ERROR_FAILURE;
5348}
5349
5350void nsGlobalWindowInner::ObserveStorageNotification(
5351 StorageEvent* aEvent, const char16_t* aStorageType, bool aPrivateBrowsing) {
5352 MOZ_ASSERT(aEvent)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEvent)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aEvent))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aEvent", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 5352); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent" ")"
); do { *((volatile int*)__null) = 5352; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5353
5354 // The private browsing check must be done here again because this window
5355 // could have changed its state before the notification check and now. This
5356 // happens in case this window did have a docShell at that time.
5357 if (aPrivateBrowsing != IsPrivateBrowsing()) {
5358 return;
5359 }
5360
5361 // LocalStorage can only exist on an inner window, and we don't want to
5362 // generate events on frozen or otherwise-navigated-away from windows.
5363 // (Actually, this code used to try and buffer events for frozen windows,
5364 // but it never worked, so we've removed it. See bug 1285898.)
5365 if (!IsCurrentInnerWindow() || IsFrozen()) {
5366 return;
5367 }
5368
5369 nsIPrincipal* principal = GetPrincipal();
5370 if (!principal) {
5371 return;
5372 }
5373
5374 bool fireMozStorageChanged = false;
5375 nsAutoString eventType;
5376 eventType.AssignLiteral("storage");
5377
5378 if (!NS_strcmp(aStorageType, u"sessionStorage")) {
5379 RefPtr<Storage> changingStorage = aEvent->GetStorageArea();
5380 MOZ_ASSERT(changingStorage)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(changingStorage)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(changingStorage))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("changingStorage"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 5380); AnnotateMozCrashReason("MOZ_ASSERT" "(" "changingStorage"
")"); do { *((volatile int*)__null) = 5380; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5381
5382 bool check = false;
5383
5384 if (const RefPtr<SessionStorageManager> storageManager =
5385 GetBrowsingContext()->GetSessionStorageManager()) {
5386 nsresult rv = storageManager->CheckStorage(GetEffectiveStoragePrincipal(),
5387 changingStorage, &check);
5388 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5389 return;
5390 }
5391 }
5392
5393 if (!check) {
5394 // This storage event is not coming from our storage or is coming
5395 // from a different docshell, i.e. it is a clone, ignore this event.
5396 return;
5397 }
5398
5399 MOZ_LOG(do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogInner
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsGlobalWindowInner %p with sessionStorage %p passing event from %p"
, this, mSessionStorage.get(), changingStorage.get()); } } while
(0)
5400 gDOMLeakPRLogInner, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogInner
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsGlobalWindowInner %p with sessionStorage %p passing event from %p"
, this, mSessionStorage.get(), changingStorage.get()); } } while
(0)
5401 ("nsGlobalWindowInner %p with sessionStorage %p passing event from %p",do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogInner
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsGlobalWindowInner %p with sessionStorage %p passing event from %p"
, this, mSessionStorage.get(), changingStorage.get()); } } while
(0)
5402 this, mSessionStorage.get(), changingStorage.get()))do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogInner
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsGlobalWindowInner %p with sessionStorage %p passing event from %p"
, this, mSessionStorage.get(), changingStorage.get()); } } while
(0)
;
5403
5404 fireMozStorageChanged = mSessionStorage == changingStorage;
5405 if (fireMozStorageChanged) {
5406 eventType.AssignLiteral("MozSessionStorageChanged");
5407 }
5408 }
5409
5410 else {
5411 MOZ_ASSERT(!NS_strcmp(aStorageType, u"localStorage"))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!NS_strcmp(aStorageType, u"localStorage"))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!NS_strcmp(aStorageType, u"localStorage")))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("!NS_strcmp(aStorageType, u\"localStorage\")"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 5411); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_strcmp(aStorageType, u\"localStorage\")"
")"); do { *((volatile int*)__null) = 5411; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5412
5413 nsIPrincipal* storagePrincipal = GetEffectiveStoragePrincipal();
5414 if (!storagePrincipal) {
5415 return;
5416 }
5417
5418 MOZ_DIAGNOSTIC_ASSERT(StorageUtils::PrincipalsEqual(aEvent->GetPrincipal(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(StorageUtils::PrincipalsEqual(aEvent->GetPrincipal
(), storagePrincipal))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(StorageUtils::PrincipalsEqual
(aEvent->GetPrincipal(), storagePrincipal)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("StorageUtils::PrincipalsEqual(aEvent->GetPrincipal(), storagePrincipal)"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 5419); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "StorageUtils::PrincipalsEqual(aEvent->GetPrincipal(), storagePrincipal)"
")"); do { *((volatile int*)__null) = 5419; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5419 storagePrincipal))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(StorageUtils::PrincipalsEqual(aEvent->GetPrincipal
(), storagePrincipal))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(StorageUtils::PrincipalsEqual
(aEvent->GetPrincipal(), storagePrincipal)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("StorageUtils::PrincipalsEqual(aEvent->GetPrincipal(), storagePrincipal)"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 5419); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "StorageUtils::PrincipalsEqual(aEvent->GetPrincipal(), storagePrincipal)"
")"); do { *((volatile int*)__null) = 5419; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5420
5421 fireMozStorageChanged =
5422 mLocalStorage && mLocalStorage == aEvent->GetStorageArea();
5423
5424 if (fireMozStorageChanged) {
5425 eventType.AssignLiteral("MozLocalStorageChanged");
5426 }
5427 }
5428
5429 // Clone the storage event included in the observer notification. We want
5430 // to dispatch clones rather than the original event.
5431 IgnoredErrorResult error;
5432 RefPtr<StorageEvent> clonedEvent =
5433 CloneStorageEvent(eventType, aEvent, error);
5434 if (error.Failed() || !clonedEvent) {
5435 return;
5436 }
5437
5438 clonedEvent->SetTrusted(true);
5439
5440 if (fireMozStorageChanged) {
5441 WidgetEvent* internalEvent = clonedEvent->WidgetEventPtr();
5442 internalEvent->mFlags.mOnlyChromeDispatch = true;
5443 }
5444
5445 DispatchEvent(*clonedEvent);
5446}
5447
5448already_AddRefed<StorageEvent> nsGlobalWindowInner::CloneStorageEvent(
5449 const nsAString& aType, const RefPtr<StorageEvent>& aEvent,
5450 ErrorResult& aRv) {
5451 StorageEventInit dict;
5452
5453 dict.mBubbles = aEvent->Bubbles();
5454 dict.mCancelable = aEvent->Cancelable();
5455 aEvent->GetKey(dict.mKey);
5456 aEvent->GetOldValue(dict.mOldValue);
5457 aEvent->GetNewValue(dict.mNewValue);
5458 aEvent->GetUrl(dict.mUrl);
5459
5460 RefPtr<Storage> storageArea = aEvent->GetStorageArea();
5461
5462 RefPtr<Storage> storage;
5463
5464 // If null, this is a localStorage event received by IPC.
5465 if (!storageArea) {
5466 storage = GetLocalStorage(aRv);
5467 if (!NextGenLocalStorageEnabled()) {
5468 if (aRv.Failed() || !storage) {
5469 return nullptr;
5470 }
5471
5472 if (storage->Type() == Storage::eLocalStorage) {
5473 RefPtr<LocalStorage> localStorage =
5474 static_cast<LocalStorage*>(storage.get());
5475
5476 // We must apply the current change to the 'local' localStorage.
5477 localStorage->ApplyEvent(aEvent);
5478 }
5479 }
5480 } else if (storageArea->Type() == Storage::eSessionStorage) {
5481 storage = GetSessionStorage(aRv);
5482 } else {
5483 MOZ_ASSERT(storageArea->Type() == Storage::eLocalStorage)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(storageArea->Type() == Storage::eLocalStorage)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(storageArea->Type() == Storage::eLocalStorage))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("storageArea->Type() == Storage::eLocalStorage"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 5483); AnnotateMozCrashReason("MOZ_ASSERT" "(" "storageArea->Type() == Storage::eLocalStorage"
")"); do { *((volatile int*)__null) = 5483; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5484 storage = GetLocalStorage(aRv);
5485 }
5486
5487 if (aRv.Failed() || !storage) {
5488 return nullptr;
5489 }
5490
5491 if (storage->Type() == Storage::ePartitionedLocalStorage) {
5492 // This error message is not exposed.
5493 aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
5494 return nullptr;
5495 }
5496
5497 MOZ_ASSERT(storage)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(storage)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(storage))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("storage", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 5497); AnnotateMozCrashReason("MOZ_ASSERT" "(" "storage" ")"
); do { *((volatile int*)__null) = 5497; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5498 MOZ_ASSERT_IF(storageArea, storage->IsForkOf(storageArea))do { if (storageArea) { do { static_assert( mozilla::detail::
AssertionConditionType<decltype(storage->IsForkOf(storageArea
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(storage->IsForkOf(storageArea)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("storage->IsForkOf(storageArea)"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 5498); AnnotateMozCrashReason("MOZ_ASSERT" "(" "storage->IsForkOf(storageArea)"
")"); do { *((volatile int*)__null) = 5498; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
5499
5500 dict.mStorageArea = storage;
5501
5502 RefPtr<StorageEvent> event = StorageEvent::Constructor(this, aType, dict);
5503 return event.forget();
5504}
5505
5506void nsGlobalWindowInner::Suspend(bool aIncludeSubWindows) {
5507 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/nsGlobalWindowInner.cpp"
, 5507); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 5507; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5508
5509 // We can only safely suspend windows that are the current inner window. If
5510 // its not the current inner, then we are in one of two different cases.
5511 // Either we are in the bfcache or we are doomed window that is going away.
5512 // When a window becomes inactive we purposely avoid placing already suspended
5513 // windows into the bfcache. It only expects windows suspended due to the
5514 // Freeze() method which occurs while the window is still the current inner.
5515 // So we must not call Suspend() on bfcache windows at this point or this
5516 // invariant will be broken. If the window is doomed there is no point in
5517 // suspending it since it will soon be gone.
5518 if (!IsCurrentInnerWindow()) {
5519 return;
5520 }
5521
5522 // All in-process descendants are also suspended. This ensure mSuspendDepth
5523 // is set properly and the timers are properly canceled for each in-process
5524 // descendant.
5525 if (aIncludeSubWindows) {
5526 CallOnInProcessDescendants(&nsGlobalWindowInner::Suspend, false);
5527 }
5528
5529 mSuspendDepth += 1;
5530 if (mSuspendDepth != 1) {
5531 return;
5532 }
5533
5534 if (mWindowGlobalChild) {
5535 mWindowGlobalChild->BlockBFCacheFor(BFCacheStatus::SUSPENDED);
5536 }
5537
5538 nsCOMPtr<nsIDeviceSensors> ac = do_GetService(NS_DEVICE_SENSORS_CONTRACTID"@mozilla.org/devicesensors;1");
5539 if (ac) {
5540 for (uint32_t i = 0; i < mEnabledSensors.Length(); i++)
5541 ac->RemoveWindowListener(mEnabledSensors[i], this);
5542 }
5543 DisableGamepadUpdates();
5544 DisableVRUpdates();
5545
5546 SuspendWorkersForWindow(*this);
5547
5548 for (RefPtr<mozilla::dom::SharedWorker> pinnedWorker :
5549 mSharedWorkers.ForwardRange()) {
5550 pinnedWorker->Suspend();
5551 }
5552
5553 SuspendIdleRequests();
5554
5555 mTimeoutManager->Suspend();
5556
5557 // Suspend all of the AudioContexts for this window
5558 for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) {
5559 mAudioContexts[i]->SuspendFromChrome();
5560 }
5561}
5562
5563void nsGlobalWindowInner::Resume(bool aIncludeSubWindows) {
5564 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/nsGlobalWindowInner.cpp"
, 5564); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 5564; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5565
5566 // We can only safely resume a window if its the current inner window. If
5567 // its not the current inner, then we are in one of two different cases.
5568 // Either we are in the bfcache or we are doomed window that is going away.
5569 // If a window is suspended when it becomes inactive we purposely do not
5570 // put it in the bfcache, so Resume should never be needed in that case.
5571 // If the window is doomed then there is no point in resuming it.
5572 if (!IsCurrentInnerWindow()) {
5573 return;
5574 }
5575
5576 // Resume all in-process descendants. This restores timers recursively
5577 // canceled in Suspend() and ensures all in-process descendants have the
5578 // correct mSuspendDepth.
5579 if (aIncludeSubWindows) {
5580 CallOnInProcessDescendants(&nsGlobalWindowInner::Resume, false);
5581 }
5582
5583 if (mSuspendDepth == 0) {
5584 // Ignore if the window is not suspended.
5585 return;
5586 }
5587
5588 mSuspendDepth -= 1;
5589
5590 if (mSuspendDepth != 0) {
5591 return;
5592 }
5593
5594 // We should not be able to resume a frozen window. It must be Thaw()'d
5595 // first.
5596 MOZ_ASSERT(mFreezeDepth == 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mFreezeDepth == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mFreezeDepth == 0))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("mFreezeDepth == 0"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 5596); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFreezeDepth == 0"
")"); do { *((volatile int*)__null) = 5596; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5597
5598 nsCOMPtr<nsIDeviceSensors> ac = do_GetService(NS_DEVICE_SENSORS_CONTRACTID"@mozilla.org/devicesensors;1");
5599 if (ac) {
5600 for (uint32_t i = 0; i < mEnabledSensors.Length(); i++)
5601 ac->AddWindowListener(mEnabledSensors[i], this);
5602 }
5603 EnableGamepadUpdates();
5604 EnableVRUpdates();
5605
5606 // Resume all of the AudioContexts for this window
5607 for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) {
5608 mAudioContexts[i]->ResumeFromChrome();
5609 }
5610
5611 if (RefPtr<MediaDevices> devices = GetExtantMediaDevices()) {
5612 devices->WindowResumed();
5613 }
5614
5615 mTimeoutManager->Resume();
5616
5617 ResumeIdleRequests();
5618
5619 // Resume all of the workers for this window. We must do this
5620 // after timeouts since workers may have queued events that can trigger
5621 // a setTimeout().
5622 ResumeWorkersForWindow(*this);
5623
5624 for (RefPtr<mozilla::dom::SharedWorker> pinnedWorker :
5625 mSharedWorkers.ForwardRange()) {
5626 pinnedWorker->Resume();
5627 }
5628
5629 if (mWindowGlobalChild) {
5630 mWindowGlobalChild->UnblockBFCacheFor(BFCacheStatus::SUSPENDED);
5631 }
5632}
5633
5634bool nsGlobalWindowInner::IsSuspended() const {
5635 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/nsGlobalWindowInner.cpp"
, 5635); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 5635; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5636 return mSuspendDepth != 0;
5637}
5638
5639void nsGlobalWindowInner::Freeze(bool aIncludeSubWindows) {
5640 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/nsGlobalWindowInner.cpp"
, 5640); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 5640; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5641 Suspend(aIncludeSubWindows);
5642 FreezeInternal(aIncludeSubWindows);
5643}
5644
5645void nsGlobalWindowInner::FreezeInternal(bool aIncludeSubWindows) {
5646 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/nsGlobalWindowInner.cpp"
, 5646); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 5646; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5647 MOZ_DIAGNOSTIC_ASSERT(IsCurrentInnerWindow())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsCurrentInnerWindow())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsCurrentInnerWindow()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("IsCurrentInnerWindow()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 5647); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "IsCurrentInnerWindow()"
")"); do { *((volatile int*)__null) = 5647; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5648 MOZ_DIAGNOSTIC_ASSERT(IsSuspended())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsSuspended())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsSuspended()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("IsSuspended()",
"/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 5648); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "IsSuspended()"
")"); do { *((volatile int*)__null) = 5648; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5649
5650 HintIsLoading(false);
5651
5652 if (aIncludeSubWindows) {
5653 CallOnInProcessChildren(&nsGlobalWindowInner::FreezeInternal,
5654 aIncludeSubWindows);
5655 }
5656
5657 mFreezeDepth += 1;
5658 MOZ_ASSERT(mSuspendDepth >= mFreezeDepth)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mSuspendDepth >= mFreezeDepth)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mSuspendDepth >= mFreezeDepth
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mSuspendDepth >= mFreezeDepth", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 5658); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mSuspendDepth >= mFreezeDepth"
")"); do { *((volatile int*)__null) = 5658; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5659 if (mFreezeDepth != 1) {
5660 return;
5661 }
5662
5663 FreezeWorkersForWindow(*this);
5664
5665 for (RefPtr<mozilla::dom::SharedWorker> pinnedWorker :
5666 mSharedWorkers.ForwardRange()) {
5667 pinnedWorker->Freeze();
5668 }
5669
5670 mTimeoutManager->Freeze();
5671 if (mClientSource) {
5672 mClientSource->Freeze();
5673 }
5674
5675 NotifyDOMWindowFrozen(this);
5676 NotifyGlobalFrozen();
5677}
5678
5679void nsGlobalWindowInner::Thaw(bool aIncludeSubWindows) {
5680 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/nsGlobalWindowInner.cpp"
, 5680); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 5680; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5681 ThawInternal(aIncludeSubWindows);
5682 Resume(aIncludeSubWindows);
5683}
5684
5685void nsGlobalWindowInner::ThawInternal(bool aIncludeSubWindows) {
5686 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/nsGlobalWindowInner.cpp"
, 5686); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 5686; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5687 MOZ_DIAGNOSTIC_ASSERT(IsCurrentInnerWindow())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsCurrentInnerWindow())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsCurrentInnerWindow()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("IsCurrentInnerWindow()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 5687); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "IsCurrentInnerWindow()"
")"); do { *((volatile int*)__null) = 5687; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5688 MOZ_DIAGNOSTIC_ASSERT(IsSuspended())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsSuspended())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsSuspended()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("IsSuspended()",
"/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 5688); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "IsSuspended()"
")"); do { *((volatile int*)__null) = 5688; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5689
5690 if (aIncludeSubWindows) {
5691 CallOnInProcessChildren(&nsGlobalWindowInner::ThawInternal,
5692 aIncludeSubWindows);
5693 }
5694
5695 MOZ_ASSERT(mFreezeDepth != 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mFreezeDepth != 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mFreezeDepth != 0))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("mFreezeDepth != 0"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 5695); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFreezeDepth != 0"
")"); do { *((volatile int*)__null) = 5695; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5696 mFreezeDepth -= 1;
5697 MOZ_ASSERT(mSuspendDepth >= mFreezeDepth)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mSuspendDepth >= mFreezeDepth)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mSuspendDepth >= mFreezeDepth
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mSuspendDepth >= mFreezeDepth", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 5697); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mSuspendDepth >= mFreezeDepth"
")"); do { *((volatile int*)__null) = 5697; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5698 if (mFreezeDepth != 0) {
5699 return;
5700 }
5701
5702 if (mClientSource) {
5703 mClientSource->Thaw();
5704 }
5705 mTimeoutManager->Thaw();
5706
5707 ThawWorkersForWindow(*this);
5708
5709 for (RefPtr<mozilla::dom::SharedWorker> pinnedWorker :
5710 mSharedWorkers.ForwardRange()) {
5711 pinnedWorker->Thaw();
5712 }
5713
5714 NotifyDOMWindowThawed(this);
5715 NotifyGlobalThawed();
5716}
5717
5718bool nsGlobalWindowInner::IsFrozen() const {
5719 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/nsGlobalWindowInner.cpp"
, 5719); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 5719; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5720 bool frozen = mFreezeDepth != 0;
5721 MOZ_ASSERT_IF(frozen, IsSuspended())do { if (frozen) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(IsSuspended())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsSuspended()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("IsSuspended()",
"/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 5721); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsSuspended()"
")"); do { *((volatile int*)__null) = 5721; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
5722 return frozen;
5723}
5724
5725void nsGlobalWindowInner::SyncStateFromParentWindow() {
5726 // This method should only be called on an inner window that has been
5727 // assigned to an outer window already.
5728 MOZ_ASSERT(IsCurrentInnerWindow())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsCurrentInnerWindow())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsCurrentInnerWindow()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("IsCurrentInnerWindow()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 5728); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsCurrentInnerWindow()"
")"); do { *((volatile int*)__null) = 5728; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5729 nsPIDOMWindowOuter* outer = GetOuterWindow();
5730 MOZ_ASSERT(outer)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(outer)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(outer))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("outer", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 5730); AnnotateMozCrashReason("MOZ_ASSERT" "(" "outer" ")")
; do { *((volatile int*)__null) = 5730; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5731
5732 // Attempt to find our parent windows.
5733 nsCOMPtr<Element> frame = outer->GetFrameElementInternal();
5734 nsPIDOMWindowOuter* parentOuter =
5735 frame ? frame->OwnerDoc()->GetWindow() : nullptr;
5736 nsGlobalWindowInner* parentInner =
5737 parentOuter
5738 ? nsGlobalWindowInner::Cast(parentOuter->GetCurrentInnerWindow())
5739 : nullptr;
5740
5741 // If our outer is in a modal state, but our parent is not in a modal
5742 // state, then we must apply the suspend directly. If our parent is
5743 // in a modal state then we should get the suspend automatically
5744 // via the parentSuspendDepth application below.
5745 if ((!parentInner || !parentInner->IsInModalState()) && IsInModalState()) {
5746 Suspend();
5747 }
5748
5749 uint32_t parentFreezeDepth = parentInner ? parentInner->mFreezeDepth : 0;
5750 uint32_t parentSuspendDepth = parentInner ? parentInner->mSuspendDepth : 0;
5751
5752 // Since every Freeze() calls Suspend(), the suspend count must
5753 // be equal or greater to the freeze count.
5754 MOZ_ASSERT(parentFreezeDepth <= parentSuspendDepth)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(parentFreezeDepth <= parentSuspendDepth)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(parentFreezeDepth <= parentSuspendDepth))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("parentFreezeDepth <= parentSuspendDepth"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 5754); AnnotateMozCrashReason("MOZ_ASSERT" "(" "parentFreezeDepth <= parentSuspendDepth"
")"); do { *((volatile int*)__null) = 5754; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5755
5756 // First apply the Freeze() calls.
5757 for (uint32_t i = 0; i < parentFreezeDepth; ++i) {
5758 Freeze();
5759 }
5760
5761 // Now apply only the number of Suspend() calls to reach the target
5762 // suspend count after applying the Freeze() calls.
5763 for (uint32_t i = 0; i < (parentSuspendDepth - parentFreezeDepth); ++i) {
5764 Suspend();
5765 }
5766}
5767
5768void nsGlobalWindowInner::UpdateBackgroundState() {
5769 if (RefPtr<MediaDevices> devices = GetExtantMediaDevices()) {
5770 devices->BackgroundStateChanged();
5771 }
5772 mTimeoutManager->UpdateBackgroundState();
5773
5774 UpdateWorkersBackgroundState(*this, IsBackgroundInternal());
5775}
5776
5777template <typename Method, typename... Args>
5778CallState nsGlobalWindowInner::CallOnInProcessDescendantsInternal(
5779 BrowsingContext* aBrowsingContext, bool aChildOnly, Method aMethod,
5780 Args&&... aArgs) {
5781 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/nsGlobalWindowInner.cpp"
, 5781); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 5781; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5782 MOZ_ASSERT(aBrowsingContext)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aBrowsingContext)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aBrowsingContext))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aBrowsingContext"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 5782); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBrowsingContext"
")"); do { *((volatile int*)__null) = 5782; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5783
5784 CallState state = CallState::Continue;
5785 for (const RefPtr<BrowsingContext>& bc : aBrowsingContext->Children()) {
5786 if (nsCOMPtr<nsPIDOMWindowOuter> pWin = bc->GetDOMWindow()) {
5787 auto* win = nsGlobalWindowOuter::Cast(pWin);
5788 if (nsGlobalWindowInner* inner =
5789 nsGlobalWindowInner::Cast(win->GetCurrentInnerWindow())) {
5790 // Call the descendant method using our helper CallDescendant() template
5791 // method. This allows us to handle both void returning methods and
5792 // methods that return CallState explicitly. For void returning methods
5793 // we assume CallState::Continue.
5794 using returnType = decltype((inner->*aMethod)(aArgs...));
5795 state = CallDescendant<returnType>(inner, aMethod, aArgs...);
5796
5797 if (state == CallState::Stop) {
5798 return state;
5799 }
5800 }
5801 }
5802
5803 if (!aChildOnly) {
5804 state = CallOnInProcessDescendantsInternal(bc.get(), aChildOnly, aMethod,
5805 aArgs...);
5806 if (state == CallState::Stop) {
5807 return state;
5808 }
5809 }
5810 }
5811
5812 return state;
5813}
5814
5815Maybe<ClientInfo> nsGlobalWindowInner::GetClientInfo() const {
5816 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/nsGlobalWindowInner.cpp"
, 5816); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 5816; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5817 if (mDoc && mDoc->IsStaticDocument()) {
5818 if (Maybe<ClientInfo> info = mDoc->GetOriginalDocument()->GetClientInfo()) {
5819 return info;
5820 }
5821 }
5822
5823 Maybe<ClientInfo> clientInfo;
5824 if (mClientSource) {
5825 clientInfo.emplace(mClientSource->Info());
5826 }
5827 return clientInfo;
5828}
5829
5830Maybe<ClientState> nsGlobalWindowInner::GetClientState() const {
5831 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/nsGlobalWindowInner.cpp"
, 5831); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 5831; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5832 if (mDoc && mDoc->IsStaticDocument()) {
5833 if (Maybe<ClientState> state =
5834 mDoc->GetOriginalDocument()->GetClientState()) {
5835 return state;
5836 }
5837 }
5838
5839 Maybe<ClientState> clientState;
5840 if (mClientSource) {
5841 Result<ClientState, ErrorResult> res = mClientSource->SnapshotState();
5842 if (res.isOk()) {
5843 clientState.emplace(res.unwrap());
5844 } else {
5845 res.unwrapErr().SuppressException();
5846 }
5847 }
5848 return clientState;
5849}
5850
5851Maybe<ServiceWorkerDescriptor> nsGlobalWindowInner::GetController() const {
5852 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/nsGlobalWindowInner.cpp"
, 5852); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 5852; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5853 if (mDoc && mDoc->IsStaticDocument()) {
5854 if (Maybe<ServiceWorkerDescriptor> controller =
5855 mDoc->GetOriginalDocument()->GetController()) {
5856 return controller;
5857 }
5858 }
5859
5860 Maybe<ServiceWorkerDescriptor> controller;
5861 if (mClientSource) {
5862 controller = mClientSource->GetController();
5863 }
5864 return controller;
5865}
5866
5867void nsGlobalWindowInner::SetCsp(nsIContentSecurityPolicy* aCsp) {
5868 if (!mClientSource) {
5869 return;
5870 }
5871 mClientSource->SetCsp(aCsp);
5872 // Also cache the CSP within the document
5873 mDoc->SetCsp(aCsp);
5874
5875 if (mWindowGlobalChild) {
5876 mWindowGlobalChild->SendSetClientInfo(mClientSource->Info().ToIPC());
5877 }
5878}
5879
5880void nsGlobalWindowInner::SetPreloadCsp(nsIContentSecurityPolicy* aPreloadCsp) {
5881 if (!mClientSource) {
5882 return;
5883 }
5884 mClientSource->SetPreloadCsp(aPreloadCsp);
5885 // Also cache the preload CSP within the document
5886 mDoc->SetPreloadCsp(aPreloadCsp);
5887
5888 if (mWindowGlobalChild) {
5889 mWindowGlobalChild->SendSetClientInfo(mClientSource->Info().ToIPC());
5890 }
5891}
5892
5893nsIContentSecurityPolicy* nsGlobalWindowInner::GetCsp() {
5894 if (mDoc) {
5895 return mDoc->GetCsp();
5896 }
5897
5898 // If the window is partially torn down and has its document nulled out,
5899 // we query the CSP we snapshot in FreeInnerObjects.
5900 if (mDocumentCsp) {
5901 return mDocumentCsp;
5902 }
5903 return nullptr;
5904}
5905
5906RefPtr<ServiceWorker> nsGlobalWindowInner::GetOrCreateServiceWorker(
5907 const ServiceWorkerDescriptor& aDescriptor) {
5908 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/nsGlobalWindowInner.cpp"
, 5908); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 5908; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5909 RefPtr<ServiceWorker> ref;
5910 ForEachGlobalTeardownObserver(
5911 [&](GlobalTeardownObserver* aObserver, bool* aDoneOut) {
5912 RefPtr<ServiceWorker> sw = do_QueryObject(aObserver);
5913 if (!sw || !sw->Descriptor().Matches(aDescriptor)) {
5914 return;
5915 }
5916
5917 ref = std::move(sw);
5918 *aDoneOut = true;
5919 });
5920
5921 if (!ref) {
5922 ref = ServiceWorker::Create(this, aDescriptor);
5923 }
5924
5925 return ref;
5926}
5927
5928RefPtr<mozilla::dom::ServiceWorkerRegistration>
5929nsGlobalWindowInner::GetServiceWorkerRegistration(
5930 const mozilla::dom::ServiceWorkerRegistrationDescriptor& aDescriptor)
5931 const {
5932 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/nsGlobalWindowInner.cpp"
, 5932); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 5932; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5933 RefPtr<ServiceWorkerRegistration> ref;
5934 ForEachGlobalTeardownObserver(
5935 [&](GlobalTeardownObserver* aObserver, bool* aDoneOut) {
5936 RefPtr<ServiceWorkerRegistration> swr = do_QueryObject(aObserver);
5937 if (!swr || !swr->MatchesDescriptor(aDescriptor)) {
5938 return;
5939 }
5940
5941 ref = std::move(swr);
5942 *aDoneOut = true;
5943 });
5944 return ref;
5945}
5946
5947RefPtr<ServiceWorkerRegistration>
5948nsGlobalWindowInner::GetOrCreateServiceWorkerRegistration(
5949 const ServiceWorkerRegistrationDescriptor& aDescriptor) {
5950 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/nsGlobalWindowInner.cpp"
, 5950); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 5950; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5951 RefPtr<ServiceWorkerRegistration> ref =
5952 GetServiceWorkerRegistration(aDescriptor);
5953 if (!ref) {
5954 ref = ServiceWorkerRegistration::CreateForMainThread(this, aDescriptor);
5955 }
5956 return ref;
5957}
5958
5959StorageAccess nsGlobalWindowInner::GetStorageAccess() {
5960 return StorageAllowedForWindow(this);
5961}
5962
5963nsresult nsGlobalWindowInner::FireDelayedDOMEvents(bool aIncludeSubWindows) {
5964 // Fires an offline status event if the offline status has changed
5965 FireOfflineStatusEventIfChanged();
5966
5967 if (!aIncludeSubWindows) {
5968 return NS_OK;
5969 }
5970
5971 nsCOMPtr<nsIDocShell> docShell = GetDocShell();
5972 if (docShell) {
5973 int32_t childCount = 0;
5974 docShell->GetInProcessChildCount(&childCount);
5975
5976 // Take a copy of the current children so that modifications to
5977 // the child list don't affect to the iteration.
5978 AutoTArray<nsCOMPtr<nsIDocShellTreeItem>, 8> children;
5979 for (int32_t i = 0; i < childCount; ++i) {
5980 nsCOMPtr<nsIDocShellTreeItem> childShell;
5981 docShell->GetInProcessChildAt(i, getter_AddRefs(childShell));
5982 if (childShell) {
5983 children.AppendElement(childShell);
5984 }
5985 }
5986
5987 for (nsCOMPtr<nsIDocShellTreeItem> childShell : children) {
5988 if (nsCOMPtr<nsPIDOMWindowOuter> pWin = childShell->GetWindow()) {
5989 auto* win = nsGlobalWindowOuter::Cast(pWin);
5990 win->FireDelayedDOMEvents(true);
5991 }
5992 }
5993 }
5994
5995 return NS_OK;
5996}
5997
5998//*****************************************************************************
5999// nsGlobalWindowInner: Window Control Functions
6000//*****************************************************************************
6001
6002nsPIDOMWindowOuter* nsGlobalWindowInner::GetInProcessParentInternal() {
6003 nsGlobalWindowOuter* outer = GetOuterWindowInternal();
6004 if (!outer) {
6005 // No outer window available!
6006 return nullptr;
6007 }
6008 return outer->GetInProcessParentInternal();
6009}
6010
6011nsIPrincipal* nsGlobalWindowInner::GetTopLevelAntiTrackingPrincipal() {
6012 nsPIDOMWindowOuter* outerWindow = GetOuterWindowInternal();
6013 if (!outerWindow) {
6014 return nullptr;
6015 }
6016
6017 nsPIDOMWindowOuter* topLevelOuterWindow =
6018 GetBrowsingContext()->Top()->GetDOMWindow();
6019 if (!topLevelOuterWindow) {
6020 return nullptr;
6021 }
6022
6023 bool stopAtOurLevel =
6024 mDoc && mDoc->CookieJarSettings()->GetCookieBehavior() ==
6025 nsICookieService::BEHAVIOR_REJECT_TRACKER;
6026
6027 if (stopAtOurLevel && topLevelOuterWindow == outerWindow) {
6028 return nullptr;
6029 }
6030
6031 nsPIDOMWindowInner* topLevelInnerWindow =
6032 topLevelOuterWindow->GetCurrentInnerWindow();
6033 if (NS_WARN_IF(!topLevelInnerWindow)NS_warn_if_impl(!topLevelInnerWindow, "!topLevelInnerWindow",
"/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 6033)
) {
6034 return nullptr;
6035 }
6036
6037 nsIPrincipal* topLevelPrincipal =
6038 nsGlobalWindowInner::Cast(topLevelInnerWindow)->GetPrincipal();
6039 if (NS_WARN_IF(!topLevelPrincipal)NS_warn_if_impl(!topLevelPrincipal, "!topLevelPrincipal", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 6039)
) {
6040 return nullptr;
6041 }
6042
6043 return topLevelPrincipal;
6044}
6045
6046nsIPrincipal* nsGlobalWindowInner::GetClientPrincipal() {
6047 return mClientSource ? mClientSource->GetPrincipal() : nullptr;
6048}
6049
6050bool nsGlobalWindowInner::IsInFullScreenTransition() {
6051 if (!mIsChrome) {
6052 return false;
6053 }
6054
6055 nsGlobalWindowOuter* outerWindow = GetOuterWindowInternal();
6056 if (!outerWindow) {
6057 return false;
6058 }
6059
6060 return outerWindow->mIsInFullScreenTransition;
6061}
6062
6063//*****************************************************************************
6064// nsGlobalWindowInner: Timeout Functions
6065//*****************************************************************************
6066
6067class WindowScriptTimeoutHandler final : public ScriptTimeoutHandler {
6068 public:
6069 NS_DECL_ISUPPORTS_INHERITEDpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override;
6070 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(WindowScriptTimeoutHandler,class cycleCollection : public ScriptTimeoutHandler::cycleCollection
{ public: constexpr explicit cycleCollection(Flags aFlags = 0
) : ScriptTimeoutHandler::cycleCollection(aFlags) {} private:
public: virtual nsresult TraverseNative(void* p, nsCycleCollectionTraversalCallback
& cb) override; virtual const char* ClassName() override {
return "WindowScriptTimeoutHandler"; }; static WindowScriptTimeoutHandler
* Downcast(nsISupports* s) { return static_cast<WindowScriptTimeoutHandler
*>(static_cast<ScriptTimeoutHandler*>( ScriptTimeoutHandler
::cycleCollection::Downcast(s))); } virtual void Unlink(void*
p) override; static constexpr nsXPCOMCycleCollectionParticipant
* GetParticipant() { return &WindowScriptTimeoutHandler::
_cycleCollectorGlobal; } }; virtual void CheckForRightParticipant
() override { nsXPCOMCycleCollectionParticipant* p; CallQueryInterface
(this, &p); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(p == &_cycleCollectorGlobal)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(p == &_cycleCollectorGlobal
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"p == &_cycleCollectorGlobal" " (" "WindowScriptTimeoutHandler"
" should QI to its own CC participant" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 6071); AnnotateMozCrashReason("MOZ_ASSERT" "(" "p == &_cycleCollectorGlobal"
") (" "WindowScriptTimeoutHandler" " should QI to its own CC participant"
")"); do { *((volatile int*)__null) = 6071; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } static cycleCollection
_cycleCollectorGlobal;
6071 ScriptTimeoutHandler)class cycleCollection : public ScriptTimeoutHandler::cycleCollection
{ public: constexpr explicit cycleCollection(Flags aFlags = 0
) : ScriptTimeoutHandler::cycleCollection(aFlags) {} private:
public: virtual nsresult TraverseNative(void* p, nsCycleCollectionTraversalCallback
& cb) override; virtual const char* ClassName() override {
return "WindowScriptTimeoutHandler"; }; static WindowScriptTimeoutHandler
* Downcast(nsISupports* s) { return static_cast<WindowScriptTimeoutHandler
*>(static_cast<ScriptTimeoutHandler*>( ScriptTimeoutHandler
::cycleCollection::Downcast(s))); } virtual void Unlink(void*
p) override; static constexpr nsXPCOMCycleCollectionParticipant
* GetParticipant() { return &WindowScriptTimeoutHandler::
_cycleCollectorGlobal; } }; virtual void CheckForRightParticipant
() override { nsXPCOMCycleCollectionParticipant* p; CallQueryInterface
(this, &p); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(p == &_cycleCollectorGlobal)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(p == &_cycleCollectorGlobal
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"p == &_cycleCollectorGlobal" " (" "WindowScriptTimeoutHandler"
" should QI to its own CC participant" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 6071); AnnotateMozCrashReason("MOZ_ASSERT" "(" "p == &_cycleCollectorGlobal"
") (" "WindowScriptTimeoutHandler" " should QI to its own CC participant"
")"); do { *((volatile int*)__null) = 6071; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } static cycleCollection
_cycleCollectorGlobal;
6072
6073 WindowScriptTimeoutHandler(JSContext* aCx, nsIGlobalObject* aGlobal,
6074 const nsAString& aExpression)
6075 : ScriptTimeoutHandler(aCx, aGlobal, aExpression),
6076 mInitiatingScript(ScriptLoader::GetActiveScript(aCx)) {}
6077
6078 MOZ_CAN_RUN_SCRIPT virtual bool Call(const char* aExecutionReason) override;
6079
6080 private:
6081 virtual ~WindowScriptTimeoutHandler() = default;
6082
6083 // Initiating script for use when evaluating mExpr on the main thread.
6084 RefPtr<JS::loader::LoadedScript> mInitiatingScript;
6085};
6086
6087NS_IMPL_CYCLE_COLLECTION_INHERITED(WindowScriptTimeoutHandler,WindowScriptTimeoutHandler::cycleCollection WindowScriptTimeoutHandler
::_cycleCollectorGlobal; void WindowScriptTimeoutHandler::cycleCollection
::Unlink(void* p) { WindowScriptTimeoutHandler* tmp = DowncastCCParticipant
<WindowScriptTimeoutHandler>(p); nsISupports* s = static_cast
<nsISupports*>(p); ScriptTimeoutHandler::cycleCollection
::Unlink(s); ImplCycleCollectionUnlink(tmp->mInitiatingScript
); (void)tmp; } nsresult WindowScriptTimeoutHandler::cycleCollection
::TraverseNative( void* p, nsCycleCollectionTraversalCallback
& cb) { WindowScriptTimeoutHandler* tmp = DowncastCCParticipant
<WindowScriptTimeoutHandler>(p); nsISupports* s = static_cast
<nsISupports*>(p); if (ScriptTimeoutHandler::cycleCollection
::TraverseNative(s, cb) == NS_SUCCESS_INTERRUPTED_TRAVERSE) {
return NS_SUCCESS_INTERRUPTED_TRAVERSE; } ImplCycleCollectionTraverse
(cb, tmp->mInitiatingScript, "mInitiatingScript", 0); (void
)tmp; return NS_OK; }
6088 ScriptTimeoutHandler, mInitiatingScript)WindowScriptTimeoutHandler::cycleCollection WindowScriptTimeoutHandler
::_cycleCollectorGlobal; void WindowScriptTimeoutHandler::cycleCollection
::Unlink(void* p) { WindowScriptTimeoutHandler* tmp = DowncastCCParticipant
<WindowScriptTimeoutHandler>(p); nsISupports* s = static_cast
<nsISupports*>(p); ScriptTimeoutHandler::cycleCollection
::Unlink(s); ImplCycleCollectionUnlink(tmp->mInitiatingScript
); (void)tmp; } nsresult WindowScriptTimeoutHandler::cycleCollection
::TraverseNative( void* p, nsCycleCollectionTraversalCallback
& cb) { WindowScriptTimeoutHandler* tmp = DowncastCCParticipant
<WindowScriptTimeoutHandler>(p); nsISupports* s = static_cast
<nsISupports*>(p); if (ScriptTimeoutHandler::cycleCollection
::TraverseNative(s, cb) == NS_SUCCESS_INTERRUPTED_TRAVERSE) {
return NS_SUCCESS_INTERRUPTED_TRAVERSE; } ImplCycleCollectionTraverse
(cb, tmp->mInitiatingScript, "mInitiatingScript", 0); (void
)tmp; return NS_OK; }
6089
6090NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WindowScriptTimeoutHandler)nsresult WindowScriptTimeoutHandler::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/nsGlobalWindowInner.cpp"
, 6090); 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 = WindowScriptTimeoutHandler
::cycleCollection::GetParticipant(); return NS_OK; } if (LowWordEquals
(aIID, (nsCycleCollectionISupports::COMTypeInfo<nsCycleCollectionISupports
, void>::kIID))) { *aInstancePtr = WindowScriptTimeoutHandler
::cycleCollection::Upcast(this); return NS_OK; } foundInterface
= nullptr; } else
6091NS_INTERFACE_MAP_END_INHERITING(ScriptTimeoutHandler)foundInterface = 0; nsresult status; if (!foundInterface) status
= ScriptTimeoutHandler::QueryInterface(aIID, (void**)&foundInterface
); else { (foundInterface)->AddRef(); status = NS_OK; } *aInstancePtr
= foundInterface; return status; }
6092
6093NS_IMPL_ADDREF_INHERITED(WindowScriptTimeoutHandler, ScriptTimeoutHandler)MozExternalRefCountType WindowScriptTimeoutHandler::AddRef(void
) { static_assert(!std::is_destructible_v<WindowScriptTimeoutHandler
>, "Reference-counted class " "WindowScriptTimeoutHandler"
" should not have a public destructor. " "Make this class's destructor non-public"
); nsrefcnt r = ScriptTimeoutHandler::AddRef(); if constexpr (
::mozilla::detail::ShouldLogInheritedRefcnt<WindowScriptTimeoutHandler
>) { NS_LogAddRef((this), (r), ("WindowScriptTimeoutHandler"
), (uint32_t)(sizeof(*this))); } return r; }
6094NS_IMPL_RELEASE_INHERITED(WindowScriptTimeoutHandler, ScriptTimeoutHandler)MozExternalRefCountType WindowScriptTimeoutHandler::Release(void
) { nsrefcnt r = ScriptTimeoutHandler::Release(); if constexpr
(::mozilla::detail::ShouldLogInheritedRefcnt<WindowScriptTimeoutHandler
>) { NS_LogRelease((this), (r), ("WindowScriptTimeoutHandler"
)); } return r; }
6095
6096bool WindowScriptTimeoutHandler::Call(const char* aExecutionReason) {
6097 // New script entry point required, due to the "Create a script" sub-step
6098 // of
6099 // http://www.whatwg.org/specs/web-apps/current-work/#timer-initialisation-steps
6100 nsAutoMicroTask mt;
6101 AutoEntryScript aes(mGlobal, aExecutionReason, true);
6102 JS::CompileOptions options(aes.cx());
6103 options.setFileAndLine(mFileName.get(), mLineNo);
6104 options.setNoScriptRval(true);
6105 options.setIntroductionType("domTimer");
6106 JS::Rooted<JSObject*> global(aes.cx(), mGlobal->GetGlobalJSObject());
6107 {
6108 JSExecutionContext exec(aes.cx(), global, options);
6109 nsresult rv = exec.Compile(mExpr);
6110
6111 JS::Rooted<JSScript*> script(aes.cx(), exec.MaybeGetScript());
6112 if (script) {
6113 if (mInitiatingScript) {
6114 mInitiatingScript->AssociateWithScript(script);
6115 }
6116
6117 rv = exec.ExecScript();
6118 }
6119
6120 if (rv == NS_SUCCESS_DOM_SCRIPT_EVALUATION_THREW_UNCATCHABLE) {
6121 return false;
6122 }
6123 }
6124
6125 return true;
6126};
6127
6128nsGlobalWindowInner* nsGlobalWindowInner::InnerForSetTimeoutOrInterval(
6129 ErrorResult& aError) {
6130 nsGlobalWindowOuter* outer = GetOuterWindowInternal();
6131 nsPIDOMWindowInner* currentInner =
6132 outer ? outer->GetCurrentInnerWindow() : this;
6133
6134 // If forwardTo is not the window with an active document then we want the
6135 // call to setTimeout/Interval to be a noop, so return null but don't set an
6136 // error.
6137 return HasActiveDocument() ? nsGlobalWindowInner::Cast(currentInner)
6138 : nullptr;
6139}
6140
6141int32_t nsGlobalWindowInner::SetTimeout(JSContext* aCx, Function& aFunction,
6142 int32_t aTimeout,
6143 const Sequence<JS::Value>& aArguments,
6144 ErrorResult& aError) {
6145 return SetTimeoutOrInterval(aCx, aFunction, aTimeout, aArguments, false,
6146 aError);
6147}
6148
6149int32_t nsGlobalWindowInner::SetTimeout(JSContext* aCx,
6150 const nsAString& aHandler,
6151 int32_t aTimeout,
6152 const Sequence<JS::Value>& /* unused */,
6153 ErrorResult& aError) {
6154 return SetTimeoutOrInterval(aCx, aHandler, aTimeout, false, aError);
6155}
6156
6157int32_t nsGlobalWindowInner::SetInterval(JSContext* aCx, Function& aFunction,
6158 const int32_t aTimeout,
6159 const Sequence<JS::Value>& aArguments,
6160 ErrorResult& aError) {
6161 return SetTimeoutOrInterval(aCx, aFunction, aTimeout, aArguments, true,
6162 aError);
6163}
6164
6165int32_t nsGlobalWindowInner::SetInterval(
6166 JSContext* aCx, const nsAString& aHandler, const int32_t aTimeout,
6167 const Sequence<JS::Value>& /* unused */, ErrorResult& aError) {
6168 return SetTimeoutOrInterval(aCx, aHandler, aTimeout, true, aError);
6169}
6170
6171int32_t nsGlobalWindowInner::SetTimeoutOrInterval(
6172 JSContext* aCx, Function& aFunction, int32_t aTimeout,
6173 const Sequence<JS::Value>& aArguments, bool aIsInterval,
6174 ErrorResult& aError) {
6175 nsGlobalWindowInner* inner = InnerForSetTimeoutOrInterval(aError);
6176 if (!inner) {
6177 return -1;
6178 }
6179
6180 if (inner != this) {
6181 RefPtr<nsGlobalWindowInner> innerRef(inner);
6182 return innerRef->SetTimeoutOrInterval(aCx, aFunction, aTimeout, aArguments,
6183 aIsInterval, aError);
6184 }
6185
6186 DebuggerNotificationDispatch(
6187 this, aIsInterval ? DebuggerNotificationType::SetInterval
6188 : DebuggerNotificationType::SetTimeout);
6189
6190 if (!GetContextInternal() || !HasJSGlobal()) {
6191 // This window was already closed, or never properly initialized,
6192 // don't let a timer be scheduled on such a window.
6193 aError.Throw(NS_ERROR_NOT_INITIALIZED);
6194 return 0;
6195 }
6196
6197 nsTArray<JS::Heap<JS::Value>> args;
6198 if (!args.AppendElements(aArguments, fallible)) {
6199 aError.Throw(NS_ERROR_OUT_OF_MEMORY);
6200 return 0;
6201 }
6202
6203 RefPtr<TimeoutHandler> handler =
6204 new CallbackTimeoutHandler(aCx, this, &aFunction, std::move(args));
6205
6206 int32_t result;
6207 aError =
6208 mTimeoutManager->SetTimeout(handler, aTimeout, aIsInterval,
6209 Timeout::Reason::eTimeoutOrInterval, &result);
6210 return result;
6211}
6212
6213int32_t nsGlobalWindowInner::SetTimeoutOrInterval(JSContext* aCx,
6214 const nsAString& aHandler,
6215 int32_t aTimeout,
6216 bool aIsInterval,
6217 ErrorResult& aError) {
6218 nsGlobalWindowInner* inner = InnerForSetTimeoutOrInterval(aError);
6219 if (!inner) {
6220 return -1;
6221 }
6222
6223 if (inner != this) {
6224 RefPtr<nsGlobalWindowInner> innerRef(inner);
6225 return innerRef->SetTimeoutOrInterval(aCx, aHandler, aTimeout, aIsInterval,
6226 aError);
6227 }
6228
6229 DebuggerNotificationDispatch(
6230 this, aIsInterval ? DebuggerNotificationType::SetInterval
6231 : DebuggerNotificationType::SetTimeout);
6232
6233 if (!GetContextInternal() || !HasJSGlobal()) {
6234 // This window was already closed, or never properly initialized,
6235 // don't let a timer be scheduled on such a window.
6236 aError.Throw(NS_ERROR_NOT_INITIALIZED);
6237 return 0;
6238 }
6239
6240 bool allowEval = false;
6241 aError = CSPEvalChecker::CheckForWindow(aCx, this, aHandler, &allowEval);
6242 if (NS_WARN_IF(aError.Failed())NS_warn_if_impl(aError.Failed(), "aError.Failed()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 6242)
|| !allowEval) {
6243 return 0;
6244 }
6245
6246 RefPtr<TimeoutHandler> handler =
6247 new WindowScriptTimeoutHandler(aCx, this, aHandler);
6248
6249 int32_t result;
6250 aError =
6251 mTimeoutManager->SetTimeout(handler, aTimeout, aIsInterval,
6252 Timeout::Reason::eTimeoutOrInterval, &result);
6253 return result;
6254}
6255
6256static const char* GetTimeoutReasonString(Timeout* aTimeout) {
6257 switch (aTimeout->mReason) {
6258 case Timeout::Reason::eTimeoutOrInterval:
6259 if (aTimeout->mIsInterval) {
6260 return "setInterval handler";
6261 }
6262 return "setTimeout handler";
6263 case Timeout::Reason::eIdleCallbackTimeout:
6264 return "setIdleCallback handler (timed out)";
6265 case Timeout::Reason::eAbortSignalTimeout:
6266 return "AbortSignal timeout";
6267 case Timeout::Reason::eDelayedWebTaskTimeout:
6268 return "delayedWebTaskCallback handler (timed out)";
6269 default:
6270 MOZ_CRASH("Unexpected enum value")do { do { } while (false); MOZ_ReportCrash("" "Unexpected enum value"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 6270); AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected enum value"
")"); do { *((volatile int*)__null) = 6270; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
6271 return "";
6272 }
6273 MOZ_CRASH("Unexpected enum value")do { do { } while (false); MOZ_ReportCrash("" "Unexpected enum value"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 6273); AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected enum value"
")"); do { *((volatile int*)__null) = 6273; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
6274 return "";
6275}
6276
6277bool nsGlobalWindowInner::RunTimeoutHandler(Timeout* aTimeout,
6278 nsIScriptContext* aScx) {
6279 // Hold on to the timeout in case mExpr or mFunObj releases its
6280 // doc.
6281 // XXXbz Our caller guarantees it'll hold on to the timeout (because
6282 // we're MOZ_CAN_RUN_SCRIPT), so we can probably stop doing that...
6283 RefPtr<Timeout> timeout = aTimeout;
6284 Timeout* last_running_timeout = mTimeoutManager->BeginRunningTimeout(timeout);
6285 timeout->mRunning = true;
6286
6287 // Push this timeout's popup control state, which should only be
6288 // enabled the first time a timeout fires that was created while
6289 // popups were enabled and with a delay less than
6290 // "dom.disable_open_click_delay".
6291 AutoPopupStatePusherAutoPopupStatePusherInternal popupStatePusher(timeout->mPopupState);
6292
6293 // Clear the timeout's popup state, if any, to prevent interval
6294 // timeouts from repeatedly opening poups.
6295 timeout->mPopupState = PopupBlocker::openAbused;
6296
6297 uint32_t nestingLevel = TimeoutManager::GetNestingLevel();
6298 TimeoutManager::SetNestingLevel(timeout->mNestingLevel);
6299
6300 const char* reason = GetTimeoutReasonString(timeout);
6301
6302 nsCString str;
6303 if (profiler_thread_is_being_profiled_for_markers()) {
6304 TimeDuration originalInterval = timeout->When() - timeout->SubmitTime();
6305 str.Append(reason);
6306 str.Append(" with interval ");
6307 str.AppendInt(int(originalInterval.ToMilliseconds()));
6308 str.Append("ms: ");
6309 nsCString handlerDescription;
6310 timeout->mScriptHandler->GetDescription(handlerDescription);
6311 str.Append(handlerDescription);
6312 }
6313 AUTO_PROFILER_MARKER_TEXT("setTimeout callback", DOM,AutoProfilerTextMarker raiiObject6317( "setTimeout callback",
::mozilla::baseprofiler::category::DOM, MarkerOptions(MarkerStack
::TakeBacktrace( timeout->TakeProfilerBacktrace()), MarkerInnerWindowId
(mWindowID)), str)
6314 MarkerOptions(MarkerStack::TakeBacktrace(AutoProfilerTextMarker raiiObject6317( "setTimeout callback",
::mozilla::baseprofiler::category::DOM, MarkerOptions(MarkerStack
::TakeBacktrace( timeout->TakeProfilerBacktrace()), MarkerInnerWindowId
(mWindowID)), str)
6315 timeout->TakeProfilerBacktrace()),AutoProfilerTextMarker raiiObject6317( "setTimeout callback",
::mozilla::baseprofiler::category::DOM, MarkerOptions(MarkerStack
::TakeBacktrace( timeout->TakeProfilerBacktrace()), MarkerInnerWindowId
(mWindowID)), str)
6316 MarkerInnerWindowId(mWindowID)),AutoProfilerTextMarker raiiObject6317( "setTimeout callback",
::mozilla::baseprofiler::category::DOM, MarkerOptions(MarkerStack
::TakeBacktrace( timeout->TakeProfilerBacktrace()), MarkerInnerWindowId
(mWindowID)), str)
6317 str)AutoProfilerTextMarker raiiObject6317( "setTimeout callback",
::mozilla::baseprofiler::category::DOM, MarkerOptions(MarkerStack
::TakeBacktrace( timeout->TakeProfilerBacktrace()), MarkerInnerWindowId
(mWindowID)), str)
;
6318
6319 bool abortIntervalHandler;
6320 {
6321 RefPtr<TimeoutHandler> handler(timeout->mScriptHandler);
6322
6323 CallbackDebuggerNotificationGuard guard(
6324 this, timeout->mIsInterval
6325 ? DebuggerNotificationType::SetIntervalCallback
6326 : DebuggerNotificationType::SetTimeoutCallback);
6327 abortIntervalHandler = !handler->Call(reason);
6328 }
6329
6330 // If we received an uncatchable exception, do not schedule the timeout again.
6331 // This allows the slow script dialog to break easy DoS attacks like
6332 // setInterval(function() { while(1); }, 100);
6333 if (abortIntervalHandler) {
6334 // If it wasn't an interval timer to begin with, this does nothing. If it
6335 // was, we'll treat it as a timeout that we just ran and discard it when
6336 // we return.
6337 timeout->mIsInterval = false;
6338 }
6339
6340 // We ignore any failures from calling EvaluateString() on the context or
6341 // Call() on a Function here since we're in a loop
6342 // where we're likely to be running timeouts whose OS timers
6343 // didn't fire in time and we don't want to not fire those timers
6344 // now just because execution of one timer failed. We can't
6345 // propagate the error to anyone who cares about it from this
6346 // point anyway, and the script context should have already reported
6347 // the script error in the usual way - so we just drop it.
6348
6349 TimeoutManager::SetNestingLevel(nestingLevel);
6350
6351 mTimeoutManager->EndRunningTimeout(last_running_timeout);
6352 timeout->mRunning = false;
6353
6354 return timeout->mCleared;
6355}
6356
6357//*****************************************************************************
6358// nsGlobalWindowInner: Helper Functions
6359//*****************************************************************************
6360
6361already_AddRefed<nsIDocShellTreeOwner> nsGlobalWindowInner::GetTreeOwner() {
6362 FORWARD_TO_OUTER(GetTreeOwner, (), nullptr);
6363}
6364
6365already_AddRefed<nsIWebBrowserChrome>
6366nsGlobalWindowInner::GetWebBrowserChrome() {
6367 nsCOMPtr<nsIDocShellTreeOwner> treeOwner = GetTreeOwner();
6368
6369 nsCOMPtr<nsIWebBrowserChrome> browserChrome = do_GetInterface(treeOwner);
6370 return browserChrome.forget();
6371}
6372
6373ScrollContainerFrame* nsGlobalWindowInner::GetScrollContainerFrame() {
6374 FORWARD_TO_OUTER(GetScrollContainerFrame, (), nullptr);
6375}
6376
6377bool nsGlobalWindowInner::IsPrivateBrowsing() {
6378 nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(GetDocShell());
6379 return loadContext && loadContext->UsePrivateBrowsing();
6380}
6381
6382void nsGlobalWindowInner::FlushPendingNotifications(FlushType aType) {
6383 if (mDoc) {
6384 mDoc->FlushPendingNotifications(aType);
6385 }
6386}
6387
6388void nsGlobalWindowInner::EnableDeviceSensor(uint32_t aType) {
6389 bool alreadyEnabled = false;
6390 for (uint32_t i = 0; i < mEnabledSensors.Length(); i++) {
6391 if (mEnabledSensors[i] == aType) {
6392 alreadyEnabled = true;
6393 break;
6394 }
6395 }
6396
6397 mEnabledSensors.AppendElement(aType);
6398
6399 if (alreadyEnabled) {
6400 return;
6401 }
6402
6403 nsCOMPtr<nsIDeviceSensors> ac = do_GetService(NS_DEVICE_SENSORS_CONTRACTID"@mozilla.org/devicesensors;1");
6404 if (ac) {
6405 ac->AddWindowListener(aType, this);
6406 }
6407}
6408
6409void nsGlobalWindowInner::DisableDeviceSensor(uint32_t aType) {
6410 int32_t doomedElement = -1;
6411 int32_t listenerCount = 0;
6412 for (uint32_t i = 0; i < mEnabledSensors.Length(); i++) {
6413 if (mEnabledSensors[i] == aType) {
6414 doomedElement = i;
6415 listenerCount++;
6416 }
6417 }
6418
6419 if (doomedElement == -1) {
6420 return;
6421 }
6422
6423 mEnabledSensors.RemoveElementAt(doomedElement);
6424
6425 if (listenerCount > 1) {
6426 return;
6427 }
6428
6429 nsCOMPtr<nsIDeviceSensors> ac = do_GetService(NS_DEVICE_SENSORS_CONTRACTID"@mozilla.org/devicesensors;1");
6430 if (ac) {
6431 ac->RemoveWindowListener(aType, this);
6432 }
6433}
6434
6435#if defined(MOZ_WIDGET_ANDROID)
6436void nsGlobalWindowInner::EnableOrientationChangeListener() {
6437 if (!ShouldResistFingerprinting(RFPTarget::ScreenOrientation)) {
6438 mHasOrientationChangeListeners = true;
6439 mOrientationAngle = Orientation(CallerType::System);
6440 }
6441}
6442
6443void nsGlobalWindowInner::DisableOrientationChangeListener() {
6444 mHasOrientationChangeListeners = false;
6445}
6446#endif
6447
6448void nsGlobalWindowInner::SetHasGamepadEventListener(
6449 bool aHasGamepad /* = true*/) {
6450 mHasGamepad = aHasGamepad;
6451 if (aHasGamepad) {
6452 EnableGamepadUpdates();
6453 }
6454}
6455
6456void nsGlobalWindowInner::NotifyDetectXRRuntimesCompleted() {
6457 if (!mXRRuntimeDetectionInFlight) {
6458 return;
6459 }
6460 mXRRuntimeDetectionInFlight = false;
6461 if (mXRPermissionRequestInFlight) {
6462 return;
6463 }
6464 gfx::VRManagerChild* vm = gfx::VRManagerChild::Get();
6465 bool supported = vm->RuntimeSupportsVR();
6466 if (!supported) {
6467 // A VR runtime was not installed; we can suppress
6468 // the permission prompt
6469 OnXRPermissionRequestCancel();
6470 return;
6471 }
6472 // A VR runtime was found. Display a permission prompt before
6473 // allowing it to be accessed.
6474 // Connect to the VRManager in order to receive the runtime
6475 // detection results.
6476 mXRPermissionRequestInFlight = true;
6477 RefPtr<XRPermissionRequest> request =
6478 new XRPermissionRequest(this, WindowID());
6479 Unused << NS_WARN_IF(NS_FAILED(request->Start()))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(request
->Start())), 0))), "NS_FAILED(request->Start())", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 6479)
;
6480}
6481
6482void nsGlobalWindowInner::RequestXRPermission() {
6483 if (IsDying()) {
6484 // Do not proceed if the window is dying, as that will result
6485 // in leaks of objects that get re-allocated after FreeInnerObjects
6486 // has been called, including mVREventObserver.
6487 return;
6488 }
6489 if (mXRPermissionGranted) {
6490 // Don't prompt redundantly once permission to
6491 // access XR devices has been granted.
6492 OnXRPermissionRequestAllow();
6493 return;
6494 }
6495 if (mXRRuntimeDetectionInFlight || mXRPermissionRequestInFlight) {
6496 // Don't allow multiple simultaneous permissions requests;
6497 return;
6498 }
6499 // Before displaying a permission prompt, detect
6500 // if there is any VR runtime installed.
6501 gfx::VRManagerChild* vm = gfx::VRManagerChild::Get();
6502 mXRRuntimeDetectionInFlight = true;
6503 EnableVRUpdates();
6504 vm->DetectRuntimes();
6505}
6506
6507void nsGlobalWindowInner::OnXRPermissionRequestAllow() {
6508 mXRPermissionRequestInFlight = false;
6509 if (IsDying()) {
6510 // The window may have started dying while the permission request
6511 // is in flight.
6512 // Do not proceed if the window is dying, as that will result
6513 // in leaks of objects that get re-allocated after FreeInnerObjects
6514 // has been called, including mNavigator.
6515 return;
6516 }
6517 mXRPermissionGranted = true;
6518
6519 NotifyHasXRSession();
6520
6521 dom::Navigator* nav = Navigator();
6522 MOZ_ASSERT(nav != nullptr)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(nav != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(nav != nullptr))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("nav != nullptr"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 6522); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nav != nullptr"
")"); do { *((volatile int*)__null) = 6522; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6523 nav->OnXRPermissionRequestAllow();
6524}
6525
6526void nsGlobalWindowInner::OnXRPermissionRequestCancel() {
6527 mXRPermissionRequestInFlight = false;
6528 if (IsDying()) {
6529 // The window may have started dying while the permission request
6530 // is in flight.
6531 // Do not proceed if the window is dying, as that will result
6532 // in leaks of objects that get re-allocated after FreeInnerObjects
6533 // has been called, including mNavigator.
6534 return;
6535 }
6536 dom::Navigator* nav = Navigator();
6537 MOZ_ASSERT(nav != nullptr)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(nav != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(nav != nullptr))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("nav != nullptr"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 6537); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nav != nullptr"
")"); do { *((volatile int*)__null) = 6537; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6538 nav->OnXRPermissionRequestCancel();
6539}
6540
6541void nsGlobalWindowInner::EventListenerAdded(nsAtom* aType) {
6542 if (aType == nsGkAtoms::onvrdisplayactivate ||
6543 aType == nsGkAtoms::onvrdisplayconnect ||
6544 aType == nsGkAtoms::onvrdisplaydeactivate ||
6545 aType == nsGkAtoms::onvrdisplaydisconnect ||
6546 aType == nsGkAtoms::onvrdisplaypresentchange) {
6547 RequestXRPermission();
6548 }
6549
6550 if (aType == nsGkAtoms::onvrdisplayactivate) {
6551 mHasVRDisplayActivateEvents = true;
6552 }
6553
6554 if (aType == nsGkAtoms::onunload && mWindowGlobalChild) {
6555 if (++mUnloadOrBeforeUnloadListenerCount == 1) {
6556 mWindowGlobalChild->BlockBFCacheFor(BFCacheStatus::UNLOAD_LISTENER);
6557 }
6558 }
6559
6560 if (aType == nsGkAtoms::onbeforeunload && mWindowGlobalChild) {
6561 if (!mozilla::SessionHistoryInParent() ||
6562 !StaticPrefs::
6563 docshell_shistory_bfcache_ship_allow_beforeunload_listeners()) {
6564 if (++mUnloadOrBeforeUnloadListenerCount == 1) {
6565 mWindowGlobalChild->BlockBFCacheFor(
6566 BFCacheStatus::BEFOREUNLOAD_LISTENER);
6567 }
6568 }
6569 if (!mDoc || !(mDoc->GetSandboxFlags() & SANDBOXED_MODALS)) {
6570 mWindowGlobalChild->BeforeUnloadAdded();
6571 MOZ_ASSERT(mWindowGlobalChild->BeforeUnloadListeners() > 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mWindowGlobalChild->BeforeUnloadListeners() > 0
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mWindowGlobalChild->BeforeUnloadListeners() > 0
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mWindowGlobalChild->BeforeUnloadListeners() > 0", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 6571); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mWindowGlobalChild->BeforeUnloadListeners() > 0"
")"); do { *((volatile int*)__null) = 6571; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6572 }
6573 }
6574
6575 // We need to initialize localStorage in order to receive notifications.
6576 if (aType == nsGkAtoms::onstorage) {
6577 ErrorResult rv;
6578 GetLocalStorage(rv);
6579 rv.SuppressException();
6580
6581 if (NextGenLocalStorageEnabled() && mLocalStorage &&
6582 mLocalStorage->Type() == Storage::eLocalStorage) {
6583 auto object = static_cast<LSObject*>(mLocalStorage.get());
6584
6585 Unused << NS_WARN_IF(NS_FAILED(object->EnsureObserver()))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(object
->EnsureObserver())), 0))), "NS_FAILED(object->EnsureObserver())"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 6585)
;
6586 }
6587 }
6588}
6589
6590void nsGlobalWindowInner::EventListenerRemoved(nsAtom* aType) {
6591 if (aType == nsGkAtoms::onunload && mWindowGlobalChild) {
6592 MOZ_ASSERT(mUnloadOrBeforeUnloadListenerCount > 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mUnloadOrBeforeUnloadListenerCount > 0)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mUnloadOrBeforeUnloadListenerCount > 0))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("mUnloadOrBeforeUnloadListenerCount > 0"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 6592); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mUnloadOrBeforeUnloadListenerCount > 0"
")"); do { *((volatile int*)__null) = 6592; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6593 if (--mUnloadOrBeforeUnloadListenerCount == 0) {
6594 mWindowGlobalChild->UnblockBFCacheFor(BFCacheStatus::UNLOAD_LISTENER);
6595 }
6596 }
6597
6598 if (aType == nsGkAtoms::onbeforeunload && mWindowGlobalChild) {
6599 if (!mozilla::SessionHistoryInParent() ||
6600 !StaticPrefs::
6601 docshell_shistory_bfcache_ship_allow_beforeunload_listeners()) {
6602 if (--mUnloadOrBeforeUnloadListenerCount == 0) {
6603 mWindowGlobalChild->UnblockBFCacheFor(
6604 BFCacheStatus::BEFOREUNLOAD_LISTENER);
6605 }
6606 }
6607 if (!mDoc || !(mDoc->GetSandboxFlags() & SANDBOXED_MODALS)) {
6608 mWindowGlobalChild->BeforeUnloadRemoved();
6609 MOZ_ASSERT(mWindowGlobalChild->BeforeUnloadListeners() >= 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mWindowGlobalChild->BeforeUnloadListeners() >=
0)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mWindowGlobalChild->BeforeUnloadListeners() >=
0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mWindowGlobalChild->BeforeUnloadListeners() >= 0", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 6609); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mWindowGlobalChild->BeforeUnloadListeners() >= 0"
")"); do { *((volatile int*)__null) = 6609; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6610 }
6611 }
6612
6613 if (aType == nsGkAtoms::onstorage) {
6614 if (NextGenLocalStorageEnabled() && mLocalStorage &&
6615 mLocalStorage->Type() == Storage::eLocalStorage &&
6616 // The remove event is fired even if this isn't the last listener, so
6617 // only remove if there are no other listeners left.
6618 mListenerManager &&
6619 !mListenerManager->HasListenersFor(nsGkAtoms::onstorage)) {
6620 auto object = static_cast<LSObject*>(mLocalStorage.get());
6621
6622 object->DropObserver();
6623 }
6624 }
6625}
6626
6627void nsGlobalWindowInner::NotifyHasXRSession() {
6628 if (IsDying()) {
6629 // Do not proceed if the window is dying, as that will result
6630 // in leaks of objects that get re-allocated after FreeInnerObjects
6631 // has been called, including mVREventObserver.
6632 return;
6633 }
6634 if (mWindowGlobalChild && !mHasXRSession) {
6635 mWindowGlobalChild->BlockBFCacheFor(BFCacheStatus::HAS_USED_VR);
6636 }
6637 mHasXRSession = true;
6638 EnableVRUpdates();
6639}
6640
6641bool nsGlobalWindowInner::HasUsedVR() const {
6642 // Returns true only if content has enumerated and activated
6643 // XR devices. Detection of XR runtimes without activation
6644 // will not cause true to be returned.
6645 return mHasXRSession;
6646}
6647
6648bool nsGlobalWindowInner::IsVRContentDetected() const {
6649 // Returns true only if the content will respond to
6650 // the VRDisplayActivate event.
6651 return mHasVRDisplayActivateEvents;
6652}
6653
6654bool nsGlobalWindowInner::IsVRContentPresenting() const {
6655 for (const auto& display : mVRDisplays) {
6656 if (display->IsAnyPresenting(gfx::kVRGroupAll)) {
6657 return true;
6658 }
6659 }
6660 return false;
6661}
6662
6663void nsGlobalWindowInner::AddSizeOfIncludingThis(
6664 nsWindowSizes& aWindowSizes) const {
6665 aWindowSizes.mDOMSizes.mDOMOtherSize +=
6666 aWindowSizes.mState.mMallocSizeOf(this);
6667 aWindowSizes.mDOMSizes.mDOMOtherSize +=
6668 nsIGlobalObject::ShallowSizeOfExcludingThis(
6669 aWindowSizes.mState.mMallocSizeOf);
6670
6671 EventListenerManager* elm = GetExistingListenerManager();
6672 if (elm) {
6673 aWindowSizes.mDOMSizes.mDOMOtherSize +=
6674 elm->SizeOfIncludingThis(aWindowSizes.mState.mMallocSizeOf);
6675 aWindowSizes.mDOMEventListenersCount += elm->ListenerCount();
6676 }
6677 if (mDoc) {
6678 // Multiple global windows can share a document. So only measure the
6679 // document if it (a) doesn't have a global window, or (b) it's the
6680 // primary document for the window.
6681 if (!mDoc->GetInnerWindow() || mDoc->GetInnerWindow() == this) {
6682 mDoc->DocAddSizeOfIncludingThis(aWindowSizes);
6683 }
6684 }
6685
6686 if (mNavigator) {
6687 aWindowSizes.mDOMSizes.mDOMOtherSize +=
6688 mNavigator->SizeOfIncludingThis(aWindowSizes.mState.mMallocSizeOf);
6689 }
6690
6691 ForEachGlobalTeardownObserver([&](GlobalTeardownObserver* et,
6692 bool* aDoneOut) {
6693 if (nsCOMPtr<nsISizeOfEventTarget> iSizeOf = do_QueryObject(et)) {
6694 aWindowSizes.mDOMSizes.mDOMEventTargetsSize +=
6695 iSizeOf->SizeOfEventTargetIncludingThis(
6696 aWindowSizes.mState.mMallocSizeOf);
6697 }
6698 if (nsCOMPtr<DOMEventTargetHelper> helper = do_QueryObject(et)) {
6699 if (EventListenerManager* elm = helper->GetExistingListenerManager()) {
6700 aWindowSizes.mDOMEventListenersCount += elm->ListenerCount();
6701 }
6702 }
6703 ++aWindowSizes.mDOMEventTargetsCount;
6704 });
6705
6706 if (mPerformance) {
6707 aWindowSizes.mDOMSizes.mDOMPerformanceUserEntries =
6708 mPerformance->SizeOfUserEntries(aWindowSizes.mState.mMallocSizeOf);
6709 aWindowSizes.mDOMSizes.mDOMPerformanceResourceEntries =
6710 mPerformance->SizeOfResourceEntries(aWindowSizes.mState.mMallocSizeOf);
6711 aWindowSizes.mDOMSizes.mDOMPerformanceEventEntries =
6712 mPerformance->SizeOfEventEntries(aWindowSizes.mState.mMallocSizeOf);
6713 }
6714}
6715
6716void nsGlobalWindowInner::RegisterDataDocumentForMemoryReporting(
6717 Document* aDocument) {
6718 aDocument->SetAddedToMemoryReportAsDataDocument();
6719 mDataDocumentsForMemoryReporting.AppendElement(aDocument);
6720}
6721
6722void nsGlobalWindowInner::UnregisterDataDocumentForMemoryReporting(
6723 Document* aDocument) {
6724 DebugOnly<bool> found =
6725 mDataDocumentsForMemoryReporting.RemoveElement(aDocument);
6726 MOZ_ASSERT(found)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(found)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(found))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("found", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 6726); AnnotateMozCrashReason("MOZ_ASSERT" "(" "found" ")")
; do { *((volatile int*)__null) = 6726; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6727}
6728
6729void nsGlobalWindowInner::CollectDOMSizesForDataDocuments(
6730 nsWindowSizes& aSize) const {
6731 for (Document* doc : mDataDocumentsForMemoryReporting) {
6732 if (doc) {
6733 doc->DocAddSizeOfIncludingThis(aSize);
6734 }
6735 }
6736}
6737
6738void nsGlobalWindowInner::AddGamepad(GamepadHandle aHandle, Gamepad* aGamepad) {
6739 // Create the index we will present to content based on which indices are
6740 // already taken, as required by the spec.
6741 // https://w3c.github.io/gamepad/gamepad.html#widl-Gamepad-index
6742 int index = 0;
6743 while (mGamepadIndexSet.Contains(index)) {
6744 ++index;
6745 }
6746 mGamepadIndexSet.Put(index);
6747 aGamepad->SetIndex(index);
6748 mGamepads.InsertOrUpdate(aHandle, RefPtr{aGamepad});
6749}
6750
6751void nsGlobalWindowInner::RemoveGamepad(GamepadHandle aHandle) {
6752 RefPtr<Gamepad> gamepad;
6753 if (!mGamepads.Get(aHandle, getter_AddRefs(gamepad))) {
6754 return;
6755 }
6756 // Free up the index we were using so it can be reused
6757 mGamepadIndexSet.Remove(gamepad->Index());
6758 mGamepads.Remove(aHandle);
6759}
6760
6761void nsGlobalWindowInner::GetGamepads(nsTArray<RefPtr<Gamepad>>& aGamepads) {
6762 aGamepads.Clear();
6763
6764 // navigator.getGamepads() always returns an empty array when
6765 // privacy.resistFingerprinting is true.
6766 if (ShouldResistFingerprinting(RFPTarget::Gamepad)) {
6767 return;
6768 }
6769
6770 // mGamepads.Count() may not be sufficient, but it's not harmful.
6771 aGamepads.SetCapacity(mGamepads.Count());
6772 for (const auto& entry : mGamepads) {
6773 Gamepad* gamepad = entry.GetWeak();
6774 aGamepads.EnsureLengthAtLeast(gamepad->Index() + 1);
6775 aGamepads[gamepad->Index()] = gamepad;
6776 }
6777}
6778
6779already_AddRefed<mozilla::dom::Promise> nsGlobalWindowInner::RequestAllGamepads(
6780 ErrorResult& aRv) {
6781 RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService());
6782
6783 if (!gamepadManager) {
6784 aRv.Throw(NS_ERROR_UNEXPECTED);
6785 return nullptr;
6786 }
6787
6788 return gamepadManager->RequestAllGamepads(this, aRv);
6789}
6790
6791already_AddRefed<Gamepad> nsGlobalWindowInner::GetGamepad(
6792 GamepadHandle aHandle) {
6793 RefPtr<Gamepad> gamepad;
6794
6795 if (mGamepads.Get(aHandle, getter_AddRefs(gamepad))) {
6796 return gamepad.forget();
6797 }
6798
6799 return nullptr;
6800}
6801
6802void nsGlobalWindowInner::SetHasSeenGamepadInput(bool aHasSeen) {
6803 mHasSeenGamepadInput = aHasSeen;
6804}
6805
6806bool nsGlobalWindowInner::HasSeenGamepadInput() { return mHasSeenGamepadInput; }
6807
6808void nsGlobalWindowInner::SyncGamepadState() {
6809 if (mHasSeenGamepadInput) {
6810 RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService());
6811 for (const auto& entry : mGamepads) {
6812 gamepadManager->SyncGamepadState(entry.GetKey(), this, entry.GetWeak());
6813 }
6814 }
6815}
6816
6817void nsGlobalWindowInner::StopGamepadHaptics() {
6818 if (mHasSeenGamepadInput) {
6819 RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService());
6820 gamepadManager->StopHaptics();
6821 }
6822}
6823
6824bool nsGlobalWindowInner::UpdateVRDisplays(
6825 nsTArray<RefPtr<mozilla::dom::VRDisplay>>& aDevices) {
6826 VRDisplay::UpdateVRDisplays(mVRDisplays, this);
6827 aDevices = mVRDisplays.Clone();
6828 return true;
6829}
6830
6831void nsGlobalWindowInner::NotifyActiveVRDisplaysChanged() {
6832 if (mNavigator) {
6833 mNavigator->NotifyActiveVRDisplaysChanged();
6834 }
6835}
6836
6837void nsGlobalWindowInner::NotifyPresentationGenerationChanged(
6838 uint32_t aDisplayID) {
6839 for (const auto& display : mVRDisplays) {
6840 if (display->DisplayId() == aDisplayID) {
6841 display->OnPresentationGenerationChanged();
6842 }
6843 }
6844}
6845
6846void nsGlobalWindowInner::DispatchVRDisplayActivate(
6847 uint32_t aDisplayID, mozilla::dom::VRDisplayEventReason aReason) {
6848 // Ensure that our list of displays is up to date
6849 VRDisplay::UpdateVRDisplays(mVRDisplays, this);
6850
6851 // Search for the display identified with aDisplayID and fire the
6852 // event if found.
6853 for (const auto& display : mVRDisplays) {
6854 if (display->DisplayId() == aDisplayID) {
6855 if (aReason != VRDisplayEventReason::Navigation &&
6856 display->IsAnyPresenting(gfx::kVRGroupContent)) {
6857 // We only want to trigger this event if nobody is presenting to the
6858 // display already or when a page is loaded by navigating away
6859 // from a page with an active VR Presentation.
6860 continue;
6861 }
6862
6863 VRDisplayEventInit init;
6864 init.mBubbles = false;
6865 init.mCancelable = false;
6866 init.mDisplay = display;
6867 init.mReason.Construct(aReason);
6868
6869 RefPtr<VRDisplayEvent> event =
6870 VRDisplayEvent::Constructor(this, u"vrdisplayactivate"_ns, init);
6871 // vrdisplayactivate is a trusted event, allowing VRDisplay.requestPresent
6872 // to be used in response to link traversal, user request (chrome UX), and
6873 // HMD mounting detection sensors.
6874 event->SetTrusted(true);
6875 // VRDisplay.requestPresent normally requires a user gesture; however, an
6876 // exception is made to allow it to be called in response to
6877 // vrdisplayactivate during VR link traversal.
6878 display->StartHandlingVRNavigationEvent();
6879 DispatchEvent(*event);
6880 display->StopHandlingVRNavigationEvent();
6881 // Once we dispatch the event, we must not access any members as an event
6882 // listener can do anything, including closing windows.
6883 return;
6884 }
6885 }
6886}
6887
6888void nsGlobalWindowInner::DispatchVRDisplayDeactivate(
6889 uint32_t aDisplayID, mozilla::dom::VRDisplayEventReason aReason) {
6890 // Ensure that our list of displays is up to date
6891 VRDisplay::UpdateVRDisplays(mVRDisplays, this);
6892
6893 // Search for the display identified with aDisplayID and fire the
6894 // event if found.
6895 for (const auto& display : mVRDisplays) {
6896 if (display->DisplayId() == aDisplayID && display->IsPresenting()) {
6897 // We only want to trigger this event to content that is presenting to
6898 // the display already.
6899
6900 VRDisplayEventInit init;
6901 init.mBubbles = false;
6902 init.mCancelable = false;
6903 init.mDisplay = display;
6904 init.mReason.Construct(aReason);
6905
6906 RefPtr<VRDisplayEvent> event =
6907 VRDisplayEvent::Constructor(this, u"vrdisplaydeactivate"_ns, init);
6908 event->SetTrusted(true);
6909 DispatchEvent(*event);
6910 // Once we dispatch the event, we must not access any members as an event
6911 // listener can do anything, including closing windows.
6912 return;
6913 }
6914 }
6915}
6916
6917void nsGlobalWindowInner::DispatchVRDisplayConnect(uint32_t aDisplayID) {
6918 // Ensure that our list of displays is up to date
6919 VRDisplay::UpdateVRDisplays(mVRDisplays, this);
6920
6921 // Search for the display identified with aDisplayID and fire the
6922 // event if found.
6923 for (const auto& display : mVRDisplays) {
6924 if (display->DisplayId() == aDisplayID) {
6925 // Fire event even if not presenting to the display.
6926 VRDisplayEventInit init;
6927 init.mBubbles = false;
6928 init.mCancelable = false;
6929 init.mDisplay = display;
6930 // VRDisplayEvent.reason is not set for vrdisplayconnect
6931
6932 RefPtr<VRDisplayEvent> event =
6933 VRDisplayEvent::Constructor(this, u"vrdisplayconnect"_ns, init);
6934 event->SetTrusted(true);
6935 DispatchEvent(*event);
6936 // Once we dispatch the event, we must not access any members as an event
6937 // listener can do anything, including closing windows.
6938 return;
6939 }
6940 }
6941}
6942
6943void nsGlobalWindowInner::DispatchVRDisplayDisconnect(uint32_t aDisplayID) {
6944 // Ensure that our list of displays is up to date
6945 VRDisplay::UpdateVRDisplays(mVRDisplays, this);
6946
6947 // Search for the display identified with aDisplayID and fire the
6948 // event if found.
6949 for (const auto& display : mVRDisplays) {
6950 if (display->DisplayId() == aDisplayID) {
6951 // Fire event even if not presenting to the display.
6952 VRDisplayEventInit init;
6953 init.mBubbles = false;
6954 init.mCancelable = false;
6955 init.mDisplay = display;
6956 // VRDisplayEvent.reason is not set for vrdisplaydisconnect
6957
6958 RefPtr<VRDisplayEvent> event =
6959 VRDisplayEvent::Constructor(this, u"vrdisplaydisconnect"_ns, init);
6960 event->SetTrusted(true);
6961 DispatchEvent(*event);
6962 // Once we dispatch the event, we must not access any members as an event
6963 // listener can do anything, including closing windows.
6964 return;
6965 }
6966 }
6967}
6968
6969void nsGlobalWindowInner::DispatchVRDisplayPresentChange(uint32_t aDisplayID) {
6970 // Ensure that our list of displays is up to date
6971 VRDisplay::UpdateVRDisplays(mVRDisplays, this);
6972
6973 // Search for the display identified with aDisplayID and fire the
6974 // event if found.
6975 for (const auto& display : mVRDisplays) {
6976 if (display->DisplayId() == aDisplayID) {
6977 // Fire event even if not presenting to the display.
6978 VRDisplayEventInit init;
6979 init.mBubbles = false;
6980 init.mCancelable = false;
6981 init.mDisplay = display;
6982 // VRDisplayEvent.reason is not set for vrdisplaypresentchange
6983 RefPtr<VRDisplayEvent> event =
6984 VRDisplayEvent::Constructor(this, u"vrdisplaypresentchange"_ns, init);
6985 event->SetTrusted(true);
6986 DispatchEvent(*event);
6987 // Once we dispatch the event, we must not access any members as an event
6988 // listener can do anything, including closing windows.
6989 return;
6990 }
6991 }
6992}
6993
6994enum WindowState {
6995 // These constants need to match the constants in Window.webidl
6996 STATE_MAXIMIZED = 1,
6997 STATE_MINIMIZED = 2,
6998 STATE_NORMAL = 3,
6999 STATE_FULLSCREEN = 4
7000};
7001
7002uint16_t nsGlobalWindowInner::WindowState() {
7003 nsCOMPtr<nsIWidget> widget = GetMainWidget();
7004
7005 int32_t mode = widget ? widget->SizeMode() : 0;
7006
7007 switch (mode) {
7008 case nsSizeMode_Minimized:
7009 return STATE_MINIMIZED;
7010 case nsSizeMode_Maximized:
7011 return STATE_MAXIMIZED;
7012 case nsSizeMode_Fullscreen:
7013 return STATE_FULLSCREEN;
7014 case nsSizeMode_Normal:
7015 return STATE_NORMAL;
7016 default:
7017 NS_WARNING("Illegal window state for this chrome window")NS_DebugBreak(NS_DEBUG_WARNING, "Illegal window state for this chrome window"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 7017)
;
7018 break;
7019 }
7020
7021 return STATE_NORMAL;
7022}
7023
7024bool nsGlobalWindowInner::IsFullyOccluded() {
7025 nsCOMPtr<nsIWidget> widget = GetMainWidget();
7026 return widget && widget->IsFullyOccluded();
7027}
7028
7029void nsGlobalWindowInner::Maximize() {
7030 if (nsCOMPtr<nsIWidget> widget = GetMainWidget()) {
7031 widget->SetSizeMode(nsSizeMode_Maximized);
7032 }
7033}
7034
7035void nsGlobalWindowInner::Minimize() {
7036 if (nsCOMPtr<nsIWidget> widget = GetMainWidget()) {
7037 widget->SetSizeMode(nsSizeMode_Minimized);
7038 }
7039}
7040
7041void nsGlobalWindowInner::Restore() {
7042 if (nsCOMPtr<nsIWidget> widget = GetMainWidget()) {
7043 widget->SetSizeMode(nsSizeMode_Normal);
7044 }
7045}
7046
7047void nsGlobalWindowInner::GetWorkspaceID(nsAString& workspaceID) {
7048 workspaceID.Truncate();
7049 if (nsCOMPtr<nsIWidget> widget = GetMainWidget()) {
7050 return widget->GetWorkspaceID(workspaceID);
7051 }
7052}
7053
7054void nsGlobalWindowInner::MoveToWorkspace(const nsAString& workspaceID) {
7055 if (nsCOMPtr<nsIWidget> widget = GetMainWidget()) {
7056 widget->MoveToWorkspace(workspaceID);
7057 }
7058}
7059
7060void nsGlobalWindowInner::GetAttention(ErrorResult& aResult) {
7061 return GetAttentionWithCycleCount(-1, aResult);
7062}
7063
7064void nsGlobalWindowInner::GetAttentionWithCycleCount(int32_t aCycleCount,
7065 ErrorResult& aError) {
7066 nsCOMPtr<nsIWidget> widget = GetMainWidget();
7067
7068 if (widget) {
7069 aError = widget->GetAttention(aCycleCount);
7070 }
7071}
7072
7073already_AddRefed<Promise> nsGlobalWindowInner::PromiseDocumentFlushed(
7074 PromiseDocumentFlushedCallback& aCallback, ErrorResult& aError) {
7075 MOZ_RELEASE_ASSERT(IsChromeWindow())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsChromeWindow())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsChromeWindow()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("IsChromeWindow()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 7075); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "IsChromeWindow()"
")"); do { *((volatile int*)__null) = 7075; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7076
7077 if (!IsCurrentInnerWindow()) {
7078 aError.ThrowInvalidStateError("Not the current inner window");
7079 return nullptr;
7080 }
7081 if (!mDoc) {
7082 aError.ThrowInvalidStateError("No document");
7083 return nullptr;
7084 }
7085
7086 if (mIteratingDocumentFlushedResolvers) {
7087 aError.ThrowInvalidStateError("Already iterating through resolvers");
7088 return nullptr;
7089 }
7090
7091 PresShell* presShell = mDoc->GetPresShell();
7092 if (!presShell) {
7093 aError.ThrowInvalidStateError("No pres shell");
7094 return nullptr;
7095 }
7096
7097 // We need to associate the lifetime of the Promise to the lifetime
7098 // of the caller's global. That way, if the window we're observing
7099 // refresh driver ticks on goes away before our observer is fired,
7100 // we can still resolve the Promise.
7101 nsIGlobalObject* global = GetIncumbentGlobal();
7102 if (!global) {
7103 aError.ThrowInvalidStateError("No incumbent global");
7104 return nullptr;
7105 }
7106
7107 RefPtr<Promise> resultPromise = Promise::Create(global, aError);
7108 if (aError.Failed()) {
7109 return nullptr;
7110 }
7111
7112 UniquePtr<PromiseDocumentFlushedResolver> flushResolver(
7113 new PromiseDocumentFlushedResolver(resultPromise, aCallback));
7114
7115 if (!presShell->NeedStyleFlush() && !presShell->NeedLayoutFlush()) {
7116 flushResolver->Call();
7117 return resultPromise.forget();
7118 }
7119
7120 if (!TryToObserveRefresh()) {
7121 aError.ThrowInvalidStateError("Couldn't observe refresh");
7122 return nullptr;
7123 }
7124
7125 mDocumentFlushedResolvers.AppendElement(std::move(flushResolver));
7126 return resultPromise.forget();
7127}
7128
7129bool nsGlobalWindowInner::TryToObserveRefresh() {
7130 if (mObservingRefresh) {
7131 return true;
7132 }
7133
7134 if (!mDoc) {
7135 return false;
7136 }
7137
7138 nsPresContext* pc = mDoc->GetPresContext();
7139 if (!pc) {
7140 return false;
7141 }
7142
7143 mObservingRefresh = true;
7144 auto observer = MakeRefPtr<ManagedPostRefreshObserver>(
7145 pc, [win = RefPtr{this}](bool aWasCanceled) {
7146 if (win->MaybeCallDocumentFlushedResolvers(
7147 /* aUntilExhaustion = */ aWasCanceled)) {
7148 return ManagedPostRefreshObserver::Unregister::No;
7149 }
7150 win->mObservingRefresh = false;
7151 return ManagedPostRefreshObserver::Unregister::Yes;
7152 });
7153 pc->RegisterManagedPostRefreshObserver(observer.get());
7154 return mObservingRefresh;
7155}
7156
7157void nsGlobalWindowInner::CallDocumentFlushedResolvers(bool aUntilExhaustion) {
7158 while (true) {
7159 {
7160 // To coalesce MicroTask checkpoints inside callback call, enclose the
7161 // inner loop with nsAutoMicroTask, and perform a MicroTask checkpoint
7162 // after the loop.
7163 nsAutoMicroTask mt;
7164
7165 mIteratingDocumentFlushedResolvers = true;
7166
7167 auto resolvers = std::move(mDocumentFlushedResolvers);
7168 for (const auto& resolver : resolvers) {
7169 resolver->Call();
7170 }
7171
7172 mIteratingDocumentFlushedResolvers = false;
7173 }
7174
7175 // Leaving nsAutoMicroTask above will perform MicroTask checkpoint, and
7176 // Promise callbacks there may create mDocumentFlushedResolvers items.
7177
7178 // If there's no new resolvers, or we're not exhausting the queue, there's
7179 // nothing to do (we'll keep observing if there's any new observer).
7180 //
7181 // Otherwise, keep looping to call all promises. This case can happen while
7182 // destroying the window. This violates the constraint that the
7183 // promiseDocumentFlushed callback only ever run when no flush is needed,
7184 // but it's necessary to resolve the Promise returned by that.
7185 if (!aUntilExhaustion || mDocumentFlushedResolvers.IsEmpty()) {
7186 break;
7187 }
7188 }
7189}
7190
7191bool nsGlobalWindowInner::MaybeCallDocumentFlushedResolvers(
7192 bool aUntilExhaustion) {
7193 MOZ_ASSERT(mDoc)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDoc)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(mDoc))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("mDoc", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 7193); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDoc" ")");
do { *((volatile int*)__null) = 7193; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7194
7195 PresShell* presShell = mDoc->GetPresShell();
7196 if (!presShell || aUntilExhaustion) {
7197 CallDocumentFlushedResolvers(/* aUntilExhaustion = */ true);
7198 return false;
7199 }
7200
7201 if (presShell->NeedStyleFlush() || presShell->NeedLayoutFlush()) {
7202 // By the time our observer fired, something has already invalidated
7203 // style or layout - or perhaps we're still in the middle of a flush that
7204 // was interrupted. In either case, we'll wait until the next refresh driver
7205 // tick instead and try again.
7206 return true;
7207 }
7208
7209 CallDocumentFlushedResolvers(/* aUntilExhaustion = */ false);
7210 return !mDocumentFlushedResolvers.IsEmpty();
7211}
7212
7213already_AddRefed<nsWindowRoot> nsGlobalWindowInner::GetWindowRoot(
7214 mozilla::ErrorResult& aError) {
7215 FORWARD_TO_OUTER_OR_THROW(GetWindowRootOuter, (), aError, nullptr);
7216}
7217
7218void nsGlobalWindowInner::SetCursor(const nsACString& aCursor,
7219 ErrorResult& aError) {
7220 FORWARD_TO_OUTER_OR_THROW(SetCursorOuter, (aCursor, aError), aError, );
7221}
7222
7223nsIBrowserDOMWindow* nsGlobalWindowInner::GetBrowserDOMWindow(
7224 ErrorResult& aError) {
7225 FORWARD_TO_OUTER_OR_THROW(GetBrowserDOMWindow, (), aError, nullptr);
7226}
7227
7228void nsGlobalWindowInner::SetBrowserDOMWindow(
7229 nsIBrowserDOMWindow* aBrowserWindow, ErrorResult& aError) {
7230 FORWARD_TO_OUTER_OR_THROW(SetBrowserDOMWindowOuter, (aBrowserWindow),
7231 aError, );
7232}
7233
7234void nsGlobalWindowInner::NotifyDefaultButtonLoaded(Element& aDefaultButton,
7235 ErrorResult& aError) {
7236 // Don't snap to a disabled button.
7237 nsCOMPtr<nsIDOMXULControlElement> xulControl = aDefaultButton.AsXULControl();
7238 if (!xulControl) {
7239 aError.Throw(NS_ERROR_FAILURE);
7240 return;
7241 }
7242 bool disabled;
7243 aError = xulControl->GetDisabled(&disabled);
7244 if (aError.Failed() || disabled) {
7245 return;
7246 }
7247
7248 // Get the button rect in screen coordinates.
7249 nsIFrame* frame = aDefaultButton.GetPrimaryFrame();
7250 if (!frame) {
7251 aError.Throw(NS_ERROR_FAILURE);
7252 return;
7253 }
7254 LayoutDeviceIntRect buttonRect = LayoutDeviceIntRect::FromAppUnitsToNearest(
7255 frame->GetScreenRectInAppUnits(),
7256 frame->PresContext()->AppUnitsPerDevPixel());
7257
7258 // Get the widget rect in screen coordinates.
7259 nsIWidget* widget = GetNearestWidget();
7260 if (!widget) {
7261 aError.Throw(NS_ERROR_FAILURE);
7262 return;
7263 }
7264 LayoutDeviceIntRect widgetRect = widget->GetScreenBounds();
7265
7266 // Convert the buttonRect coordinates from screen to the widget.
7267 buttonRect -= widgetRect.TopLeft();
7268 nsresult rv = widget->OnDefaultButtonLoaded(buttonRect);
7269 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && rv != NS_ERROR_NOT_IMPLEMENTED) {
7270 aError.Throw(rv);
7271 }
7272}
7273
7274ChromeMessageBroadcaster* nsGlobalWindowInner::MessageManager() {
7275 MOZ_ASSERT(IsChromeWindow())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsChromeWindow())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsChromeWindow()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("IsChromeWindow()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 7275); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsChromeWindow()"
")"); do { *((volatile int*)__null) = 7275; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7276 if (!mChromeFields.mMessageManager) {
7277 RefPtr<ChromeMessageBroadcaster> globalMM =
7278 nsFrameMessageManager::GetGlobalMessageManager();
7279 mChromeFields.mMessageManager = new ChromeMessageBroadcaster(globalMM);
7280 }
7281 return mChromeFields.mMessageManager;
7282}
7283
7284ChromeMessageBroadcaster* nsGlobalWindowInner::GetGroupMessageManager(
7285 const nsAString& aGroup) {
7286 MOZ_ASSERT(IsChromeWindow())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsChromeWindow())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsChromeWindow()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("IsChromeWindow()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 7286); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsChromeWindow()"
")"); do { *((volatile int*)__null) = 7286; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7287
7288 return mChromeFields.mGroupMessageManagers
7289 .LookupOrInsertWith(
7290 aGroup,
7291 [&] {
7292 return MakeAndAddRef<ChromeMessageBroadcaster>(MessageManager());
7293 })
7294 .get();
7295}
7296
7297void nsGlobalWindowInner::InitWasOffline() { mWasOffline = NS_IsOffline(); }
7298
7299int16_t nsGlobalWindowInner::Orientation(CallerType aCallerType) {
7300 // GetOrientationAngle() returns 0, 90, 180 or 270.
7301 // window.orientation returns -90, 0, 90 or 180.
7302 if (nsIGlobalObject::ShouldResistFingerprinting(
7303 aCallerType, RFPTarget::ScreenOrientation)) {
7304 return 0;
7305 }
7306 int16_t angle = AssertedCast<int16_t>(Screen()->GetOrientationAngle());
7307 return angle <= 180 ? angle : angle - 360;
7308}
7309
7310already_AddRefed<Console> nsGlobalWindowInner::GetConsole(JSContext* aCx,
7311 ErrorResult& aRv) {
7312 if (!mConsole) {
7313 mConsole = Console::Create(aCx, this, aRv);
7314 if (NS_WARN_IF(aRv.Failed())NS_warn_if_impl(aRv.Failed(), "aRv.Failed()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 7314)
) {
7315 return nullptr;
7316 }
7317 }
7318
7319 RefPtr<Console> console = mConsole;
7320 return console.forget();
7321}
7322
7323bool nsGlobalWindowInner::IsSecureContext() const {
7324 JS::Realm* realm = js::GetNonCCWObjectRealm(GetWrapperPreserveColor());
7325 return JS::GetIsSecureContext(realm);
7326}
7327
7328External* nsGlobalWindowInner::External() {
7329 if (!mExternal) {
7330 mExternal = new dom::External(ToSupports(this));
7331 }
7332
7333 return mExternal;
7334}
7335
7336void nsGlobalWindowInner::ClearDocumentDependentSlots(JSContext* aCx) {
7337 // If JSAPI OOMs here, there is basically nothing we can do to recover safely.
7338 if (!Window_Binding::ClearCachedDocumentValue(aCx, this) ||
7339 !Window_Binding::ClearCachedPerformanceValue(aCx, this)) {
7340 MOZ_CRASH("Unhandlable OOM while clearing document dependent slots.")do { do { } while (false); MOZ_ReportCrash("" "Unhandlable OOM while clearing document dependent slots."
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 7340); AnnotateMozCrashReason("MOZ_CRASH(" "Unhandlable OOM while clearing document dependent slots."
")"); do { *((volatile int*)__null) = 7340; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
7341 }
7342}
7343
7344/* static */
7345JSObject* nsGlobalWindowInner::CreateNamedPropertiesObject(
7346 JSContext* aCx, JS::Handle<JSObject*> aProto) {
7347 return WindowNamedPropertiesHandler::Create(aCx, aProto);
7348}
7349
7350void nsGlobalWindowInner::RedefineProperty(JSContext* aCx,
7351 const char* aPropName,
7352 JS::Handle<JS::Value> aValue,
7353 ErrorResult& aError) {
7354 JS::Rooted<JSObject*> thisObj(aCx, GetWrapperPreserveColor());
7355 if (!thisObj) {
7356 aError.Throw(NS_ERROR_UNEXPECTED);
7357 return;
7358 }
7359
7360 if (!JS_WrapObject(aCx, &thisObj) ||
7361 !JS_DefineProperty(aCx, thisObj, aPropName, aValue, JSPROP_ENUMERATE)) {
7362 aError.Throw(NS_ERROR_FAILURE);
7363 }
7364}
7365
7366void nsGlobalWindowInner::FireOnNewGlobalObject() {
7367 // AutoEntryScript required to invoke debugger hook, which is a
7368 // Gecko-specific concept at present.
7369 AutoEntryScript aes(this, "nsGlobalWindowInner report new global");
7370 JS::Rooted<JSObject*> global(aes.cx(), GetWrapper());
7371 JS_FireOnNewGlobalObject(aes.cx(), global);
7372}
7373
7374#if defined(_WINDOWS_) && !defined(MOZ_WRAPPED_WINDOWS_H)
7375# pragma message( \
7376 "wrapper failure reason: " MOZ_WINDOWS_WRAPPER_DISABLED_REASON)
7377# error "Never include unwrapped windows.h in this file!"
7378#endif
7379
7380already_AddRefed<Promise> nsGlobalWindowInner::CreateImageBitmap(
7381 const ImageBitmapSource& aImage, const ImageBitmapOptions& aOptions,
7382 ErrorResult& aRv) {
7383 return ImageBitmap::Create(this, aImage, Nothing(), aOptions, aRv);
7384}
7385
7386already_AddRefed<Promise> nsGlobalWindowInner::CreateImageBitmap(
7387 const ImageBitmapSource& aImage, int32_t aSx, int32_t aSy, int32_t aSw,
7388 int32_t aSh, const ImageBitmapOptions& aOptions, ErrorResult& aRv) {
7389 return ImageBitmap::Create(
7390 this, aImage, Some(gfx::IntRect(aSx, aSy, aSw, aSh)), aOptions, aRv);
7391}
7392
7393// https://html.spec.whatwg.org/#structured-cloning
7394void nsGlobalWindowInner::StructuredClone(
7395 JSContext* aCx, JS::Handle<JS::Value> aValue,
7396 const StructuredSerializeOptions& aOptions,
7397 JS::MutableHandle<JS::Value> aRetval, ErrorResult& aError) {
7398 nsContentUtils::StructuredClone(aCx, this, aValue, aOptions, aRetval, aError);
7399}
7400
7401nsresult nsGlobalWindowInner::Dispatch(
7402 already_AddRefed<nsIRunnable>&& aRunnable) const {
7403 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/nsGlobalWindowInner.cpp"
, 7403); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 7403; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7404 return NS_DispatchToCurrentThread(std::move(aRunnable));
7405}
7406
7407nsISerialEventTarget* nsGlobalWindowInner::SerialEventTarget() const {
7408 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/nsGlobalWindowInner.cpp"
, 7408); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 7408; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7409 return GetMainThreadSerialEventTarget();
7410}
7411
7412Worklet* nsGlobalWindowInner::GetPaintWorklet(ErrorResult& aRv) {
7413 if (!mPaintWorklet) {
7414 nsIPrincipal* principal = GetPrincipal();
7415 if (!principal) {
7416 aRv.Throw(NS_ERROR_FAILURE);
7417 return nullptr;
7418 }
7419
7420 mPaintWorklet = PaintWorkletImpl::CreateWorklet(this, principal);
7421 }
7422
7423 return mPaintWorklet;
7424}
7425
7426void nsGlobalWindowInner::GetRegionalPrefsLocales(
7427 nsTArray<nsString>& aLocales) {
7428 MOZ_ASSERT(mozilla::intl::LocaleService::GetInstance())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mozilla::intl::LocaleService::GetInstance())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mozilla::intl::LocaleService::GetInstance()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("mozilla::intl::LocaleService::GetInstance()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 7428); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::intl::LocaleService::GetInstance()"
")"); do { *((volatile int*)__null) = 7428; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7429
7430 AutoTArray<nsCString, 10> rpLocales;
7431 mozilla::intl::LocaleService::GetInstance()->GetRegionalPrefsLocales(
7432 rpLocales);
7433
7434 for (const auto& loc : rpLocales) {
7435 aLocales.AppendElement(NS_ConvertUTF8toUTF16(loc));
7436 }
7437}
7438
7439void nsGlobalWindowInner::GetWebExposedLocales(nsTArray<nsString>& aLocales) {
7440 MOZ_ASSERT(mozilla::intl::LocaleService::GetInstance())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mozilla::intl::LocaleService::GetInstance())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mozilla::intl::LocaleService::GetInstance()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("mozilla::intl::LocaleService::GetInstance()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 7440); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::intl::LocaleService::GetInstance()"
")"); do { *((volatile int*)__null) = 7440; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7441
7442 AutoTArray<nsCString, 10> rpLocales;
7443 mozilla::intl::LocaleService::GetInstance()->GetWebExposedLocales(rpLocales);
7444
7445 for (const auto& loc : rpLocales) {
7446 aLocales.AppendElement(NS_ConvertUTF8toUTF16(loc));
7447 }
7448}
7449
7450IntlUtils* nsGlobalWindowInner::GetIntlUtils(ErrorResult& aError) {
7451 if (!mIntlUtils) {
7452 mIntlUtils = new IntlUtils(this);
7453 }
7454
7455 return mIntlUtils;
7456}
7457
7458void nsGlobalWindowInner::StoreSharedWorker(SharedWorker* aSharedWorker) {
7459 MOZ_ASSERT(aSharedWorker)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aSharedWorker)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aSharedWorker))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aSharedWorker",
"/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 7459); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSharedWorker"
")"); do { *((volatile int*)__null) = 7459; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7460 MOZ_ASSERT(!mSharedWorkers.Contains(aSharedWorker))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mSharedWorkers.Contains(aSharedWorker))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!mSharedWorkers.Contains(aSharedWorker)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!mSharedWorkers.Contains(aSharedWorker)"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 7460); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mSharedWorkers.Contains(aSharedWorker)"
")"); do { *((volatile int*)__null) = 7460; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7461
7462 mSharedWorkers.AppendElement(aSharedWorker);
7463}
7464
7465void nsGlobalWindowInner::ForgetSharedWorker(SharedWorker* aSharedWorker) {
7466 MOZ_ASSERT(aSharedWorker)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aSharedWorker)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aSharedWorker))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aSharedWorker",
"/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 7466); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSharedWorker"
")"); do { *((volatile int*)__null) = 7466; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7467 MOZ_ASSERT(mSharedWorkers.Contains(aSharedWorker))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mSharedWorkers.Contains(aSharedWorker))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mSharedWorkers.Contains(aSharedWorker)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mSharedWorkers.Contains(aSharedWorker)"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 7467); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mSharedWorkers.Contains(aSharedWorker)"
")"); do { *((volatile int*)__null) = 7467; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7468
7469 mSharedWorkers.RemoveElement(aSharedWorker);
7470}
7471
7472RefPtr<GenericPromise> nsGlobalWindowInner::StorageAccessPermissionChanged(
7473 bool aGranted) {
7474 // Invalidate cached StorageAllowed field so that calls to GetLocalStorage
7475 // give us the updated localStorage object.
7476 ClearStorageAllowedCache();
7477
7478 // If we're always partitioning non-cookie third party storage then
7479 // there is no need to clear it when the user accepts requestStorageAccess.
7480 if (StaticPrefs::
7481 privacy_partition_always_partition_third_party_non_cookie_storage()) {
7482 // Just reset the active cookie and storage principals
7483 nsCOMPtr<nsICookieJarSettings> cjs;
7484 if (mDoc) {
7485 cjs = mDoc->CookieJarSettings();
7486 }
7487 StorageAccess storageAccess = StorageAllowedForWindow(this);
7488 if (ShouldPartitionStorage(storageAccess) &&
7489 StoragePartitioningEnabled(storageAccess, cjs)) {
7490 if (mDoc) {
7491 mDoc->ClearActiveCookieAndStoragePrincipals();
7492 }
7493 // When storage access is granted the content process needs to request the
7494 // updated cookie list from the parent process. Otherwise the site won't
7495 // have access to unpartitioned cookies via document.cookie without a
7496 // reload.
7497 if (aGranted) {
7498 nsIChannel* channel = mDoc->GetChannel();
7499 if (channel) {
7500 // The promise resolves when the updated cookie list has been received
7501 // from the parent.
7502 return ContentChild::UpdateCookieStatus(channel);
7503 }
7504 }
7505 }
7506 }
7507
7508 PropagateStorageAccessPermissionGrantedToWorkers(*this);
7509
7510 // If we have a partitioned localStorage, it's time to replace it with a real
7511 // one in order to receive notifications.
7512
7513 if (mLocalStorage) {
7514 IgnoredErrorResult error;
7515 GetLocalStorage(error);
7516 if (NS_WARN_IF(error.Failed())NS_warn_if_impl(error.Failed(), "error.Failed()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 7516)
) {
7517 return MozPromise<bool, nsresult, true>::CreateAndReject(
7518 error.StealNSResult(), __func__);
7519 }
7520
7521 MOZ_ASSERT(mLocalStorage &&do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLocalStorage && mLocalStorage->Type() ==
Storage::eLocalStorage)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mLocalStorage && mLocalStorage
->Type() == Storage::eLocalStorage))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mLocalStorage && mLocalStorage->Type() == Storage::eLocalStorage"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 7522); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLocalStorage && mLocalStorage->Type() == Storage::eLocalStorage"
")"); do { *((volatile int*)__null) = 7522; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7522 mLocalStorage->Type() == Storage::eLocalStorage)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLocalStorage && mLocalStorage->Type() ==
Storage::eLocalStorage)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mLocalStorage && mLocalStorage
->Type() == Storage::eLocalStorage))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mLocalStorage && mLocalStorage->Type() == Storage::eLocalStorage"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 7522); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLocalStorage && mLocalStorage->Type() == Storage::eLocalStorage"
")"); do { *((volatile int*)__null) = 7522; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7523
7524 if (NextGenLocalStorageEnabled() && mListenerManager &&
7525 mListenerManager->HasListenersFor(nsGkAtoms::onstorage)) {
7526 auto object = static_cast<LSObject*>(mLocalStorage.get());
7527
7528 object->EnsureObserver();
7529 }
7530 }
7531
7532 // Reset the IndexedDB factory.
7533 mIndexedDB = nullptr;
7534
7535 // Reset DOM Cache
7536 mCacheStorage = nullptr;
7537
7538 // Reset the active cookie and storage principals
7539 if (mDoc) {
7540 mDoc->ClearActiveCookieAndStoragePrincipals();
7541 if (mWindowGlobalChild) {
7542 // XXX(farre): This is a bit backwards, but clearing the cookie
7543 // principal might make us end up with a new effective storage
7544 // principal on the child side than on the parent side, which
7545 // means that we need to sync it. See bug 1705359.
7546 mWindowGlobalChild->SetDocumentPrincipal(
7547 mDoc->NodePrincipal(), mDoc->EffectiveStoragePrincipal());
7548 }
7549 }
7550
7551 // When storage access is granted the content process needs to request the
7552 // updated cookie list from the parent process. Otherwise the site won't have
7553 // access to unpartitioned cookies via document.cookie without a reload.
7554 if (aGranted) {
7555 nsIChannel* channel = mDoc->GetChannel();
7556 if (channel) {
7557 // The promise resolves when the updated cookie list has been received
7558 // from the parent.
7559 return ContentChild::UpdateCookieStatus(channel);
7560 }
7561 }
7562 return MozPromise<bool, nsresult, true>::CreateAndResolve(true, __func__);
7563}
7564
7565ContentMediaController* nsGlobalWindowInner::GetContentMediaController() {
7566 if (mContentMediaController) {
7567 return mContentMediaController;
7568 }
7569 if (!mBrowsingContext) {
7570 return nullptr;
7571 }
7572
7573 mContentMediaController = new ContentMediaController(mBrowsingContext->Id());
7574 return mContentMediaController;
7575}
7576
7577void nsGlobalWindowInner::SetScrollMarks(const nsTArray<uint32_t>& aScrollMarks,
7578 bool aOnHScrollbar) {
7579 mScrollMarks.Assign(aScrollMarks);
7580 mScrollMarksOnHScrollbar = aOnHScrollbar;
7581
7582 // Mark the scrollbar for repainting.
7583 if (mDoc) {
7584 PresShell* presShell = mDoc->GetPresShell();
7585 if (presShell) {
7586 ScrollContainerFrame* sf = presShell->GetRootScrollContainerFrame();
7587 if (sf) {
7588 sf->InvalidateScrollbars();
7589 }
7590 }
7591 }
7592}
7593
7594/* static */
7595already_AddRefed<nsGlobalWindowInner> nsGlobalWindowInner::Create(
7596 nsGlobalWindowOuter* aOuterWindow, bool aIsChrome,
7597 WindowGlobalChild* aActor) {
7598 RefPtr<nsGlobalWindowInner> window =
7599 new nsGlobalWindowInner(aOuterWindow, aActor);
7600 if (aIsChrome) {
7601 window->mIsChrome = true;
7602 window->mCleanMessageManager = true;
7603 }
7604
7605 if (aActor) {
7606 aActor->InitWindowGlobal(window);
7607 }
7608
7609 window->InitWasOffline();
7610 return window.forget();
7611}
7612
7613JS::loader::ModuleLoaderBase* nsGlobalWindowInner::GetModuleLoader(
7614 JSContext* aCx) {
7615 Document* document = GetDocument();
7616 if (!document) {
7617 return nullptr;
7618 }
7619
7620 ScriptLoader* loader = document->ScriptLoader();
7621 if (!loader) {
7622 return nullptr;
7623 }
7624
7625 return loader->GetModuleLoader();
7626}
7627
7628void nsGlobalWindowInner::SetCurrentPasteDataTransfer(
7629 DataTransfer* aDataTransfer) {
7630 MOZ_ASSERT_IF(aDataTransfer, aDataTransfer->GetEventMessage() == ePaste)do { if (aDataTransfer) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(aDataTransfer->GetEventMessage
() == ePaste)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aDataTransfer->GetEventMessage
() == ePaste))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aDataTransfer->GetEventMessage() == ePaste", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 7630); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDataTransfer->GetEventMessage() == ePaste"
")"); do { *((volatile int*)__null) = 7630; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
7631 MOZ_ASSERT_IF(aDataTransfer, aDataTransfer->ClipboardType() ==do { if (aDataTransfer) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(aDataTransfer->ClipboardType
() == Some(nsIClipboard::kGlobalClipboard))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDataTransfer->ClipboardType
() == Some(nsIClipboard::kGlobalClipboard)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aDataTransfer->ClipboardType() == Some(nsIClipboard::kGlobalClipboard)"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 7632); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDataTransfer->ClipboardType() == Some(nsIClipboard::kGlobalClipboard)"
")"); do { *((volatile int*)__null) = 7632; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
7632 Some(nsIClipboard::kGlobalClipboard))do { if (aDataTransfer) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(aDataTransfer->ClipboardType
() == Some(nsIClipboard::kGlobalClipboard))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDataTransfer->ClipboardType
() == Some(nsIClipboard::kGlobalClipboard)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aDataTransfer->ClipboardType() == Some(nsIClipboard::kGlobalClipboard)"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 7632); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDataTransfer->ClipboardType() == Some(nsIClipboard::kGlobalClipboard)"
")"); do { *((volatile int*)__null) = 7632; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
7633 MOZ_ASSERT_IF(aDataTransfer, aDataTransfer->GetClipboardDataSnapshot())do { if (aDataTransfer) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(aDataTransfer->GetClipboardDataSnapshot
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aDataTransfer->GetClipboardDataSnapshot()))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("aDataTransfer->GetClipboardDataSnapshot()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 7633); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDataTransfer->GetClipboardDataSnapshot()"
")"); do { *((volatile int*)__null) = 7633; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
7634 mCurrentPasteDataTransfer = aDataTransfer;
7635}
7636
7637DataTransfer* nsGlobalWindowInner::GetCurrentPasteDataTransfer() const {
7638 return mCurrentPasteDataTransfer;
7639}
7640
7641TrustedTypePolicyFactory* nsGlobalWindowInner::TrustedTypes() {
7642 if (!mTrustedTypePolicyFactory) {
7643 mTrustedTypePolicyFactory = MakeRefPtr<TrustedTypePolicyFactory>(this);
7644 }
7645
7646 return mTrustedTypePolicyFactory;
7647}
7648
7649nsIURI* nsPIDOMWindowInner::GetDocumentURI() const {
7650 return mDoc ? mDoc->GetDocumentURI() : mDocumentURI.get();
7651}
7652
7653nsIURI* nsPIDOMWindowInner::GetDocBaseURI() const {
7654 return mDoc ? mDoc->GetDocBaseURI() : mDocBaseURI.get();
7655}
7656
7657mozilla::dom::WindowContext* nsPIDOMWindowInner::GetWindowContext() const {
7658 return mWindowGlobalChild ? mWindowGlobalChild->WindowContext() : nullptr;
7659}
7660
7661bool nsPIDOMWindowInner::RemoveFromBFCacheSync() {
7662 if (Document* doc = GetExtantDoc()) {
7663 return doc->RemoveFromBFCacheSync();
7664 }
7665 return false;
7666}
7667
7668void nsPIDOMWindowInner::MaybeCreateDoc() {
7669 // XXX: Forward to outer?
7670 MOZ_ASSERT(!mDoc)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mDoc)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(!mDoc))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("!mDoc", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 7670); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mDoc" ")")
; do { *((volatile int*)__null) = 7670; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7671 if (nsIDocShell* docShell = GetDocShell()) {
7672 // Note that |document| here is the same thing as our mDoc, but we
7673 // don't have to explicitly set the member variable because the docshell
7674 // has already called SetNewDocument().
7675 nsCOMPtr<Document> document = docShell->GetDocument();
7676 Unused << document;
7677 }
7678}
7679
7680mozilla::dom::DocGroup* nsPIDOMWindowInner::GetDocGroup() const {
7681 Document* doc = GetExtantDoc();
7682 if (doc) {
7683 return doc->GetDocGroup();
7684 }
7685 return nullptr;
7686}
7687
7688mozilla::dom::BrowsingContextGroup*
7689nsPIDOMWindowInner::GetBrowsingContextGroup() const {
7690 return mBrowsingContext ? mBrowsingContext->Group() : nullptr;
7691}
7692
7693nsIGlobalObject* nsPIDOMWindowInner::AsGlobal() {
7694 return nsGlobalWindowInner::Cast(this);
7695}
7696
7697const nsIGlobalObject* nsPIDOMWindowInner::AsGlobal() const {
7698 return nsGlobalWindowInner::Cast(this);
7699}
7700
7701RefPtr<GenericPromise>
7702nsPIDOMWindowInner::SaveStorageAccessPermissionGranted() {
7703 WindowContext* wc = GetWindowContext();
7704 if (wc) {
7705 Unused << wc->SetUsingStorageAccess(true);
7706 }
7707
7708 return nsGlobalWindowInner::Cast(this)->StorageAccessPermissionChanged(true);
7709}
7710
7711RefPtr<GenericPromise>
7712nsPIDOMWindowInner::SaveStorageAccessPermissionRevoked() {
7713 WindowContext* wc = GetWindowContext();
7714 if (wc) {
7715 Unused << wc->SetUsingStorageAccess(false);
7716 }
7717
7718 return nsGlobalWindowInner::Cast(this)->StorageAccessPermissionChanged(false);
7719}
7720
7721bool nsPIDOMWindowInner::UsingStorageAccess() {
7722 WindowContext* wc = GetWindowContext();
7723 if (!wc) {
7724 return false;
7725 }
7726
7727 return wc->GetUsingStorageAccess();
7728}
7729
7730nsPIDOMWindowInner::nsPIDOMWindowInner(nsPIDOMWindowOuter* aOuterWindow,
7731 WindowGlobalChild* aActor)
7732 : mMutationBits(0),
7733 mIsDocumentLoaded(false),
7734 mIsHandlingResizeEvent(false),
7735 mMayHaveDOMActivateEventListeners(false),
7736 mMayHavePaintEventListener(false),
7737 mMayHaveTouchEventListener(false),
7738 mMayHaveSelectionChangeEventListener(false),
7739 mMayHaveFormSelectEventListener(false),
7740 mMayHaveMouseEnterLeaveEventListener(false),
7741 mMayHavePointerEnterLeaveEventListener(false),
7742 mMayHaveTransitionEventListener(false),
7743 mMayHaveSMILTimeEventListener(false),
7744 mMayHaveBeforeInputEventListenerForTelemetry(false),
7745 mMutationObserverHasObservedNodeForTelemetry(false),
7746 mOuterWindow(aOuterWindow),
7747 mWindowID(0),
7748 mHasNotifiedGlobalCreated(false),
7749 mMarkedCCGeneration(0),
7750 mHasTriedToCacheTopInnerWindow(false),
7751 mNumOfIndexedDBDatabases(0),
7752 mNumOfOpenWebSockets(0),
7753 mEvent(nullptr),
7754 mWindowGlobalChild(aActor),
7755 mWasSuspendedByGroup(false) {
7756 MOZ_ASSERT(aOuterWindow)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aOuterWindow)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aOuterWindow))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aOuterWindow", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 7756); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOuterWindow"
")"); do { *((volatile int*)__null) = 7756; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7757 mBrowsingContext = aOuterWindow->GetBrowsingContext();
7758
7759 if (mWindowGlobalChild) {
7760 mWindowID = aActor->InnerWindowId();
7761
7762 MOZ_ASSERT(mWindowGlobalChild->BrowsingContext() == mBrowsingContext)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mWindowGlobalChild->BrowsingContext() == mBrowsingContext
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mWindowGlobalChild->BrowsingContext() == mBrowsingContext
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mWindowGlobalChild->BrowsingContext() == mBrowsingContext"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 7762); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mWindowGlobalChild->BrowsingContext() == mBrowsingContext"
")"); do { *((volatile int*)__null) = 7762; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7763 } else {
7764 mWindowID = nsContentUtils::GenerateWindowId();
7765 }
7766}
7767
7768nsPIDOMWindowInner::~nsPIDOMWindowInner() = default;
7769
7770#undef FORWARD_TO_OUTER
7771#undef FORWARD_TO_OUTER_OR_THROW
7772#undef FORWARD_TO_OUTER_VOID