Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp
Warning:line 5218, 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 STATIC_EXPORTABLE_JS_API -I /var/lib/jenkins/workspace/firefox-scan-build/dom/base -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dom/base -I /var/lib/jenkins/workspace/firefox-scan-build/dom/battery -I /var/lib/jenkins/workspace/firefox-scan-build/dom/events -I /var/lib/jenkins/workspace/firefox-scan-build/dom/media -I /var/lib/jenkins/workspace/firefox-scan-build/dom/network -I /var/lib/jenkins/workspace/firefox-scan-build/caps -I /var/lib/jenkins/workspace/firefox-scan-build/docshell/base -I /var/lib/jenkins/workspace/firefox-scan-build/dom/base -I /var/lib/jenkins/workspace/firefox-scan-build/dom/file -I /var/lib/jenkins/workspace/firefox-scan-build/dom/geolocation -I /var/lib/jenkins/workspace/firefox-scan-build/dom/html -I /var/lib/jenkins/workspace/firefox-scan-build/dom/ipc -I /var/lib/jenkins/workspace/firefox-scan-build/dom/storage -I /var/lib/jenkins/workspace/firefox-scan-build/dom/svg -I /var/lib/jenkins/workspace/firefox-scan-build/dom/xml -I /var/lib/jenkins/workspace/firefox-scan-build/dom/xslt/xpath -I /var/lib/jenkins/workspace/firefox-scan-build/dom/xul -I /var/lib/jenkins/workspace/firefox-scan-build/extensions/spellcheck/src -I /var/lib/jenkins/workspace/firefox-scan-build/gfx/2d -I /var/lib/jenkins/workspace/firefox-scan-build/image -I /var/lib/jenkins/workspace/firefox-scan-build/js/xpconnect/loader -I /var/lib/jenkins/workspace/firefox-scan-build/js/xpconnect/src -I /var/lib/jenkins/workspace/firefox-scan-build/js/xpconnect/wrappers -I /var/lib/jenkins/workspace/firefox-scan-build/layout/base -I /var/lib/jenkins/workspace/firefox-scan-build/layout/forms -I /var/lib/jenkins/workspace/firefox-scan-build/layout/generic -I /var/lib/jenkins/workspace/firefox-scan-build/layout/style -I /var/lib/jenkins/workspace/firefox-scan-build/layout/xul -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/base -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/url-classifier -I /var/lib/jenkins/workspace/firefox-scan-build/parser/htmlparser -I /var/lib/jenkins/workspace/firefox-scan-build/security/manager/ssl -I /var/lib/jenkins/workspace/firefox-scan-build/third_party/xsimd/include -I /var/lib/jenkins/workspace/firefox-scan-build/widget -I /var/lib/jenkins/workspace/firefox-scan-build/xpcom/ds -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/sctp/datachannel -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /var/lib/jenkins/workspace/firefox-scan-build/ipc/chromium/src -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/gtk-3.0/unix-print -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13 -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/x86_64-linux-gnu/c++/13 -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/backward -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-deprecated-this-capture -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -fdeprecated-macro -ferror-limit 19 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fno-aligned-allocation -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-05-16-034744-15991-1 -x c++ /var/lib/jenkins/workspace/firefox-scan-build/dom/base/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/ScrollTypes.h"
76#include "mozilla/Components.h"
77#include "mozilla/SizeOfState.h"
78#include "mozilla/Span.h"
79#include "mozilla/SpinEventLoopUntil.h"
80#include "mozilla/Sprintf.h"
81#include "mozilla/StaticPrefs_browser.h"
82#include "mozilla/StaticPrefs_docshell.h"
83#include "mozilla/StaticPrefs_dom.h"
84#include "mozilla/StaticPrefs_extensions.h"
85#include "mozilla/StaticPrefs_privacy.h"
86#include "mozilla/StorageAccess.h"
87#include "mozilla/StoragePrincipalHelper.h"
88#include "mozilla/Telemetry.h"
89#include "mozilla/TelemetryHistogramEnums.h"
90#include "mozilla/TimeStamp.h"
91#include "mozilla/UniquePtr.h"
92#include "mozilla/Unused.h"
93#include "mozilla/dom/AudioContext.h"
94#include "mozilla/dom/AutoEntryScript.h"
95#include "mozilla/dom/BarProps.h"
96#include "mozilla/dom/BindingDeclarations.h"
97#include "mozilla/dom/BindingUtils.h"
98#include "mozilla/dom/BrowserChild.h"
99#include "mozilla/dom/BrowsingContext.h"
100#include "mozilla/dom/CSPEvalChecker.h"
101#include "mozilla/dom/CallbackDebuggerNotification.h"
102#include "mozilla/dom/ChromeMessageBroadcaster.h"
103#include "mozilla/dom/ClientInfo.h"
104#include "mozilla/dom/ClientManager.h"
105#include "mozilla/dom/ClientSource.h"
106#include "mozilla/dom/ClientState.h"
107#include "mozilla/dom/ClientsBinding.h"
108#include "mozilla/dom/Console.h"
109#include "mozilla/dom/ContentChild.h"
110#include "mozilla/dom/ContentFrameMessageManager.h"
111#include "mozilla/dom/ContentMediaController.h"
112#include "mozilla/dom/CustomElementRegistry.h"
113#include "mozilla/dom/DebuggerNotification.h"
114#include "mozilla/dom/DebuggerNotificationBinding.h"
115#include "mozilla/dom/DebuggerNotificationManager.h"
116#include "mozilla/dom/DocGroup.h"
117#include "mozilla/dom/Document.h"
118#include "mozilla/dom/DocumentInlines.h"
119#include "mozilla/dom/Element.h"
120#include "mozilla/dom/Event.h"
121#include "mozilla/dom/EventTarget.h"
122#include "mozilla/dom/External.h"
123#include "mozilla/dom/Fetch.h"
124#include "mozilla/dom/Gamepad.h"
125#include "mozilla/dom/GamepadHandle.h"
126#include "mozilla/dom/GamepadManager.h"
127#include "mozilla/dom/HashChangeEvent.h"
128#include "mozilla/dom/HashChangeEventBinding.h"
129#include "mozilla/dom/IDBFactory.h"
130#include "mozilla/dom/IdleRequest.h"
131#include "mozilla/dom/ImageBitmap.h"
132#include "mozilla/dom/ImageBitmapSource.h"
133#include "mozilla/dom/InstallTriggerBinding.h"
134#include "mozilla/dom/IntlUtils.h"
135#include "mozilla/dom/JSExecutionContext.h"
136#include "mozilla/dom/LSObject.h"
137#include "mozilla/dom/LocalStorage.h"
138#include "mozilla/dom/LocalStorageCommon.h"
139#include "mozilla/dom/Location.h"
140#include "mozilla/dom/MediaDevices.h"
141#include "mozilla/dom/MediaKeys.h"
142#include "mozilla/dom/NavigatorBinding.h"
143#include "mozilla/dom/Nullable.h"
144#include "mozilla/dom/PartitionedLocalStorage.h"
145#include "mozilla/dom/Performance.h"
146#include "mozilla/dom/PerformanceMainThread.h"
147#include "mozilla/dom/PopStateEvent.h"
148#include "mozilla/dom/PopStateEventBinding.h"
149#include "mozilla/dom/PopupBlocker.h"
150#include "mozilla/dom/PrimitiveConversions.h"
151#include "mozilla/dom/Promise.h"
152#include "mozilla/dom/RootedDictionary.h"
153#include "mozilla/dom/WebTaskSchedulerMainThread.h"
154#include "mozilla/dom/ScriptLoader.h"
155#include "mozilla/dom/ScriptSettings.h"
156#include "mozilla/dom/ServiceWorker.h"
157#include "mozilla/dom/ServiceWorkerDescriptor.h"
158#include "mozilla/dom/ServiceWorkerRegistration.h"
159#include "mozilla/dom/SessionStorageManager.h"
160#include "mozilla/dom/SharedWorker.h"
161#include "mozilla/dom/Storage.h"
162#include "mozilla/dom/StorageEvent.h"
163#include "mozilla/dom/StorageEventBinding.h"
164#include "mozilla/dom/StorageNotifierService.h"
165#include "mozilla/dom/StorageUtils.h"
166#include "mozilla/dom/TabMessageTypes.h"
167#include "mozilla/dom/Timeout.h"
168#include "mozilla/dom/TimeoutHandler.h"
169#include "mozilla/dom/TimeoutManager.h"
170#include "mozilla/dom/ToJSValue.h"
171#include "mozilla/dom/TrustedTypePolicyFactory.h"
172#include "mozilla/dom/VRDisplay.h"
173#include "mozilla/dom/VRDisplayEvent.h"
174#include "mozilla/dom/VRDisplayEventBinding.h"
175#include "mozilla/dom/VREventObserver.h"
176#include "mozilla/dom/VisualViewport.h"
177#include "mozilla/dom/WebIDLGlobalNameHash.h"
178#include "mozilla/dom/WindowBinding.h"
179#include "mozilla/dom/WindowContext.h"
180#include "mozilla/dom/WindowGlobalChild.h"
181#include "mozilla/dom/WindowProxyHolder.h"
182#include "mozilla/dom/WorkerCommon.h"
183#include "mozilla/dom/Worklet.h"
184#include "mozilla/dom/XRPermissionRequest.h"
185#include "mozilla/dom/cache/CacheStorage.h"
186#include "mozilla/dom/cache/Types.h"
187#include "mozilla/glean/bindings/Glean.h"
188#include "mozilla/glean/bindings/GleanPings.h"
189#include "mozilla/extensions/WebExtensionPolicy.h"
190#include "mozilla/fallible.h"
191#include "mozilla/gfx/BasePoint.h"
192#include "mozilla/gfx/BaseRect.h"
193#include "mozilla/gfx/BaseSize.h"
194#include "mozilla/gfx/Rect.h"
195#include "mozilla/gfx/Types.h"
196#include "mozilla/intl/LocaleService.h"
197#include "mozilla/ipc/BackgroundUtils.h"
198#include "mozilla/ipc/PBackgroundSharedTypes.h"
199#include "mozilla/net/CookieJarSettings.h"
200#include "nsAtom.h"
201#include "nsBaseHashtable.h"
202#include "nsCCUncollectableMarker.h"
203#include "nsCOMPtr.h"
204#include "nsCRT.h"
205#include "nsCRTGlue.h"
206#include "nsCanvasFrame.h"
207#include "nsCharTraits.h"
208#include "nsCheapSets.h"
209#include "nsContentUtils.h"
210#include "nsCoord.h"
211#include "nsCycleCollectionNoteChild.h"
212#include "nsCycleCollectionTraversalCallback.h"
213#include "nsDOMNavigationTiming.h"
214#include "nsDebug.h"
215#include "nsDeviceContext.h"
216#include "nsDocShell.h"
217#include "nsFocusManager.h"
218#include "nsFrameMessageManager.h"
219#include "nsGkAtoms.h"
220#include "nsGlobalWindowOuter.h"
221#include "nsHashKeys.h"
222#include "nsHistory.h"
223#include "nsIAddonPolicyService.h"
224#include "nsIArray.h"
225#include "nsIBaseWindow.h"
226#include "nsIBrowserChild.h"
227#include "nsICancelableRunnable.h"
228#include "nsIChannel.h"
229#include "nsIClipboard.h"
230#include "nsIContentSecurityPolicy.h"
231#include "nsIControllers.h"
232#include "nsICookieJarSettings.h"
233#include "nsICookieService.h"
234#include "nsID.h"
235#include "nsIDOMStorageManager.h"
236#include "nsIDeviceSensors.h"
237#include "nsIDocShell.h"
238#include "nsIDocShellTreeItem.h"
239#include "nsIDocShellTreeOwner.h"
240#include "nsIDocumentLoader.h"
241#include "nsIDragService.h"
242#include "nsIFocusManager.h"
243#include "nsIFrame.h"
244#include "nsIGlobalObject.h"
245#include "nsIIOService.h"
246#include "nsIIdleRunnable.h"
247#include "nsIInterfaceRequestorUtils.h"
248#include "nsILoadContext.h"
249#include "nsILoadGroup.h"
250#include "nsILoadInfo.h"
251#include "nsINamed.h"
252#include "nsINode.h"
253#include "nsIObserver.h"
254#include "nsIObserverService.h"
255#include "nsIPermission.h"
256#include "nsIPermissionManager.h"
257#include "nsIPrefBranch.h"
258#include "nsIPrincipal.h"
259#include "nsIPrompt.h"
260#include "nsIRunnable.h"
261#include "nsIScreen.h"
262#include "nsIScreenManager.h"
263#include "nsIScriptContext.h"
264#include "nsIScriptGlobalObject.h"
265#include "nsIScriptObjectPrincipal.h"
266#include "nsIScrollableFrame.h"
267#include "nsISerialEventTarget.h"
268#include "nsISimpleEnumerator.h"
269#include "nsISizeOfEventTarget.h"
270#include "nsISlowScriptDebug.h"
271#include "nsISupportsUtils.h"
272#include "nsIThread.h"
273#include "nsITimedChannel.h"
274#include "nsIURI.h"
275#include "nsIWeakReference.h"
276#include "nsIWebBrowserChrome.h"
277#include "nsIWebNavigation.h"
278#include "nsIWebProgressListener.h"
279#include "nsIWidget.h"
280#include "nsIWidgetListener.h"
281#include "nsIXULRuntime.h"
282#include "nsJSPrincipals.h"
283#include "nsJSUtils.h"
284#include "nsLayoutStatics.h"
285#include "nsLiteralString.h"
286#include "nsNetUtil.h"
287#include "nsPIDOMWindow.h"
288#include "nsPIDOMWindowInlines.h"
289#include "nsPIWindowRoot.h"
290#include "nsPoint.h"
291#include "nsPresContext.h"
292#include "nsQueryObject.h"
293#include "nsSandboxFlags.h"
294#include "nsScreen.h"
295#include "nsServiceManagerUtils.h"
296#include "nsString.h"
297#include "nsStringFlags.h"
298#include "nsStringFwd.h"
299#include "nsTArray.h"
300#include "nsTLiteralString.h"
301#include "nsTObserverArray.h"
302#include "nsTStringRepr.h"
303#include "nsThreadUtils.h"
304#include "nsWeakReference.h"
305#include "nsWindowMemoryReporter.h"
306#include "nsWindowSizes.h"
307#include "nsWrapperCache.h"
308#include "nsWrapperCacheInlines.h"
309#include "nsXULAppAPI.h"
310#include "nsrootidl.h"
311#include "prclist.h"
312#include "prtypes.h"
313#include "xpcprivate.h"
314#include "xpcpublic.h"
315
316#include "nsIDOMXULControlElement.h"
317
318#ifdef NS_PRINTING1
319# include "nsIPrintSettings.h"
320#endif
321
322#ifdef MOZ_WEBSPEECH1
323# include "mozilla/dom/SpeechSynthesis.h"
324#endif
325
326#ifdef ANDROID
327# include <android/log.h>
328#endif
329
330#ifdef XP_WIN
331# include "mozilla/Debug.h"
332# include <process.h>
333# define getpid _getpid
334#else
335# include <unistd.h> // for getpid()
336#endif
337
338using namespace mozilla;
339using namespace mozilla::dom;
340using namespace mozilla::dom::ipc;
341using mozilla::TimeDuration;
342using mozilla::TimeStamp;
343using mozilla::dom::GamepadHandle;
344using mozilla::dom::cache::CacheStorage;
345
346#define FORWARD_TO_OUTER(method, args, err_rval) \
347 PR_BEGIN_MACROdo { \
348 RefPtr<nsGlobalWindowOuter> outer = GetOuterWindowInternal(); \
349 if (!HasActiveDocument()) { \
350 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"
, 351)
351 : "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"
, 351)
; \
352 return err_rval; \
353 } \
354 return outer->method args; \
355 PR_END_MACRO} while (0)
356
357static nsGlobalWindowOuter* GetOuterWindowForForwarding(
358 nsGlobalWindowInner* aInner, ErrorResult& aError) {
359 nsGlobalWindowOuter* outer = aInner->GetOuterWindowInternal();
360 if (MOZ_LIKELY(aInner->HasActiveDocument())(__builtin_expect(!!(aInner->HasActiveDocument()), 1))) {
361 return outer;
362 }
363 if (!outer) {
364 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"
, 364)
;
365 aError.Throw(NS_ERROR_NOT_INITIALIZED);
366 } else {
367 aError.Throw(NS_ERROR_XPC_SECURITY_MANAGER_VETO);
368 }
369 return nullptr;
370}
371
372#define FORWARD_TO_OUTER_OR_THROW(method, args, rv, err_rval) \
373 PR_BEGIN_MACROdo { \
374 RefPtr<nsGlobalWindowOuter> outer = GetOuterWindowForForwarding(this, rv); \
375 if (MOZ_LIKELY(outer)(__builtin_expect(!!(outer), 1))) { \
376 return outer->method args; \
377 } \
378 return err_rval; \
379 PR_END_MACRO} while (0)
380
381#define FORWARD_TO_OUTER_VOID(method, args) \
382 PR_BEGIN_MACROdo { \
383 RefPtr<nsGlobalWindowOuter> outer = GetOuterWindowInternal(); \
384 if (!HasActiveDocument()) { \
385 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"
, 386)
386 : "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"
, 386)
; \
387 return; \
388 } \
389 outer->method args; \
390 return; \
391 PR_END_MACRO} while (0)
392
393#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)
\
394 PR_BEGIN_MACROdo { \
395 if (MOZ_UNLIKELY(!HasActiveDocument())(__builtin_expect(!!(!HasActiveDocument()), 0))) { \
396 aError.Throw(NS_ERROR_XPC_SECURITY_MANAGER_VETO); \
397 return err_rval; \
398 } \
399 PR_END_MACRO} while (0)
400
401#define DOM_TOUCH_LISTENER_ADDED"dom-touch-listener-added" "dom-touch-listener-added"
402#define MEMORY_PRESSURE_OBSERVER_TOPIC"memory-pressure" "memory-pressure"
403#define PERMISSION_CHANGED_TOPIC"perm-changed" "perm-changed"
404
405static LazyLogModule gDOMLeakPRLogInner("DOMLeakInner");
406extern mozilla::LazyLogModule gTimeoutLog;
407
408#ifdef DEBUG1
409static LazyLogModule gDocShellAndDOMWindowLeakLogging(
410 "DocShellAndDOMWindowLeak");
411#endif
412
413static FILE* gDumpFile = nullptr;
414
415nsGlobalWindowInner::InnerWindowByIdTable*
416 nsGlobalWindowInner::sInnerWindowsById = nullptr;
417
418bool nsGlobalWindowInner::sDragServiceDisabled = false;
419bool nsGlobalWindowInner::sMouseDown = false;
420
421/**
422 * An indirect observer object that means we don't have to implement nsIObserver
423 * on nsGlobalWindow, where any script could see it.
424 */
425class nsGlobalWindowObserver final : public nsIObserver,
426 public nsIInterfaceRequestor,
427 public StorageNotificationObserver {
428 public:
429 explicit nsGlobalWindowObserver(nsGlobalWindowInner* aWindow)
430 : mWindow(aWindow) {}
431 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:
432 NS_IMETHODvirtual nsresult Observe(nsISupports* aSubject, const char* aTopic,
433 const char16_t* aData) override {
434 if (!mWindow) return NS_OK;
435 return mWindow->Observe(aSubject, aTopic, aData);
436 }
437 void Forget() { mWindow = nullptr; }
438 NS_IMETHODvirtual nsresult GetInterface(const nsIID& aIID, void** aResult) override {
439 if (mWindow && aIID.Equals(NS_GET_IID(nsIDOMWindow)(nsIDOMWindow::COMTypeInfo<nsIDOMWindow, void>::kIID)) && mWindow) {
440 return mWindow->QueryInterface(aIID, aResult);
441 }
442 return NS_NOINTERFACE;
443 }
444
445 void ObserveStorageNotification(StorageEvent* aEvent,
446 const char16_t* aStorageType,
447 bool aPrivateBrowsing) override {
448 if (mWindow) {
449 mWindow->ObserveStorageNotification(aEvent, aStorageType,
450 aPrivateBrowsing);
451 }
452 }
453
454 nsIPrincipal* GetEffectiveCookiePrincipal() const override {
455 return mWindow ? mWindow->GetEffectiveCookiePrincipal() : nullptr;
456 }
457
458 nsIPrincipal* GetEffectiveStoragePrincipal() const override {
459 return mWindow ? mWindow->GetEffectiveStoragePrincipal() : nullptr;
460 }
461
462 bool IsPrivateBrowsing() const override {
463 return mWindow ? mWindow->IsPrivateBrowsing() : false;
464 }
465
466 nsIEventTarget* GetEventTarget() const override {
467 return mWindow ? mWindow->SerialEventTarget() : nullptr;
468 }
469
470 private:
471 ~nsGlobalWindowObserver() = default;
472
473 // This reference is non-owning and safe because it's cleared by
474 // nsGlobalWindowInner::FreeInnerObjects().
475 nsGlobalWindowInner* MOZ_NON_OWNING_REF mWindow;
476};
477
478NS_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"
, 478); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
478; __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"
, 478); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsGlobalWindowObserver\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 478; __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"
, 478); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 478
; __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"
, 478); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsGlobalWindowObserver\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 478; __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"
, 478); 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; }
479
480class IdleRequestExecutor;
481
482class IdleRequestExecutorTimeoutHandler final : public TimeoutHandler {
483 public:
484 explicit IdleRequestExecutorTimeoutHandler(IdleRequestExecutor* aExecutor)
485 : mExecutor(aExecutor) {}
486
487 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:
488 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"
, 488); AnnotateMozCrashReason("MOZ_ASSERT" "(" "p == &_cycleCollectorGlobal"
") (" "IdleRequestExecutorTimeoutHandler" " should QI to its own CC participant"
")"); do { *((volatile int*)__null) = 488; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } static cycleCollection
_cycleCollectorGlobal; virtual void BaseCycleCollectable() final
{}
489
490 bool Call(const char* /* unused */) override;
491
492 private:
493 ~IdleRequestExecutorTimeoutHandler() override = default;
494 RefPtr<IdleRequestExecutor> mExecutor;
495};
496
497NS_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; }
498
499NS_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"
, 499); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
499; __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; }
500NS_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"
, 500); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 500
; __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); }
501
502NS_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"
, 502); 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
503 NS_INTERFACE_MAP_ENTRY(nsISupports)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupports>)) foundInterface = static_cast
<nsISupports*>(this); else
504NS_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"
, 504); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIID.Equals((nsISupports::COMTypeInfo<nsISupports, void>::kIID))"
")"); do { *((volatile int*)__null) = 504; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); status = NS_NOINTERFACE
; } else { (foundInterface)->AddRef(); status = NS_OK; } *
aInstancePtr = foundInterface; return status; }
505
506class IdleRequestExecutor final : public nsIRunnable,
507 public nsICancelableRunnable,
508 public nsINamed,
509 public nsIIdleRunnable {
510 public:
511 explicit IdleRequestExecutor(nsGlobalWindowInner* aWindow)
512 : mDispatched(false), mDeadline(TimeStamp::Now()), mWindow(aWindow) {
513 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"
, 513); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mWindow"
")"); do { *((volatile int*)__null) = 513; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
514
515 mIdlePeriodLimit = {mDeadline, mWindow->LastIdleRequestHandle()};
516 mDelayedExecutorDispatcher = new IdleRequestExecutorTimeoutHandler(this);
517 }
518
519 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:
520 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"
, 520); AnnotateMozCrashReason("MOZ_ASSERT" "(" "p == &_cycleCollectorGlobal"
") (" "IdleRequestExecutor" " should QI to its own CC participant"
")"); do { *((volatile int*)__null) = 520; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } static cycleCollection
_cycleCollectorGlobal; virtual void BaseCycleCollectable() final
{}
521
522 NS_DECL_NSIRUNNABLEvirtual nsresult Run(void) override;
523 NS_DECL_NSINAMEDvirtual nsresult GetName(nsACString& aName) override;
524 nsresult Cancel() override;
525 void SetDeadline(TimeStamp aDeadline) override;
526
527 bool IsCancelled() const { return !mWindow || mWindow->IsDying(); }
528 // Checks if aRequest shouldn't execute in the current idle period
529 // since it has been queued from a chained call to
530 // requestIdleCallback from within a running idle callback.
531 bool IneligibleForCurrentIdlePeriod(IdleRequest* aRequest) const {
532 return aRequest->Handle() >= mIdlePeriodLimit.mLastRequestIdInIdlePeriod &&
533 TimeStamp::Now() <= mIdlePeriodLimit.mEndOfIdlePeriod;
534 }
535
536 void MaybeUpdateIdlePeriodLimit();
537
538 // Maybe dispatch the IdleRequestExecutor. MabyeDispatch will
539 // schedule a delayed dispatch if the associated window is in the
540 // background or if given a time to wait until dispatching.
541 void MaybeDispatch(TimeStamp aDelayUntil = TimeStamp());
542 void ScheduleDispatch();
543
544 private:
545 struct IdlePeriodLimit {
546 TimeStamp mEndOfIdlePeriod;
547 uint32_t mLastRequestIdInIdlePeriod;
548 };
549
550 void DelayedDispatch(uint32_t aDelay);
551
552 ~IdleRequestExecutor() override = default;
553
554 bool mDispatched;
555 TimeStamp mDeadline;
556 IdlePeriodLimit mIdlePeriodLimit;
557 RefPtr<nsGlobalWindowInner> mWindow;
558 // The timeout handler responsible for dispatching this executor in
559 // the case of immediate dispatch to the idle queue isn't
560 // desirable. This is used if we've dispatched all idle callbacks
561 // that are allowed to run in the current idle period, or if the
562 // associated window is currently in the background.
563 RefPtr<TimeoutHandler> mDelayedExecutorDispatcher;
564 // If not Nothing() then this value is the handle to the currently
565 // scheduled delayed executor dispatcher. This is needed to be able
566 // to cancel the timeout handler in case of the executor being
567 // cancelled.
568 Maybe<int32_t> mDelayedExecutorHandle;
569};
570
571NS_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; }
572 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; }
573
574NS_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"
, 574); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
574; __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; }
575NS_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"
, 575); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 575
; __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); }
576
577NS_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"
, 577); 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
578 NS_INTERFACE_MAP_ENTRY(nsIRunnable)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIRunnable>)) foundInterface = static_cast
<nsIRunnable*>(this); else
579 NS_INTERFACE_MAP_ENTRY(nsICancelableRunnable)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsICancelableRunnable>)) foundInterface
= static_cast<nsICancelableRunnable*>(this); else
580 NS_INTERFACE_MAP_ENTRY(nsINamed)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsINamed>)) foundInterface = static_cast
<nsINamed*>(this); else
581 NS_INTERFACE_MAP_ENTRY(nsIIdleRunnable)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIIdleRunnable>)) foundInterface
= static_cast<nsIIdleRunnable*>(this); else
582 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
583NS_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"
, 583); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIID.Equals((nsISupports::COMTypeInfo<nsISupports, void>::kIID))"
")"); do { *((volatile int*)__null) = 583; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); status = NS_NOINTERFACE
; } else { (foundInterface)->AddRef(); status = NS_OK; } *
aInstancePtr = foundInterface; return status; }
584
585NS_IMETHODIMPnsresult
586IdleRequestExecutor::GetName(nsACString& aName) {
587 aName.AssignLiteral("IdleRequestExecutor");
588 return NS_OK;
589}
590
591// MOZ_CAN_RUN_SCRIPT_BOUNDARY until nsIRunnable::Run is MOZ_CAN_RUN_SCRIPT.
592// See bug 1535398.
593MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHODIMPnsresult IdleRequestExecutor::Run() {
594 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"
, 594); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 594; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
595
596 mDispatched = false;
597 if (mWindow) {
598 RefPtr<nsGlobalWindowInner> window(mWindow);
599 window->ExecuteIdleRequest(mDeadline);
600 }
601
602 return NS_OK;
603}
604
605nsresult IdleRequestExecutor::Cancel() {
606 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"
, 606); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 606; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
607
608 if (mDelayedExecutorHandle && mWindow) {
609 mWindow->TimeoutManager().ClearTimeout(
610 mDelayedExecutorHandle.value(), Timeout::Reason::eIdleCallbackTimeout);
611 }
612
613 mWindow = nullptr;
614 return NS_OK;
615}
616
617void IdleRequestExecutor::SetDeadline(TimeStamp aDeadline) {
618 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"
, 618); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 618; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
619
620 if (!mWindow) {
621 return;
622 }
623
624 mDeadline = aDeadline;
625}
626
627void IdleRequestExecutor::MaybeUpdateIdlePeriodLimit() {
628 if (TimeStamp::Now() > mIdlePeriodLimit.mEndOfIdlePeriod) {
629 mIdlePeriodLimit = {mDeadline, mWindow->LastIdleRequestHandle()};
630 }
631}
632
633void IdleRequestExecutor::MaybeDispatch(TimeStamp aDelayUntil) {
634 // If we've already dispatched the executor we don't want to do it
635 // again. Also, if we've called IdleRequestExecutor::Cancel mWindow
636 // will be null, which indicates that we shouldn't dispatch this
637 // executor either.
638 if (mDispatched || IsCancelled()) {
639 return;
640 }
641
642 mDispatched = true;
643
644 nsPIDOMWindowOuter* outer = mWindow->GetOuterWindow();
645 if (outer && outer->IsBackground()) {
646 // Set a timeout handler with a timeout of 0 ms to throttle idle
647 // callback requests coming from a backround window using
648 // background timeout throttling.
649 DelayedDispatch(0);
650 return;
651 }
652
653 TimeStamp now = TimeStamp::Now();
654 if (!aDelayUntil || aDelayUntil < now) {
655 ScheduleDispatch();
656 return;
657 }
658
659 TimeDuration delay = aDelayUntil - now;
660 DelayedDispatch(static_cast<uint32_t>(delay.ToMilliseconds()));
661}
662
663void IdleRequestExecutor::ScheduleDispatch() {
664 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"
, 664); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mWindow" ")"
); do { *((volatile int*)__null) = 664; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
665 mDelayedExecutorHandle = Nothing();
666 RefPtr<IdleRequestExecutor> request = this;
667 NS_DispatchToCurrentThreadQueue(request.forget(), EventQueuePriority::Idle);
668}
669
670void IdleRequestExecutor::DelayedDispatch(uint32_t aDelay) {
671 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"
, 671); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mWindow" ")"
); do { *((volatile int*)__null) = 671; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
672 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"
, 672); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDelayedExecutorHandle.isNothing()"
")"); do { *((volatile int*)__null) = 672; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
673 int32_t handle;
674 mWindow->TimeoutManager().SetTimeout(
675 mDelayedExecutorDispatcher, aDelay, false,
676 Timeout::Reason::eIdleCallbackTimeout, &handle);
677 mDelayedExecutorHandle = Some(handle);
678}
679
680bool IdleRequestExecutorTimeoutHandler::Call(const char* /* unused */) {
681 if (!mExecutor->IsCancelled()) {
682 mExecutor->ScheduleDispatch();
683 }
684 return true;
685}
686
687void nsGlobalWindowInner::ScheduleIdleRequestDispatch() {
688 AssertIsOnMainThread();
689
690 if (!mIdleRequestExecutor) {
691 mIdleRequestExecutor = new IdleRequestExecutor(this);
692 }
693
694 mIdleRequestExecutor->MaybeDispatch();
695}
696
697void nsGlobalWindowInner::SuspendIdleRequests() {
698 if (mIdleRequestExecutor) {
699 mIdleRequestExecutor->Cancel();
700 mIdleRequestExecutor = nullptr;
701 }
702}
703
704void nsGlobalWindowInner::ResumeIdleRequests() {
705 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"
, 705); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIdleRequestExecutor"
")"); do { *((volatile int*)__null) = 705; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
706
707 ScheduleIdleRequestDispatch();
708}
709
710void nsGlobalWindowInner::RemoveIdleCallback(
711 mozilla::dom::IdleRequest* aRequest) {
712 AssertIsOnMainThread();
713
714 if (aRequest->HasTimeout()) {
715 mTimeoutManager->ClearTimeout(aRequest->GetTimeoutHandle(),
716 Timeout::Reason::eIdleCallbackTimeout);
717 }
718
719 aRequest->removeFrom(mIdleRequestCallbacks);
720}
721
722void nsGlobalWindowInner::RunIdleRequest(IdleRequest* aRequest,
723 DOMHighResTimeStamp aDeadline,
724 bool aDidTimeout) {
725 AssertIsOnMainThread();
726 // XXXbz Do we still need this RefPtr? MOZ_CAN_RUN_SCRIPT should
727 // guarantee that caller is holding a strong ref on the stack.
728 RefPtr<IdleRequest> request(aRequest);
729 RemoveIdleCallback(request);
730 request->IdleRun(this, aDeadline, aDidTimeout);
731}
732
733void nsGlobalWindowInner::ExecuteIdleRequest(TimeStamp aDeadline) {
734 AssertIsOnMainThread();
735 RefPtr<IdleRequest> request = mIdleRequestCallbacks.getFirst();
736
737 if (!request) {
738 // There are no more idle requests, so stop scheduling idle
739 // request callbacks.
740 return;
741 }
742
743 // If the request that we're trying to execute has been queued
744 // during the current idle period, then dispatch it again at the end
745 // of the idle period.
746 if (mIdleRequestExecutor->IneligibleForCurrentIdlePeriod(request)) {
747 mIdleRequestExecutor->MaybeDispatch(aDeadline);
748 return;
749 }
750
751 DOMHighResTimeStamp deadline = 0.0;
752
753 if (Performance* perf = GetPerformance()) {
754 deadline = perf->GetDOMTiming()->TimeStampToDOMHighRes(aDeadline);
755 }
756
757 mIdleRequestExecutor->MaybeUpdateIdlePeriodLimit();
758 RunIdleRequest(request, deadline, false);
759
760 // Running the idle callback could've suspended the window, in which
761 // case mIdleRequestExecutor will be null.
762 if (mIdleRequestExecutor) {
763 mIdleRequestExecutor->MaybeDispatch();
764 }
765}
766
767class IdleRequestTimeoutHandler final : public TimeoutHandler {
768 public:
769 IdleRequestTimeoutHandler(JSContext* aCx, IdleRequest* aIdleRequest,
770 nsPIDOMWindowInner* aWindow)
771 : TimeoutHandler(aCx), mIdleRequest(aIdleRequest), mWindow(aWindow) {}
772
773 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:
774 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"
, 774); AnnotateMozCrashReason("MOZ_ASSERT" "(" "p == &_cycleCollectorGlobal"
") (" "IdleRequestTimeoutHandler" " should QI to its own CC participant"
")"); do { *((volatile int*)__null) = 774; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } static cycleCollection
_cycleCollectorGlobal; virtual void BaseCycleCollectable() final
{}
775
776 MOZ_CAN_RUN_SCRIPT bool Call(const char* /* unused */) override {
777 RefPtr<nsGlobalWindowInner> window(nsGlobalWindowInner::Cast(mWindow));
778 RefPtr<IdleRequest> request(mIdleRequest);
779 window->RunIdleRequest(request, 0.0, true);
780 return true;
781 }
782
783 private:
784 ~IdleRequestTimeoutHandler() override = default;
785
786 RefPtr<IdleRequest> mIdleRequest;
787 nsCOMPtr<nsPIDOMWindowInner> mWindow;
788};
789
790NS_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;
}
791
792NS_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"
, 792); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
792; __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; }
793NS_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"
, 793); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 793
; __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); }
794
795NS_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"
, 795); 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
796 NS_INTERFACE_MAP_ENTRY(nsISupports)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupports>)) foundInterface = static_cast
<nsISupports*>(this); else
797NS_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"
, 797); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIID.Equals((nsISupports::COMTypeInfo<nsISupports, void>::kIID))"
")"); do { *((volatile int*)__null) = 797; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); status = NS_NOINTERFACE
; } else { (foundInterface)->AddRef(); status = NS_OK; } *
aInstancePtr = foundInterface; return status; }
798
799uint32_t nsGlobalWindowInner::RequestIdleCallback(
800 JSContext* aCx, IdleRequestCallback& aCallback,
801 const IdleRequestOptions& aOptions, ErrorResult& aError) {
802 AssertIsOnMainThread();
803
804 if (IsDying()) {
805 return 0;
806 }
807
808 uint32_t handle = mIdleRequestCallbackCounter++;
809
810 RefPtr<IdleRequest> request = new IdleRequest(&aCallback, handle);
811
812 if (aOptions.mTimeout.WasPassed()) {
813 int32_t timeoutHandle;
814 RefPtr<TimeoutHandler> handler(
815 new IdleRequestTimeoutHandler(aCx, request, this));
816
817 nsresult rv = mTimeoutManager->SetTimeout(
818 handler, aOptions.mTimeout.Value(), false,
819 Timeout::Reason::eIdleCallbackTimeout, &timeoutHandle);
820
821 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"
, 821)
) {
822 return 0;
823 }
824
825 request->SetTimeoutHandle(timeoutHandle);
826 }
827
828 mIdleRequestCallbacks.insertBack(request);
829
830 if (!IsSuspended()) {
831 ScheduleIdleRequestDispatch();
832 }
833
834 return handle;
835}
836
837void nsGlobalWindowInner::CancelIdleCallback(uint32_t aHandle) {
838 for (IdleRequest* r : mIdleRequestCallbacks) {
839 if (r->Handle() == aHandle) {
840 RemoveIdleCallback(r);
841 break;
842 }
843 }
844}
845
846void nsGlobalWindowInner::DisableIdleCallbackRequests() {
847 if (mIdleRequestExecutor) {
848 mIdleRequestExecutor->Cancel();
849 mIdleRequestExecutor = nullptr;
850 }
851
852 while (!mIdleRequestCallbacks.isEmpty()) {
853 RefPtr<IdleRequest> request = mIdleRequestCallbacks.getFirst();
854 RemoveIdleCallback(request);
855 }
856}
857
858bool nsGlobalWindowInner::IsBackgroundInternal() const {
859 return !mOuterWindow || mOuterWindow->IsBackground();
860}
861
862class PromiseDocumentFlushedResolver final {
863 public:
864 PromiseDocumentFlushedResolver(Promise* aPromise,
865 PromiseDocumentFlushedCallback& aCallback)
866 : mPromise(aPromise), mCallback(&aCallback) {}
867
868 virtual ~PromiseDocumentFlushedResolver() = default;
869
870 void Call() {
871 nsMutationGuard guard;
872 ErrorResult error;
873 JS::Rooted<JS::Value> returnVal(RootingCx());
874 mCallback->Call(&returnVal, error);
875
876 if (error.Failed()) {
877 mPromise->MaybeReject(std::move(error));
878 } else if (guard.Mutated(0)) {
879 // Something within the callback mutated the DOM.
880 mPromise->MaybeRejectWithNoModificationAllowedError(
881 "DOM mutated from promiseDocumentFlushed callbacks");
882 } else {
883 mPromise->MaybeResolve(returnVal);
884 }
885 }
886
887 RefPtr<Promise> mPromise;
888 RefPtr<PromiseDocumentFlushedCallback> mCallback;
889};
890
891//*****************************************************************************
892//*** nsGlobalWindowInner: Object Management
893//*****************************************************************************
894
895nsGlobalWindowInner::nsGlobalWindowInner(nsGlobalWindowOuter* aOuterWindow,
896 WindowGlobalChild* aActor)
897 : nsPIDOMWindowInner(aOuterWindow, aActor),
898 mHasOrientationChangeListeners(false),
899 mWasOffline(false),
900 mHasHadSlowScript(false),
901 mIsChrome(false),
902 mCleanMessageManager(false),
903 mNeedsFocus(true),
904 mHasFocus(false),
905 mFocusByKeyOccurred(false),
906 mDidFireDocElemInserted(false),
907 mHasGamepad(false),
908 mHasXRSession(false),
909 mHasVRDisplayActivateEvents(false),
910 mXRRuntimeDetectionInFlight(false),
911 mXRPermissionRequestInFlight(false),
912 mXRPermissionGranted(false),
913 mWasCurrentInnerWindow(false),
914 mHasSeenGamepadInput(false),
915 mHintedWasLoading(false),
916 mHasOpenedExternalProtocolFrame(false),
917 mScrollMarksOnHScrollbar(false),
918 mStorageAllowedReasonCache(0),
919 mSuspendDepth(0),
920 mFreezeDepth(0),
921#ifdef DEBUG1
922 mSerial(0),
923#endif
924 mFocusMethod(0),
925 mIdleRequestCallbackCounter(1),
926 mIdleRequestExecutor(nullptr),
927 mObservingRefresh(false),
928 mIteratingDocumentFlushedResolvers(false),
929 mCanSkipCCGeneration(0) {
930 mIsInnerWindow = true;
931
932 AssertIsOnMainThread();
933 SetIsOnMainThread();
934 nsLayoutStatics::AddRef();
935
936 // Initialize the PRCList (this).
937 PR_INIT_CLIST(this)do { (this)->next = (this); (this)->prev = (this); } while
(0)
;
938
939 // add this inner window to the outer window list of inners.
940 PR_INSERT_AFTER(this, aOuterWindow)do { (this)->next = (aOuterWindow)->next; (this)->prev
= (aOuterWindow); (aOuterWindow)->next->prev = (this);
(aOuterWindow)->next = (this); } while (0)
;
941
942 mTimeoutManager = MakeUnique<dom::TimeoutManager>(
943 *this, StaticPrefs::dom_timeout_max_idle_defer_ms());
944
945 mObserver = new nsGlobalWindowObserver(this);
946 if (nsCOMPtr<nsIObserverService> os = services::GetObserverService()) {
947 // Watch for online/offline status changes so we can fire events. Use
948 // a strong reference.
949 os->AddObserver(mObserver, NS_IOSERVICE_OFFLINE_STATUS_TOPIC"network:offline-status-changed", false);
950 os->AddObserver(mObserver, MEMORY_PRESSURE_OBSERVER_TOPIC"memory-pressure", false);
951 os->AddObserver(mObserver, PERMISSION_CHANGED_TOPIC"perm-changed", false);
952 os->AddObserver(mObserver, "screen-information-changed", false);
953 }
954
955 Preferences::AddStrongObserver(mObserver, "intl.accept_languages");
956
957 // Watch for storage notifications so we can fire storage events.
958 RefPtr<StorageNotifierService> sns = StorageNotifierService::GetOrCreate();
959 if (sns) {
960 sns->Register(mObserver);
961 }
962
963 if (XRE_IsContentProcess()) {
964 nsCOMPtr<nsIDocShell> docShell = GetDocShell();
965 if (docShell) {
966 mBrowserChild = docShell->GetBrowserChild();
967 }
968 }
969
970 if (gDumpFile == nullptr) {
971 nsAutoCString fname;
972 Preferences::GetCString("browser.dom.window.dump.file", fname);
973 if (!fname.IsEmpty()) {
974 // If this fails to open, Dump() knows to just go to stdout on null.
975 gDumpFile = fopen(fname.get(), "wb+");
976 } else {
977 gDumpFile = stdoutstdout;
978 }
979 }
980
981#ifdef DEBUG1
982 mSerial = nsContentUtils::InnerOrOuterWindowCreated();
983
984 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)
985 ("++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)
986 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)
987 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)
988 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)
;
989#endif
990
991 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)
992 ("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)
;
993
994 // Add ourselves to the inner windows list.
995 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"
, 995); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sInnerWindowsById"
") (" "Inner Windows hash table must be created!" ")"); do {
*((volatile int*)__null) = 995; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
996 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"
, 997); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sInnerWindowsById->Contains(mWindowID)"
") (" "This window shouldn't be in the hash table yet!" ")")
; do { *((volatile int*)__null) = 997; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
997 "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"
, 997); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sInnerWindowsById->Contains(mWindowID)"
") (" "This window shouldn't be in the hash table yet!" ")")
; do { *((volatile int*)__null) = 997; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
998 // We seem to see crashes in release builds because of null
999 // |sInnerWindowsById|.
1000 if (sInnerWindowsById) {
1001 sInnerWindowsById->InsertOrUpdate(mWindowID, this);
1002 }
1003}
1004
1005#ifdef DEBUG1
1006
1007/* static */
1008void nsGlobalWindowInner::AssertIsOnMainThread() {
1009 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"
, 1009); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 1009; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1010}
1011
1012#endif // DEBUG
1013
1014/* static */
1015void nsGlobalWindowInner::Init() {
1016 AssertIsOnMainThread();
1017
1018 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"
, 1019); MOZ_PretendNoReturn(); } } while (0)
1019 "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"
, 1019); MOZ_PretendNoReturn(); } } while (0)
;
1020
1021 sInnerWindowsById = new InnerWindowByIdTable();
1022}
1023
1024nsGlobalWindowInner::~nsGlobalWindowInner() {
1025 AssertIsOnMainThread();
1026 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"
, 1026); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mHintedWasLoading"
")"); do { *((volatile int*)__null) = 1026; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1027
1028 if (IsChromeWindow()) {
1029 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"
, 1030); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCleanMessageManager"
") (" "chrome windows may always disconnect the msg manager"
")"); do { *((volatile int*)__null) = 1030; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1030 "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"
, 1030); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCleanMessageManager"
") (" "chrome windows may always disconnect the msg manager"
")"); do { *((volatile int*)__null) = 1030; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1031
1032 DisconnectAndClearGroupMessageManagers();
1033
1034 if (mChromeFields.mMessageManager) {
1035 static_cast<nsFrameMessageManager*>(mChromeFields.mMessageManager.get())
1036 ->Disconnect();
1037 }
1038
1039 mCleanMessageManager = false;
1040 }
1041
1042 // In most cases this should already have been called, but call it again
1043 // here to catch any corner cases.
1044 FreeInnerObjects();
1045
1046 if (sInnerWindowsById) {
1047 sInnerWindowsById->Remove(mWindowID);
1048 }
1049
1050 nsContentUtils::InnerOrOuterWindowDestroyed();
1051
1052#ifdef DEBUG1
1053 if (MOZ_LOG_TEST(gDocShellAndDOMWindowLeakLogging, LogLevel::Info)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellAndDOMWindowLeakLogging
, LogLevel::Info)), 0))
) {
1054 nsAutoCString url;
1055 if (mLastOpenedURI) {
1056 url = mLastOpenedURI->GetSpecOrDefault();
1057
1058 // Data URLs can be very long, so truncate to avoid flooding the log.
1059 const uint32_t maxURLLength = 1000;
1060 if (url.Length() > maxURLLength) {
1061 url.Truncate(maxURLLength);
1062 }
1063 }
1064
1065 nsGlobalWindowOuter* outer = nsGlobalWindowOuter::Cast(mOuterWindow);
1066 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)
1067 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)
1068 ("--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)
1069 "%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)
1070 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)
1071 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)
1072 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)
;
1073 }
1074#endif
1075 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)
1076 ("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)
;
1077
1078 Telemetry::Accumulate(Telemetry::INNERWINDOWS_WITH_MUTATION_LISTENERS,
1079 mMutationBits ? 1 : 0);
1080
1081 // An inner window is destroyed, pull it out of the outer window's
1082 // list if inner windows.
1083
1084 PR_REMOVE_LINK(this)do { (this)->prev->next = (this)->next; (this)->next
->prev = (this)->prev; } while (0)
;
1085
1086 // If our outer window's inner window is this window, null out the
1087 // outer window's reference to this window that's being deleted.
1088 nsGlobalWindowOuter* outer = GetOuterWindowInternal();
1089 if (outer) {
1090 outer->MaybeClearInnerWindow(this);
1091 }
1092
1093 // We don't have to leave the tab group if we are an inner window.
1094
1095 nsCOMPtr<nsIDeviceSensors> ac = do_GetService(NS_DEVICE_SENSORS_CONTRACTID"@mozilla.org/devicesensors;1");
1096 if (ac) ac->RemoveWindowAsListener(this);
1097
1098 nsLayoutStatics::Release();
1099}
1100
1101// static
1102void nsGlobalWindowInner::ShutDown() {
1103 AssertIsOnMainThread();
1104
1105 if (gDumpFile && gDumpFile != stdoutstdout) {
1106 fclose(gDumpFile);
1107 }
1108 gDumpFile = nullptr;
1109
1110 delete sInnerWindowsById;
1111 sInnerWindowsById = nullptr;
1112}
1113
1114void nsGlobalWindowInner::FreeInnerObjects() {
1115 if (IsDying()) {
1116 return;
1117 }
1118 StartDying();
1119
1120 if (mDoc && mDoc->GetWindowContext()) {
1121 // The document is about to lose its window, so this is a good time to send
1122 // our page use counters.
1123 //
1124 // (We also do this in Document::SetScriptGlobalObject(nullptr), which
1125 // catches most cases of documents losing their window, but not all.)
1126 mDoc->SendPageUseCounters();
1127 }
1128
1129 // Make sure that this is called before we null out the document and
1130 // other members that the window destroyed observers could
1131 // re-create.
1132 NotifyDOMWindowDestroyed(this);
1133 if (auto* reporter = nsWindowMemoryReporter::Get()) {
1134 reporter->ObserveDOMWindowDetached(this);
1135 }
1136
1137 // Kill all of the workers for this window.
1138 CancelWorkersForWindow(*this);
1139
1140 for (RefPtr<mozilla::dom::SharedWorker> pinnedWorker :
1141 mSharedWorkers.ForwardRange()) {
1142 pinnedWorker->Close();
1143 }
1144
1145 if (mTimeoutManager) {
1146 mTimeoutManager->ClearAllTimeouts();
1147 }
1148
1149 DisableIdleCallbackRequests();
1150
1151 mChromeEventHandler = nullptr;
1152
1153 if (mListenerManager) {
1154 mListenerManager->RemoveAllListeners();
1155 mListenerManager->Disconnect();
1156 mListenerManager = nullptr;
1157 }
1158
1159 mHistory = nullptr;
1160
1161 if (mNavigator) {
1162 mNavigator->OnNavigation();
1163 mNavigator->Invalidate();
1164 mNavigator = nullptr;
1165 }
1166
1167 mScreen = nullptr;
1168
1169 if (mDoc) {
1170 // Remember the document's principal, URI, and CSP.
1171 mDocumentPrincipal = mDoc->NodePrincipal();
1172 mDocumentCookiePrincipal = mDoc->EffectiveCookiePrincipal();
1173 mDocumentStoragePrincipal = mDoc->EffectiveStoragePrincipal();
1174 mDocumentPartitionedPrincipal = mDoc->PartitionedPrincipal();
1175 mDocumentURI = mDoc->GetDocumentURI();
1176 mDocBaseURI = mDoc->GetDocBaseURI();
1177 mDocumentCsp = mDoc->GetCsp();
1178
1179 while (mDoc->EventHandlingSuppressed()) {
1180 mDoc->UnsuppressEventHandlingAndFireEvents(false);
1181 }
1182 }
1183
1184 // Remove our reference to the document and the document principal.
1185 mFocusedElement = nullptr;
1186
1187 nsIGlobalObject::UnlinkObjectsInGlobal();
1188
1189 NotifyWindowIDDestroyed("inner-window-destroyed");
1190
1191 for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) {
1192 mAudioContexts[i]->OnWindowDestroy();
1193 }
1194 mAudioContexts.Clear();
1195
1196 for (MediaKeys* mediaKeys : mMediaKeysInstances) {
1197 mediaKeys->OnInnerWindowDestroy();
1198 }
1199 mMediaKeysInstances.Clear();
1200
1201 DisableGamepadUpdates();
1202 mHasGamepad = false;
1203 mGamepads.Clear();
1204 DisableVRUpdates();
1205 mHasXRSession = false;
1206 mHasVRDisplayActivateEvents = false;
1207 mXRRuntimeDetectionInFlight = false;
1208 mXRPermissionRequestInFlight = false;
1209 mXRPermissionGranted = false;
1210 mVRDisplays.Clear();
1211
1212 // This breaks a cycle between the window and the ClientSource object.
1213 mClientSource.reset();
1214
1215 if (mWindowGlobalChild) {
1216 // Remove any remaining listeners.
1217 int64_t nListeners = mWindowGlobalChild->BeforeUnloadListeners();
1218 for (int64_t i = 0; i < nListeners; ++i) {
1219 mWindowGlobalChild->BeforeUnloadRemoved();
1220 }
1221 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"
, 1221); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mWindowGlobalChild->BeforeUnloadListeners() == 0"
")"); do { *((volatile int*)__null) = 1221; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1222 }
1223
1224 // If we have any promiseDocumentFlushed callbacks, fire them now so
1225 // that the Promises can resolve.
1226 CallDocumentFlushedResolvers(/* aUntilExhaustion = */ true);
1227
1228 DisconnectGlobalTeardownObservers();
1229
1230#ifdef MOZ_WIDGET_ANDROID
1231 DisableOrientationChangeListener();
1232#endif
1233
1234 if (mObserver) {
1235 if (nsCOMPtr<nsIObserverService> os = services::GetObserverService()) {
1236 os->RemoveObserver(mObserver, NS_IOSERVICE_OFFLINE_STATUS_TOPIC"network:offline-status-changed");
1237 os->RemoveObserver(mObserver, MEMORY_PRESSURE_OBSERVER_TOPIC"memory-pressure");
1238 os->RemoveObserver(mObserver, PERMISSION_CHANGED_TOPIC"perm-changed");
1239 os->RemoveObserver(mObserver, "screen-information-changed");
1240 }
1241
1242 RefPtr<StorageNotifierService> sns = StorageNotifierService::GetOrCreate();
1243 if (sns) {
1244 sns->Unregister(mObserver);
1245 }
1246
1247 Preferences::RemoveObserver(mObserver, "intl.accept_languages");
1248
1249 // Drop its reference to this dying window, in case for some bogus reason
1250 // the object stays around.
1251 mObserver->Forget();
1252 }
1253
1254 mMenubar = nullptr;
1255 mToolbar = nullptr;
1256 mLocationbar = nullptr;
1257 mPersonalbar = nullptr;
1258 mStatusbar = nullptr;
1259 mScrollbars = nullptr;
1260
1261 mConsole = nullptr;
1262
1263 mPaintWorklet = nullptr;
1264
1265 mExternal = nullptr;
1266 mInstallTrigger = nullptr;
1267
1268 if (mLocalStorage) {
1269 mLocalStorage->Disconnect();
1270 mLocalStorage = nullptr;
1271 }
1272 mSessionStorage = nullptr;
1273 if (mPerformance) {
1274 // Since window is dying, nothing is going to be painted
1275 // with meaningful sizes, so these temp data for LCP is
1276 // no longer needed.
1277 static_cast<PerformanceMainThread*>(mPerformance.get())
1278 ->ClearGeneratedTempDataForLCP();
1279 }
1280 mPerformance = nullptr;
1281
1282 mContentMediaController = nullptr;
1283
1284 if (mWebTaskScheduler) {
1285 mWebTaskScheduler->Disconnect();
1286 mWebTaskScheduler = nullptr;
1287 }
1288
1289 mTrustedTypePolicyFactory = nullptr;
1290
1291 mSharedWorkers.Clear();
1292
1293#ifdef MOZ_WEBSPEECH1
1294 mSpeechSynthesis = nullptr;
1295#endif
1296
1297 mGlean = nullptr;
1298 mGleanPings = nullptr;
1299
1300 mParentTarget = nullptr;
1301
1302 if (mCleanMessageManager) {
1303 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"
, 1303); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIsChrome" ") ("
"only chrome should have msg manager cleaned" ")"); do { *((
volatile int*)__null) = 1303; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
1304 if (mChromeFields.mMessageManager) {
1305 mChromeFields.mMessageManager->Disconnect();
1306 }
1307 }
1308
1309 if (mWindowGlobalChild && !mWindowGlobalChild->IsClosed()) {
1310 mWindowGlobalChild->Destroy();
1311 }
1312
1313 mIntlUtils = nullptr;
1314
1315 HintIsLoading(false);
1316}
1317
1318//*****************************************************************************
1319// nsGlobalWindowInner::nsISupports
1320//*****************************************************************************
1321
1322// QueryInterface implementation for nsGlobalWindowInner
1323NS_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"
, 1323); 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
1324 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRYif (aIID.Equals((nsWrapperCache::COMTypeInfo<nsWrapperCache
, void>::kIID))) { *aInstancePtr = static_cast<nsWrapperCache
*>(this); return NS_OK; } else
1325 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
1326 NS_INTERFACE_MAP_ENTRY(nsIDOMWindow)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIDOMWindow>)) foundInterface = static_cast
<nsIDOMWindow*>(this); else
1327 NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIGlobalObject>)) foundInterface
= static_cast<nsIGlobalObject*>(this); else
1328 NS_INTERFACE_MAP_ENTRY(nsIScriptGlobalObject)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIScriptGlobalObject>)) foundInterface
= static_cast<nsIScriptGlobalObject*>(this); else
1329 NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIScriptObjectPrincipal>)) foundInterface
= static_cast<nsIScriptObjectPrincipal*>(this); else
1330 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
1331 NS_INTERFACE_MAP_ENTRY(nsPIDOMWindowInner)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsPIDOMWindowInner>)) foundInterface
= static_cast<nsPIDOMWindowInner*>(this); else
1332 NS_INTERFACE_MAP_ENTRY(mozIDOMWindow)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, mozIDOMWindow>)) foundInterface =
static_cast<mozIDOMWindow*>(this); else
1333 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupportsWeakReference>)) foundInterface
= static_cast<nsISupportsWeakReference*>(this); else
1334 NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIInterfaceRequestor>)) foundInterface
= static_cast<nsIInterfaceRequestor*>(this); else
1335NS_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"
, 1335); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIID.Equals((nsISupports::COMTypeInfo<nsISupports, void>::kIID))"
")"); do { *((volatile int*)__null) = 1335; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); status = NS_NOINTERFACE
; } else { (foundInterface)->AddRef(); status = NS_OK; } *
aInstancePtr = foundInterface; return status; }
1336
1337NS_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"
, 1337); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
1337; __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; }
1338NS_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"
, 1338); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 1338
; __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); }
1339
1340NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsGlobalWindowInner)bool nsGlobalWindowInner::cycleCollection::CanSkipReal(void* p
, bool aRemovingAllowed) { nsGlobalWindowInner* tmp = DowncastCCParticipant
<nsGlobalWindowInner>(p);
1341 if (tmp->IsBlackForCC(false)) {
1342 if (nsCCUncollectableMarker::InGeneration(tmp->mCanSkipCCGeneration)) {
1343 return true;
1344 }
1345 tmp->mCanSkipCCGeneration = nsCCUncollectableMarker::sGeneration;
1346 if (EventListenerManager* elm = tmp->GetExistingListenerManager()) {
1347 elm->MarkForCC();
1348 }
1349 if (tmp->mTimeoutManager) {
1350 tmp->mTimeoutManager->UnmarkGrayTimers();
1351 }
1352 return true;
1353 }
1354NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END(void)tmp; return false; }
1355
1356NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsGlobalWindowInner)bool nsGlobalWindowInner::cycleCollection::CanSkipInCCReal(void
* p) { nsGlobalWindowInner* tmp = DowncastCCParticipant<nsGlobalWindowInner
>(p);
1357 return tmp->IsBlackForCC(true);
1358NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END(void)tmp; return false; }
1359
1360NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsGlobalWindowInner)bool nsGlobalWindowInner::cycleCollection::CanSkipThisReal(void
* p) { nsGlobalWindowInner* tmp = DowncastCCParticipant<nsGlobalWindowInner
>(p);
1361 return tmp->IsBlackForCC(false);
1362NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END(void)tmp; return false; }
1363
1364NS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalWindowInner)nsGlobalWindowInner::cycleCollection nsGlobalWindowInner::_cycleCollectorGlobal
;
1365
1366NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGlobalWindowInner)nsresult nsGlobalWindowInner::cycleCollection::TraverseNative
( void* p, nsCycleCollectionTraversalCallback& cb) { nsGlobalWindowInner
* tmp = DowncastCCParticipant<nsGlobalWindowInner>(p);
1367 if (MOZ_UNLIKELY(cb.WantDebugInfo())(__builtin_expect(!!(cb.WantDebugInfo()), 0))) {
1368 char name[512];
1369 nsAutoCString uri;
1370 if (tmp->mDoc && tmp->mDoc->GetDocumentURI()) {
1371 uri = tmp->mDoc->GetDocumentURI()->GetSpecOrDefault();
1372 }
1373 SprintfLiteral(name, "nsGlobalWindowInner # %" PRIu64"l" "u" " inner %s",
1374 tmp->mWindowID, uri.get());
1375 cb.DescribeRefCountedNode(tmp->mRefCnt.get(), name);
1376 } else {
1377 NS_IMPL_CYCLE_COLLECTION_DESCRIBE(nsGlobalWindowInner, tmp->mRefCnt.get())cb.DescribeRefCountedNode(tmp->mRefCnt.get(), "nsGlobalWindowInner"
);
1378 }
1379
1380 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNavigator)ImplCycleCollectionTraverse(cb, tmp->mNavigator, "mNavigator"
, 0);
1381
1382 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPerformance)ImplCycleCollectionTraverse(cb, tmp->mPerformance, "mPerformance"
, 0);
1383
1384 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWebTaskScheduler)ImplCycleCollectionTraverse(cb, tmp->mWebTaskScheduler, "mWebTaskScheduler"
, 0);
1385
1386 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTrustedTypePolicyFactory)ImplCycleCollectionTraverse(cb, tmp->mTrustedTypePolicyFactory
, "mTrustedTypePolicyFactory", 0);
1387
1388#ifdef MOZ_WEBSPEECH1
1389 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSpeechSynthesis)ImplCycleCollectionTraverse(cb, tmp->mSpeechSynthesis, "mSpeechSynthesis"
, 0);
1390#endif
1391
1392 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlean)ImplCycleCollectionTraverse(cb, tmp->mGlean, "mGlean", 0);
1393 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGleanPings)ImplCycleCollectionTraverse(cb, tmp->mGleanPings, "mGleanPings"
, 0);
1394
1395 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOuterWindow)ImplCycleCollectionTraverse(cb, tmp->mOuterWindow, "mOuterWindow"
, 0);
1396
1397 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTopInnerWindow)ImplCycleCollectionTraverse(cb, tmp->mTopInnerWindow, "mTopInnerWindow"
, 0);
1398
1399 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mListenerManager)ImplCycleCollectionTraverse(cb, tmp->mListenerManager, "mListenerManager"
, 0);
1400
1401 if (tmp->mTimeoutManager) {
1402 tmp->mTimeoutManager->ForEachUnorderedTimeout([&cb](Timeout* timeout) {
1403 cb.NoteNativeChild(timeout, NS_CYCLE_COLLECTION_PARTICIPANT(Timeout)Timeout::cycleCollection::GetParticipant());
1404 });
1405 }
1406
1407 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocation)ImplCycleCollectionTraverse(cb, tmp->mLocation, "mLocation"
, 0);
1408 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mHistory)ImplCycleCollectionTraverse(cb, tmp->mHistory, "mHistory",
0);
1409 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCustomElements)ImplCycleCollectionTraverse(cb, tmp->mCustomElements, "mCustomElements"
, 0);
1410 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSharedWorkers)ImplCycleCollectionTraverse(cb, tmp->mSharedWorkers, "mSharedWorkers"
, 0);
1411 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocalStorage)ImplCycleCollectionTraverse(cb, tmp->mLocalStorage, "mLocalStorage"
, 0);
1412 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSessionStorage)ImplCycleCollectionTraverse(cb, tmp->mSessionStorage, "mSessionStorage"
, 0);
1413 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIndexedDB)ImplCycleCollectionTraverse(cb, tmp->mIndexedDB, "mIndexedDB"
, 0);
1414 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentPrincipal)ImplCycleCollectionTraverse(cb, tmp->mDocumentPrincipal, "mDocumentPrincipal"
, 0);
1415 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentCookiePrincipal)ImplCycleCollectionTraverse(cb, tmp->mDocumentCookiePrincipal
, "mDocumentCookiePrincipal", 0);
1416 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentStoragePrincipal)ImplCycleCollectionTraverse(cb, tmp->mDocumentStoragePrincipal
, "mDocumentStoragePrincipal", 0);
1417 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentPartitionedPrincipal)ImplCycleCollectionTraverse(cb, tmp->mDocumentPartitionedPrincipal
, "mDocumentPartitionedPrincipal", 0);
1418 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentCsp)ImplCycleCollectionTraverse(cb, tmp->mDocumentCsp, "mDocumentCsp"
, 0);
1419 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowserChild)ImplCycleCollectionTraverse(cb, tmp->mBrowserChild, "mBrowserChild"
, 0);
1420 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDoc)ImplCycleCollectionTraverse(cb, tmp->mDoc, "mDoc", 0);
1421
1422 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIdleRequestExecutor)ImplCycleCollectionTraverse(cb, tmp->mIdleRequestExecutor,
"mIdleRequestExecutor", 0);
1423 for (IdleRequest* request : tmp->mIdleRequestCallbacks) {
1424 cb.NoteNativeChild(request, NS_CYCLE_COLLECTION_PARTICIPANT(IdleRequest)IdleRequest::cycleCollection::GetParticipant());
1425 }
1426
1427 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mClientSource)ImplCycleCollectionTraverse(cb, tmp->mClientSource, "mClientSource"
, 0);
1428
1429 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGamepads)ImplCycleCollectionTraverse(cb, tmp->mGamepads, "mGamepads"
, 0);
1430
1431 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCacheStorage)ImplCycleCollectionTraverse(cb, tmp->mCacheStorage, "mCacheStorage"
, 0);
1432 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVRDisplays)ImplCycleCollectionTraverse(cb, tmp->mVRDisplays, "mVRDisplays"
, 0);
1433
1434 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDebuggerNotificationManager)ImplCycleCollectionTraverse(cb, tmp->mDebuggerNotificationManager
, "mDebuggerNotificationManager", 0);
1435
1436 // Traverse stuff from nsPIDOMWindow
1437 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeEventHandler)ImplCycleCollectionTraverse(cb, tmp->mChromeEventHandler, "mChromeEventHandler"
, 0);
1438 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParentTarget)ImplCycleCollectionTraverse(cb, tmp->mParentTarget, "mParentTarget"
, 0);
1439 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFocusedElement)ImplCycleCollectionTraverse(cb, tmp->mFocusedElement, "mFocusedElement"
, 0);
1440 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowsingContext)ImplCycleCollectionTraverse(cb, tmp->mBrowsingContext, "mBrowsingContext"
, 0);
1441 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindowGlobalChild)ImplCycleCollectionTraverse(cb, tmp->mWindowGlobalChild, "mWindowGlobalChild"
, 0);
1442
1443 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMenubar)ImplCycleCollectionTraverse(cb, tmp->mMenubar, "mMenubar",
0);
1444 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mToolbar)ImplCycleCollectionTraverse(cb, tmp->mToolbar, "mToolbar",
0);
1445 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocationbar)ImplCycleCollectionTraverse(cb, tmp->mLocationbar, "mLocationbar"
, 0);
1446 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPersonalbar)ImplCycleCollectionTraverse(cb, tmp->mPersonalbar, "mPersonalbar"
, 0);
1447 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStatusbar)ImplCycleCollectionTraverse(cb, tmp->mStatusbar, "mStatusbar"
, 0);
1448 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mScrollbars)ImplCycleCollectionTraverse(cb, tmp->mScrollbars, "mScrollbars"
, 0);
1449 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCrypto)ImplCycleCollectionTraverse(cb, tmp->mCrypto, "mCrypto", 0
);
1450 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConsole)ImplCycleCollectionTraverse(cb, tmp->mConsole, "mConsole",
0);
1451 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPaintWorklet)ImplCycleCollectionTraverse(cb, tmp->mPaintWorklet, "mPaintWorklet"
, 0);
1452 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mExternal)ImplCycleCollectionTraverse(cb, tmp->mExternal, "mExternal"
, 0);
1453 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mInstallTrigger)ImplCycleCollectionTraverse(cb, tmp->mInstallTrigger, "mInstallTrigger"
, 0);
1454 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIntlUtils)ImplCycleCollectionTraverse(cb, tmp->mIntlUtils, "mIntlUtils"
, 0);
1455 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVisualViewport)ImplCycleCollectionTraverse(cb, tmp->mVisualViewport, "mVisualViewport"
, 0);
1456 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCurrentPasteDataTransfer)ImplCycleCollectionTraverse(cb, tmp->mCurrentPasteDataTransfer
, "mCurrentPasteDataTransfer", 0);
1457
1458 tmp->TraverseObjectsInGlobal(cb);
1459
1460 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeFields.mMessageManager)ImplCycleCollectionTraverse(cb, tmp->mChromeFields.mMessageManager
, "mChromeFields.mMessageManager", 0);
1461 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeFields.mGroupMessageManagers)ImplCycleCollectionTraverse(cb, tmp->mChromeFields.mGroupMessageManagers
, "mChromeFields.mGroupMessageManagers", 0);
1462
1463 for (size_t i = 0; i < tmp->mDocumentFlushedResolvers.Length(); i++) {
1464 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentFlushedResolvers[i]->mPromise)ImplCycleCollectionTraverse(cb, tmp->mDocumentFlushedResolvers
[i]->mPromise, "mDocumentFlushedResolvers[i]->mPromise"
, 0);
;
1465 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentFlushedResolvers[i]->mCallback)ImplCycleCollectionTraverse(cb, tmp->mDocumentFlushedResolvers
[i]->mCallback, "mDocumentFlushedResolvers[i]->mCallback"
, 0);
;
1466 }
1467
1468NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END(void)tmp; return NS_OK; }
1469
1470NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindowInner)void nsGlobalWindowInner::cycleCollection::Unlink(void* p) { nsGlobalWindowInner
* tmp = DowncastCCParticipant<nsGlobalWindowInner>(p);
1471 NS_IMPL_CYCLE_COLLECTION_UNLINK_WEAK_REFERENCEtmp->ClearWeakReferences();
1472 if (sInnerWindowsById) {
1473 sInnerWindowsById->Remove(tmp->mWindowID);
1474 }
1475
1476 JSObject* wrapper = tmp->GetWrapperPreserveColor();
1477 if (wrapper) {
1478 // Mark our realm as dead, so the JS engine won't hand out our
1479 // global after this point.
1480 JS::SetRealmNonLive(js::GetNonCCWObjectRealm(wrapper));
1481 }
1482
1483 NS_IMPL_CYCLE_COLLECTION_UNLINK(mNavigator)ImplCycleCollectionUnlink(tmp->mNavigator);
1484
1485 NS_IMPL_CYCLE_COLLECTION_UNLINK(mPerformance)ImplCycleCollectionUnlink(tmp->mPerformance);
1486
1487 if (tmp->mWebTaskScheduler) {
1488 tmp->mWebTaskScheduler->Disconnect();
1489 NS_IMPL_CYCLE_COLLECTION_UNLINK(mWebTaskScheduler)ImplCycleCollectionUnlink(tmp->mWebTaskScheduler);
1490 }
1491
1492 NS_IMPL_CYCLE_COLLECTION_UNLINK(mTrustedTypePolicyFactory)ImplCycleCollectionUnlink(tmp->mTrustedTypePolicyFactory);
1493
1494#ifdef MOZ_WEBSPEECH1
1495 NS_IMPL_CYCLE_COLLECTION_UNLINK(mSpeechSynthesis)ImplCycleCollectionUnlink(tmp->mSpeechSynthesis);
1496#endif
1497
1498 NS_IMPL_CYCLE_COLLECTION_UNLINK(mGlean)ImplCycleCollectionUnlink(tmp->mGlean);
1499 NS_IMPL_CYCLE_COLLECTION_UNLINK(mGleanPings)ImplCycleCollectionUnlink(tmp->mGleanPings);
1500
1501 if (tmp->mOuterWindow) {
1502 nsGlobalWindowOuter::Cast(tmp->mOuterWindow)->MaybeClearInnerWindow(tmp);
1503 NS_IMPL_CYCLE_COLLECTION_UNLINK(mOuterWindow)ImplCycleCollectionUnlink(tmp->mOuterWindow);
1504 }
1505
1506 if (tmp->mListenerManager) {
1507 tmp->mListenerManager->Disconnect();
1508 NS_IMPL_CYCLE_COLLECTION_UNLINK(mListenerManager)ImplCycleCollectionUnlink(tmp->mListenerManager);
1509 }
1510
1511 // Here the Timeouts list would've been unlinked, but we rely on
1512 // that Timeout objects have been traced and will remove themselves
1513 // while unlinking.
1514
1515 tmp->UpdateTopInnerWindow();
1516 NS_IMPL_CYCLE_COLLECTION_UNLINK(mTopInnerWindow)ImplCycleCollectionUnlink(tmp->mTopInnerWindow);
1517
1518 NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocation)ImplCycleCollectionUnlink(tmp->mLocation);
1519 NS_IMPL_CYCLE_COLLECTION_UNLINK(mHistory)ImplCycleCollectionUnlink(tmp->mHistory);
1520 NS_IMPL_CYCLE_COLLECTION_UNLINK(mCustomElements)ImplCycleCollectionUnlink(tmp->mCustomElements);
1521 NS_IMPL_CYCLE_COLLECTION_UNLINK(mSharedWorkers)ImplCycleCollectionUnlink(tmp->mSharedWorkers);
1522 if (tmp->mLocalStorage) {
1523 tmp->mLocalStorage->Disconnect();
1524 NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocalStorage)ImplCycleCollectionUnlink(tmp->mLocalStorage);
1525 }
1526 NS_IMPL_CYCLE_COLLECTION_UNLINK(mSessionStorage)ImplCycleCollectionUnlink(tmp->mSessionStorage);
1527 NS_IMPL_CYCLE_COLLECTION_UNLINK(mIndexedDB)ImplCycleCollectionUnlink(tmp->mIndexedDB);
1528 NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentPrincipal)ImplCycleCollectionUnlink(tmp->mDocumentPrincipal);
1529 NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentCookiePrincipal)ImplCycleCollectionUnlink(tmp->mDocumentCookiePrincipal);
1530 NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentStoragePrincipal)ImplCycleCollectionUnlink(tmp->mDocumentStoragePrincipal);
1531 NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentPartitionedPrincipal)ImplCycleCollectionUnlink(tmp->mDocumentPartitionedPrincipal
);
1532 NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentCsp)ImplCycleCollectionUnlink(tmp->mDocumentCsp);
1533 NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowserChild)ImplCycleCollectionUnlink(tmp->mBrowserChild);
1534 NS_IMPL_CYCLE_COLLECTION_UNLINK(mDoc)ImplCycleCollectionUnlink(tmp->mDoc);
1535
1536 NS_IMPL_CYCLE_COLLECTION_UNLINK(mGamepads)ImplCycleCollectionUnlink(tmp->mGamepads);
1537
1538 NS_IMPL_CYCLE_COLLECTION_UNLINK(mCacheStorage)ImplCycleCollectionUnlink(tmp->mCacheStorage);
1539 NS_IMPL_CYCLE_COLLECTION_UNLINK(mVRDisplays)ImplCycleCollectionUnlink(tmp->mVRDisplays);
1540
1541 NS_IMPL_CYCLE_COLLECTION_UNLINK(mDebuggerNotificationManager)ImplCycleCollectionUnlink(tmp->mDebuggerNotificationManager
);
1542
1543 // Unlink stuff from nsPIDOMWindow
1544 NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeEventHandler)ImplCycleCollectionUnlink(tmp->mChromeEventHandler);
1545 NS_IMPL_CYCLE_COLLECTION_UNLINK(mParentTarget)ImplCycleCollectionUnlink(tmp->mParentTarget);
1546 NS_IMPL_CYCLE_COLLECTION_UNLINK(mFocusedElement)ImplCycleCollectionUnlink(tmp->mFocusedElement);
1547 NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowsingContext)ImplCycleCollectionUnlink(tmp->mBrowsingContext);
1548
1549 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"
, 1551); 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) = 1551; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1550 !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"
, 1551); 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) = 1551; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1551 "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"
, 1551); 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) = 1551; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1552 NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindowGlobalChild)ImplCycleCollectionUnlink(tmp->mWindowGlobalChild);
1553
1554 NS_IMPL_CYCLE_COLLECTION_UNLINK(mMenubar)ImplCycleCollectionUnlink(tmp->mMenubar);
1555 NS_IMPL_CYCLE_COLLECTION_UNLINK(mToolbar)ImplCycleCollectionUnlink(tmp->mToolbar);
1556 NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocationbar)ImplCycleCollectionUnlink(tmp->mLocationbar);
1557 NS_IMPL_CYCLE_COLLECTION_UNLINK(mPersonalbar)ImplCycleCollectionUnlink(tmp->mPersonalbar);
1558 NS_IMPL_CYCLE_COLLECTION_UNLINK(mStatusbar)ImplCycleCollectionUnlink(tmp->mStatusbar);
1559 NS_IMPL_CYCLE_COLLECTION_UNLINK(mScrollbars)ImplCycleCollectionUnlink(tmp->mScrollbars);
1560 NS_IMPL_CYCLE_COLLECTION_UNLINK(mCrypto)ImplCycleCollectionUnlink(tmp->mCrypto);
1561 NS_IMPL_CYCLE_COLLECTION_UNLINK(mConsole)ImplCycleCollectionUnlink(tmp->mConsole);
1562 NS_IMPL_CYCLE_COLLECTION_UNLINK(mPaintWorklet)ImplCycleCollectionUnlink(tmp->mPaintWorklet);
1563 NS_IMPL_CYCLE_COLLECTION_UNLINK(mExternal)ImplCycleCollectionUnlink(tmp->mExternal);
1564 NS_IMPL_CYCLE_COLLECTION_UNLINK(mInstallTrigger)ImplCycleCollectionUnlink(tmp->mInstallTrigger);
1565 NS_IMPL_CYCLE_COLLECTION_UNLINK(mIntlUtils)ImplCycleCollectionUnlink(tmp->mIntlUtils);
1566 NS_IMPL_CYCLE_COLLECTION_UNLINK(mVisualViewport)ImplCycleCollectionUnlink(tmp->mVisualViewport);
1567 NS_IMPL_CYCLE_COLLECTION_UNLINK(mCurrentPasteDataTransfer)ImplCycleCollectionUnlink(tmp->mCurrentPasteDataTransfer);
1568
1569 tmp->UnlinkObjectsInGlobal();
1570
1571 NS_IMPL_CYCLE_COLLECTION_UNLINK(mIdleRequestExecutor)ImplCycleCollectionUnlink(tmp->mIdleRequestExecutor);
1572
1573 // Here the IdleRequest list would've been unlinked, but we rely on
1574 // that IdleRequest objects have been traced and will remove
1575 // themselves while unlinking.
1576
1577 NS_IMPL_CYCLE_COLLECTION_UNLINK(mClientSource)ImplCycleCollectionUnlink(tmp->mClientSource);
1578
1579 if (tmp->IsChromeWindow()) {
1580 if (tmp->mChromeFields.mMessageManager) {
1581 static_cast<nsFrameMessageManager*>(
1582 tmp->mChromeFields.mMessageManager.get())
1583 ->Disconnect();
1584 NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeFields.mMessageManager)ImplCycleCollectionUnlink(tmp->mChromeFields.mMessageManager
);
1585 }
1586 tmp->DisconnectAndClearGroupMessageManagers();
1587 NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeFields.mGroupMessageManagers)ImplCycleCollectionUnlink(tmp->mChromeFields.mGroupMessageManagers
);
1588 }
1589
1590 for (size_t i = 0; i < tmp->mDocumentFlushedResolvers.Length(); i++) {
1591 NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentFlushedResolvers[i]->mPromise)ImplCycleCollectionUnlink(tmp->mDocumentFlushedResolvers[i
]->mPromise);
;
1592 NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentFlushedResolvers[i]->mCallback)ImplCycleCollectionUnlink(tmp->mDocumentFlushedResolvers[i
]->mCallback);
;
1593 }
1594 tmp->mDocumentFlushedResolvers.Clear();
1595
1596 NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPERtmp->ReleaseWrapper(p);
1597NS_IMPL_CYCLE_COLLECTION_UNLINK_END(void)tmp; }
1598
1599#ifdef DEBUG1
1600void nsGlobalWindowInner::RiskyUnlink() {
1601 NS_CYCLE_COLLECTION_INNERNAME_cycleCollectorGlobal.Unlink(this);
1602}
1603#endif
1604
1605NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsGlobalWindowInner)void nsGlobalWindowInner::cycleCollection::Trace( void* p, const
TraceCallbacks& aCallbacks, void* aClosure) { nsGlobalWindowInner
* tmp = DowncastCCParticipant<nsGlobalWindowInner>(p);
1606 NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPERtmp->TraceWrapper(aCallbacks, aClosure);
1607NS_IMPL_CYCLE_COLLECTION_TRACE_END(void)tmp; }
1608
1609bool nsGlobalWindowInner::IsBlackForCC(bool aTracingNeeded) {
1610 if (!nsCCUncollectableMarker::sGeneration) {
1611 return false;
1612 }
1613
1614 return (nsCCUncollectableMarker::InGeneration(GetMarkedCCGeneration()) ||
1615 HasKnownLiveWrapper()) &&
1616 (!aTracingNeeded || HasNothingToTrace(ToSupports(this)));
1617}
1618
1619//*****************************************************************************
1620// nsGlobalWindowInner::nsIScriptGlobalObject
1621//*****************************************************************************
1622
1623bool nsGlobalWindowInner::ShouldResistFingerprinting(RFPTarget aTarget) const {
1624 if (mDoc) {
1625 return mDoc->ShouldResistFingerprinting(aTarget);
1626 }
1627 return nsContentUtils::ShouldResistFingerprinting(
1628 "If we do not have a document then we do not have any context"
1629 "to make an informed RFP choice, so we fall back to the global pref",
1630 aTarget);
1631}
1632
1633OriginTrials nsGlobalWindowInner::Trials() const {
1634 return OriginTrials::FromWindow(this);
1635}
1636
1637FontFaceSet* nsGlobalWindowInner::GetFonts() {
1638 if (mDoc) {
1639 return mDoc->Fonts();
1640 }
1641 return nullptr;
1642}
1643
1644mozilla::Result<mozilla::ipc::PrincipalInfo, nsresult>
1645nsGlobalWindowInner::GetStorageKey() {
1646 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"
, 1646); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 1646; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1647
1648 nsIPrincipal* principal = GetEffectiveStoragePrincipal();
1649 if (!principal) {
1650 return mozilla::Err(NS_ERROR_FAILURE);
1651 }
1652
1653 mozilla::ipc::PrincipalInfo principalInfo;
1654 nsresult rv = PrincipalToPrincipalInfo(principal, &principalInfo);
1655 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1656 return mozilla::Err(rv);
1657 }
1658
1659 // Block expanded and null principals, let content and system through.
1660 if (principalInfo.type() !=
1661 mozilla::ipc::PrincipalInfo::TContentPrincipalInfo &&
1662 principalInfo.type() !=
1663 mozilla::ipc::PrincipalInfo::TSystemPrincipalInfo) {
1664 return Err(NS_ERROR_DOM_SECURITY_ERR);
1665 }
1666
1667 return std::move(principalInfo);
1668}
1669
1670mozilla::dom::StorageManager* nsGlobalWindowInner::GetStorageManager() {
1671 return Navigator()->Storage();
1672}
1673
1674// https://html.spec.whatwg.org/multipage/web-messaging.html#eligible-for-messaging
1675// * a Window object whose associated Document is fully active
1676bool nsGlobalWindowInner::IsEligibleForMessaging() { return IsFullyActive(); }
1677
1678nsresult nsGlobalWindowInner::EnsureScriptEnvironment() {
1679 // NOTE: We can't use FORWARD_TO_OUTER here because we don't want to fail if
1680 // we're called on an inactive inner window.
1681 nsGlobalWindowOuter* outer = GetOuterWindowInternal();
1682 if (!outer) {
1683 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"
, 1683)
;
1684 return NS_ERROR_FAILURE;
1685 }
1686 return outer->EnsureScriptEnvironment();
1687}
1688
1689nsIScriptContext* nsGlobalWindowInner::GetScriptContext() {
1690 nsGlobalWindowOuter* outer = GetOuterWindowInternal();
1691 if (!outer) {
1692 return nullptr;
1693 }
1694 return outer->GetScriptContext();
1695}
1696
1697void nsGlobalWindowInner::TraceGlobalJSObject(JSTracer* aTrc) {
1698 TraceWrapper(aTrc, "active window global");
1699}
1700
1701void nsGlobalWindowInner::UpdateAutoplayPermission() {
1702 if (!GetWindowContext()) {
1703 return;
1704 }
1705 uint32_t perm =
1706 media::AutoplayPolicy::GetSiteAutoplayPermission(GetPrincipal());
1707 if (GetWindowContext()->GetAutoplayPermission() == perm) {
1708 return;
1709 }
1710
1711 // Setting autoplay permission on a discarded context has no effect.
1712 Unused << GetWindowContext()->SetAutoplayPermission(perm);
1713}
1714
1715void nsGlobalWindowInner::UpdateShortcutsPermission() {
1716 if (!GetWindowContext() ||
1717 !GetWindowContext()->GetBrowsingContext()->IsTop()) {
1718 // We only cache the shortcuts permission on top-level WindowContexts
1719 // since we always check the top-level principal for the permission.
1720 return;
1721 }
1722
1723 uint32_t perm = GetShortcutsPermission(GetPrincipal());
1724
1725 if (GetWindowContext()->GetShortcutsPermission() == perm) {
1726 return;
1727 }
1728
1729 // If the WindowContext is discarded this has no effect.
1730 Unused << GetWindowContext()->SetShortcutsPermission(perm);
1731}
1732
1733/* static */
1734uint32_t nsGlobalWindowInner::GetShortcutsPermission(nsIPrincipal* aPrincipal) {
1735 uint32_t perm = nsIPermissionManager::DENY_ACTION;
1736 nsCOMPtr<nsIPermissionManager> permMgr =
1737 mozilla::components::PermissionManager::Service();
1738 if (aPrincipal && permMgr) {
1739 permMgr->TestExactPermissionFromPrincipal(aPrincipal, "shortcuts"_ns,
1740 &perm);
1741 }
1742 return perm;
1743}
1744
1745void nsGlobalWindowInner::UpdatePopupPermission() {
1746 if (!GetWindowContext()) {
1747 return;
1748 }
1749
1750 uint32_t perm = PopupBlocker::GetPopupPermission(GetPrincipal());
1751 if (GetWindowContext()->GetPopupPermission() == perm) {
1752 return;
1753 }
1754
1755 // If the WindowContext is discarded this has no effect.
1756 Unused << GetWindowContext()->SetPopupPermission(perm);
1757}
1758
1759void nsGlobalWindowInner::UpdatePermissions() {
1760 if (!GetWindowContext()) {
1761 return;
1762 }
1763
1764 nsCOMPtr<nsIPrincipal> principal = GetPrincipal();
1765 RefPtr<WindowContext> windowContext = GetWindowContext();
1766
1767 WindowContext::Transaction txn;
1768 txn.SetAutoplayPermission(
1769 media::AutoplayPolicy::GetSiteAutoplayPermission(principal));
1770 txn.SetPopupPermission(PopupBlocker::GetPopupPermission(principal));
1771
1772 if (windowContext->IsTop()) {
1773 txn.SetShortcutsPermission(GetShortcutsPermission(principal));
1774 }
1775
1776 // Setting permissions on a discarded WindowContext has no effect
1777 Unused << txn.Commit(windowContext);
1778}
1779
1780void nsGlobalWindowInner::InitDocumentDependentState(JSContext* aCx) {
1781 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"
, 1781); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDoc" ")");
do { *((volatile int*)__null) = 1781; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1782
1783 if (MOZ_LOG_TEST(gDOMLeakPRLogInner, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gDOMLeakPRLogInner
, LogLevel::Debug)), 0))
) {
1784 nsIURI* uri = mDoc->GetDocumentURI();
1785 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)
1786 ("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)
1787 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)
;
1788 }
1789
1790 mFocusedElement = nullptr;
1791 mLocalStorage = nullptr;
1792 mSessionStorage = nullptr;
1793 mPerformance = nullptr;
1794 if (mWebTaskScheduler) {
1795 mWebTaskScheduler->Disconnect();
1796 mWebTaskScheduler = nullptr;
1797 }
1798
1799 // This must be called after nullifying the internal objects because here we
1800 // could recreate them, calling the getter methods, and store them into the JS
1801 // slots. If we nullify them after, the slot values and the objects will be
1802 // out of sync.
1803 ClearDocumentDependentSlots(aCx);
1804
1805 if (!mWindowGlobalChild) {
1806 mWindowGlobalChild = WindowGlobalChild::Create(this);
1807 }
1808 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"
, 1810); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!GetWindowContext()->HasBeenUserGestureActivated()"
") (" "WindowContext should always not have user gesture activation at "
"this point." ")"); do { *((volatile int*)__null) = 1810; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
1809 "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"
, 1810); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!GetWindowContext()->HasBeenUserGestureActivated()"
") (" "WindowContext should always not have user gesture activation at "
"this point." ")"); do { *((volatile int*)__null) = 1810; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
1810 "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"
, 1810); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!GetWindowContext()->HasBeenUserGestureActivated()"
") (" "WindowContext should always not have user gesture activation at "
"this point." ")"); do { *((volatile int*)__null) = 1810; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
1811
1812 UpdatePermissions();
1813
1814 RefPtr<PermissionDelegateHandler> permDelegateHandler =
1815 mDoc->GetPermissionDelegateHandler();
1816
1817 if (permDelegateHandler) {
1818 permDelegateHandler->PopulateAllDelegatedPermissions();
1819 }
1820
1821#if defined(MOZ_WIDGET_ANDROID)
1822 // When we insert the new document to the window in the top-level browsing
1823 // context, we should reset the status of the request which is used for the
1824 // previous document.
1825 if (mWindowGlobalChild && GetBrowsingContext() &&
1826 !GetBrowsingContext()->GetParent()) {
1827 // Return value of setting synced field should be checked. See bug 1656492.
1828 Unused << GetBrowsingContext()->ResetGVAutoplayRequestStatus();
1829 }
1830#endif
1831
1832#ifdef DEBUG1
1833 mLastOpenedURI = mDoc->GetDocumentURI();
1834#endif
1835
1836 Telemetry::Accumulate(Telemetry::INNERWINDOWS_WITH_MUTATION_LISTENERS,
1837 mMutationBits ? 1 : 0);
1838
1839 // Clear our mutation bitfield.
1840 mMutationBits = 0;
1841}
1842
1843nsresult nsGlobalWindowInner::EnsureClientSource() {
1844 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"
, 1844); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mDoc"
")"); do { *((volatile int*)__null) = 1844; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1845
1846 bool newClientSource = false;
1847
1848 // Get the load info for the document if we performed a load. Be careful not
1849 // to look at local URLs, though. Local URLs are those that have a scheme of:
1850 // * about:
1851 // * data:
1852 // * blob:
1853 // We also do an additional check here so that we only treat about:blank
1854 // and about:srcdoc as local URLs. Other internal firefox about: URLs should
1855 // not be treated this way.
1856 nsCOMPtr<nsILoadInfo> loadInfo;
1857 nsCOMPtr<nsIChannel> channel = mDoc->GetChannel();
1858 if (channel) {
1859 nsCOMPtr<nsIURI> uri;
1860 Unused << channel->GetURI(getter_AddRefs(uri));
1861
1862 bool ignoreLoadInfo = false;
1863
1864 // Note, this is mostly copied from NS_IsAboutBlank(). Its duplicated
1865 // here so we can efficiently check about:srcdoc as well.
1866 if (uri->SchemeIs("about")) {
1867 nsCString spec = uri->GetSpecOrDefault();
1868 ignoreLoadInfo = spec.EqualsLiteral("about:blank") ||
1869 spec.EqualsLiteral("about:srcdoc");
1870 } else {
1871 // Its not an about: URL, so now check for our other URL types.
1872 ignoreLoadInfo = uri->SchemeIs("data") || uri->SchemeIs("blob");
1873 }
1874
1875 if (!ignoreLoadInfo) {
1876 loadInfo = channel->LoadInfo();
1877 }
1878 }
1879
1880 // Take the initial client source from the docshell immediately. Even if we
1881 // don't end up using it here we should consume it.
1882 UniquePtr<ClientSource> initialClientSource;
1883 nsIDocShell* docshell = GetDocShell();
1884 if (docshell) {
1885 initialClientSource = docshell->TakeInitialClientSource();
1886 }
1887
1888 // Try to get the reserved client from the LoadInfo. A Client is
1889 // reserved at the start of the channel load if there is not an
1890 // initial about:blank document that will be reused. It is also
1891 // created if the channel load encounters a cross-origin redirect.
1892 if (loadInfo) {
1893 UniquePtr<ClientSource> reservedClient =
1894 loadInfo->TakeReservedClientSource();
1895 if (reservedClient) {
1896 mClientSource.reset();
1897 mClientSource = std::move(reservedClient);
1898 newClientSource = true;
1899 }
1900 }
1901
1902 // We don't have a LoadInfo reserved client, but maybe we should
1903 // be inheriting an initial one from the docshell. This means
1904 // that the docshell started the channel load before creating the
1905 // initial about:blank document. This is an optimization, though,
1906 // and it created an initial Client as a placeholder for the document.
1907 // In this case we want to inherit this placeholder Client here.
1908 if (!mClientSource) {
1909 mClientSource = std::move(initialClientSource);
1910 if (mClientSource) {
1911 newClientSource = true;
1912 }
1913 }
1914
1915 nsCOMPtr<nsIPrincipal> foreignPartitionedPrincipal;
1916
1917 nsresult rv = StoragePrincipalHelper::GetPrincipal(
1918 this,
1919 StaticPrefs::privacy_partition_serviceWorkers()
1920 ? StoragePrincipalHelper::eForeignPartitionedPrincipal
1921 : StoragePrincipalHelper::eRegularPrincipal,
1922 getter_AddRefs(foreignPartitionedPrincipal));
1923 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"
, 1923); return rv; } } while (false)
;
1924
1925 // Verify the final ClientSource principal matches the final document
1926 // principal. The ClientChannelHelper handles things like network
1927 // redirects, but there are other ways the document principal can change.
1928 // For example, if something sets the nsIChannel.owner property, then
1929 // the final channel principal can be anything. Unfortunately there is
1930 // no good way to detect this until after the channel completes loading.
1931 //
1932 // For now we handle this just by reseting the ClientSource. This will
1933 // result in a new ClientSource with the correct principal being created.
1934 // To APIs like ServiceWorker and Clients API it will look like there was
1935 // an initial content page created that was then immediately replaced.
1936 // This is pretty close to what we are actually doing.
1937 if (mClientSource) {
1938 auto principalOrErr = mClientSource->Info().GetPrincipal();
1939 nsCOMPtr<nsIPrincipal> clientPrincipal =
1940 principalOrErr.isOk() ? principalOrErr.unwrap() : nullptr;
1941 if (!clientPrincipal ||
1942 !clientPrincipal->Equals(foreignPartitionedPrincipal)) {
1943 mClientSource.reset();
1944 }
1945 }
1946
1947 // If we don't have a reserved client or an initial client, then create
1948 // one now. This can happen in certain cases where we avoid preallocating
1949 // the client in the docshell. This mainly occurs in situations where
1950 // the principal is not clearly inherited from the parent; e.g. sandboxed
1951 // iframes, window.open(), etc.
1952 //
1953 // We also do this late ClientSource creation if the final document ended
1954 // up with a different principal.
1955 //
1956 // TODO: We may not be marking initial about:blank documents created
1957 // this way as controlled by a service worker properly. The
1958 // controller should be coming from the same place as the inheritted
1959 // principal. We do this in docshell, but as mentioned we aren't
1960 // smart enough to handle all cases yet. For example, a
1961 // window.open() with new URL should inherit the controller from
1962 // the opener, but we probably don't handle that yet.
1963 if (!mClientSource) {
1964 mClientSource = ClientManager::CreateSource(
1965 ClientType::Window, SerialEventTarget(), foreignPartitionedPrincipal);
1966 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"
, 1966); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mClientSource"
")"); do { *((volatile int*)__null) = 1966; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1967 newClientSource = true;
1968
1969 // Note, we don't apply the loadinfo controller below if we create
1970 // the ClientSource here.
1971 }
1972
1973 // The load may have started controlling the Client as well. If
1974 // so, mark it as controlled immediately here. The actor may
1975 // or may not have been notified by the parent side about being
1976 // controlled yet.
1977 //
1978 // Note: We should be careful not to control a client that was created late.
1979 // These clients were not seen by the ServiceWorkerManager when it
1980 // marked the LoadInfo controlled and it won't know about them. Its
1981 // also possible we are creating the client late due to the final
1982 // principal changing and these clients should definitely not be
1983 // controlled by a service worker with a different principal.
1984 else if (loadInfo) {
1985 const Maybe<ServiceWorkerDescriptor> controller = loadInfo->GetController();
1986 if (controller.isSome()) {
1987 mClientSource->SetController(controller.ref());
1988 }
1989
1990 // We also have to handle the case where te initial about:blank is
1991 // controlled due to inheritting the service worker from its parent,
1992 // but the actual nsIChannel load is not covered by any service worker.
1993 // In this case we want the final page to be uncontrolled. There is
1994 // an open spec issue about how exactly this should be handled, but for
1995 // now we just force creation of a new ClientSource to clear the
1996 // controller.
1997 //
1998 // https://github.com/w3c/ServiceWorker/issues/1232
1999 //
2000 else if (mClientSource->GetController().isSome()) {
2001 mClientSource.reset();
2002 mClientSource = ClientManager::CreateSource(
2003 ClientType::Window, SerialEventTarget(), foreignPartitionedPrincipal);
2004 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"
, 2004); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mClientSource"
")"); do { *((volatile int*)__null) = 2004; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2005 newClientSource = true;
2006 }
2007 }
2008
2009 if (mClientSource) {
2010 // Generally the CSP is stored within the Client and cached on the document.
2011 // At the time of CSP parsing however, the Client has not been created yet,
2012 // hence we store the CSP on the document and propagate/sync the CSP with
2013 // Client here when we create the Client.
2014 mClientSource->SetCsp(mDoc->GetCsp());
2015
2016 DocGroup* docGroup = GetDocGroup();
2017 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"
, 2017); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "docGroup"
")"); do { *((volatile int*)__null) = 2017; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2018 mClientSource->SetAgentClusterId(docGroup->AgentClusterId());
2019
2020 if (mWindowGlobalChild) {
2021 mWindowGlobalChild->SendSetClientInfo(mClientSource->Info().ToIPC());
2022 }
2023 }
2024
2025 // Its possible that we got a client just after being frozen in
2026 // the bfcache. In that case freeze the client immediately.
2027 if (newClientSource && IsFrozen()) {
2028 mClientSource->Freeze();
2029 }
2030
2031 return NS_OK;
2032}
2033
2034nsresult nsGlobalWindowInner::ExecutionReady() {
2035 nsresult rv = EnsureClientSource();
2036 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"
, 2036); return rv; } } while (false)
;
2037
2038 rv = mClientSource->WindowExecutionReady(this);
2039 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"
, 2039); return rv; } } while (false)
;
2040
2041 return NS_OK;
2042}
2043
2044void nsGlobalWindowInner::UpdateParentTarget() {
2045 // NOTE: This method is identical to
2046 // nsGlobalWindowOuter::UpdateParentTarget(). IF YOU UPDATE THIS METHOD,
2047 // UPDATE THE OTHER ONE TOO!
2048
2049 // Try to get our frame element's tab child global (its in-process message
2050 // manager). If that fails, fall back to the chrome event handler's tab
2051 // child global, and if it doesn't have one, just use the chrome event
2052 // handler itself.
2053
2054 nsPIDOMWindowOuter* outer = GetOuterWindow();
2055 if (!outer) {
2056 return;
2057 }
2058 nsCOMPtr<Element> frameElement = outer->GetFrameElementInternal();
2059 nsCOMPtr<EventTarget> eventTarget =
2060 nsContentUtils::TryGetBrowserChildGlobal(frameElement);
2061
2062 if (!eventTarget) {
2063 nsGlobalWindowOuter* topWin = GetInProcessScriptableTopInternal();
2064 if (topWin) {
2065 frameElement = topWin->GetFrameElementInternal();
2066 eventTarget = nsContentUtils::TryGetBrowserChildGlobal(frameElement);
2067 }
2068 }
2069
2070 if (!eventTarget) {
2071 eventTarget = nsContentUtils::TryGetBrowserChildGlobal(mChromeEventHandler);
2072 }
2073
2074 if (!eventTarget) {
2075 eventTarget = mChromeEventHandler;
2076 }
2077
2078 mParentTarget = eventTarget;
2079}
2080
2081EventTarget* nsGlobalWindowInner::GetTargetForDOMEvent() {
2082 return GetOuterWindowInternal();
2083}
2084
2085void nsGlobalWindowInner::GetEventTargetParent(EventChainPreVisitor& aVisitor) {
2086 EventMessage msg = aVisitor.mEvent->mMessage;
2087
2088 aVisitor.mCanHandle = true;
2089 aVisitor.mForceContentDispatch = true; // FIXME! Bug 329119
2090 if (msg == eResize && aVisitor.mEvent->IsTrusted()) {
2091 // Checking whether the event target is an inner window or not, so we can
2092 // keep the old behavior also in case a child window is handling resize.
2093 if (aVisitor.mEvent->mOriginalTarget &&
2094 aVisitor.mEvent->mOriginalTarget->IsInnerWindow()) {
2095 mIsHandlingResizeEvent = true;
2096 }
2097 } else if (msg == eMouseDown && aVisitor.mEvent->IsTrusted()) {
2098 sMouseDown = true;
2099 } else if ((msg == eMouseUp || msg == eDragEnd) &&
2100 aVisitor.mEvent->IsTrusted()) {
2101 sMouseDown = false;
2102 if (sDragServiceDisabled) {
2103 nsCOMPtr<nsIDragService> ds =
2104 do_GetService("@mozilla.org/widget/dragservice;1");
2105 if (ds) {
2106 sDragServiceDisabled = false;
2107 ds->Unsuppress();
2108 }
2109 }
2110 }
2111
2112 aVisitor.SetParentTarget(GetParentTarget(), true);
2113}
2114
2115void nsGlobalWindowInner::FireFrameLoadEvent() {
2116 // If we're not in a content frame, or are at a BrowsingContext tree boundary,
2117 // such as the content-chrome boundary, don't fire the "load" event.
2118 if (GetBrowsingContext()->IsTopContent() ||
2119 GetBrowsingContext()->IsChrome()) {
2120 return;
2121 }
2122
2123 // If embedder is same-process, fire the event on our embedder element.
2124 //
2125 // XXX: Bug 1440212 is looking into potentially changing this behaviour to act
2126 // more like the remote case when in-process.
2127 RefPtr<Element> element = GetBrowsingContext()->GetEmbedderElement();
2128 if (element) {
2129 nsEventStatus status = nsEventStatus_eIgnore;
2130 WidgetEvent event(/* aIsTrusted = */ true, eLoad);
2131 event.mFlags.mBubbles = false;
2132 event.mFlags.mCancelable = false;
2133
2134 // Most of the time we could get a pres context to pass in here, but not
2135 // always (i.e. if this window is not shown there won't be a pres context
2136 // available). Since we're not firing a GUI event we don't need a pres
2137 // context anyway so we just pass null as the pres context all the time.
2138 EventDispatcher::Dispatch(element, nullptr, &event, nullptr, &status);
2139 return;
2140 }
2141
2142 // We don't have an in-process embedder. Try to get our `BrowserChild` actor
2143 // to send a message to that embedder. We want to double-check that our outer
2144 // window is actually the one at the root of this browserChild though, just in
2145 // case.
2146 RefPtr<BrowserChild> browserChild =
2147 BrowserChild::GetFrom(static_cast<nsPIDOMWindowInner*>(this));
2148 if (browserChild &&
2149 !GetBrowsingContext()->GetParentWindowContext()->IsInProcess()) {
2150 // Double-check that our outer window is actually at the root of this
2151 // `BrowserChild`, in case we're in an odd maybe-unhosted situation like a
2152 // print preview dialog.
2153 nsCOMPtr<nsPIDOMWindowOuter> rootOuter =
2154 do_GetInterface(browserChild->WebNavigation());
2155 if (!rootOuter || rootOuter != GetOuterWindow()) {
2156 return;
2157 }
2158
2159 mozilla::Unused << browserChild->SendMaybeFireEmbedderLoadEvents(
2160 EmbedderElementEventType::LoadEvent);
2161 }
2162}
2163
2164nsresult nsGlobalWindowInner::PostHandleEvent(EventChainPostVisitor& aVisitor) {
2165 // Return early if there is nothing to do.
2166 switch (aVisitor.mEvent->mMessage) {
2167 case eResize:
2168 case eUnload:
2169 case eLoad:
2170 break;
2171 default:
2172 return NS_OK;
2173 }
2174
2175 /* mChromeEventHandler and mContext go dangling in the middle of this
2176 function under some circumstances (events that destroy the window)
2177 without this addref. */
2178 RefPtr<EventTarget> kungFuDeathGrip1(mChromeEventHandler);
2179 mozilla::Unused
2180 << kungFuDeathGrip1; // These aren't referred to through the function
2181 nsCOMPtr<nsIScriptContext> kungFuDeathGrip2(GetContextInternal());
2182 mozilla::Unused
2183 << kungFuDeathGrip2; // These aren't referred to through the function
2184
2185 if (aVisitor.mEvent->mMessage == eResize) {
2186 mIsHandlingResizeEvent = false;
2187 } else if (aVisitor.mEvent->mMessage == eUnload &&
2188 aVisitor.mEvent->IsTrusted()) {
2189 // If any VR display presentation is active at unload, the next page
2190 // will receive a vrdisplayactive event to indicate that it should
2191 // immediately begin vr presentation. This should occur when navigating
2192 // forwards, navigating backwards, and on page reload.
2193 for (const auto& display : mVRDisplays) {
2194 if (display->IsPresenting()) {
2195 display->StartVRNavigation();
2196 // Save this VR display ID to trigger vrdisplayactivate event
2197 // after the next load event.
2198 nsGlobalWindowOuter* outer = GetOuterWindowInternal();
2199 if (outer) {
2200 outer->SetAutoActivateVRDisplayID(display->DisplayId());
2201 }
2202
2203 // XXX The WebVR 1.1 spec does not define which of multiple VR
2204 // presenting VR displays will be chosen during navigation.
2205 // As the underlying platform VR API's currently only allow a single
2206 // VR display, it is safe to choose the first VR display for now.
2207 break;
2208 }
2209 }
2210 mIsDocumentLoaded = false;
2211 // Tell the parent process that the document is not loaded.
2212 if (mWindowGlobalChild) {
2213 mWindowGlobalChild->SendUpdateDocumentHasLoaded(mIsDocumentLoaded);
2214 }
2215 } else if (aVisitor.mEvent->mMessage == eLoad &&
2216 aVisitor.mEvent->IsTrusted()) {
2217 // This is page load event since load events don't propagate to |window|.
2218 // @see Document::GetEventTargetParent.
2219 mIsDocumentLoaded = true;
2220 // Tell the parent process that the document is loaded.
2221 if (mWindowGlobalChild) {
2222 mWindowGlobalChild->SendUpdateDocumentHasLoaded(mIsDocumentLoaded);
2223 }
2224
2225 mTimeoutManager->OnDocumentLoaded();
2226
2227 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"
, 2227); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aVisitor.mEvent->IsTrusted()"
")"); do { *((volatile int*)__null) = 2227; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2228 FireFrameLoadEvent();
2229
2230 if (mVREventObserver) {
2231 mVREventObserver->NotifyAfterLoad();
2232 }
2233
2234 uint32_t autoActivateVRDisplayID = 0;
2235 nsGlobalWindowOuter* outer = GetOuterWindowInternal();
2236 if (outer) {
2237 autoActivateVRDisplayID = outer->GetAutoActivateVRDisplayID();
2238 }
2239 if (autoActivateVRDisplayID) {
2240 DispatchVRDisplayActivate(autoActivateVRDisplayID,
2241 VRDisplayEventReason::Navigation);
2242 }
2243 }
2244
2245 return NS_OK;
2246}
2247
2248nsresult nsGlobalWindowInner::DefineArgumentsProperty(nsIArray* aArguments) {
2249 nsIScriptContext* ctx = GetOuterWindowInternal()->mContext;
2250 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"
, 2250); return NS_ERROR_NOT_INITIALIZED; } } while (false)
;
2251
2252 JS::Rooted<JSObject*> obj(RootingCx(), GetWrapperPreserveColor());
2253 return ctx->SetProperty(obj, "arguments", aArguments);
2254}
2255
2256//*****************************************************************************
2257// nsGlobalWindowInner::nsIScriptObjectPrincipal
2258//*****************************************************************************
2259
2260nsIPrincipal* nsGlobalWindowInner::GetPrincipal() {
2261 if (mDoc) {
2262 // If we have a document, get the principal from the document
2263 return mDoc->NodePrincipal();
2264 }
2265
2266 if (mDocumentPrincipal) {
2267 return mDocumentPrincipal;
2268 }
2269
2270 // If we don't have a principal and we don't have a document we
2271 // ask the parent window for the principal. This can happen when
2272 // loading a frameset that has a <frame src="javascript:xxx">, in
2273 // that case the global window is used in JS before we've loaded
2274 // a document into the window.
2275
2276 nsCOMPtr<nsIScriptObjectPrincipal> objPrincipal =
2277 do_QueryInterface(GetInProcessParentInternal());
2278
2279 if (objPrincipal) {
2280 return objPrincipal->GetPrincipal();
2281 }
2282
2283 return nullptr;
2284}
2285
2286nsIPrincipal* nsGlobalWindowInner::GetEffectiveCookiePrincipal() {
2287 if (mDoc) {
2288 // If we have a document, get the principal from the document
2289 return mDoc->EffectiveCookiePrincipal();
2290 }
2291
2292 if (mDocumentCookiePrincipal) {
2293 return mDocumentCookiePrincipal;
2294 }
2295
2296 // If we don't have a cookie principal and we don't have a document we ask
2297 // the parent window for the cookie principal.
2298
2299 nsCOMPtr<nsIScriptObjectPrincipal> objPrincipal =
2300 do_QueryInterface(GetInProcessParentInternal());
2301
2302 if (objPrincipal) {
2303 return objPrincipal->GetEffectiveCookiePrincipal();
2304 }
2305
2306 return nullptr;
2307}
2308
2309nsIPrincipal* nsGlobalWindowInner::GetEffectiveStoragePrincipal() {
2310 if (mDoc) {
2311 // If we have a document, get the principal from the document
2312 return mDoc->EffectiveStoragePrincipal();
2313 }
2314
2315 if (mDocumentStoragePrincipal) {
2316 return mDocumentStoragePrincipal;
2317 }
2318
2319 // If we don't have a cookie principal and we don't have a document we ask
2320 // the parent window for the cookie principal.
2321
2322 nsCOMPtr<nsIScriptObjectPrincipal> objPrincipal =
2323 do_QueryInterface(GetInProcessParentInternal());
2324
2325 if (objPrincipal) {
2326 return objPrincipal->GetEffectiveStoragePrincipal();
2327 }
2328
2329 return nullptr;
2330}
2331
2332nsIPrincipal* nsGlobalWindowInner::PartitionedPrincipal() {
2333 if (mDoc) {
2334 // If we have a document, get the principal from the document
2335 return mDoc->PartitionedPrincipal();
2336 }
2337
2338 if (mDocumentPartitionedPrincipal) {
2339 return mDocumentPartitionedPrincipal;
2340 }
2341
2342 // If we don't have a partitioned principal and we don't have a document we
2343 // ask the parent window for the partitioned principal.
2344
2345 nsCOMPtr<nsIScriptObjectPrincipal> objPrincipal =
2346 do_QueryInterface(GetInProcessParentInternal());
2347
2348 if (objPrincipal) {
2349 return objPrincipal->PartitionedPrincipal();
2350 }
2351
2352 return nullptr;
2353}
2354
2355//*****************************************************************************
2356// nsGlobalWindowInner::nsIDOMWindow
2357//*****************************************************************************
2358
2359bool nsPIDOMWindowInner::AddAudioContext(AudioContext* aAudioContext) {
2360 mAudioContexts.AppendElement(aAudioContext);
2361
2362 // Return true if the context should be muted and false if not.
2363 nsIDocShell* docShell = GetDocShell();
2364 return docShell && !docShell->GetAllowMedia() && !aAudioContext->IsOffline();
2365}
2366
2367void nsPIDOMWindowInner::RemoveAudioContext(AudioContext* aAudioContext) {
2368 mAudioContexts.RemoveElement(aAudioContext);
2369}
2370
2371void nsPIDOMWindowInner::MuteAudioContexts() {
2372 for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) {
2373 if (!mAudioContexts[i]->IsOffline()) {
2374 mAudioContexts[i]->Mute();
2375 }
2376 }
2377}
2378
2379void nsPIDOMWindowInner::UnmuteAudioContexts() {
2380 for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) {
2381 if (!mAudioContexts[i]->IsOffline()) {
2382 mAudioContexts[i]->Unmute();
2383 }
2384 }
2385}
2386
2387WindowProxyHolder nsGlobalWindowInner::Window() {
2388 return WindowProxyHolder(GetBrowsingContext());
2389}
2390
2391Navigator* nsPIDOMWindowInner::Navigator() {
2392 if (!mNavigator) {
2393 mNavigator = new mozilla::dom::Navigator(this);
2394 }
2395
2396 return mNavigator;
2397}
2398
2399MediaDevices* nsPIDOMWindowInner::GetExtantMediaDevices() const {
2400 return mNavigator ? mNavigator->GetExtantMediaDevices() : nullptr;
2401}
2402
2403VisualViewport* nsGlobalWindowInner::VisualViewport() {
2404 if (!mVisualViewport) {
2405 mVisualViewport = new mozilla::dom::VisualViewport(this);
2406 }
2407 return mVisualViewport;
2408}
2409
2410nsScreen* nsGlobalWindowInner::Screen() {
2411 if (!mScreen) {
2412 mScreen = new nsScreen(this);
2413 }
2414 return mScreen;
2415}
2416
2417nsHistory* nsGlobalWindowInner::GetHistory(ErrorResult& aError) {
2418 if (!mHistory) {
2419 mHistory = new nsHistory(this);
2420 }
2421 return mHistory;
2422}
2423
2424CustomElementRegistry* nsGlobalWindowInner::CustomElements() {
2425 if (!mCustomElements) {
2426 mCustomElements = new CustomElementRegistry(this);
2427 }
2428
2429 return mCustomElements;
2430}
2431
2432CustomElementRegistry* nsGlobalWindowInner::GetExistingCustomElements() {
2433 return mCustomElements;
2434}
2435
2436Performance* nsPIDOMWindowInner::GetPerformance() {
2437 CreatePerformanceObjectIfNeeded();
2438 return mPerformance;
2439}
2440
2441void nsPIDOMWindowInner::QueuePerformanceNavigationTiming() {
2442 CreatePerformanceObjectIfNeeded();
2443 if (mPerformance) {
2444 mPerformance->QueueNavigationTimingEntry();
2445 }
2446}
2447
2448void nsPIDOMWindowInner::CreatePerformanceObjectIfNeeded() {
2449 if (mPerformance || !mDoc) {
2450 return;
2451 }
2452 RefPtr<nsDOMNavigationTiming> timing = mDoc->GetNavigationTiming();
2453 nsCOMPtr<nsITimedChannel> timedChannel(do_QueryInterface(mDoc->GetChannel()));
2454 bool timingEnabled = false;
2455 if (!timedChannel ||
2456 !NS_SUCCEEDED(timedChannel->GetTimingEnabled(&timingEnabled))((bool)(__builtin_expect(!!(!NS_FAILED_impl(timedChannel->
GetTimingEnabled(&timingEnabled))), 1)))
||
2457 !timingEnabled) {
2458 timedChannel = nullptr;
2459 }
2460 if (timing) {
2461 mPerformance = Performance::CreateForMainThread(this, mDoc->NodePrincipal(),
2462 timing, timedChannel);
2463 }
2464}
2465
2466bool nsPIDOMWindowInner::IsSecureContext() const {
2467 return nsGlobalWindowInner::Cast(this)->IsSecureContext();
2468}
2469
2470void nsPIDOMWindowInner::Suspend(bool aIncludeSubWindows) {
2471 nsGlobalWindowInner::Cast(this)->Suspend(aIncludeSubWindows);
2472}
2473
2474void nsPIDOMWindowInner::Resume(bool aIncludeSubWindows) {
2475 nsGlobalWindowInner::Cast(this)->Resume(aIncludeSubWindows);
2476}
2477
2478void nsPIDOMWindowInner::SyncStateFromParentWindow() {
2479 nsGlobalWindowInner::Cast(this)->SyncStateFromParentWindow();
2480}
2481
2482Maybe<ClientInfo> nsPIDOMWindowInner::GetClientInfo() const {
2483 return nsGlobalWindowInner::Cast(this)->GetClientInfo();
2484}
2485
2486Maybe<ClientState> nsPIDOMWindowInner::GetClientState() const {
2487 return nsGlobalWindowInner::Cast(this)->GetClientState();
2488}
2489
2490Maybe<ServiceWorkerDescriptor> nsPIDOMWindowInner::GetController() const {
2491 return nsGlobalWindowInner::Cast(this)->GetController();
2492}
2493
2494void nsPIDOMWindowInner::SetCsp(nsIContentSecurityPolicy* aCsp) {
2495 return nsGlobalWindowInner::Cast(this)->SetCsp(aCsp);
2496}
2497
2498void nsPIDOMWindowInner::SetPreloadCsp(nsIContentSecurityPolicy* aPreloadCsp) {
2499 return nsGlobalWindowInner::Cast(this)->SetPreloadCsp(aPreloadCsp);
2500}
2501
2502nsIContentSecurityPolicy* nsPIDOMWindowInner::GetCsp() {
2503 return nsGlobalWindowInner::Cast(this)->GetCsp();
2504}
2505
2506void nsPIDOMWindowInner::NoteCalledRegisterForServiceWorkerScope(
2507 const nsACString& aScope) {
2508 nsGlobalWindowInner::Cast(this)->NoteCalledRegisterForServiceWorkerScope(
2509 aScope);
2510}
2511
2512void nsPIDOMWindowInner::NoteDOMContentLoaded() {
2513 nsGlobalWindowInner::Cast(this)->NoteDOMContentLoaded();
2514}
2515
2516bool nsGlobalWindowInner::ShouldReportForServiceWorkerScope(
2517 const nsAString& aScope) {
2518 bool result = false;
2519
2520 nsPIDOMWindowOuter* topOuter = GetInProcessScriptableTop();
2521 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"
, 2521); return false; } } while (false)
;
2522
2523 nsGlobalWindowInner* topInner =
2524 nsGlobalWindowInner::Cast(topOuter->GetCurrentInnerWindow());
2525 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"
, 2525); return false; } } while (false)
;
2526
2527 topInner->ShouldReportForServiceWorkerScopeInternal(
2528 NS_ConvertUTF16toUTF8(aScope), &result);
2529 return result;
2530}
2531
2532InstallTriggerImpl* nsGlobalWindowInner::GetInstallTrigger() {
2533 if (!mInstallTrigger &&
2534 !StaticPrefs::extensions_InstallTriggerImpl_enabled()) {
2535 // Return nullptr when InstallTriggerImpl is disabled by pref,
2536 // which does not yet break the "typeof InstallTrigger !== 'undefined"
2537 // "UA detection" use case, but prevents access to the InstallTriggerImpl
2538 // methods and properties.
2539 //
2540 // NOTE: a separate pref ("extensions.InstallTrigger.enabled"), associated
2541 // to this property using the [Pref] extended attribute in Window.webidl,
2542 // does instead hide the entire InstallTrigger property.
2543 //
2544 // See Bug 1754441 for more details about this deprecation.
2545 return nullptr;
2546 }
2547 if (!mInstallTrigger) {
2548 ErrorResult rv;
2549 mInstallTrigger = ConstructJSImplementation<InstallTriggerImpl>(
2550 "@mozilla.org/addons/installtrigger;1", this, rv);
2551 if (rv.Failed()) {
2552 rv.SuppressException();
2553 return nullptr;
2554 }
2555 }
2556
2557 return mInstallTrigger;
2558}
2559
2560nsIDOMWindowUtils* nsGlobalWindowInner::GetWindowUtils(ErrorResult& aRv) {
2561 FORWARD_TO_OUTER_OR_THROW(WindowUtils, (), aRv, nullptr);
2562}
2563
2564CallState nsGlobalWindowInner::ShouldReportForServiceWorkerScopeInternal(
2565 const nsACString& aScope, bool* aResultOut) {
2566 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"
, 2566); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aResultOut"
")"); do { *((volatile int*)__null) = 2566; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2567
2568 // First check to see if this window is controlled. If so, then we have
2569 // found a match and are done.
2570 const Maybe<ServiceWorkerDescriptor> swd = GetController();
2571 if (swd.isSome() && swd.ref().Scope() == aScope) {
2572 *aResultOut = true;
2573 return CallState::Stop;
2574 }
2575
2576 // Next, check to see if this window has called
2577 // navigator.serviceWorker.register() for this scope. If so, then treat this
2578 // as a match so console reports appear in the devtools console.
2579 if (mClientSource &&
2580 mClientSource->CalledRegisterForServiceWorkerScope(aScope)) {
2581 *aResultOut = true;
2582 return CallState::Stop;
2583 }
2584
2585 // Finally check the current docshell nsILoadGroup to see if there are any
2586 // outstanding navigation requests. If so, match the scope against the
2587 // channel's URL. We want to show console reports during the FetchEvent
2588 // intercepting the navigation itself.
2589 nsCOMPtr<nsIDocumentLoader> loader(do_QueryInterface(GetDocShell()));
2590 if (loader) {
2591 nsCOMPtr<nsILoadGroup> loadgroup;
2592 Unused << loader->GetLoadGroup(getter_AddRefs(loadgroup));
2593 if (loadgroup) {
2594 nsCOMPtr<nsISimpleEnumerator> iter;
2595 Unused << loadgroup->GetRequests(getter_AddRefs(iter));
2596 if (iter) {
2597 nsCOMPtr<nsISupports> tmp;
2598 bool hasMore = true;
2599 // Check each network request in the load group.
2600 while (NS_SUCCEEDED(iter->HasMoreElements(&hasMore))((bool)(__builtin_expect(!!(!NS_FAILED_impl(iter->HasMoreElements
(&hasMore))), 1)))
&& hasMore) {
2601 iter->GetNext(getter_AddRefs(tmp));
2602 nsCOMPtr<nsIChannel> loadingChannel(do_QueryInterface(tmp));
2603 // Ignore subresource requests. Logging for a subresource
2604 // FetchEvent should be handled above since the client is
2605 // already controlled.
2606 if (!loadingChannel ||
2607 !nsContentUtils::IsNonSubresourceRequest(loadingChannel)) {
2608 continue;
2609 }
2610 nsCOMPtr<nsIURI> loadingURL;
2611 Unused << loadingChannel->GetURI(getter_AddRefs(loadingURL));
2612 if (!loadingURL) {
2613 continue;
2614 }
2615 nsAutoCString loadingSpec;
2616 Unused << loadingURL->GetSpec(loadingSpec);
2617 // Perform a simple substring comparison to match the scope
2618 // against the channel URL.
2619 if (StringBeginsWith(loadingSpec, aScope)) {
2620 *aResultOut = true;
2621 return CallState::Stop;
2622 }
2623 }
2624 }
2625 }
2626 }
2627
2628 // The current window doesn't care about this service worker, but maybe
2629 // one of our child frames does.
2630 return CallOnInProcessChildren(
2631 &nsGlobalWindowInner::ShouldReportForServiceWorkerScopeInternal, aScope,
2632 aResultOut);
2633}
2634
2635void nsGlobalWindowInner::NoteCalledRegisterForServiceWorkerScope(
2636 const nsACString& aScope) {
2637 if (!mClientSource) {
2638 return;
2639 }
2640
2641 mClientSource->NoteCalledRegisterForServiceWorkerScope(aScope);
2642}
2643
2644void nsGlobalWindowInner::NoteDOMContentLoaded() {
2645 if (!mClientSource) {
2646 return;
2647 }
2648
2649 mClientSource->NoteDOMContentLoaded();
2650}
2651
2652void nsGlobalWindowInner::UpdateTopInnerWindow() {
2653 if (IsTopInnerWindow() || !mTopInnerWindow) {
2654 return;
2655 }
2656
2657 mTopInnerWindow->UpdateWebSocketCount(-(int32_t)mNumOfOpenWebSockets);
2658}
2659
2660bool nsGlobalWindowInner::IsInSyncOperation() {
2661 return GetExtantDoc() && GetExtantDoc()->IsInSyncOperation();
2662}
2663
2664bool nsGlobalWindowInner::IsSharedMemoryAllowedInternal(
2665 nsIPrincipal* aPrincipal) const {
2666 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"
, 2666); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 2666; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2667
2668 if (StaticPrefs::
2669 dom_postMessage_sharedArrayBuffer_bypassCOOP_COEP_insecure_enabled()) {
2670 return true;
2671 }
2672
2673 if (ExtensionPolicyService::GetSingleton().IsExtensionProcess()) {
2674 if (auto* basePrincipal = BasePrincipal::Cast(aPrincipal)) {
2675 if (auto* policy = basePrincipal->AddonPolicy()) {
2676 return policy->IsPrivileged();
2677 }
2678 }
2679 }
2680
2681 return CrossOriginIsolated();
2682}
2683
2684bool nsGlobalWindowInner::CrossOriginIsolated() const {
2685 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"
, 2685); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 2685; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2686
2687 RefPtr<BrowsingContext> bc = GetBrowsingContext();
2688 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"
, 2688); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "bc"
")"); do { *((volatile int*)__null) = 2688; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2689 return bc->CrossOriginIsolated();
2690}
2691
2692WindowContext* TopWindowContext(nsPIDOMWindowInner& aWindow) {
2693 WindowContext* wc = aWindow.GetWindowContext();
2694 if (!wc) {
2695 return nullptr;
2696 }
2697
2698 return wc->TopWindowContext();
2699}
2700
2701void nsPIDOMWindowInner::AddPeerConnection() {
2702 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"
, 2702); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 2702; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2703 ++mActivePeerConnections;
2704 if (mActivePeerConnections == 1 && mWindowGlobalChild) {
2705 mWindowGlobalChild->SendUpdateActivePeerConnectionStatus(
2706 /*aIsAdded*/ true);
2707
2708 // We need to present having active peer connections immediately. If we need
2709 // to wait for the parent process to come back with this information we
2710 // might start throttling.
2711 if (WindowContext* top = TopWindowContext(*this)) {
2712 top->TransientSetHasActivePeerConnections();
2713 }
2714 }
2715}
2716
2717void nsPIDOMWindowInner::RemovePeerConnection() {
2718 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"
, 2718); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 2718; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2719 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"
, 2719); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mActivePeerConnections > 0"
")"); do { *((volatile int*)__null) = 2719; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2720 --mActivePeerConnections;
2721 if (mActivePeerConnections == 0 && mWindowGlobalChild) {
2722 mWindowGlobalChild->SendUpdateActivePeerConnectionStatus(
2723 /*aIsAdded*/ false);
2724 }
2725}
2726
2727bool nsPIDOMWindowInner::HasActivePeerConnections() {
2728 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"
, 2728); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 2728; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2729
2730 WindowContext* topWindowContext = TopWindowContext(*this);
2731 return topWindowContext && topWindowContext->GetHasActivePeerConnections();
2732}
2733
2734void nsPIDOMWindowInner::AddMediaKeysInstance(MediaKeys* aMediaKeys) {
2735 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"
, 2735); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 2735; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2736 mMediaKeysInstances.AppendElement(aMediaKeys);
2737 if (mWindowGlobalChild && mMediaKeysInstances.Length() == 1) {
2738 mWindowGlobalChild->BlockBFCacheFor(BFCacheStatus::CONTAINS_EME_CONTENT);
2739 }
2740}
2741
2742void nsPIDOMWindowInner::RemoveMediaKeysInstance(MediaKeys* aMediaKeys) {
2743 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"
, 2743); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 2743; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2744 mMediaKeysInstances.RemoveElement(aMediaKeys);
2745 if (mWindowGlobalChild && mMediaKeysInstances.IsEmpty()) {
2746 mWindowGlobalChild->UnblockBFCacheFor(BFCacheStatus::CONTAINS_EME_CONTENT);
2747 }
2748}
2749
2750bool nsPIDOMWindowInner::HasActiveMediaKeysInstance() {
2751 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"
, 2751); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 2751; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2752 return !mMediaKeysInstances.IsEmpty();
2753}
2754
2755bool nsPIDOMWindowInner::IsPlayingAudio() {
2756 for (uint32_t i = 0; i < mAudioContexts.Length(); i++) {
2757 if (mAudioContexts[i]->IsRunning()) {
2758 return true;
2759 }
2760 }
2761 RefPtr<AudioChannelService> acs = AudioChannelService::Get();
2762 if (!acs) {
2763 return false;
2764 }
2765 auto outer = GetOuterWindow();
2766 if (!outer) {
2767 // We've been unlinked and are about to die. Not a good time to pretend to
2768 // be playing audio.
2769 return false;
2770 }
2771 return acs->IsWindowActive(outer);
2772}
2773
2774bool nsPIDOMWindowInner::IsDocumentLoaded() const { return mIsDocumentLoaded; }
2775
2776mozilla::dom::TimeoutManager& nsPIDOMWindowInner::TimeoutManager() {
2777 return *mTimeoutManager;
2778}
2779
2780bool nsPIDOMWindowInner::IsRunningTimeout() {
2781 return TimeoutManager().IsRunningTimeout();
2782}
2783
2784void nsPIDOMWindowInner::TryToCacheTopInnerWindow() {
2785 if (mHasTriedToCacheTopInnerWindow) {
2786 return;
2787 }
2788
2789 nsGlobalWindowInner* window = nsGlobalWindowInner::Cast(this);
2790
2791 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"
, 2791); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!window->IsDying()"
")"); do { *((volatile int*)__null) = 2791; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2792
2793 mHasTriedToCacheTopInnerWindow = true;
2794
2795 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"
, 2795); AnnotateMozCrashReason("MOZ_ASSERT" "(" "window" ")"
); do { *((volatile int*)__null) = 2795; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2796
2797 if (nsCOMPtr<nsPIDOMWindowOuter> topOutter =
2798 window->GetInProcessScriptableTop()) {
2799 mTopInnerWindow = topOutter->GetCurrentInnerWindow();
2800 }
2801}
2802
2803void nsPIDOMWindowInner::UpdateActiveIndexedDBDatabaseCount(int32_t aDelta) {
2804 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"
, 2804); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 2804; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2805
2806 if (aDelta == 0) {
2807 return;
2808 }
2809
2810 // We count databases but not transactions because only active databases
2811 // could block throttling.
2812 uint32_t& counter = mTopInnerWindow
2813 ? mTopInnerWindow->mNumOfIndexedDBDatabases
2814 : mNumOfIndexedDBDatabases;
2815
2816 counter += aDelta;
2817}
2818
2819bool nsPIDOMWindowInner::HasActiveIndexedDBDatabases() {
2820 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"
, 2820); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 2820; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2821
2822 return mTopInnerWindow ? mTopInnerWindow->mNumOfIndexedDBDatabases > 0
2823 : mNumOfIndexedDBDatabases > 0;
2824}
2825
2826void nsPIDOMWindowInner::UpdateWebSocketCount(int32_t aDelta) {
2827 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"
, 2827); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 2827; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2828
2829 if (aDelta == 0) {
2830 return;
2831 }
2832
2833 if (mTopInnerWindow && !IsTopInnerWindow()) {
2834 mTopInnerWindow->UpdateWebSocketCount(aDelta);
2835 }
2836
2837 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"
, 2838); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aDelta > 0 || ((aDelta + mNumOfOpenWebSockets) < mNumOfOpenWebSockets)"
")"); do { *((volatile int*)__null) = 2838; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2838 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"
, 2838); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aDelta > 0 || ((aDelta + mNumOfOpenWebSockets) < mNumOfOpenWebSockets)"
")"); do { *((volatile int*)__null) = 2838; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2839
2840 mNumOfOpenWebSockets += aDelta;
2841}
2842
2843bool nsPIDOMWindowInner::HasOpenWebSockets() const {
2844 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"
, 2844); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 2844; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2845
2846 return mNumOfOpenWebSockets ||
2847 (mTopInnerWindow && mTopInnerWindow->mNumOfOpenWebSockets);
2848}
2849
2850bool nsPIDOMWindowInner::IsCurrentInnerWindow() const {
2851 if (mozilla::SessionHistoryInParent() && mBrowsingContext &&
2852 mBrowsingContext->IsInBFCache()) {
2853 return false;
2854 }
2855
2856 if (!mBrowsingContext || mBrowsingContext->IsDiscarded()) {
2857 // If our BrowsingContext has been discarded, we consider ourselves
2858 // still-current if we were current at the time it was discarded.
2859 return mOuterWindow && WasCurrentInnerWindow();
2860 }
2861
2862 nsPIDOMWindowOuter* outer = mBrowsingContext->GetDOMWindow();
2863 return outer && outer->GetCurrentInnerWindow() == this;
2864}
2865
2866bool nsPIDOMWindowInner::IsFullyActive() const {
2867 WindowContext* wc = GetWindowContext();
2868 if (!wc || wc->IsDiscarded() || !wc->IsCurrent()) {
2869 return false;
2870 }
2871 return GetBrowsingContext()->AncestorsAreCurrent();
2872}
2873
2874void nsPIDOMWindowInner::SetAudioCapture(bool aCapture) {
2875 RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
2876 if (service) {
2877 service->SetWindowAudioCaptured(GetOuterWindow(), mWindowID, aCapture);
2878 }
2879}
2880
2881void nsGlobalWindowInner::SetActiveLoadingState(bool aIsLoading) {
2882 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)
2883 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)
2884 ("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)
;
2885 if (GetBrowsingContext()) {
2886 // Setting loading on a discarded context has no effect.
2887 Unused << GetBrowsingContext()->SetLoading(aIsLoading);
2888 }
2889
2890 if (!nsGlobalWindowInner::Cast(this)->IsChromeWindow()) {
2891 mTimeoutManager->SetLoading(aIsLoading);
2892 }
2893
2894 HintIsLoading(aIsLoading);
2895}
2896
2897void nsGlobalWindowInner::HintIsLoading(bool aIsLoading) {
2898 // Hint to tell the JS GC to use modified triggers during pageload.
2899 if (mHintedWasLoading != aIsLoading) {
2900 using namespace js::gc;
2901 SetPerformanceHint(danger::GetJSContext(), aIsLoading
2902 ? PerformanceHint::InPageLoad
2903 : PerformanceHint::Normal);
2904 mHintedWasLoading = aIsLoading;
2905 }
2906}
2907
2908// nsISpeechSynthesisGetter
2909
2910#ifdef MOZ_WEBSPEECH1
2911SpeechSynthesis* nsGlobalWindowInner::GetSpeechSynthesis(ErrorResult& aError) {
2912 if (!mSpeechSynthesis) {
2913 mSpeechSynthesis = new SpeechSynthesis(this);
2914 }
2915
2916 return mSpeechSynthesis;
2917}
2918
2919bool nsGlobalWindowInner::HasActiveSpeechSynthesis() {
2920 if (mSpeechSynthesis) {
2921 return !mSpeechSynthesis->HasEmptyQueue();
2922 }
2923
2924 return false;
2925}
2926
2927#endif
2928
2929mozilla::glean::Glean* nsGlobalWindowInner::Glean() {
2930 if (!mGlean) {
2931 mGlean = new mozilla::glean::Glean(this);
2932 }
2933
2934 return mGlean;
2935}
2936
2937mozilla::glean::GleanPings* nsGlobalWindowInner::GleanPings() {
2938 if (!mGleanPings) {
2939 mGleanPings = new mozilla::glean::GleanPings();
2940 }
2941
2942 return mGleanPings;
2943}
2944
2945Nullable<WindowProxyHolder> nsGlobalWindowInner::GetParent(
2946 ErrorResult& aError) {
2947 FORWARD_TO_OUTER_OR_THROW(GetParentOuter, (), aError, nullptr);
2948}
2949
2950/**
2951 * GetInProcessScriptableParent used to be called when a script read
2952 * window.parent. Under Fission, that is now handled by
2953 * BrowsingContext::GetParent, and the result is a WindowProxyHolder rather than
2954 * an actual global window. This method still exists for legacy callers which
2955 * relied on the old logic, and require in-process windows. However, it only
2956 * works correctly when no out-of-process frames exist between this window and
2957 * the top-level window, so it should not be used in new code.
2958 *
2959 * In contrast to GetRealParent, GetInProcessScriptableParent respects <iframe
2960 * mozbrowser> boundaries, so if |this| is contained by an <iframe
2961 * mozbrowser>, we will return |this| as its own parent.
2962 */
2963nsPIDOMWindowOuter* nsGlobalWindowInner::GetInProcessScriptableParent() {
2964 FORWARD_TO_OUTER(GetInProcessScriptableParent, (), nullptr);
2965}
2966
2967/**
2968 * GetInProcessScriptableTop used to be called when a script read window.top.
2969 * Under Fission, that is now handled by BrowsingContext::Top, and the result is
2970 * a WindowProxyHolder rather than an actual global window. This method still
2971 * exists for legacy callers which relied on the old logic, and require
2972 * in-process windows. However, it only works correctly when no out-of-process
2973 * frames exist between this window and the top-level window, so it should not
2974 * be used in new code.
2975 *
2976 * In contrast to GetRealTop, GetInProcessScriptableTop respects <iframe
2977 * mozbrowser> boundaries. If we encounter a window owned by an <iframe
2978 * mozbrowser> while walking up the window hierarchy, we'll stop and return that
2979 * window.
2980 */
2981nsPIDOMWindowOuter* nsGlobalWindowInner::GetInProcessScriptableTop() {
2982 FORWARD_TO_OUTER(GetInProcessScriptableTop, (), nullptr);
2983}
2984
2985void nsGlobalWindowInner::GetContent(JSContext* aCx,
2986 JS::MutableHandle<JSObject*> aRetval,
2987 CallerType aCallerType,
2988 ErrorResult& aError) {
2989 FORWARD_TO_OUTER_OR_THROW(GetContentOuter,
2990 (aCx, aRetval, aCallerType, aError), aError, );
2991}
2992
2993BarProp* nsGlobalWindowInner::GetMenubar(ErrorResult& aError) {
2994 if (!mMenubar) {
2995 mMenubar = new MenubarProp(this);
2996 }
2997
2998 return mMenubar;
2999}
3000
3001BarProp* nsGlobalWindowInner::GetToolbar(ErrorResult& aError) {
3002 if (!mToolbar) {
3003 mToolbar = new ToolbarProp(this);
3004 }
3005
3006 return mToolbar;
3007}
3008
3009BarProp* nsGlobalWindowInner::GetLocationbar(ErrorResult& aError) {
3010 if (!mLocationbar) {
3011 mLocationbar = new LocationbarProp(this);
3012 }
3013 return mLocationbar;
3014}
3015
3016BarProp* nsGlobalWindowInner::GetPersonalbar(ErrorResult& aError) {
3017 if (!mPersonalbar) {
3018 mPersonalbar = new PersonalbarProp(this);
3019 }
3020 return mPersonalbar;
3021}
3022
3023BarProp* nsGlobalWindowInner::GetStatusbar(ErrorResult& aError) {
3024 if (!mStatusbar) {
3025 mStatusbar = new StatusbarProp(this);
3026 }
3027 return mStatusbar;
3028}
3029
3030BarProp* nsGlobalWindowInner::GetScrollbars(ErrorResult& aError) {
3031 if (!mScrollbars) {
3032 mScrollbars = new ScrollbarsProp(this);
3033 }
3034
3035 return mScrollbars;
3036}
3037
3038bool nsGlobalWindowInner::GetClosed(ErrorResult& aError) {
3039 // If we're called from JS (which is the only way we should be getting called
3040 // here) and we reach this point, that means our JS global is the current
3041 // target of the WindowProxy, which means that we are the "current inner"
3042 // of our outer. So if FORWARD_TO_OUTER fails to forward, that means the
3043 // outer is already torn down, which corresponds to the closed state.
3044 FORWARD_TO_OUTER(GetClosedOuter, (), true);
3045}
3046
3047Nullable<WindowProxyHolder> nsGlobalWindowInner::IndexedGetter(
3048 uint32_t aIndex) {
3049 FORWARD_TO_OUTER(IndexedGetterOuter, (aIndex), nullptr);
3050}
3051
3052namespace {
3053
3054struct InterfaceShimEntry {
3055 const char* geckoName;
3056 const char* domName;
3057};
3058
3059} // anonymous namespace
3060
3061// We add shims from Components.interfaces.nsIDOMFoo to window.Foo for each
3062// interface that has interface constants that sites might be getting off
3063// of Ci.
3064const InterfaceShimEntry kInterfaceShimMap[] = {
3065 {"nsIXMLHttpRequest", "XMLHttpRequest"},
3066 {"nsIDOMDOMException", "DOMException"},
3067 {"nsIDOMNode", "Node"},
3068 {"nsIDOMCSSRule", "CSSRule"},
3069 {"nsIDOMEvent", "Event"},
3070 {"nsIDOMNSEvent", "Event"},
3071 {"nsIDOMKeyEvent", "KeyEvent"},
3072 {"nsIDOMMouseEvent", "MouseEvent"},
3073 {"nsIDOMMouseScrollEvent", "MouseScrollEvent"},
3074 {"nsIDOMMutationEvent", "MutationEvent"},
3075 {"nsIDOMUIEvent", "UIEvent"},
3076 {"nsIDOMHTMLMediaElement", "HTMLMediaElement"},
3077 {"nsIDOMRange", "Range"},
3078 // Think about whether Ci.nsINodeFilter can just go away for websites!
3079 {"nsIDOMNodeFilter", "NodeFilter"},
3080 {"nsIDOMXPathResult", "XPathResult"}};
3081
3082bool nsGlobalWindowInner::ResolveComponentsShim(
3083 JSContext* aCx, JS::Handle<JSObject*> aGlobal,
3084 JS::MutableHandle<mozilla::Maybe<JS::PropertyDescriptor>> aDesc) {
3085 // Keep track of how often this happens.
3086 Telemetry::Accumulate(Telemetry::COMPONENTS_SHIM_ACCESSED_BY_CONTENT, true);
3087
3088 // Warn once.
3089 nsCOMPtr<Document> doc = GetExtantDoc();
3090 if (doc) {
3091 doc->WarnOnceAbout(DeprecatedOperations::eComponents, /* asError = */ true);
3092 }
3093
3094 // Create a fake Components object.
3095 AssertSameCompartment(aCx, aGlobal);
3096 JS::Rooted<JSObject*> components(aCx, JS_NewPlainObject(aCx));
3097 if (NS_WARN_IF(!components)NS_warn_if_impl(!components, "!components", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 3097)
) {
3098 return false;
3099 }
3100
3101 // Create a fake interfaces object.
3102 JS::Rooted<JSObject*> interfaces(aCx, JS_NewPlainObject(aCx));
3103 if (NS_WARN_IF(!interfaces)NS_warn_if_impl(!interfaces, "!interfaces", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 3103)
) {
3104 return false;
3105 }
3106 bool ok =
3107 JS_DefineProperty(aCx, components, "interfaces", interfaces,
3108 JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY);
3109 if (NS_WARN_IF(!ok)NS_warn_if_impl(!ok, "!ok", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 3109)
) {
3110 return false;
3111 }
3112
3113 // Define a bunch of shims from the Ci.nsIDOMFoo to window.Foo for DOM
3114 // interfaces with constants.
3115 for (uint32_t i = 0; i < ArrayLength(kInterfaceShimMap); ++i) {
3116 // Grab the names from the table.
3117 const char* geckoName = kInterfaceShimMap[i].geckoName;
3118 const char* domName = kInterfaceShimMap[i].domName;
3119
3120 // Look up the appopriate interface object on the global.
3121 JS::Rooted<JS::Value> v(aCx, JS::UndefinedValue());
3122 ok = JS_GetProperty(aCx, aGlobal, domName, &v);
3123 if (NS_WARN_IF(!ok)NS_warn_if_impl(!ok, "!ok", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 3123)
) {
3124 return false;
3125 }
3126 if (!v.isObject()) {
3127 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"
, 3127)
;
3128 continue;
3129 }
3130
3131 // Define the shim on the interfaces object.
3132 ok = JS_DefineProperty(
3133 aCx, interfaces, geckoName, v,
3134 JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY);
3135 if (NS_WARN_IF(!ok)NS_warn_if_impl(!ok, "!ok", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 3135)
) {
3136 return false;
3137 }
3138 }
3139
3140 aDesc.set(mozilla::Some(JS::PropertyDescriptor::Data(
3141 JS::ObjectValue(*components),
3142 {JS::PropertyAttribute::Configurable, JS::PropertyAttribute::Enumerable,
3143 JS::PropertyAttribute::Writable})));
3144 return true;
3145}
3146
3147#ifdef RELEASE_OR_BETA
3148# define USE_CONTROLLERS_SHIM
3149#endif
3150
3151#ifdef USE_CONTROLLERS_SHIM
3152static const JSClass ControllersShimClass = {"Controllers", 0};
3153static const JSClass XULControllersShimClass = {"XULControllers", 0};
3154#endif
3155
3156bool nsGlobalWindowInner::DoResolve(
3157 JSContext* aCx, JS::Handle<JSObject*> aObj, JS::Handle<jsid> aId,
3158 JS::MutableHandle<mozilla::Maybe<JS::PropertyDescriptor>> aDesc) {
3159 // Note: Keep this in sync with MayResolve.
3160
3161 // Note: The infallibleInit call in GlobalResolve depends on this check.
3162 if (!aId.isString()) {
3163 return true;
3164 }
3165
3166 bool found;
3167 if (!WebIDLGlobalNameHash::DefineIfEnabled(aCx, aObj, aId, aDesc, &found)) {
3168 return false;
3169 }
3170
3171 if (found) {
3172 return true;
3173 }
3174
3175 // We support a cut-down Components.interfaces in case websites are
3176 // using Components.interfaces.nsIFoo.CONSTANT_NAME for the ones
3177 // that have constants.
3178 if (StaticPrefs::dom_use_components_shim() &&
3179 aId == XPCJSRuntime::Get()->GetStringID(XPCJSContext::IDX_COMPONENTS)) {
3180 return ResolveComponentsShim(aCx, aObj, aDesc);
3181 }
3182
3183 // We also support a "window.controllers" thing; apparently some
3184 // sites use it for browser-sniffing. See bug 1010577.
3185#ifdef USE_CONTROLLERS_SHIM
3186 // Note: We use |aObj| rather than |this| to get the principal here, because
3187 // this is called during Window setup when the Document isn't necessarily
3188 // hooked up yet.
3189 if ((aId == XPCJSRuntime::Get()->GetStringID(XPCJSContext::IDX_CONTROLLERS) ||
3190 aId == XPCJSRuntime::Get()->GetStringID(
3191 XPCJSContext::IDX_CONTROLLERS_CLASS)) &&
3192 !xpc::IsXrayWrapper(aObj) &&
3193 !nsContentUtils::ObjectPrincipal(aObj)->IsSystemPrincipal()) {
3194 if (GetExtantDoc()) {
3195 GetExtantDoc()->WarnOnceAbout(
3196 DeprecatedOperations::eWindow_Cc_ontrollers);
3197 }
3198 const JSClass* clazz;
3199 if (aId ==
3200 XPCJSRuntime::Get()->GetStringID(XPCJSContext::IDX_CONTROLLERS)) {
3201 clazz = &XULControllersShimClass;
3202 } else {
3203 clazz = &ControllersShimClass;
3204 }
3205 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"
, 3205); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JS_IsGlobalObject(aObj)"
")"); do { *((volatile int*)__null) = 3205; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3206 JS::Rooted<JSObject*> shim(aCx, JS_NewObject(aCx, clazz));
3207 if (NS_WARN_IF(!shim)NS_warn_if_impl(!shim, "!shim", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 3207)
) {
3208 return false;
3209 }
3210
3211 aDesc.set(mozilla::Some(JS::PropertyDescriptor::Data(
3212 JS::ObjectValue(*shim),
3213 {JS::PropertyAttribute::Configurable, JS::PropertyAttribute::Enumerable,
3214 JS::PropertyAttribute::Writable})));
3215 return true;
3216 }
3217#endif
3218
3219 return true;
3220}
3221
3222/* static */
3223bool nsGlobalWindowInner::MayResolve(jsid aId) {
3224 // Note: This function does not fail and may not have any side-effects.
3225 // Note: Keep this in sync with DoResolve.
3226 if (!aId.isString()) {
3227 return false;
3228 }
3229
3230 if (aId == XPCJSRuntime::Get()->GetStringID(XPCJSContext::IDX_COMPONENTS)) {
3231 return true;
3232 }
3233
3234 if (aId == XPCJSRuntime::Get()->GetStringID(XPCJSContext::IDX_CONTROLLERS) ||
3235 aId == XPCJSRuntime::Get()->GetStringID(
3236 XPCJSContext::IDX_CONTROLLERS_CLASS)) {
3237 // We only resolve .controllers/.Controllers in release builds and on
3238 // non-chrome windows, but let's not worry about any of that stuff.
3239 return true;
3240 }
3241
3242 return WebIDLGlobalNameHash::MayResolve(aId);
3243}
3244
3245void nsGlobalWindowInner::GetOwnPropertyNames(
3246 JSContext* aCx, JS::MutableHandleVector<jsid> aNames, bool aEnumerableOnly,
3247 ErrorResult& aRv) {
3248 if (aEnumerableOnly) {
3249 // The names we would return from here get defined on the window via one of
3250 // two codepaths. The ones coming from the WebIDLGlobalNameHash will end up
3251 // in the DefineConstructor function in BindingUtils, which always defines
3252 // things as non-enumerable. The ones coming from the script namespace
3253 // manager get defined by our resolve hook using FillPropertyDescriptor with
3254 // 0 for the property attributes, so non-enumerable as well.
3255 //
3256 // So in the aEnumerableOnly case we have nothing to do.
3257 return;
3258 }
3259
3260 // "Components" is marked as enumerable but only resolved on demand :-/.
3261 // aNames.AppendElement(u"Components"_ns);
3262
3263 JS::Rooted<JSObject*> wrapper(aCx, GetWrapper());
3264
3265 // There are actually two ways we can get called here: For normal
3266 // enumeration or for Xray enumeration. In the latter case, we want to
3267 // return all possible WebIDL names, because we don't really support
3268 // deleting these names off our Xray; trying to resolve them will just make
3269 // them come back. In the former case, we want to avoid returning deleted
3270 // names. But the JS engine already knows about the non-deleted
3271 // already-resolved names, so we can just return the so-far-unresolved ones.
3272 //
3273 // We can tell which case we're in by whether aCx is in our wrapper's
3274 // compartment. If not, we're in the Xray case.
3275 WebIDLGlobalNameHash::NameType nameType =
3276 js::IsObjectInContextCompartment(wrapper, aCx)
3277 ? WebIDLGlobalNameHash::UnresolvedNamesOnly
3278 : WebIDLGlobalNameHash::AllNames;
3279 if (!WebIDLGlobalNameHash::GetNames(aCx, wrapper, nameType, aNames)) {
3280 aRv.NoteJSContextException(aCx);
3281 }
3282}
3283
3284/* static */
3285bool nsGlobalWindowInner::IsPrivilegedChromeWindow(JSContext*, JSObject* aObj) {
3286 // For now, have to deal with XPConnect objects here.
3287 nsGlobalWindowInner* win = xpc::WindowOrNull(aObj);
3288 return win && win->IsChromeWindow() &&
3289 nsContentUtils::ObjectPrincipal(aObj) ==
3290 nsContentUtils::GetSystemPrincipal();
3291}
3292
3293/* static */
3294bool nsGlobalWindowInner::DeviceSensorsEnabled(JSContext*, JSObject*) {
3295 return Preferences::GetBool("device.sensors.enabled");
3296}
3297
3298/* static */
3299bool nsGlobalWindowInner::CachesEnabled(JSContext* aCx, JSObject* aObj) {
3300 if (!IsSecureContextOrObjectIsFromSecureContext(aCx, aObj)) {
3301 return StaticPrefs::dom_caches_testing_enabled() ||
3302 StaticPrefs::dom_serviceWorkers_testing_enabled();
3303 }
3304 return true;
3305}
3306
3307/* static */
3308bool nsGlobalWindowInner::IsSizeToContentEnabled(JSContext* aCx, JSObject*) {
3309 return StaticPrefs::dom_window_sizeToContent_enabled() ||
3310 nsContentUtils::IsSystemCaller(aCx);
3311}
3312
3313/* static */
3314bool nsGlobalWindowInner::IsGleanNeeded(JSContext* aCx, JSObject* aObj) {
3315 // Glean is needed in ChromeOnly contexts and also in privileged about pages.
3316 nsIPrincipal* principal = nsContentUtils::SubjectPrincipal(aCx);
3317 if (principal->IsSystemPrincipal()) {
3318 return true;
3319 }
3320
3321 uint32_t flags = 0;
3322 if (NS_FAILED(principal->GetAboutModuleFlags(&flags))((bool)(__builtin_expect(!!(NS_FAILED_impl(principal->GetAboutModuleFlags
(&flags))), 0)))
) {
3323 return false;
3324 }
3325 return flags & nsIAboutModule::IS_SECURE_CHROME_UI;
3326}
3327
3328Crypto* nsGlobalWindowInner::GetCrypto(ErrorResult& aError) {
3329 if (!mCrypto) {
3330 mCrypto = new Crypto(this);
3331 }
3332 return mCrypto;
3333}
3334
3335nsIControllers* nsGlobalWindowInner::GetControllers(ErrorResult& aError) {
3336 FORWARD_TO_OUTER_OR_THROW(GetControllersOuter, (aError), aError, nullptr);
3337}
3338
3339nsresult nsGlobalWindowInner::GetControllers(nsIControllers** aResult) {
3340 ErrorResult rv;
3341 nsCOMPtr<nsIControllers> controllers = GetControllers(rv);
3342 controllers.forget(aResult);
3343
3344 return rv.StealNSResult();
3345}
3346
3347Nullable<WindowProxyHolder> nsGlobalWindowInner::GetOpenerWindow(
3348 ErrorResult& aError) {
3349 FORWARD_TO_OUTER_OR_THROW(GetOpenerWindowOuter, (), aError, nullptr);
3350}
3351
3352void nsGlobalWindowInner::GetOpener(JSContext* aCx,
3353 JS::MutableHandle<JS::Value> aRetval,
3354 ErrorResult& aError) {
3355 Nullable<WindowProxyHolder> opener = GetOpenerWindow(aError);
3356 if (aError.Failed() || opener.IsNull()) {
3357 aRetval.setNull();
3358 return;
3359 }
3360
3361 if (!ToJSValue(aCx, opener.Value(), aRetval)) {
3362 aError.NoteJSContextException(aCx);
3363 }
3364}
3365
3366void nsGlobalWindowInner::SetOpener(JSContext* aCx,
3367 JS::Handle<JS::Value> aOpener,
3368 ErrorResult& aError) {
3369 if (aOpener.isNull()) {
3370 RefPtr<BrowsingContext> bc(GetBrowsingContext());
3371 if (!bc->IsDiscarded()) {
3372 bc->SetOpener(nullptr);
3373 }
3374 return;
3375 }
3376
3377 // If something other than null is passed, just define aOpener on our inner
3378 // window's JS object, wrapped into the current compartment so that for Xrays
3379 // we define on the Xray expando object, but don't set it on the outer window,
3380 // so that it'll get reset on navigation. This is just like replaceable
3381 // properties, but we're not quite readonly.
3382 RedefineProperty(aCx, "opener", aOpener, aError);
3383}
3384
3385void nsGlobalWindowInner::GetEvent(OwningEventOrUndefined& aRetval) {
3386 if (mEvent) {
3387 aRetval.SetAsEvent() = mEvent;
3388 } else {
3389 aRetval.SetUndefined();
3390 }
3391}
3392
3393void nsGlobalWindowInner::GetStatus(nsAString& aStatus, ErrorResult& aError) {
3394 FORWARD_TO_OUTER_OR_THROW(GetStatusOuter, (aStatus), aError, );
3395}
3396
3397void nsGlobalWindowInner::SetStatus(const nsAString& aStatus,
3398 ErrorResult& aError) {
3399 FORWARD_TO_OUTER_OR_THROW(SetStatusOuter, (aStatus), aError, );
3400}
3401
3402void nsGlobalWindowInner::GetName(nsAString& aName, ErrorResult& aError) {
3403 FORWARD_TO_OUTER_OR_THROW(GetNameOuter, (aName), aError, );
3404}
3405
3406void nsGlobalWindowInner::SetName(const nsAString& aName,
3407 mozilla::ErrorResult& aError) {
3408 FORWARD_TO_OUTER_OR_THROW(SetNameOuter, (aName, aError), aError, );
3409}
3410
3411double nsGlobalWindowInner::GetInnerWidth(ErrorResult& aError) {
3412 FORWARD_TO_OUTER_OR_THROW(GetInnerWidthOuter, (aError), aError, 0);
3413}
3414
3415nsresult nsGlobalWindowInner::GetInnerWidth(double* aWidth) {
3416 ErrorResult rv;
3417 // Callee doesn't care about the caller type, but play it safe.
3418 *aWidth = GetInnerWidth(rv);
3419 return rv.StealNSResult();
3420}
3421
3422double nsGlobalWindowInner::GetInnerHeight(ErrorResult& aError) {
3423 // We ignore aCallerType; we only have that argument because some other things
3424 // called by GetReplaceableWindowCoord need it. If this ever changes, fix
3425 // nsresult nsGlobalWindowInner::GetInnerHeight(double* aInnerWidth)
3426 // to actually take a useful CallerType and pass it in here.
3427 FORWARD_TO_OUTER_OR_THROW(GetInnerHeightOuter, (aError), aError, 0);
3428}
3429
3430nsresult nsGlobalWindowInner::GetInnerHeight(double* aHeight) {
3431 ErrorResult rv;
3432 // Callee doesn't care about the caller type, but play it safe.
3433 *aHeight = GetInnerHeight(rv);
3434 return rv.StealNSResult();
3435}
3436
3437int32_t nsGlobalWindowInner::GetOuterWidth(CallerType aCallerType,
3438 ErrorResult& aError) {
3439 FORWARD_TO_OUTER_OR_THROW(GetOuterWidthOuter, (aCallerType, aError), aError,
3440 0);
3441}
3442
3443int32_t nsGlobalWindowInner::GetOuterHeight(CallerType aCallerType,
3444 ErrorResult& aError) {
3445 FORWARD_TO_OUTER_OR_THROW(GetOuterHeightOuter, (aCallerType, aError), aError,
3446 0);
3447}
3448
3449double nsGlobalWindowInner::ScreenEdgeSlopX() const {
3450 FORWARD_TO_OUTER(ScreenEdgeSlopX, (), 0);
3451}
3452
3453double nsGlobalWindowInner::ScreenEdgeSlopY() const {
3454 FORWARD_TO_OUTER(ScreenEdgeSlopY, (), 0);
3455}
3456
3457int32_t nsGlobalWindowInner::GetScreenX(CallerType aCallerType,
3458 ErrorResult& aError) {
3459 FORWARD_TO_OUTER_OR_THROW(GetScreenXOuter, (aCallerType, aError), aError, 0);
3460}
3461
3462int32_t nsGlobalWindowInner::GetScreenY(CallerType aCallerType,
3463 ErrorResult& aError) {
3464 FORWARD_TO_OUTER_OR_THROW(GetScreenYOuter, (aCallerType, aError), aError, 0);
3465}
3466
3467float nsGlobalWindowInner::GetMozInnerScreenX(CallerType aCallerType,
3468 ErrorResult& aError) {
3469 FORWARD_TO_OUTER_OR_THROW(GetMozInnerScreenXOuter, (aCallerType), aError, 0);
3470}
3471
3472float nsGlobalWindowInner::GetMozInnerScreenY(CallerType aCallerType,
3473 ErrorResult& aError) {
3474 FORWARD_TO_OUTER_OR_THROW(GetMozInnerScreenYOuter, (aCallerType), aError, 0);
3475}
3476
3477static nsPresContext* GetPresContextForRatio(Document* aDoc) {
3478 if (nsPresContext* presContext = aDoc->GetPresContext()) {
3479 return presContext;
3480 }
3481 // We're in an undisplayed subdocument... There's not really an awesome way
3482 // to tell what the right DPI is from here, so we try to walk up our parent
3483 // document chain to the extent that the docs can observe each other.
3484 Document* doc = aDoc;
3485 while (doc->StyleOrLayoutObservablyDependsOnParentDocumentLayout()) {
3486 doc = doc->GetInProcessParentDocument();
3487 if (nsPresContext* presContext = doc->GetPresContext()) {
3488 return presContext;
3489 }
3490 }
3491 return nullptr;
3492}
3493
3494double nsGlobalWindowInner::GetDevicePixelRatio(CallerType aCallerType,
3495 ErrorResult& aError) {
3496 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)
;
3497
3498 RefPtr<nsPresContext> presContext = GetPresContextForRatio(mDoc);
3499 if (NS_WARN_IF(!presContext)NS_warn_if_impl(!presContext, "!presContext", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp"
, 3499)
) {
3500 // Still nothing, oh well.
3501 return 1.0;
3502 }
3503
3504 if (nsIGlobalObject::ShouldResistFingerprinting(
3505 aCallerType, RFPTarget::WindowDevicePixelRatio)) {
3506 return 2.0;
3507 }
3508
3509 if (aCallerType == CallerType::NonSystem) {
3510 float overrideDPPX = presContext->GetOverrideDPPX();
3511 if (overrideDPPX > 0.0f) {
3512 return overrideDPPX;
3513 }
3514 }
3515
3516 return double(AppUnitsPerCSSPixel()) /
3517 double(presContext->AppUnitsPerDevPixel());
3518}
3519
3520double nsGlobalWindowInner::GetDesktopToDeviceScale(ErrorResult& aError) {
3521 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)
;
3522 nsPresContext* presContext = GetPresContextForRatio(mDoc);
3523 if (!presContext) {
3524 return 1.0;
3525 }
3526 return presContext->DeviceContext()->GetDesktopToDeviceScale().scale;
3527}
3528
3529int32_t nsGlobalWindowInner::RequestAnimationFrame(
3530 FrameRequestCallback& aCallback, ErrorResult& aError) {
3531 if (!mDoc) {
3532 return 0;
3533 }
3534
3535 if (GetWrapperPreserveColor()) {
3536 js::NotifyAnimationActivity(GetWrapperPreserveColor());
3537 }
3538
3539 DebuggerNotificationDispatch(this,
3540 DebuggerNotificationType::RequestAnimationFrame);
3541
3542 int32_t handle;
3543 aError = mDoc->ScheduleFrameRequestCallback(aCallback, &handle);
3544 return handle;
3545}
3546
3547void nsGlobalWindowInner::CancelAnimationFrame(int32_t aHandle,
3548 ErrorResult& aError) {
3549 if (!mDoc) {
3550 return;
3551 }
3552
3553 DebuggerNotificationDispatch(this,
3554 DebuggerNotificationType::CancelAnimationFrame);
3555
3556 mDoc->CancelFrameRequestCallback(aHandle);
3557}
3558
3559already_AddRefed<MediaQueryList> nsGlobalWindowInner::MatchMedia(
3560 const nsACString& aMediaQueryList, CallerType aCallerType,
3561 ErrorResult& aError) {
3562 ENSURE_ACTIVE_DOCUMENT(aError, nullptr)do { if ((__builtin_expect(!!(!HasActiveDocument()), 0))) { aError
.Throw(NS_ERROR_XPC_SECURITY_MANAGER_VETO); return nullptr; }
} while (0)
;
3563 return mDoc->MatchMedia(aMediaQueryList, aCallerType);
3564}
3565
3566int32_t nsGlobalWindowInner::GetScrollMinX(ErrorResult& aError) {
3567 FORWARD_TO_OUTER_OR_THROW(GetScrollBoundaryOuter, (eSideLeft), aError, 0);
3568}
3569
3570int32_t nsGlobalWindowInner::GetScrollMinY(ErrorResult& aError) {
3571 FORWARD_TO_OUTER_OR_THROW(GetScrollBoundaryOuter, (eSideTop), aError, 0);
3572}
3573
3574int32_t nsGlobalWindowInner::GetScrollMaxX(ErrorResult& aError) {
3575 FORWARD_TO_OUTER_OR_THROW(GetScrollBoundaryOuter, (eSideRight), aError, 0);
3576}
3577
3578int32_t nsGlobalWindowInner::GetScrollMaxY(ErrorResult& aError) {
3579 FORWARD_TO_OUTER_OR_THROW(GetScrollBoundaryOuter, (eSideBottom), aError, 0);
3580}
3581
3582double nsGlobalWindowInner::GetScrollX(ErrorResult& aError) {
3583 FORWARD_TO_OUTER_OR_THROW(GetScrollXOuter, (), aError, 0);
3584}
3585
3586double nsGlobalWindowInner::GetScrollY(ErrorResult& aError) {
3587 FORWARD_TO_OUTER_OR_THROW(GetScrollYOuter, (), aError, 0);
3588}
3589
3590uint32_t nsGlobalWindowInner::Length() { FORWARD_TO_OUTER(Length, (), 0); }
3591
3592Nullable<WindowProxyHolder> nsGlobalWindowInner::GetTop(
3593 mozilla::ErrorResult& aError) {
3594 FORWARD_TO_OUTER_OR_THROW(GetTopOuter, (), aError, nullptr);
3595}
3596
3597already_AddRefed<BrowsingContext> nsGlobalWindowInner::GetChildWindow(
3598 const nsAString& aName) {
3599 if (GetOuterWindowInternal()) {
3600 return GetOuterWindowInternal()->GetChildWindow(aName);
3601 }
3602 return nullptr;
3603}
3604
3605void nsGlobalWindowInner::RefreshRealmPrincipal() {
3606 JS::SetRealmPrincipals(js::GetNonCCWObjectRealm(GetWrapperPreserveColor()),
3607 nsJSPrincipals::get(mDoc->NodePrincipal()));
3608}
3609
3610void nsGlobalWindowInner::RefreshReduceTimerPrecisionCallerType() {
3611 JS::SetRealmReduceTimerPrecisionCallerType(
3612 js::GetNonCCWObjectRealm(GetWrapperPreserveColor()),
3613 RTPCallerTypeToToken(GetRTPCallerType()));
3614}
3615
3616already_AddRefed<nsIWidget> nsGlobalWindowInner::GetMainWidget() {
3617 FORWARD_TO_OUTER(GetMainWidget, (), nullptr);
3618}
3619
3620nsIWidget* nsGlobalWindowInner::GetNearestWidget() const {
3621 if (GetOuterWindowInternal()) {
3622 return GetOuterWindowInternal()->GetNearestWidget();
3623 }
3624 return nullptr;
3625}
3626
3627void nsGlobalWindowInner::SetFullScreen(bool aFullscreen,
3628 mozilla::ErrorResult& aError) {
3629 FORWARD_TO_OUTER_OR_THROW(SetFullscreenOuter, (aFullscreen, aError), aError,
3630 /* void */);
3631}
3632
3633bool nsGlobalWindowInner::GetFullScreen(ErrorResult& aError) {
3634 FORWARD_TO_OUTER_OR_THROW(GetFullscreenOuter, (), aError, false);
3635}
3636
3637bool nsGlobalWindowInner::GetFullScreen() {
3638 ErrorResult dummy;
3639 bool fullscreen = GetFullScreen(dummy);
3640 dummy.SuppressException();
3641 return fullscreen;
3642}
3643
3644void nsGlobalWindowInner::Dump(const nsAString& aStr) {
3645 if (!nsJSUtils::DumpEnabled()) {
3646 return;
3647 }
3648
3649 char* cstr = ToNewUTF8String(aStr);
3650
3651#if defined(XP_MACOSX)
3652 // have to convert \r to \n so that printing to the console works
3653 char *c = cstr, *cEnd = cstr + strlen(cstr);
3654 while (c < cEnd) {
3655 if (*c == '\r') *c = '\n';
3656 c++;
3657 }
3658#endif
3659
3660 if (cstr) {
3661 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)
3662 ("[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)
;
3663#ifdef XP_WIN
3664 PrintToDebugger(cstr);
3665#endif
3666#ifdef ANDROID
3667 __android_log_write(ANDROID_LOG_INFO, "GeckoDump", cstr);
3668#endif
3669 FILE* fp = gDumpFile ? gDumpFile : stdoutstdout;
3670 fputs(cstr, fp);
3671 fflush(fp);
3672 free(cstr);
3673 }
3674}
3675
3676void nsGlobalWindowInner::Alert(nsIPrincipal& aSubjectPrincipal,
3677 ErrorResult& aError) {
3678 Alert(u""_ns, aSubjectPrincipal, aError);
3679}
3680
3681void nsGlobalWindowInner::Alert(const nsAString& aMessage,
3682 nsIPrincipal& aSubjectPrincipal,
3683 ErrorResult& aError) {
3684 FORWARD_TO_OUTER_OR_THROW(AlertOuter, (aMessage, aSubjectPrincipal, aError),
3685 aError, );
3686}
3687
3688bool nsGlobalWindowInner::Confirm(const nsAString& aMessage,
3689 nsIPrincipal& aSubjectPrincipal,
3690 ErrorResult& aError) {
3691 FORWARD_TO_OUTER_OR_THROW(ConfirmOuter, (aMessage, aSubjectPrincipal, aError),
3692 aError, false);
3693}
3694
3695already_AddRefed<Promise> nsGlobalWindowInner::Fetch(
3696 const RequestOrUTF8String& aInput, const RequestInit& aInit,
3697 CallerType aCallerType, ErrorResult& aRv) {
3698 return FetchRequest(this, aInput, aInit, aCallerType, aRv);
3699}
3700
3701void nsGlobalWindowInner::Prompt(const nsAString& aMessage,
3702 const nsAString& aInitial, nsAString& aReturn,
3703 nsIPrincipal& aSubjectPrincipal,
3704 ErrorResult& aError) {
3705 FORWARD_TO_OUTER_OR_THROW(
3706 PromptOuter, (aMessage, aInitial, aReturn, aSubjectPrincipal, aError),
3707 aError, );
3708}
3709
3710void nsGlobalWindowInner::Focus(CallerType aCallerType, ErrorResult& aError) {
3711 FORWARD_TO_OUTER_OR_THROW(FocusOuter,
3712 (aCallerType, /* aFromOtherProcess */ false,
3713 nsFocusManager::GenerateFocusActionId()),
3714 aError, );
3715}
3716
3717nsresult nsGlobalWindowInner::Focus(CallerType aCallerType) {
3718 ErrorResult rv;
3719 Focus(aCallerType, rv);
3720
3721 return rv.StealNSResult();
3722}
3723
3724void nsGlobalWindowInner::Blur(CallerType aCallerType, ErrorResult& aError) {
3725 FORWARD_TO_OUTER_OR_THROW(BlurOuter, (aCallerType), aError, );
3726}
3727
3728void nsGlobalWindowInner::Stop(ErrorResult& aError) {
3729 FORWARD_TO_OUTER_OR_THROW(StopOuter, (aError), aError, );
3730}
3731
3732void nsGlobalWindowInner::Print(ErrorResult& aError) {
3733 FORWARD_TO_OUTER_OR_THROW(PrintOuter, (aError), aError, );
3734}
3735
3736Nullable<WindowProxyHolder> nsGlobalWindowInner::PrintPreview(
3737 nsIPrintSettings* aSettings, nsIWebProgressListener* aListener,
3738 nsIDocShell* aDocShellToCloneInto, ErrorResult& aError) {
3739 FORWARD_TO_OUTER_OR_THROW(
3740 Print,
3741 (aSettings,
3742 /* aRemotePrintJob = */ nullptr, aListener, aDocShellToCloneInto,
3743 nsGlobalWindowOuter::IsPreview::Yes,
3744 nsGlobalWindowOuter::IsForWindowDotPrint::No,
3745 /* aPrintPreviewCallback = */ nullptr, nullptr, aError),
3746 aError, nullptr);
3747}
3748
3749void nsGlobalWindowInner::MoveTo(int32_t aXPos, int32_t aYPos,
3750 CallerType aCallerType, ErrorResult& aError) {
3751 FORWARD_TO_OUTER_OR_THROW(MoveToOuter, (aXPos, aYPos, aCallerType, aError),
3752 aError, );
3753}
3754
3755void nsGlobalWindowInner::MoveBy(int32_t aXDif, int32_t aYDif,
3756 CallerType aCallerType, ErrorResult& aError) {
3757 FORWARD_TO_OUTER_OR_THROW(MoveByOuter, (aXDif, aYDif, aCallerType, aError),
3758 aError, );
3759}
3760
3761void nsGlobalWindowInner::ResizeTo(int32_t aWidth, int32_t aHeight,
3762 CallerType aCallerType,
3763 ErrorResult& aError) {
3764 FORWARD_TO_OUTER_OR_THROW(ResizeToOuter,
3765 (aWidth, aHeight, aCallerType, aError), aError, );
3766}
3767
3768void nsGlobalWindowInner::ResizeBy(int32_t aWidthDif, int32_t aHeightDif,
3769 CallerType aCallerType,
3770 ErrorResult& aError) {
3771 FORWARD_TO_OUTER_OR_THROW(
3772 ResizeByOuter, (aWidthDif, aHeightDif, aCallerType, aError), aError, );
3773}
3774
3775void nsGlobalWindowInner::SizeToContent(CallerType aCallerType,
3776 ErrorResult& aError) {
3777 FORWARD_TO_OUTER_OR_THROW(SizeToContentOuter, (aCallerType, {}, aError),
3778 aError, );
3779}
3780
3781void nsGlobalWindowInner::SizeToContentConstrained(
3782 const SizeToContentConstraints& aConstraints, ErrorResult& aError) {
3783 FORWARD_TO_OUTER_OR_THROW(
3784 SizeToContentOuter, (CallerType::System, aConstraints, aError), aError, );
3785}
3786
3787already_AddRefed<nsPIWindowRoot> nsGlobalWindowInner::GetTopWindowRoot() {
3788 nsGlobalWindowOuter* outer = GetOuterWindowInternal();
3789 if (!outer) {
3790 return nullptr;
3791 }
3792 return outer->GetTopWindowRoot();
3793}
3794
3795void nsGlobalWindowInner::Scroll(double aXScroll, double aYScroll) {
3796 // Convert -Inf, Inf, and NaN to 0; otherwise, convert by C-style cast.
3797 auto scrollPos = CSSIntPoint::Truncate(mozilla::ToZeroIfNonfinite(aXScroll),
3798 mozilla::ToZeroIfNonfinite(aYScroll));
3799 ScrollTo(scrollPos, ScrollOptions());
3800}
3801
3802void nsGlobalWindowInner::ScrollTo(double aXScroll, double aYScroll) {
3803 // Convert -Inf, Inf, and NaN to 0; otherwise, convert by C-style cast.
3804 auto scrollPos = CSSIntPoint::Truncate(mozilla::ToZeroIfNonfinite(aXScroll),
3805 mozilla::ToZeroIfNonfinite(aYScroll));
3806 ScrollTo(scrollPos, ScrollOptions());
3807}
3808
3809void nsGlobalWindowInner::ScrollTo(const ScrollToOptions& aOptions) {
3810 // When scrolling to a non-zero offset, we need to determine whether that
3811 // position is within our scrollable range, so we need updated layout
3812 // information which requires a layout flush, otherwise all we need is to
3813 // flush frames to be able to access our scrollable frame here.
3814 FlushType flushType =
3815 ((aOptions.mLeft.WasPassed() && aOptions.mLeft.Value() > 0) ||
3816 (aOptions.mTop.WasPassed() && aOptions.mTop.Value() > 0))
3817 ? FlushType::Layout
3818 : FlushType::Frames;
3819 FlushPendingNotifications(flushType);
3820 nsIScrollableFrame* sf = GetScrollFrame();
3821
3822 if (sf) {
3823 CSSIntPoint scrollPos = sf->GetRoundedScrollPositionCSSPixels();
3824 if (aOptions.mLeft.WasPassed()) {
3825 scrollPos.x = static_cast<int32_t>(
3826 mozilla::ToZeroIfNonfinite(aOptions.mLeft.Value()));
3827 }
3828 if (aOptions.mTop.WasPassed()) {
3829 scrollPos.y = static_cast<int32_t>(
3830 mozilla::ToZeroIfNonfinite(aOptions.mTop.Value()));
3831 }
3832
3833 ScrollTo(scrollPos, aOptions);
3834 }
3835}
3836
3837void nsGlobalWindowInner::Scroll(const ScrollToOptions& aOptions) {
3838 ScrollTo(aOptions);
3839}
3840
3841void nsGlobalWindowInner::ScrollTo(const CSSIntPoint& aScroll,
3842 const ScrollOptions& aOptions) {
3843 // When scrolling to a non-zero offset, we need to determine whether that
3844 // position is within our scrollable range, so we need updated layout
3845 // information which requires a layout flush, otherwise all we need is to
3846 // flush frames to be able to access our scrollable frame here.
3847 FlushType flushType =
3848 (aScroll.x || aScroll.y) ? FlushType::Layout : FlushType::Frames;
3849 FlushPendingNotifications(flushType);
3850 nsIScrollableFrame* sf = GetScrollFrame();
3851
3852 if (sf) {
3853 // Here we calculate what the max pixel value is that we can
3854 // scroll to, we do this by dividing maxint with the pixel to
3855 // twips conversion factor, and subtracting 4, the 4 comes from
3856 // experimenting with this value, anything less makes the view
3857 // code not scroll correctly, I have no idea why. -- jst
3858 const int32_t maxpx = nsPresContext::AppUnitsToIntCSSPixels(0x7fffffff) - 4;
3859
3860 CSSIntPoint scroll(aScroll);
3861 if (scroll.x > maxpx) {
3862 scroll.x = maxpx;
3863 }
3864
3865 if (scroll.y > maxpx) {
3866 scroll.y = maxpx;
3867 }
3868
3869 ScrollMode scrollMode = sf->IsSmoothScroll(aOptions.mBehavior)
3870 ? ScrollMode::SmoothMsd
3871 : ScrollMode::Instant;
3872
3873 sf->ScrollToCSSPixels(scroll, scrollMode);
3874 }
3875}
3876
3877void nsGlobalWindowInner::ScrollBy(double aXScrollDif, double aYScrollDif) {
3878 FlushPendingNotifications(FlushType::Layout);
3879 nsIScrollableFrame* sf = GetScrollFrame();
3880
3881 if (sf) {
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 ScrollToOptions options;
3886 options.mLeft.Construct(aXScrollDif);
3887 options.mTop.Construct(aYScrollDif);
3888 ScrollBy(options);
3889 }
3890}
3891
3892void nsGlobalWindowInner::ScrollBy(const ScrollToOptions& aOptions) {
3893 FlushPendingNotifications(FlushType::Layout);
3894 nsIScrollableFrame* sf = GetScrollFrame();
3895
3896 if (sf) {
3897 CSSIntPoint scrollDelta;
3898 if (aOptions.mLeft.WasPassed()) {
3899 scrollDelta.x = static_cast<int32_t>(
3900 mozilla::ToZeroIfNonfinite(aOptions.mLeft.Value()));
3901 }
3902 if (aOptions.mTop.WasPassed()) {
3903 scrollDelta.y = static_cast<int32_t>(
3904 mozilla::ToZeroIfNonfinite(aOptions.mTop.Value()));
3905 }
3906
3907 ScrollMode scrollMode = sf->IsSmoothScroll(aOptions.mBehavior)
3908 ? ScrollMode::SmoothMsd
3909 : ScrollMode::Instant;
3910
3911 sf->ScrollByCSSPixels(scrollDelta, scrollMode);
3912 }
3913}
3914
3915void nsGlobalWindowInner::ScrollByLines(int32_t numLines,
3916 const ScrollOptions& aOptions) {
3917 FlushPendingNotifications(FlushType::Layout);
3918 nsIScrollableFrame* sf = GetScrollFrame();
3919 if (sf) {
3920 // It seems like it would make more sense for ScrollByLines to use
3921 // SMOOTH mode, but tests seem to depend on the synchronous behaviour.
3922 // Perhaps Web content does too.
3923 ScrollMode scrollMode = sf->IsSmoothScroll(aOptions.mBehavior)
3924 ? ScrollMode::SmoothMsd
3925 : ScrollMode::Instant;
3926
3927 sf->ScrollBy(nsIntPoint(0, numLines), ScrollUnit::LINES, scrollMode);
3928 }
3929}
3930
3931void nsGlobalWindowInner::ScrollByPages(int32_t numPages,
3932 const ScrollOptions& aOptions) {
3933 FlushPendingNotifications(FlushType::Layout);
3934 nsIScrollableFrame* sf = GetScrollFrame();
3935 if (sf) {
3936 // It seems like it would make more sense for ScrollByPages to use
3937 // SMOOTH mode, but tests seem to depend on the synchronous behaviour.
3938 // Perhaps Web content does too.
3939 ScrollMode scrollMode = sf->IsSmoothScroll(aOptions.mBehavior)
3940 ? ScrollMode::SmoothMsd
3941 : ScrollMode::Instant;
3942
3943 sf->ScrollBy(nsIntPoint(0, numPages), ScrollUnit::PAGES, scrollMode);
3944 }
3945}
3946
3947void nsGlobalWindowInner::MozScrollSnap() {
3948 FlushPendingNotifications(FlushType::Layout);
3949 nsIScrollableFrame* sf = GetScrollFrame();
3950 if (sf) {
3951 sf->ScrollSnap();
3952 }
3953}
3954
3955void nsGlobalWindowInner::ClearTimeout(int32_t aHandle) {
3956 DebuggerNotificationDispatch(this, DebuggerNotificationType::ClearTimeout);
3957
3958 if (aHandle > 0) {
3959 mTimeoutManager->ClearTimeout(aHandle, Timeout::Reason::eTimeoutOrInterval);
3960 }
3961}
3962
3963void nsGlobalWindowInner::ClearInterval(int32_t aHandle) {
3964 DebuggerNotificationDispatch(this, DebuggerNotificationType::ClearInterval);
3965
3966 if (aHandle > 0) {
3967 mTimeoutManager->ClearTimeout(aHandle, Timeout::Reason::eTimeoutOrInterval);
3968 }
3969}
3970
3971void nsGlobalWindowInner::SetResizable(bool aResizable) const {
3972 // nop
3973}
3974
3975void nsGlobalWindowInner::CaptureEvents() {
3976 if (mDoc) {
3977 mDoc->WarnOnceAbout(DeprecatedOperations::eUseOfCaptureEvents);
3978 }
3979}
3980
3981void nsGlobalWindowInner::ReleaseEvents() {
3982 if (mDoc) {
3983 mDoc->WarnOnceAbout(DeprecatedOperations::eUseOfReleaseEvents);
3984 }
3985}
3986
3987Nullable<WindowProxyHolder> nsGlobalWindowInner::Open(const nsAString& aUrl,
3988 const nsAString& aName,
3989 const nsAString& aOptions,
3990 ErrorResult& aError) {
3991 FORWARD_TO_OUTER_OR_THROW(OpenOuter, (aUrl, aName, aOptions, aError), aError,
3992 nullptr);
3993}
3994
3995Nullable<WindowProxyHolder> nsGlobalWindowInner::OpenDialog(
3996 JSContext* aCx, const nsAString& aUrl, const nsAString& aName,
3997 const nsAString& aOptions, const Sequence<JS::Value>& aExtraArgument,
3998 ErrorResult& aError) {
3999 FORWARD_TO_OUTER_OR_THROW(
4000 OpenDialogOuter, (aCx, aUrl, aName, aOptions, aExtraArgument, aError),
4001 aError, nullptr);
4002}
4003
4004WindowProxyHolder nsGlobalWindowInner::GetFrames(ErrorResult& aError) {
4005 FORWARD_TO_OUTER_OR_THROW(GetFramesOuter, (), aError, Window());
4006}
4007
4008void nsGlobalWindowInner::PostMessageMoz(JSContext* aCx,
4009 JS::Handle<JS::Value> aMessage,
4010 const nsAString& aTargetOrigin,
4011 JS::Handle<JS::Value> aTransfer,
4012 nsIPrincipal& aSubjectPrincipal,
4013 ErrorResult& aError) {
4014 FORWARD_TO_OUTER_OR_THROW(
4015 PostMessageMozOuter,
4016 (aCx, aMessage, aTargetOrigin, aTransfer, aSubjectPrincipal, aError),
4017 aError, );
4018}
4019
4020void nsGlobalWindowInner::PostMessageMoz(JSContext* aCx,
4021 JS::Handle<JS::Value> aMessage,
4022 const nsAString& aTargetOrigin,
4023 const Sequence<JSObject*>& aTransfer,
4024 nsIPrincipal& aSubjectPrincipal,
4025 ErrorResult& aRv) {
4026 JS::Rooted<JS::Value> transferArray(aCx, JS::UndefinedValue());
4027
4028 aRv = nsContentUtils::CreateJSValueFromSequenceOfObject(aCx, aTransfer,
4029 &transferArray);
4030 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"
, 4030)
) {
4031 return;
4032 }
4033
4034 PostMessageMoz(aCx, aMessage, aTargetOrigin, transferArray, aSubjectPrincipal,
4035 aRv);
4036}
4037
4038void nsGlobalWindowInner::PostMessageMoz(
4039 JSContext* aCx, JS::Handle<JS::Value> aMessage,
4040 const WindowPostMessageOptions& aOptions, nsIPrincipal& aSubjectPrincipal,
4041 ErrorResult& aRv) {
4042 JS::Rooted<JS::Value> transferArray(aCx, JS::UndefinedValue());
4043
4044 aRv = nsContentUtils::CreateJSValueFromSequenceOfObject(
4045 aCx, aOptions.mTransfer, &transferArray);
4046 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"
, 4046)
) {
4047 return;
4048 }
4049
4050 PostMessageMoz(aCx, aMessage, aOptions.mTargetOrigin, transferArray,
4051 aSubjectPrincipal, aRv);
4052}
4053
4054void nsGlobalWindowInner::Close(CallerType aCallerType, ErrorResult& aError) {
4055 FORWARD_TO_OUTER_OR_THROW(CloseOuter, (aCallerType == CallerType::System),
4056 aError, );
4057}
4058
4059nsresult nsGlobalWindowInner::Close() {
4060 FORWARD_TO_OUTER(Close, (), NS_ERROR_UNEXPECTED);
4061}
4062
4063bool nsGlobalWindowInner::IsInModalState() {
4064 FORWARD_TO_OUTER(IsInModalState, (), false);
4065}
4066
4067// static
4068void nsGlobalWindowInner::NotifyDOMWindowDestroyed(
4069 nsGlobalWindowInner* aWindow) {
4070 nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
4071 if (observerService) {
4072 observerService->NotifyObservers(ToSupports(aWindow),
4073 DOM_WINDOW_DESTROYED_TOPIC"dom-window-destroyed", nullptr);
4074 }
4075}
4076
4077void nsGlobalWindowInner::NotifyWindowIDDestroyed(const char* aTopic) {
4078 nsCOMPtr<nsIRunnable> runnable =
4079 new WindowDestroyedEvent(this, mWindowID, aTopic);
4080 Dispatch(runnable.forget());
4081}
4082
4083// static
4084void nsGlobalWindowInner::NotifyDOMWindowFrozen(nsGlobalWindowInner* aWindow) {
4085 if (aWindow) {
4086 nsCOMPtr<nsIObserverService> observerService =
4087 services::GetObserverService();
4088 if (observerService) {
4089 observerService->NotifyObservers(ToSupports(aWindow),
4090 DOM_WINDOW_FROZEN_TOPIC"dom-window-frozen", nullptr);
4091 }
4092 }
4093}
4094
4095// static
4096void nsGlobalWindowInner::NotifyDOMWindowThawed(nsGlobalWindowInner* aWindow) {
4097 if (aWindow) {
4098 nsCOMPtr<nsIObserverService> observerService =
4099 services::GetObserverService();
4100 if (observerService) {
4101 observerService->NotifyObservers(ToSupports(aWindow),
4102 DOM_WINDOW_THAWED_TOPIC"dom-window-thawed", nullptr);
4103 }
4104 }
4105}
4106
4107Element* nsGlobalWindowInner::GetFrameElement(nsIPrincipal& aSubjectPrincipal,
4108 ErrorResult& aError) {
4109 FORWARD_TO_OUTER_OR_THROW(GetFrameElement, (aSubjectPrincipal), aError,
4110 nullptr);
4111}
4112
4113Element* nsGlobalWindowInner::GetRealFrameElement(ErrorResult& aError) {
4114 FORWARD_TO_OUTER_OR_THROW(GetFrameElement, (), aError, nullptr);
4115}
4116
4117void nsGlobalWindowInner::UpdateCommands(const nsAString& anAction) {
4118 if (GetOuterWindowInternal()) {
4119 GetOuterWindowInternal()->UpdateCommands(anAction);
4120 }
4121}
4122
4123Selection* nsGlobalWindowInner::GetSelection(ErrorResult& aError) {
4124 FORWARD_TO_OUTER_OR_THROW(GetSelectionOuter, (), aError, nullptr);
4125}
4126
4127WebTaskScheduler* nsGlobalWindowInner::Scheduler() {
4128 if (!mWebTaskScheduler) {
4129 mWebTaskScheduler = WebTaskScheduler::CreateForMainThread(this);
4130 }
4131 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"
, 4131); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mWebTaskScheduler"
")"); do { *((volatile int*)__null) = 4131; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4132 return mWebTaskScheduler;
4133}
4134
4135bool nsGlobalWindowInner::Find(const nsAString& aString, bool aCaseSensitive,
4136 bool aBackwards, bool aWrapAround,
4137 bool aWholeWord, bool aSearchInFrames,
4138 bool aShowDialog, ErrorResult& aError) {
4139 FORWARD_TO_OUTER_OR_THROW(FindOuter,
4140 (aString, aCaseSensitive, aBackwards, aWrapAround,
4141 aWholeWord, aSearchInFrames, aShowDialog, aError),
4142 aError, false);
4143}
4144
4145void nsGlobalWindowInner::GetOrigin(nsAString& aOrigin) {
4146 nsContentUtils::GetWebExposedOriginSerialization(GetPrincipal(), aOrigin);
4147}
4148
4149// See also AutoJSAPI::ReportException
4150void nsGlobalWindowInner::ReportError(JSContext* aCx,
4151 JS::Handle<JS::Value> aError,
4152 CallerType aCallerType,
4153 ErrorResult& aRv) {
4154 if (MOZ_UNLIKELY(!HasActiveDocument())(__builtin_expect(!!(!HasActiveDocument()), 0))) {
4155 return aRv.Throw(NS_ERROR_XPC_SECURITY_MANAGER_VETO);
4156 }
4157
4158 JS::ErrorReportBuilder jsReport(aCx);
4159 JS::ExceptionStack exnStack(aCx, aError, nullptr);
4160 if (!jsReport.init(aCx, exnStack, JS::ErrorReportBuilder::NoSideEffects)) {
4161 return aRv.NoteJSContextException(aCx);
4162 }
4163
4164 RefPtr<xpc::ErrorReport> xpcReport = new xpc::ErrorReport();
4165 bool isChrome = aCallerType == CallerType::System;
4166 xpcReport->Init(jsReport.report(), jsReport.toStringResult().c_str(),
4167 isChrome, WindowID());
4168
4169 JS::RootingContext* rcx = JS::RootingContext::get(aCx);
4170 DispatchScriptErrorEvent(this, rcx, xpcReport, exnStack.exception(),
4171 exnStack.stack());
4172}
4173
4174void nsGlobalWindowInner::Atob(const nsAString& aAsciiBase64String,
4175 nsAString& aBinaryData, ErrorResult& aError) {
4176 aError = nsContentUtils::Atob(aAsciiBase64String, aBinaryData);
4177}
4178
4179void nsGlobalWindowInner::Btoa(const nsAString& aBinaryData,
4180 nsAString& aAsciiBase64String,
4181 ErrorResult& aError) {
4182 aError = nsContentUtils::Btoa(aBinaryData, aAsciiBase64String);
4183}
4184
4185//*****************************************************************************
4186// EventTarget
4187//*****************************************************************************
4188
4189nsPIDOMWindowOuter* nsGlobalWindowInner::GetOwnerGlobalForBindingsInternal() {
4190 return nsPIDOMWindowOuter::GetFromCurrentInner(this);
4191}
4192
4193bool nsGlobalWindowInner::DispatchEvent(Event& aEvent, CallerType aCallerType,
4194 ErrorResult& aRv) {
4195 if (!IsCurrentInnerWindow()) {
4196 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"
, 4198)
4197 "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"
, 4198)
4198 "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"
, 4198)
;
4199 aRv.Throw(NS_ERROR_FAILURE);
4200 return false;
4201 }
4202
4203 if (!mDoc) {
4204 aRv.Throw(NS_ERROR_FAILURE);
4205 return false;
4206 }
4207
4208 // Obtain a presentation shell
4209 RefPtr<nsPresContext> presContext = mDoc->GetPresContext();
4210
4211 nsEventStatus status = nsEventStatus_eIgnore;
4212 nsresult rv = EventDispatcher::DispatchDOMEvent(this, nullptr, &aEvent,
4213 presContext, &status);
4214 bool retval = !aEvent.DefaultPrevented(aCallerType);
4215 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4216 aRv.Throw(rv);
4217 }
4218 return retval;
4219}
4220
4221mozilla::Maybe<mozilla::dom::EventCallbackDebuggerNotificationType>
4222nsGlobalWindowInner::GetDebuggerNotificationType() const {
4223 return mozilla::Some(
4224 mozilla::dom::EventCallbackDebuggerNotificationType::Global);
4225}
4226
4227bool nsGlobalWindowInner::ComputeDefaultWantsUntrusted(ErrorResult& aRv) {
4228 return !nsContentUtils::IsChromeDoc(mDoc);
4229}
4230
4231EventListenerManager* nsGlobalWindowInner::GetOrCreateListenerManager() {
4232 if (!mListenerManager) {
4233 mListenerManager =
4234 new EventListenerManager(static_cast<EventTarget*>(this));
4235 }
4236
4237 return mListenerManager;
4238}
4239
4240EventListenerManager* nsGlobalWindowInner::GetExistingListenerManager() const {
4241 return mListenerManager;
4242}
4243
4244mozilla::dom::DebuggerNotificationManager*
4245nsGlobalWindowInner::GetOrCreateDebuggerNotificationManager() {
4246 if (!mDebuggerNotificationManager) {
4247 mDebuggerNotificationManager = new DebuggerNotificationManager(this);
4248 }
4249
4250 return mDebuggerNotificationManager;
4251}
4252
4253mozilla::dom::DebuggerNotificationManager*
4254nsGlobalWindowInner::GetExistingDebuggerNotificationManager() {
4255 return mDebuggerNotificationManager;
4256}
4257
4258//*****************************************************************************
4259// nsGlobalWindowInner::nsPIDOMWindow
4260//*****************************************************************************
4261
4262Location* nsGlobalWindowInner::Location() {
4263 if (!mLocation) {
4264 mLocation = new dom::Location(this);
4265 }
4266
4267 return mLocation;
4268}
4269
4270void nsGlobalWindowInner::MaybeUpdateTouchState() {
4271 if (mMayHaveTouchEventListener) {
4272 nsCOMPtr<nsIObserverService> observerService =
4273 services::GetObserverService();
4274
4275 if (observerService) {
4276 observerService->NotifyObservers(static_cast<nsIDOMWindow*>(this),
4277 DOM_TOUCH_LISTENER_ADDED"dom-touch-listener-added", nullptr);
4278 }
4279 }
4280}
4281
4282void nsGlobalWindowInner::EnableGamepadUpdates() {
4283 if (mHasGamepad) {
4284 RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService());
4285 if (gamepadManager) {
4286 gamepadManager->AddListener(this);
4287 }
4288 }
4289}
4290
4291void nsGlobalWindowInner::DisableGamepadUpdates() {
4292 if (mHasGamepad) {
4293 RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService());
4294 if (gamepadManager) {
4295 gamepadManager->RemoveListener(this);
4296 }
4297 }
4298}
4299
4300void nsGlobalWindowInner::EnableVRUpdates() {
4301 // We need to create a VREventObserver before we can either detect XR runtimes
4302 // or start an XR session
4303 if (!mVREventObserver && (mHasXRSession || mXRRuntimeDetectionInFlight)) {
4304 // Assert that we are not creating the observer while IsDying() as
4305 // that would result in a leak. VREventObserver holds a RefPtr to
4306 // this nsGlobalWindowInner and would prevent it from being deallocated.
4307 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"
, 4309); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDying()"
") (" "Creating a VREventObserver for an nsGlobalWindow that is "
"dying would cause it to leak." ")"); do { *((volatile int*)
__null) = 4309; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
4308 "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"
, 4309); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDying()"
") (" "Creating a VREventObserver for an nsGlobalWindow that is "
"dying would cause it to leak." ")"); do { *((volatile int*)
__null) = 4309; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
4309 "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"
, 4309); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDying()"
") (" "Creating a VREventObserver for an nsGlobalWindow that is "
"dying would cause it to leak." ")"); do { *((volatile int*)
__null) = 4309; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4310 mVREventObserver = new VREventObserver(this);
4311 }
4312 // If the content has an XR session, then we need to tell
4313 // VREventObserver that there is VR activity.
4314 if (mHasXRSession) {
4315 nsPIDOMWindowOuter* outer = GetOuterWindow();
4316 if (outer && !outer->IsBackground()) {
4317 StartVRActivity();
4318 }
4319 }
4320}
4321
4322void nsGlobalWindowInner::DisableVRUpdates() {
4323 if (mVREventObserver) {
4324 mVREventObserver->DisconnectFromOwner();
4325 mVREventObserver = nullptr;
4326 }
4327}
4328
4329void nsGlobalWindowInner::ResetVRTelemetry(bool aUpdate) {
4330 if (mVREventObserver) {
4331 mVREventObserver->UpdateSpentTimeIn2DTelemetry(aUpdate);
4332 }
4333}
4334
4335void nsGlobalWindowInner::StartVRActivity() {
4336 /**
4337 * If the content has an XR session, tell
4338 * the VREventObserver that the window is accessing
4339 * VR devices.
4340 *
4341 * It's possible to have a VREventObserver without
4342 * and XR session, if we are using it to get updates
4343 * about XR runtime enumeration. In this case,
4344 * we would not tell the VREventObserver that
4345 * we are accessing VR devices.
4346 */
4347 if (mVREventObserver && mHasXRSession) {
4348 mVREventObserver->StartActivity();
4349 }
4350}
4351
4352void nsGlobalWindowInner::StopVRActivity() {
4353 /**
4354 * If the content has an XR session, tell
4355 * the VReventObserver that the window is no longer
4356 * accessing VR devices. This does not stop the
4357 * XR session itself, which may be resumed with
4358 * EnableVRUpdates.
4359 * It's possible to have a VREventObserver without
4360 * and XR session, if we are using it to get updates
4361 * about XR runtime enumeration. In this case,
4362 * we would not tell the VREventObserver that
4363 * we ending an activity that accesses VR devices.
4364 */
4365 if (mVREventObserver && mHasXRSession) {
4366 mVREventObserver->StopActivity();
4367 }
4368}
4369
4370void nsGlobalWindowInner::SetFocusedElement(Element* aElement,
4371 uint32_t aFocusMethod,
4372 bool aNeedsFocus) {
4373 if (aElement && aElement->GetComposedDoc() != mDoc) {
4374 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"
, 4374)
;
4375 return;
4376 }
4377
4378 if (IsDying()) {
4379 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"
, 4379); MOZ_PretendNoReturn(); } } while (0)
;
4380 aElement = nullptr;
4381 aNeedsFocus = false;
4382 }
4383 if (mFocusedElement != aElement) {
4384 UpdateCanvasFocus(false, aElement);
4385 mFocusedElement = aElement;
4386 // TODO: Maybe this should be set on refocus too?
4387 mFocusMethod = aFocusMethod & nsIFocusManager::METHOD_MASK;
4388 }
4389
4390 if (mFocusedElement) {
4391 // if a node was focused by a keypress, turn on focus rings for the
4392 // window.
4393 if (mFocusMethod & nsIFocusManager::FLAG_BYKEY) {
4394 mUnknownFocusMethodShouldShowOutline = true;
4395 mFocusByKeyOccurred = true;
4396 } else if (nsFocusManager::GetFocusMoveActionCause(mFocusMethod) !=
4397 widget::InputContextAction::CAUSE_UNKNOWN) {
4398 mUnknownFocusMethodShouldShowOutline = false;
4399 } else if (aFocusMethod & nsIFocusManager::FLAG_NOSHOWRING) {
4400 // If we get focused via script, and script has explicitly opted out of
4401 // outlines via FLAG_NOSHOWRING, we don't want to make a refocus start
4402 // showing outlines.
4403 mUnknownFocusMethodShouldShowOutline = false;
4404 }
4405 }
4406
4407 if (aNeedsFocus) {
4408 mNeedsFocus = aNeedsFocus;
4409 }
4410}
4411
4412uint32_t nsGlobalWindowInner::GetFocusMethod() { return mFocusMethod; }
4413
4414bool nsGlobalWindowInner::ShouldShowFocusRing() {
4415 if (mFocusByKeyOccurred &&
4416 StaticPrefs::browser_display_always_show_rings_after_key_focus()) {
4417 return true;
4418 }
4419 return StaticPrefs::browser_display_show_focus_rings();
4420}
4421
4422bool nsGlobalWindowInner::TakeFocus(bool aFocus, uint32_t aFocusMethod) {
4423 if (IsDying()) {
4424 return false;
4425 }
4426
4427 if (aFocus) {
4428 mFocusMethod = aFocusMethod & nsIFocusManager::METHOD_MASK;
4429 }
4430
4431 if (mHasFocus != aFocus) {
4432 mHasFocus = aFocus;
4433 UpdateCanvasFocus(true, mFocusedElement);
4434 }
4435
4436 // if mNeedsFocus is true, then the document has not yet received a
4437 // document-level focus event. If there is a root content node, then return
4438 // true to tell the calling focus manager that a focus event is expected. If
4439 // there is no root content node, the document hasn't loaded enough yet, or
4440 // there isn't one and there is no point in firing a focus event.
4441 if (aFocus && mNeedsFocus && mDoc && mDoc->GetRootElement() != nullptr) {
4442 mNeedsFocus = false;
4443 return true;
4444 }
4445
4446 mNeedsFocus = false;
4447 return false;
4448}
4449
4450void nsGlobalWindowInner::SetReadyForFocus() {
4451 bool oldNeedsFocus = mNeedsFocus;
4452 mNeedsFocus = false;
4453
4454 if (RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager()) {
4455 nsCOMPtr<nsPIDOMWindowOuter> outerWindow = GetOuterWindow();
4456 fm->WindowShown(outerWindow, oldNeedsFocus);
4457 }
4458}
4459
4460void nsGlobalWindowInner::PageHidden() {
4461 // the window is being hidden, so tell the focus manager that the frame is
4462 // no longer valid. Use the persisted field to determine if the document
4463 // is being destroyed.
4464
4465 if (RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager()) {
4466 nsCOMPtr<nsPIDOMWindowOuter> outerWindow = GetOuterWindow();
4467 fm->WindowHidden(outerWindow, nsFocusManager::GenerateFocusActionId());
4468 }
4469
4470 mNeedsFocus = true;
4471}
4472
4473class HashchangeCallback : public Runnable {
4474 public:
4475 HashchangeCallback(const nsAString& aOldURL, const nsAString& aNewURL,
4476 nsGlobalWindowInner* aWindow)
4477 : mozilla::Runnable("HashchangeCallback"), mWindow(aWindow) {
4478 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"
, 4478); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mWindow" ")"
); do { *((volatile int*)__null) = 4478; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4479 mOldURL.Assign(aOldURL);
4480 mNewURL.Assign(aNewURL);
4481 }
4482
4483 NS_IMETHODvirtual nsresult Run() override {
4484 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"
, 4484); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Should be called on the main thread." ")"); do { *((volatile
int*)__null) = 4484; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
4485 return mWindow->FireHashchange(mOldURL, mNewURL);
4486 }
4487
4488 private:
4489 nsString mOldURL;
4490 nsString mNewURL;
4491 RefPtr<nsGlobalWindowInner> mWindow;
4492};
4493
4494nsresult nsGlobalWindowInner::DispatchAsyncHashchange(nsIURI* aOldURI,
4495 nsIURI* aNewURI) {
4496 // Make sure that aOldURI and aNewURI are identical up to the '#', and that
4497 // their hashes are different.
4498 bool equal = false;
4499 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"
, 4500); return NS_ERROR_UNEXPECTED; } } while (false)
4500 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"
, 4500); return NS_ERROR_UNEXPECTED; } } while (false)
;
4501 nsAutoCString oldHash, newHash;
4502 bool oldHasHash, newHasHash;
4503 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"
, 4507); return NS_ERROR_UNEXPECTED; } } while (false)
4504 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"
, 4507); return NS_ERROR_UNEXPECTED; } } while (false)
4505 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"
, 4507); return NS_ERROR_UNEXPECTED; } } while (false)
4506 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"
, 4507); return NS_ERROR_UNEXPECTED; } } while (false)
4507 (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"
, 4507); return NS_ERROR_UNEXPECTED; } } while (false)
;
4508
4509 nsAutoCString oldSpec, newSpec;
4510 nsresult rv = aOldURI->GetSpec(oldSpec);
4511 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"
, 4511); return rv; } } while (false)
;
4512 rv = aNewURI->GetSpec(newSpec);
4513 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"
, 4513); return rv; } } while (false)
;
4514
4515 NS_ConvertUTF8toUTF16 oldWideSpec(oldSpec);
4516 NS_ConvertUTF8toUTF16 newWideSpec(newSpec);
4517
4518 nsCOMPtr<nsIRunnable> callback =
4519 new HashchangeCallback(oldWideSpec, newWideSpec, this);
4520 return Dispatch(callback.forget());
4521}
4522
4523nsresult nsGlobalWindowInner::FireHashchange(const nsAString& aOldURL,
4524 const nsAString& aNewURL) {
4525 // Don't do anything if the window is frozen.
4526 if (IsFrozen()) {
4527 return NS_OK;
4528 }
4529
4530 // Get a presentation shell for use in creating the hashchange event.
4531 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"
, 4531); return NS_ERROR_UNEXPECTED; } } while (false)
;
4532
4533 HashChangeEventInit init;
4534 init.mNewURL = aNewURL;
4535 init.mOldURL = aOldURL;
4536
4537 RefPtr<HashChangeEvent> event =
4538 HashChangeEvent::Constructor(this, u"hashchange"_ns, init);
4539
4540 event->SetTrusted(true);
4541
4542 ErrorResult rv;
4543 DispatchEvent(*event, rv);
4544 return rv.StealNSResult();
4545}
4546
4547nsresult nsGlobalWindowInner::DispatchSyncPopState() {
4548 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"
, 4549); MOZ_PretendNoReturn(); } } while (0)
4549 "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"
, 4549); MOZ_PretendNoReturn(); } } while (0)
;
4550
4551 // Bail if the window is frozen.
4552 if (IsFrozen()) {
4553 return NS_OK;
4554 }
4555
4556 AutoJSAPI jsapi;
4557 bool result = jsapi.Init(this);
4558 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"
, 4558); return NS_ERROR_FAILURE; } } while (false)
;
4559
4560 JSContext* cx = jsapi.cx();
4561
4562 // Get the document's pending state object -- it contains the data we're
4563 // going to send along with the popstate event. The object is serialized
4564 // using structured clone.
4565 JS::Rooted<JS::Value> stateJSValue(cx);
4566 nsresult rv = mDoc->GetStateObject(&stateJSValue);
4567 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"
, 4567); return rv; } } while (false)
;
4568
4569 if (!JS_WrapValue(cx, &stateJSValue)) {
4570 return NS_ERROR_OUT_OF_MEMORY;
4571 }
4572
4573 RootedDictionary<PopStateEventInit> init(cx);
4574 init.mState = stateJSValue;
4575
4576 RefPtr<PopStateEvent> event =
4577 PopStateEvent::Constructor(this, u"popstate"_ns, init);
4578 event->SetTrusted(true);
4579 event->SetTarget(this);
4580
4581 ErrorResult err;
4582 DispatchEvent(*event, err);
4583 return err.StealNSResult();
4584}
4585
4586//-------------------------------------------------------
4587// Tells the HTMLFrame/CanvasFrame that is now has focus
4588void nsGlobalWindowInner::UpdateCanvasFocus(bool aFocusChanged,
4589 nsIContent* aNewContent) {
4590 // this is called from the inner window so use GetDocShell
4591 nsIDocShell* docShell = GetDocShell();
4592 if (!docShell) return;
4593
4594 bool editable;
4595 docShell->GetEditable(&editable);
4596 if (editable) return;
4597
4598 PresShell* presShell = docShell->GetPresShell();
4599 if (!presShell || !mDoc) {
4600 return;
4601 }
4602
4603 Element* rootElement = mDoc->GetRootElement();
4604 if (rootElement) {
4605 if ((mHasFocus || aFocusChanged) &&
4606 (mFocusedElement == rootElement || aNewContent == rootElement)) {
4607 nsCanvasFrame* canvasFrame = presShell->GetCanvasFrame();
4608 if (canvasFrame) {
4609 canvasFrame->SetHasFocus(mHasFocus && rootElement == aNewContent);
4610 }
4611 }
4612 } else {
4613 // XXXbz I would expect that there is never a canvasFrame in this case...
4614 nsCanvasFrame* canvasFrame = presShell->GetCanvasFrame();
4615 if (canvasFrame) {
4616 canvasFrame->SetHasFocus(false);
4617 }
4618 }
4619}
4620
4621already_AddRefed<nsICSSDeclaration> nsGlobalWindowInner::GetComputedStyle(
4622 Element& aElt, const nsAString& aPseudoElt, ErrorResult& aError) {
4623 return GetComputedStyleHelper(aElt, aPseudoElt, false, aError);
4624}
4625
4626already_AddRefed<nsICSSDeclaration>
4627nsGlobalWindowInner::GetDefaultComputedStyle(Element& aElt,
4628 const nsAString& aPseudoElt,
4629 ErrorResult& aError) {
4630 return GetComputedStyleHelper(aElt, aPseudoElt, true, aError);
4631}
4632
4633already_AddRefed<nsICSSDeclaration> nsGlobalWindowInner::GetComputedStyleHelper(
4634 Element& aElt, const nsAString& aPseudoElt, bool aDefaultStylesOnly,
4635 ErrorResult& aError) {
4636 FORWARD_TO_OUTER_OR_THROW(GetComputedStyleHelperOuter,
4637 (aElt, aPseudoElt, aDefaultStylesOnly, aError),
4638 aError, nullptr);
4639}
4640
4641void nsGlobalWindowInner::MaybeNotifyStorageKeyUsed() {
4642 // Only notify once per window lifetime.
4643 if (hasNotifiedStorageKeyUsed) {
4644 return;
4645 }
4646 nsresult rv =
4647 BounceTrackingStorageObserver::OnInitialStorageAccess(GetWindowContext());
4648 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"
, 4648)
) {
4649 return;
4650 }
4651 hasNotifiedStorageKeyUsed = true;
4652}
4653
4654Storage* nsGlobalWindowInner::GetSessionStorage(ErrorResult& aError) {
4655 nsIPrincipal* principal = GetPrincipal();
4656 nsIPrincipal* storagePrincipal;
4657 if (StaticPrefs::
4658 privacy_partition_always_partition_third_party_non_cookie_storage_exempt_sessionstorage()) {
4659 storagePrincipal = GetEffectiveCookiePrincipal();
4660 } else {
4661 storagePrincipal = GetEffectiveStoragePrincipal();
4662 }
4663 BrowsingContext* browsingContext = GetBrowsingContext();
4664
4665 if (!principal || !storagePrincipal || !browsingContext ||
4666 !Storage::StoragePrefIsEnabled()) {
4667 return nullptr;
4668 }
4669
4670 if (mSessionStorage) {
4671 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)
4672 ("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)
4673 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)
;
4674 bool canAccess =
4675 principal->Subsumes(mSessionStorage->Principal()) &&
4676 storagePrincipal->Subsumes(mSessionStorage->StoragePrincipal());
4677 if (!canAccess) {
4678 mSessionStorage = nullptr;
4679 }
4680 }
4681
4682 if (!mSessionStorage) {
4683 nsString documentURI;
4684 if (mDoc) {
4685 aError = mDoc->GetDocumentURI(documentURI);
4686 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"
, 4686)
) {
4687 return nullptr;
4688 }
4689 }
4690
4691 if (!mDoc) {
4692 aError.Throw(NS_ERROR_FAILURE);
4693 return nullptr;
4694 }
4695
4696 // If the document's sandboxed origin flag is set, then accessing
4697 // sessionStorage is prohibited.
4698 if (mDoc->GetSandboxFlags() & SANDBOXED_ORIGIN) {
4699 aError.ThrowSecurityError(
4700 "Forbidden in a sandboxed document without the 'allow-same-origin' "
4701 "flag.");
4702 return nullptr;
4703 }
4704
4705 uint32_t rejectedReason = 0;
4706 StorageAccess access = StorageAllowedForWindow(this, &rejectedReason);
4707
4708 // SessionStorage is an ephemeral per-tab per-origin storage that only lives
4709 // as long as the tab is open, although it may survive browser restarts
4710 // thanks to the session store. So we interpret storage access differently
4711 // than we would for persistent per-origin storage like LocalStorage and so
4712 // it may be okay to provide SessionStorage even when we receive a value of
4713 // eDeny.
4714 //
4715 // ContentBlocking::ShouldAllowAccessFor will return false for 3 main
4716 // reasons.
4717 //
4718 // 1. Cookies are entirely blocked due to a per-origin permission
4719 // (nsICookiePermission::ACCESS_DENY for the top-level principal or this
4720 // window's principal) or the very broad BEHAVIOR_REJECT. This will return
4721 // eDeny with a reason of STATE_COOKIES_BLOCKED_BY_PERMISSION or
4722 // STATE_COOKIES_BLOCKED_ALL.
4723 //
4724 // 2. Third-party cookies are limited via BEHAVIOR_REJECT_FOREIGN and
4725 // BEHAVIOR_LIMIT_FOREIGN and this is a third-party window. This will return
4726 // eDeny with a reason of STATE_COOKIES_BLOCKED_FOREIGN.
4727 //
4728 // 3. Tracking protection (BEHAVIOR_REJECT_TRACKER and
4729 // BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN) is in effect and
4730 // IsThirdPartyTrackingResourceWindow() returned true and there wasn't a
4731 // permission that allows it. This will return ePartitionTrackersOrDeny with
4732 // a reason of STATE_COOKIES_BLOCKED_TRACKER or
4733 // STATE_COOKIES_BLOCKED_SOCIALTRACKER.
4734 //
4735 // In the 1st case, the user has explicitly indicated that they don't want
4736 // to allow any storage to the origin or all origins and so we throw an
4737 // error and deny access to SessionStorage. In the 2nd case, a legacy
4738 // decision reasoned that there's no harm in providing SessionStorage
4739 // because the information is not durable and cannot escape the current tab.
4740 // The rationale is similar for the 3rd case.
4741 if (access == StorageAccess::eDeny &&
4742 rejectedReason !=
4743 nsIWebProgressListener::STATE_COOKIES_BLOCKED_FOREIGN) {
4744 aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
4745 return nullptr;
4746 }
4747
4748 const RefPtr<SessionStorageManager> storageManager =
4749 browsingContext->GetSessionStorageManager();
4750 if (!storageManager) {
4751 aError.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
4752 return nullptr;
4753 }
4754
4755 RefPtr<Storage> storage;
4756 aError = storageManager->CreateStorage(this, principal, storagePrincipal,
4757 documentURI, IsPrivateBrowsing(),
4758 getter_AddRefs(storage));
4759 if (aError.Failed()) {
4760 return nullptr;
4761 }
4762
4763 mSessionStorage = storage;
4764 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"
, 4764); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mSessionStorage"
")"); do { *((volatile int*)__null) = 4764; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4765
4766 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)
4767 ("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)
4768 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)
;
4769
4770 if (!mSessionStorage) {
4771 aError.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
4772 return nullptr;
4773 }
4774 }
4775
4776 MaybeNotifyStorageKeyUsed();
4777
4778 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)
4779 ("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)
4780 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)
;
4781
4782 return mSessionStorage;
4783}
4784
4785Storage* nsGlobalWindowInner::GetLocalStorage(ErrorResult& aError) {
4786 if (!Storage::StoragePrefIsEnabled()) {
4787 return nullptr;
4788 }
4789
4790 // If the document's sandboxed origin flag is set, then accessing localStorage
4791 // is prohibited.
4792 if (mDoc && mDoc->GetSandboxFlags() & SANDBOXED_ORIGIN) {
4793 aError.ThrowSecurityError(
4794 "Forbidden in a sandboxed document without the 'allow-same-origin' "
4795 "flag.");
4796 return nullptr;
4797 }
4798
4799 // LocalStorage needs to be exposed in every context except for sandboxes and
4800 // NullPrincipals (data: URLs, for instance). But we need to keep data
4801 // separate in some scenarios: private-browsing and partitioned trackers.
4802 // In private-browsing, LocalStorage keeps data in memory, and it shares
4803 // StorageEvents just with other origins in the same private-browsing
4804 // environment.
4805 // For Partitioned Trackers, we expose a partitioned LocalStorage, which
4806 // doesn't share data with other contexts, and it's just in memory.
4807 // Partitioned localStorage is available only for trackers listed in the
4808 // privacy.restrict3rdpartystorage.partitionedHosts pref. See
4809 // nsContentUtils::IsURIInPrefList to know the syntax for the pref value.
4810 // This is a temporary web-compatibility hack.
4811
4812 StorageAccess access = StorageAllowedForWindow(this);
4813
4814 // We allow partitioned localStorage only to some hosts.
4815 bool isolated = false;
4816 if (ShouldPartitionStorage(access)) {
4817 if (!mDoc) {
4818 access = StorageAccess::eDeny;
4819 } else if (!StoragePartitioningEnabled(access, mDoc->CookieJarSettings())) {
4820 static const char* kPrefName =
4821 "privacy.restrict3rdpartystorage.partitionedHosts";
4822
4823 bool isInList = false;
4824 mDoc->NodePrincipal()->IsURIInPrefList(kPrefName, &isInList);
4825 if (!isInList) {
4826 access = StorageAccess::eDeny;
4827 } else {
4828 isolated = true;
4829 }
4830 }
4831 }
4832
4833 if (access == StorageAccess::eDeny) {
4834 aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
4835 return nullptr;
4836 }
4837
4838 nsCOMPtr<nsICookieJarSettings> cookieJarSettings;
4839 if (mDoc) {
4840 cookieJarSettings = mDoc->CookieJarSettings();
4841 } else {
4842 cookieJarSettings = net::CookieJarSettings::GetBlockingAll(
4843 ShouldResistFingerprinting(RFPTarget::IsAlwaysEnabledForPrecompute));
4844 }
4845
4846 // Note that this behavior is observable: if we grant storage permission to a
4847 // tracker, we pass from the partitioned LocalStorage (or a partitioned cookie
4848 // jar) to the 'normal' one. The previous data is lost and the 2
4849 // window.localStorage objects, before and after the permission granted, will
4850 // be different.
4851 if (mLocalStorage) {
4852 if ((mLocalStorage->Type() == (isolated ? Storage::ePartitionedLocalStorage
4853 : Storage::eLocalStorage)) &&
4854 (mLocalStorage->StoragePrincipal() == GetEffectiveStoragePrincipal())) {
4855 return mLocalStorage;
4856 }
4857
4858 // storage needs change
4859 mLocalStorage = nullptr;
4860 }
4861
4862 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"
, 4862); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mLocalStorage"
")"); do { *((volatile int*)__null) = 4862; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4863
4864 if (!isolated) {
4865 RefPtr<Storage> storage;
4866
4867 if (NextGenLocalStorageEnabled()) {
4868 aError = LSObject::CreateForWindow(this, getter_AddRefs(storage));
4869 } else {
4870 nsresult rv;
4871 nsCOMPtr<nsIDOMStorageManager> storageManager =
4872 do_GetService("@mozilla.org/dom/localStorage-manager;1", &rv);
4873 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4874 aError.Throw(rv);
4875 return nullptr;
4876 }
4877
4878 nsString documentURI;
4879 if (mDoc) {
4880 aError = mDoc->GetDocumentURI(documentURI);
4881 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"
, 4881)
) {
4882 return nullptr;
4883 }
4884 }
4885
4886 nsIPrincipal* principal = GetPrincipal();
4887 if (!principal) {
4888 aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
4889 return nullptr;
4890 }
4891
4892 nsIPrincipal* storagePrincipal = GetEffectiveStoragePrincipal();
4893 if (!storagePrincipal) {
4894 aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
4895 return nullptr;
4896 }
4897
4898 aError = storageManager->CreateStorage(this, principal, storagePrincipal,
4899 documentURI, IsPrivateBrowsing(),
4900 getter_AddRefs(storage));
4901 }
4902
4903 if (aError.Failed()) {
4904 return nullptr;
4905 }
4906
4907 mLocalStorage = storage;
4908 } else {
4909 nsresult rv;
4910 nsCOMPtr<nsIDOMSessionStorageManager> storageManager =
4911 do_GetService("@mozilla.org/dom/sessionStorage-manager;1", &rv);
4912 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4913 aError.Throw(rv);
4914 return nullptr;
4915 }
4916
4917 nsIPrincipal* principal = GetPrincipal();
4918 if (!principal) {
4919 aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
4920 return nullptr;
4921 }
4922
4923 nsIPrincipal* storagePrincipal = GetEffectiveStoragePrincipal();
4924 if (!storagePrincipal) {
4925 aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
4926 return nullptr;
4927 }
4928
4929 RefPtr<SessionStorageCache> cache;
4930 if (isolated) {
4931 cache = new SessionStorageCache();
4932 } else {
4933 // This will clone the session storage if it exists.
4934 rv = storageManager->GetSessionStorageCache(principal, storagePrincipal,
4935 &cache);
4936 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4937 aError.Throw(rv);
4938 return nullptr;
4939 }
4940 }
4941
4942 mLocalStorage =
4943 new PartitionedLocalStorage(this, principal, storagePrincipal, cache);
4944 }
4945
4946 MaybeNotifyStorageKeyUsed();
4947
4948 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"
, 4948); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLocalStorage"
")"); do { *((volatile int*)__null) = 4948; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4949 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"
, 4951); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLocalStorage->Type() == (isolated ? Storage::ePartitionedLocalStorage : Storage::eLocalStorage)"
")"); do { *((volatile int*)__null) = 4951; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4950 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"
, 4951); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLocalStorage->Type() == (isolated ? Storage::ePartitionedLocalStorage : Storage::eLocalStorage)"
")"); do { *((volatile int*)__null) = 4951; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4951 (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"
, 4951); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLocalStorage->Type() == (isolated ? Storage::ePartitionedLocalStorage : Storage::eLocalStorage)"
")"); do { *((volatile int*)__null) = 4951; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4952 return mLocalStorage;
4953}
4954
4955IDBFactory* nsGlobalWindowInner::GetIndexedDB(JSContext* aCx,
4956 ErrorResult& aError) {
4957 if (!mIndexedDB) {
4958 // This may keep mIndexedDB null without setting an error.
4959 auto res = IDBFactory::CreateForWindow(this);
4960 if (res.isErr()) {
4961 aError = res.unwrapErr();
4962 } else {
4963 mIndexedDB = res.unwrap();
4964 }
4965 }
4966
4967 MaybeNotifyStorageKeyUsed();
4968
4969 return mIndexedDB;
4970}
4971
4972//*****************************************************************************
4973// nsGlobalWindowInner::nsIInterfaceRequestor
4974//*****************************************************************************
4975
4976NS_IMETHODIMPnsresult
4977nsGlobalWindowInner::GetInterface(const nsIID& aIID, void** aSink) {
4978 nsGlobalWindowOuter* outer = GetOuterWindowInternal();
4979 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"
, 4979); return NS_ERROR_NOT_INITIALIZED; } } while (false)
;
4980
4981 nsresult rv = outer->GetInterfaceInternal(aIID, aSink);
4982 if (rv == NS_ERROR_NO_INTERFACE) {
4983 return QueryInterface(aIID, aSink);
4984 }
4985 return rv;
4986}
4987
4988void nsGlobalWindowInner::GetInterface(JSContext* aCx,
4989 JS::Handle<JS::Value> aIID,
4990 JS::MutableHandle<JS::Value> aRetval,
4991 ErrorResult& aError) {
4992 dom::GetInterface(aCx, this, aIID, aRetval, aError);
4993}
4994
4995already_AddRefed<CacheStorage> nsGlobalWindowInner::GetCaches(
4996 ErrorResult& aRv) {
4997 if (!mCacheStorage) {
4998 bool forceTrustedOrigin =
4999 GetBrowsingContext() &&
5000 GetBrowsingContext()->Top()->GetServiceWorkersTestingEnabled();
5001 mCacheStorage = CacheStorage::CreateOnMainThread(
5002 cache::DEFAULT_NAMESPACE, this, GetEffectiveStoragePrincipal(),
5003 forceTrustedOrigin, aRv);
5004 }
5005
5006 RefPtr<CacheStorage> ref = mCacheStorage;
5007 return ref.forget();
5008}
5009
5010void nsGlobalWindowInner::FireOfflineStatusEventIfChanged() {
5011 if (!IsCurrentInnerWindow()) return;
5012
5013 // Don't fire an event if the status hasn't changed
5014 if (mWasOffline == NS_IsOffline()) {
5015 return;
5016 }
5017
5018 mWasOffline = !mWasOffline;
5019
5020 nsAutoString name;
5021 if (mWasOffline) {
5022 name.AssignLiteral("offline");
5023 } else {
5024 name.AssignLiteral("online");
5025 }
5026 nsContentUtils::DispatchTrustedEvent(mDoc, this, name, CanBubble::eNo,
5027 Cancelable::eNo);
5028}
5029
5030nsGlobalWindowInner::SlowScriptResponse
5031nsGlobalWindowInner::ShowSlowScriptDialog(JSContext* aCx,
5032 const nsString& aAddonId,
5033 const double aDuration) {
5034 nsresult rv;
5035
5036 if (Preferences::GetBool("dom.always_stop_slow_scripts")) {
1
Assuming the condition is false
2
Taking false branch
5037 return KillSlowScript;
5038 }
5039
5040 // If it isn't safe to run script, then it isn't safe to bring up the prompt
5041 // (since that spins the event loop). In that (rare) case, we just kill the
5042 // script and report a warning.
5043 if (!nsContentUtils::IsSafeToRunScript()) {
3
Assuming the condition is false
4
Taking false branch
5044 JS::WarnASCII(aCx, "A long running script was terminated");
5045 return KillSlowScript;
5046 }
5047
5048 // If our document is not active, just kill the script: we've been unloaded
5049 if (!HasActiveDocument()) {
5
Assuming the condition is false
6
Taking false branch
5050 return KillSlowScript;
5051 }
5052
5053 // Check if we should offer the option to debug
5054 JS::AutoFilename filename;
5055 uint32_t lineno;
7
'lineno' declared without an initial value
5056 // Computing the line number can be very expensive (see bug 1330231 for
5057 // example), and we don't use the line number anywhere except than in the
5058 // parent process, so we avoid computing it elsewhere. This gives us most of
5059 // the wins we are interested in, since the source of the slowness here is
5060 // minified scripts which is more common in Web content that is loaded in the
5061 // content process.
5062 uint32_t* linenop = XRE_IsParentProcess() ? &lineno : nullptr;
8
Assuming the condition is false
9
'?' condition is false
5063 bool hasFrame = JS::DescribeScriptedCaller(aCx, &filename, linenop);
5064
5065 // Record the slow script event if we haven't done so already for this inner
5066 // window (which represents a particular page to the user).
5067 if (!mHasHadSlowScript) {
10
Assuming field 'mHasHadSlowScript' is true
11
Taking false branch
5068 Telemetry::Accumulate(Telemetry::SLOW_SCRIPT_PAGE_COUNT, 1);
5069 }
5070 mHasHadSlowScript = true;
5071
5072 // Override the cursor to something that we're sure the user can see.
5073 SetCursor("auto"_ns, IgnoreErrors());
5074
5075 if (XRE_IsContentProcess() && ProcessHangMonitor::Get()) {
12
Assuming the condition is false
5076 ProcessHangMonitor::SlowScriptAction action;
5077 RefPtr<ProcessHangMonitor> monitor = ProcessHangMonitor::Get();
5078 nsIDocShell* docShell = GetDocShell();
5079 nsCOMPtr<nsIBrowserChild> child =
5080 docShell ? docShell->GetBrowserChild() : nullptr;
5081 action =
5082 monitor->NotifySlowScript(child, filename.get(), aAddonId, aDuration);
5083 if (action == ProcessHangMonitor::Terminate) {
5084 return KillSlowScript;
5085 }
5086
5087 if (action == ProcessHangMonitor::StartDebugger) {
5088 // Spin a nested event loop so that the debugger in the parent can fetch
5089 // any information it needs. Once the debugger has started, return to the
5090 // script.
5091 RefPtr<nsGlobalWindowOuter> outer = GetOuterWindowInternal();
5092 outer->EnterModalState();
5093 SpinEventLoopUntil("nsGlobalWindowInner::ShowSlowScriptDialog"_ns, [&]() {
5094 return monitor->IsDebuggerStartupComplete();
5095 });
5096 outer->LeaveModalState();
5097 return ContinueSlowScript;
5098 }
5099
5100 return ContinueSlowScriptAndKeepNotifying;
5101 }
5102
5103 // Reached only on non-e10s - once per slow script dialog.
5104 // On e10s - we probe once at ProcessHangsMonitor.sys.mjs
5105 Telemetry::Accumulate(Telemetry::SLOW_SCRIPT_NOTICE_COUNT, 1);
5106
5107 // Get the nsIPrompt interface from the docshell
5108 nsCOMPtr<nsIDocShell> ds = GetDocShell();
5109 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"
, 5109); return KillSlowScript; } } while (false)
;
13
Taking false branch
14
Loop condition is false. Exiting loop
5110 nsCOMPtr<nsIPrompt> prompt = do_GetInterface(ds);
5111 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"
, 5111); return KillSlowScript; } } while (false)
;
15
Taking false branch
16
Loop condition is false. Exiting loop
5112
5113 // Prioritize the SlowScriptDebug interface over JSD1.
5114 nsCOMPtr<nsISlowScriptDebugCallback> debugCallback;
5115
5116 if (hasFrame) {
17
Assuming 'hasFrame' is false
18
Taking false branch
5117 const char* debugCID = "@mozilla.org/dom/slow-script-debug;1";
5118 nsCOMPtr<nsISlowScriptDebug> debugService = do_GetService(debugCID, &rv);
5119 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5120 debugService->GetActivationHandler(getter_AddRefs(debugCallback));
5121 }
5122 }
5123
5124 bool failed = false;
5125 auto getString = [&](const char* name,
5126 nsContentUtils::PropertiesFile propFile =
5127 nsContentUtils::eDOM_PROPERTIES) {
5128 nsAutoString result;
5129 nsresult rv = nsContentUtils::GetLocalizedString(propFile, name, result);
5130
5131 // GetStringFromName can return NS_OK and still give nullptr string
5132 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
5133 return result;
5134 };
5135
5136 bool isAddonScript = !aAddonId.IsEmpty();
19
Assuming the condition is false
5137 bool showDebugButton = debugCallback && !isAddonScript;
5138
5139 // Get localizable strings
5140
5141 nsAutoString title, checkboxMsg, debugButton, msg;
5142 if (isAddonScript
19.1
'isAddonScript' is false
) {
20
Taking false branch
5143 title = getString("KillAddonScriptTitle");
5144 checkboxMsg = getString("KillAddonScriptGlobalMessage");
5145
5146 auto appName =
5147 getString("brandShortName", nsContentUtils::eBRAND_PROPERTIES);
5148
5149 nsCOMPtr<nsIAddonPolicyService> aps =
5150 do_GetService("@mozilla.org/addons/policy-service;1");
5151 nsString addonName;
5152 if (!aps || NS_FAILED(aps->GetExtensionName(aAddonId, addonName))((bool)(__builtin_expect(!!(NS_FAILED_impl(aps->GetExtensionName
(aAddonId, addonName))), 0)))
) {
5153 addonName = aAddonId;
5154 }
5155
5156 rv = nsContentUtils::FormatLocalizedString(
5157 msg, nsContentUtils::eDOM_PROPERTIES, "KillAddonScriptMessage",
5158 addonName, appName);
5159
5160 failed = failed || NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)));
5161 } else {
5162 title = getString("KillScriptTitle");
5163 checkboxMsg = getString("DontAskAgain");
5164
5165 if (showDebugButton
20.1
'showDebugButton' is false
) {
21
Taking false branch
5166 debugButton = getString("DebugScriptButton");
5167 msg = getString("KillScriptWithDebugMessage");
5168 } else {
5169 msg = getString("KillScriptMessage");
5170 }
5171 }
5172
5173 auto stopButton = getString("StopScriptButton");
5174 auto waitButton = getString("WaitForScriptButton");
22
Calling 'operator()'
26
Returning from 'operator()'
5175
5176 if (failed) {
27
Assuming 'failed' is false
28
Taking false branch
5177 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"
, 5177); MOZ_PretendNoReturn(); } while (0)
;
5178 return ContinueSlowScript;
5179 }
5180
5181 // Append file and line number information, if available
5182 if (filename.get()) {
29
Assuming the condition is true
30
Taking true branch
5183 nsAutoString scriptLocation;
5184 // We want to drop the middle part of too-long locations. We'll
5185 // define "too-long" as longer than 60 UTF-16 code units. Just
5186 // have to be a bit careful about unpaired surrogates.
5187 NS_ConvertUTF8toUTF16 filenameUTF16(filename.get());
5188 if (filenameUTF16.Length() > 60) {
31
Assuming the condition is false
32
Taking false branch
5189 // XXXbz Do we need to insert any bidi overrides here?
5190 size_t cutStart = 30;
5191 size_t cutLength = filenameUTF16.Length() - 60;
5192 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"
, 5192); AnnotateMozCrashReason("MOZ_ASSERT" "(" "cutLength > 0"
")"); do { *((volatile int*)__null) = 5192; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5193 if (NS_IS_LOW_SURROGATE(filenameUTF16[cutStart])((uint32_t(filenameUTF16[cutStart]) & 0xFFFFFC00) == 0xDC00
)
) {
5194 // Don't truncate before the low surrogate, in case it's preceded by a
5195 // high surrogate and forms a single Unicode character. Instead, just
5196 // include the low surrogate.
5197 ++cutStart;
5198 --cutLength;
5199 }
5200 if (NS_IS_LOW_SURROGATE(filenameUTF16[cutStart + cutLength])((uint32_t(filenameUTF16[cutStart + cutLength]) & 0xFFFFFC00
) == 0xDC00)
) {
5201 // Likewise, don't drop a trailing low surrogate here. We want to
5202 // increase cutLength, since it might be 0 already so we can't very well
5203 // decrease it.
5204 ++cutLength;
5205 }
5206
5207 // Insert U+2026 HORIZONTAL ELLIPSIS
5208 filenameUTF16.ReplaceLiteral(cutStart, cutLength, u"\x2026");
5209 }
5210 rv = nsContentUtils::FormatLocalizedString(
5211 scriptLocation, nsContentUtils::eDOM_PROPERTIES, "KillScriptLocation",
5212 filenameUTF16);
5213
5214 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
33
Assuming the condition is true
34
Taking true branch
5215 msg.AppendLiteral("\n\n");
5216 msg.Append(scriptLocation);
5217 msg.Append(':');
5218 msg.AppendInt(lineno);
35
1st function call argument is an uninitialized value
5219 }
5220 }
5221
5222 uint32_t buttonFlags = nsIPrompt::BUTTON_POS_1_DEFAULT +
5223 (nsIPrompt::BUTTON_TITLE_IS_STRING *
5224 (nsIPrompt::BUTTON_POS_0 + nsIPrompt::BUTTON_POS_1));
5225
5226 // Add a third button if necessary.
5227 if (showDebugButton)
5228 buttonFlags += nsIPrompt::BUTTON_TITLE_IS_STRING * nsIPrompt::BUTTON_POS_2;
5229
5230 bool checkboxValue = false;
5231 int32_t buttonPressed = 0; // In case the user exits dialog by clicking X.
5232 {
5233 // Null out the operation callback while we're re-entering JS here.
5234 AutoDisableJSInterruptCallback disabler(aCx);
5235
5236 // Open the dialog.
5237 rv = prompt->ConfirmEx(
5238 title.get(), msg.get(), buttonFlags, waitButton.get(), stopButton.get(),
5239 debugButton.get(), checkboxMsg.get(), &checkboxValue, &buttonPressed);
5240 }
5241
5242 if (buttonPressed == 0) {
5243 if (checkboxValue && !isAddonScript && NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))))
5244 return AlwaysContinueSlowScript;
5245 return ContinueSlowScript;
5246 }
5247
5248 if (buttonPressed == 2) {
5249 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"
, 5249); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "debugCallback"
")"); do { *((volatile int*)__null) = 5249; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5250
5251 rv = debugCallback->HandleSlowScriptDebug(this);
5252 return NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) ? ContinueSlowScript : KillSlowScript;
5253 }
5254
5255 JS_ClearPendingException(aCx);
5256
5257 return KillSlowScript;
5258}
5259
5260nsresult nsGlobalWindowInner::Observe(nsISupports* aSubject, const char* aTopic,
5261 const char16_t* aData) {
5262 if (!nsCRT::strcmp(aTopic, NS_IOSERVICE_OFFLINE_STATUS_TOPIC"network:offline-status-changed")) {
5263 if (!IsFrozen()) {
5264 // Fires an offline status event if the offline status has changed
5265 FireOfflineStatusEventIfChanged();
5266 }
5267 return NS_OK;
5268 }
5269
5270 if (!nsCRT::strcmp(aTopic, MEMORY_PRESSURE_OBSERVER_TOPIC"memory-pressure")) {
5271 if (mPerformance) {
5272 mPerformance->MemoryPressure();
5273 }
5274 RemoveReportRecords();
5275 return NS_OK;
5276 }
5277
5278 if (!nsCRT::strcmp(aTopic, PERMISSION_CHANGED_TOPIC"perm-changed")) {
5279 nsCOMPtr<nsIPermission> perm(do_QueryInterface(aSubject));
5280 if (!perm) {
5281 // A null permission indicates that the entire permission list
5282 // was cleared.
5283 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"
, 5283); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!nsCRT::strcmp(aData, u\"cleared\")"
")"); do { *((volatile int*)__null) = 5283; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5284 UpdatePermissions();
5285 return NS_OK;
5286 }
5287
5288 nsAutoCString type;
5289 perm->GetType(type);
5290 if (type == "autoplay-media"_ns) {
5291 UpdateAutoplayPermission();
5292 } else if (type == "shortcuts"_ns) {
5293 UpdateShortcutsPermission();
5294 } else if (type == "popup"_ns) {
5295 UpdatePopupPermission();
5296 }
5297
5298 if (!mDoc) {
5299 return NS_OK;
5300 }
5301
5302 RefPtr<PermissionDelegateHandler> permDelegateHandler =
5303 mDoc->GetPermissionDelegateHandler();
5304
5305 if (permDelegateHandler) {
5306 permDelegateHandler->UpdateDelegatedPermission(type);
5307 }
5308
5309 return NS_OK;
5310 }
5311
5312 if (!nsCRT::strcmp(aTopic, "screen-information-changed")) {
5313 if (mScreen) {
5314 if (RefPtr<ScreenOrientation> orientation =
5315 mScreen->GetOrientationIfExists()) {
5316 orientation->MaybeChanged();
5317 }
5318 }
5319 if (mHasOrientationChangeListeners) {
5320 int32_t oldAngle = mOrientationAngle;
5321 mOrientationAngle = Orientation(CallerType::System);
5322 if (mOrientationAngle != oldAngle && IsCurrentInnerWindow()) {
5323 nsCOMPtr<nsPIDOMWindowOuter> outer = GetOuterWindow();
5324 outer->DispatchCustomEvent(u"orientationchange"_ns);
5325 }
5326 }
5327 return NS_OK;
5328 }
5329
5330 if (!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID"nsPref:changed")) {
5331 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"
, 5331); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_strcmp(aData, u\"intl.accept_languages\")"
")"); do { *((volatile int*)__null) = 5331; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5332
5333 // The user preferred languages have changed, we need to fire an event on
5334 // Window object and invalidate the cache for navigator.languages. It is
5335 // done for every change which can be a waste of cycles but those should be
5336 // fairly rare.
5337 // We MUST invalidate navigator.languages before sending the event in the
5338 // very likely situation where an event handler will try to read its value.
5339
5340 if (mNavigator) {
5341 Navigator_Binding::ClearCachedLanguageValue(mNavigator);
5342 Navigator_Binding::ClearCachedLanguagesValue(mNavigator);
5343 }
5344
5345 // The event has to be dispatched only to the current inner window.
5346 if (!IsCurrentInnerWindow()) {
5347 return NS_OK;
5348 }
5349
5350 RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
5351 event->InitEvent(u"languagechange"_ns, false, false);
5352 event->SetTrusted(true);
5353
5354 ErrorResult rv;
5355 DispatchEvent(*event, rv);
5356 return rv.StealNSResult();
5357 }
5358
5359 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"
, 5359)
;
5360 return NS_ERROR_FAILURE;
5361}
5362
5363void nsGlobalWindowInner::ObserveStorageNotification(
5364 StorageEvent* aEvent, const char16_t* aStorageType, bool aPrivateBrowsing) {
5365 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"
, 5365); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent" ")"
); do { *((volatile int*)__null) = 5365; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5366
5367 // The private browsing check must be done here again because this window
5368 // could have changed its state before the notification check and now. This
5369 // happens in case this window did have a docShell at that time.
5370 if (aPrivateBrowsing != IsPrivateBrowsing()) {
5371 return;
5372 }
5373
5374 // LocalStorage can only exist on an inner window, and we don't want to
5375 // generate events on frozen or otherwise-navigated-away from windows.
5376 // (Actually, this code used to try and buffer events for frozen windows,
5377 // but it never worked, so we've removed it. See bug 1285898.)
5378 if (!IsCurrentInnerWindow() || IsFrozen()) {
5379 return;
5380 }
5381
5382 nsIPrincipal* principal = GetPrincipal();
5383 if (!principal) {
5384 return;
5385 }
5386
5387 bool fireMozStorageChanged = false;
5388 nsAutoString eventType;
5389 eventType.AssignLiteral("storage");
5390
5391