Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp
Warning:line 5224, 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-27-022226-2793976-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::MaybeResolvePendingCredentialPromise(
3654 const RefPtr<mozilla::dom::Credential>& aCredential) {
3655 if (!mPendingCredential) {
3656 // If we don't have a pending promise, that is okay.
3657 return;
3658 }
3659 mPendingCredential->MaybeResolve(aCredential);
3660 mPendingCredential = nullptr;
3661}
3662
3663nsresult nsGlobalWindowInner::SetPendingCredentialPromise(
3664 const RefPtr<mozilla::dom::Promise>& aPromise) {
3665 if (mPendingCredential) {
3666 return nsresult::NS_ERROR_DOM_INVALID_STATE_ERR;
3667 }
3668 mPendingCredential = aPromise;
3669 return NS_OK;
3670}
3671
3672void nsGlobalWindowInner::Dump(const nsAString& aStr) {
3673 if (!nsJSUtils::DumpEnabled()) {
3674 return;
3675 }
3676
3677 char* cstr = ToNewUTF8String(aStr);
3678
3679#if defined(XP_MACOSX)
3680 // have to convert \r to \n so that printing to the console works
3681 char *c = cstr, *cEnd = cstr + strlen(cstr);
3682 while (c < cEnd) {
3683 if (*c == '\r') *c = '\n';
3684 c++;
3685 }
3686#endif
3687
3688 if (cstr) {
3689 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)
3690 ("[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)
;
3691#ifdef XP_WIN
3692 PrintToDebugger(cstr);
3693#endif
3694#ifdef ANDROID
3695 __android_log_write(ANDROID_LOG_INFO, "GeckoDump", cstr);
3696#endif
3697 FILE* fp = gDumpFile ? gDumpFile : stdoutstdout;
3698 fputs(cstr, fp);
3699 fflush(fp);
3700 free(cstr);
3701 }
3702}
3703
3704void nsGlobalWindowInner::Alert(nsIPrincipal& aSubjectPrincipal,
3705 ErrorResult& aError) {
3706 Alert(u""_ns, aSubjectPrincipal, aError);
3707}
3708
3709void nsGlobalWindowInner::Alert(const nsAString& aMessage,
3710 nsIPrincipal& aSubjectPrincipal,
3711 ErrorResult& aError) {
3712 FORWARD_TO_OUTER_OR_THROW(AlertOuter, (aMessage, aSubjectPrincipal, aError),
3713 aError, );
3714}
3715
3716bool nsGlobalWindowInner::Confirm(const nsAString& aMessage,
3717 nsIPrincipal& aSubjectPrincipal,
3718 ErrorResult& aError) {
3719 FORWARD_TO_OUTER_OR_THROW(ConfirmOuter, (aMessage, aSubjectPrincipal, aError),
3720 aError, false);
3721}
3722
3723already_AddRefed<Promise> nsGlobalWindowInner::Fetch(
3724 const RequestOrUTF8String& aInput, const RequestInit& aInit,
3725 CallerType aCallerType, ErrorResult& aRv) {
3726 return FetchRequest(this, aInput, aInit, aCallerType, aRv);
3727}
3728
3729void nsGlobalWindowInner::Prompt(const nsAString& aMessage,
3730 const nsAString& aInitial, nsAString& aReturn,
3731 nsIPrincipal& aSubjectPrincipal,
3732 ErrorResult& aError) {
3733 FORWARD_TO_OUTER_OR_THROW(
3734 PromptOuter, (aMessage, aInitial, aReturn, aSubjectPrincipal, aError),
3735 aError, );
3736}
3737
3738void nsGlobalWindowInner::Focus(CallerType aCallerType, ErrorResult& aError) {
3739 FORWARD_TO_OUTER_OR_THROW(FocusOuter,
3740 (aCallerType, /* aFromOtherProcess */ false,
3741 nsFocusManager::GenerateFocusActionId()),
3742 aError, );
3743}
3744
3745nsresult nsGlobalWindowInner::Focus(CallerType aCallerType) {
3746 ErrorResult rv;
3747 Focus(aCallerType, rv);
3748
3749 return rv.StealNSResult();
3750}
3751
3752void nsGlobalWindowInner::Blur(CallerType aCallerType, ErrorResult& aError) {
3753 FORWARD_TO_OUTER_OR_THROW(BlurOuter, (aCallerType), aError, );
3754}
3755
3756void nsGlobalWindowInner::Stop(ErrorResult& aError) {
3757 FORWARD_TO_OUTER_OR_THROW(StopOuter, (aError), aError, );
3758}
3759
3760void nsGlobalWindowInner::Print(ErrorResult& aError) {
3761 FORWARD_TO_OUTER_OR_THROW(PrintOuter, (aError), aError, );
3762}
3763
3764Nullable<WindowProxyHolder> nsGlobalWindowInner::PrintPreview(
3765 nsIPrintSettings* aSettings, nsIWebProgressListener* aListener,
3766 nsIDocShell* aDocShellToCloneInto, ErrorResult& aError) {
3767 FORWARD_TO_OUTER_OR_THROW(
3768 Print,
3769 (aSettings,
3770 /* aRemotePrintJob = */ nullptr, aListener, aDocShellToCloneInto,
3771 nsGlobalWindowOuter::IsPreview::Yes,
3772 nsGlobalWindowOuter::IsForWindowDotPrint::No,
3773 /* aPrintPreviewCallback = */ nullptr, nullptr, aError),
3774 aError, nullptr);
3775}
3776
3777void nsGlobalWindowInner::MoveTo(int32_t aXPos, int32_t aYPos,
3778 CallerType aCallerType, ErrorResult& aError) {
3779 FORWARD_TO_OUTER_OR_THROW(MoveToOuter, (aXPos, aYPos, aCallerType, aError),
3780 aError, );
3781}
3782
3783void nsGlobalWindowInner::MoveBy(int32_t aXDif, int32_t aYDif,
3784 CallerType aCallerType, ErrorResult& aError) {
3785 FORWARD_TO_OUTER_OR_THROW(MoveByOuter, (aXDif, aYDif, aCallerType, aError),
3786 aError, );
3787}
3788
3789void nsGlobalWindowInner::ResizeTo(int32_t aWidth, int32_t aHeight,
3790 CallerType aCallerType,
3791 ErrorResult& aError) {
3792 FORWARD_TO_OUTER_OR_THROW(ResizeToOuter,
3793 (aWidth, aHeight, aCallerType, aError), aError, );
3794}
3795
3796void nsGlobalWindowInner::ResizeBy(int32_t aWidthDif, int32_t aHeightDif,
3797 CallerType aCallerType,
3798 ErrorResult& aError) {
3799 FORWARD_TO_OUTER_OR_THROW(
3800 ResizeByOuter, (aWidthDif, aHeightDif, aCallerType, aError), aError, );
3801}
3802
3803void nsGlobalWindowInner::SizeToContent(CallerType aCallerType,
3804 ErrorResult& aError) {
3805 FORWARD_TO_OUTER_OR_THROW(SizeToContentOuter, (aCallerType, {}, aError),
3806 aError, );
3807}
3808
3809void nsGlobalWindowInner::SizeToContentConstrained(
3810 const SizeToContentConstraints& aConstraints, ErrorResult& aError) {
3811 FORWARD_TO_OUTER_OR_THROW(
3812 SizeToContentOuter, (CallerType::System, aConstraints, aError), aError, );
3813}
3814
3815already_AddRefed<nsPIWindowRoot> nsGlobalWindowInner::GetTopWindowRoot() {
3816 nsGlobalWindowOuter* outer = GetOuterWindowInternal();
3817 if (!outer) {
3818 return nullptr;
3819 }
3820 return outer->GetTopWindowRoot();
3821}
3822
3823void nsGlobalWindowInner::ScrollTo(double aXScroll, double aYScroll) {
3824 ScrollToOptions options;
3825 options.mLeft.Construct(aXScroll);
3826 options.mTop.Construct(aYScroll);
3827 ScrollTo(options);
3828}
3829
3830void nsGlobalWindowInner::ScrollTo(const ScrollToOptions& aOptions) {
3831 Maybe<int32_t> left;
3832 Maybe<int32_t> top;
3833 if (aOptions.mLeft.WasPassed()) {
3834 left.emplace(static_cast<int32_t>(
3835 mozilla::ToZeroIfNonfinite(aOptions.mLeft.Value())));
3836 }
3837 if (aOptions.mTop.WasPassed()) {
3838 top.emplace(static_cast<int32_t>(
3839 mozilla::ToZeroIfNonfinite(aOptions.mTop.Value())));
3840 }
3841
3842 // When scrolling to a non-zero offset, we need to determine whether that
3843 // position is within our scrollable range, so we need updated layout
3844 // information.
3845 if ((top && *top != 0) || (left && *left != 0)) {
3846 FlushPendingNotifications(FlushType::Layout);
3847 }
3848
3849 ScrollContainerFrame* sf = GetScrollContainerFrame();
3850 if (!sf) {
3851 return;
3852 }
3853 CSSIntPoint scrollPos = sf->GetRoundedScrollPositionCSSPixels();
3854 if (left) {
3855 scrollPos.x = *left;
3856 }
3857 if (top) {
3858 scrollPos.y = *top;
3859 }
3860 // Here we calculate what the max pixel value is that we can
3861 // scroll to, we do this by dividing maxint with the pixel to
3862 // twips conversion factor, and subtracting 4, the 4 comes from
3863 // experimenting with this value, anything less makes the view
3864 // code not scroll correctly, I have no idea why. -- jst
3865 const int32_t maxpx = nsPresContext::AppUnitsToIntCSSPixels(0x7fffffff) - 4;
3866 if (scrollPos.x > maxpx) {
3867 scrollPos.x = maxpx;
3868 }
3869 if (scrollPos.y > maxpx) {
3870 scrollPos.y = maxpx;
3871 }
3872 auto scrollMode = sf->IsSmoothScroll(aOptions.mBehavior)
3873 ? ScrollMode::SmoothMsd
3874 : ScrollMode::Instant;
3875 sf->ScrollToCSSPixels(scrollPos, scrollMode);
3876}
3877
3878void nsGlobalWindowInner::ScrollBy(double aXScrollDif, double aYScrollDif) {
3879 ScrollToOptions options;
3880 options.mLeft.Construct(aXScrollDif);
3881 options.mTop.Construct(aYScrollDif);
3882 // It seems like it would make more sense for ScrollBy to use
3883 // SMOOTH mode, but tests seem to depend on the synchronous behaviour.
3884 // Perhaps Web content does too.
3885 ScrollBy(options);
3886}
3887
3888void nsGlobalWindowInner::ScrollBy(const ScrollToOptions& aOptions) {
3889 CSSIntPoint scrollDelta;
3890 if (aOptions.mLeft.WasPassed()) {
3891 scrollDelta.x = static_cast<int32_t>(
3892 mozilla::ToZeroIfNonfinite(aOptions.mLeft.Value()));
3893 }
3894 if (aOptions.mTop.WasPassed()) {
3895 scrollDelta.y =
3896 static_cast<int32_t>(mozilla::ToZeroIfNonfinite(aOptions.mTop.Value()));
3897 }
3898
3899 if (!scrollDelta.x && !scrollDelta.y) {
3900 return;
3901 }
3902
3903 FlushPendingNotifications(FlushType::Layout);
3904 ScrollContainerFrame* sf = GetScrollContainerFrame();
3905 if (!sf) {
3906 return;
3907 }
3908
3909 auto scrollMode = sf->IsSmoothScroll(aOptions.mBehavior)
3910 ? ScrollMode::SmoothMsd
3911 : ScrollMode::Instant;
3912 sf->ScrollByCSSPixels(scrollDelta, scrollMode);
3913}
3914
3915void nsGlobalWindowInner::ScrollByLines(int32_t numLines,
3916 const ScrollOptions& aOptions) {
3917 if (!numLines) {
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 ScrollByLines 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 sf->ScrollBy(nsIntPoint(0, numLines), ScrollUnit::LINES, scrollMode);
3932}
3933
3934void nsGlobalWindowInner::ScrollByPages(int32_t numPages,
3935 const ScrollOptions& aOptions) {
3936 if (!numPages) {
3937 return;
3938 }
3939 FlushPendingNotifications(FlushType::Layout);
3940 ScrollContainerFrame* sf = GetScrollContainerFrame();
3941 if (!sf) {
3942 return;
3943 }
3944 // It seems like it would make more sense for ScrollByPages to use
3945 // SMOOTH mode, but tests seem to depend on the synchronous behaviour.
3946 // Perhaps Web content does too.
3947 ScrollMode scrollMode = sf->IsSmoothScroll(aOptions.mBehavior)
3948 ? ScrollMode::SmoothMsd
3949 : ScrollMode::Instant;
3950
3951 sf->ScrollBy(nsIntPoint(0, numPages), ScrollUnit::PAGES, scrollMode);
3952}
3953
3954void nsGlobalWindowInner::MozScrollSnap() {
3955 FlushPendingNotifications(FlushType::Layout);
3956 if (ScrollContainerFrame* sf = GetScrollContainerFrame()) {
3957 sf->ScrollSnap();
3958 }
3959}
3960
3961void nsGlobalWindowInner::ClearTimeout(int32_t aHandle) {
3962 DebuggerNotificationDispatch(this, DebuggerNotificationType::ClearTimeout);
3963
3964 if (aHandle > 0) {
3965 mTimeoutManager->ClearTimeout(aHandle, Timeout::Reason::eTimeoutOrInterval);
3966 }
3967}
3968
3969void nsGlobalWindowInner::ClearInterval(int32_t aHandle) {
3970 DebuggerNotificationDispatch(this, DebuggerNotificationType::ClearInterval);
3971
3972 if (aHandle > 0) {
3973 mTimeoutManager->ClearTimeout(aHandle, Timeout::Reason::eTimeoutOrInterval);
3974 }
3975}
3976
3977void nsGlobalWindowInner::SetResizable(bool aResizable) const {
3978 // nop
3979}
3980
3981void nsGlobalWindowInner::CaptureEvents() {
3982 if (mDoc) {
3983 mDoc->WarnOnceAbout(DeprecatedOperations::eUseOfCaptureEvents);
3984 }
3985}
3986
3987void nsGlobalWindowInner::ReleaseEvents() {
3988 if (mDoc) {
3989 mDoc->WarnOnceAbout(DeprecatedOperations::eUseOfReleaseEvents);
3990 }
3991}
3992
3993Nullable<WindowProxyHolder> nsGlobalWindowInner::Open(const nsAString& aUrl,
3994 const nsAString& aName,
3995 const nsAString& aOptions,
3996 ErrorResult& aError) {
3997 FORWARD_TO_OUTER_OR_THROW(OpenOuter, (aUrl, aName, aOptions, aError), aError,
3998 nullptr);
3999}
4000
4001Nullable<WindowProxyHolder> nsGlobalWindowInner::OpenDialog(
4002 JSContext* aCx, const nsAString& aUrl, const nsAString& aName,
4003 const nsAString& aOptions, const Sequence<JS::Value>& aExtraArgument,
4004 ErrorResult& aError) {
4005 FORWARD_TO_OUTER_OR_THROW(
4006 OpenDialogOuter, (aCx, aUrl, aName, aOptions, aExtraArgument, aError),
4007 aError, nullptr);
4008}
4009
4010WindowProxyHolder nsGlobalWindowInner::GetFrames(ErrorResult& aError) {
4011 FORWARD_TO_OUTER_OR_THROW(GetFramesOuter, (), aError, Window());
4012}
4013
4014void nsGlobalWindowInner::PostMessageMoz(JSContext* aCx,
4015 JS::Handle<JS::Value> aMessage,
4016 const nsAString& aTargetOrigin,
4017 JS::Handle<JS::Value> aTransfer,
4018 nsIPrincipal& aSubjectPrincipal,
4019 ErrorResult& aError) {
4020 FORWARD_TO_OUTER_OR_THROW(
4021 PostMessageMozOuter,
4022 (aCx, aMessage, aTargetOrigin, aTransfer, aSubjectPrincipal, aError),
4023 aError, );
4024}
4025
4026void nsGlobalWindowInner::PostMessageMoz(JSContext* aCx,
4027 JS::Handle<JS::Value> aMessage,
4028 const nsAString& aTargetOrigin,
4029 const Sequence<JSObject*>& aTransfer,
4030 nsIPrincipal& aSubjectPrincipal,
4031 ErrorResult& aRv) {
4032 JS::Rooted<JS::Value> transferArray(aCx, JS::UndefinedValue());
4033
4034 aRv = nsContentUtils::CreateJSValueFromSequenceOfObject(aCx, aTransfer,
4035 &transferArray);
4036 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"
, 4036)
) {
4037 return;
4038 }
4039
4040 PostMessageMoz(aCx, aMessage, aTargetOrigin, transferArray, aSubjectPrincipal,
4041 aRv);
4042}
4043
4044void nsGlobalWindowInner::PostMessageMoz(
4045 JSContext* aCx, JS::Handle<JS::Value> aMessage,
4046 const WindowPostMessageOptions& aOptions, nsIPrincipal& aSubjectPrincipal,
4047 ErrorResult& aRv) {
4048 JS::Rooted<JS::Value> transferArray(aCx, JS::UndefinedValue());
4049
4050 aRv = nsContentUtils::CreateJSValueFromSequenceOfObject(
4051 aCx, aOptions.mTransfer, &transferArray);
4052 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"
, 4052)
) {
4053 return;
4054 }
4055
4056 PostMessageMoz(aCx, aMessage, aOptions.mTargetOrigin, transferArray,
4057 aSubjectPrincipal, aRv);
4058}
4059
4060void nsGlobalWindowInner::Close(CallerType aCallerType, ErrorResult& aError) {
4061 FORWARD_TO_OUTER_OR_THROW(CloseOuter, (aCallerType == CallerType::System),
4062 aError, );
4063}
4064
4065nsresult nsGlobalWindowInner::Close() {
4066 FORWARD_TO_OUTER(Close, (), NS_ERROR_UNEXPECTED);
4067}
4068
4069bool nsGlobalWindowInner::IsInModalState() {
4070 FORWARD_TO_OUTER(IsInModalState, (), false);
4071}
4072
4073// static
4074void nsGlobalWindowInner::NotifyDOMWindowDestroyed(
4075 nsGlobalWindowInner* aWindow) {
4076 nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
4077 if (observerService) {
4078 observerService->NotifyObservers(ToSupports(aWindow),
4079 DOM_WINDOW_DESTROYED_TOPIC"dom-window-destroyed", nullptr);
4080 }
4081}
4082
4083void nsGlobalWindowInner::NotifyWindowIDDestroyed(const char* aTopic) {
4084 nsCOMPtr<nsIRunnable> runnable =
4085 new WindowDestroyedEvent(this, mWindowID, aTopic);
4086 Dispatch(runnable.forget());
4087}
4088
4089// static
4090void nsGlobalWindowInner::NotifyDOMWindowFrozen(nsGlobalWindowInner* aWindow) {
4091 if (aWindow) {
4092 nsCOMPtr<nsIObserverService> observerService =
4093 services::GetObserverService();
4094 if (observerService) {
4095 observerService->NotifyObservers(ToSupports(aWindow),
4096 DOM_WINDOW_FROZEN_TOPIC"dom-window-frozen", nullptr);
4097 }
4098 }
4099}
4100
4101// static
4102void nsGlobalWindowInner::NotifyDOMWindowThawed(nsGlobalWindowInner* aWindow) {
4103 if (aWindow) {
4104 nsCOMPtr<nsIObserverService> observerService =
4105 services::GetObserverService();
4106 if (observerService) {
4107 observerService->NotifyObservers(ToSupports(aWindow),
4108 DOM_WINDOW_THAWED_TOPIC"dom-window-thawed", nullptr);
4109 }
4110 }
4111}
4112
4113Element* nsGlobalWindowInner::GetFrameElement(nsIPrincipal& aSubjectPrincipal,
4114 ErrorResult& aError) {
4115 FORWARD_TO_OUTER_OR_THROW(GetFrameElement, (aSubjectPrincipal), aError,
4116 nullptr);
4117}
4118
4119Element* nsGlobalWindowInner::GetRealFrameElement(ErrorResult& aError) {
4120 FORWARD_TO_OUTER_OR_THROW(GetFrameElement, (), aError, nullptr);
4121}
4122
4123void nsGlobalWindowInner::UpdateCommands(const nsAString& anAction) {
4124 if (GetOuterWindowInternal()) {
4125 GetOuterWindowInternal()->UpdateCommands(anAction);
4126 }
4127}
4128
4129Selection* nsGlobalWindowInner::GetSelection(ErrorResult& aError) {
4130 FORWARD_TO_OUTER_OR_THROW(GetSelectionOuter, (), aError, nullptr);
4131}
4132
4133WebTaskScheduler* nsGlobalWindowInner::Scheduler() {
4134 if (!mWebTaskScheduler) {
4135 mWebTaskScheduler = WebTaskScheduler::CreateForMainThread(this);
4136 }
4137 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"
, 4137); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mWebTaskScheduler"
")"); do { *((volatile int*)__null) = 4137; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4138 return mWebTaskScheduler;
4139}
4140
4141bool nsGlobalWindowInner::Find(const nsAString& aString, bool aCaseSensitive,
4142 bool aBackwards, bool aWrapAround,
4143 bool aWholeWord, bool aSearchInFrames,
4144 bool aShowDialog, ErrorResult& aError) {
4145 FORWARD_TO_OUTER_OR_THROW(FindOuter,
4146 (aString, aCaseSensitive, aBackwards, aWrapAround,
4147 aWholeWord, aSearchInFrames, aShowDialog, aError),
4148 aError, false);
4149}
4150
4151void nsGlobalWindowInner::GetOrigin(nsAString& aOrigin) {
4152 nsContentUtils::GetWebExposedOriginSerialization(GetPrincipal(), aOrigin);
4153}
4154
4155// See also AutoJSAPI::ReportException
4156void nsGlobalWindowInner::ReportError(JSContext* aCx,
4157 JS::Handle<JS::Value> aError,
4158 CallerType aCallerType,
4159 ErrorResult& aRv) {
4160 if (MOZ_UNLIKELY(!HasActiveDocument())(__builtin_expect(!!(!HasActiveDocument()), 0))) {
4161 return aRv.Throw(NS_ERROR_XPC_SECURITY_MANAGER_VETO);
4162 }
4163
4164 JS::ErrorReportBuilder jsReport(aCx);
4165 JS::ExceptionStack exnStack(aCx, aError, nullptr);
4166 if (!jsReport.init(aCx, exnStack, JS::ErrorReportBuilder::NoSideEffects)) {
4167 return aRv.NoteJSContextException(aCx);
4168 }
4169
4170 RefPtr<xpc::ErrorReport> xpcReport = new xpc::ErrorReport();
4171 bool isChrome = aCallerType == CallerType::System;
4172 xpcReport->Init(jsReport.report(), jsReport.toStringResult().c_str(),
4173 isChrome, WindowID());
4174
4175 JS::RootingContext* rcx = JS::RootingContext::get(aCx);
4176 DispatchScriptErrorEvent(this, rcx, xpcReport, exnStack.exception(),
4177 exnStack.stack());
4178}
4179
4180void nsGlobalWindowInner::Atob(const nsAString& aAsciiBase64String,
4181 nsAString& aBinaryData, ErrorResult& aError) {
4182 aError = nsContentUtils::Atob(aAsciiBase64String, aBinaryData);
4183}
4184
4185void nsGlobalWindowInner::Btoa(const nsAString& aBinaryData,
4186 nsAString& aAsciiBase64String,
4187 ErrorResult& aError) {
4188 aError = nsContentUtils::Btoa(aBinaryData, aAsciiBase64String);
4189}
4190
4191//*****************************************************************************
4192// EventTarget
4193//*****************************************************************************
4194
4195nsPIDOMWindowOuter* nsGlobalWindowInner::GetOwnerGlobalForBindingsInternal() {
4196 return nsPIDOMWindowOuter::GetFromCurrentInner(this);
4197}
4198
4199bool nsGlobalWindowInner::DispatchEvent(Event& aEvent, CallerType aCallerType,
4200 ErrorResult& aRv) {
4201 if (!IsCurrentInnerWindow()) {
4202 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"
, 4204)
4203 "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"
, 4204)
4204 "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"
, 4204)
;
4205 aRv.Throw(NS_ERROR_FAILURE);
4206 return false;
4207 }
4208
4209 if (!mDoc) {
4210 aRv.Throw(NS_ERROR_FAILURE);
4211 return false;
4212 }
4213
4214 // Obtain a presentation shell
4215 RefPtr<nsPresContext> presContext = mDoc->GetPresContext();
4216
4217 nsEventStatus status = nsEventStatus_eIgnore;
4218 nsresult rv = EventDispatcher::DispatchDOMEvent(this, nullptr, &aEvent,
4219 presContext, &status);
4220 bool retval = !aEvent.DefaultPrevented(aCallerType);
4221 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4222 aRv.Throw(rv);
4223 }
4224 return retval;
4225}
4226
4227mozilla::Maybe<mozilla::dom::EventCallbackDebuggerNotificationType>
4228nsGlobalWindowInner::GetDebuggerNotificationType() const {
4229 return mozilla::Some(
4230 mozilla::dom::EventCallbackDebuggerNotificationType::Global);
4231}
4232
4233bool nsGlobalWindowInner::ComputeDefaultWantsUntrusted(ErrorResult& aRv) {
4234 return !nsContentUtils::IsChromeDoc(mDoc);
4235}
4236
4237EventListenerManager* nsGlobalWindowInner::GetOrCreateListenerManager() {
4238 if (!mListenerManager) {
4239 mListenerManager =
4240 new EventListenerManager(static_cast<EventTarget*>(this));
4241 }
4242
4243 return mListenerManager;
4244}
4245
4246EventListenerManager* nsGlobalWindowInner::GetExistingListenerManager() const {
4247 return mListenerManager;
4248}
4249
4250mozilla::dom::DebuggerNotificationManager*
4251nsGlobalWindowInner::GetOrCreateDebuggerNotificationManager() {
4252 if (!mDebuggerNotificationManager) {
4253 mDebuggerNotificationManager = new DebuggerNotificationManager(this);
4254 }
4255
4256 return mDebuggerNotificationManager;
4257}
4258
4259mozilla::dom::DebuggerNotificationManager*
4260nsGlobalWindowInner::GetExistingDebuggerNotificationManager() {
4261 return mDebuggerNotificationManager;
4262}
4263
4264//*****************************************************************************
4265// nsGlobalWindowInner::nsPIDOMWindow
4266//*****************************************************************************
4267
4268Location* nsGlobalWindowInner::Location() {
4269 if (!mLocation) {
4270 mLocation = new dom::Location(this);
4271 }
4272
4273 return mLocation;
4274}
4275
4276void nsGlobalWindowInner::MaybeUpdateTouchState() {
4277 if (mMayHaveTouchEventListener) {
4278 nsCOMPtr<nsIObserverService> observerService =
4279 services::GetObserverService();
4280
4281 if (observerService) {
4282 observerService->NotifyObservers(static_cast<nsIDOMWindow*>(this),
4283 DOM_TOUCH_LISTENER_ADDED"dom-touch-listener-added", nullptr);
4284 }
4285 }
4286}
4287
4288void nsGlobalWindowInner::EnableGamepadUpdates() {
4289 if (mHasGamepad) {
4290 RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService());
4291 if (gamepadManager) {
4292 gamepadManager->AddListener(this);
4293 }
4294 }
4295}
4296
4297void nsGlobalWindowInner::DisableGamepadUpdates() {
4298 if (mHasGamepad) {
4299 RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService());
4300 if (gamepadManager) {
4301 gamepadManager->RemoveListener(this);
4302 }
4303 }
4304}
4305
4306void nsGlobalWindowInner::EnableVRUpdates() {
4307 // We need to create a VREventObserver before we can either detect XR runtimes
4308 // or start an XR session
4309 if (!mVREventObserver && (mHasXRSession || mXRRuntimeDetectionInFlight)) {
4310 // Assert that we are not creating the observer while IsDying() as
4311 // that would result in a leak. VREventObserver holds a RefPtr to
4312 // this nsGlobalWindowInner and would prevent it from being deallocated.
4313 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"
, 4315); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDying()"
") (" "Creating a VREventObserver for an nsGlobalWindow that is "
"dying would cause it to leak." ")"); do { *((volatile int*)
__null) = 4315; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
4314 "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"
, 4315); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDying()"
") (" "Creating a VREventObserver for an nsGlobalWindow that is "
"dying would cause it to leak." ")"); do { *((volatile int*)
__null) = 4315; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
4315 "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"
, 4315); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDying()"
") (" "Creating a VREventObserver for an nsGlobalWindow that is "
"dying would cause it to leak." ")"); do { *((volatile int*)
__null) = 4315; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4316 mVREventObserver = new VREventObserver(this);
4317 }
4318 // If the content has an XR session, then we need to tell
4319 // VREventObserver that there is VR activity.
4320 if (mHasXRSession) {
4321 nsPIDOMWindowOuter* outer = GetOuterWindow();
4322 if (outer && !outer->IsBackground()) {
4323 StartVRActivity();
4324 }
4325 }
4326}
4327
4328void nsGlobalWindowInner::DisableVRUpdates() {
4329 if (mVREventObserver) {
4330 mVREventObserver->DisconnectFromOwner();
4331 mVREventObserver = nullptr;
4332 }
4333}
4334
4335void nsGlobalWindowInner::ResetVRTelemetry(bool aUpdate) {
4336 if (mVREventObserver) {
4337 mVREventObserver->UpdateSpentTimeIn2DTelemetry(aUpdate);
4338 }
4339}
4340
4341void nsGlobalWindowInner::StartVRActivity() {
4342 /**
4343 * If the content has an XR session, tell
4344 * the VREventObserver that the window is accessing
4345 * VR devices.
4346 *
4347 * It's possible to have a VREventObserver without
4348 * and XR session, if we are using it to get updates
4349 * about XR runtime enumeration. In this case,
4350 * we would not tell the VREventObserver that
4351 * we are accessing VR devices.
4352 */
4353 if (mVREventObserver && mHasXRSession) {
4354 mVREventObserver->StartActivity();
4355 }
4356}
4357
4358void nsGlobalWindowInner::StopVRActivity() {
4359 /**
4360 * If the content has an XR session, tell
4361 * the VReventObserver that the window is no longer
4362 * accessing VR devices. This does not stop the
4363 * XR session itself, which may be resumed with
4364 * EnableVRUpdates.
4365 * It's possible to have a VREventObserver without
4366 * and XR session, if we are using it to get updates
4367 * about XR runtime enumeration. In this case,
4368 * we would not tell the VREventObserver that
4369 * we ending an activity that accesses VR devices.
4370 */
4371 if (mVREventObserver && mHasXRSession) {
4372 mVREventObserver->StopActivity();
4373 }
4374}
4375
4376void nsGlobalWindowInner::SetFocusedElement(Element* aElement,
4377 uint32_t aFocusMethod,
4378 bool aNeedsFocus) {
4379 if (aElement && aElement->GetComposedDoc() != mDoc) {
4380 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"
, 4380)
;
4381 return;
4382 }
4383
4384 if (IsDying()) {
4385 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"
, 4385); MOZ_PretendNoReturn(); } } while (0)
;
4386 aElement = nullptr;
4387 aNeedsFocus = false;
4388 }
4389 if (mFocusedElement != aElement) {
4390 UpdateCanvasFocus(false, aElement);
4391 mFocusedElement = aElement;
4392 // TODO: Maybe this should be set on refocus too?
4393 mFocusMethod = aFocusMethod & nsIFocusManager::METHOD_MASK;
4394 }
4395
4396 if (mFocusedElement) {
4397 // if a node was focused by a keypress, turn on focus rings for the
4398 // window.
4399 if (mFocusMethod & nsIFocusManager::FLAG_BYKEY) {
4400 mUnknownFocusMethodShouldShowOutline = true;
4401 mFocusByKeyOccurred = true;
4402 } else if (nsFocusManager::GetFocusMoveActionCause(mFocusMethod) !=
4403 widget::InputContextAction::CAUSE_UNKNOWN) {
4404 mUnknownFocusMethodShouldShowOutline = false;
4405 } else if (aFocusMethod & nsIFocusManager::FLAG_NOSHOWRING) {
4406 // If we get focused via script, and script has explicitly opted out of
4407 // outlines via FLAG_NOSHOWRING, we don't want to make a refocus start
4408 // showing outlines.
4409 mUnknownFocusMethodShouldShowOutline = false;
4410 }
4411 }
4412
4413 if (aNeedsFocus) {
4414 mNeedsFocus = aNeedsFocus;
4415 }
4416}
4417
4418uint32_t nsGlobalWindowInner::GetFocusMethod() { return mFocusMethod; }
4419
4420bool nsGlobalWindowInner::ShouldShowFocusRing() {
4421 if (mFocusByKeyOccurred &&
4422 StaticPrefs::browser_display_always_show_rings_after_key_focus()) {
4423 return true;
4424 }
4425 return StaticPrefs::browser_display_show_focus_rings();
4426}
4427
4428bool nsGlobalWindowInner::TakeFocus(bool aFocus, uint32_t aFocusMethod) {
4429 if (IsDying()) {
4430 return false;
4431 }
4432
4433 if (aFocus) {
4434 mFocusMethod = aFocusMethod & nsIFocusManager::METHOD_MASK;
4435 }
4436
4437 if (mHasFocus != aFocus) {
4438 mHasFocus = aFocus;
4439 UpdateCanvasFocus(true, mFocusedElement);
4440 }
4441
4442 // if mNeedsFocus is true, then the document has not yet received a
4443 // document-level focus event. If there is a root content node, then return
4444 // true to tell the calling focus manager that a focus event is expected. If
4445 // there is no root content node, the document hasn't loaded enough yet, or
4446 // there isn't one and there is no point in firing a focus event.
4447 if (aFocus && mNeedsFocus && mDoc && mDoc->GetRootElement() != nullptr) {
4448 mNeedsFocus = false;
4449 return true;
4450 }
4451
4452 mNeedsFocus = false;
4453 return false;
4454}
4455
4456void nsGlobalWindowInner::SetReadyForFocus() {
4457 bool oldNeedsFocus = mNeedsFocus;
4458 mNeedsFocus = false;
4459
4460 if (RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager()) {
4461 nsCOMPtr<nsPIDOMWindowOuter> outerWindow = GetOuterWindow();
4462 fm->WindowShown(outerWindow, oldNeedsFocus);
4463 }
4464}
4465
4466void nsGlobalWindowInner::PageHidden() {
4467 // the window is being hidden, so tell the focus manager that the frame is
4468 // no longer valid. Use the persisted field to determine if the document
4469 // is being destroyed.
4470
4471 if (RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager()) {
4472 nsCOMPtr<nsPIDOMWindowOuter> outerWindow = GetOuterWindow();
4473 fm->WindowHidden(outerWindow, nsFocusManager::GenerateFocusActionId());
4474 }
4475
4476 mNeedsFocus = true;
4477}
4478
4479class HashchangeCallback : public Runnable {
4480 public:
4481 HashchangeCallback(const nsAString& aOldURL, const nsAString& aNewURL,
4482 nsGlobalWindowInner* aWindow)
4483 : mozilla::Runnable("HashchangeCallback"), mWindow(aWindow) {
4484 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"
, 4484); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mWindow" ")"
); do { *((volatile int*)__null) = 4484; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4485 mOldURL.Assign(aOldURL);
4486 mNewURL.Assign(aNewURL);
4487 }
4488
4489 NS_IMETHODvirtual nsresult Run() override {
4490 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"
, 4490); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Should be called on the main thread." ")"); do { *((volatile
int*)__null) = 4490; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
4491 return mWindow->FireHashchange(mOldURL, mNewURL);
4492 }
4493
4494 private:
4495 nsString mOldURL;
4496 nsString mNewURL;
4497 RefPtr<nsGlobalWindowInner> mWindow;
4498};
4499
4500nsresult nsGlobalWindowInner::DispatchAsyncHashchange(nsIURI* aOldURI,
4501 nsIURI* aNewURI) {
4502 // Make sure that aOldURI and aNewURI are identical up to the '#', and that
4503 // their hashes are different.
4504 bool equal = false;
4505 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"
, 4506); return NS_ERROR_UNEXPECTED; } } while (false)
4506 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"
, 4506); return NS_ERROR_UNEXPECTED; } } while (false)
;
4507 nsAutoCString oldHash, newHash;
4508 bool oldHasHash, newHasHash;
4509 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"
, 4513); return NS_ERROR_UNEXPECTED; } } while (false)
4510 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"
, 4513); return NS_ERROR_UNEXPECTED; } } while (false)
4511 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"
, 4513); return NS_ERROR_UNEXPECTED; } } while (false)
4512 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"
, 4513); return NS_ERROR_UNEXPECTED; } } while (false)
4513 (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"
, 4513); return NS_ERROR_UNEXPECTED; } } while (false)
;
4514
4515 nsAutoCString oldSpec, newSpec;
4516 nsresult rv = aOldURI->GetSpec(oldSpec);
4517 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"
, 4517); return rv; } } while (false)
;
4518 rv = aNewURI->GetSpec(newSpec);
4519 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"
, 4519); return rv; } } while (false)
;
4520
4521 NS_ConvertUTF8toUTF16 oldWideSpec(oldSpec);
4522 NS_ConvertUTF8toUTF16 newWideSpec(newSpec);
4523
4524 nsCOMPtr<nsIRunnable> callback =
4525 new HashchangeCallback(oldWideSpec, newWideSpec, this);
4526 return Dispatch(callback.forget());
4527}
4528
4529nsresult nsGlobalWindowInner::FireHashchange(const nsAString& aOldURL,
4530 const nsAString& aNewURL) {
4531 // Don't do anything if the window is frozen.
4532 if (IsFrozen()) {
4533 return NS_OK;
4534 }
4535
4536 // Get a presentation shell for use in creating the hashchange event.
4537 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"
, 4537); return NS_ERROR_UNEXPECTED; } } while (false)
;
4538
4539 HashChangeEventInit init;
4540 init.mNewURL = aNewURL;
4541 init.mOldURL = aOldURL;
4542
4543 RefPtr<HashChangeEvent> event =
4544 HashChangeEvent::Constructor(this, u"hashchange"_ns, init);
4545
4546 event->SetTrusted(true);
4547
4548 ErrorResult rv;
4549 DispatchEvent(*event, rv);
4550 return rv.StealNSResult();
4551}
4552
4553nsresult nsGlobalWindowInner::DispatchSyncPopState() {
4554 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"
, 4555); MOZ_PretendNoReturn(); } } while (0)
4555 "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"
, 4555); MOZ_PretendNoReturn(); } } while (0)
;
4556
4557 // Bail if the window is frozen.
4558 if (IsFrozen()) {
4559 return NS_OK;
4560 }
4561
4562 AutoJSAPI jsapi;
4563 bool result = jsapi.Init(this);
4564 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"
, 4564); return NS_ERROR_FAILURE; } } while (false)
;
4565
4566 JSContext* cx = jsapi.cx();
4567
4568 // Get the document's pending state object -- it contains the data we're
4569 // going to send along with the popstate event. The object is serialized
4570 // using structured clone.
4571 JS::Rooted<JS::Value> stateJSValue(cx);
4572 nsresult rv = mDoc->GetStateObject(&stateJSValue);
4573 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"
, 4573); return rv; } } while (false)
;
4574
4575 if (!JS_WrapValue(cx, &stateJSValue)) {
4576 return NS_ERROR_OUT_OF_MEMORY;
4577 }
4578
4579 RootedDictionary<PopStateEventInit> init(cx);
4580 init.mState = stateJSValue;
4581
4582 RefPtr<PopStateEvent> event =
4583 PopStateEvent::Constructor(this, u"popstate"_ns, init);
4584 event->SetTrusted(true);
4585 event->SetTarget(this);
4586
4587 ErrorResult err;
4588 DispatchEvent(*event, err);
4589 return err.StealNSResult();
4590}
4591
4592//-------------------------------------------------------
4593// Tells the HTMLFrame/CanvasFrame that is now has focus
4594void nsGlobalWindowInner::UpdateCanvasFocus(bool aFocusChanged,
4595 nsIContent* aNewContent) {
4596 // this is called from the inner window so use GetDocShell
4597 nsIDocShell* docShell = GetDocShell();
4598 if (!docShell) return;
4599
4600 bool editable;
4601 docShell->GetEditable(&editable);
4602 if (editable) return;
4603
4604 PresShell* presShell = docShell->GetPresShell();
4605 if (!presShell || !mDoc) {
4606 return;
4607 }
4608
4609 Element* rootElement = mDoc->GetRootElement();
4610 if (rootElement) {
4611 if ((mHasFocus || aFocusChanged) &&
4612 (mFocusedElement == rootElement || aNewContent == rootElement)) {
4613 nsCanvasFrame* canvasFrame = presShell->GetCanvasFrame();
4614 if (canvasFrame) {
4615 canvasFrame->SetHasFocus(mHasFocus && rootElement == aNewContent);
4616 }
4617 }
4618 } else {
4619 // XXXbz I would expect that there is never a canvasFrame in this case...
4620 nsCanvasFrame* canvasFrame = presShell->GetCanvasFrame();
4621 if (canvasFrame) {
4622 canvasFrame->SetHasFocus(false);
4623 }
4624 }
4625}
4626
4627already_AddRefed<nsICSSDeclaration> nsGlobalWindowInner::GetComputedStyle(
4628 Element& aElt, const nsAString& aPseudoElt, ErrorResult& aError) {
4629 return GetComputedStyleHelper(aElt, aPseudoElt, false, aError);
4630}
4631
4632already_AddRefed<nsICSSDeclaration>
4633nsGlobalWindowInner::GetDefaultComputedStyle(Element& aElt,
4634 const nsAString& aPseudoElt,
4635 ErrorResult& aError) {
4636 return GetComputedStyleHelper(aElt, aPseudoElt, true, aError);
4637}
4638
4639already_AddRefed<nsICSSDeclaration> nsGlobalWindowInner::GetComputedStyleHelper(
4640 Element& aElt, const nsAString& aPseudoElt, bool aDefaultStylesOnly,
4641 ErrorResult& aError) {
4642 FORWARD_TO_OUTER_OR_THROW(GetComputedStyleHelperOuter,
4643 (aElt, aPseudoElt, aDefaultStylesOnly, aError),
4644 aError, nullptr);
4645}
4646
4647void nsGlobalWindowInner::MaybeNotifyStorageKeyUsed() {
4648 // Only notify once per window lifetime.
4649 if (hasNotifiedStorageKeyUsed) {
4650 return;
4651 }
4652 nsresult rv =
4653 BounceTrackingStorageObserver::OnInitialStorageAccess(GetWindowContext());
4654 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"
, 4654)
) {
4655 return;
4656 }
4657 hasNotifiedStorageKeyUsed = true;
4658}
4659
4660Storage* nsGlobalWindowInner::GetSessionStorage(ErrorResult& aError) {
4661 nsIPrincipal* principal = GetPrincipal();
4662 nsIPrincipal* storagePrincipal;
4663 if (StaticPrefs::
4664 privacy_partition_always_partition_third_party_non_cookie_storage_exempt_sessionstorage()) {
4665 storagePrincipal = GetEffectiveCookiePrincipal();
4666 } else {
4667 storagePrincipal = GetEffectiveStoragePrincipal();
4668 }
4669 BrowsingContext* browsingContext = GetBrowsingContext();
4670
4671 if (!principal || !storagePrincipal || !browsingContext ||
4672 !Storage::StoragePrefIsEnabled()) {
4673 return nullptr;
4674 }
4675
4676 if (mSessionStorage) {
4677 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)
4678 ("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)
4679 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)
;
4680 bool canAccess =
4681 principal->Subsumes(mSessionStorage->Principal()) &&
4682 storagePrincipal->Subsumes(mSessionStorage->StoragePrincipal());
4683 if (!canAccess) {
4684 mSessionStorage = nullptr;
4685 }
4686 }
4687
4688 if (!mSessionStorage) {
4689 nsString documentURI;
4690 if (mDoc) {
4691 aError = mDoc->GetDocumentURI(documentURI);
4692 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"
, 4692)
) {
4693 return nullptr;
4694 }
4695 }
4696
4697 if (!mDoc) {
4698 aError.Throw(NS_ERROR_FAILURE);
4699 return nullptr;
4700 }
4701
4702 // If the document's sandboxed origin flag is set, then accessing
4703 // sessionStorage is prohibited.
4704 if (mDoc->GetSandboxFlags() & SANDBOXED_ORIGIN) {
4705 aError.ThrowSecurityError(
4706 "Forbidden in a sandboxed document without the 'allow-same-origin' "
4707 "flag.");
4708 return nullptr;
4709 }
4710
4711 uint32_t rejectedReason = 0;
4712 StorageAccess access = StorageAllowedForWindow(this, &rejectedReason);
4713
4714 // SessionStorage is an ephemeral per-tab per-origin storage that only lives
4715 // as long as the tab is open, although it may survive browser restarts
4716 // thanks to the session store. So we interpret storage access differently
4717 // than we would for persistent per-origin storage like LocalStorage and so
4718 // it may be okay to provide SessionStorage even when we receive a value of
4719 // eDeny.
4720 //
4721 // ContentBlocking::ShouldAllowAccessFor will return false for 3 main
4722 // reasons.
4723 //
4724 // 1. Cookies are entirely blocked due to a per-origin permission
4725 // (nsICookiePermission::ACCESS_DENY for the top-level principal or this
4726 // window's principal) or the very broad BEHAVIOR_REJECT. This will return
4727 // eDeny with a reason of STATE_COOKIES_BLOCKED_BY_PERMISSION or
4728 // STATE_COOKIES_BLOCKED_ALL.
4729 //
4730 // 2. Third-party cookies are limited via BEHAVIOR_REJECT_FOREIGN and
4731 // BEHAVIOR_LIMIT_FOREIGN and this is a third-party window. This will return
4732 // eDeny with a reason of STATE_COOKIES_BLOCKED_FOREIGN.
4733 //
4734 // 3. Tracking protection (BEHAVIOR_REJECT_TRACKER and
4735 // BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN) is in effect and
4736 // IsThirdPartyTrackingResourceWindow() returned true and there wasn't a
4737 // permission that allows it. This will return ePartitionTrackersOrDeny with
4738 // a reason of STATE_COOKIES_BLOCKED_TRACKER or
4739 // STATE_COOKIES_BLOCKED_SOCIALTRACKER.
4740 //
4741 // In the 1st case, the user has explicitly indicated that they don't want
4742 // to allow any storage to the origin or all origins and so we throw an
4743 // error and deny access to SessionStorage. In the 2nd case, a legacy
4744 // decision reasoned that there's no harm in providing SessionStorage
4745 // because the information is not durable and cannot escape the current tab.
4746 // The rationale is similar for the 3rd case.
4747 if (access == StorageAccess::eDeny &&
4748 rejectedReason !=
4749 nsIWebProgressListener::STATE_COOKIES_BLOCKED_FOREIGN) {
4750 aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
4751 return nullptr;
4752 }
4753
4754 const RefPtr<SessionStorageManager> storageManager =
4755 browsingContext->GetSessionStorageManager();
4756 if (!storageManager) {
4757 aError.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
4758 return nullptr;
4759 }
4760
4761 RefPtr<Storage> storage;
4762 aError = storageManager->CreateStorage(this, principal, storagePrincipal,
4763 documentURI, IsPrivateBrowsing(),
4764 getter_AddRefs(storage));
4765 if (aError.Failed()) {
4766 return nullptr;
4767 }
4768
4769 mSessionStorage = storage;
4770 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"
, 4770); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mSessionStorage"
")"); do { *((volatile int*)__null) = 4770; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4771
4772 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)
4773 ("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)
4774 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)
;
4775
4776 if (!mSessionStorage) {
4777 aError.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
4778 return nullptr;
4779 }
4780 }
4781
4782 MaybeNotifyStorageKeyUsed();
4783
4784 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)
4785 ("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)
4786 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)
;
4787
4788 return mSessionStorage;
4789}
4790
4791Storage* nsGlobalWindowInner::GetLocalStorage(ErrorResult& aError) {
4792 if (!Storage::StoragePrefIsEnabled()) {
4793 return nullptr;
4794 }
4795
4796 // If the document's sandboxed origin flag is set, then accessing localStorage
4797 // is prohibited.
4798 if (mDoc && mDoc->GetSandboxFlags() & SANDBOXED_ORIGIN) {
4799 aError.ThrowSecurityError(
4800 "Forbidden in a sandboxed document without the 'allow-same-origin' "
4801 "flag.");
4802 return nullptr;
4803 }
4804
4805 // LocalStorage needs to be exposed in every context except for sandboxes and
4806 // NullPrincipals (data: URLs, for instance). But we need to keep data
4807 // separate in some scenarios: private-browsing and partitioned trackers.
4808 // In private-browsing, LocalStorage keeps data in memory, and it shares
4809 // StorageEvents just with other origins in the same private-browsing
4810 // environment.
4811 // For Partitioned Trackers, we expose a partitioned LocalStorage, which
4812 // doesn't share data with other contexts, and it's just in memory.
4813 // Partitioned localStorage is available only for trackers listed in the
4814 // privacy.restrict3rdpartystorage.partitionedHosts pref. See
4815 // nsContentUtils::IsURIInPrefList to know the syntax for the pref value.
4816 // This is a temporary web-compatibility hack.
4817
4818 StorageAccess access = StorageAllowedForWindow(this);
4819
4820 // We allow partitioned localStorage only to some hosts.
4821 bool isolated = false;
4822 if (ShouldPartitionStorage(access)) {
4823 if (!mDoc) {
4824 access = StorageAccess::eDeny;
4825 } else if (!StoragePartitioningEnabled(access, mDoc->CookieJarSettings())) {
4826 static const char* kPrefName =
4827 "privacy.restrict3rdpartystorage.partitionedHosts";
4828
4829 bool isInList = false;
4830 mDoc->NodePrincipal()->IsURIInPrefList(kPrefName, &isInList);
4831 if (!isInList) {
4832 access = StorageAccess::eDeny;
4833 } else {
4834 isolated = true;
4835 }
4836 }
4837 }
4838
4839 if (access == StorageAccess::eDeny) {
4840 aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
4841 return nullptr;
4842 }
4843
4844 nsCOMPtr<nsICookieJarSettings> cookieJarSettings;
4845 if (mDoc) {
4846 cookieJarSettings = mDoc->CookieJarSettings();
4847 } else {
4848 cookieJarSettings = net::CookieJarSettings::GetBlockingAll(
4849 ShouldResistFingerprinting(RFPTarget::IsAlwaysEnabledForPrecompute));
4850 }
4851
4852 // Note that this behavior is observable: if we grant storage permission to a
4853 // tracker, we pass from the partitioned LocalStorage (or a partitioned cookie
4854 // jar) to the 'normal' one. The previous data is lost and the 2
4855 // window.localStorage objects, before and after the permission granted, will
4856 // be different.
4857 if (mLocalStorage) {
4858 if ((mLocalStorage->Type() == (isolated ? Storage::ePartitionedLocalStorage
4859 : Storage::eLocalStorage)) &&
4860 (mLocalStorage->StoragePrincipal() == GetEffectiveStoragePrincipal())) {
4861 return mLocalStorage;
4862 }
4863
4864 // storage needs change
4865 mLocalStorage = nullptr;
4866 }
4867
4868 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"
, 4868); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mLocalStorage"
")"); do { *((volatile int*)__null) = 4868; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4869
4870 if (!isolated) {
4871 RefPtr<Storage> storage;
4872
4873 if (NextGenLocalStorageEnabled()) {
4874 aError = LSObject::CreateForWindow(this, getter_AddRefs(storage));
4875 } else {
4876 nsresult rv;
4877 nsCOMPtr<nsIDOMStorageManager> storageManager =
4878 do_GetService("@mozilla.org/dom/localStorage-manager;1", &rv);
4879 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4880 aError.Throw(rv);
4881 return nullptr;
4882 }
4883
4884 nsString documentURI;
4885 if (mDoc) {
4886 aError = mDoc->GetDocumentURI(documentURI);
4887 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"
, 4887)
) {
4888 return nullptr;
4889 }
4890 }
4891
4892 nsIPrincipal* principal = GetPrincipal();
4893 if (!principal) {
4894 aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
4895 return nullptr;
4896 }
4897
4898 nsIPrincipal* storagePrincipal = GetEffectiveStoragePrincipal();
4899 if (!storagePrincipal) {
4900 aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
4901 return nullptr;
4902 }
4903
4904 aError = storageManager->CreateStorage(this, principal, storagePrincipal,
4905 documentURI, IsPrivateBrowsing(),
4906 getter_AddRefs(storage));
4907 }
4908
4909 if (aError.Failed()) {
4910 return nullptr;
4911 }
4912
4913 mLocalStorage = storage;
4914 } else {
4915 nsresult rv;
4916 nsCOMPtr<nsIDOMSessionStorageManager> storageManager =
4917 do_GetService("@mozilla.org/dom/sessionStorage-manager;1", &rv);
4918 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4919 aError.Throw(rv);
4920 return nullptr;
4921 }
4922
4923 nsIPrincipal* principal = GetPrincipal();
4924 if (!principal) {
4925 aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
4926 return nullptr;
4927 }
4928
4929 nsIPrincipal* storagePrincipal = GetEffectiveStoragePrincipal();
4930 if (!storagePrincipal) {
4931 aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
4932 return nullptr;
4933 }
4934
4935 RefPtr<SessionStorageCache> cache;
4936 if (isolated) {
4937 cache = new SessionStorageCache();
4938 } else {
4939 // This will clone the session storage if it exists.
4940 rv = storageManager->GetSessionStorageCache(principal, storagePrincipal,
4941 &cache);
4942 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4943 aError.Throw(rv);
4944 return nullptr;
4945 }
4946 }
4947
4948 mLocalStorage =
4949 new PartitionedLocalStorage(this, principal, storagePrincipal, cache);
4950 }
4951
4952 MaybeNotifyStorageKeyUsed();
4953
4954 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"
, 4954); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLocalStorage"
")"); do { *((volatile int*)__null) = 4954; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4955 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"
, 4957); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLocalStorage->Type() == (isolated ? Storage::ePartitionedLocalStorage : Storage::eLocalStorage)"
")"); do { *((volatile int*)__null) = 4957; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4956 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"
, 4957); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLocalStorage->Type() == (isolated ? Storage::ePartitionedLocalStorage : Storage::eLocalStorage)"
")"); do { *((volatile int*)__null) = 4957; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4957 (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"
, 4957); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLocalStorage->Type() == (isolated ? Storage::ePartitionedLocalStorage : Storage::eLocalStorage)"
")"); do { *((volatile int*)__null) = 4957; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4958 return mLocalStorage;
4959}
4960
4961IDBFactory* nsGlobalWindowInner::GetIndexedDB(JSContext* aCx,
4962 ErrorResult& aError) {
4963 if (!mIndexedDB) {
4964 // This may keep mIndexedDB null without setting an error.
4965 auto res = IDBFactory::CreateForWindow(this);
4966 if (res.isErr()) {
4967 aError = res.unwrapErr();
4968 } else {
4969 mIndexedDB = res.unwrap();
4970 }
4971 }
4972
4973 MaybeNotifyStorageKeyUsed();
4974
4975 return mIndexedDB;
4976}
4977
4978//*****************************************************************************
4979// nsGlobalWindowInner::nsIInterfaceRequestor
4980//*****************************************************************************
4981
4982NS_IMETHODIMPnsresult
4983nsGlobalWindowInner::GetInterface(const nsIID& aIID, void** aSink) {
4984 nsGlobalWindowOuter* outer = GetOuterWindowInternal();
4985 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"
, 4985); return NS_ERROR_NOT_INITIALIZED; } } while (false)
;
4986
4987 nsresult rv = outer->GetInterfaceInternal(aIID, aSink);
4988 if (rv == NS_ERROR_NO_INTERFACE) {
4989 return QueryInterface(aIID, aSink);
4990 }
4991 return rv;
4992}
4993
4994void nsGlobalWindowInner::GetInterface(JSContext* aCx,
4995 JS::Handle<JS::Value> aIID,
4996 JS::MutableHandle<JS::Value> aRetval,
4997 ErrorResult& aError) {
4998 dom::GetInterface(aCx, this, aIID, aRetval, aError);
4999}
5000
5001already_AddRefed<CacheStorage> nsGlobalWindowInner::GetCaches(
5002 ErrorResult& aRv) {
5003 if (!mCacheStorage) {
5004 bool forceTrustedOrigin =
5005 GetBrowsingContext() &&
5006 GetBrowsingContext()->Top()->GetServiceWorkersTestingEnabled();
5007 mCacheStorage = CacheStorage::CreateOnMainThread(
5008 cache::DEFAULT_NAMESPACE, this, GetEffectiveStoragePrincipal(),
5009 forceTrustedOrigin, aRv);
5010 }
5011
5012 RefPtr<CacheStorage> ref = mCacheStorage;
5013 return ref.forget();
5014}
5015
5016void nsGlobalWindowInner::FireOfflineStatusEventIfChanged() {
5017 if (!IsCurrentInnerWindow()) return;
5018
5019 // Don't fire an event if the status hasn't changed
5020 if (mWasOffline == NS_IsOffline()) {
5021 return;
5022 }
5023
5024 mWasOffline = !mWasOffline;
5025
5026 nsAutoString name;
5027 if (mWasOffline) {
5028 name.AssignLiteral("offline");
5029 } else {
5030 name.AssignLiteral("online");
5031 }
5032 nsContentUtils::DispatchTrustedEvent(mDoc, this, name, CanBubble::eNo,
5033 Cancelable::eNo);
5034}
5035
5036nsGlobalWindowInner::SlowScriptResponse
5037nsGlobalWindowInner::ShowSlowScriptDialog(JSContext* aCx,
5038 const nsString& aAddonId,
5039 const double aDuration) {
5040 nsresult rv;
5041
5042 if (Preferences::GetBool("dom.always_stop_slow_scripts")) {
1
Assuming the condition is false
2
Taking false branch
5043 return KillSlowScript;
5044 }
5045
5046 // If it isn't safe to run script, then it isn't safe to bring up the prompt
5047 // (since that spins the event loop). In that (rare) case, we just kill the
5048 // script and report a warning.
5049 if (!nsContentUtils::IsSafeToRunScript()) {
3
Assuming the condition is false
4
Taking false branch
5050 JS::WarnASCII(aCx, "A long running script was terminated");
5051 return KillSlowScript;
5052 }
5053
5054 // If our document is not active, just kill the script: we've been unloaded
5055 if (!HasActiveDocument()) {
5
Assuming the condition is false
6
Taking false branch
5056 return KillSlowScript;
5057 }
5058
5059 // Check if we should offer the option to debug
5060 JS::AutoFilename filename;
5061 uint32_t lineno;
7
'lineno' declared without an initial value
5062 // Computing the line number can be very expensive (see bug 1330231 for
5063 // example), and we don't use the line number anywhere except than in the
5064 // parent process, so we avoid computing it elsewhere. This gives us most of
5065 // the wins we are interested in, since the source of the slowness here is
5066 // minified scripts which is more common in Web content that is loaded in the
5067 // content process.
5068 uint32_t* linenop = XRE_IsParentProcess() ? &lineno : nullptr;
8
Assuming the condition is false
9
'?' condition is false
5069 bool hasFrame = JS::DescribeScriptedCaller(aCx, &filename, linenop);
5070
5071 // Record the slow script event if we haven't done so already for this inner
5072 // window (which represents a particular page to the user).
5073 if (!mHasHadSlowScript) {
10
Assuming field 'mHasHadSlowScript' is true
11
Taking false branch
5074 Telemetry::Accumulate(Telemetry::SLOW_SCRIPT_PAGE_COUNT, 1);
5075 }
5076 mHasHadSlowScript = true;
5077
5078 // Override the cursor to something that we're sure the user can see.
5079 SetCursor("auto"_ns, IgnoreErrors());
5080
5081 if (XRE_IsContentProcess() && ProcessHangMonitor::Get()) {
12
Assuming the condition is false
5082 ProcessHangMonitor::SlowScriptAction action;
5083 RefPtr<ProcessHangMonitor> monitor = ProcessHangMonitor::Get();
5084 nsIDocShell* docShell = GetDocShell();
5085 nsCOMPtr<nsIBrowserChild> child =
5086 docShell ? docShell->GetBrowserChild() : nullptr;
5087 action =
5088 monitor->NotifySlowScript(child, filename.get(), aAddonId, aDuration);
5089 if (action == ProcessHangMonitor::Terminate) {
5090 return KillSlowScript;
5091 }
5092
5093 if (action == ProcessHangMonitor::StartDebugger) {
5094 // Spin a nested event loop so that the debugger in the parent can fetch
5095 // any information it needs. Once the debugger has started, return to the
5096 // script.
5097 RefPtr<nsGlobalWindowOuter> outer = GetOuterWindowInternal();
5098 outer->EnterModalState();
5099 SpinEventLoopUntil("nsGlobalWindowInner::ShowSlowScriptDialog"_ns, [&]() {
5100 return monitor->IsDebuggerStartupComplete();
5101 });
5102 outer->LeaveModalState();
5103 return ContinueSlowScript;
5104 }
5105
5106 return ContinueSlowScriptAndKeepNotifying;
5107 }
5108
5109 // Reached only on non-e10s - once per slow script dialog.
5110 // On e10s - we probe once at ProcessHangsMonitor.sys.mjs
5111 Telemetry::Accumulate(Telemetry::SLOW_SCRIPT_NOTICE_COUNT, 1);
5112
5113 // Get the nsIPrompt interface from the docshell
5114 nsCOMPtr<nsIDocShell> ds = GetDocShell();
5115 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"
, 5115); return KillSlowScript; } } while (false)
;
13
Taking false branch
14
Loop condition is false. Exiting loop
5116 nsCOMPtr<nsIPrompt> prompt = do_GetInterface(ds);
5117 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"
, 5117); return KillSlowScript; } } while (false)
;
15
Taking false branch
16
Loop condition is false. Exiting loop
5118
5119 // Prioritize the SlowScriptDebug interface over JSD1.
5120 nsCOMPtr<nsISlowScriptDebugCallback> debugCallback;
5121
5122 if (hasFrame) {
17
Assuming 'hasFrame' is false
18
Taking false branch
5123 const char* debugCID = "@mozilla.org/dom/slow-script-debug;1";
5124 nsCOMPtr<nsISlowScriptDebug> debugService = do_GetService(debugCID, &rv);
5125 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5126 debugService->GetActivationHandler(getter_AddRefs(debugCallback));
5127 }
5128 }
5129
5130 bool failed = false;
5131 auto getString = [&](const char* name,
5132 nsContentUtils::PropertiesFile propFile =
5133 nsContentUtils::eDOM_PROPERTIES) {
5134 nsAutoString result;
5135 nsresult rv = nsContentUtils::GetLocalizedString(propFile, name, result);
5136
5137 // GetStringFromName can return NS_OK and still give nullptr string
5138 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
5139 return result;
5140 };
5141
5142 bool isAddonScript = !aAddonId.IsEmpty();
19
Assuming the condition is false
5143 bool showDebugButton = debugCallback && !isAddonScript;
5144
5145 // Get localizable strings
5146
5147 nsAutoString title, checkboxMsg, debugButton, msg;
5148 if (isAddonScript
19.1
'isAddonScript' is false
) {
20
Taking false branch
5149 title = getString("KillAddonScriptTitle");
5150 checkboxMsg = getString("KillAddonScriptGlobalMessage");
5151
5152 auto appName =
5153 getString("brandShortName", nsContentUtils::eBRAND_PROPERTIES);
5154
5155 nsCOMPtr<nsIAddonPolicyService> aps =
5156 do_GetService("@mozilla.org/addons/policy-service;1");
5157 nsString addonName;
5158 if (!aps || NS_FAILED(aps->GetExtensionName(aAddonId, addonName))((bool)(__builtin_expect(!!(NS_FAILED_impl(aps->GetExtensionName
(aAddonId, addonName))), 0)))
) {
5159 addonName = aAddonId;
5160 }
5161
5162 rv = nsContentUtils::FormatLocalizedString(
5163 msg, nsContentUtils::eDOM_PROPERTIES, "KillAddonScriptMessage",
5164 addonName, appName);
5165
5166 failed = failed || NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)));
5167 } else {
5168 title = getString("KillScriptTitle");
5169 checkboxMsg = getString("DontAskAgain");
5170
5171 if (showDebugButton
20.1
'showDebugButton' is false
) {
21
Taking false branch
5172 debugButton = getString("DebugScriptButton");
5173 msg = getString("KillScriptWithDebugMessage");
5174 } else {
5175 msg = getString("KillScriptMessage");
5176 }
5177 }
5178
5179 auto stopButton = getString("StopScriptButton");
5180 auto waitButton = getString("WaitForScriptButton");
22
Calling 'operator()'
26
Returning from 'operator()'
5181
5182 if (failed) {
27
Assuming 'failed' is false
28
Taking false branch
5183 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"
, 5183); MOZ_PretendNoReturn(); } while (0)
;
5184 return ContinueSlowScript;
5185 }
5186
5187 // Append file and line number information, if available
5188 if (filename.get()) {
29
Assuming the condition is true
30
Taking true branch
5189 nsAutoString scriptLocation;
5190 // We want to drop the middle part of too-long locations. We'll
5191 // define "too-long" as longer than 60 UTF-16 code units. Just
5192 // have to be a bit careful about unpaired surrogates.
5193 NS_ConvertUTF8toUTF16 filenameUTF16(filename.get());
5194 if (filenameUTF16.Length() > 60) {
31
Assuming the condition is false
32
Taking false branch
5195 // XXXbz Do we need to insert any bidi overrides here?
5196 size_t cutStart = 30;
5197 size_t cutLength = filenameUTF16.Length() - 60;
5198 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"
, 5198); AnnotateMozCrashReason("MOZ_ASSERT" "(" "cutLength > 0"
")"); do { *((volatile int*)__null) = 5198; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5199 if (NS_IS_LOW_SURROGATE(filenameUTF16[cutStart])((uint32_t(filenameUTF16[cutStart]) & 0xFFFFFC00) == 0xDC00
)
) {
5200 // Don't truncate before the low surrogate, in case it's preceded by a
5201 // high surrogate and forms a single Unicode character. Instead, just
5202 // include the low surrogate.
5203 ++cutStart;
5204 --cutLength;
5205 }
5206 if (NS_IS_LOW_SURROGATE(filenameUTF16[cutStart + cutLength])((uint32_t(filenameUTF16[cutStart + cutLength]) & 0xFFFFFC00
) == 0xDC00)
) {
5207 // Likewise, don't drop a trailing low surrogate here. We want to
5208 // increase cutLength, since it might be 0 already so we can't very well
5209 // decrease it.
5210 ++cutLength;
5211 }
5212
5213 // Insert U+2026 HORIZONTAL ELLIPSIS
5214 filenameUTF16.ReplaceLiteral(cutStart, cutLength, u"\x2026");
5215 }
5216 rv = nsContentUtils::FormatLocalizedString(
5217 scriptLocation, nsContentUtils::eDOM_PROPERTIES, "KillScriptLocation",
5218 filenameUTF16);
5219
5220 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
33
Assuming the condition is true
34
Taking true branch
5221 msg.AppendLiteral("\n\n");
5222 msg.Append(scriptLocation);
5223 msg.Append(':');
5224 msg.AppendInt(lineno);
35
1st function call argument is an uninitialized value
5225 }
5226 }
5227
5228 uint32_t buttonFlags = nsIPrompt::BUTTON_POS_1_DEFAULT +
5229 (nsIPrompt::BUTTON_TITLE_IS_STRING *
5230 (nsIPrompt::BUTTON_POS_0 + nsIPrompt::BUTTON_POS_1));
5231
5232 // Add a third button if necessary.
5233 if (showDebugButton)
5234 buttonFlags += nsIPrompt::BUTTON_TITLE_IS_STRING * nsIPrompt::BUTTON_POS_2;
5235
5236 bool checkboxValue = false;
5237 int32_t buttonPressed = 0; // In case the user exits dialog by clicking X.
5238 {
5239 // Null out the operation callback while we're re-entering JS here.
5240 AutoDisableJSInterruptCallback disabler(aCx);
5241
5242 // Open the dialog.
5243 rv = prompt->ConfirmEx(
5244 title.get(), msg.get(), buttonFlags, waitButton.get(), stopButton.get(),
5245 debugButton.get(), checkboxMsg.get(), &checkboxValue, &buttonPressed);
5246 }
5247
5248 if (buttonPressed == 0) {
5249 if (checkboxValue && !isAddonScript && NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))))
5250 return AlwaysContinueSlowScript;
5251 return ContinueSlowScript;
5252 }
5253
5254 if (buttonPressed == 2) {
5255 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"
, 5255); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "debugCallback"
")"); do { *((volatile int*)__null) = 5255; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5256
5257 rv = debugCallback->HandleSlowScriptDebug(this);
5258 return NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) ? ContinueSlowScript : KillSlowScript;
5259 }
5260
5261 JS_ClearPendingException(aCx);
5262
5263 return KillSlowScript;
5264}
5265
5266nsresult nsGlobalWindowInner::Observe(nsISupports* aSubject, const char* aTopic,
5267 const char16_t* aData) {
5268 if (!nsCRT::strcmp(aTopic, NS_IOSERVICE_OFFLINE_STATUS_TOPIC"network:offline-status-changed")) {
5269 if (!IsFrozen()) {
5270 // Fires an offline status event if the offline status has changed
5271 FireOfflineStatusEventIfChanged();
5272 }
5273 return NS_OK;
5274 }
5275
5276 if (!nsCRT::strcmp(aTopic, MEMORY_PRESSURE_OBSERVER_TOPIC"memory-pressure")) {
5277 if (mPerformance) {
5278 mPerformance->MemoryPressure();
5279 }
5280 RemoveReportRecords();
5281 return NS_OK;
5282 }
5283
5284 if (!nsCRT::strcmp(aTopic, PERMISSION_CHANGED_TOPIC"perm-changed")) {
5285 nsCOMPtr<nsIPermission> perm(do_QueryInterface(aSubject));
5286 if (!perm) {
5287 // A null permission indicates that the entire permission list
5288 // was cleared.
5289 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"
, 5289); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!nsCRT::strcmp(aData, u\"cleared\")"
")"); do { *((volatile int*)__null) = 5289; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5290 UpdatePermissions();
5291 return NS_OK;
5292 }
5293
5294 nsAutoCString type;
5295 perm->GetType(type);
5296 if (type == "autoplay-media"_ns) {
5297 UpdateAutoplayPermission();
5298 } else if (type == "shortcuts"_ns) {
5299 UpdateShortcutsPermission();
5300 } else if (type == "popup"_ns) {
5301 UpdatePopupPermission();
5302 }
5303
5304 if (!mDoc) {
5305 return NS_OK;
5306 }
5307
5308 RefPtr<PermissionDelegateHandler> permDelegateHandler =
5309 mDoc->GetPermissionDelegateHandler();
5310
5311 if (permDelegateHandler) {
5312 permDelegateHandler->UpdateDelegatedPermission(type);
5313 }
5314
5315 return NS_OK;
5316 }
5317
5318 if (!nsCRT::strcmp(aTopic, "screen-information-changed")) {
5319 if (mScreen) {
5320 if (RefPtr<ScreenOrientation> orientation =
5321 mScreen->GetOrientationIfExists()) {
5322 orientation->MaybeChanged();
5323 }
5324 }
5325 if (mHasOrientationChangeListeners) {
5326 int32_t oldAngle = mOrientationAngle;
5327 mOrientationAngle = Orientation(CallerType::System);
5328 if (mOrientationAngle != oldAngle && IsCurrentInnerWindow()) {
5329 nsCOMPtr<nsPIDOMWindowOuter> outer = GetOuterWindow();
5330 outer->DispatchCustomEvent(u"orientationchange"_ns);
5331 }
5332 }
5333 return NS_OK;
5334 }
5335
5336 if (!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID"nsPref:changed")) {
5337 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"
, 5337); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_strcmp(aData, u\"intl.accept_languages\")"
")"); do { *((volatile int*)__null) = 5337; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5338
5339 // The user preferred languages have changed, we need to fire an event on
5340 // Window object and invalidate the cache for navigator.languages. It is
5341 // done for every change which can be a waste of cycles but those should be
5342 // fairly rare.
5343 // We MUST invalidate navigator.languages before sending the event in the
5344 // very likely situation where an event handler will try to read its value.
5345
5346 if (mNavigator) {
5347 Navigator_Binding::ClearCachedLanguageValue(mNavigator);
5348 Navigator_Binding::ClearCachedLanguagesValue(mNavigator);
5349 }
5350
5351 // The event has to be dispatched only to the current inner window.
5352 if (!IsCurrentInnerWindow()) {
5353 return NS_OK;
5354 }
5355
5356 RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
5357 event->InitEvent(u"languagechange"_ns, false, false);
5358 event->SetTrusted(true);
5359
5360 ErrorResult rv;
5361 DispatchEvent(*event, rv);
5362 return rv.StealNSResult();
5363 }
5364
5365 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"
, 5365)
;
5366 return NS_ERROR_FAILURE;
5367}
5368
5369void nsGlobalWindowInner::ObserveStorageNotification(
5370 StorageEvent* aEvent, const char16_t* aStorageType, bool aPrivateBrowsing) {
5371 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"
, 5371); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent" ")"
); do { *((volatile int*)__null) = 5371; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5372
5373 // The private browsing check must be done here again because this window
5374 // could have changed its state before the notification check and now. This
5375 // happens in case this window did have a docShell at that time.
5376 if (aPrivateBrowsing != IsPrivateBrowsing()) {
5377 return;
5378 }
5379
5380 // LocalStorage can only exist on an inner window, and we don't want to
5381 // generate events on frozen or otherwise-navigated-away from windows.
5382 // (Actually, this code used to try and buffer events for frozen windows,
5383 // but it never worked, so we've removed it. See bug 1285898.)
5384 if (!IsCurrentInnerWindow() || IsFrozen()) {
5385 return;
5386 }
5387
5388 nsIPrincipal* principal = GetPrincipal();
5389 if (!principal) {
5390 return;
5391 }
5392
5393 bool fireMozStorageChanged = false;
5394 nsAutoString eventType;
5395 eventType.AssignLiteral("storage");
5396
5397 if (!NS_strcmp(aStorageType, u"sessionStorage")) {
5398 RefPtr<Storage> changingStorage = aEvent->GetStorageArea();
5399 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"
, 5399); AnnotateMozCrashReason("MOZ_ASSERT" "(" "changingStorage"
")"); do { *((volatile int*)__null) = 5399; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5400
5401 bool check = false;
5402
5403 if (const RefPtr<SessionStorageManager> storageManager =
5404 GetBrowsingContext()->GetSessionStorageManager()) {
5405 nsresult rv = storageManager->CheckStorage(GetEffectiveStoragePrincipal(),
5406 changingStorage, &check);
5407 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5408 return;
5409 }
5410 }
5411
5412 if (!check) {
5413 // This storage event is not coming from our storage or is coming
5414 // from a different docshell, i.e. it is a clone, ignore this event.
5415 return;
5416 }
5417
5418 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)
5419 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)
5420 ("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)
5421 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)
;
5422
5423 fireMozStorageChanged = mSessionStorage == changingStorage;
5424 if (fireMozStorageChanged) {
5425 eventType.AssignLiteral("MozSessionStorageChanged");
5426 }
5427 }
5428
5429 else {
5430 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"
, 5430); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_strcmp(aStorageType, u\"localStorage\")"
")"); do { *((volatile int*)__null) = 5430; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5431
5432 nsIPrincipal* storagePrincipal = GetEffectiveStoragePrincipal();
5433 if (!storagePrincipal) {
5434 return;
5435 }
5436
5437 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"
, 5438); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "StorageUtils::PrincipalsEqual(aEvent->GetPrincipal(), storagePrincipal)"
")"); do { *((volatile int*)__null) = 5438; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5438 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"
, 5438); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "StorageUtils::PrincipalsEqual(aEvent->GetPrincipal(), storagePrincipal)"
")"); do { *((volatile int*)__null) = 5438; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5439
5440 fireMozStorageChanged =
5441 mLocalStorage && mLocalStorage == aEvent->GetStorageArea();
5442
5443 if (fireMozStorageChanged) {
5444 eventType.AssignLiteral("MozLocalStorageChanged");
5445 }
5446 }
5447
5448 // Clone the storage event included in the observer notification. We want
5449 // to dispatch clones rather than the original event.
5450 IgnoredErrorResult error;
5451 RefPtr<StorageEvent> clonedEvent =
5452 CloneStorageEvent(eventType, aEvent, error);
5453 if (error.Failed() || !clonedEvent) {
5454 return;
5455 }
5456
5457 clonedEvent->SetTrusted(true);
5458
5459 if (fireMozStorageChanged) {
5460 WidgetEvent* internalEvent = clonedEvent->WidgetEventPtr();
5461 internalEvent->mFlags.mOnlyChromeDispatch = true;
5462 }
5463
5464 DispatchEvent(*clonedEvent);
5465}
5466
5467already_AddRefed<StorageEvent> nsGlobalWindowInner::CloneStorageEvent(
5468 const nsAString& aType, const RefPtr<StorageEvent>& aEvent,
5469 ErrorResult& aRv) {
5470 StorageEventInit dict;
5471
5472 dict.mBubbles = aEvent->Bubbles();
5473 dict.mCancelable = aEvent->Cancelable();
5474 aEvent->GetKey(dict.mKey);
5475 aEvent->GetOldValue(dict.mOldValue);
5476 aEvent->GetNewValue(dict.mNewValue);
5477 aEvent->GetUrl(dict.mUrl);
5478
5479 RefPtr<Storage> storageArea = aEvent->GetStorageArea();
5480
5481 RefPtr<Storage> storage;
5482
5483 // If null, this is a localStorage event received by IPC.
5484 if (!storageArea) {
5485 storage = GetLocalStorage(aRv);
5486 if (!NextGenLocalStorageEnabled()) {
5487 if (aRv.Failed() || !storage) {
5488 return nullptr;
5489 }
5490
5491 if (storage->Type() == Storage::eLocalStorage) {
5492 RefPtr<LocalStorage> localStorage =
5493 static_cast<LocalStorage*>(storage.get());
5494
5495 // We must apply the current change to the 'local' localStorage.
5496 localStorage->ApplyEvent(aEvent);
5497 }
5498 }
5499 } else if (storageArea->Type() == Storage::eSessionStorage) {
5500 storage = GetSessionStorage(aRv);
5501 } else {
5502 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"
, 5502); AnnotateMozCrashReason("MOZ_ASSERT" "(" "storageArea->Type() == Storage::eLocalStorage"
")"); do { *((volatile int*)__null) = 5502; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5503 storage = GetLocalStorage(aRv);
5504 }
5505
5506 if (aRv.Failed() || !storage) {
5507 return nullptr;
5508 }
5509
5510 if (storage->Type() == Storage::ePartitionedLocalStorage) {
5511 // This error message is not exposed.
5512 aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
5513 return nullptr;
5514 }
5515
5516 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"
, 5516); AnnotateMozCrashReason("MOZ_ASSERT" "(" "storage" ")"
); do { *((volatile int*)__null) = 5516; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5517 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"
, 5517); AnnotateMozCrashReason("MOZ_ASSERT" "(" "storage->IsForkOf(storageArea)"
")"); do { *((volatile int*)__null) = 5517; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
5518
5519 dict.mStorageArea = storage;
5520
5521 RefPtr<StorageEvent> event = StorageEvent::Constructor(this, aType, dict);
5522 return event.forget();
5523}
5524
5525void nsGlobalWindowInner::Suspend(bool aIncludeSubWindows) {
5526 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"
, 5526); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 5526; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5527
5528 // We can only safely suspend windows that are the current inner window. If
5529 // its not the current inner, then we are in one of two different cases.
5530 // Either we are in the bfcache or we are doomed window that is going away.
5531 // When a window becomes inactive we purposely avoid placing already suspended
5532 // windows into the bfcache. It only expects windows suspended due to the
5533 // Freeze() method which occurs while the window is still the current inner.
5534 // So we must not call Suspend() on bfcache windows at this point or this
5535 // invariant will be broken. If the window is doomed there is no point in
5536 // suspending it since it will soon be gone.
5537 if (!IsCurrentInnerWindow()) {
5538 return;
5539 }
5540
5541 // All in-process descendants are also suspended. This ensure mSuspendDepth
5542 // is set properly and the timers are properly canceled for each in-process
5543 // descendant.
5544 if (aIncludeSubWindows) {
5545 CallOnInProcessDescendants(&nsGlobalWindowInner::Suspend, false);
5546 }
5547
5548 mSuspendDepth += 1;
5549 if (mSuspendDepth != 1) {
5550 return;
5551 }
5552
5553 if (mWindowGlobalChild) {
5554 mWindowGlobalChild->BlockBFCacheFor(BFCacheStatus::SUSPENDED);
5555 }
5556
5557 nsCOMPtr<nsIDeviceSensors> ac = do_GetService(NS_DEVICE_SENSORS_CONTRACTID"@mozilla.org/devicesensors;1");
5558 if (ac) {
5559 for (uint32_t i = 0; i < mEnabledSensors.Length(); i++)
5560 ac->RemoveWindowListener(mEnabledSensors[i], this);
5561 }
5562 DisableGamepadUpdates();
5563 DisableVRUpdates();
5564
5565 SuspendWorkersForWindow(*this);
5566
5567 for (RefPtr<mozilla::dom::SharedWorker> pinnedWorker :
5568 mSharedWorkers.ForwardRange()) {
5569 pinnedWorker->Suspend();
5570 }
5571
5572 SuspendIdleRequests();
5573
5574 mTimeoutManager->Suspend();
5575
5576 // Suspend all of the AudioContexts for this window
5577 for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) {
5578 mAudioContexts[i]->SuspendFromChrome();
5579 }
5580}
5581
5582void nsGlobalWindowInner::Resume(bool aIncludeSubWindows) {
5583 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"
, 5583); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 5583; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5584
5585 // We can only safely resume a window if its the current inner window. If
5586 // its not the current inner, then we are in one of two different cases.
5587 // Either we are in the bfcache or we are doomed window that is going away.
5588 // If a window is suspended when it becomes inactive we purposely do not
5589 // put it in the bfcache, so Resume should never be needed in that case.
5590 // If the window is doomed then there is no point in resuming it.
5591 if (!IsCurrentInnerWindow()) {
5592 return;
5593 }
5594
5595 // Resume all in-process descendants. This restores timers recursively
5596 // canceled in Suspend() and ensures all in-process descendants have the
5597 // correct mSuspendDepth.
5598 if (aIncludeSubWindows) {
5599 CallOnInProcessDescendants(&nsGlobalWindowInner::Resume, false);
5600 }
5601
5602 if (mSuspendDepth == 0) {
5603 // Ignore if the window is not suspended.
5604 return;
5605 }
5606
5607 mSuspendDepth -= 1;
5608
5609 if (mSuspendDepth != 0) {
5610 return;
5611 }
5612
5613 // We should not be able to resume a frozen window. It must be Thaw()'d
5614 // first.
5615 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"
, 5615); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFreezeDepth == 0"
")"); do { *((volatile int*)__null) = 5615; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5616
5617 nsCOMPtr<nsIDeviceSensors> ac = do_GetService(NS_DEVICE_SENSORS_CONTRACTID"@mozilla.org/devicesensors;1");
5618 if (ac) {
5619 for (uint32_t i = 0; i < mEnabledSensors.Length(); i++)
5620 ac->AddWindowListener(mEnabledSensors[i], this);
5621 }
5622 EnableGamepadUpdates();
5623 EnableVRUpdates();
5624
5625 // Resume all of the AudioContexts for this window
5626 for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) {
5627 mAudioContexts[i]->ResumeFromChrome();
5628 }
5629
5630 if (RefPtr<MediaDevices> devices = GetExtantMediaDevices()) {
5631 devices->WindowResumed();
5632 }
5633
5634 mTimeoutManager->Resume();
5635
5636 ResumeIdleRequests();
5637
5638 // Resume all of the workers for this window. We must do this
5639 // after timeouts since workers may have queued events that can trigger
5640 // a setTimeout().
5641 ResumeWorkersForWindow(*this);
5642
5643 for (RefPtr<mozilla::dom::SharedWorker> pinnedWorker :
5644 mSharedWorkers.ForwardRange()) {
5645 pinnedWorker->Resume();
5646 }
5647
5648 if (mWindowGlobalChild) {
5649 mWindowGlobalChild->UnblockBFCacheFor(BFCacheStatus::SUSPENDED);
5650 }
5651}
5652
5653bool nsGlobalWindowInner::IsSuspended() const {
5654 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"
, 5654); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 5654; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5655 return mSuspendDepth != 0;
5656}
5657
5658void nsGlobalWindowInner::Freeze(bool aIncludeSubWindows) {
5659 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"
, 5659); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 5659; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5660 Suspend(aIncludeSubWindows);
5661 FreezeInternal(aIncludeSubWindows);
5662}
5663
5664void nsGlobalWindowInner::FreezeInternal(bool aIncludeSubWindows) {
5665 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"
, 5665); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 5665; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5666 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"
, 5666); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "IsCurrentInnerWindow()"
")"); do { *((volatile int*)__null) = 5666; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5667 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"
, 5667); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "IsSuspended()"
")"); do { *((volatile int*)__null) = 5667; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5668
5669 HintIsLoading(false);
5670
5671 if (aIncludeSubWindows) {
5672 CallOnInProcessChildren(&nsGlobalWindowInner::FreezeInternal,
5673 aIncludeSubWindows);
5674 }
5675
5676 mFreezeDepth += 1;
5677 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"
, 5677); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mSuspendDepth >= mFreezeDepth"
")"); do { *((volatile int*)__null) = 5677; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5678 if (mFreezeDepth != 1) {
5679 return;
5680 }
5681
5682 FreezeWorkersForWindow(*this);
5683
5684 for (RefPtr<mozilla::dom::SharedWorker> pinnedWorker :
5685 mSharedWorkers.ForwardRange()) {
5686 pinnedWorker->Freeze();
5687 }
5688
5689 mTimeoutManager->Freeze();
5690 if (mClientSource) {
5691 mClientSource->Freeze();
5692 }
5693
5694 NotifyDOMWindowFrozen(this);
5695 NotifyGlobalFrozen();
5696}
5697
5698void nsGlobalWindowInner::Thaw(bool aIncludeSubWindows) {
5699 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"
, 5699); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 5699; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5700 ThawInternal(aIncludeSubWindows);
5701 Resume(aIncludeSubWindows);
5702}
5703
5704void nsGlobalWindowInner::ThawInternal(bool aIncludeSubWindows) {
5705 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"
, 5705); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 5705; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5706 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"
, 5706); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "IsCurrentInnerWindow()"
")"); do { *((volatile int*)__null) = 5706; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5707 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"
, 5707); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "IsSuspended()"
")"); do { *((volatile int*)__null) = 5707; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5708
5709 if (aIncludeSubWindows) {
5710 CallOnInProcessChildren(&nsGlobalWindowInner::ThawInternal,
5711 aIncludeSubWindows);
5712 }
5713
5714 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"
, 5714); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFreezeDepth != 0"
")"); do { *((volatile int*)__null) = 5714; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5715 mFreezeDepth -= 1;
5716 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"
, 5716); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mSuspendDepth >= mFreezeDepth"
")"); do { *((volatile int*)__null) = 5716; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5717 if (mFreezeDepth != 0) {
5718 return;
5719 }
5720
5721 if (mClientSource) {
5722 mClientSource->Thaw();
5723 }
5724 mTimeoutManager->Thaw();
5725
5726 ThawWorkersForWindow(*this);
5727
5728 for (RefPtr<mozilla::dom::SharedWorker> pinnedWorker :
5729 mSharedWorkers.ForwardRange()) {
5730 pinnedWorker->Thaw();
5731 }
5732
5733 NotifyDOMWindowThawed(this);
5734 NotifyGlobalThawed();
5735}
5736
5737bool nsGlobalWindowInner::IsFrozen() const {
5738 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"
, 5738); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 5738; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5739 bool frozen = mFreezeDepth != 0;
5740 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"
, 5740); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsSuspended()"
")"); do { *((volatile int*)__null) = 5740; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
5741 return frozen;
5742}
5743
5744void nsGlobalWindowInner::SyncStateFromParentWindow() {
5745 // This method should only be called on an inner window that has been
5746 // assigned to an outer window already.
5747 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"
, 5747); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsCurrentInnerWindow()"
")"); do { *((volatile int*)__null) = 5747; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5748 nsPIDOMWindowOuter* outer = GetOuterWindow();
5749 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"
, 5749); AnnotateMozCrashReason("MOZ_ASSERT" "(" "outer" ")")
; do { *((volatile int*)__null) = 5749; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5750
5751 // Attempt to find our parent windows.
5752 nsCOMPtr<Element> frame = outer->GetFrameElementInternal();
5753 nsPIDOMWindowOuter* parentOuter =
5754 frame ? frame->OwnerDoc()->GetWindow() : nullptr;
5755 nsGlobalWindowInner* parentInner =
5756 parentOuter
5757 ? nsGlobalWindowInner::Cast(parentOuter->GetCurrentInnerWindow())
5758 : nullptr;
5759
5760 // If our outer is in a modal state, but our parent is not in a modal
5761 // state, then we must apply the suspend directly. If our parent is
5762 // in a modal state then we should get the suspend automatically
5763 // via the parentSuspendDepth application below.
5764 if ((!parentInner || !parentInner->IsInModalState()) && IsInModalState()) {
5765 Suspend();
5766 }
5767
5768 uint32_t parentFreezeDepth = parentInner ? parentInner->mFreezeDepth : 0;
5769 uint32_t parentSuspendDepth = parentInner ? parentInner->mSuspendDepth : 0;
5770
5771 // Since every Freeze() calls Suspend(), the suspend count must
5772 // be equal or greater to the freeze count.
5773 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"
, 5773); AnnotateMozCrashReason("MOZ_ASSERT" "(" "parentFreezeDepth <= parentSuspendDepth"
")"); do { *((volatile int*)__null) = 5773; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5774
5775 // First apply the Freeze() calls.
5776 for (uint32_t i = 0; i < parentFreezeDepth; ++i) {
5777 Freeze();
5778 }
5779
5780 // Now apply only the number of Suspend() calls to reach the target
5781 // suspend count after applying the Freeze() calls.
5782 for (uint32_t i = 0; i < (parentSuspendDepth - parentFreezeDepth); ++i) {
5783 Suspend();
5784 }
5785}
5786
5787void nsGlobalWindowInner::UpdateBackgroundState() {
5788 if (RefPtr<MediaDevices> devices = GetExtantMediaDevices()) {
5789 devices->BackgroundStateChanged();
5790 }
5791 mTimeoutManager->UpdateBackgroundState();
5792
5793 UpdateWorkersBackgroundState(*this, IsBackgroundInternal());
5794}
5795
5796template <typename Method, typename... Args>
5797CallState nsGlobalWindowInner::CallOnInProcessDescendantsInternal(
5798 BrowsingContext* aBrowsingContext, bool aChildOnly, Method aMethod,
5799 Args&&... aArgs) {
5800 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"
, 5800); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 5800; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5801 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"
, 5801); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBrowsingContext"
")"); do { *((volatile int*)__null) = 5801; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5802
5803 CallState state = CallState::Continue;
5804 for (const RefPtr<BrowsingContext>& bc : aBrowsingContext->Children()) {
5805 if (nsCOMPtr<nsPIDOMWindowOuter> pWin = bc->GetDOMWindow()) {
5806 auto* win = nsGlobalWindowOuter::Cast(pWin);
5807 if (nsGlobalWindowInner* inner =
5808 nsGlobalWindowInner::Cast(win->GetCurrentInnerWindow())) {
5809 // Call the descendant method using our helper CallDescendant() template
5810 // method. This allows us to handle both void returning methods and
5811 // methods that return CallState explicitly. For void returning methods
5812 // we assume CallState::Continue.
5813 using returnType = decltype((inner->*aMethod)(aArgs...));
5814 state = CallDescendant<returnType>(inner, aMethod, aArgs...);
5815
5816 if (state == CallState::Stop) {
5817 return state;
5818 }
5819 }
5820 }
5821
5822 if (!aChildOnly) {
5823 state = CallOnInProcessDescendantsInternal(bc.get(), aChildOnly, aMethod,
5824 aArgs...);
5825 if (state == CallState::Stop) {
5826 return state;
5827 }
5828 }
5829 }
5830
5831 return state;
5832}
5833
5834Maybe<ClientInfo> nsGlobalWindowInner::GetClientInfo() const {
5835 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"
, 5835); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 5835; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5836 if (mDoc && mDoc->IsStaticDocument()) {
5837 if (Maybe<ClientInfo> info = mDoc->GetOriginalDocument()->GetClientInfo()) {
5838 return info;
5839 }
5840 }
5841
5842 Maybe<ClientInfo> clientInfo;
5843 if (mClientSource) {
5844 clientInfo.emplace(mClientSource->Info());
5845 }
5846 return clientInfo;
5847}
5848
5849Maybe<ClientState> nsGlobalWindowInner::GetClientState() const {
5850 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"
, 5850); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 5850; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5851 if (mDoc && mDoc->IsStaticDocument()) {
5852 if (Maybe<ClientState> state =
5853 mDoc->GetOriginalDocument()->GetClientState()) {
5854 return state;
5855 }
5856 }
5857
5858 Maybe<ClientState> clientState;
5859 if (mClientSource) {
5860 Result<ClientState, ErrorResult> res = mClientSource->SnapshotState();
5861 if (res.isOk()) {
5862 clientState.emplace(res.unwrap());
5863 } else {
5864 res.unwrapErr().SuppressException();
5865 }
5866 }
5867 return clientState;
5868}
5869
5870Maybe<ServiceWorkerDescriptor> nsGlobalWindowInner::GetController() const {
5871 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"
, 5871); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 5871; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5872 if (mDoc && mDoc->IsStaticDocument()) {
5873 if (Maybe<ServiceWorkerDescriptor> controller =
5874 mDoc->GetOriginalDocument()->GetController()) {
5875 return controller;
5876 }
5877 }
5878
5879 Maybe<ServiceWorkerDescriptor> controller;
5880 if (mClientSource) {
5881 controller = mClientSource->GetController();
5882 }
5883 return controller;
5884}
5885
5886void nsGlobalWindowInner::SetCsp(nsIContentSecurityPolicy* aCsp) {
5887 if (!mClientSource) {
5888 return;
5889 }
5890 mClientSource->SetCsp(aCsp);
5891 // Also cache the CSP within the document
5892 mDoc->SetCsp(aCsp);
5893
5894 if (mWindowGlobalChild) {
5895 mWindowGlobalChild->SendSetClientInfo(mClientSource->Info().ToIPC());
5896 }
5897}
5898
5899void nsGlobalWindowInner::SetPreloadCsp(nsIContentSecurityPolicy* aPreloadCsp) {
5900 if (!mClientSource) {
5901 return;
5902 }
5903 mClientSource->SetPreloadCsp(aPreloadCsp);
5904 // Also cache the preload CSP within the document
5905 mDoc->SetPreloadCsp(aPreloadCsp);
5906
5907 if (mWindowGlobalChild) {
5908 mWindowGlobalChild->SendSetClientInfo(mClientSource->Info().ToIPC());
5909 }
5910}
5911
5912nsIContentSecurityPolicy* nsGlobalWindowInner::GetCsp() {
5913 if (mDoc) {
5914 return mDoc->GetCsp();
5915 }
5916
5917 // If the window is partially torn down and has its document nulled out,
5918 // we query the CSP we snapshot in FreeInnerObjects.
5919 if (mDocumentCsp) {
5920 return mDocumentCsp;
5921 }
5922 return nullptr;
5923}
5924
5925RefPtr<ServiceWorker> nsGlobalWindowInner::GetOrCreateServiceWorker(
5926 const ServiceWorkerDescriptor& aDescriptor) {
5927 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"
, 5927); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 5927; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5928 RefPtr<ServiceWorker> ref;
5929 ForEachGlobalTeardownObserver(
5930 [&](GlobalTeardownObserver* aObserver, bool* aDoneOut) {
5931 RefPtr<ServiceWorker> sw = do_QueryObject(aObserver);
5932 if (!sw || !sw->Descriptor().Matches(aDescriptor)) {
5933 return;
5934 }
5935
5936 ref = std::move(sw);
5937 *aDoneOut = true;
5938 });
5939
5940 if (!ref) {
5941 ref = ServiceWorker::Create(this, aDescriptor);
5942 }
5943
5944 return ref;
5945}
5946
5947RefPtr<mozilla::dom::ServiceWorkerRegistration>
5948nsGlobalWindowInner::GetServiceWorkerRegistration(
5949 const mozilla::dom::ServiceWorkerRegistrationDescriptor& aDescriptor)
5950 const {
5951 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"
, 5951); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 5951; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5952 RefPtr<ServiceWorkerRegistration> ref;
5953 ForEachGlobalTeardownObserver(
5954 [&](GlobalTeardownObserver* aObserver, bool* aDoneOut) {
5955 RefPtr<ServiceWorkerRegistration> swr = do_QueryObject(aObserver);
5956 if (!swr || !swr->MatchesDescriptor(aDescriptor)) {
5957 return;
5958 }
5959
5960 ref = std::move(swr);
5961 *aDoneOut = true;
5962 });
5963 return ref;
5964}
5965
5966RefPtr<ServiceWorkerRegistration>
5967nsGlobalWindowInner::GetOrCreateServiceWorkerRegistration(
5968 const ServiceWorkerRegistrationDescriptor& aDescriptor) {
5969 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"
, 5969); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 5969; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5970 RefPtr<ServiceWorkerRegistration> ref =
5971 GetServiceWorkerRegistration(aDescriptor);
5972 if (!ref) {
5973 ref = ServiceWorkerRegistration::CreateForMainThread(this, aDescriptor);
5974 }
5975 return ref;
5976}
5977
5978StorageAccess nsGlobalWindowInner::GetStorageAccess() {
5979 return StorageAllowedForWindow(this);
5980}
5981
5982nsresult nsGlobalWindowInner::FireDelayedDOMEvents(bool aIncludeSubWindows) {
5983 // Fires an offline status event if the offline status has changed
5984 FireOfflineStatusEventIfChanged();
5985
5986 if (!aIncludeSubWindows) {
5987 return NS_OK;
5988 }
5989
5990 nsCOMPtr<nsIDocShell> docShell = GetDocShell();
5991 if (docShell) {
5992 int32_t childCount = 0;
5993 docShell->GetInProcessChildCount(&childCount);
5994
5995 // Take a copy of the current children so that modifications to
5996 // the child list don't affect to the iteration.
5997 AutoTArray<nsCOMPtr<nsIDocShellTreeItem>, 8> children;
5998 for (int32_t i = 0; i < childCount; ++i) {
5999 nsCOMPtr<nsIDocShellTreeItem> childShell;
6000 docShell->GetInProcessChildAt(i, getter_AddRefs(childShell));
6001 if (childShell) {
6002 children.AppendElement(childShell);
6003 }
6004 }
6005
6006 for (nsCOMPtr<nsIDocShellTreeItem> childShell : children) {
6007 if (nsCOMPtr<nsPIDOMWindowOuter> pWin = childShell->GetWindow()) {
6008 auto* win = nsGlobalWindowOuter::Cast(pWin);
6009 win->FireDelayedDOMEvents(true);
6010 }
6011 }
6012 }
6013
6014 return NS_OK;
6015}
6016
6017//*****************************************************************************
6018// nsGlobalWindowInner: Window Control Functions
6019//*****************************************************************************
6020
6021nsPIDOMWindowOuter* nsGlobalWindowInner::GetInProcessParentInternal() {
6022 nsGlobalWindowOuter* outer = GetOuterWindowInternal();
6023 if (!outer) {
6024 // No outer window available!
6025 return nullptr;
6026 }
6027 return outer->GetInProcessParentInternal();
6028}
6029
6030nsIPrincipal* nsGlobalWindowInner::GetTopLevelAntiTrackingPrincipal() {
6031 nsPIDOMWindowOuter* outerWindow = GetOuterWindowInternal();
6032 if (!outerWindow) {
6033 return nullptr;
6034 }
6035
6036 nsPIDOMWindowOuter* topLevelOuterWindow =
6037 GetBrowsingContext()->Top()->GetDOMWindow();
6038 if (!topLevelOuterWindow) {
6039 return nullptr;
6040 }
6041
6042 bool stopAtOurLevel =
6043 mDoc && mDoc->CookieJarSettings()->GetCookieBehavior() ==
6044 nsICookieService::BEHAVIOR_REJECT_TRACKER;
6045
6046 if (stopAtOurLevel && topLevelOuterWindow == outerWindow) {
6047 return nullptr;
6048 }
6049
6050 nsPIDOMWindowInner* topLevelInnerWindow =
6051 topLevelOuterWindow->GetCurrentInnerWindow();
6052 if (NS_WARN_IF(!topLevelInnerWindow)NS_warn_if_impl(!topLevelInnerWindow, "!topLevelInnerWindow",
"/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 6052)
) {
6053 return nullptr;
6054 }
6055
6056 nsIPrincipal* topLevelPrincipal =
6057 nsGlobalWindowInner::Cast(topLevelInnerWindow)->GetPrincipal();
6058 if (NS_WARN_IF(!topLevelPrincipal)NS_warn_if_impl(!topLevelPrincipal, "!topLevelPrincipal", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 6058)
) {
6059 return nullptr;
6060 }
6061
6062 return topLevelPrincipal;
6063}
6064
6065nsIPrincipal* nsGlobalWindowInner::GetClientPrincipal() {
6066 return mClientSource ? mClientSource->GetPrincipal() : nullptr;
6067}
6068
6069bool nsGlobalWindowInner::IsInFullScreenTransition() {
6070 if (!mIsChrome) {
6071 return false;
6072 }
6073
6074 nsGlobalWindowOuter* outerWindow = GetOuterWindowInternal();
6075 if (!outerWindow) {
6076 return false;
6077 }
6078
6079 return outerWindow->mIsInFullScreenTransition;
6080}
6081
6082//*****************************************************************************
6083// nsGlobalWindowInner: Timeout Functions
6084//*****************************************************************************
6085
6086class WindowScriptTimeoutHandler final : public ScriptTimeoutHandler {
6087 public:
6088 NS_DECL_ISUPPORTS_INHERITEDpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override;
6089 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"
, 6090); AnnotateMozCrashReason("MOZ_ASSERT" "(" "p == &_cycleCollectorGlobal"
") (" "WindowScriptTimeoutHandler" " should QI to its own CC participant"
")"); do { *((volatile int*)__null) = 6090; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } static cycleCollection
_cycleCollectorGlobal;
6090 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"
, 6090); AnnotateMozCrashReason("MOZ_ASSERT" "(" "p == &_cycleCollectorGlobal"
") (" "WindowScriptTimeoutHandler" " should QI to its own CC participant"
")"); do { *((volatile int*)__null) = 6090; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } static cycleCollection
_cycleCollectorGlobal;
6091
6092 WindowScriptTimeoutHandler(JSContext* aCx, nsIGlobalObject* aGlobal,
6093 const nsAString& aExpression)
6094 : ScriptTimeoutHandler(aCx, aGlobal, aExpression),
6095 mInitiatingScript(ScriptLoader::GetActiveScript(aCx)) {}
6096
6097 MOZ_CAN_RUN_SCRIPT virtual bool Call(const char* aExecutionReason) override;
6098
6099 private:
6100 virtual ~WindowScriptTimeoutHandler() = default;
6101
6102 // Initiating script for use when evaluating mExpr on the main thread.
6103 RefPtr<JS::loader::LoadedScript> mInitiatingScript;
6104};
6105
6106NS_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; }
6107 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; }
6108
6109NS_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"
, 6109); 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
6110NS_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; }
6111
6112NS_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; }
6113NS_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; }
6114
6115bool WindowScriptTimeoutHandler::Call(const char* aExecutionReason) {
6116 // New script entry point required, due to the "Create a script" sub-step
6117 // of
6118 // http://www.whatwg.org/specs/web-apps/current-work/#timer-initialisation-steps
6119 nsAutoMicroTask mt;
6120 AutoEntryScript aes(mGlobal, aExecutionReason, true);
6121 JS::CompileOptions options(aes.cx());
6122 options.setFileAndLine(mFileName.get(), mLineNo);
6123 options.setNoScriptRval(true);
6124 options.setIntroductionType("domTimer");
6125 JS::Rooted<JSObject*> global(aes.cx(), mGlobal->GetGlobalJSObject());
6126 {
6127 JSExecutionContext exec(aes.cx(), global, options);
6128 nsresult rv = exec.Compile(mExpr);
6129
6130 JS::Rooted<JSScript*> script(aes.cx(), exec.MaybeGetScript());
6131 if (script) {
6132 if (mInitiatingScript) {
6133 mInitiatingScript->AssociateWithScript(script);
6134 }
6135
6136 rv = exec.ExecScript();
6137 }
6138
6139 if (rv == NS_SUCCESS_DOM_SCRIPT_EVALUATION_THREW_UNCATCHABLE) {
6140 return false;
6141 }
6142 }
6143
6144 return true;
6145};
6146
6147nsGlobalWindowInner* nsGlobalWindowInner::InnerForSetTimeoutOrInterval(
6148 ErrorResult& aError) {
6149 nsGlobalWindowOuter* outer = GetOuterWindowInternal();
6150 nsPIDOMWindowInner* currentInner =
6151 outer ? outer->GetCurrentInnerWindow() : this;
6152
6153 // If forwardTo is not the window with an active document then we want the
6154 // call to setTimeout/Interval to be a noop, so return null but don't set an
6155 // error.
6156 return HasActiveDocument() ? nsGlobalWindowInner::Cast(currentInner)
6157 : nullptr;
6158}
6159
6160int32_t nsGlobalWindowInner::SetTimeout(JSContext* aCx, Function& aFunction,
6161 int32_t aTimeout,
6162 const Sequence<JS::Value>& aArguments,
6163 ErrorResult& aError) {
6164 return SetTimeoutOrInterval(aCx, aFunction, aTimeout, aArguments, false,
6165 aError);
6166}
6167
6168int32_t nsGlobalWindowInner::SetTimeout(JSContext* aCx,
6169 const nsAString& aHandler,
6170 int32_t aTimeout,
6171 const Sequence<JS::Value>& /* unused */,
6172 ErrorResult& aError) {
6173 return SetTimeoutOrInterval(aCx, aHandler, aTimeout, false, aError);
6174}
6175
6176int32_t nsGlobalWindowInner::SetInterval(JSContext* aCx, Function& aFunction,
6177 const int32_t aTimeout,
6178 const Sequence<JS::Value>& aArguments,
6179 ErrorResult& aError) {
6180 return SetTimeoutOrInterval(aCx, aFunction, aTimeout, aArguments, true,
6181 aError);
6182}
6183
6184int32_t nsGlobalWindowInner::SetInterval(
6185 JSContext* aCx, const nsAString& aHandler, const int32_t aTimeout,
6186 const Sequence<JS::Value>& /* unused */, ErrorResult& aError) {
6187 return SetTimeoutOrInterval(aCx, aHandler, aTimeout, true, aError);
6188}
6189
6190int32_t nsGlobalWindowInner::SetTimeoutOrInterval(
6191 JSContext* aCx, Function& aFunction, int32_t aTimeout,
6192 const Sequence<JS::Value>& aArguments, bool aIsInterval,
6193 ErrorResult& aError) {
6194 nsGlobalWindowInner* inner = InnerForSetTimeoutOrInterval(aError);
6195 if (!inner) {
6196 return -1;
6197 }
6198
6199 if (inner != this) {
6200 RefPtr<nsGlobalWindowInner> innerRef(inner);
6201 return innerRef->SetTimeoutOrInterval(aCx, aFunction, aTimeout, aArguments,
6202 aIsInterval, aError);
6203 }
6204
6205 DebuggerNotificationDispatch(
6206 this, aIsInterval ? DebuggerNotificationType::SetInterval
6207 : DebuggerNotificationType::SetTimeout);
6208
6209 if (!GetContextInternal() || !HasJSGlobal()) {
6210 // This window was already closed, or never properly initialized,
6211 // don't let a timer be scheduled on such a window.
6212 aError.Throw(NS_ERROR_NOT_INITIALIZED);
6213 return 0;
6214 }
6215
6216 nsTArray<JS::Heap<JS::Value>> args;
6217 if (!args.AppendElements(aArguments, fallible)) {
6218 aError.Throw(NS_ERROR_OUT_OF_MEMORY);
6219 return 0;
6220 }
6221
6222 RefPtr<TimeoutHandler> handler =
6223 new CallbackTimeoutHandler(aCx, this, &aFunction, std::move(args));
6224
6225 int32_t result;
6226 aError =
6227 mTimeoutManager->SetTimeout(handler, aTimeout, aIsInterval,
6228 Timeout::Reason::eTimeoutOrInterval, &result);
6229 return result;
6230}
6231
6232int32_t nsGlobalWindowInner::SetTimeoutOrInterval(JSContext* aCx,
6233 const nsAString& aHandler,
6234 int32_t aTimeout,
6235 bool aIsInterval,
6236 ErrorResult& aError) {
6237 nsGlobalWindowInner* inner = InnerForSetTimeoutOrInterval(aError);
6238 if (!inner) {
6239 return -1;
6240 }
6241
6242 if (inner != this) {
6243 RefPtr<nsGlobalWindowInner> innerRef(inner);
6244 return innerRef->SetTimeoutOrInterval(aCx, aHandler, aTimeout, aIsInterval,
6245 aError);
6246 }
6247
6248 DebuggerNotificationDispatch(
6249 this, aIsInterval ? DebuggerNotificationType::SetInterval
6250 : DebuggerNotificationType::SetTimeout);
6251
6252 if (!GetContextInternal() || !HasJSGlobal()) {
6253 // This window was already closed, or never properly initialized,
6254 // don't let a timer be scheduled on such a window.
6255 aError.Throw(NS_ERROR_NOT_INITIALIZED);
6256 return 0;
6257 }
6258
6259 bool allowEval = false;
6260 aError = CSPEvalChecker::CheckForWindow(aCx, this, aHandler, &allowEval);
6261 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"
, 6261)
|| !allowEval) {
6262 return 0;
6263 }
6264
6265 RefPtr<TimeoutHandler> handler =
6266 new WindowScriptTimeoutHandler(aCx, this, aHandler);
6267
6268 int32_t result;
6269 aError =
6270 mTimeoutManager->SetTimeout(handler, aTimeout, aIsInterval,
6271 Timeout::Reason::eTimeoutOrInterval, &result);
6272 return result;
6273}
6274
6275static const char* GetTimeoutReasonString(Timeout* aTimeout) {
6276 switch (aTimeout->mReason) {
6277 case Timeout::Reason::eTimeoutOrInterval:
6278 if (aTimeout->mIsInterval) {
6279 return "setInterval handler";
6280 }
6281 return "setTimeout handler";
6282 case Timeout::Reason::eIdleCallbackTimeout:
6283 return "setIdleCallback handler (timed out)";
6284 case Timeout::Reason::eAbortSignalTimeout:
6285 return "AbortSignal timeout";
6286 case Timeout::Reason::eDelayedWebTaskTimeout:
6287 return "delayedWebTaskCallback handler (timed out)";
6288 default:
6289 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"
, 6289); AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected enum value"
")"); do { *((volatile int*)__null) = 6289; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
6290 return "";
6291 }
6292 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"
, 6292); AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected enum value"
")"); do { *((volatile int*)__null) = 6292; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
6293 return "";
6294}
6295
6296bool nsGlobalWindowInner::RunTimeoutHandler(Timeout* aTimeout,
6297 nsIScriptContext* aScx) {
6298 // Hold on to the timeout in case mExpr or mFunObj releases its
6299 // doc.
6300 // XXXbz Our caller guarantees it'll hold on to the timeout (because
6301 // we're MOZ_CAN_RUN_SCRIPT), so we can probably stop doing that...
6302 RefPtr<Timeout> timeout = aTimeout;
6303 Timeout* last_running_timeout = mTimeoutManager->BeginRunningTimeout(timeout);
6304 timeout->mRunning = true;
6305
6306 // Push this timeout's popup control state, which should only be
6307 // enabled the first time a timeout fires that was created while
6308 // popups were enabled and with a delay less than
6309 // "dom.disable_open_click_delay".
6310 AutoPopupStatePusherAutoPopupStatePusherInternal popupStatePusher(timeout->mPopupState);
6311
6312 // Clear the timeout's popup state, if any, to prevent interval
6313 // timeouts from repeatedly opening poups.
6314 timeout->mPopupState = PopupBlocker::openAbused;
6315
6316 uint32_t nestingLevel = TimeoutManager::GetNestingLevel();
6317 TimeoutManager::SetNestingLevel(timeout->mNestingLevel);
6318
6319 const char* reason = GetTimeoutReasonString(timeout);
6320
6321 nsCString str;
6322 if (profiler_thread_is_being_profiled_for_markers()) {
6323 TimeDuration originalInterval = timeout->When() - timeout->SubmitTime();
6324 str.Append(reason);
6325 str.Append(" with interval ");
6326 str.AppendInt(int(originalInterval.ToMilliseconds()));
6327 str.Append("ms: ");
6328 nsCString handlerDescription;
6329 timeout->mScriptHandler->GetDescription(handlerDescription);
6330 str.Append(handlerDescription);
6331 }
6332 AUTO_PROFILER_MARKER_TEXT("setTimeout callback", DOM,AutoProfilerTextMarker raiiObject6336( "setTimeout callback",
::mozilla::baseprofiler::category::DOM, MarkerOptions(MarkerStack
::TakeBacktrace( timeout->TakeProfilerBacktrace()), MarkerInnerWindowId
(mWindowID)), str)
6333 MarkerOptions(MarkerStack::TakeBacktrace(AutoProfilerTextMarker raiiObject6336( "setTimeout callback",
::mozilla::baseprofiler::category::DOM, MarkerOptions(MarkerStack
::TakeBacktrace( timeout->TakeProfilerBacktrace()), MarkerInnerWindowId
(mWindowID)), str)
6334 timeout->TakeProfilerBacktrace()),AutoProfilerTextMarker raiiObject6336( "setTimeout callback",
::mozilla::baseprofiler::category::DOM, MarkerOptions(MarkerStack
::TakeBacktrace( timeout->TakeProfilerBacktrace()), MarkerInnerWindowId
(mWindowID)), str)
6335 MarkerInnerWindowId(mWindowID)),AutoProfilerTextMarker raiiObject6336( "setTimeout callback",
::mozilla::baseprofiler::category::DOM, MarkerOptions(MarkerStack
::TakeBacktrace( timeout->TakeProfilerBacktrace()), MarkerInnerWindowId
(mWindowID)), str)
6336 str)AutoProfilerTextMarker raiiObject6336( "setTimeout callback",
::mozilla::baseprofiler::category::DOM, MarkerOptions(MarkerStack
::TakeBacktrace( timeout->TakeProfilerBacktrace()), MarkerInnerWindowId
(mWindowID)), str)
;
6337
6338 bool abortIntervalHandler;
6339 {
6340 RefPtr<TimeoutHandler> handler(timeout->mScriptHandler);
6341
6342 CallbackDebuggerNotificationGuard guard(
6343 this, timeout->mIsInterval
6344 ? DebuggerNotificationType::SetIntervalCallback
6345 : DebuggerNotificationType::SetTimeoutCallback);
6346 abortIntervalHandler = !handler->Call(reason);
6347 }
6348
6349 // If we received an uncatchable exception, do not schedule the timeout again.
6350 // This allows the slow script dialog to break easy DoS attacks like
6351 // setInterval(function() { while(1); }, 100);
6352 if (abortIntervalHandler) {
6353 // If it wasn't an interval timer to begin with, this does nothing. If it
6354 // was, we'll treat it as a timeout that we just ran and discard it when
6355 // we return.
6356 timeout->mIsInterval = false;
6357 }
6358
6359 // We ignore any failures from calling EvaluateString() on the context or
6360 // Call() on a Function here since we're in a loop
6361 // where we're likely to be running timeouts whose OS timers
6362 // didn't fire in time and we don't want to not fire those timers
6363 // now just because execution of one timer failed. We can't
6364 // propagate the error to anyone who cares about it from this
6365 // point anyway, and the script context should have already reported
6366 // the script error in the usual way - so we just drop it.
6367
6368 TimeoutManager::SetNestingLevel(nestingLevel);
6369
6370 mTimeoutManager->EndRunningTimeout(last_running_timeout);
6371 timeout->mRunning = false;
6372
6373 return timeout->mCleared;
6374}
6375
6376//*****************************************************************************
6377// nsGlobalWindowInner: Helper Functions
6378//*****************************************************************************
6379
6380already_AddRefed<nsIDocShellTreeOwner> nsGlobalWindowInner::GetTreeOwner() {
6381 FORWARD_TO_OUTER(GetTreeOwner, (), nullptr);
6382}
6383
6384already_AddRefed<nsIWebBrowserChrome>
6385nsGlobalWindowInner::GetWebBrowserChrome() {
6386 nsCOMPtr<nsIDocShellTreeOwner> treeOwner = GetTreeOwner();
6387
6388 nsCOMPtr<nsIWebBrowserChrome> browserChrome = do_GetInterface(treeOwner);
6389 return browserChrome.forget();
6390}
6391
6392ScrollContainerFrame* nsGlobalWindowInner::GetScrollContainerFrame() {
6393 FORWARD_TO_OUTER(GetScrollContainerFrame, (), nullptr);
6394}
6395
6396bool nsGlobalWindowInner::IsPrivateBrowsing() {
6397 nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(GetDocShell());
6398 return loadContext && loadContext->UsePrivateBrowsing();
6399}
6400
6401void nsGlobalWindowInner::FlushPendingNotifications(FlushType aType) {
6402 if (mDoc) {
6403 mDoc->FlushPendingNotifications(aType);
6404 }
6405}
6406
6407void nsGlobalWindowInner::EnableDeviceSensor(uint32_t aType) {
6408 bool alreadyEnabled = false;
6409 for (uint32_t i = 0; i < mEnabledSensors.Length(); i++) {
6410 if (mEnabledSensors[i] == aType) {
6411 alreadyEnabled = true;
6412 break;
6413 }
6414 }
6415
6416 mEnabledSensors.AppendElement(aType);
6417
6418 if (alreadyEnabled) {
6419 return;
6420 }
6421
6422 nsCOMPtr<nsIDeviceSensors> ac = do_GetService(NS_DEVICE_SENSORS_CONTRACTID"@mozilla.org/devicesensors;1");
6423 if (ac) {
6424 ac->AddWindowListener(aType, this);
6425 }
6426}
6427
6428void nsGlobalWindowInner::DisableDeviceSensor(uint32_t aType) {
6429 int32_t doomedElement = -1;
6430 int32_t listenerCount = 0;
6431 for (uint32_t i = 0; i < mEnabledSensors.Length(); i++) {
6432 if (mEnabledSensors[i] == aType) {
6433 doomedElement = i;
6434 listenerCount++;
6435 }
6436 }
6437
6438 if (doomedElement == -1) {
6439 return;
6440 }
6441
6442 mEnabledSensors.RemoveElementAt(doomedElement);
6443
6444 if (listenerCount > 1) {
6445 return;
6446 }
6447
6448 nsCOMPtr<nsIDeviceSensors> ac = do_GetService(NS_DEVICE_SENSORS_CONTRACTID"@mozilla.org/devicesensors;1");
6449 if (ac) {
6450 ac->RemoveWindowListener(aType, this);
6451 }
6452}
6453
6454#if defined(MOZ_WIDGET_ANDROID)
6455void nsGlobalWindowInner::EnableOrientationChangeListener() {
6456 if (!ShouldResistFingerprinting(RFPTarget::ScreenOrientation)) {
6457 mHasOrientationChangeListeners = true;
6458 mOrientationAngle = Orientation(CallerType::System);
6459 }
6460}
6461
6462void nsGlobalWindowInner::DisableOrientationChangeListener() {
6463 mHasOrientationChangeListeners = false;
6464}
6465#endif
6466
6467void nsGlobalWindowInner::SetHasGamepadEventListener(
6468 bool aHasGamepad /* = true*/) {
6469 mHasGamepad = aHasGamepad;
6470 if (aHasGamepad) {
6471 EnableGamepadUpdates();
6472 }
6473}
6474
6475void nsGlobalWindowInner::NotifyDetectXRRuntimesCompleted() {
6476 if (!mXRRuntimeDetectionInFlight) {
6477 return;
6478 }
6479 mXRRuntimeDetectionInFlight = false;
6480 if (mXRPermissionRequestInFlight) {
6481 return;
6482 }
6483 gfx::VRManagerChild* vm = gfx::VRManagerChild::Get();
6484 bool supported = vm->RuntimeSupportsVR();
6485 if (!supported) {
6486 // A VR runtime was not installed; we can suppress
6487 // the permission prompt
6488 OnXRPermissionRequestCancel();
6489 return;
6490 }
6491 // A VR runtime was found. Display a permission prompt before
6492 // allowing it to be accessed.
6493 // Connect to the VRManager in order to receive the runtime
6494 // detection results.
6495 mXRPermissionRequestInFlight = true;
6496 RefPtr<XRPermissionRequest> request =
6497 new XRPermissionRequest(this, WindowID());
6498 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"
, 6498)
;
6499}
6500
6501void nsGlobalWindowInner::RequestXRPermission() {
6502 if (IsDying()) {
6503 // Do not proceed if the window is dying, as that will result
6504 // in leaks of objects that get re-allocated after FreeInnerObjects
6505 // has been called, including mVREventObserver.
6506 return;
6507 }
6508 if (mXRPermissionGranted) {
6509 // Don't prompt redundantly once permission to
6510 // access XR devices has been granted.
6511 OnXRPermissionRequestAllow();
6512 return;
6513 }
6514 if (mXRRuntimeDetectionInFlight || mXRPermissionRequestInFlight) {
6515 // Don't allow multiple simultaneous permissions requests;
6516 return;
6517 }
6518 // Before displaying a permission prompt, detect
6519 // if there is any VR runtime installed.
6520 gfx::VRManagerChild* vm = gfx::VRManagerChild::Get();
6521 mXRRuntimeDetectionInFlight = true;
6522 EnableVRUpdates();
6523 vm->DetectRuntimes();
6524}
6525
6526void nsGlobalWindowInner::OnXRPermissionRequestAllow() {
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 mXRPermissionGranted = true;
6537
6538 NotifyHasXRSession();
6539
6540 dom::Navigator* nav = Navigator();
6541 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"
, 6541); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nav != nullptr"
")"); do { *((volatile int*)__null) = 6541; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6542 nav->OnXRPermissionRequestAllow();
6543}
6544
6545void nsGlobalWindowInner::OnXRPermissionRequestCancel() {
6546 mXRPermissionRequestInFlight = false;
6547 if (IsDying()) {
6548 // The window may have started dying while the permission request
6549 // is in flight.
6550 // Do not proceed if the window is dying, as that will result
6551 // in leaks of objects that get re-allocated after FreeInnerObjects
6552 // has been called, including mNavigator.
6553 return;
6554 }
6555 dom::Navigator* nav = Navigator();
6556 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"
, 6556); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nav != nullptr"
")"); do { *((volatile int*)__null) = 6556; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6557 nav->OnXRPermissionRequestCancel();
6558}
6559
6560void nsGlobalWindowInner::EventListenerAdded(nsAtom* aType) {
6561 if (aType == nsGkAtoms::onvrdisplayactivate ||
6562 aType == nsGkAtoms::onvrdisplayconnect ||
6563 aType == nsGkAtoms::onvrdisplaydeactivate ||
6564 aType == nsGkAtoms::onvrdisplaydisconnect ||
6565 aType == nsGkAtoms::onvrdisplaypresentchange) {
6566 RequestXRPermission();
6567 }
6568
6569 if (aType == nsGkAtoms::onvrdisplayactivate) {
6570 mHasVRDisplayActivateEvents = true;
6571 }
6572
6573 if (aType == nsGkAtoms::onunload && mWindowGlobalChild) {
6574 if (++mUnloadOrBeforeUnloadListenerCount == 1) {
6575 mWindowGlobalChild->BlockBFCacheFor(BFCacheStatus::UNLOAD_LISTENER);
6576 }
6577 }
6578
6579 if (aType == nsGkAtoms::onbeforeunload && mWindowGlobalChild) {
6580 if (!mozilla::SessionHistoryInParent() ||
6581 !StaticPrefs::
6582 docshell_shistory_bfcache_ship_allow_beforeunload_listeners()) {
6583 if (++mUnloadOrBeforeUnloadListenerCount == 1) {
6584 mWindowGlobalChild->BlockBFCacheFor(
6585 BFCacheStatus::BEFOREUNLOAD_LISTENER);
6586 }
6587 }
6588 if (!mDoc || !(mDoc->GetSandboxFlags() & SANDBOXED_MODALS)) {
6589 mWindowGlobalChild->BeforeUnloadAdded();
6590 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"
, 6590); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mWindowGlobalChild->BeforeUnloadListeners() > 0"
")"); do { *((volatile int*)__null) = 6590; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6591 }
6592 }
6593
6594 // We need to initialize localStorage in order to receive notifications.
6595 if (aType == nsGkAtoms::onstorage) {
6596 ErrorResult rv;
6597 GetLocalStorage(rv);
6598 rv.SuppressException();
6599
6600 if (NextGenLocalStorageEnabled() && mLocalStorage &&
6601 mLocalStorage->Type() == Storage::eLocalStorage) {
6602 auto object = static_cast<LSObject*>(mLocalStorage.get());
6603
6604 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"
, 6604)
;
6605 }
6606 }
6607}
6608
6609void nsGlobalWindowInner::EventListenerRemoved(nsAtom* aType) {
6610 if (aType == nsGkAtoms::onunload && mWindowGlobalChild) {
6611 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"
, 6611); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mUnloadOrBeforeUnloadListenerCount > 0"
")"); do { *((volatile int*)__null) = 6611; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6612 if (--mUnloadOrBeforeUnloadListenerCount == 0) {
6613 mWindowGlobalChild->UnblockBFCacheFor(BFCacheStatus::UNLOAD_LISTENER);
6614 }
6615 }
6616
6617 if (aType == nsGkAtoms::onbeforeunload && mWindowGlobalChild) {
6618 if (!mozilla::SessionHistoryInParent() ||
6619 !StaticPrefs::
6620 docshell_shistory_bfcache_ship_allow_beforeunload_listeners()) {
6621 if (--mUnloadOrBeforeUnloadListenerCount == 0) {
6622 mWindowGlobalChild->UnblockBFCacheFor(
6623 BFCacheStatus::BEFOREUNLOAD_LISTENER);
6624 }
6625 }
6626 if (!mDoc || !(mDoc->GetSandboxFlags() & SANDBOXED_MODALS)) {
6627 mWindowGlobalChild->BeforeUnloadRemoved();
6628 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"
, 6628); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mWindowGlobalChild->BeforeUnloadListeners() >= 0"
")"); do { *((volatile int*)__null) = 6628; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6629 }
6630 }
6631
6632 if (aType == nsGkAtoms::onstorage) {
6633 if (NextGenLocalStorageEnabled() && mLocalStorage &&
6634 mLocalStorage->Type() == Storage::eLocalStorage &&
6635 // The remove event is fired even if this isn't the last listener, so
6636 // only remove if there are no other listeners left.
6637 mListenerManager &&
6638 !mListenerManager->HasListenersFor(nsGkAtoms::onstorage)) {
6639 auto object = static_cast<LSObject*>(mLocalStorage.get());
6640
6641 object->DropObserver();
6642 }
6643 }
6644}
6645
6646void nsGlobalWindowInner::NotifyHasXRSession() {
6647 if (IsDying()) {
6648 // Do not proceed if the window is dying, as that will result
6649 // in leaks of objects that get re-allocated after FreeInnerObjects
6650 // has been called, including mVREventObserver.
6651 return;
6652 }
6653 if (mWindowGlobalChild && !mHasXRSession) {
6654 mWindowGlobalChild->BlockBFCacheFor(BFCacheStatus::HAS_USED_VR);
6655 }
6656 mHasXRSession = true;
6657 EnableVRUpdates();
6658}
6659
6660bool nsGlobalWindowInner::HasUsedVR() const {
6661 // Returns true only if content has enumerated and activated
6662 // XR devices. Detection of XR runtimes without activation
6663 // will not cause true to be returned.
6664 return mHasXRSession;
6665}
6666
6667bool nsGlobalWindowInner::IsVRContentDetected() const {
6668 // Returns true only if the content will respond to
6669 // the VRDisplayActivate event.
6670 return mHasVRDisplayActivateEvents;
6671}
6672
6673bool nsGlobalWindowInner::IsVRContentPresenting() const {
6674 for (const auto& display : mVRDisplays) {
6675 if (display->IsAnyPresenting(gfx::kVRGroupAll)) {
6676 return true;
6677 }
6678 }
6679 return false;
6680}
6681
6682void nsGlobalWindowInner::AddSizeOfIncludingThis(
6683 nsWindowSizes& aWindowSizes) const {
6684 aWindowSizes.mDOMSizes.mDOMOtherSize +=
6685 aWindowSizes.mState.mMallocSizeOf(this);
6686 aWindowSizes.mDOMSizes.mDOMOtherSize +=
6687 nsIGlobalObject::ShallowSizeOfExcludingThis(
6688 aWindowSizes.mState.mMallocSizeOf);
6689
6690 EventListenerManager* elm = GetExistingListenerManager();
6691 if (elm) {
6692 aWindowSizes.mDOMSizes.mDOMOtherSize +=
6693 elm->SizeOfIncludingThis(aWindowSizes.mState.mMallocSizeOf);
6694 aWindowSizes.mDOMEventListenersCount += elm->ListenerCount();
6695 }
6696 if (mDoc) {
6697 // Multiple global windows can share a document. So only measure the
6698 // document if it (a) doesn't have a global window, or (b) it's the
6699 // primary document for the window.
6700 if (!mDoc->GetInnerWindow() || mDoc->GetInnerWindow() == this) {
6701 mDoc->DocAddSizeOfIncludingThis(aWindowSizes);
6702 }
6703 }
6704
6705 if (mNavigator) {
6706 aWindowSizes.mDOMSizes.mDOMOtherSize +=
6707 mNavigator->SizeOfIncludingThis(aWindowSizes.mState.mMallocSizeOf);
6708 }
6709
6710 ForEachGlobalTeardownObserver([&](GlobalTeardownObserver* et,
6711 bool* aDoneOut) {
6712 if (nsCOMPtr<nsISizeOfEventTarget> iSizeOf = do_QueryObject(et)) {
6713 aWindowSizes.mDOMSizes.mDOMEventTargetsSize +=
6714 iSizeOf->SizeOfEventTargetIncludingThis(
6715 aWindowSizes.mState.mMallocSizeOf);
6716 }
6717 if (nsCOMPtr<DOMEventTargetHelper> helper = do_QueryObject(et)) {
6718 if (EventListenerManager* elm = helper->GetExistingListenerManager()) {
6719 aWindowSizes.mDOMEventListenersCount += elm->ListenerCount();
6720 }
6721 }
6722 ++aWindowSizes.mDOMEventTargetsCount;
6723 });
6724
6725 if (mPerformance) {
6726 aWindowSizes.mDOMSizes.mDOMPerformanceUserEntries =
6727 mPerformance->SizeOfUserEntries(aWindowSizes.mState.mMallocSizeOf);
6728 aWindowSizes.mDOMSizes.mDOMPerformanceResourceEntries =
6729 mPerformance->SizeOfResourceEntries(aWindowSizes.mState.mMallocSizeOf);
6730 aWindowSizes.mDOMSizes.mDOMPerformanceEventEntries =
6731 mPerformance->SizeOfEventEntries(aWindowSizes.mState.mMallocSizeOf);
6732 }
6733}
6734
6735void nsGlobalWindowInner::RegisterDataDocumentForMemoryReporting(
6736 Document* aDocument) {
6737 aDocument->SetAddedToMemoryReportAsDataDocument();
6738 mDataDocumentsForMemoryReporting.AppendElement(aDocument);
6739}
6740
6741void nsGlobalWindowInner::UnregisterDataDocumentForMemoryReporting(
6742 Document* aDocument) {
6743 DebugOnly<bool> found =
6744 mDataDocumentsForMemoryReporting.RemoveElement(aDocument);
6745 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"
, 6745); AnnotateMozCrashReason("MOZ_ASSERT" "(" "found" ")")
; do { *((volatile int*)__null) = 6745; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6746}
6747
6748void nsGlobalWindowInner::CollectDOMSizesForDataDocuments(
6749 nsWindowSizes& aSize) const {
6750 for (Document* doc : mDataDocumentsForMemoryReporting) {
6751 if (doc) {
6752 doc->DocAddSizeOfIncludingThis(aSize);
6753 }
6754 }
6755}
6756
6757void nsGlobalWindowInner::AddGamepad(GamepadHandle aHandle, Gamepad* aGamepad) {
6758 // Create the index we will present to content based on which indices are
6759 // already taken, as required by the spec.
6760 // https://w3c.github.io/gamepad/gamepad.html#widl-Gamepad-index
6761 int index = 0;
6762 while (mGamepadIndexSet.Contains(index)) {
6763 ++index;
6764 }
6765 mGamepadIndexSet.Put(index);
6766 aGamepad->SetIndex(index);
6767 mGamepads.InsertOrUpdate(aHandle, RefPtr{aGamepad});
6768}
6769
6770void nsGlobalWindowInner::RemoveGamepad(GamepadHandle aHandle) {
6771 RefPtr<Gamepad> gamepad;
6772 if (!mGamepads.Get(aHandle, getter_AddRefs(gamepad))) {
6773 return;
6774 }
6775 // Free up the index we were using so it can be reused
6776 mGamepadIndexSet.Remove(gamepad->Index());
6777 mGamepads.Remove(aHandle);
6778}
6779
6780void nsGlobalWindowInner::GetGamepads(nsTArray<RefPtr<Gamepad>>& aGamepads) {
6781 aGamepads.Clear();
6782
6783 // navigator.getGamepads() always returns an empty array when
6784 // privacy.resistFingerprinting is true.
6785 if (ShouldResistFingerprinting(RFPTarget::Gamepad)) {
6786 return;
6787 }
6788
6789 // mGamepads.Count() may not be sufficient, but it's not harmful.
6790 aGamepads.SetCapacity(mGamepads.Count());
6791 for (const auto& entry : mGamepads) {
6792 Gamepad* gamepad = entry.GetWeak();
6793 aGamepads.EnsureLengthAtLeast(gamepad->Index() + 1);
6794 aGamepads[gamepad->Index()] = gamepad;
6795 }
6796}
6797
6798already_AddRefed<mozilla::dom::Promise> nsGlobalWindowInner::RequestAllGamepads(
6799 ErrorResult& aRv) {
6800 RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService());
6801
6802 if (!gamepadManager) {
6803 aRv.Throw(NS_ERROR_UNEXPECTED);
6804 return nullptr;
6805 }
6806
6807 return gamepadManager->RequestAllGamepads(this, aRv);
6808}
6809
6810already_AddRefed<Gamepad> nsGlobalWindowInner::GetGamepad(
6811 GamepadHandle aHandle) {
6812 RefPtr<Gamepad> gamepad;
6813
6814 if (mGamepads.Get(aHandle, getter_AddRefs(gamepad))) {
6815 return gamepad.forget();
6816 }
6817
6818 return nullptr;
6819}
6820
6821void nsGlobalWindowInner::SetHasSeenGamepadInput(bool aHasSeen) {
6822 mHasSeenGamepadInput = aHasSeen;
6823}
6824
6825bool nsGlobalWindowInner::HasSeenGamepadInput() { return mHasSeenGamepadInput; }
6826
6827void nsGlobalWindowInner::SyncGamepadState() {
6828 if (mHasSeenGamepadInput) {
6829 RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService());
6830 for (const auto& entry : mGamepads) {
6831 gamepadManager->SyncGamepadState(entry.GetKey(), this, entry.GetWeak());
6832 }
6833 }
6834}
6835
6836void nsGlobalWindowInner::StopGamepadHaptics() {
6837 if (mHasSeenGamepadInput) {
6838 RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService());
6839 gamepadManager->StopHaptics();
6840 }
6841}
6842
6843bool nsGlobalWindowInner::UpdateVRDisplays(
6844 nsTArray<RefPtr<mozilla::dom::VRDisplay>>& aDevices) {
6845 VRDisplay::UpdateVRDisplays(mVRDisplays, this);
6846 aDevices = mVRDisplays.Clone();
6847 return true;
6848}
6849
6850void nsGlobalWindowInner::NotifyActiveVRDisplaysChanged() {
6851 if (mNavigator) {
6852 mNavigator->NotifyActiveVRDisplaysChanged();
6853 }
6854}
6855
6856void nsGlobalWindowInner::NotifyPresentationGenerationChanged(
6857 uint32_t aDisplayID) {
6858 for (const auto& display : mVRDisplays) {
6859 if (display->DisplayId() == aDisplayID) {
6860 display->OnPresentationGenerationChanged();
6861 }
6862 }
6863}
6864
6865void nsGlobalWindowInner::DispatchVRDisplayActivate(
6866 uint32_t aDisplayID, mozilla::dom::VRDisplayEventReason aReason) {
6867 // Ensure that our list of displays is up to date
6868 VRDisplay::UpdateVRDisplays(mVRDisplays, this);
6869
6870 // Search for the display identified with aDisplayID and fire the
6871 // event if found.
6872 for (const auto& display : mVRDisplays) {
6873 if (display->DisplayId() == aDisplayID) {
6874 if (aReason != VRDisplayEventReason::Navigation &&
6875 display->IsAnyPresenting(gfx::kVRGroupContent)) {
6876 // We only want to trigger this event if nobody is presenting to the
6877 // display already or when a page is loaded by navigating away
6878 // from a page with an active VR Presentation.
6879 continue;
6880 }
6881
6882 VRDisplayEventInit init;
6883 init.mBubbles = false;
6884 init.mCancelable = false;
6885 init.mDisplay = display;
6886 init.mReason.Construct(aReason);
6887
6888 RefPtr<VRDisplayEvent> event =
6889 VRDisplayEvent::Constructor(this, u"vrdisplayactivate"_ns, init);
6890 // vrdisplayactivate is a trusted event, allowing VRDisplay.requestPresent
6891 // to be used in response to link traversal, user request (chrome UX), and
6892 // HMD mounting detection sensors.
6893 event->SetTrusted(true);
6894 // VRDisplay.requestPresent normally requires a user gesture; however, an
6895 // exception is made to allow it to be called in response to
6896 // vrdisplayactivate during VR link traversal.
6897 display->StartHandlingVRNavigationEvent();
6898 DispatchEvent(*event);
6899 display->StopHandlingVRNavigationEvent();
6900 // Once we dispatch the event, we must not access any members as an event
6901 // listener can do anything, including closing windows.
6902 return;
6903 }
6904 }
6905}
6906
6907void nsGlobalWindowInner::DispatchVRDisplayDeactivate(
6908 uint32_t aDisplayID, mozilla::dom::VRDisplayEventReason aReason) {
6909 // Ensure that our list of displays is up to date
6910 VRDisplay::UpdateVRDisplays(mVRDisplays, this);
6911
6912 // Search for the display identified with aDisplayID and fire the
6913 // event if found.
6914 for (const auto& display : mVRDisplays) {
6915 if (display->DisplayId() == aDisplayID && display->IsPresenting()) {
6916 // We only want to trigger this event to content that is presenting to
6917 // the display already.
6918
6919 VRDisplayEventInit init;
6920 init.mBubbles = false;
6921 init.mCancelable = false;
6922 init.mDisplay = display;
6923 init.mReason.Construct(aReason);
6924
6925 RefPtr<VRDisplayEvent> event =
6926 VRDisplayEvent::Constructor(this, u"vrdisplaydeactivate"_ns, init);
6927 event->SetTrusted(true);
6928 DispatchEvent(*event);
6929 // Once we dispatch the event, we must not access any members as an event
6930 // listener can do anything, including closing windows.
6931 return;
6932 }
6933 }
6934}
6935
6936void nsGlobalWindowInner::DispatchVRDisplayConnect(uint32_t aDisplayID) {
6937 // Ensure that our list of displays is up to date
6938 VRDisplay::UpdateVRDisplays(mVRDisplays, this);
6939
6940 // Search for the display identified with aDisplayID and fire the
6941 // event if found.
6942 for (const auto& display : mVRDisplays) {
6943 if (display->DisplayId() == aDisplayID) {
6944 // Fire event even if not presenting to the display.
6945 VRDisplayEventInit init;
6946 init.mBubbles = false;
6947 init.mCancelable = false;
6948 init.mDisplay = display;
6949 // VRDisplayEvent.reason is not set for vrdisplayconnect
6950
6951 RefPtr<VRDisplayEvent> event =
6952 VRDisplayEvent::Constructor(this, u"vrdisplayconnect"_ns, init);
6953 event->SetTrusted(true);
6954 DispatchEvent(*event);
6955 // Once we dispatch the event, we must not access any members as an event
6956 // listener can do anything, including closing windows.
6957 return;
6958 }
6959 }
6960}
6961
6962void nsGlobalWindowInner::DispatchVRDisplayDisconnect(uint32_t aDisplayID) {
6963 // Ensure that our list of displays is up to date
6964 VRDisplay::UpdateVRDisplays(mVRDisplays, this);
6965
6966 // Search for the display identified with aDisplayID and fire the
6967 // event if found.
6968 for (const auto& display : mVRDisplays) {
6969 if (display->DisplayId() == aDisplayID) {
6970 // Fire event even if not presenting to the display.
6971 VRDisplayEventInit init;
6972 init.mBubbles = false;
6973 init.mCancelable = false;
6974 init.mDisplay = display;
6975 // VRDisplayEvent.reason is not set for vrdisplaydisconnect
6976
6977 RefPtr<VRDisplayEvent> event =
6978 VRDisplayEvent::Constructor(this, u"vrdisplaydisconnect"_ns, init);
6979 event->SetTrusted(true);
6980 DispatchEvent(*event);
6981 // Once we dispatch the event, we must not access any members as an event
6982 // listener can do anything, including closing windows.
6983 return;
6984 }
6985 }
6986}
6987
6988void nsGlobalWindowInner::DispatchVRDisplayPresentChange(uint32_t aDisplayID) {
6989 // Ensure that our list of displays is up to date
6990 VRDisplay::UpdateVRDisplays(mVRDisplays, this);
6991
6992 // Search for the display identified with aDisplayID and fire the
6993 // event if found.
6994 for (const auto& display : mVRDisplays) {
6995 if (display->DisplayId() == aDisplayID) {
6996 // Fire event even if not presenting to the display.
6997 VRDisplayEventInit init;
6998 init.mBubbles = false;
6999 init.mCancelable = false;
7000 init.mDisplay = display;
7001 // VRDisplayEvent.reason is not set for vrdisplaypresentchange
7002 RefPtr<VRDisplayEvent> event =
7003 VRDisplayEvent::Constructor(this, u"vrdisplaypresentchange"_ns, init);
7004 event->SetTrusted(true);
7005 DispatchEvent(*event);
7006 // Once we dispatch the event, we must not access any members as an event
7007 // listener can do anything, including closing windows.
7008 return;
7009 }
7010 }
7011}
7012
7013enum WindowState {
7014 // These constants need to match the constants in Window.webidl
7015 STATE_MAXIMIZED = 1,
7016 STATE_MINIMIZED = 2,
7017 STATE_NORMAL = 3,
7018 STATE_FULLSCREEN = 4
7019};
7020
7021uint16_t nsGlobalWindowInner::WindowState() {
7022 nsCOMPtr<nsIWidget> widget = GetMainWidget();
7023
7024 int32_t mode = widget ? widget->SizeMode() : 0;
7025
7026 switch (mode) {
7027 case nsSizeMode_Minimized:
7028 return STATE_MINIMIZED;
7029 case nsSizeMode_Maximized:
7030 return STATE_MAXIMIZED;
7031 case nsSizeMode_Fullscreen:
7032 return STATE_FULLSCREEN;
7033 case nsSizeMode_Normal:
7034 return STATE_NORMAL;
7035 default:
7036 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"
, 7036)
;
7037 break;
7038 }
7039
7040 return STATE_NORMAL;
7041}
7042
7043bool nsGlobalWindowInner::IsFullyOccluded() {
7044 nsCOMPtr<nsIWidget> widget = GetMainWidget();
7045 return widget && widget->IsFullyOccluded();
7046}
7047
7048void nsGlobalWindowInner::Maximize() {
7049 if (nsCOMPtr<nsIWidget> widget = GetMainWidget()) {
7050 widget->SetSizeMode(nsSizeMode_Maximized);
7051 }
7052}
7053
7054void nsGlobalWindowInner::Minimize() {
7055 if (nsCOMPtr<nsIWidget> widget = GetMainWidget()) {
7056 widget->SetSizeMode(nsSizeMode_Minimized);
7057 }
7058}
7059
7060void nsGlobalWindowInner::Restore() {
7061 if (nsCOMPtr<nsIWidget> widget = GetMainWidget()) {
7062 widget->SetSizeMode(nsSizeMode_Normal);
7063 }
7064}
7065
7066void nsGlobalWindowInner::GetWorkspaceID(nsAString& workspaceID) {
7067 workspaceID.Truncate();
7068 if (nsCOMPtr<nsIWidget> widget = GetMainWidget()) {
7069 return widget->GetWorkspaceID(workspaceID);
7070 }
7071}
7072
7073void nsGlobalWindowInner::MoveToWorkspace(const nsAString& workspaceID) {
7074 if (nsCOMPtr<nsIWidget> widget = GetMainWidget()) {
7075 widget->MoveToWorkspace(workspaceID);
7076 }
7077}
7078
7079void nsGlobalWindowInner::GetAttention(ErrorResult& aResult) {
7080 return GetAttentionWithCycleCount(-1, aResult);
7081}
7082
7083void nsGlobalWindowInner::GetAttentionWithCycleCount(int32_t aCycleCount,
7084 ErrorResult& aError) {
7085 nsCOMPtr<nsIWidget> widget = GetMainWidget();
7086
7087 if (widget) {
7088 aError = widget->GetAttention(aCycleCount);
7089 }
7090}
7091
7092already_AddRefed<Promise> nsGlobalWindowInner::PromiseDocumentFlushed(
7093 PromiseDocumentFlushedCallback& aCallback, ErrorResult& aError) {
7094 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"
, 7094); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "IsChromeWindow()"
")"); do { *((volatile int*)__null) = 7094; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7095
7096 if (!IsCurrentInnerWindow()) {
7097 aError.ThrowInvalidStateError("Not the current inner window");
7098 return nullptr;
7099 }
7100 if (!mDoc) {
7101 aError.ThrowInvalidStateError("No document");
7102 return nullptr;
7103 }
7104
7105 if (mIteratingDocumentFlushedResolvers) {
7106 aError.ThrowInvalidStateError("Already iterating through resolvers");
7107 return nullptr;
7108 }
7109
7110 PresShell* presShell = mDoc->GetPresShell();
7111 if (!presShell) {
7112 aError.ThrowInvalidStateError("No pres shell");
7113 return nullptr;
7114 }
7115
7116 // We need to associate the lifetime of the Promise to the lifetime
7117 // of the caller's global. That way, if the window we're observing
7118 // refresh driver ticks on goes away before our observer is fired,
7119 // we can still resolve the Promise.
7120 nsIGlobalObject* global = GetIncumbentGlobal();
7121 if (!global) {
7122 aError.ThrowInvalidStateError("No incumbent global");
7123 return nullptr;
7124 }
7125
7126 RefPtr<Promise> resultPromise = Promise::Create(global, aError);
7127 if (aError.Failed()) {
7128 return nullptr;
7129 }
7130
7131 UniquePtr<PromiseDocumentFlushedResolver> flushResolver(
7132 new PromiseDocumentFlushedResolver(resultPromise, aCallback));
7133
7134 if (!presShell->NeedStyleFlush() && !presShell->NeedLayoutFlush()) {
7135 flushResolver->Call();
7136 return resultPromise.forget();
7137 }
7138
7139 if (!TryToObserveRefresh()) {
7140 aError.ThrowInvalidStateError("Couldn't observe refresh");
7141 return nullptr;
7142 }
7143
7144 mDocumentFlushedResolvers.AppendElement(std::move(flushResolver));
7145 return resultPromise.forget();
7146}
7147
7148bool nsGlobalWindowInner::TryToObserveRefresh() {
7149 if (mObservingRefresh) {
7150 return true;
7151 }
7152
7153 if (!mDoc) {
7154 return false;
7155 }
7156
7157 nsPresContext* pc = mDoc->GetPresContext();
7158 if (!pc) {
7159 return false;
7160 }
7161
7162 mObservingRefresh = true;
7163 auto observer = MakeRefPtr<ManagedPostRefreshObserver>(
7164 pc, [win = RefPtr{this}](bool aWasCanceled) {
7165 if (win->MaybeCallDocumentFlushedResolvers(
7166 /* aUntilExhaustion = */ aWasCanceled)) {
7167 return ManagedPostRefreshObserver::Unregister::No;
7168 }
7169 win->mObservingRefresh = false;
7170 return ManagedPostRefreshObserver::Unregister::Yes;
7171 });
7172 pc->RegisterManagedPostRefreshObserver(observer.get());
7173 return mObservingRefresh;
7174}
7175
7176void nsGlobalWindowInner::CallDocumentFlushedResolvers(bool aUntilExhaustion) {
7177 while (true) {
7178 {
7179 // To coalesce MicroTask checkpoints inside callback call, enclose the
7180 // inner loop with nsAutoMicroTask, and perform a MicroTask checkpoint
7181 // after the loop.
7182 nsAutoMicroTask mt;
7183
7184 mIteratingDocumentFlushedResolvers = true;
7185
7186 auto resolvers = std::move(mDocumentFlushedResolvers);
7187 for (const auto& resolver : resolvers) {
7188 resolver->Call();
7189 }
7190
7191 mIteratingDocumentFlushedResolvers = false;
7192 }
7193
7194 // Leaving nsAutoMicroTask above will perform MicroTask checkpoint, and
7195 // Promise callbacks there may create mDocumentFlushedResolvers items.
7196
7197 // If there's no new resolvers, or we're not exhausting the queue, there's
7198 // nothing to do (we'll keep observing if there's any new observer).
7199 //
7200 // Otherwise, keep looping to call all promises. This case can happen while
7201 // destroying the window. This violates the constraint that the
7202 // promiseDocumentFlushed callback only ever run when no flush is needed,
7203 // but it's necessary to resolve the Promise returned by that.
7204 if (!aUntilExhaustion || mDocumentFlushedResolvers.IsEmpty()) {
7205 break;
7206 }
7207 }
7208}
7209
7210bool nsGlobalWindowInner::MaybeCallDocumentFlushedResolvers(
7211 bool aUntilExhaustion) {
7212 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"
, 7212); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDoc" ")");
do { *((volatile int*)__null) = 7212; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7213
7214 PresShell* presShell = mDoc->GetPresShell();
7215 if (!presShell || aUntilExhaustion) {
7216 CallDocumentFlushedResolvers(/* aUntilExhaustion = */ true);
7217 return false;
7218 }
7219
7220 if (presShell->NeedStyleFlush() || presShell->NeedLayoutFlush()) {
7221 // By the time our observer fired, something has already invalidated
7222 // style or layout - or perhaps we're still in the middle of a flush that
7223 // was interrupted. In either case, we'll wait until the next refresh driver
7224 // tick instead and try again.
7225 return true;
7226 }
7227
7228 CallDocumentFlushedResolvers(/* aUntilExhaustion = */ false);
7229 return !mDocumentFlushedResolvers.IsEmpty();
7230}
7231
7232already_AddRefed<nsWindowRoot> nsGlobalWindowInner::GetWindowRoot(
7233 mozilla::ErrorResult& aError) {
7234 FORWARD_TO_OUTER_OR_THROW(GetWindowRootOuter, (), aError, nullptr);
7235}
7236
7237void nsGlobalWindowInner::SetCursor(const nsACString& aCursor,
7238 ErrorResult& aError) {
7239 FORWARD_TO_OUTER_OR_THROW(SetCursorOuter, (aCursor, aError), aError, );
7240}
7241
7242nsIBrowserDOMWindow* nsGlobalWindowInner::GetBrowserDOMWindow(
7243 ErrorResult& aError) {
7244 FORWARD_TO_OUTER_OR_THROW(GetBrowserDOMWindow, (), aError, nullptr);
7245}
7246
7247void nsGlobalWindowInner::SetBrowserDOMWindow(
7248 nsIBrowserDOMWindow* aBrowserWindow, ErrorResult& aError) {
7249 FORWARD_TO_OUTER_OR_THROW(SetBrowserDOMWindowOuter, (aBrowserWindow),
7250 aError, );
7251}
7252
7253void nsGlobalWindowInner::NotifyDefaultButtonLoaded(Element& aDefaultButton,
7254 ErrorResult& aError) {
7255 // Don't snap to a disabled button.
7256 nsCOMPtr<nsIDOMXULControlElement> xulControl = aDefaultButton.AsXULControl();
7257 if (!xulControl) {
7258 aError.Throw(NS_ERROR_FAILURE);
7259 return;
7260 }
7261 bool disabled;
7262 aError = xulControl->GetDisabled(&disabled);
7263 if (aError.Failed() || disabled) {
7264 return;
7265 }
7266
7267 // Get the button rect in screen coordinates.
7268 nsIFrame* frame = aDefaultButton.GetPrimaryFrame();
7269 if (!frame) {
7270 aError.Throw(NS_ERROR_FAILURE);
7271 return;
7272 }
7273 LayoutDeviceIntRect buttonRect = LayoutDeviceIntRect::FromAppUnitsToNearest(
7274 frame->GetScreenRectInAppUnits(),
7275 frame->PresContext()->AppUnitsPerDevPixel());
7276
7277 // Get the widget rect in screen coordinates.
7278 nsIWidget* widget = GetNearestWidget();
7279 if (!widget) {
7280 aError.Throw(NS_ERROR_FAILURE);
7281 return;
7282 }
7283 LayoutDeviceIntRect widgetRect = widget->GetScreenBounds();
7284
7285 // Convert the buttonRect coordinates from screen to the widget.
7286 buttonRect -= widgetRect.TopLeft();
7287 nsresult rv = widget->OnDefaultButtonLoaded(buttonRect);
7288 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && rv != NS_ERROR_NOT_IMPLEMENTED) {
7289 aError.Throw(rv);
7290 }
7291}
7292
7293ChromeMessageBroadcaster* nsGlobalWindowInner::MessageManager() {
7294 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"
, 7294); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsChromeWindow()"
")"); do { *((volatile int*)__null) = 7294; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7295 if (!mChromeFields.mMessageManager) {
7296 RefPtr<ChromeMessageBroadcaster> globalMM =
7297 nsFrameMessageManager::GetGlobalMessageManager();
7298 mChromeFields.mMessageManager = new ChromeMessageBroadcaster(globalMM);
7299 }
7300 return mChromeFields.mMessageManager;
7301}
7302
7303ChromeMessageBroadcaster* nsGlobalWindowInner::GetGroupMessageManager(
7304 const nsAString& aGroup) {
7305 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"
, 7305); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsChromeWindow()"
")"); do { *((volatile int*)__null) = 7305; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7306
7307 return mChromeFields.mGroupMessageManagers
7308 .LookupOrInsertWith(
7309 aGroup,
7310 [&] {
7311 return MakeAndAddRef<ChromeMessageBroadcaster>(MessageManager());
7312 })
7313 .get();
7314}
7315
7316void nsGlobalWindowInner::InitWasOffline() { mWasOffline = NS_IsOffline(); }
7317
7318int16_t nsGlobalWindowInner::Orientation(CallerType aCallerType) {
7319 // GetOrientationAngle() returns 0, 90, 180 or 270.
7320 // window.orientation returns -90, 0, 90 or 180.
7321 if (nsIGlobalObject::ShouldResistFingerprinting(
7322 aCallerType, RFPTarget::ScreenOrientation)) {
7323 return 0;
7324 }
7325 int16_t angle = AssertedCast<int16_t>(Screen()->GetOrientationAngle());
7326 return angle <= 180 ? angle : angle - 360;
7327}
7328
7329already_AddRefed<Console> nsGlobalWindowInner::GetConsole(JSContext* aCx,
7330 ErrorResult& aRv) {
7331 if (!mConsole) {
7332 mConsole = Console::Create(aCx, this, aRv);
7333 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"
, 7333)
) {
7334 return nullptr;
7335 }
7336 }
7337
7338 RefPtr<Console> console = mConsole;
7339 return console.forget();
7340}
7341
7342bool nsGlobalWindowInner::IsSecureContext() const {
7343 JS::Realm* realm = js::GetNonCCWObjectRealm(GetWrapperPreserveColor());
7344 return JS::GetIsSecureContext(realm);
7345}
7346
7347External* nsGlobalWindowInner::External() {
7348 if (!mExternal) {
7349 mExternal = new dom::External(ToSupports(this));
7350 }
7351
7352 return mExternal;
7353}
7354
7355void nsGlobalWindowInner::ClearDocumentDependentSlots(JSContext* aCx) {
7356 // If JSAPI OOMs here, there is basically nothing we can do to recover safely.
7357 if (!Window_Binding::ClearCachedDocumentValue(aCx, this) ||
7358 !Window_Binding::ClearCachedPerformanceValue(aCx, this)) {
7359 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"
, 7359); AnnotateMozCrashReason("MOZ_CRASH(" "Unhandlable OOM while clearing document dependent slots."
")"); do { *((volatile int*)__null) = 7359; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
7360 }
7361}
7362
7363/* static */
7364JSObject* nsGlobalWindowInner::CreateNamedPropertiesObject(
7365 JSContext* aCx, JS::Handle<JSObject*> aProto) {
7366 return WindowNamedPropertiesHandler::Create(aCx, aProto);
7367}
7368
7369void nsGlobalWindowInner::RedefineProperty(JSContext* aCx,
7370 const char* aPropName,
7371 JS::Handle<JS::Value> aValue,
7372 ErrorResult& aError) {
7373 JS::Rooted<JSObject*> thisObj(aCx, GetWrapperPreserveColor());
7374 if (!thisObj) {
7375 aError.Throw(NS_ERROR_UNEXPECTED);
7376 return;
7377 }
7378
7379 if (!JS_WrapObject(aCx, &thisObj) ||
7380 !JS_DefineProperty(aCx, thisObj, aPropName, aValue, JSPROP_ENUMERATE)) {
7381 aError.Throw(NS_ERROR_FAILURE);
7382 }
7383}
7384
7385void nsGlobalWindowInner::FireOnNewGlobalObject() {
7386 // AutoEntryScript required to invoke debugger hook, which is a
7387 // Gecko-specific concept at present.
7388 AutoEntryScript aes(this, "nsGlobalWindowInner report new global");
7389 JS::Rooted<JSObject*> global(aes.cx(), GetWrapper());
7390 JS_FireOnNewGlobalObject(aes.cx(), global);
7391}
7392
7393#if defined(_WINDOWS_) && !defined(MOZ_WRAPPED_WINDOWS_H)
7394# pragma message( \
7395 "wrapper failure reason: " MOZ_WINDOWS_WRAPPER_DISABLED_REASON)
7396# error "Never include unwrapped windows.h in this file!"
7397#endif
7398
7399already_AddRefed<Promise> nsGlobalWindowInner::CreateImageBitmap(
7400 const ImageBitmapSource& aImage, const ImageBitmapOptions& aOptions,
7401 ErrorResult& aRv) {
7402 return ImageBitmap::Create(this, aImage, Nothing(), aOptions, aRv);
7403}
7404
7405already_AddRefed<Promise> nsGlobalWindowInner::CreateImageBitmap(
7406 const ImageBitmapSource& aImage, int32_t aSx, int32_t aSy, int32_t aSw,
7407 int32_t aSh, const ImageBitmapOptions& aOptions, ErrorResult& aRv) {
7408 return ImageBitmap::Create(
7409 this, aImage, Some(gfx::IntRect(aSx, aSy, aSw, aSh)), aOptions, aRv);
7410}
7411
7412// https://html.spec.whatwg.org/#structured-cloning
7413void nsGlobalWindowInner::StructuredClone(
7414 JSContext* aCx, JS::Handle<JS::Value> aValue,
7415 const StructuredSerializeOptions& aOptions,
7416 JS::MutableHandle<JS::Value> aRetval, ErrorResult& aError) {
7417 nsContentUtils::StructuredClone(aCx, this, aValue, aOptions, aRetval, aError);
7418}
7419
7420nsresult nsGlobalWindowInner::Dispatch(
7421 already_AddRefed<nsIRunnable>&& aRunnable) const {
7422 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"
, 7422); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 7422; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7423 return NS_DispatchToCurrentThread(std::move(aRunnable));
7424}
7425
7426nsISerialEventTarget* nsGlobalWindowInner::SerialEventTarget() const {
7427 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"
, 7427); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 7427; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7428 return GetMainThreadSerialEventTarget();
7429}
7430
7431Worklet* nsGlobalWindowInner::GetPaintWorklet(ErrorResult& aRv) {
7432 if (!mPaintWorklet) {
7433 nsIPrincipal* principal = GetPrincipal();
7434 if (!principal) {
7435 aRv.Throw(NS_ERROR_FAILURE);
7436 return nullptr;
7437 }
7438
7439 mPaintWorklet = PaintWorkletImpl::CreateWorklet(this, principal);
7440 }
7441
7442 return mPaintWorklet;
7443}
7444
7445void nsGlobalWindowInner::GetRegionalPrefsLocales(
7446 nsTArray<nsString>& aLocales) {
7447 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"
, 7447); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::intl::LocaleService::GetInstance()"
")"); do { *((volatile int*)__null) = 7447; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7448
7449 AutoTArray<nsCString, 10> rpLocales;
7450 mozilla::intl::LocaleService::GetInstance()->GetRegionalPrefsLocales(
7451 rpLocales);
7452
7453 for (const auto& loc : rpLocales) {
7454 aLocales.AppendElement(NS_ConvertUTF8toUTF16(loc));
7455 }
7456}
7457
7458void nsGlobalWindowInner::GetWebExposedLocales(nsTArray<nsString>& aLocales) {
7459 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"
, 7459); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::intl::LocaleService::GetInstance()"
")"); do { *((volatile int*)__null) = 7459; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7460
7461 AutoTArray<nsCString, 10> rpLocales;
7462 mozilla::intl::LocaleService::GetInstance()->GetWebExposedLocales(rpLocales);
7463
7464 for (const auto& loc : rpLocales) {
7465 aLocales.AppendElement(NS_ConvertUTF8toUTF16(loc));
7466 }
7467}
7468
7469IntlUtils* nsGlobalWindowInner::GetIntlUtils(ErrorResult& aError) {
7470 if (!mIntlUtils) {
7471 mIntlUtils = new IntlUtils(this);
7472 }
7473
7474 return mIntlUtils;
7475}
7476
7477void nsGlobalWindowInner::StoreSharedWorker(SharedWorker* aSharedWorker) {
7478 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"
, 7478); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSharedWorker"
")"); do { *((volatile int*)__null) = 7478; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7479 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"
, 7479); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mSharedWorkers.Contains(aSharedWorker)"
")"); do { *((volatile int*)__null) = 7479; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7480
7481 mSharedWorkers.AppendElement(aSharedWorker);
7482}
7483
7484void nsGlobalWindowInner::ForgetSharedWorker(SharedWorker* aSharedWorker) {
7485 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"
, 7485); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSharedWorker"
")"); do { *((volatile int*)__null) = 7485; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7486 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"
, 7486); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mSharedWorkers.Contains(aSharedWorker)"
")"); do { *((volatile int*)__null) = 7486; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7487
7488 mSharedWorkers.RemoveElement(aSharedWorker);
7489}
7490
7491RefPtr<GenericPromise> nsGlobalWindowInner::StorageAccessPermissionChanged(
7492 bool aGranted) {
7493 // Invalidate cached StorageAllowed field so that calls to GetLocalStorage
7494 // give us the updated localStorage object.
7495 ClearStorageAllowedCache();
7496
7497 // If we're always partitioning non-cookie third party storage then
7498 // there is no need to clear it when the user accepts requestStorageAccess.
7499 if (StaticPrefs::
7500 privacy_partition_always_partition_third_party_non_cookie_storage()) {
7501 // Just reset the active cookie and storage principals
7502 nsCOMPtr<nsICookieJarSettings> cjs;
7503 if (mDoc) {
7504 cjs = mDoc->CookieJarSettings();
7505 }
7506 StorageAccess storageAccess = StorageAllowedForWindow(this);
7507 if (ShouldPartitionStorage(storageAccess) &&
7508 StoragePartitioningEnabled(storageAccess, cjs)) {
7509 if (mDoc) {
7510 mDoc->ClearActiveCookieAndStoragePrincipals();
7511 }
7512 // When storage access is granted the content process needs to request the
7513 // updated cookie list from the parent process. Otherwise the site won't
7514 // have access to unpartitioned cookies via document.cookie without a
7515 // reload.
7516 if (aGranted) {
7517 nsIChannel* channel = mDoc->GetChannel();
7518 if (channel) {
7519 // The promise resolves when the updated cookie list has been received
7520 // from the parent.
7521 return ContentChild::UpdateCookieStatus(channel);
7522 }
7523 }
7524 }
7525 }
7526
7527 PropagateStorageAccessPermissionGrantedToWorkers(*this);
7528
7529 // If we have a partitioned localStorage, it's time to replace it with a real
7530 // one in order to receive notifications.
7531
7532 if (mLocalStorage) {
7533 IgnoredErrorResult error;
7534 GetLocalStorage(error);
7535 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"
, 7535)
) {
7536 return MozPromise<bool, nsresult, true>::CreateAndReject(
7537 error.StealNSResult(), __func__);
7538 }
7539
7540 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"
, 7541); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLocalStorage && mLocalStorage->Type() == Storage::eLocalStorage"
")"); do { *((volatile int*)__null) = 7541; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7541 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"
, 7541); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLocalStorage && mLocalStorage->Type() == Storage::eLocalStorage"
")"); do { *((volatile int*)__null) = 7541; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7542
7543 if (NextGenLocalStorageEnabled() && mListenerManager &&
7544 mListenerManager->HasListenersFor(nsGkAtoms::onstorage)) {
7545 auto object = static_cast<LSObject*>(mLocalStorage.get());
7546
7547 object->EnsureObserver();
7548 }
7549 }
7550
7551 // Reset the IndexedDB factory.
7552 mIndexedDB = nullptr;
7553
7554 // Reset DOM Cache
7555 mCacheStorage = nullptr;
7556
7557 // Reset the active cookie and storage principals
7558 if (mDoc) {
7559 mDoc->ClearActiveCookieAndStoragePrincipals();
7560 if (mWindowGlobalChild) {
7561 // XXX(farre): This is a bit backwards, but clearing the cookie
7562 // principal might make us end up with a new effective storage
7563 // principal on the child side than on the parent side, which
7564 // means that we need to sync it. See bug 1705359.
7565 mWindowGlobalChild->SetDocumentPrincipal(
7566 mDoc->NodePrincipal(), mDoc->EffectiveStoragePrincipal());
7567 }
7568 }
7569
7570 // When storage access is granted the content process needs to request the
7571 // updated cookie list from the parent process. Otherwise the site won't have
7572 // access to unpartitioned cookies via document.cookie without a reload.
7573 if (aGranted) {
7574 nsIChannel* channel = mDoc->GetChannel();
7575 if (channel) {
7576 // The promise resolves when the updated cookie list has been received
7577 // from the parent.
7578 return ContentChild::UpdateCookieStatus(channel);
7579 }
7580 }
7581 return MozPromise<bool, nsresult, true>::CreateAndResolve(true, __func__);
7582}
7583
7584ContentMediaController* nsGlobalWindowInner::GetContentMediaController() {
7585 if (mContentMediaController) {
7586 return mContentMediaController;
7587 }
7588 if (!mBrowsingContext) {
7589 return nullptr;
7590 }
7591
7592 mContentMediaController = new ContentMediaController(mBrowsingContext->Id());
7593 return mContentMediaController;
7594}
7595
7596void nsGlobalWindowInner::SetScrollMarks(const nsTArray<uint32_t>& aScrollMarks,
7597 bool aOnHScrollbar) {
7598 mScrollMarks.Assign(aScrollMarks);
7599 mScrollMarksOnHScrollbar = aOnHScrollbar;
7600
7601 // Mark the scrollbar for repainting.
7602 if (mDoc) {
7603 PresShell* presShell = mDoc->GetPresShell();
7604 if (presShell) {
7605 ScrollContainerFrame* sf = presShell->GetRootScrollContainerFrame();
7606 if (sf) {
7607 sf->InvalidateScrollbars();
7608 }
7609 }
7610 }
7611}
7612
7613/* static */
7614already_AddRefed<nsGlobalWindowInner> nsGlobalWindowInner::Create(
7615 nsGlobalWindowOuter* aOuterWindow, bool aIsChrome,
7616 WindowGlobalChild* aActor) {
7617 RefPtr<nsGlobalWindowInner> window =
7618 new nsGlobalWindowInner(aOuterWindow, aActor);
7619 if (aIsChrome) {
7620 window->mIsChrome = true;
7621 window->mCleanMessageManager = true;
7622 }
7623
7624 if (aActor) {
7625 aActor->InitWindowGlobal(window);
7626 }
7627
7628 window->InitWasOffline();
7629 return window.forget();
7630}
7631
7632JS::loader::ModuleLoaderBase* nsGlobalWindowInner::GetModuleLoader(
7633 JSContext* aCx) {
7634 Document* document = GetDocument();
7635 if (!document) {
7636 return nullptr;
7637 }
7638
7639 ScriptLoader* loader = document->ScriptLoader();
7640 if (!loader) {
7641 return nullptr;
7642 }
7643
7644 return loader->GetModuleLoader();
7645}
7646
7647void nsGlobalWindowInner::SetCurrentPasteDataTransfer(
7648 DataTransfer* aDataTransfer) {
7649 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"
, 7649); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDataTransfer->GetEventMessage() == ePaste"
")"); do { *((volatile int*)__null) = 7649; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
7650 MOZ_ASSERT_IF(aDataTransfer, aDataTransfer->ClipboardType() ==do { if (aDataTransfer) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(aDataTransfer->ClipboardType
() == nsIClipboard::kGlobalClipboard)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDataTransfer->ClipboardType
() == nsIClipboard::kGlobalClipboard))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("aDataTransfer->ClipboardType() == nsIClipboard::kGlobalClipboard"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 7651); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDataTransfer->ClipboardType() == nsIClipboard::kGlobalClipboard"
")"); do { *((volatile int*)__null) = 7651; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
7651 nsIClipboard::kGlobalClipboard)do { if (aDataTransfer) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(aDataTransfer->ClipboardType
() == nsIClipboard::kGlobalClipboard)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDataTransfer->ClipboardType
() == nsIClipboard::kGlobalClipboard))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("aDataTransfer->ClipboardType() == nsIClipboard::kGlobalClipboard"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 7651); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDataTransfer->ClipboardType() == nsIClipboard::kGlobalClipboard"
")"); do { *((volatile int*)__null) = 7651; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
7652 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"
, 7652); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDataTransfer->GetClipboardDataSnapshot()"
")"); do { *((volatile int*)__null) = 7652; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
7653 mCurrentPasteDataTransfer = aDataTransfer;
7654}
7655
7656DataTransfer* nsGlobalWindowInner::GetCurrentPasteDataTransfer() const {
7657 return mCurrentPasteDataTransfer;
7658}
7659
7660TrustedTypePolicyFactory* nsGlobalWindowInner::TrustedTypes() {
7661 if (!mTrustedTypePolicyFactory) {
7662 mTrustedTypePolicyFactory = MakeRefPtr<TrustedTypePolicyFactory>(this);
7663 }
7664
7665 return mTrustedTypePolicyFactory;
7666}
7667
7668nsIURI* nsPIDOMWindowInner::GetDocumentURI() const {
7669 return mDoc ? mDoc->GetDocumentURI() : mDocumentURI.get();
7670}
7671
7672nsIURI* nsPIDOMWindowInner::GetDocBaseURI() const {
7673 return mDoc ? mDoc->GetDocBaseURI() : mDocBaseURI.get();
7674}
7675
7676mozilla::dom::WindowContext* nsPIDOMWindowInner::GetWindowContext() const {
7677 return mWindowGlobalChild ? mWindowGlobalChild->WindowContext() : nullptr;
7678}
7679
7680bool nsPIDOMWindowInner::RemoveFromBFCacheSync() {
7681 if (Document* doc = GetExtantDoc()) {
7682 return doc->RemoveFromBFCacheSync();
7683 }
7684 return false;
7685}
7686
7687void nsPIDOMWindowInner::MaybeCreateDoc() {
7688 // XXX: Forward to outer?
7689 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"
, 7689); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mDoc" ")")
; do { *((volatile int*)__null) = 7689; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7690 if (nsIDocShell* docShell = GetDocShell()) {
7691 // Note that |document| here is the same thing as our mDoc, but we
7692 // don't have to explicitly set the member variable because the docshell
7693 // has already called SetNewDocument().
7694 nsCOMPtr<Document> document = docShell->GetDocument();
7695 Unused << document;
7696 }
7697}
7698
7699mozilla::dom::DocGroup* nsPIDOMWindowInner::GetDocGroup() const {
7700 Document* doc = GetExtantDoc();
7701 if (doc) {
7702 return doc->GetDocGroup();
7703 }
7704 return nullptr;
7705}
7706
7707mozilla::dom::BrowsingContextGroup*
7708nsPIDOMWindowInner::GetBrowsingContextGroup() const {
7709 return mBrowsingContext ? mBrowsingContext->Group() : nullptr;
7710}
7711
7712nsIGlobalObject* nsPIDOMWindowInner::AsGlobal() {
7713 return nsGlobalWindowInner::Cast(this);
7714}
7715
7716const nsIGlobalObject* nsPIDOMWindowInner::AsGlobal() const {
7717 return nsGlobalWindowInner::Cast(this);
7718}
7719
7720RefPtr<GenericPromise>
7721nsPIDOMWindowInner::SaveStorageAccessPermissionGranted() {
7722 WindowContext* wc = GetWindowContext();
7723 if (wc) {
7724 Unused << wc->SetUsingStorageAccess(true);
7725 }
7726
7727 return nsGlobalWindowInner::Cast(this)->StorageAccessPermissionChanged(true);
7728}
7729
7730RefPtr<GenericPromise>
7731nsPIDOMWindowInner::SaveStorageAccessPermissionRevoked() {
7732 WindowContext* wc = GetWindowContext();
7733 if (wc) {
7734 Unused << wc->SetUsingStorageAccess(false);
7735 }
7736
7737 return nsGlobalWindowInner::Cast(this)->StorageAccessPermissionChanged(false);
7738}
7739
7740bool nsPIDOMWindowInner::UsingStorageAccess() {
7741 WindowContext* wc = GetWindowContext();
7742 if (!wc) {
7743 return false;
7744 }
7745
7746 return wc->GetUsingStorageAccess();
7747}
7748
7749nsPIDOMWindowInner::nsPIDOMWindowInner(nsPIDOMWindowOuter* aOuterWindow,
7750 WindowGlobalChild* aActor)
7751 : mMutationBits(0),
7752 mIsDocumentLoaded(false),
7753 mIsHandlingResizeEvent(false),
7754 mMayHaveDOMActivateEventListeners(false),
7755 mMayHavePaintEventListener(false),
7756 mMayHaveTouchEventListener(false),
7757 mMayHaveSelectionChangeEventListener(false),
7758 mMayHaveFormSelectEventListener(false),
7759 mMayHaveMouseEnterLeaveEventListener(false),
7760 mMayHavePointerEnterLeaveEventListener(false),
7761 mMayHaveTransitionEventListener(false),
7762 mMayHaveSMILTimeEventListener(false),
7763 mMayHaveBeforeInputEventListenerForTelemetry(false),
7764 mMutationObserverHasObservedNodeForTelemetry(false),
7765 mOuterWindow(aOuterWindow),
7766 mWindowID(0),
7767 mHasNotifiedGlobalCreated(false),
7768 mMarkedCCGeneration(0),
7769 mHasTriedToCacheTopInnerWindow(false),
7770 mNumOfIndexedDBDatabases(0),
7771 mNumOfOpenWebSockets(0),
7772 mEvent(nullptr),
7773 mWindowGlobalChild(aActor),
7774 mWasSuspendedByGroup(false) {
7775 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"
, 7775); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOuterWindow"
")"); do { *((volatile int*)__null) = 7775; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7776 mBrowsingContext = aOuterWindow->GetBrowsingContext();
7777
7778 if (mWindowGlobalChild) {
7779 mWindowID = aActor->InnerWindowId();
7780
7781 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"
, 7781); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mWindowGlobalChild->BrowsingContext() == mBrowsingContext"
")"); do { *((volatile int*)__null) = 7781; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7782 } else {
7783 mWindowID = nsContentUtils::GenerateWindowId();
7784 }
7785}
7786
7787nsPIDOMWindowInner::~nsPIDOMWindowInner() = default;
7788
7789#undef FORWARD_TO_OUTER
7790#undef FORWARD_TO_OUTER_OR_THROW
7791#undef FORWARD_TO_OUTER_VOID