File: | var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp |
Warning: | line 5205, column 7 1st function call argument is an uninitialized value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ | |||
2 | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ | |||
3 | /* This Source Code Form is subject to the terms of the Mozilla Public | |||
4 | * License, v. 2.0. If a copy of the MPL was not distributed with this | |||
5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |||
6 | ||||
7 | #include "nsGlobalWindowInner.h" | |||
8 | ||||
9 | #include <inttypes.h> | |||
10 | #include <stdio.h> | |||
11 | #include <stdlib.h> | |||
12 | #include <string.h> | |||
13 | #include <cstdint> | |||
14 | #include <new> | |||
15 | #include <type_traits> | |||
16 | #include <utility> | |||
17 | #include "AudioChannelService.h" | |||
18 | #include "AutoplayPolicy.h" | |||
19 | #include "Crypto.h" | |||
20 | #include "MainThreadUtils.h" | |||
21 | #include "Navigator.h" | |||
22 | #include "PaintWorkletImpl.h" | |||
23 | #include "SessionStorageCache.h" | |||
24 | #include "Units.h" | |||
25 | #include "VRManagerChild.h" | |||
26 | #include "WindowDestroyedEvent.h" | |||
27 | #include "WindowNamedPropertiesHandler.h" | |||
28 | #include "js/ComparisonOperators.h" | |||
29 | #include "js/CompileOptions.h" | |||
30 | #include "js/friend/PerformanceHint.h" | |||
31 | #include "js/Id.h" | |||
32 | #include "js/loader/LoadedScript.h" | |||
33 | #include "js/PropertyAndElement.h" // JS_DefineProperty, JS_GetProperty | |||
34 | #include "js/PropertyDescriptor.h" | |||
35 | #include "js/RealmOptions.h" | |||
36 | #include "js/RootingAPI.h" | |||
37 | #include "js/TypeDecls.h" | |||
38 | #include "js/Value.h" | |||
39 | #include "js/Warnings.h" | |||
40 | #include "js/shadow/String.h" | |||
41 | #include "jsapi.h" | |||
42 | #include "jsfriendapi.h" | |||
43 | #include "mozIDOMWindow.h" | |||
44 | #include "moz_external_vr.h" | |||
45 | #include "mozilla/AlreadyAddRefed.h" | |||
46 | #include "mozilla/ArrayIterator.h" | |||
47 | #include "mozilla/ArrayUtils.h" | |||
48 | #include "mozilla/Attributes.h" | |||
49 | #include "mozilla/BaseProfilerMarkersPrerequisites.h" | |||
50 | #include "mozilla/BasicEvents.h" | |||
51 | #include "mozilla/BounceTrackingStorageObserver.h" | |||
52 | #include "mozilla/CallState.h" | |||
53 | #include "mozilla/CycleCollectedJSContext.h" | |||
54 | #include "mozilla/DOMEventTargetHelper.h" | |||
55 | #include "mozilla/ErrorResult.h" | |||
56 | #include "mozilla/EventDispatcher.h" | |||
57 | #include "mozilla/EventListenerManager.h" | |||
58 | #include "mozilla/EventQueue.h" | |||
59 | #include "mozilla/ExtensionPolicyService.h" | |||
60 | #include "mozilla/FloatingPoint.h" | |||
61 | #include "mozilla/FlushType.h" | |||
62 | #include "mozilla/Likely.h" | |||
63 | #include "mozilla/LinkedList.h" | |||
64 | #include "mozilla/LookAndFeel.h" | |||
65 | #include "mozilla/Logging.h" | |||
66 | #include "mozilla/MacroForEach.h" | |||
67 | #include "mozilla/Maybe.h" | |||
68 | #include "mozilla/OwningNonNull.h" | |||
69 | #include "mozilla/PermissionDelegateHandler.h" | |||
70 | #include "mozilla/Preferences.h" | |||
71 | #include "mozilla/PresShell.h" | |||
72 | #include "mozilla/ProcessHangMonitor.h" | |||
73 | #include "mozilla/RefPtr.h" | |||
74 | #include "mozilla/Result.h" | |||
75 | #include "mozilla/ScrollContainerFrame.h" | |||
76 | #include "mozilla/ScrollTypes.h" | |||
77 | #include "mozilla/Components.h" | |||
78 | #include "mozilla/SizeOfState.h" | |||
79 | #include "mozilla/Span.h" | |||
80 | #include "mozilla/SpinEventLoopUntil.h" | |||
81 | #include "mozilla/Sprintf.h" | |||
82 | #include "mozilla/StaticPrefs_browser.h" | |||
83 | #include "mozilla/StaticPrefs_docshell.h" | |||
84 | #include "mozilla/StaticPrefs_dom.h" | |||
85 | #include "mozilla/StaticPrefs_extensions.h" | |||
86 | #include "mozilla/StaticPrefs_privacy.h" | |||
87 | #include "mozilla/StorageAccess.h" | |||
88 | #include "mozilla/StoragePrincipalHelper.h" | |||
89 | #include "mozilla/Telemetry.h" | |||
90 | #include "mozilla/TelemetryHistogramEnums.h" | |||
91 | #include "mozilla/TimeStamp.h" | |||
92 | #include "mozilla/UniquePtr.h" | |||
93 | #include "mozilla/Unused.h" | |||
94 | #include "mozilla/dom/AudioContext.h" | |||
95 | #include "mozilla/dom/AutoEntryScript.h" | |||
96 | #include "mozilla/dom/BarProps.h" | |||
97 | #include "mozilla/dom/BindingDeclarations.h" | |||
98 | #include "mozilla/dom/BindingUtils.h" | |||
99 | #include "mozilla/dom/BrowserChild.h" | |||
100 | #include "mozilla/dom/BrowsingContext.h" | |||
101 | #include "mozilla/dom/Credential.h" | |||
102 | #include "mozilla/dom/CSPEvalChecker.h" | |||
103 | #include "mozilla/dom/CallbackDebuggerNotification.h" | |||
104 | #include "mozilla/dom/ChromeMessageBroadcaster.h" | |||
105 | #include "mozilla/dom/ClientInfo.h" | |||
106 | #include "mozilla/dom/ClientManager.h" | |||
107 | #include "mozilla/dom/ClientSource.h" | |||
108 | #include "mozilla/dom/ClientState.h" | |||
109 | #include "mozilla/dom/ClientsBinding.h" | |||
110 | #include "mozilla/dom/Console.h" | |||
111 | #include "mozilla/dom/ContentChild.h" | |||
112 | #include "mozilla/dom/ContentFrameMessageManager.h" | |||
113 | #include "mozilla/dom/ContentMediaController.h" | |||
114 | #include "mozilla/dom/CustomElementRegistry.h" | |||
115 | #include "mozilla/dom/DebuggerNotification.h" | |||
116 | #include "mozilla/dom/DebuggerNotificationBinding.h" | |||
117 | #include "mozilla/dom/DebuggerNotificationManager.h" | |||
118 | #include "mozilla/dom/DocGroup.h" | |||
119 | #include "mozilla/dom/Document.h" | |||
120 | #include "mozilla/dom/DocumentInlines.h" | |||
121 | #include "mozilla/dom/Element.h" | |||
122 | #include "mozilla/dom/Event.h" | |||
123 | #include "mozilla/dom/EventTarget.h" | |||
124 | #include "mozilla/dom/External.h" | |||
125 | #include "mozilla/dom/Fetch.h" | |||
126 | #include "mozilla/dom/Gamepad.h" | |||
127 | #include "mozilla/dom/GamepadHandle.h" | |||
128 | #include "mozilla/dom/GamepadManager.h" | |||
129 | #include "mozilla/dom/HashChangeEvent.h" | |||
130 | #include "mozilla/dom/HashChangeEventBinding.h" | |||
131 | #include "mozilla/dom/IDBFactory.h" | |||
132 | #include "mozilla/dom/IdleRequest.h" | |||
133 | #include "mozilla/dom/ImageBitmap.h" | |||
134 | #include "mozilla/dom/ImageBitmapSource.h" | |||
135 | #include "mozilla/dom/InstallTriggerBinding.h" | |||
136 | #include "mozilla/dom/IntlUtils.h" | |||
137 | #include "mozilla/dom/JSExecutionContext.h" | |||
138 | #include "mozilla/dom/LSObject.h" | |||
139 | #include "mozilla/dom/LocalStorage.h" | |||
140 | #include "mozilla/dom/LocalStorageCommon.h" | |||
141 | #include "mozilla/dom/Location.h" | |||
142 | #include "mozilla/dom/MediaDevices.h" | |||
143 | #include "mozilla/dom/MediaKeys.h" | |||
144 | #include "mozilla/dom/Navigation.h" | |||
145 | #include "mozilla/dom/NavigatorBinding.h" | |||
146 | #include "mozilla/dom/Nullable.h" | |||
147 | #include "mozilla/dom/PartitionedLocalStorage.h" | |||
148 | #include "mozilla/dom/Performance.h" | |||
149 | #include "mozilla/dom/PerformanceMainThread.h" | |||
150 | #include "mozilla/dom/PopStateEvent.h" | |||
151 | #include "mozilla/dom/PopStateEventBinding.h" | |||
152 | #include "mozilla/dom/PopupBlocker.h" | |||
153 | #include "mozilla/dom/PrimitiveConversions.h" | |||
154 | #include "mozilla/dom/Promise.h" | |||
155 | #include "mozilla/dom/RootedDictionary.h" | |||
156 | #include "mozilla/dom/WebTaskSchedulerMainThread.h" | |||
157 | #include "mozilla/dom/ScriptLoader.h" | |||
158 | #include "mozilla/dom/ScriptSettings.h" | |||
159 | #include "mozilla/dom/ServiceWorker.h" | |||
160 | #include "mozilla/dom/ServiceWorkerDescriptor.h" | |||
161 | #include "mozilla/dom/ServiceWorkerRegistration.h" | |||
162 | #include "mozilla/dom/SessionStorageManager.h" | |||
163 | #include "mozilla/dom/SharedWorker.h" | |||
164 | #include "mozilla/dom/Storage.h" | |||
165 | #include "mozilla/dom/StorageEvent.h" | |||
166 | #include "mozilla/dom/StorageEventBinding.h" | |||
167 | #include "mozilla/dom/StorageNotifierService.h" | |||
168 | #include "mozilla/dom/StorageUtils.h" | |||
169 | #include "mozilla/dom/TabMessageTypes.h" | |||
170 | #include "mozilla/dom/Timeout.h" | |||
171 | #include "mozilla/dom/TimeoutHandler.h" | |||
172 | #include "mozilla/dom/TimeoutManager.h" | |||
173 | #include "mozilla/dom/ToJSValue.h" | |||
174 | #include "mozilla/dom/TrustedTypePolicyFactory.h" | |||
175 | #include "mozilla/dom/VRDisplay.h" | |||
176 | #include "mozilla/dom/VRDisplayEvent.h" | |||
177 | #include "mozilla/dom/VRDisplayEventBinding.h" | |||
178 | #include "mozilla/dom/VREventObserver.h" | |||
179 | #include "mozilla/dom/VisualViewport.h" | |||
180 | #include "mozilla/dom/WebIDLGlobalNameHash.h" | |||
181 | #include "mozilla/dom/WindowBinding.h" | |||
182 | #include "mozilla/dom/WindowContext.h" | |||
183 | #include "mozilla/dom/WindowGlobalChild.h" | |||
184 | #include "mozilla/dom/WindowProxyHolder.h" | |||
185 | #include "mozilla/dom/WorkerCommon.h" | |||
186 | #include "mozilla/dom/Worklet.h" | |||
187 | #include "mozilla/dom/XRPermissionRequest.h" | |||
188 | #include "mozilla/dom/cache/CacheStorage.h" | |||
189 | #include "mozilla/dom/cache/Types.h" | |||
190 | #include "mozilla/glean/bindings/Glean.h" | |||
191 | #include "mozilla/glean/bindings/GleanPings.h" | |||
192 | #include "mozilla/extensions/WebExtensionPolicy.h" | |||
193 | #include "mozilla/fallible.h" | |||
194 | #include "mozilla/gfx/BasePoint.h" | |||
195 | #include "mozilla/gfx/BaseRect.h" | |||
196 | #include "mozilla/gfx/BaseSize.h" | |||
197 | #include "mozilla/gfx/Rect.h" | |||
198 | #include "mozilla/gfx/Types.h" | |||
199 | #include "mozilla/intl/LocaleService.h" | |||
200 | #include "mozilla/ipc/BackgroundUtils.h" | |||
201 | #include "mozilla/ipc/PBackgroundSharedTypes.h" | |||
202 | #include "mozilla/net/CookieJarSettings.h" | |||
203 | #include "nsAtom.h" | |||
204 | #include "nsBaseHashtable.h" | |||
205 | #include "nsCCUncollectableMarker.h" | |||
206 | #include "nsCOMPtr.h" | |||
207 | #include "nsCRT.h" | |||
208 | #include "nsCRTGlue.h" | |||
209 | #include "nsCanvasFrame.h" | |||
210 | #include "nsCharTraits.h" | |||
211 | #include "nsCheapSets.h" | |||
212 | #include "nsContentUtils.h" | |||
213 | #include "nsCoord.h" | |||
214 | #include "nsCycleCollectionNoteChild.h" | |||
215 | #include "nsCycleCollectionTraversalCallback.h" | |||
216 | #include "nsDOMNavigationTiming.h" | |||
217 | #include "nsDebug.h" | |||
218 | #include "nsDeviceContext.h" | |||
219 | #include "nsDocShell.h" | |||
220 | #include "nsFocusManager.h" | |||
221 | #include "nsFrameMessageManager.h" | |||
222 | #include "nsGkAtoms.h" | |||
223 | #include "nsGlobalWindowOuter.h" | |||
224 | #include "nsHashKeys.h" | |||
225 | #include "nsHistory.h" | |||
226 | #include "nsIAddonPolicyService.h" | |||
227 | #include "nsIArray.h" | |||
228 | #include "nsIBaseWindow.h" | |||
229 | #include "nsIBrowserChild.h" | |||
230 | #include "nsICancelableRunnable.h" | |||
231 | #include "nsIChannel.h" | |||
232 | #include "nsIClipboard.h" | |||
233 | #include "nsIContentSecurityPolicy.h" | |||
234 | #include "nsIControllers.h" | |||
235 | #include "nsICookieJarSettings.h" | |||
236 | #include "nsICookieService.h" | |||
237 | #include "nsID.h" | |||
238 | #include "nsIDOMStorageManager.h" | |||
239 | #include "nsIDeviceSensors.h" | |||
240 | #include "nsIDocShell.h" | |||
241 | #include "nsIDocShellTreeItem.h" | |||
242 | #include "nsIDocShellTreeOwner.h" | |||
243 | #include "nsIDocumentLoader.h" | |||
244 | #include "nsIDragService.h" | |||
245 | #include "nsIFocusManager.h" | |||
246 | #include "nsIFrame.h" | |||
247 | #include "nsIGlobalObject.h" | |||
248 | #include "nsIIOService.h" | |||
249 | #include "nsIIdleRunnable.h" | |||
250 | #include "nsIInterfaceRequestorUtils.h" | |||
251 | #include "nsILoadContext.h" | |||
252 | #include "nsILoadGroup.h" | |||
253 | #include "nsILoadInfo.h" | |||
254 | #include "nsINamed.h" | |||
255 | #include "nsINode.h" | |||
256 | #include "nsIObserver.h" | |||
257 | #include "nsIObserverService.h" | |||
258 | #include "nsIPermission.h" | |||
259 | #include "nsIPermissionManager.h" | |||
260 | #include "nsIPrefBranch.h" | |||
261 | #include "nsIPrincipal.h" | |||
262 | #include "nsIPrompt.h" | |||
263 | #include "nsIRunnable.h" | |||
264 | #include "nsIScreen.h" | |||
265 | #include "nsIScreenManager.h" | |||
266 | #include "nsIScriptContext.h" | |||
267 | #include "nsIScriptGlobalObject.h" | |||
268 | #include "nsIScriptObjectPrincipal.h" | |||
269 | #include "nsISerialEventTarget.h" | |||
270 | #include "nsISimpleEnumerator.h" | |||
271 | #include "nsISizeOfEventTarget.h" | |||
272 | #include "nsISlowScriptDebug.h" | |||
273 | #include "nsISupportsUtils.h" | |||
274 | #include "nsIThread.h" | |||
275 | #include "nsITimedChannel.h" | |||
276 | #include "nsIURI.h" | |||
277 | #include "nsIWeakReference.h" | |||
278 | #include "nsIWebBrowserChrome.h" | |||
279 | #include "nsIWebNavigation.h" | |||
280 | #include "nsIWebProgressListener.h" | |||
281 | #include "nsIWidget.h" | |||
282 | #include "nsIWidgetListener.h" | |||
283 | #include "nsIXULRuntime.h" | |||
284 | #include "nsJSPrincipals.h" | |||
285 | #include "nsJSUtils.h" | |||
286 | #include "nsLayoutStatics.h" | |||
287 | #include "nsLiteralString.h" | |||
288 | #include "nsNetUtil.h" | |||
289 | #include "nsPIDOMWindow.h" | |||
290 | #include "nsPIDOMWindowInlines.h" | |||
291 | #include "nsPIWindowRoot.h" | |||
292 | #include "nsPoint.h" | |||
293 | #include "nsPresContext.h" | |||
294 | #include "nsQueryObject.h" | |||
295 | #include "nsSandboxFlags.h" | |||
296 | #include "nsScreen.h" | |||
297 | #include "nsServiceManagerUtils.h" | |||
298 | #include "nsString.h" | |||
299 | #include "nsStringFlags.h" | |||
300 | #include "nsStringFwd.h" | |||
301 | #include "nsTArray.h" | |||
302 | #include "nsTLiteralString.h" | |||
303 | #include "nsTObserverArray.h" | |||
304 | #include "nsTStringRepr.h" | |||
305 | #include "nsThreadUtils.h" | |||
306 | #include "nsWeakReference.h" | |||
307 | #include "nsWindowMemoryReporter.h" | |||
308 | #include "nsWindowSizes.h" | |||
309 | #include "nsWrapperCache.h" | |||
310 | #include "nsWrapperCacheInlines.h" | |||
311 | #include "nsXULAppAPI.h" | |||
312 | #include "nsrootidl.h" | |||
313 | #include "prclist.h" | |||
314 | #include "prtypes.h" | |||
315 | #include "xpcprivate.h" | |||
316 | #include "xpcpublic.h" | |||
317 | ||||
318 | #include "nsIDOMXULControlElement.h" | |||
319 | ||||
320 | #ifdef NS_PRINTING1 | |||
321 | # include "nsIPrintSettings.h" | |||
322 | #endif | |||
323 | ||||
324 | #ifdef MOZ_WEBSPEECH1 | |||
325 | # include "mozilla/dom/SpeechSynthesis.h" | |||
326 | #endif | |||
327 | ||||
328 | #ifdef ANDROID | |||
329 | # include <android/log.h> | |||
330 | #endif | |||
331 | ||||
332 | #ifdef XP_WIN | |||
333 | # include "mozilla/Debug.h" | |||
334 | # include <process.h> | |||
335 | # define getpid _getpid | |||
336 | #else | |||
337 | # include <unistd.h> // for getpid() | |||
338 | #endif | |||
339 | ||||
340 | using namespace mozilla; | |||
341 | using namespace mozilla::dom; | |||
342 | using namespace mozilla::dom::ipc; | |||
343 | using mozilla::TimeDuration; | |||
344 | using mozilla::TimeStamp; | |||
345 | using mozilla::dom::GamepadHandle; | |||
346 | using mozilla::dom::cache::CacheStorage; | |||
347 | ||||
348 | #define FORWARD_TO_OUTER(method, args, err_rval) \ | |||
349 | PR_BEGIN_MACROdo { \ | |||
350 | RefPtr<nsGlobalWindowOuter> outer = GetOuterWindowInternal(); \ | |||
351 | if (!HasActiveDocument()) { \ | |||
352 | NS_WARNING(outer ? "Inner window does not have active document." \NS_DebugBreak(NS_DEBUG_WARNING, outer ? "Inner window does not have active document." : "No outer window available!", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 353) | |||
353 | : "No outer window available!")NS_DebugBreak(NS_DEBUG_WARNING, outer ? "Inner window does not have active document." : "No outer window available!", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 353); \ | |||
354 | return err_rval; \ | |||
355 | } \ | |||
356 | return outer->method args; \ | |||
357 | PR_END_MACRO} while (0) | |||
358 | ||||
359 | static nsGlobalWindowOuter* GetOuterWindowForForwarding( | |||
360 | nsGlobalWindowInner* aInner, ErrorResult& aError) { | |||
361 | nsGlobalWindowOuter* outer = aInner->GetOuterWindowInternal(); | |||
362 | if (MOZ_LIKELY(aInner->HasActiveDocument())(__builtin_expect(!!(aInner->HasActiveDocument()), 1))) { | |||
363 | return outer; | |||
364 | } | |||
365 | if (!outer) { | |||
366 | NS_WARNING("No outer window available!")NS_DebugBreak(NS_DEBUG_WARNING, "No outer window available!", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 366); | |||
367 | aError.Throw(NS_ERROR_NOT_INITIALIZED); | |||
368 | } else { | |||
369 | aError.Throw(NS_ERROR_XPC_SECURITY_MANAGER_VETO); | |||
370 | } | |||
371 | return nullptr; | |||
372 | } | |||
373 | ||||
374 | #define FORWARD_TO_OUTER_OR_THROW(method, args, rv, err_rval) \ | |||
375 | PR_BEGIN_MACROdo { \ | |||
376 | RefPtr<nsGlobalWindowOuter> outer = GetOuterWindowForForwarding(this, rv); \ | |||
377 | if (MOZ_LIKELY(outer)(__builtin_expect(!!(outer), 1))) { \ | |||
378 | return outer->method args; \ | |||
379 | } \ | |||
380 | return err_rval; \ | |||
381 | PR_END_MACRO} while (0) | |||
382 | ||||
383 | #define FORWARD_TO_OUTER_VOID(method, args) \ | |||
384 | PR_BEGIN_MACROdo { \ | |||
385 | RefPtr<nsGlobalWindowOuter> outer = GetOuterWindowInternal(); \ | |||
386 | if (!HasActiveDocument()) { \ | |||
387 | NS_WARNING(outer ? "Inner window does not have active document." \NS_DebugBreak(NS_DEBUG_WARNING, outer ? "Inner window does not have active document." : "No outer window available!", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 388) | |||
388 | : "No outer window available!")NS_DebugBreak(NS_DEBUG_WARNING, outer ? "Inner window does not have active document." : "No outer window available!", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 388); \ | |||
389 | return; \ | |||
390 | } \ | |||
391 | outer->method args; \ | |||
392 | return; \ | |||
393 | PR_END_MACRO} while (0) | |||
394 | ||||
395 | #define ENSURE_ACTIVE_DOCUMENT(errorresult, err_rval)do { if ((__builtin_expect(!!(!HasActiveDocument()), 0))) { aError .Throw(NS_ERROR_XPC_SECURITY_MANAGER_VETO); return err_rval; } } while (0) \ | |||
396 | PR_BEGIN_MACROdo { \ | |||
397 | if (MOZ_UNLIKELY(!HasActiveDocument())(__builtin_expect(!!(!HasActiveDocument()), 0))) { \ | |||
398 | aError.Throw(NS_ERROR_XPC_SECURITY_MANAGER_VETO); \ | |||
399 | return err_rval; \ | |||
400 | } \ | |||
401 | PR_END_MACRO} while (0) | |||
402 | ||||
403 | #define DOM_TOUCH_LISTENER_ADDED"dom-touch-listener-added" "dom-touch-listener-added" | |||
404 | #define MEMORY_PRESSURE_OBSERVER_TOPIC"memory-pressure" "memory-pressure" | |||
405 | #define PERMISSION_CHANGED_TOPIC"perm-changed" "perm-changed" | |||
406 | ||||
407 | static LazyLogModule gDOMLeakPRLogInner("DOMLeakInner"); | |||
408 | extern mozilla::LazyLogModule gTimeoutLog; | |||
409 | ||||
410 | #ifdef DEBUG1 | |||
411 | static LazyLogModule gDocShellAndDOMWindowLeakLogging( | |||
412 | "DocShellAndDOMWindowLeak"); | |||
413 | #endif | |||
414 | ||||
415 | static FILE* gDumpFile = nullptr; | |||
416 | ||||
417 | nsGlobalWindowInner::InnerWindowByIdTable* | |||
418 | nsGlobalWindowInner::sInnerWindowsById = nullptr; | |||
419 | ||||
420 | bool nsGlobalWindowInner::sDragServiceDisabled = false; | |||
421 | bool nsGlobalWindowInner::sMouseDown = false; | |||
422 | ||||
423 | /** | |||
424 | * An indirect observer object that means we don't have to implement nsIObserver | |||
425 | * on nsGlobalWindow, where any script could see it. | |||
426 | */ | |||
427 | class nsGlobalWindowObserver final : public nsIObserver, | |||
428 | public nsIInterfaceRequestor, | |||
429 | public StorageNotificationObserver { | |||
430 | public: | |||
431 | explicit nsGlobalWindowObserver(nsGlobalWindowInner* aWindow) | |||
432 | : mWindow(aWindow) {} | |||
433 | NS_DECL_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID , void** aInstancePtr) override; virtual MozExternalRefCountType AddRef(void) override; virtual MozExternalRefCountType Release (void) override; using HasThreadSafeRefCnt = std::false_type; protected: nsAutoRefCnt mRefCnt; nsAutoOwningThread _mOwningThread ; public: | |||
434 | NS_IMETHODvirtual nsresult Observe(nsISupports* aSubject, const char* aTopic, | |||
435 | const char16_t* aData) override { | |||
436 | if (!mWindow) return NS_OK; | |||
437 | return mWindow->Observe(aSubject, aTopic, aData); | |||
438 | } | |||
439 | void Forget() { mWindow = nullptr; } | |||
440 | NS_IMETHODvirtual nsresult GetInterface(const nsIID& aIID, void** aResult) override { | |||
441 | if (mWindow && aIID.Equals(NS_GET_IID(nsIDOMWindow)(nsIDOMWindow::COMTypeInfo<nsIDOMWindow, void>::kIID)) && mWindow) { | |||
442 | return mWindow->QueryInterface(aIID, aResult); | |||
443 | } | |||
444 | return NS_NOINTERFACE; | |||
445 | } | |||
446 | ||||
447 | void ObserveStorageNotification(StorageEvent* aEvent, | |||
448 | const char16_t* aStorageType, | |||
449 | bool aPrivateBrowsing) override { | |||
450 | if (mWindow) { | |||
451 | mWindow->ObserveStorageNotification(aEvent, aStorageType, | |||
452 | aPrivateBrowsing); | |||
453 | } | |||
454 | } | |||
455 | ||||
456 | nsIPrincipal* GetEffectiveCookiePrincipal() const override { | |||
457 | return mWindow ? mWindow->GetEffectiveCookiePrincipal() : nullptr; | |||
458 | } | |||
459 | ||||
460 | nsIPrincipal* GetEffectiveStoragePrincipal() const override { | |||
461 | return mWindow ? mWindow->GetEffectiveStoragePrincipal() : nullptr; | |||
462 | } | |||
463 | ||||
464 | bool IsPrivateBrowsing() const override { | |||
465 | return mWindow ? mWindow->IsPrivateBrowsing() : false; | |||
466 | } | |||
467 | ||||
468 | nsIEventTarget* GetEventTarget() const override { | |||
469 | return mWindow ? mWindow->SerialEventTarget() : nullptr; | |||
470 | } | |||
471 | ||||
472 | private: | |||
473 | ~nsGlobalWindowObserver() = default; | |||
474 | ||||
475 | // This reference is non-owning and safe because it's cleared by | |||
476 | // nsGlobalWindowInner::FreeInnerObjects(). | |||
477 | nsGlobalWindowInner* MOZ_NON_OWNING_REF mWindow; | |||
478 | }; | |||
479 | ||||
480 | NS_IMPL_ISUPPORTS(nsGlobalWindowObserver, nsIObserver, nsIInterfaceRequestor)MozExternalRefCountType nsGlobalWindowObserver::AddRef(void) { static_assert(!std::is_destructible_v<nsGlobalWindowObserver >, "Reference-counted class " "nsGlobalWindowObserver" " should not have a public destructor. " "Make this class's destructor non-public"); do { static_assert ( mozilla::detail::AssertionConditionType<decltype(int32_t (mRefCnt) >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0" " (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 480); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 480; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("nsGlobalWindowObserver" != nullptr)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!("nsGlobalWindowObserver" != nullptr))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"nsGlobalWindowObserver\" != nullptr" " (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 480); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsGlobalWindowObserver\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 480; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread .AssertOwnership("nsGlobalWindowObserver" " not thread-safe") ; nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), ( "nsGlobalWindowObserver"), (uint32_t)(sizeof(*this))); return count; } MozExternalRefCountType nsGlobalWindowObserver::Release (void) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 480); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 480 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("nsGlobalWindowObserver" != nullptr)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!("nsGlobalWindowObserver" != nullptr))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"nsGlobalWindowObserver\" != nullptr" " (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 480); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsGlobalWindowObserver\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 480; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread .AssertOwnership("nsGlobalWindowObserver" " not thread-safe") ; const char* const nametmp = "nsGlobalWindowObserver"; nsrefcnt count = --mRefCnt; NS_LogRelease((this), (count), (nametmp)) ; if (count == 0) { mRefCnt = 1; delete (this); return 0; } return count; } nsresult nsGlobalWindowObserver::QueryInterface(const nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr )) { NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!" , "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 480); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE ; static_assert(2 > 0, "Need more arguments to NS_INTERFACE_TABLE" ); static const QITableEntry table[] = { {&mozilla::detail ::kImplementedIID<nsGlobalWindowObserver, nsIObserver>, int32_t( reinterpret_cast<char*>(static_cast<nsIObserver *>((nsGlobalWindowObserver*)0x1000)) - reinterpret_cast< char*>((nsGlobalWindowObserver*)0x1000))}, {&mozilla:: detail::kImplementedIID<nsGlobalWindowObserver, nsIInterfaceRequestor >, int32_t( reinterpret_cast<char*>(static_cast<nsIInterfaceRequestor *>((nsGlobalWindowObserver*)0x1000)) - reinterpret_cast< char*>((nsGlobalWindowObserver*)0x1000))}, {&mozilla:: detail::kImplementedIID<nsGlobalWindowObserver, nsISupports >, int32_t(reinterpret_cast<char*>(static_cast<nsISupports *>( static_cast<nsIObserver*>((nsGlobalWindowObserver *)0x1000))) - reinterpret_cast<char*>((nsGlobalWindowObserver *)0x1000))}, { nullptr, 0 } } ; static_assert((sizeof(table) / sizeof(table[0])) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID, aInstancePtr , table); return rv; } | |||
481 | ||||
482 | class IdleRequestExecutor; | |||
483 | ||||
484 | class IdleRequestExecutorTimeoutHandler final : public TimeoutHandler { | |||
485 | public: | |||
486 | explicit IdleRequestExecutorTimeoutHandler(IdleRequestExecutor* aExecutor) | |||
487 | : mExecutor(aExecutor) {} | |||
488 | ||||
489 | NS_DECL_CYCLE_COLLECTING_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID , void** aInstancePtr) override; virtual MozExternalRefCountType AddRef(void) override; virtual MozExternalRefCountType Release (void) override; using HasThreadSafeRefCnt = std::false_type; protected: nsCycleCollectingAutoRefCnt mRefCnt; nsAutoOwningThread _mOwningThread; public: virtual void DeleteCycleCollectable( void); public: | |||
490 | NS_DECL_CYCLE_COLLECTION_CLASS(IdleRequestExecutorTimeoutHandler)class cycleCollection : public nsXPCOMCycleCollectionParticipant { public: constexpr explicit cycleCollection(Flags aFlags = 0 ) : nsXPCOMCycleCollectionParticipant(aFlags) {} private: public : virtual nsresult TraverseNative(void* p, nsCycleCollectionTraversalCallback & cb) override; virtual const char* ClassName() override { return "IdleRequestExecutorTimeoutHandler"; }; virtual void DeleteCycleCollectable (void* p) override { DowncastCCParticipant<IdleRequestExecutorTimeoutHandler >(p)->DeleteCycleCollectable(); } static IdleRequestExecutorTimeoutHandler * Downcast(nsISupports* s) { return static_cast<IdleRequestExecutorTimeoutHandler *>(static_cast<IdleRequestExecutorTimeoutHandler*>(s )); } static nsISupports* Upcast(IdleRequestExecutorTimeoutHandler * p) { return static_cast<nsISupports*>(static_cast< IdleRequestExecutorTimeoutHandler*>(p)); } template <typename T> friend nsISupports* ToSupports(T* p, cycleCollection* dummy ); virtual void Unlink(void* p) override; static constexpr nsXPCOMCycleCollectionParticipant * GetParticipant() { return &IdleRequestExecutorTimeoutHandler ::_cycleCollectorGlobal; } }; virtual void CheckForRightParticipant () { nsXPCOMCycleCollectionParticipant* p; CallQueryInterface (this, &p); do { static_assert( mozilla::detail::AssertionConditionType <decltype(p == &_cycleCollectorGlobal)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(p == &_cycleCollectorGlobal ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "p == &_cycleCollectorGlobal" " (" "IdleRequestExecutorTimeoutHandler" " should QI to its own CC participant" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 490); AnnotateMozCrashReason("MOZ_ASSERT" "(" "p == &_cycleCollectorGlobal" ") (" "IdleRequestExecutorTimeoutHandler" " should QI to its own CC participant" ")"); do { *((volatile int*)__null) = 490; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } static cycleCollection _cycleCollectorGlobal; virtual void BaseCycleCollectable() final {} | |||
491 | ||||
492 | bool Call(const char* /* unused */) override; | |||
493 | ||||
494 | private: | |||
495 | ~IdleRequestExecutorTimeoutHandler() override = default; | |||
496 | RefPtr<IdleRequestExecutor> mExecutor; | |||
497 | }; | |||
498 | ||||
499 | NS_IMPL_CYCLE_COLLECTION(IdleRequestExecutorTimeoutHandler, mExecutor)IdleRequestExecutorTimeoutHandler::cycleCollection IdleRequestExecutorTimeoutHandler ::_cycleCollectorGlobal; void IdleRequestExecutorTimeoutHandler ::cycleCollection::Unlink(void* p) { IdleRequestExecutorTimeoutHandler * tmp = DowncastCCParticipant<IdleRequestExecutorTimeoutHandler >(p); ImplCycleCollectionUnlink(tmp->mExecutor); (void) tmp; } nsresult IdleRequestExecutorTimeoutHandler::cycleCollection ::TraverseNative( void* p, nsCycleCollectionTraversalCallback & cb) { IdleRequestExecutorTimeoutHandler* tmp = DowncastCCParticipant <IdleRequestExecutorTimeoutHandler>(p); cb.DescribeRefCountedNode (tmp->mRefCnt.get(), "IdleRequestExecutorTimeoutHandler"); ImplCycleCollectionTraverse(cb, tmp->mExecutor, "mExecutor" , 0); (void)tmp; return NS_OK; } | |||
500 | ||||
501 | NS_IMPL_CYCLE_COLLECTING_ADDREF(IdleRequestExecutorTimeoutHandler)MozExternalRefCountType IdleRequestExecutorTimeoutHandler::AddRef (void) { static_assert(!std::is_destructible_v<IdleRequestExecutorTimeoutHandler >, "Reference-counted class " "IdleRequestExecutorTimeoutHandler" " should not have a public destructor. " "Make this class's destructor non-public" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0" " (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 501); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 501; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); _mOwningThread.AssertOwnership("IdleRequestExecutorTimeoutHandler" " not thread-safe"); nsISupports* base = IdleRequestExecutorTimeoutHandler ::cycleCollection::Upcast(this); nsrefcnt count = mRefCnt.incr (base); NS_LogAddRef((this), (count), ("IdleRequestExecutorTimeoutHandler" ), (uint32_t)(sizeof(*this))); return count; } | |||
502 | NS_IMPL_CYCLE_COLLECTING_RELEASE(IdleRequestExecutorTimeoutHandler)MozExternalRefCountType IdleRequestExecutorTimeoutHandler::Release (void) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 502); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 502 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); _mOwningThread.AssertOwnership("IdleRequestExecutorTimeoutHandler" " not thread-safe"); nsISupports* base = IdleRequestExecutorTimeoutHandler ::cycleCollection::Upcast(this); nsrefcnt count = mRefCnt.decr (base); NS_LogRelease((this), (count), ("IdleRequestExecutorTimeoutHandler" )); return count; } void IdleRequestExecutorTimeoutHandler::DeleteCycleCollectable (void) { delete (this); } | |||
503 | ||||
504 | NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IdleRequestExecutorTimeoutHandler)nsresult IdleRequestExecutorTimeoutHandler::QueryInterface(const nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr )) { NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!" , "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 504); MOZ_PretendNoReturn(); } } while (0); nsISupports* foundInterface ; if (TopThreeWordsEquals( aIID, (nsXPCOMCycleCollectionParticipant ::COMTypeInfo<nsXPCOMCycleCollectionParticipant, void>:: kIID), (nsCycleCollectionISupports::COMTypeInfo<nsCycleCollectionISupports , void>::kIID)) && (LowWordEquals(aIID, (nsXPCOMCycleCollectionParticipant ::COMTypeInfo<nsXPCOMCycleCollectionParticipant, void>:: kIID)) || LowWordEquals(aIID, (nsCycleCollectionISupports::COMTypeInfo <nsCycleCollectionISupports, void>::kIID)))) { if (LowWordEquals (aIID, (nsXPCOMCycleCollectionParticipant::COMTypeInfo<nsXPCOMCycleCollectionParticipant , void>::kIID))) { *aInstancePtr = IdleRequestExecutorTimeoutHandler ::cycleCollection::GetParticipant(); return NS_OK; } if (LowWordEquals (aIID, (nsCycleCollectionISupports::COMTypeInfo<nsCycleCollectionISupports , void>::kIID))) { *aInstancePtr = IdleRequestExecutorTimeoutHandler ::cycleCollection::Upcast(this); return NS_OK; } foundInterface = nullptr; } else | |||
505 | NS_INTERFACE_MAP_ENTRY(nsISupports)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsISupports>)) foundInterface = static_cast <nsISupports*>(this); else | |||
506 | NS_INTERFACE_MAP_ENDfoundInterface = 0; nsresult status; if (!foundInterface) { do { static_assert( mozilla::detail::AssertionConditionType< decltype(!aIID.Equals((nsISupports::COMTypeInfo<nsISupports , void>::kIID)))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!aIID.Equals((nsISupports::COMTypeInfo <nsISupports, void>::kIID))))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("!aIID.Equals((nsISupports::COMTypeInfo<nsISupports, void>::kIID))" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 506); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIID.Equals((nsISupports::COMTypeInfo<nsISupports, void>::kIID))" ")"); do { *((volatile int*)__null) = 506; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); status = NS_NOINTERFACE ; } else { (foundInterface)->AddRef(); status = NS_OK; } * aInstancePtr = foundInterface; return status; } | |||
507 | ||||
508 | class IdleRequestExecutor final : public nsIRunnable, | |||
509 | public nsICancelableRunnable, | |||
510 | public nsINamed, | |||
511 | public nsIIdleRunnable { | |||
512 | public: | |||
513 | explicit IdleRequestExecutor(nsGlobalWindowInner* aWindow) | |||
514 | : mDispatched(false), mDeadline(TimeStamp::Now()), mWindow(aWindow) { | |||
515 | MOZ_DIAGNOSTIC_ASSERT(mWindow)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mWindow)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mWindow))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mWindow", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 515); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mWindow" ")"); do { *((volatile int*)__null) = 515; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
516 | ||||
517 | mIdlePeriodLimit = {mDeadline, mWindow->LastIdleRequestHandle()}; | |||
518 | mDelayedExecutorDispatcher = new IdleRequestExecutorTimeoutHandler(this); | |||
519 | } | |||
520 | ||||
521 | NS_DECL_CYCLE_COLLECTING_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID , void** aInstancePtr) override; virtual MozExternalRefCountType AddRef(void) override; virtual MozExternalRefCountType Release (void) override; using HasThreadSafeRefCnt = std::false_type; protected: nsCycleCollectingAutoRefCnt mRefCnt; nsAutoOwningThread _mOwningThread; public: virtual void DeleteCycleCollectable( void); public: | |||
522 | NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(IdleRequestExecutor, nsIRunnable)class cycleCollection : public nsXPCOMCycleCollectionParticipant { public: constexpr explicit cycleCollection(Flags aFlags = 0 ) : nsXPCOMCycleCollectionParticipant(aFlags) {} private: public : virtual nsresult TraverseNative(void* p, nsCycleCollectionTraversalCallback & cb) override; virtual const char* ClassName() override { return "IdleRequestExecutor"; }; virtual void DeleteCycleCollectable (void* p) override { DowncastCCParticipant<IdleRequestExecutor >(p)->DeleteCycleCollectable(); } static IdleRequestExecutor * Downcast(nsISupports* s) { return static_cast<IdleRequestExecutor *>(static_cast<nsIRunnable*>(s)); } static nsISupports * Upcast(IdleRequestExecutor* p) { return static_cast<nsISupports *>(static_cast<nsIRunnable*>(p)); } template <typename T> friend nsISupports* ToSupports(T* p, cycleCollection* dummy ); virtual void Unlink(void* p) override; static constexpr nsXPCOMCycleCollectionParticipant * GetParticipant() { return &IdleRequestExecutor::_cycleCollectorGlobal ; } }; virtual void CheckForRightParticipant() { nsXPCOMCycleCollectionParticipant * p; CallQueryInterface(this, &p); do { static_assert( mozilla ::detail::AssertionConditionType<decltype(p == &_cycleCollectorGlobal )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(p == &_cycleCollectorGlobal))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("p == &_cycleCollectorGlobal" " (" "IdleRequestExecutor" " should QI to its own CC participant" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 522); AnnotateMozCrashReason("MOZ_ASSERT" "(" "p == &_cycleCollectorGlobal" ") (" "IdleRequestExecutor" " should QI to its own CC participant" ")"); do { *((volatile int*)__null) = 522; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } static cycleCollection _cycleCollectorGlobal; virtual void BaseCycleCollectable() final {} | |||
523 | ||||
524 | NS_DECL_NSIRUNNABLEvirtual nsresult Run(void) override; | |||
525 | NS_DECL_NSINAMEDvirtual nsresult GetName(nsACString& aName) override; | |||
526 | nsresult Cancel() override; | |||
527 | void SetDeadline(TimeStamp aDeadline) override; | |||
528 | ||||
529 | bool IsCancelled() const { return !mWindow || mWindow->IsDying(); } | |||
530 | // Checks if aRequest shouldn't execute in the current idle period | |||
531 | // since it has been queued from a chained call to | |||
532 | // requestIdleCallback from within a running idle callback. | |||
533 | bool IneligibleForCurrentIdlePeriod(IdleRequest* aRequest) const { | |||
534 | return aRequest->Handle() >= mIdlePeriodLimit.mLastRequestIdInIdlePeriod && | |||
535 | TimeStamp::Now() <= mIdlePeriodLimit.mEndOfIdlePeriod; | |||
536 | } | |||
537 | ||||
538 | void MaybeUpdateIdlePeriodLimit(); | |||
539 | ||||
540 | // Maybe dispatch the IdleRequestExecutor. MabyeDispatch will | |||
541 | // schedule a delayed dispatch if the associated window is in the | |||
542 | // background or if given a time to wait until dispatching. | |||
543 | void MaybeDispatch(TimeStamp aDelayUntil = TimeStamp()); | |||
544 | void ScheduleDispatch(); | |||
545 | ||||
546 | private: | |||
547 | struct IdlePeriodLimit { | |||
548 | TimeStamp mEndOfIdlePeriod; | |||
549 | uint32_t mLastRequestIdInIdlePeriod; | |||
550 | }; | |||
551 | ||||
552 | void DelayedDispatch(uint32_t aDelay); | |||
553 | ||||
554 | ~IdleRequestExecutor() override = default; | |||
555 | ||||
556 | bool mDispatched; | |||
557 | TimeStamp mDeadline; | |||
558 | IdlePeriodLimit mIdlePeriodLimit; | |||
559 | RefPtr<nsGlobalWindowInner> mWindow; | |||
560 | // The timeout handler responsible for dispatching this executor in | |||
561 | // the case of immediate dispatch to the idle queue isn't | |||
562 | // desirable. This is used if we've dispatched all idle callbacks | |||
563 | // that are allowed to run in the current idle period, or if the | |||
564 | // associated window is currently in the background. | |||
565 | RefPtr<TimeoutHandler> mDelayedExecutorDispatcher; | |||
566 | // If not Nothing() then this value is the handle to the currently | |||
567 | // scheduled delayed executor dispatcher. This is needed to be able | |||
568 | // to cancel the timeout handler in case of the executor being | |||
569 | // cancelled. | |||
570 | Maybe<int32_t> mDelayedExecutorHandle; | |||
571 | }; | |||
572 | ||||
573 | NS_IMPL_CYCLE_COLLECTION(IdleRequestExecutor, mWindow,IdleRequestExecutor::cycleCollection IdleRequestExecutor::_cycleCollectorGlobal ; void IdleRequestExecutor::cycleCollection::Unlink(void* p) { IdleRequestExecutor* tmp = DowncastCCParticipant<IdleRequestExecutor >(p); ImplCycleCollectionUnlink(tmp->mWindow); ImplCycleCollectionUnlink (tmp->mDelayedExecutorDispatcher); (void)tmp; } nsresult IdleRequestExecutor ::cycleCollection::TraverseNative( void* p, nsCycleCollectionTraversalCallback & cb) { IdleRequestExecutor* tmp = DowncastCCParticipant< IdleRequestExecutor>(p); cb.DescribeRefCountedNode(tmp-> mRefCnt.get(), "IdleRequestExecutor"); ImplCycleCollectionTraverse (cb, tmp->mWindow, "mWindow", 0); ImplCycleCollectionTraverse (cb, tmp->mDelayedExecutorDispatcher, "mDelayedExecutorDispatcher" , 0); (void)tmp; return NS_OK; } | |||
574 | mDelayedExecutorDispatcher)IdleRequestExecutor::cycleCollection IdleRequestExecutor::_cycleCollectorGlobal ; void IdleRequestExecutor::cycleCollection::Unlink(void* p) { IdleRequestExecutor* tmp = DowncastCCParticipant<IdleRequestExecutor >(p); ImplCycleCollectionUnlink(tmp->mWindow); ImplCycleCollectionUnlink (tmp->mDelayedExecutorDispatcher); (void)tmp; } nsresult IdleRequestExecutor ::cycleCollection::TraverseNative( void* p, nsCycleCollectionTraversalCallback & cb) { IdleRequestExecutor* tmp = DowncastCCParticipant< IdleRequestExecutor>(p); cb.DescribeRefCountedNode(tmp-> mRefCnt.get(), "IdleRequestExecutor"); ImplCycleCollectionTraverse (cb, tmp->mWindow, "mWindow", 0); ImplCycleCollectionTraverse (cb, tmp->mDelayedExecutorDispatcher, "mDelayedExecutorDispatcher" , 0); (void)tmp; return NS_OK; } | |||
575 | ||||
576 | NS_IMPL_CYCLE_COLLECTING_ADDREF(IdleRequestExecutor)MozExternalRefCountType IdleRequestExecutor::AddRef(void) { static_assert (!std::is_destructible_v<IdleRequestExecutor>, "Reference-counted class " "IdleRequestExecutor" " should not have a public destructor. " "Make this class's destructor non-public"); do { static_assert ( mozilla::detail::AssertionConditionType<decltype(int32_t (mRefCnt) >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0" " (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 576); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 576; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); _mOwningThread.AssertOwnership("IdleRequestExecutor" " not thread-safe"); nsISupports* base = IdleRequestExecutor ::cycleCollection::Upcast(this); nsrefcnt count = mRefCnt.incr (base); NS_LogAddRef((this), (count), ("IdleRequestExecutor") , (uint32_t)(sizeof(*this))); return count; } | |||
577 | NS_IMPL_CYCLE_COLLECTING_RELEASE(IdleRequestExecutor)MozExternalRefCountType IdleRequestExecutor::Release(void) { do { static_assert( mozilla::detail::AssertionConditionType< decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 577); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 577 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); _mOwningThread.AssertOwnership("IdleRequestExecutor" " not thread-safe"); nsISupports* base = IdleRequestExecutor ::cycleCollection::Upcast(this); nsrefcnt count = mRefCnt.decr (base); NS_LogRelease((this), (count), ("IdleRequestExecutor" )); return count; } void IdleRequestExecutor::DeleteCycleCollectable (void) { delete (this); } | |||
578 | ||||
579 | NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IdleRequestExecutor)nsresult IdleRequestExecutor::QueryInterface(const nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak (NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!" , "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 579); MOZ_PretendNoReturn(); } } while (0); nsISupports* foundInterface ; if (TopThreeWordsEquals( aIID, (nsXPCOMCycleCollectionParticipant ::COMTypeInfo<nsXPCOMCycleCollectionParticipant, void>:: kIID), (nsCycleCollectionISupports::COMTypeInfo<nsCycleCollectionISupports , void>::kIID)) && (LowWordEquals(aIID, (nsXPCOMCycleCollectionParticipant ::COMTypeInfo<nsXPCOMCycleCollectionParticipant, void>:: kIID)) || LowWordEquals(aIID, (nsCycleCollectionISupports::COMTypeInfo <nsCycleCollectionISupports, void>::kIID)))) { if (LowWordEquals (aIID, (nsXPCOMCycleCollectionParticipant::COMTypeInfo<nsXPCOMCycleCollectionParticipant , void>::kIID))) { *aInstancePtr = IdleRequestExecutor::cycleCollection ::GetParticipant(); return NS_OK; } if (LowWordEquals(aIID, ( nsCycleCollectionISupports::COMTypeInfo<nsCycleCollectionISupports , void>::kIID))) { *aInstancePtr = IdleRequestExecutor::cycleCollection ::Upcast(this); return NS_OK; } foundInterface = nullptr; } else | |||
580 | NS_INTERFACE_MAP_ENTRY(nsIRunnable)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsIRunnable>)) foundInterface = static_cast <nsIRunnable*>(this); else | |||
581 | NS_INTERFACE_MAP_ENTRY(nsICancelableRunnable)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsICancelableRunnable>)) foundInterface = static_cast<nsICancelableRunnable*>(this); else | |||
582 | NS_INTERFACE_MAP_ENTRY(nsINamed)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsINamed>)) foundInterface = static_cast <nsINamed*>(this); else | |||
583 | NS_INTERFACE_MAP_ENTRY(nsIIdleRunnable)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsIIdleRunnable>)) foundInterface = static_cast<nsIIdleRunnable*>(this); else | |||
584 | NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIRunnable)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsISupports>)) foundInterface = static_cast <nsISupports*>(static_cast<nsIRunnable*>(this)); else | |||
585 | NS_INTERFACE_MAP_ENDfoundInterface = 0; nsresult status; if (!foundInterface) { do { static_assert( mozilla::detail::AssertionConditionType< decltype(!aIID.Equals((nsISupports::COMTypeInfo<nsISupports , void>::kIID)))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!aIID.Equals((nsISupports::COMTypeInfo <nsISupports, void>::kIID))))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("!aIID.Equals((nsISupports::COMTypeInfo<nsISupports, void>::kIID))" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 585); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIID.Equals((nsISupports::COMTypeInfo<nsISupports, void>::kIID))" ")"); do { *((volatile int*)__null) = 585; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); status = NS_NOINTERFACE ; } else { (foundInterface)->AddRef(); status = NS_OK; } * aInstancePtr = foundInterface; return status; } | |||
586 | ||||
587 | NS_IMETHODIMPnsresult | |||
588 | IdleRequestExecutor::GetName(nsACString& aName) { | |||
589 | aName.AssignLiteral("IdleRequestExecutor"); | |||
590 | return NS_OK; | |||
591 | } | |||
592 | ||||
593 | // MOZ_CAN_RUN_SCRIPT_BOUNDARY until nsIRunnable::Run is MOZ_CAN_RUN_SCRIPT. | |||
594 | // See bug 1535398. | |||
595 | MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHODIMPnsresult IdleRequestExecutor::Run() { | |||
596 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 596); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 596; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
597 | ||||
598 | mDispatched = false; | |||
599 | if (mWindow) { | |||
600 | RefPtr<nsGlobalWindowInner> window(mWindow); | |||
601 | window->ExecuteIdleRequest(mDeadline); | |||
602 | } | |||
603 | ||||
604 | return NS_OK; | |||
605 | } | |||
606 | ||||
607 | nsresult IdleRequestExecutor::Cancel() { | |||
608 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 608); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 608; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
609 | ||||
610 | if (mDelayedExecutorHandle && mWindow) { | |||
611 | mWindow->GetTimeoutManager()->ClearTimeout( | |||
612 | mDelayedExecutorHandle.value(), Timeout::Reason::eIdleCallbackTimeout); | |||
613 | } | |||
614 | ||||
615 | mWindow = nullptr; | |||
616 | return NS_OK; | |||
617 | } | |||
618 | ||||
619 | void IdleRequestExecutor::SetDeadline(TimeStamp aDeadline) { | |||
620 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 620); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 620; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
621 | ||||
622 | if (!mWindow) { | |||
623 | return; | |||
624 | } | |||
625 | ||||
626 | mDeadline = aDeadline; | |||
627 | } | |||
628 | ||||
629 | void IdleRequestExecutor::MaybeUpdateIdlePeriodLimit() { | |||
630 | if (TimeStamp::Now() > mIdlePeriodLimit.mEndOfIdlePeriod) { | |||
631 | mIdlePeriodLimit = {mDeadline, mWindow->LastIdleRequestHandle()}; | |||
632 | } | |||
633 | } | |||
634 | ||||
635 | void IdleRequestExecutor::MaybeDispatch(TimeStamp aDelayUntil) { | |||
636 | // If we've already dispatched the executor we don't want to do it | |||
637 | // again. Also, if we've called IdleRequestExecutor::Cancel mWindow | |||
638 | // will be null, which indicates that we shouldn't dispatch this | |||
639 | // executor either. | |||
640 | if (mDispatched || IsCancelled()) { | |||
641 | return; | |||
642 | } | |||
643 | ||||
644 | mDispatched = true; | |||
645 | ||||
646 | nsPIDOMWindowOuter* outer = mWindow->GetOuterWindow(); | |||
647 | if (outer && outer->IsBackground()) { | |||
648 | // Set a timeout handler with a timeout of 0 ms to throttle idle | |||
649 | // callback requests coming from a backround window using | |||
650 | // background timeout throttling. | |||
651 | DelayedDispatch(0); | |||
652 | return; | |||
653 | } | |||
654 | ||||
655 | TimeStamp now = TimeStamp::Now(); | |||
656 | if (!aDelayUntil || aDelayUntil < now) { | |||
657 | ScheduleDispatch(); | |||
658 | return; | |||
659 | } | |||
660 | ||||
661 | TimeDuration delay = aDelayUntil - now; | |||
662 | DelayedDispatch(static_cast<uint32_t>(delay.ToMilliseconds())); | |||
663 | } | |||
664 | ||||
665 | void IdleRequestExecutor::ScheduleDispatch() { | |||
666 | MOZ_ASSERT(mWindow)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mWindow)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mWindow))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mWindow", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 666); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mWindow" ")" ); do { *((volatile int*)__null) = 666; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
667 | mDelayedExecutorHandle = Nothing(); | |||
668 | RefPtr<IdleRequestExecutor> request = this; | |||
669 | NS_DispatchToCurrentThreadQueue(request.forget(), EventQueuePriority::Idle); | |||
670 | } | |||
671 | ||||
672 | void IdleRequestExecutor::DelayedDispatch(uint32_t aDelay) { | |||
673 | MOZ_ASSERT(mWindow)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mWindow)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mWindow))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mWindow", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 673); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mWindow" ")" ); do { *((volatile int*)__null) = 673; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
674 | MOZ_ASSERT(mDelayedExecutorHandle.isNothing())do { static_assert( mozilla::detail::AssertionConditionType< decltype(mDelayedExecutorHandle.isNothing())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mDelayedExecutorHandle.isNothing ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mDelayedExecutorHandle.isNothing()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 674); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDelayedExecutorHandle.isNothing()" ")"); do { *((volatile int*)__null) = 674; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
675 | int32_t handle; | |||
676 | mWindow->GetTimeoutManager()->SetTimeout( | |||
677 | mDelayedExecutorDispatcher, aDelay, false, | |||
678 | Timeout::Reason::eIdleCallbackTimeout, &handle); | |||
679 | mDelayedExecutorHandle = Some(handle); | |||
680 | } | |||
681 | ||||
682 | bool IdleRequestExecutorTimeoutHandler::Call(const char* /* unused */) { | |||
683 | if (!mExecutor->IsCancelled()) { | |||
684 | mExecutor->ScheduleDispatch(); | |||
685 | } | |||
686 | return true; | |||
687 | } | |||
688 | ||||
689 | void nsGlobalWindowInner::ScheduleIdleRequestDispatch() { | |||
690 | AssertIsOnMainThread(); | |||
691 | ||||
692 | if (!mIdleRequestExecutor) { | |||
693 | mIdleRequestExecutor = new IdleRequestExecutor(this); | |||
694 | } | |||
695 | ||||
696 | mIdleRequestExecutor->MaybeDispatch(); | |||
697 | } | |||
698 | ||||
699 | void nsGlobalWindowInner::SuspendIdleRequests() { | |||
700 | if (mIdleRequestExecutor) { | |||
701 | mIdleRequestExecutor->Cancel(); | |||
702 | mIdleRequestExecutor = nullptr; | |||
703 | } | |||
704 | } | |||
705 | ||||
706 | void nsGlobalWindowInner::ResumeIdleRequests() { | |||
707 | MOZ_ASSERT(!mIdleRequestExecutor)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mIdleRequestExecutor)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mIdleRequestExecutor))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("!mIdleRequestExecutor" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 707); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIdleRequestExecutor" ")"); do { *((volatile int*)__null) = 707; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
708 | ||||
709 | ScheduleIdleRequestDispatch(); | |||
710 | } | |||
711 | ||||
712 | void nsGlobalWindowInner::RemoveIdleCallback( | |||
713 | mozilla::dom::IdleRequest* aRequest) { | |||
714 | AssertIsOnMainThread(); | |||
715 | ||||
716 | if (aRequest->HasTimeout()) { | |||
717 | mTimeoutManager->ClearTimeout(aRequest->GetTimeoutHandle(), | |||
718 | Timeout::Reason::eIdleCallbackTimeout); | |||
719 | } | |||
720 | ||||
721 | aRequest->removeFrom(mIdleRequestCallbacks); | |||
722 | } | |||
723 | ||||
724 | void nsGlobalWindowInner::RunIdleRequest(IdleRequest* aRequest, | |||
725 | DOMHighResTimeStamp aDeadline, | |||
726 | bool aDidTimeout) { | |||
727 | AssertIsOnMainThread(); | |||
728 | // XXXbz Do we still need this RefPtr? MOZ_CAN_RUN_SCRIPT should | |||
729 | // guarantee that caller is holding a strong ref on the stack. | |||
730 | RefPtr<IdleRequest> request(aRequest); | |||
731 | RemoveIdleCallback(request); | |||
732 | request->IdleRun(this, aDeadline, aDidTimeout); | |||
733 | } | |||
734 | ||||
735 | void nsGlobalWindowInner::ExecuteIdleRequest(TimeStamp aDeadline) { | |||
736 | AssertIsOnMainThread(); | |||
737 | RefPtr<IdleRequest> request = mIdleRequestCallbacks.getFirst(); | |||
738 | ||||
739 | if (!request) { | |||
740 | // There are no more idle requests, so stop scheduling idle | |||
741 | // request callbacks. | |||
742 | return; | |||
743 | } | |||
744 | ||||
745 | // If the request that we're trying to execute has been queued | |||
746 | // during the current idle period, then dispatch it again at the end | |||
747 | // of the idle period. | |||
748 | if (mIdleRequestExecutor->IneligibleForCurrentIdlePeriod(request)) { | |||
749 | mIdleRequestExecutor->MaybeDispatch(aDeadline); | |||
750 | return; | |||
751 | } | |||
752 | ||||
753 | DOMHighResTimeStamp deadline = 0.0; | |||
754 | ||||
755 | if (Performance* perf = GetPerformance()) { | |||
756 | deadline = perf->GetDOMTiming()->TimeStampToDOMHighRes(aDeadline); | |||
757 | } | |||
758 | ||||
759 | mIdleRequestExecutor->MaybeUpdateIdlePeriodLimit(); | |||
760 | RunIdleRequest(request, deadline, false); | |||
761 | ||||
762 | // Running the idle callback could've suspended the window, in which | |||
763 | // case mIdleRequestExecutor will be null. | |||
764 | if (mIdleRequestExecutor) { | |||
765 | mIdleRequestExecutor->MaybeDispatch(); | |||
766 | } | |||
767 | } | |||
768 | ||||
769 | class IdleRequestTimeoutHandler final : public TimeoutHandler { | |||
770 | public: | |||
771 | IdleRequestTimeoutHandler(JSContext* aCx, IdleRequest* aIdleRequest, | |||
772 | nsPIDOMWindowInner* aWindow) | |||
773 | : TimeoutHandler(aCx), mIdleRequest(aIdleRequest), mWindow(aWindow) {} | |||
774 | ||||
775 | NS_DECL_CYCLE_COLLECTING_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID , void** aInstancePtr) override; virtual MozExternalRefCountType AddRef(void) override; virtual MozExternalRefCountType Release (void) override; using HasThreadSafeRefCnt = std::false_type; protected: nsCycleCollectingAutoRefCnt mRefCnt; nsAutoOwningThread _mOwningThread; public: virtual void DeleteCycleCollectable( void); public: | |||
776 | NS_DECL_CYCLE_COLLECTION_CLASS(IdleRequestTimeoutHandler)class cycleCollection : public nsXPCOMCycleCollectionParticipant { public: constexpr explicit cycleCollection(Flags aFlags = 0 ) : nsXPCOMCycleCollectionParticipant(aFlags) {} private: public : virtual nsresult TraverseNative(void* p, nsCycleCollectionTraversalCallback & cb) override; virtual const char* ClassName() override { return "IdleRequestTimeoutHandler"; }; virtual void DeleteCycleCollectable (void* p) override { DowncastCCParticipant<IdleRequestTimeoutHandler >(p)->DeleteCycleCollectable(); } static IdleRequestTimeoutHandler * Downcast(nsISupports* s) { return static_cast<IdleRequestTimeoutHandler *>(static_cast<IdleRequestTimeoutHandler*>(s)); } static nsISupports* Upcast(IdleRequestTimeoutHandler* p) { return static_cast <nsISupports*>(static_cast<IdleRequestTimeoutHandler *>(p)); } template <typename T> friend nsISupports* ToSupports (T* p, cycleCollection* dummy); virtual void Unlink(void* p) override ; static constexpr nsXPCOMCycleCollectionParticipant* GetParticipant () { return &IdleRequestTimeoutHandler::_cycleCollectorGlobal ; } }; virtual void CheckForRightParticipant() { nsXPCOMCycleCollectionParticipant * p; CallQueryInterface(this, &p); do { static_assert( mozilla ::detail::AssertionConditionType<decltype(p == &_cycleCollectorGlobal )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(p == &_cycleCollectorGlobal))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("p == &_cycleCollectorGlobal" " (" "IdleRequestTimeoutHandler" " should QI to its own CC participant" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 776); AnnotateMozCrashReason("MOZ_ASSERT" "(" "p == &_cycleCollectorGlobal" ") (" "IdleRequestTimeoutHandler" " should QI to its own CC participant" ")"); do { *((volatile int*)__null) = 776; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } static cycleCollection _cycleCollectorGlobal; virtual void BaseCycleCollectable() final {} | |||
777 | ||||
778 | MOZ_CAN_RUN_SCRIPT bool Call(const char* /* unused */) override { | |||
779 | RefPtr<nsGlobalWindowInner> window(nsGlobalWindowInner::Cast(mWindow)); | |||
780 | RefPtr<IdleRequest> request(mIdleRequest); | |||
781 | window->RunIdleRequest(request, 0.0, true); | |||
782 | return true; | |||
783 | } | |||
784 | ||||
785 | private: | |||
786 | ~IdleRequestTimeoutHandler() override = default; | |||
787 | ||||
788 | RefPtr<IdleRequest> mIdleRequest; | |||
789 | nsCOMPtr<nsPIDOMWindowInner> mWindow; | |||
790 | }; | |||
791 | ||||
792 | NS_IMPL_CYCLE_COLLECTION(IdleRequestTimeoutHandler, mIdleRequest, mWindow)IdleRequestTimeoutHandler::cycleCollection IdleRequestTimeoutHandler ::_cycleCollectorGlobal; void IdleRequestTimeoutHandler::cycleCollection ::Unlink(void* p) { IdleRequestTimeoutHandler* tmp = DowncastCCParticipant <IdleRequestTimeoutHandler>(p); ImplCycleCollectionUnlink (tmp->mIdleRequest); ImplCycleCollectionUnlink(tmp->mWindow ); (void)tmp; } nsresult IdleRequestTimeoutHandler::cycleCollection ::TraverseNative( void* p, nsCycleCollectionTraversalCallback & cb) { IdleRequestTimeoutHandler* tmp = DowncastCCParticipant <IdleRequestTimeoutHandler>(p); cb.DescribeRefCountedNode (tmp->mRefCnt.get(), "IdleRequestTimeoutHandler"); ImplCycleCollectionTraverse (cb, tmp->mIdleRequest, "mIdleRequest", 0); ImplCycleCollectionTraverse (cb, tmp->mWindow, "mWindow", 0); (void)tmp; return NS_OK; } | |||
793 | ||||
794 | NS_IMPL_CYCLE_COLLECTING_ADDREF(IdleRequestTimeoutHandler)MozExternalRefCountType IdleRequestTimeoutHandler::AddRef(void ) { static_assert(!std::is_destructible_v<IdleRequestTimeoutHandler >, "Reference-counted class " "IdleRequestTimeoutHandler" " should not have a public destructor. " "Make this class's destructor non-public"); do { static_assert ( mozilla::detail::AssertionConditionType<decltype(int32_t (mRefCnt) >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0" " (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 794); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 794; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); _mOwningThread.AssertOwnership("IdleRequestTimeoutHandler" " not thread-safe"); nsISupports* base = IdleRequestTimeoutHandler ::cycleCollection::Upcast(this); nsrefcnt count = mRefCnt.incr (base); NS_LogAddRef((this), (count), ("IdleRequestTimeoutHandler" ), (uint32_t)(sizeof(*this))); return count; } | |||
795 | NS_IMPL_CYCLE_COLLECTING_RELEASE(IdleRequestTimeoutHandler)MozExternalRefCountType IdleRequestTimeoutHandler::Release(void ) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 795); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 795 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); _mOwningThread.AssertOwnership("IdleRequestTimeoutHandler" " not thread-safe"); nsISupports* base = IdleRequestTimeoutHandler ::cycleCollection::Upcast(this); nsrefcnt count = mRefCnt.decr (base); NS_LogRelease((this), (count), ("IdleRequestTimeoutHandler" )); return count; } void IdleRequestTimeoutHandler::DeleteCycleCollectable (void) { delete (this); } | |||
796 | ||||
797 | NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IdleRequestTimeoutHandler)nsresult IdleRequestTimeoutHandler::QueryInterface(const nsIID & aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!" , "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 797); MOZ_PretendNoReturn(); } } while (0); nsISupports* foundInterface ; if (TopThreeWordsEquals( aIID, (nsXPCOMCycleCollectionParticipant ::COMTypeInfo<nsXPCOMCycleCollectionParticipant, void>:: kIID), (nsCycleCollectionISupports::COMTypeInfo<nsCycleCollectionISupports , void>::kIID)) && (LowWordEquals(aIID, (nsXPCOMCycleCollectionParticipant ::COMTypeInfo<nsXPCOMCycleCollectionParticipant, void>:: kIID)) || LowWordEquals(aIID, (nsCycleCollectionISupports::COMTypeInfo <nsCycleCollectionISupports, void>::kIID)))) { if (LowWordEquals (aIID, (nsXPCOMCycleCollectionParticipant::COMTypeInfo<nsXPCOMCycleCollectionParticipant , void>::kIID))) { *aInstancePtr = IdleRequestTimeoutHandler ::cycleCollection::GetParticipant(); return NS_OK; } if (LowWordEquals (aIID, (nsCycleCollectionISupports::COMTypeInfo<nsCycleCollectionISupports , void>::kIID))) { *aInstancePtr = IdleRequestTimeoutHandler ::cycleCollection::Upcast(this); return NS_OK; } foundInterface = nullptr; } else | |||
798 | NS_INTERFACE_MAP_ENTRY(nsISupports)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsISupports>)) foundInterface = static_cast <nsISupports*>(this); else | |||
799 | NS_INTERFACE_MAP_ENDfoundInterface = 0; nsresult status; if (!foundInterface) { do { static_assert( mozilla::detail::AssertionConditionType< decltype(!aIID.Equals((nsISupports::COMTypeInfo<nsISupports , void>::kIID)))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!aIID.Equals((nsISupports::COMTypeInfo <nsISupports, void>::kIID))))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("!aIID.Equals((nsISupports::COMTypeInfo<nsISupports, void>::kIID))" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 799); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIID.Equals((nsISupports::COMTypeInfo<nsISupports, void>::kIID))" ")"); do { *((volatile int*)__null) = 799; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); status = NS_NOINTERFACE ; } else { (foundInterface)->AddRef(); status = NS_OK; } * aInstancePtr = foundInterface; return status; } | |||
800 | ||||
801 | uint32_t nsGlobalWindowInner::RequestIdleCallback( | |||
802 | JSContext* aCx, IdleRequestCallback& aCallback, | |||
803 | const IdleRequestOptions& aOptions, ErrorResult& aError) { | |||
804 | AssertIsOnMainThread(); | |||
805 | ||||
806 | if (IsDying()) { | |||
807 | return 0; | |||
808 | } | |||
809 | ||||
810 | uint32_t handle = mIdleRequestCallbackCounter++; | |||
811 | ||||
812 | RefPtr<IdleRequest> request = new IdleRequest(&aCallback, handle); | |||
813 | ||||
814 | if (aOptions.mTimeout.WasPassed()) { | |||
815 | int32_t timeoutHandle; | |||
816 | RefPtr<TimeoutHandler> handler( | |||
817 | new IdleRequestTimeoutHandler(aCx, request, this)); | |||
818 | ||||
819 | nsresult rv = mTimeoutManager->SetTimeout( | |||
820 | handler, aOptions.mTimeout.Value(), false, | |||
821 | Timeout::Reason::eIdleCallbackTimeout, &timeoutHandle); | |||
822 | ||||
823 | if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 823)) { | |||
824 | return 0; | |||
825 | } | |||
826 | ||||
827 | request->SetTimeoutHandle(timeoutHandle); | |||
828 | } | |||
829 | ||||
830 | mIdleRequestCallbacks.insertBack(request); | |||
831 | ||||
832 | if (!IsSuspended()) { | |||
833 | ScheduleIdleRequestDispatch(); | |||
834 | } | |||
835 | ||||
836 | return handle; | |||
837 | } | |||
838 | ||||
839 | void nsGlobalWindowInner::CancelIdleCallback(uint32_t aHandle) { | |||
840 | for (IdleRequest* r : mIdleRequestCallbacks) { | |||
841 | if (r->Handle() == aHandle) { | |||
842 | RemoveIdleCallback(r); | |||
843 | break; | |||
844 | } | |||
845 | } | |||
846 | } | |||
847 | ||||
848 | void nsGlobalWindowInner::DisableIdleCallbackRequests() { | |||
849 | if (mIdleRequestExecutor) { | |||
850 | mIdleRequestExecutor->Cancel(); | |||
851 | mIdleRequestExecutor = nullptr; | |||
852 | } | |||
853 | ||||
854 | while (!mIdleRequestCallbacks.isEmpty()) { | |||
855 | RefPtr<IdleRequest> request = mIdleRequestCallbacks.getFirst(); | |||
856 | RemoveIdleCallback(request); | |||
857 | } | |||
858 | } | |||
859 | ||||
860 | bool nsGlobalWindowInner::IsBackgroundInternal() const { | |||
861 | return !mOuterWindow || mOuterWindow->IsBackground(); | |||
862 | } | |||
863 | ||||
864 | class PromiseDocumentFlushedResolver final { | |||
865 | public: | |||
866 | PromiseDocumentFlushedResolver(Promise* aPromise, | |||
867 | PromiseDocumentFlushedCallback& aCallback) | |||
868 | : mPromise(aPromise), mCallback(&aCallback) {} | |||
869 | ||||
870 | virtual ~PromiseDocumentFlushedResolver() = default; | |||
871 | ||||
872 | void Call() { | |||
873 | nsMutationGuard guard; | |||
874 | ErrorResult error; | |||
875 | JS::Rooted<JS::Value> returnVal(RootingCx()); | |||
876 | mCallback->Call(&returnVal, error); | |||
877 | ||||
878 | if (error.Failed()) { | |||
879 | mPromise->MaybeReject(std::move(error)); | |||
880 | } else if (guard.Mutated(0)) { | |||
881 | // Something within the callback mutated the DOM. | |||
882 | mPromise->MaybeRejectWithNoModificationAllowedError( | |||
883 | "DOM mutated from promiseDocumentFlushed callbacks"); | |||
884 | } else { | |||
885 | mPromise->MaybeResolve(returnVal); | |||
886 | } | |||
887 | } | |||
888 | ||||
889 | RefPtr<Promise> mPromise; | |||
890 | RefPtr<PromiseDocumentFlushedCallback> mCallback; | |||
891 | }; | |||
892 | ||||
893 | //***************************************************************************** | |||
894 | //*** nsGlobalWindowInner: Object Management | |||
895 | //***************************************************************************** | |||
896 | ||||
897 | nsGlobalWindowInner::nsGlobalWindowInner(nsGlobalWindowOuter* aOuterWindow, | |||
898 | WindowGlobalChild* aActor) | |||
899 | : nsPIDOMWindowInner(aOuterWindow, aActor), | |||
900 | mHasOrientationChangeListeners(false), | |||
901 | mWasOffline(false), | |||
902 | mHasHadSlowScript(false), | |||
903 | mIsChrome(false), | |||
904 | mCleanMessageManager(false), | |||
905 | mNeedsFocus(true), | |||
906 | mHasFocus(false), | |||
907 | mFocusByKeyOccurred(false), | |||
908 | mDidFireDocElemInserted(false), | |||
909 | mHasGamepad(false), | |||
910 | mHasXRSession(false), | |||
911 | mHasVRDisplayActivateEvents(false), | |||
912 | mXRRuntimeDetectionInFlight(false), | |||
913 | mXRPermissionRequestInFlight(false), | |||
914 | mXRPermissionGranted(false), | |||
915 | mWasCurrentInnerWindow(false), | |||
916 | mHasSeenGamepadInput(false), | |||
917 | mHintedWasLoading(false), | |||
918 | mHasOpenedExternalProtocolFrame(false), | |||
919 | mScrollMarksOnHScrollbar(false), | |||
920 | mStorageAllowedReasonCache(0), | |||
921 | mSuspendDepth(0), | |||
922 | mFreezeDepth(0), | |||
923 | #ifdef DEBUG1 | |||
924 | mSerial(0), | |||
925 | #endif | |||
926 | mFocusMethod(0), | |||
927 | mIdleRequestCallbackCounter(1), | |||
928 | mIdleRequestExecutor(nullptr), | |||
929 | mObservingRefresh(false), | |||
930 | mIteratingDocumentFlushedResolvers(false), | |||
931 | mCanSkipCCGeneration(0) { | |||
932 | mIsInnerWindow = true; | |||
933 | ||||
934 | AssertIsOnMainThread(); | |||
935 | SetIsOnMainThread(); | |||
936 | nsLayoutStatics::AddRef(); | |||
937 | ||||
938 | // Initialize the PRCList (this). | |||
939 | PR_INIT_CLIST(this)do { (this)->next = (this); (this)->prev = (this); } while (0); | |||
940 | ||||
941 | // add this inner window to the outer window list of inners. | |||
942 | PR_INSERT_AFTER(this, aOuterWindow)do { (this)->next = (aOuterWindow)->next; (this)->prev = (aOuterWindow); (aOuterWindow)->next->prev = (this); (aOuterWindow)->next = (this); } while (0); | |||
943 | ||||
944 | mTimeoutManager = MakeUnique<dom::TimeoutManager>( | |||
945 | *this, StaticPrefs::dom_timeout_max_idle_defer_ms()); | |||
946 | ||||
947 | mObserver = new nsGlobalWindowObserver(this); | |||
948 | if (nsCOMPtr<nsIObserverService> os = services::GetObserverService()) { | |||
949 | // Watch for online/offline status changes so we can fire events. Use | |||
950 | // a strong reference. | |||
951 | os->AddObserver(mObserver, NS_IOSERVICE_OFFLINE_STATUS_TOPIC"network:offline-status-changed", false); | |||
952 | os->AddObserver(mObserver, MEMORY_PRESSURE_OBSERVER_TOPIC"memory-pressure", false); | |||
953 | os->AddObserver(mObserver, PERMISSION_CHANGED_TOPIC"perm-changed", false); | |||
954 | os->AddObserver(mObserver, "screen-information-changed", false); | |||
955 | } | |||
956 | ||||
957 | Preferences::AddStrongObserver(mObserver, "intl.accept_languages"); | |||
958 | ||||
959 | // Watch for storage notifications so we can fire storage events. | |||
960 | RefPtr<StorageNotifierService> sns = StorageNotifierService::GetOrCreate(); | |||
961 | if (sns) { | |||
962 | sns->Register(mObserver); | |||
963 | } | |||
964 | ||||
965 | if (XRE_IsContentProcess()) { | |||
966 | nsCOMPtr<nsIDocShell> docShell = GetDocShell(); | |||
967 | if (docShell) { | |||
968 | mBrowserChild = docShell->GetBrowserChild(); | |||
969 | } | |||
970 | } | |||
971 | ||||
972 | if (gDumpFile == nullptr) { | |||
973 | nsAutoCString fname; | |||
974 | Preferences::GetCString("browser.dom.window.dump.file", fname); | |||
975 | if (!fname.IsEmpty()) { | |||
976 | // If this fails to open, Dump() knows to just go to stdout on null. | |||
977 | gDumpFile = fopen(fname.get(), "wb+"); | |||
978 | } else { | |||
979 | gDumpFile = stdoutstdout; | |||
980 | } | |||
981 | } | |||
982 | ||||
983 | #ifdef DEBUG1 | |||
984 | mSerial = nsContentUtils::InnerOrOuterWindowCreated(); | |||
985 | ||||
986 | MOZ_LOG(gDocShellAndDOMWindowLeakLogging, LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "++DOMWINDOW == %d (%p) [pid = %d] [serial = %d] [outer = %p]\n" , nsContentUtils::GetCurrentInnerOrOuterWindowCount(), static_cast <void*>(ToCanonicalSupports(this)), getpid(), mSerial, static_cast <void*>(ToCanonicalSupports(aOuterWindow))); } } while ( 0) | |||
987 | ("++DOMWINDOW == %d (%p) [pid = %d] [serial = %d] [outer = %p]\n",do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "++DOMWINDOW == %d (%p) [pid = %d] [serial = %d] [outer = %p]\n" , nsContentUtils::GetCurrentInnerOrOuterWindowCount(), static_cast <void*>(ToCanonicalSupports(this)), getpid(), mSerial, static_cast <void*>(ToCanonicalSupports(aOuterWindow))); } } while ( 0) | |||
988 | nsContentUtils::GetCurrentInnerOrOuterWindowCount(),do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "++DOMWINDOW == %d (%p) [pid = %d] [serial = %d] [outer = %p]\n" , nsContentUtils::GetCurrentInnerOrOuterWindowCount(), static_cast <void*>(ToCanonicalSupports(this)), getpid(), mSerial, static_cast <void*>(ToCanonicalSupports(aOuterWindow))); } } while ( 0) | |||
989 | static_cast<void*>(ToCanonicalSupports(this)), getpid(), mSerial,do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "++DOMWINDOW == %d (%p) [pid = %d] [serial = %d] [outer = %p]\n" , nsContentUtils::GetCurrentInnerOrOuterWindowCount(), static_cast <void*>(ToCanonicalSupports(this)), getpid(), mSerial, static_cast <void*>(ToCanonicalSupports(aOuterWindow))); } } while ( 0) | |||
990 | static_cast<void*>(ToCanonicalSupports(aOuterWindow))))do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "++DOMWINDOW == %d (%p) [pid = %d] [serial = %d] [outer = %p]\n" , nsContentUtils::GetCurrentInnerOrOuterWindowCount(), static_cast <void*>(ToCanonicalSupports(this)), getpid(), mSerial, static_cast <void*>(ToCanonicalSupports(aOuterWindow))); } } while ( 0); | |||
991 | #endif | |||
992 | ||||
993 | MOZ_LOG(gDOMLeakPRLogInner, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogInner ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "DOMWINDOW %p created outer=%p", this, aOuterWindow ); } } while (0) | |||
994 | ("DOMWINDOW %p created outer=%p", this, aOuterWindow))do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogInner ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "DOMWINDOW %p created outer=%p", this, aOuterWindow ); } } while (0); | |||
995 | ||||
996 | // Add ourselves to the inner windows list. | |||
997 | MOZ_ASSERT(sInnerWindowsById, "Inner Windows hash table must be created!")do { static_assert( mozilla::detail::AssertionConditionType< decltype(sInnerWindowsById)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sInnerWindowsById))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("sInnerWindowsById" " (" "Inner Windows hash table must be created!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 997); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sInnerWindowsById" ") (" "Inner Windows hash table must be created!" ")"); do { *((volatile int*)__null) = 997; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); | |||
998 | MOZ_ASSERT(!sInnerWindowsById->Contains(mWindowID),do { static_assert( mozilla::detail::AssertionConditionType< decltype(!sInnerWindowsById->Contains(mWindowID))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(!sInnerWindowsById->Contains(mWindowID)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!sInnerWindowsById->Contains(mWindowID)" " (" "This window shouldn't be in the hash table yet!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 999); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sInnerWindowsById->Contains(mWindowID)" ") (" "This window shouldn't be in the hash table yet!" ")") ; do { *((volatile int*)__null) = 999; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
999 | "This window shouldn't be in the hash table yet!")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!sInnerWindowsById->Contains(mWindowID))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(!sInnerWindowsById->Contains(mWindowID)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!sInnerWindowsById->Contains(mWindowID)" " (" "This window shouldn't be in the hash table yet!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 999); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sInnerWindowsById->Contains(mWindowID)" ") (" "This window shouldn't be in the hash table yet!" ")") ; do { *((volatile int*)__null) = 999; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
1000 | // We seem to see crashes in release builds because of null | |||
1001 | // |sInnerWindowsById|. | |||
1002 | if (sInnerWindowsById) { | |||
1003 | sInnerWindowsById->InsertOrUpdate(mWindowID, this); | |||
1004 | } | |||
1005 | } | |||
1006 | ||||
1007 | #ifdef DEBUG1 | |||
1008 | ||||
1009 | /* static */ | |||
1010 | void nsGlobalWindowInner::AssertIsOnMainThread() { | |||
1011 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 1011); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 1011; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
1012 | } | |||
1013 | ||||
1014 | #endif // DEBUG | |||
1015 | ||||
1016 | /* static */ | |||
1017 | void nsGlobalWindowInner::Init() { | |||
1018 | AssertIsOnMainThread(); | |||
1019 | ||||
1020 | NS_ASSERTION(gDOMLeakPRLogInner,do { if (!(gDOMLeakPRLogInner)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "gDOMLeakPRLogInner should have been initialized!", "gDOMLeakPRLogInner" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 1021); MOZ_PretendNoReturn(); } } while (0) | |||
1021 | "gDOMLeakPRLogInner should have been initialized!")do { if (!(gDOMLeakPRLogInner)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "gDOMLeakPRLogInner should have been initialized!", "gDOMLeakPRLogInner" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 1021); MOZ_PretendNoReturn(); } } while (0); | |||
1022 | ||||
1023 | sInnerWindowsById = new InnerWindowByIdTable(); | |||
1024 | } | |||
1025 | ||||
1026 | nsGlobalWindowInner::~nsGlobalWindowInner() { | |||
1027 | AssertIsOnMainThread(); | |||
1028 | MOZ_ASSERT(!mHintedWasLoading)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mHintedWasLoading)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mHintedWasLoading))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mHintedWasLoading" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 1028); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mHintedWasLoading" ")"); do { *((volatile int*)__null) = 1028; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
1029 | ||||
1030 | if (IsChromeWindow()) { | |||
1031 | MOZ_ASSERT(mCleanMessageManager,do { static_assert( mozilla::detail::AssertionConditionType< decltype(mCleanMessageManager)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mCleanMessageManager))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("mCleanMessageManager" " (" "chrome windows may always disconnect the msg manager" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 1032); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCleanMessageManager" ") (" "chrome windows may always disconnect the msg manager" ")"); do { *((volatile int*)__null) = 1032; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
1032 | "chrome windows may always disconnect the msg manager")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mCleanMessageManager)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mCleanMessageManager))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("mCleanMessageManager" " (" "chrome windows may always disconnect the msg manager" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 1032); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCleanMessageManager" ") (" "chrome windows may always disconnect the msg manager" ")"); do { *((volatile int*)__null) = 1032; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
1033 | ||||
1034 | DisconnectAndClearGroupMessageManagers(); | |||
1035 | ||||
1036 | if (mChromeFields.mMessageManager) { | |||
1037 | static_cast<nsFrameMessageManager*>(mChromeFields.mMessageManager.get()) | |||
1038 | ->Disconnect(); | |||
1039 | } | |||
1040 | ||||
1041 | mCleanMessageManager = false; | |||
1042 | } | |||
1043 | ||||
1044 | // In most cases this should already have been called, but call it again | |||
1045 | // here to catch any corner cases. | |||
1046 | FreeInnerObjects(); | |||
1047 | ||||
1048 | if (sInnerWindowsById) { | |||
1049 | sInnerWindowsById->Remove(mWindowID); | |||
1050 | } | |||
1051 | ||||
1052 | nsContentUtils::InnerOrOuterWindowDestroyed(); | |||
1053 | ||||
1054 | #ifdef DEBUG1 | |||
1055 | if (MOZ_LOG_TEST(gDocShellAndDOMWindowLeakLogging, LogLevel::Info)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellAndDOMWindowLeakLogging , LogLevel::Info)), 0))) { | |||
1056 | nsAutoCString url; | |||
1057 | if (mLastOpenedURI) { | |||
1058 | url = mLastOpenedURI->GetSpecOrDefault(); | |||
1059 | ||||
1060 | // Data URLs can be very long, so truncate to avoid flooding the log. | |||
1061 | const uint32_t maxURLLength = 1000; | |||
1062 | if (url.Length() > maxURLLength) { | |||
1063 | url.Truncate(maxURLLength); | |||
1064 | } | |||
1065 | } | |||
1066 | ||||
1067 | nsGlobalWindowOuter* outer = nsGlobalWindowOuter::Cast(mOuterWindow); | |||
1068 | MOZ_LOG(do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "--DOMWINDOW == %d (%p) [pid = %d] [serial = %d] [outer = %p] [url = " "%s]\n", nsContentUtils::GetCurrentInnerOrOuterWindowCount() , static_cast<void*>(ToCanonicalSupports(this)), getpid (), mSerial, static_cast<void*>(ToCanonicalSupports(outer )), url.get()); } } while (0) | |||
1069 | gDocShellAndDOMWindowLeakLogging, LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "--DOMWINDOW == %d (%p) [pid = %d] [serial = %d] [outer = %p] [url = " "%s]\n", nsContentUtils::GetCurrentInnerOrOuterWindowCount() , static_cast<void*>(ToCanonicalSupports(this)), getpid (), mSerial, static_cast<void*>(ToCanonicalSupports(outer )), url.get()); } } while (0) | |||
1070 | ("--DOMWINDOW == %d (%p) [pid = %d] [serial = %d] [outer = %p] [url = "do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "--DOMWINDOW == %d (%p) [pid = %d] [serial = %d] [outer = %p] [url = " "%s]\n", nsContentUtils::GetCurrentInnerOrOuterWindowCount() , static_cast<void*>(ToCanonicalSupports(this)), getpid (), mSerial, static_cast<void*>(ToCanonicalSupports(outer )), url.get()); } } while (0) | |||
1071 | "%s]\n",do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "--DOMWINDOW == %d (%p) [pid = %d] [serial = %d] [outer = %p] [url = " "%s]\n", nsContentUtils::GetCurrentInnerOrOuterWindowCount() , static_cast<void*>(ToCanonicalSupports(this)), getpid (), mSerial, static_cast<void*>(ToCanonicalSupports(outer )), url.get()); } } while (0) | |||
1072 | nsContentUtils::GetCurrentInnerOrOuterWindowCount(),do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "--DOMWINDOW == %d (%p) [pid = %d] [serial = %d] [outer = %p] [url = " "%s]\n", nsContentUtils::GetCurrentInnerOrOuterWindowCount() , static_cast<void*>(ToCanonicalSupports(this)), getpid (), mSerial, static_cast<void*>(ToCanonicalSupports(outer )), url.get()); } } while (0) | |||
1073 | static_cast<void*>(ToCanonicalSupports(this)), getpid(), mSerial,do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "--DOMWINDOW == %d (%p) [pid = %d] [serial = %d] [outer = %p] [url = " "%s]\n", nsContentUtils::GetCurrentInnerOrOuterWindowCount() , static_cast<void*>(ToCanonicalSupports(this)), getpid (), mSerial, static_cast<void*>(ToCanonicalSupports(outer )), url.get()); } } while (0) | |||
1074 | static_cast<void*>(ToCanonicalSupports(outer)), url.get()))do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "--DOMWINDOW == %d (%p) [pid = %d] [serial = %d] [outer = %p] [url = " "%s]\n", nsContentUtils::GetCurrentInnerOrOuterWindowCount() , static_cast<void*>(ToCanonicalSupports(this)), getpid (), mSerial, static_cast<void*>(ToCanonicalSupports(outer )), url.get()); } } while (0); | |||
1075 | } | |||
1076 | #endif | |||
1077 | MOZ_LOG(gDOMLeakPRLogInner, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogInner ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "DOMWINDOW %p destroyed", this); } } while (0) | |||
1078 | ("DOMWINDOW %p destroyed", this))do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogInner ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "DOMWINDOW %p destroyed", this); } } while (0); | |||
1079 | ||||
1080 | Telemetry::Accumulate(Telemetry::INNERWINDOWS_WITH_MUTATION_LISTENERS, | |||
1081 | mMutationBits ? 1 : 0); | |||
1082 | ||||
1083 | // An inner window is destroyed, pull it out of the outer window's | |||
1084 | // list if inner windows. | |||
1085 | ||||
1086 | PR_REMOVE_LINK(this)do { (this)->prev->next = (this)->next; (this)->next ->prev = (this)->prev; } while (0); | |||
1087 | ||||
1088 | // If our outer window's inner window is this window, null out the | |||
1089 | // outer window's reference to this window that's being deleted. | |||
1090 | nsGlobalWindowOuter* outer = GetOuterWindowInternal(); | |||
1091 | if (outer) { | |||
1092 | outer->MaybeClearInnerWindow(this); | |||
1093 | } | |||
1094 | ||||
1095 | // We don't have to leave the tab group if we are an inner window. | |||
1096 | ||||
1097 | nsCOMPtr<nsIDeviceSensors> ac = do_GetService(NS_DEVICE_SENSORS_CONTRACTID"@mozilla.org/devicesensors;1"); | |||
1098 | if (ac) ac->RemoveWindowAsListener(this); | |||
1099 | ||||
1100 | nsLayoutStatics::Release(); | |||
1101 | } | |||
1102 | ||||
1103 | // static | |||
1104 | void nsGlobalWindowInner::ShutDown() { | |||
1105 | AssertIsOnMainThread(); | |||
1106 | ||||
1107 | if (gDumpFile && gDumpFile != stdoutstdout) { | |||
1108 | fclose(gDumpFile); | |||
1109 | } | |||
1110 | gDumpFile = nullptr; | |||
1111 | ||||
1112 | delete sInnerWindowsById; | |||
1113 | sInnerWindowsById = nullptr; | |||
1114 | } | |||
1115 | ||||
1116 | void nsGlobalWindowInner::FreeInnerObjects() { | |||
1117 | if (IsDying()) { | |||
1118 | return; | |||
1119 | } | |||
1120 | StartDying(); | |||
1121 | ||||
1122 | if (mDoc && mDoc->GetWindowContext()) { | |||
1123 | // The document is about to lose its window, so this is a good time to send | |||
1124 | // our page use counters. | |||
1125 | // | |||
1126 | // (We also do this in Document::SetScriptGlobalObject(nullptr), which | |||
1127 | // catches most cases of documents losing their window, but not all.) | |||
1128 | mDoc->SendPageUseCounters(); | |||
1129 | } | |||
1130 | ||||
1131 | // Make sure that this is called before we null out the document and | |||
1132 | // other members that the window destroyed observers could | |||
1133 | // re-create. | |||
1134 | NotifyDOMWindowDestroyed(this); | |||
1135 | if (auto* reporter = nsWindowMemoryReporter::Get()) { | |||
1136 | reporter->ObserveDOMWindowDetached(this); | |||
1137 | } | |||
1138 | ||||
1139 | // Kill all of the workers for this window. | |||
1140 | CancelWorkersForWindow(*this); | |||
1141 | ||||
1142 | for (RefPtr<mozilla::dom::SharedWorker> pinnedWorker : | |||
1143 | mSharedWorkers.ForwardRange()) { | |||
1144 | pinnedWorker->Close(); | |||
1145 | } | |||
1146 | ||||
1147 | if (mTimeoutManager) { | |||
1148 | mTimeoutManager->ClearAllTimeouts(); | |||
1149 | } | |||
1150 | ||||
1151 | DisableIdleCallbackRequests(); | |||
1152 | ||||
1153 | mChromeEventHandler = nullptr; | |||
1154 | ||||
1155 | if (mListenerManager) { | |||
1156 | mListenerManager->RemoveAllListeners(); | |||
1157 | mListenerManager->Disconnect(); | |||
1158 | mListenerManager = nullptr; | |||
1159 | } | |||
1160 | ||||
1161 | mHistory = nullptr; | |||
1162 | ||||
1163 | if (mNavigator) { | |||
1164 | mNavigator->OnNavigation(); | |||
1165 | mNavigator->Invalidate(); | |||
1166 | mNavigator = nullptr; | |||
1167 | } | |||
1168 | ||||
1169 | mScreen = nullptr; | |||
1170 | ||||
1171 | if (mDoc) { | |||
1172 | // Remember the document's principal, URI, and CSP. | |||
1173 | mDocumentPrincipal = mDoc->NodePrincipal(); | |||
1174 | mDocumentCookiePrincipal = mDoc->EffectiveCookiePrincipal(); | |||
1175 | mDocumentStoragePrincipal = mDoc->EffectiveStoragePrincipal(); | |||
1176 | mDocumentPartitionedPrincipal = mDoc->PartitionedPrincipal(); | |||
1177 | mDocumentURI = mDoc->GetDocumentURI(); | |||
1178 | mDocBaseURI = mDoc->GetDocBaseURI(); | |||
1179 | mDocumentCsp = mDoc->GetCsp(); | |||
1180 | ||||
1181 | while (mDoc->EventHandlingSuppressed()) { | |||
1182 | mDoc->UnsuppressEventHandlingAndFireEvents(false); | |||
1183 | } | |||
1184 | } | |||
1185 | ||||
1186 | // Remove our reference to the document and the document principal. | |||
1187 | mFocusedElement = nullptr; | |||
1188 | ||||
1189 | nsIGlobalObject::UnlinkObjectsInGlobal(); | |||
1190 | ||||
1191 | NotifyWindowIDDestroyed("inner-window-destroyed"); | |||
1192 | ||||
1193 | for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) { | |||
1194 | mAudioContexts[i]->OnWindowDestroy(); | |||
1195 | } | |||
1196 | mAudioContexts.Clear(); | |||
1197 | ||||
1198 | for (MediaKeys* mediaKeys : mMediaKeysInstances) { | |||
1199 | mediaKeys->OnInnerWindowDestroy(); | |||
1200 | } | |||
1201 | mMediaKeysInstances.Clear(); | |||
1202 | ||||
1203 | DisableGamepadUpdates(); | |||
1204 | mHasGamepad = false; | |||
1205 | mGamepads.Clear(); | |||
1206 | DisableVRUpdates(); | |||
1207 | mHasXRSession = false; | |||
1208 | mHasVRDisplayActivateEvents = false; | |||
1209 | mXRRuntimeDetectionInFlight = false; | |||
1210 | mXRPermissionRequestInFlight = false; | |||
1211 | mXRPermissionGranted = false; | |||
1212 | mVRDisplays.Clear(); | |||
1213 | ||||
1214 | // This breaks a cycle between the window and the ClientSource object. | |||
1215 | mClientSource.reset(); | |||
1216 | ||||
1217 | if (mWindowGlobalChild) { | |||
1218 | // Remove any remaining listeners. | |||
1219 | int64_t nListeners = mWindowGlobalChild->BeforeUnloadListeners(); | |||
1220 | for (int64_t i = 0; i < nListeners; ++i) { | |||
1221 | mWindowGlobalChild->BeforeUnloadRemoved(); | |||
1222 | } | |||
1223 | MOZ_ASSERT(mWindowGlobalChild->BeforeUnloadListeners() == 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mWindowGlobalChild->BeforeUnloadListeners() == 0) >::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(mWindowGlobalChild->BeforeUnloadListeners() == 0) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mWindowGlobalChild->BeforeUnloadListeners() == 0" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 1223); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mWindowGlobalChild->BeforeUnloadListeners() == 0" ")"); do { *((volatile int*)__null) = 1223; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
1224 | } | |||
1225 | ||||
1226 | // If we have any promiseDocumentFlushed callbacks, fire them now so | |||
1227 | // that the Promises can resolve. | |||
1228 | CallDocumentFlushedResolvers(/* aUntilExhaustion = */ true); | |||
1229 | ||||
1230 | DisconnectGlobalTeardownObservers(); | |||
1231 | ||||
1232 | #ifdef MOZ_WIDGET_ANDROID | |||
1233 | DisableOrientationChangeListener(); | |||
1234 | #endif | |||
1235 | ||||
1236 | if (mObserver) { | |||
1237 | if (nsCOMPtr<nsIObserverService> os = services::GetObserverService()) { | |||
1238 | os->RemoveObserver(mObserver, NS_IOSERVICE_OFFLINE_STATUS_TOPIC"network:offline-status-changed"); | |||
1239 | os->RemoveObserver(mObserver, MEMORY_PRESSURE_OBSERVER_TOPIC"memory-pressure"); | |||
1240 | os->RemoveObserver(mObserver, PERMISSION_CHANGED_TOPIC"perm-changed"); | |||
1241 | os->RemoveObserver(mObserver, "screen-information-changed"); | |||
1242 | } | |||
1243 | ||||
1244 | RefPtr<StorageNotifierService> sns = StorageNotifierService::GetOrCreate(); | |||
1245 | if (sns) { | |||
1246 | sns->Unregister(mObserver); | |||
1247 | } | |||
1248 | ||||
1249 | Preferences::RemoveObserver(mObserver, "intl.accept_languages"); | |||
1250 | ||||
1251 | // Drop its reference to this dying window, in case for some bogus reason | |||
1252 | // the object stays around. | |||
1253 | mObserver->Forget(); | |||
1254 | } | |||
1255 | ||||
1256 | mMenubar = nullptr; | |||
1257 | mToolbar = nullptr; | |||
1258 | mLocationbar = nullptr; | |||
1259 | mPersonalbar = nullptr; | |||
1260 | mStatusbar = nullptr; | |||
1261 | mScrollbars = nullptr; | |||
1262 | ||||
1263 | mConsole = nullptr; | |||
1264 | ||||
1265 | mPaintWorklet = nullptr; | |||
1266 | ||||
1267 | mExternal = nullptr; | |||
1268 | mInstallTrigger = nullptr; | |||
1269 | ||||
1270 | if (mLocalStorage) { | |||
1271 | mLocalStorage->Disconnect(); | |||
1272 | mLocalStorage = nullptr; | |||
1273 | } | |||
1274 | mSessionStorage = nullptr; | |||
1275 | if (mPerformance) { | |||
1276 | // Since window is dying, nothing is going to be painted | |||
1277 | // with meaningful sizes, so these temp data for LCP is | |||
1278 | // no longer needed. | |||
1279 | static_cast<PerformanceMainThread*>(mPerformance.get()) | |||
1280 | ->ClearGeneratedTempDataForLCP(); | |||
1281 | } | |||
1282 | mPerformance = nullptr; | |||
1283 | ||||
1284 | mContentMediaController = nullptr; | |||
1285 | ||||
1286 | if (mWebTaskScheduler) { | |||
1287 | mWebTaskScheduler->Disconnect(); | |||
1288 | mWebTaskScheduler = nullptr; | |||
1289 | } | |||
1290 | ||||
1291 | mTrustedTypePolicyFactory = nullptr; | |||
1292 | ||||
1293 | mSharedWorkers.Clear(); | |||
1294 | ||||
1295 | #ifdef MOZ_WEBSPEECH1 | |||
1296 | mSpeechSynthesis = nullptr; | |||
1297 | #endif | |||
1298 | ||||
1299 | mGlean = nullptr; | |||
1300 | mGleanPings = nullptr; | |||
1301 | ||||
1302 | mParentTarget = nullptr; | |||
1303 | ||||
1304 | if (mCleanMessageManager) { | |||
1305 | MOZ_ASSERT(mIsChrome, "only chrome should have msg manager cleaned")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mIsChrome)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mIsChrome))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mIsChrome" " (" "only chrome should have msg manager cleaned" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 1305); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIsChrome" ") (" "only chrome should have msg manager cleaned" ")"); do { *(( volatile int*)__null) = 1305; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); | |||
1306 | if (mChromeFields.mMessageManager) { | |||
1307 | mChromeFields.mMessageManager->Disconnect(); | |||
1308 | } | |||
1309 | } | |||
1310 | ||||
1311 | if (mWindowGlobalChild && !mWindowGlobalChild->IsClosed()) { | |||
1312 | mWindowGlobalChild->Destroy(); | |||
1313 | } | |||
1314 | ||||
1315 | mIntlUtils = nullptr; | |||
1316 | ||||
1317 | HintIsLoading(false); | |||
1318 | } | |||
1319 | ||||
1320 | //***************************************************************************** | |||
1321 | // nsGlobalWindowInner::nsISupports | |||
1322 | //***************************************************************************** | |||
1323 | ||||
1324 | // QueryInterface implementation for nsGlobalWindowInner | |||
1325 | NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsGlobalWindowInner)nsresult nsGlobalWindowInner::QueryInterface(const nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak (NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!" , "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 1325); MOZ_PretendNoReturn(); } } while (0); nsISupports* foundInterface ; if (TopThreeWordsEquals( aIID, (nsXPCOMCycleCollectionParticipant ::COMTypeInfo<nsXPCOMCycleCollectionParticipant, void>:: kIID), (nsCycleCollectionISupports::COMTypeInfo<nsCycleCollectionISupports , void>::kIID)) && (LowWordEquals(aIID, (nsXPCOMCycleCollectionParticipant ::COMTypeInfo<nsXPCOMCycleCollectionParticipant, void>:: kIID)) || LowWordEquals(aIID, (nsCycleCollectionISupports::COMTypeInfo <nsCycleCollectionISupports, void>::kIID)))) { if (LowWordEquals (aIID, (nsXPCOMCycleCollectionParticipant::COMTypeInfo<nsXPCOMCycleCollectionParticipant , void>::kIID))) { *aInstancePtr = nsGlobalWindowInner::cycleCollection ::GetParticipant(); return NS_OK; } if (LowWordEquals(aIID, ( nsCycleCollectionISupports::COMTypeInfo<nsCycleCollectionISupports , void>::kIID))) { *aInstancePtr = nsGlobalWindowInner::cycleCollection ::Upcast(this); return NS_OK; } foundInterface = nullptr; } else | |||
1326 | NS_WRAPPERCACHE_INTERFACE_MAP_ENTRYif (aIID.Equals((nsWrapperCache::COMTypeInfo<nsWrapperCache , void>::kIID))) { *aInstancePtr = static_cast<nsWrapperCache *>(this); return NS_OK; } else | |||
1327 | NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, EventTarget)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsISupports>)) foundInterface = static_cast <nsISupports*>(static_cast<EventTarget*>(this)); else | |||
1328 | NS_INTERFACE_MAP_ENTRY(nsIDOMWindow)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsIDOMWindow>)) foundInterface = static_cast <nsIDOMWindow*>(this); else | |||
1329 | NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsIGlobalObject>)) foundInterface = static_cast<nsIGlobalObject*>(this); else | |||
1330 | NS_INTERFACE_MAP_ENTRY(nsIScriptGlobalObject)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsIScriptGlobalObject>)) foundInterface = static_cast<nsIScriptGlobalObject*>(this); else | |||
1331 | NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsIScriptObjectPrincipal>)) foundInterface = static_cast<nsIScriptObjectPrincipal*>(this); else | |||
1332 | NS_INTERFACE_MAP_ENTRY(mozilla::dom::EventTarget)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, mozilla::dom::EventTarget>)) foundInterface = static_cast<mozilla::dom::EventTarget*>(this); else | |||
1333 | NS_INTERFACE_MAP_ENTRY(nsPIDOMWindowInner)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsPIDOMWindowInner>)) foundInterface = static_cast<nsPIDOMWindowInner*>(this); else | |||
1334 | NS_INTERFACE_MAP_ENTRY(mozIDOMWindow)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, mozIDOMWindow>)) foundInterface = static_cast<mozIDOMWindow*>(this); else | |||
1335 | NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsISupportsWeakReference>)) foundInterface = static_cast<nsISupportsWeakReference*>(this); else | |||
1336 | NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsIInterfaceRequestor>)) foundInterface = static_cast<nsIInterfaceRequestor*>(this); else | |||
1337 | NS_INTERFACE_MAP_ENDfoundInterface = 0; nsresult status; if (!foundInterface) { do { static_assert( mozilla::detail::AssertionConditionType< decltype(!aIID.Equals((nsISupports::COMTypeInfo<nsISupports , void>::kIID)))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!aIID.Equals((nsISupports::COMTypeInfo <nsISupports, void>::kIID))))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("!aIID.Equals((nsISupports::COMTypeInfo<nsISupports, void>::kIID))" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 1337); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIID.Equals((nsISupports::COMTypeInfo<nsISupports, void>::kIID))" ")"); do { *((volatile int*)__null) = 1337; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); status = NS_NOINTERFACE ; } else { (foundInterface)->AddRef(); status = NS_OK; } * aInstancePtr = foundInterface; return status; } | |||
1338 | ||||
1339 | NS_IMPL_CYCLE_COLLECTING_ADDREF(nsGlobalWindowInner)MozExternalRefCountType nsGlobalWindowInner::AddRef(void) { static_assert (!std::is_destructible_v<nsGlobalWindowInner>, "Reference-counted class " "nsGlobalWindowInner" " should not have a public destructor. " "Make this class's destructor non-public"); do { static_assert ( mozilla::detail::AssertionConditionType<decltype(int32_t (mRefCnt) >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0" " (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 1339); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 1339; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); _mOwningThread.AssertOwnership("nsGlobalWindowInner" " not thread-safe"); nsISupports* base = nsGlobalWindowInner ::cycleCollection::Upcast(this); nsrefcnt count = mRefCnt.incr (base); NS_LogAddRef((this), (count), ("nsGlobalWindowInner") , (uint32_t)(sizeof(*this))); return count; } | |||
1340 | NS_IMPL_CYCLE_COLLECTING_RELEASE(nsGlobalWindowInner)MozExternalRefCountType nsGlobalWindowInner::Release(void) { do { static_assert( mozilla::detail::AssertionConditionType< decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 1340); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 1340 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); _mOwningThread.AssertOwnership("nsGlobalWindowInner" " not thread-safe"); nsISupports* base = nsGlobalWindowInner ::cycleCollection::Upcast(this); nsrefcnt count = mRefCnt.decr (base); NS_LogRelease((this), (count), ("nsGlobalWindowInner" )); return count; } void nsGlobalWindowInner::DeleteCycleCollectable (void) { delete (this); } | |||
1341 | ||||
1342 | NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsGlobalWindowInner)bool nsGlobalWindowInner::cycleCollection::CanSkipReal(void* p , bool aRemovingAllowed) { nsGlobalWindowInner* tmp = DowncastCCParticipant <nsGlobalWindowInner>(p); | |||
1343 | if (tmp->IsBlackForCC(false)) { | |||
1344 | if (nsCCUncollectableMarker::InGeneration(tmp->mCanSkipCCGeneration)) { | |||
1345 | return true; | |||
1346 | } | |||
1347 | tmp->mCanSkipCCGeneration = nsCCUncollectableMarker::sGeneration; | |||
1348 | if (EventListenerManager* elm = tmp->GetExistingListenerManager()) { | |||
1349 | elm->MarkForCC(); | |||
1350 | } | |||
1351 | if (tmp->mTimeoutManager) { | |||
1352 | tmp->mTimeoutManager->UnmarkGrayTimers(); | |||
1353 | } | |||
1354 | return true; | |||
1355 | } | |||
1356 | NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END(void)tmp; return false; } | |||
1357 | ||||
1358 | NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsGlobalWindowInner)bool nsGlobalWindowInner::cycleCollection::CanSkipInCCReal(void * p) { nsGlobalWindowInner* tmp = DowncastCCParticipant<nsGlobalWindowInner >(p); | |||
1359 | return tmp->IsBlackForCC(true); | |||
1360 | NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END(void)tmp; return false; } | |||
1361 | ||||
1362 | NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsGlobalWindowInner)bool nsGlobalWindowInner::cycleCollection::CanSkipThisReal(void * p) { nsGlobalWindowInner* tmp = DowncastCCParticipant<nsGlobalWindowInner >(p); | |||
1363 | return tmp->IsBlackForCC(false); | |||
1364 | NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END(void)tmp; return false; } | |||
1365 | ||||
1366 | NS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalWindowInner)nsGlobalWindowInner::cycleCollection nsGlobalWindowInner::_cycleCollectorGlobal ; | |||
1367 | ||||
1368 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGlobalWindowInner)nsresult nsGlobalWindowInner::cycleCollection::TraverseNative ( void* p, nsCycleCollectionTraversalCallback& cb) { nsGlobalWindowInner * tmp = DowncastCCParticipant<nsGlobalWindowInner>(p); | |||
1369 | if (MOZ_UNLIKELY(cb.WantDebugInfo())(__builtin_expect(!!(cb.WantDebugInfo()), 0))) { | |||
1370 | char name[512]; | |||
1371 | nsAutoCString uri; | |||
1372 | if (tmp->mDoc && tmp->mDoc->GetDocumentURI()) { | |||
1373 | uri = tmp->mDoc->GetDocumentURI()->GetSpecOrDefault(); | |||
1374 | } | |||
1375 | SprintfLiteral(name, "nsGlobalWindowInner # %" PRIu64"l" "u" " inner %s", | |||
1376 | tmp->mWindowID, uri.get()); | |||
1377 | cb.DescribeRefCountedNode(tmp->mRefCnt.get(), name); | |||
1378 | } else { | |||
1379 | NS_IMPL_CYCLE_COLLECTION_DESCRIBE(nsGlobalWindowInner, tmp->mRefCnt.get())cb.DescribeRefCountedNode(tmp->mRefCnt.get(), "nsGlobalWindowInner" ); | |||
1380 | } | |||
1381 | ||||
1382 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNavigator)ImplCycleCollectionTraverse(cb, tmp->mNavigator, "mNavigator" , 0); | |||
1383 | ||||
1384 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPerformance)ImplCycleCollectionTraverse(cb, tmp->mPerformance, "mPerformance" , 0); | |||
1385 | ||||
1386 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWebTaskScheduler)ImplCycleCollectionTraverse(cb, tmp->mWebTaskScheduler, "mWebTaskScheduler" , 0); | |||
1387 | ||||
1388 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTrustedTypePolicyFactory)ImplCycleCollectionTraverse(cb, tmp->mTrustedTypePolicyFactory , "mTrustedTypePolicyFactory", 0); | |||
1389 | ||||
1390 | #ifdef MOZ_WEBSPEECH1 | |||
1391 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSpeechSynthesis)ImplCycleCollectionTraverse(cb, tmp->mSpeechSynthesis, "mSpeechSynthesis" , 0); | |||
1392 | #endif | |||
1393 | ||||
1394 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlean)ImplCycleCollectionTraverse(cb, tmp->mGlean, "mGlean", 0); | |||
1395 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGleanPings)ImplCycleCollectionTraverse(cb, tmp->mGleanPings, "mGleanPings" , 0); | |||
1396 | ||||
1397 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOuterWindow)ImplCycleCollectionTraverse(cb, tmp->mOuterWindow, "mOuterWindow" , 0); | |||
1398 | ||||
1399 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTopInnerWindow)ImplCycleCollectionTraverse(cb, tmp->mTopInnerWindow, "mTopInnerWindow" , 0); | |||
1400 | ||||
1401 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mListenerManager)ImplCycleCollectionTraverse(cb, tmp->mListenerManager, "mListenerManager" , 0); | |||
1402 | ||||
1403 | if (tmp->mTimeoutManager) { | |||
1404 | tmp->mTimeoutManager->ForEachUnorderedTimeout([&cb](Timeout* timeout) { | |||
1405 | cb.NoteNativeChild(timeout, NS_CYCLE_COLLECTION_PARTICIPANT(Timeout)Timeout::cycleCollection::GetParticipant()); | |||
1406 | }); | |||
1407 | } | |||
1408 | ||||
1409 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocation)ImplCycleCollectionTraverse(cb, tmp->mLocation, "mLocation" , 0); | |||
1410 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mHistory)ImplCycleCollectionTraverse(cb, tmp->mHistory, "mHistory", 0); | |||
1411 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNavigation)ImplCycleCollectionTraverse(cb, tmp->mNavigation, "mNavigation" , 0); | |||
1412 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCustomElements)ImplCycleCollectionTraverse(cb, tmp->mCustomElements, "mCustomElements" , 0); | |||
1413 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSharedWorkers)ImplCycleCollectionTraverse(cb, tmp->mSharedWorkers, "mSharedWorkers" , 0); | |||
1414 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocalStorage)ImplCycleCollectionTraverse(cb, tmp->mLocalStorage, "mLocalStorage" , 0); | |||
1415 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSessionStorage)ImplCycleCollectionTraverse(cb, tmp->mSessionStorage, "mSessionStorage" , 0); | |||
1416 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIndexedDB)ImplCycleCollectionTraverse(cb, tmp->mIndexedDB, "mIndexedDB" , 0); | |||
1417 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentPrincipal)ImplCycleCollectionTraverse(cb, tmp->mDocumentPrincipal, "mDocumentPrincipal" , 0); | |||
1418 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentCookiePrincipal)ImplCycleCollectionTraverse(cb, tmp->mDocumentCookiePrincipal , "mDocumentCookiePrincipal", 0); | |||
1419 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentStoragePrincipal)ImplCycleCollectionTraverse(cb, tmp->mDocumentStoragePrincipal , "mDocumentStoragePrincipal", 0); | |||
1420 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentPartitionedPrincipal)ImplCycleCollectionTraverse(cb, tmp->mDocumentPartitionedPrincipal , "mDocumentPartitionedPrincipal", 0); | |||
1421 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentCsp)ImplCycleCollectionTraverse(cb, tmp->mDocumentCsp, "mDocumentCsp" , 0); | |||
1422 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowserChild)ImplCycleCollectionTraverse(cb, tmp->mBrowserChild, "mBrowserChild" , 0); | |||
1423 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDoc)ImplCycleCollectionTraverse(cb, tmp->mDoc, "mDoc", 0); | |||
1424 | ||||
1425 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIdleRequestExecutor)ImplCycleCollectionTraverse(cb, tmp->mIdleRequestExecutor, "mIdleRequestExecutor", 0); | |||
1426 | for (IdleRequest* request : tmp->mIdleRequestCallbacks) { | |||
1427 | cb.NoteNativeChild(request, NS_CYCLE_COLLECTION_PARTICIPANT(IdleRequest)IdleRequest::cycleCollection::GetParticipant()); | |||
1428 | } | |||
1429 | ||||
1430 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mClientSource)ImplCycleCollectionTraverse(cb, tmp->mClientSource, "mClientSource" , 0); | |||
1431 | ||||
1432 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGamepads)ImplCycleCollectionTraverse(cb, tmp->mGamepads, "mGamepads" , 0); | |||
1433 | ||||
1434 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCacheStorage)ImplCycleCollectionTraverse(cb, tmp->mCacheStorage, "mCacheStorage" , 0); | |||
1435 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVRDisplays)ImplCycleCollectionTraverse(cb, tmp->mVRDisplays, "mVRDisplays" , 0); | |||
1436 | ||||
1437 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDebuggerNotificationManager)ImplCycleCollectionTraverse(cb, tmp->mDebuggerNotificationManager , "mDebuggerNotificationManager", 0); | |||
1438 | ||||
1439 | // Traverse stuff from nsPIDOMWindow | |||
1440 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeEventHandler)ImplCycleCollectionTraverse(cb, tmp->mChromeEventHandler, "mChromeEventHandler" , 0); | |||
1441 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParentTarget)ImplCycleCollectionTraverse(cb, tmp->mParentTarget, "mParentTarget" , 0); | |||
1442 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFocusedElement)ImplCycleCollectionTraverse(cb, tmp->mFocusedElement, "mFocusedElement" , 0); | |||
1443 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowsingContext)ImplCycleCollectionTraverse(cb, tmp->mBrowsingContext, "mBrowsingContext" , 0); | |||
1444 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindowGlobalChild)ImplCycleCollectionTraverse(cb, tmp->mWindowGlobalChild, "mWindowGlobalChild" , 0); | |||
1445 | ||||
1446 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMenubar)ImplCycleCollectionTraverse(cb, tmp->mMenubar, "mMenubar", 0); | |||
1447 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mToolbar)ImplCycleCollectionTraverse(cb, tmp->mToolbar, "mToolbar", 0); | |||
1448 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocationbar)ImplCycleCollectionTraverse(cb, tmp->mLocationbar, "mLocationbar" , 0); | |||
1449 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPersonalbar)ImplCycleCollectionTraverse(cb, tmp->mPersonalbar, "mPersonalbar" , 0); | |||
1450 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStatusbar)ImplCycleCollectionTraverse(cb, tmp->mStatusbar, "mStatusbar" , 0); | |||
1451 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mScrollbars)ImplCycleCollectionTraverse(cb, tmp->mScrollbars, "mScrollbars" , 0); | |||
1452 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCrypto)ImplCycleCollectionTraverse(cb, tmp->mCrypto, "mCrypto", 0 ); | |||
1453 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConsole)ImplCycleCollectionTraverse(cb, tmp->mConsole, "mConsole", 0); | |||
1454 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPaintWorklet)ImplCycleCollectionTraverse(cb, tmp->mPaintWorklet, "mPaintWorklet" , 0); | |||
1455 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mExternal)ImplCycleCollectionTraverse(cb, tmp->mExternal, "mExternal" , 0); | |||
1456 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mInstallTrigger)ImplCycleCollectionTraverse(cb, tmp->mInstallTrigger, "mInstallTrigger" , 0); | |||
1457 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIntlUtils)ImplCycleCollectionTraverse(cb, tmp->mIntlUtils, "mIntlUtils" , 0); | |||
1458 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVisualViewport)ImplCycleCollectionTraverse(cb, tmp->mVisualViewport, "mVisualViewport" , 0); | |||
1459 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCurrentPasteDataTransfer)ImplCycleCollectionTraverse(cb, tmp->mCurrentPasteDataTransfer , "mCurrentPasteDataTransfer", 0); | |||
1460 | ||||
1461 | tmp->TraverseObjectsInGlobal(cb); | |||
1462 | ||||
1463 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeFields.mMessageManager)ImplCycleCollectionTraverse(cb, tmp->mChromeFields.mMessageManager , "mChromeFields.mMessageManager", 0); | |||
1464 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeFields.mGroupMessageManagers)ImplCycleCollectionTraverse(cb, tmp->mChromeFields.mGroupMessageManagers , "mChromeFields.mGroupMessageManagers", 0); | |||
1465 | ||||
1466 | for (size_t i = 0; i < tmp->mDocumentFlushedResolvers.Length(); i++) { | |||
1467 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentFlushedResolvers[i]->mPromise)ImplCycleCollectionTraverse(cb, tmp->mDocumentFlushedResolvers [i]->mPromise, "mDocumentFlushedResolvers[i]->mPromise" , 0);; | |||
1468 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentFlushedResolvers[i]->mCallback)ImplCycleCollectionTraverse(cb, tmp->mDocumentFlushedResolvers [i]->mCallback, "mDocumentFlushedResolvers[i]->mCallback" , 0);; | |||
1469 | } | |||
1470 | ||||
1471 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END(void)tmp; return NS_OK; } | |||
1472 | ||||
1473 | NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindowInner)void nsGlobalWindowInner::cycleCollection::Unlink(void* p) { nsGlobalWindowInner * tmp = DowncastCCParticipant<nsGlobalWindowInner>(p); | |||
1474 | NS_IMPL_CYCLE_COLLECTION_UNLINK_WEAK_REFERENCEtmp->ClearWeakReferences(); | |||
1475 | if (sInnerWindowsById) { | |||
1476 | sInnerWindowsById->Remove(tmp->mWindowID); | |||
1477 | } | |||
1478 | ||||
1479 | JSObject* wrapper = tmp->GetWrapperPreserveColor(); | |||
1480 | if (wrapper) { | |||
1481 | // Mark our realm as dead, so the JS engine won't hand out our | |||
1482 | // global after this point. | |||
1483 | JS::SetRealmNonLive(js::GetNonCCWObjectRealm(wrapper)); | |||
1484 | } | |||
1485 | ||||
1486 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mNavigator)ImplCycleCollectionUnlink(tmp->mNavigator); | |||
1487 | ||||
1488 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mPerformance)ImplCycleCollectionUnlink(tmp->mPerformance); | |||
1489 | ||||
1490 | if (tmp->mWebTaskScheduler) { | |||
1491 | tmp->mWebTaskScheduler->Disconnect(); | |||
1492 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mWebTaskScheduler)ImplCycleCollectionUnlink(tmp->mWebTaskScheduler); | |||
1493 | } | |||
1494 | ||||
1495 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mTrustedTypePolicyFactory)ImplCycleCollectionUnlink(tmp->mTrustedTypePolicyFactory); | |||
1496 | ||||
1497 | #ifdef MOZ_WEBSPEECH1 | |||
1498 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mSpeechSynthesis)ImplCycleCollectionUnlink(tmp->mSpeechSynthesis); | |||
1499 | #endif | |||
1500 | ||||
1501 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mGlean)ImplCycleCollectionUnlink(tmp->mGlean); | |||
1502 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mGleanPings)ImplCycleCollectionUnlink(tmp->mGleanPings); | |||
1503 | ||||
1504 | if (tmp->mOuterWindow) { | |||
1505 | nsGlobalWindowOuter::Cast(tmp->mOuterWindow)->MaybeClearInnerWindow(tmp); | |||
1506 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mOuterWindow)ImplCycleCollectionUnlink(tmp->mOuterWindow); | |||
1507 | } | |||
1508 | ||||
1509 | if (tmp->mListenerManager) { | |||
1510 | tmp->mListenerManager->Disconnect(); | |||
1511 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mListenerManager)ImplCycleCollectionUnlink(tmp->mListenerManager); | |||
1512 | } | |||
1513 | ||||
1514 | // Here the Timeouts list would've been unlinked, but we rely on | |||
1515 | // that Timeout objects have been traced and will remove themselves | |||
1516 | // while unlinking. | |||
1517 | ||||
1518 | tmp->UpdateTopInnerWindow(); | |||
1519 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mTopInnerWindow)ImplCycleCollectionUnlink(tmp->mTopInnerWindow); | |||
1520 | ||||
1521 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocation)ImplCycleCollectionUnlink(tmp->mLocation); | |||
1522 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mHistory)ImplCycleCollectionUnlink(tmp->mHistory); | |||
1523 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mNavigation)ImplCycleCollectionUnlink(tmp->mNavigation); | |||
1524 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mCustomElements)ImplCycleCollectionUnlink(tmp->mCustomElements); | |||
1525 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mSharedWorkers)ImplCycleCollectionUnlink(tmp->mSharedWorkers); | |||
1526 | if (tmp->mLocalStorage) { | |||
1527 | tmp->mLocalStorage->Disconnect(); | |||
1528 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocalStorage)ImplCycleCollectionUnlink(tmp->mLocalStorage); | |||
1529 | } | |||
1530 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mSessionStorage)ImplCycleCollectionUnlink(tmp->mSessionStorage); | |||
1531 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mIndexedDB)ImplCycleCollectionUnlink(tmp->mIndexedDB); | |||
1532 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentPrincipal)ImplCycleCollectionUnlink(tmp->mDocumentPrincipal); | |||
1533 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentCookiePrincipal)ImplCycleCollectionUnlink(tmp->mDocumentCookiePrincipal); | |||
1534 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentStoragePrincipal)ImplCycleCollectionUnlink(tmp->mDocumentStoragePrincipal); | |||
1535 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentPartitionedPrincipal)ImplCycleCollectionUnlink(tmp->mDocumentPartitionedPrincipal ); | |||
1536 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentCsp)ImplCycleCollectionUnlink(tmp->mDocumentCsp); | |||
1537 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowserChild)ImplCycleCollectionUnlink(tmp->mBrowserChild); | |||
1538 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mDoc)ImplCycleCollectionUnlink(tmp->mDoc); | |||
1539 | ||||
1540 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mGamepads)ImplCycleCollectionUnlink(tmp->mGamepads); | |||
1541 | ||||
1542 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mCacheStorage)ImplCycleCollectionUnlink(tmp->mCacheStorage); | |||
1543 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mVRDisplays)ImplCycleCollectionUnlink(tmp->mVRDisplays); | |||
1544 | ||||
1545 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mDebuggerNotificationManager)ImplCycleCollectionUnlink(tmp->mDebuggerNotificationManager ); | |||
1546 | ||||
1547 | // Unlink stuff from nsPIDOMWindow | |||
1548 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeEventHandler)ImplCycleCollectionUnlink(tmp->mChromeEventHandler); | |||
1549 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mParentTarget)ImplCycleCollectionUnlink(tmp->mParentTarget); | |||
1550 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mFocusedElement)ImplCycleCollectionUnlink(tmp->mFocusedElement); | |||
1551 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowsingContext)ImplCycleCollectionUnlink(tmp->mBrowsingContext); | |||
1552 | ||||
1553 | MOZ_DIAGNOSTIC_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(!tmp->mWindowGlobalChild || tmp->mWindowGlobalChild ->IsClosed())>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(!tmp->mWindowGlobalChild || tmp->mWindowGlobalChild->IsClosed()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!tmp->mWindowGlobalChild || tmp->mWindowGlobalChild->IsClosed()" " (" "How are we unlinking a window before its actor has been destroyed?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 1555); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!tmp->mWindowGlobalChild || tmp->mWindowGlobalChild->IsClosed()" ") (" "How are we unlinking a window before its actor has been destroyed?" ")"); do { *((volatile int*)__null) = 1555; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
1554 | !tmp->mWindowGlobalChild || tmp->mWindowGlobalChild->IsClosed(),do { static_assert( mozilla::detail::AssertionConditionType< decltype(!tmp->mWindowGlobalChild || tmp->mWindowGlobalChild ->IsClosed())>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(!tmp->mWindowGlobalChild || tmp->mWindowGlobalChild->IsClosed()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!tmp->mWindowGlobalChild || tmp->mWindowGlobalChild->IsClosed()" " (" "How are we unlinking a window before its actor has been destroyed?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 1555); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!tmp->mWindowGlobalChild || tmp->mWindowGlobalChild->IsClosed()" ") (" "How are we unlinking a window before its actor has been destroyed?" ")"); do { *((volatile int*)__null) = 1555; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
1555 | "How are we unlinking a window before its actor has been destroyed?")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!tmp->mWindowGlobalChild || tmp->mWindowGlobalChild ->IsClosed())>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(!tmp->mWindowGlobalChild || tmp->mWindowGlobalChild->IsClosed()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!tmp->mWindowGlobalChild || tmp->mWindowGlobalChild->IsClosed()" " (" "How are we unlinking a window before its actor has been destroyed?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 1555); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!tmp->mWindowGlobalChild || tmp->mWindowGlobalChild->IsClosed()" ") (" "How are we unlinking a window before its actor has been destroyed?" ")"); do { *((volatile int*)__null) = 1555; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
1556 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindowGlobalChild)ImplCycleCollectionUnlink(tmp->mWindowGlobalChild); | |||
1557 | ||||
1558 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mMenubar)ImplCycleCollectionUnlink(tmp->mMenubar); | |||
1559 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mToolbar)ImplCycleCollectionUnlink(tmp->mToolbar); | |||
1560 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocationbar)ImplCycleCollectionUnlink(tmp->mLocationbar); | |||
1561 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mPersonalbar)ImplCycleCollectionUnlink(tmp->mPersonalbar); | |||
1562 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mStatusbar)ImplCycleCollectionUnlink(tmp->mStatusbar); | |||
1563 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mScrollbars)ImplCycleCollectionUnlink(tmp->mScrollbars); | |||
1564 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mCrypto)ImplCycleCollectionUnlink(tmp->mCrypto); | |||
1565 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mConsole)ImplCycleCollectionUnlink(tmp->mConsole); | |||
1566 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mPaintWorklet)ImplCycleCollectionUnlink(tmp->mPaintWorklet); | |||
1567 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mExternal)ImplCycleCollectionUnlink(tmp->mExternal); | |||
1568 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mInstallTrigger)ImplCycleCollectionUnlink(tmp->mInstallTrigger); | |||
1569 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mIntlUtils)ImplCycleCollectionUnlink(tmp->mIntlUtils); | |||
1570 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mVisualViewport)ImplCycleCollectionUnlink(tmp->mVisualViewport); | |||
1571 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mCurrentPasteDataTransfer)ImplCycleCollectionUnlink(tmp->mCurrentPasteDataTransfer); | |||
1572 | ||||
1573 | tmp->UnlinkObjectsInGlobal(); | |||
1574 | ||||
1575 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mIdleRequestExecutor)ImplCycleCollectionUnlink(tmp->mIdleRequestExecutor); | |||
1576 | ||||
1577 | // Here the IdleRequest list would've been unlinked, but we rely on | |||
1578 | // that IdleRequest objects have been traced and will remove | |||
1579 | // themselves while unlinking. | |||
1580 | ||||
1581 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mClientSource)ImplCycleCollectionUnlink(tmp->mClientSource); | |||
1582 | ||||
1583 | if (tmp->IsChromeWindow()) { | |||
1584 | if (tmp->mChromeFields.mMessageManager) { | |||
1585 | static_cast<nsFrameMessageManager*>( | |||
1586 | tmp->mChromeFields.mMessageManager.get()) | |||
1587 | ->Disconnect(); | |||
1588 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeFields.mMessageManager)ImplCycleCollectionUnlink(tmp->mChromeFields.mMessageManager ); | |||
1589 | } | |||
1590 | tmp->DisconnectAndClearGroupMessageManagers(); | |||
1591 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeFields.mGroupMessageManagers)ImplCycleCollectionUnlink(tmp->mChromeFields.mGroupMessageManagers ); | |||
1592 | } | |||
1593 | ||||
1594 | for (size_t i = 0; i < tmp->mDocumentFlushedResolvers.Length(); i++) { | |||
1595 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentFlushedResolvers[i]->mPromise)ImplCycleCollectionUnlink(tmp->mDocumentFlushedResolvers[i ]->mPromise);; | |||
1596 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentFlushedResolvers[i]->mCallback)ImplCycleCollectionUnlink(tmp->mDocumentFlushedResolvers[i ]->mCallback);; | |||
1597 | } | |||
1598 | tmp->mDocumentFlushedResolvers.Clear(); | |||
1599 | ||||
1600 | NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPERtmp->ReleaseWrapper(p); | |||
1601 | NS_IMPL_CYCLE_COLLECTION_UNLINK_END(void)tmp; } | |||
1602 | ||||
1603 | #ifdef DEBUG1 | |||
1604 | void nsGlobalWindowInner::RiskyUnlink() { | |||
1605 | NS_CYCLE_COLLECTION_INNERNAME_cycleCollectorGlobal.Unlink(this); | |||
1606 | } | |||
1607 | #endif | |||
1608 | ||||
1609 | NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsGlobalWindowInner)void nsGlobalWindowInner::cycleCollection::Trace( void* p, const TraceCallbacks& aCallbacks, void* aClosure) { nsGlobalWindowInner * tmp = DowncastCCParticipant<nsGlobalWindowInner>(p); | |||
1610 | NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPERtmp->TraceWrapper(aCallbacks, aClosure); | |||
1611 | NS_IMPL_CYCLE_COLLECTION_TRACE_END(void)tmp; } | |||
1612 | ||||
1613 | bool nsGlobalWindowInner::IsBlackForCC(bool aTracingNeeded) { | |||
1614 | if (!nsCCUncollectableMarker::sGeneration) { | |||
1615 | return false; | |||
1616 | } | |||
1617 | ||||
1618 | return (nsCCUncollectableMarker::InGeneration(GetMarkedCCGeneration()) || | |||
1619 | HasKnownLiveWrapper()) && | |||
1620 | (!aTracingNeeded || HasNothingToTrace(ToSupports(this))); | |||
1621 | } | |||
1622 | ||||
1623 | //***************************************************************************** | |||
1624 | // nsGlobalWindowInner::nsIScriptGlobalObject | |||
1625 | //***************************************************************************** | |||
1626 | ||||
1627 | bool nsGlobalWindowInner::ShouldResistFingerprinting(RFPTarget aTarget) const { | |||
1628 | if (mDoc) { | |||
1629 | return mDoc->ShouldResistFingerprinting(aTarget); | |||
1630 | } | |||
1631 | return nsContentUtils::ShouldResistFingerprinting( | |||
1632 | "If we do not have a document then we do not have any context" | |||
1633 | "to make an informed RFP choice, so we fall back to the global pref", | |||
1634 | aTarget); | |||
1635 | } | |||
1636 | ||||
1637 | OriginTrials nsGlobalWindowInner::Trials() const { | |||
1638 | return OriginTrials::FromWindow(this); | |||
1639 | } | |||
1640 | ||||
1641 | FontFaceSet* nsGlobalWindowInner::GetFonts() { | |||
1642 | if (mDoc) { | |||
1643 | return mDoc->Fonts(); | |||
1644 | } | |||
1645 | return nullptr; | |||
1646 | } | |||
1647 | ||||
1648 | mozilla::Result<mozilla::ipc::PrincipalInfo, nsresult> | |||
1649 | nsGlobalWindowInner::GetStorageKey() { | |||
1650 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 1650); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 1650; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
1651 | ||||
1652 | nsIPrincipal* principal = GetEffectiveStoragePrincipal(); | |||
1653 | if (!principal) { | |||
1654 | return mozilla::Err(NS_ERROR_FAILURE); | |||
1655 | } | |||
1656 | ||||
1657 | mozilla::ipc::PrincipalInfo principalInfo; | |||
1658 | nsresult rv = PrincipalToPrincipalInfo(principal, &principalInfo); | |||
1659 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
1660 | return mozilla::Err(rv); | |||
1661 | } | |||
1662 | ||||
1663 | // Block expanded and null principals, let content and system through. | |||
1664 | if (principalInfo.type() != | |||
1665 | mozilla::ipc::PrincipalInfo::TContentPrincipalInfo && | |||
1666 | principalInfo.type() != | |||
1667 | mozilla::ipc::PrincipalInfo::TSystemPrincipalInfo) { | |||
1668 | return Err(NS_ERROR_DOM_SECURITY_ERR); | |||
1669 | } | |||
1670 | ||||
1671 | return std::move(principalInfo); | |||
1672 | } | |||
1673 | ||||
1674 | mozilla::dom::StorageManager* nsGlobalWindowInner::GetStorageManager() { | |||
1675 | return Navigator()->Storage(); | |||
1676 | } | |||
1677 | ||||
1678 | // https://html.spec.whatwg.org/multipage/web-messaging.html#eligible-for-messaging | |||
1679 | // * a Window object whose associated Document is fully active | |||
1680 | bool nsGlobalWindowInner::IsEligibleForMessaging() { return IsFullyActive(); } | |||
1681 | ||||
1682 | nsresult nsGlobalWindowInner::EnsureScriptEnvironment() { | |||
1683 | // NOTE: We can't use FORWARD_TO_OUTER here because we don't want to fail if | |||
1684 | // we're called on an inactive inner window. | |||
1685 | nsGlobalWindowOuter* outer = GetOuterWindowInternal(); | |||
1686 | if (!outer) { | |||
1687 | NS_WARNING("No outer window available!")NS_DebugBreak(NS_DEBUG_WARNING, "No outer window available!", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 1687); | |||
1688 | return NS_ERROR_FAILURE; | |||
1689 | } | |||
1690 | return outer->EnsureScriptEnvironment(); | |||
1691 | } | |||
1692 | ||||
1693 | nsIScriptContext* nsGlobalWindowInner::GetScriptContext() { | |||
1694 | nsGlobalWindowOuter* outer = GetOuterWindowInternal(); | |||
1695 | if (!outer) { | |||
1696 | return nullptr; | |||
1697 | } | |||
1698 | return outer->GetScriptContext(); | |||
1699 | } | |||
1700 | ||||
1701 | void nsGlobalWindowInner::TraceGlobalJSObject(JSTracer* aTrc) { | |||
1702 | TraceWrapper(aTrc, "active window global"); | |||
1703 | } | |||
1704 | ||||
1705 | void nsGlobalWindowInner::UpdateAutoplayPermission() { | |||
1706 | if (!GetWindowContext()) { | |||
1707 | return; | |||
1708 | } | |||
1709 | uint32_t perm = | |||
1710 | media::AutoplayPolicy::GetSiteAutoplayPermission(GetPrincipal()); | |||
1711 | if (GetWindowContext()->GetAutoplayPermission() == perm) { | |||
1712 | return; | |||
1713 | } | |||
1714 | ||||
1715 | // Setting autoplay permission on a discarded context has no effect. | |||
1716 | Unused << GetWindowContext()->SetAutoplayPermission(perm); | |||
1717 | } | |||
1718 | ||||
1719 | void nsGlobalWindowInner::UpdateShortcutsPermission() { | |||
1720 | if (!GetWindowContext() || | |||
1721 | !GetWindowContext()->GetBrowsingContext()->IsTop()) { | |||
1722 | // We only cache the shortcuts permission on top-level WindowContexts | |||
1723 | // since we always check the top-level principal for the permission. | |||
1724 | return; | |||
1725 | } | |||
1726 | ||||
1727 | uint32_t perm = GetShortcutsPermission(GetPrincipal()); | |||
1728 | ||||
1729 | if (GetWindowContext()->GetShortcutsPermission() == perm) { | |||
1730 | return; | |||
1731 | } | |||
1732 | ||||
1733 | // If the WindowContext is discarded this has no effect. | |||
1734 | Unused << GetWindowContext()->SetShortcutsPermission(perm); | |||
1735 | } | |||
1736 | ||||
1737 | /* static */ | |||
1738 | uint32_t nsGlobalWindowInner::GetShortcutsPermission(nsIPrincipal* aPrincipal) { | |||
1739 | uint32_t perm = nsIPermissionManager::DENY_ACTION; | |||
1740 | nsCOMPtr<nsIPermissionManager> permMgr = | |||
1741 | mozilla::components::PermissionManager::Service(); | |||
1742 | if (aPrincipal && permMgr) { | |||
1743 | permMgr->TestExactPermissionFromPrincipal(aPrincipal, "shortcuts"_ns, | |||
1744 | &perm); | |||
1745 | } | |||
1746 | return perm; | |||
1747 | } | |||
1748 | ||||
1749 | void nsGlobalWindowInner::UpdatePopupPermission() { | |||
1750 | if (!GetWindowContext()) { | |||
1751 | return; | |||
1752 | } | |||
1753 | ||||
1754 | uint32_t perm = PopupBlocker::GetPopupPermission(GetPrincipal()); | |||
1755 | if (GetWindowContext()->GetPopupPermission() == perm) { | |||
1756 | return; | |||
1757 | } | |||
1758 | ||||
1759 | // If the WindowContext is discarded this has no effect. | |||
1760 | Unused << GetWindowContext()->SetPopupPermission(perm); | |||
1761 | } | |||
1762 | ||||
1763 | void nsGlobalWindowInner::UpdatePermissions() { | |||
1764 | if (!GetWindowContext()) { | |||
1765 | return; | |||
1766 | } | |||
1767 | ||||
1768 | nsCOMPtr<nsIPrincipal> principal = GetPrincipal(); | |||
1769 | RefPtr<WindowContext> windowContext = GetWindowContext(); | |||
1770 | ||||
1771 | WindowContext::Transaction txn; | |||
1772 | txn.SetAutoplayPermission( | |||
1773 | media::AutoplayPolicy::GetSiteAutoplayPermission(principal)); | |||
1774 | txn.SetPopupPermission(PopupBlocker::GetPopupPermission(principal)); | |||
1775 | ||||
1776 | if (windowContext->IsTop()) { | |||
1777 | txn.SetShortcutsPermission(GetShortcutsPermission(principal)); | |||
1778 | } | |||
1779 | ||||
1780 | // Setting permissions on a discarded WindowContext has no effect | |||
1781 | Unused << txn.Commit(windowContext); | |||
1782 | } | |||
1783 | ||||
1784 | void nsGlobalWindowInner::InitDocumentDependentState(JSContext* aCx) { | |||
1785 | MOZ_ASSERT(mDoc)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mDoc)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(mDoc))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("mDoc", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 1785); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDoc" ")"); do { *((volatile int*)__null) = 1785; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
1786 | ||||
1787 | if (MOZ_LOG_TEST(gDOMLeakPRLogInner, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gDOMLeakPRLogInner , LogLevel::Debug)), 0))) { | |||
1788 | nsIURI* uri = mDoc->GetDocumentURI(); | |||
1789 | MOZ_LOG(gDOMLeakPRLogInner, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogInner ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "DOMWINDOW %p SetNewDocument %s", this, uri ? uri->GetSpecOrDefault().get() : ""); } } while (0) | |||
1790 | ("DOMWINDOW %p SetNewDocument %s", this,do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogInner ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "DOMWINDOW %p SetNewDocument %s", this, uri ? uri->GetSpecOrDefault().get() : ""); } } while (0) | |||
1791 | uri ? uri->GetSpecOrDefault().get() : ""))do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogInner ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "DOMWINDOW %p SetNewDocument %s", this, uri ? uri->GetSpecOrDefault().get() : ""); } } while (0); | |||
1792 | } | |||
1793 | ||||
1794 | mFocusedElement = nullptr; | |||
1795 | mLocalStorage = nullptr; | |||
1796 | mSessionStorage = nullptr; | |||
1797 | mPerformance = nullptr; | |||
1798 | if (mWebTaskScheduler) { | |||
1799 | mWebTaskScheduler->Disconnect(); | |||
1800 | mWebTaskScheduler = nullptr; | |||
1801 | } | |||
1802 | ||||
1803 | // This must be called after nullifying the internal objects because here we | |||
1804 | // could recreate them, calling the getter methods, and store them into the JS | |||
1805 | // slots. If we nullify them after, the slot values and the objects will be | |||
1806 | // out of sync. | |||
1807 | ClearDocumentDependentSlots(aCx); | |||
1808 | ||||
1809 | if (!mWindowGlobalChild) { | |||
1810 | mWindowGlobalChild = WindowGlobalChild::Create(this); | |||
1811 | } | |||
1812 | MOZ_ASSERT(!GetWindowContext()->HasBeenUserGestureActivated(),do { static_assert( mozilla::detail::AssertionConditionType< decltype(!GetWindowContext()->HasBeenUserGestureActivated( ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!GetWindowContext()->HasBeenUserGestureActivated( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!GetWindowContext()->HasBeenUserGestureActivated()" " (" "WindowContext should always not have user gesture activation at " "this point." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 1814); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!GetWindowContext()->HasBeenUserGestureActivated()" ") (" "WindowContext should always not have user gesture activation at " "this point." ")"); do { *((volatile int*)__null) = 1814; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false) | |||
1813 | "WindowContext should always not have user gesture activation at "do { static_assert( mozilla::detail::AssertionConditionType< decltype(!GetWindowContext()->HasBeenUserGestureActivated( ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!GetWindowContext()->HasBeenUserGestureActivated( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!GetWindowContext()->HasBeenUserGestureActivated()" " (" "WindowContext should always not have user gesture activation at " "this point." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 1814); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!GetWindowContext()->HasBeenUserGestureActivated()" ") (" "WindowContext should always not have user gesture activation at " "this point." ")"); do { *((volatile int*)__null) = 1814; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false) | |||
1814 | "this point.")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!GetWindowContext()->HasBeenUserGestureActivated( ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!GetWindowContext()->HasBeenUserGestureActivated( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!GetWindowContext()->HasBeenUserGestureActivated()" " (" "WindowContext should always not have user gesture activation at " "this point." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 1814); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!GetWindowContext()->HasBeenUserGestureActivated()" ") (" "WindowContext should always not have user gesture activation at " "this point." ")"); do { *((volatile int*)__null) = 1814; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false); | |||
1815 | ||||
1816 | UpdatePermissions(); | |||
1817 | ||||
1818 | RefPtr<PermissionDelegateHandler> permDelegateHandler = | |||
1819 | mDoc->GetPermissionDelegateHandler(); | |||
1820 | ||||
1821 | if (permDelegateHandler) { | |||
1822 | permDelegateHandler->PopulateAllDelegatedPermissions(); | |||
1823 | } | |||
1824 | ||||
1825 | #if defined(MOZ_WIDGET_ANDROID) | |||
1826 | // When we insert the new document to the window in the top-level browsing | |||
1827 | // context, we should reset the status of the request which is used for the | |||
1828 | // previous document. | |||
1829 | if (mWindowGlobalChild && GetBrowsingContext() && | |||
1830 | !GetBrowsingContext()->GetParent()) { | |||
1831 | // Return value of setting synced field should be checked. See bug 1656492. | |||
1832 | Unused << GetBrowsingContext()->ResetGVAutoplayRequestStatus(); | |||
1833 | } | |||
1834 | #endif | |||
1835 | ||||
1836 | #ifdef DEBUG1 | |||
1837 | mLastOpenedURI = mDoc->GetDocumentURI(); | |||
1838 | #endif | |||
1839 | ||||
1840 | Telemetry::Accumulate(Telemetry::INNERWINDOWS_WITH_MUTATION_LISTENERS, | |||
1841 | mMutationBits ? 1 : 0); | |||
1842 | ||||
1843 | // Clear our mutation bitfield. | |||
1844 | mMutationBits = 0; | |||
1845 | } | |||
1846 | ||||
1847 | nsresult nsGlobalWindowInner::EnsureClientSource() { | |||
1848 | MOZ_DIAGNOSTIC_ASSERT(mDoc)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mDoc)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(mDoc))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("mDoc", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 1848); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mDoc" ")"); do { *((volatile int*)__null) = 1848; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
1849 | ||||
1850 | bool newClientSource = false; | |||
1851 | ||||
1852 | // Get the load info for the document if we performed a load. Be careful not | |||
1853 | // to look at local URLs, though. Local URLs are those that have a scheme of: | |||
1854 | // * about: | |||
1855 | // * data: | |||
1856 | // * blob: | |||
1857 | // We also do an additional check here so that we only treat about:blank | |||
1858 | // and about:srcdoc as local URLs. Other internal firefox about: URLs should | |||
1859 | // not be treated this way. | |||
1860 | nsCOMPtr<nsILoadInfo> loadInfo; | |||
1861 | nsCOMPtr<nsIChannel> channel = mDoc->GetChannel(); | |||
1862 | if (channel) { | |||
1863 | nsCOMPtr<nsIURI> uri; | |||
1864 | Unused << channel->GetURI(getter_AddRefs(uri)); | |||
1865 | ||||
1866 | bool ignoreLoadInfo = false; | |||
1867 | ||||
1868 | if (uri->SchemeIs("about")) { | |||
1869 | ignoreLoadInfo = | |||
1870 | NS_IsAboutBlankAllowQueryAndFragment(uri) || NS_IsAboutSrcdoc(uri); | |||
1871 | } else { | |||
1872 | // Its not an about: URL, so now check for our other URL types. | |||
1873 | ignoreLoadInfo = uri->SchemeIs("data") || uri->SchemeIs("blob"); | |||
1874 | } | |||
1875 | ||||
1876 | if (!ignoreLoadInfo) { | |||
1877 | loadInfo = channel->LoadInfo(); | |||
1878 | } | |||
1879 | } | |||
1880 | ||||
1881 | // Take the initial client source from the docshell immediately. Even if we | |||
1882 | // don't end up using it here we should consume it. | |||
1883 | UniquePtr<ClientSource> initialClientSource; | |||
1884 | nsIDocShell* docshell = GetDocShell(); | |||
1885 | if (docshell) { | |||
1886 | initialClientSource = docshell->TakeInitialClientSource(); | |||
1887 | } | |||
1888 | ||||
1889 | // Try to get the reserved client from the LoadInfo. A Client is | |||
1890 | // reserved at the start of the channel load if there is not an | |||
1891 | // initial about:blank document that will be reused. It is also | |||
1892 | // created if the channel load encounters a cross-origin redirect. | |||
1893 | if (loadInfo) { | |||
1894 | UniquePtr<ClientSource> reservedClient = | |||
1895 | loadInfo->TakeReservedClientSource(); | |||
1896 | if (reservedClient) { | |||
1897 | mClientSource.reset(); | |||
1898 | mClientSource = std::move(reservedClient); | |||
1899 | newClientSource = true; | |||
1900 | } | |||
1901 | } | |||
1902 | ||||
1903 | // We don't have a LoadInfo reserved client, but maybe we should | |||
1904 | // be inheriting an initial one from the docshell. This means | |||
1905 | // that the docshell started the channel load before creating the | |||
1906 | // initial about:blank document. This is an optimization, though, | |||
1907 | // and it created an initial Client as a placeholder for the document. | |||
1908 | // In this case we want to inherit this placeholder Client here. | |||
1909 | if (!mClientSource) { | |||
1910 | mClientSource = std::move(initialClientSource); | |||
1911 | if (mClientSource) { | |||
1912 | newClientSource = true; | |||
1913 | } | |||
1914 | } | |||
1915 | ||||
1916 | nsCOMPtr<nsIPrincipal> foreignPartitionedPrincipal; | |||
1917 | ||||
1918 | nsresult rv = StoragePrincipalHelper::GetPrincipal( | |||
1919 | this, | |||
1920 | StaticPrefs::privacy_partition_serviceWorkers() | |||
1921 | ? StoragePrincipalHelper::eForeignPartitionedPrincipal | |||
1922 | : StoragePrincipalHelper::eRegularPrincipal, | |||
1923 | getter_AddRefs(foreignPartitionedPrincipal)); | |||
1924 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 1924); return rv; } } while (false); | |||
1925 | ||||
1926 | // Verify the final ClientSource principal matches the final document | |||
1927 | // principal. The ClientChannelHelper handles things like network | |||
1928 | // redirects, but there are other ways the document principal can change. | |||
1929 | // For example, if something sets the nsIChannel.owner property, then | |||
1930 | // the final channel principal can be anything. Unfortunately there is | |||
1931 | // no good way to detect this until after the channel completes loading. | |||
1932 | // | |||
1933 | // For now we handle this just by reseting the ClientSource. This will | |||
1934 | // result in a new ClientSource with the correct principal being created. | |||
1935 | // To APIs like ServiceWorker and Clients API it will look like there was | |||
1936 | // an initial content page created that was then immediately replaced. | |||
1937 | // This is pretty close to what we are actually doing. | |||
1938 | if (mClientSource) { | |||
1939 | auto principalOrErr = mClientSource->Info().GetPrincipal(); | |||
1940 | nsCOMPtr<nsIPrincipal> clientPrincipal = | |||
1941 | principalOrErr.isOk() ? principalOrErr.unwrap() : nullptr; | |||
1942 | if (!clientPrincipal || | |||
1943 | !clientPrincipal->Equals(foreignPartitionedPrincipal)) { | |||
1944 | mClientSource.reset(); | |||
1945 | } | |||
1946 | } | |||
1947 | ||||
1948 | // If we don't have a reserved client or an initial client, then create | |||
1949 | // one now. This can happen in certain cases where we avoid preallocating | |||
1950 | // the client in the docshell. This mainly occurs in situations where | |||
1951 | // the principal is not clearly inherited from the parent; e.g. sandboxed | |||
1952 | // iframes, window.open(), etc. | |||
1953 | // | |||
1954 | // We also do this late ClientSource creation if the final document ended | |||
1955 | // up with a different principal. | |||
1956 | // | |||
1957 | // TODO: We may not be marking initial about:blank documents created | |||
1958 | // this way as controlled by a service worker properly. The | |||
1959 | // controller should be coming from the same place as the inheritted | |||
1960 | // principal. We do this in docshell, but as mentioned we aren't | |||
1961 | // smart enough to handle all cases yet. For example, a | |||
1962 | // window.open() with new URL should inherit the controller from | |||
1963 | // the opener, but we probably don't handle that yet. | |||
1964 | if (!mClientSource) { | |||
1965 | mClientSource = ClientManager::CreateSource( | |||
1966 | ClientType::Window, SerialEventTarget(), foreignPartitionedPrincipal); | |||
1967 | MOZ_DIAGNOSTIC_ASSERT(mClientSource)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mClientSource)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mClientSource))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mClientSource", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 1967); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mClientSource" ")"); do { *((volatile int*)__null) = 1967; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
1968 | newClientSource = true; | |||
1969 | ||||
1970 | // Note, we don't apply the loadinfo controller below if we create | |||
1971 | // the ClientSource here. | |||
1972 | } | |||
1973 | ||||
1974 | // The load may have started controlling the Client as well. If | |||
1975 | // so, mark it as controlled immediately here. The actor may | |||
1976 | // or may not have been notified by the parent side about being | |||
1977 | // controlled yet. | |||
1978 | // | |||
1979 | // Note: We should be careful not to control a client that was created late. | |||
1980 | // These clients were not seen by the ServiceWorkerManager when it | |||
1981 | // marked the LoadInfo controlled and it won't know about them. Its | |||
1982 | // also possible we are creating the client late due to the final | |||
1983 | // principal changing and these clients should definitely not be | |||
1984 | // controlled by a service worker with a different principal. | |||
1985 | else if (loadInfo) { | |||
1986 | const Maybe<ServiceWorkerDescriptor> controller = loadInfo->GetController(); | |||
1987 | if (controller.isSome()) { | |||
1988 | mClientSource->SetController(controller.ref()); | |||
1989 | } | |||
1990 | ||||
1991 | // We also have to handle the case where te initial about:blank is | |||
1992 | // controlled due to inheritting the service worker from its parent, | |||
1993 | // but the actual nsIChannel load is not covered by any service worker. | |||
1994 | // In this case we want the final page to be uncontrolled. There is | |||
1995 | // an open spec issue about how exactly this should be handled, but for | |||
1996 | // now we just force creation of a new ClientSource to clear the | |||
1997 | // controller. | |||
1998 | // | |||
1999 | // https://github.com/w3c/ServiceWorker/issues/1232 | |||
2000 | // | |||
2001 | else if (mClientSource->GetController().isSome()) { | |||
2002 | mClientSource.reset(); | |||
2003 | mClientSource = ClientManager::CreateSource( | |||
2004 | ClientType::Window, SerialEventTarget(), foreignPartitionedPrincipal); | |||
2005 | MOZ_DIAGNOSTIC_ASSERT(mClientSource)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mClientSource)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mClientSource))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mClientSource", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 2005); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mClientSource" ")"); do { *((volatile int*)__null) = 2005; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
2006 | newClientSource = true; | |||
2007 | } | |||
2008 | } | |||
2009 | ||||
2010 | if (mClientSource) { | |||
2011 | // Generally the CSP is stored within the Client and cached on the document. | |||
2012 | // At the time of CSP parsing however, the Client has not been created yet, | |||
2013 | // hence we store the CSP on the document and propagate/sync the CSP with | |||
2014 | // Client here when we create the Client. | |||
2015 | mClientSource->SetCsp(mDoc->GetCsp()); | |||
2016 | ||||
2017 | DocGroup* docGroup = GetDocGroup(); | |||
2018 | MOZ_DIAGNOSTIC_ASSERT(docGroup)do { static_assert( mozilla::detail::AssertionConditionType< decltype(docGroup)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(docGroup))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("docGroup", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 2018); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "docGroup" ")"); do { *((volatile int*)__null) = 2018; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
2019 | mClientSource->SetAgentClusterId(docGroup->AgentClusterId()); | |||
2020 | ||||
2021 | if (mWindowGlobalChild) { | |||
2022 | mWindowGlobalChild->SendSetClientInfo(mClientSource->Info().ToIPC()); | |||
2023 | } | |||
2024 | } | |||
2025 | ||||
2026 | // Its possible that we got a client just after being frozen in | |||
2027 | // the bfcache. In that case freeze the client immediately. | |||
2028 | if (newClientSource && IsFrozen()) { | |||
2029 | mClientSource->Freeze(); | |||
2030 | } | |||
2031 | ||||
2032 | return NS_OK; | |||
2033 | } | |||
2034 | ||||
2035 | nsresult nsGlobalWindowInner::ExecutionReady() { | |||
2036 | nsresult rv = EnsureClientSource(); | |||
2037 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 2037); return rv; } } while (false); | |||
2038 | ||||
2039 | rv = mClientSource->WindowExecutionReady(this); | |||
2040 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 2040); return rv; } } while (false); | |||
2041 | ||||
2042 | return NS_OK; | |||
2043 | } | |||
2044 | ||||
2045 | void nsGlobalWindowInner::UpdateParentTarget() { | |||
2046 | // NOTE: This method is identical to | |||
2047 | // nsGlobalWindowOuter::UpdateParentTarget(). IF YOU UPDATE THIS METHOD, | |||
2048 | // UPDATE THE OTHER ONE TOO! | |||
2049 | ||||
2050 | // Try to get our frame element's tab child global (its in-process message | |||
2051 | // manager). If that fails, fall back to the chrome event handler's tab | |||
2052 | // child global, and if it doesn't have one, just use the chrome event | |||
2053 | // handler itself. | |||
2054 | ||||
2055 | nsPIDOMWindowOuter* outer = GetOuterWindow(); | |||
2056 | if (!outer) { | |||
2057 | return; | |||
2058 | } | |||
2059 | nsCOMPtr<Element> frameElement = outer->GetFrameElementInternal(); | |||
2060 | nsCOMPtr<EventTarget> eventTarget = | |||
2061 | nsContentUtils::TryGetBrowserChildGlobal(frameElement); | |||
2062 | ||||
2063 | if (!eventTarget) { | |||
2064 | nsGlobalWindowOuter* topWin = GetInProcessScriptableTopInternal(); | |||
2065 | if (topWin) { | |||
2066 | frameElement = topWin->GetFrameElementInternal(); | |||
2067 | eventTarget = nsContentUtils::TryGetBrowserChildGlobal(frameElement); | |||
2068 | } | |||
2069 | } | |||
2070 | ||||
2071 | if (!eventTarget) { | |||
2072 | eventTarget = nsContentUtils::TryGetBrowserChildGlobal(mChromeEventHandler); | |||
2073 | } | |||
2074 | ||||
2075 | if (!eventTarget) { | |||
2076 | eventTarget = mChromeEventHandler; | |||
2077 | } | |||
2078 | ||||
2079 | mParentTarget = eventTarget; | |||
2080 | } | |||
2081 | ||||
2082 | EventTarget* nsGlobalWindowInner::GetTargetForDOMEvent() { | |||
2083 | return GetOuterWindowInternal(); | |||
2084 | } | |||
2085 | ||||
2086 | void nsGlobalWindowInner::GetEventTargetParent(EventChainPreVisitor& aVisitor) { | |||
2087 | EventMessage msg = aVisitor.mEvent->mMessage; | |||
2088 | ||||
2089 | aVisitor.mCanHandle = true; | |||
2090 | aVisitor.mForceContentDispatch = true; // FIXME! Bug 329119 | |||
2091 | if (msg == eResize && aVisitor.mEvent->IsTrusted()) { | |||
2092 | // Checking whether the event target is an inner window or not, so we can | |||
2093 | // keep the old behavior also in case a child window is handling resize. | |||
2094 | if (aVisitor.mEvent->mOriginalTarget && | |||
2095 | aVisitor.mEvent->mOriginalTarget->IsInnerWindow()) { | |||
2096 | mIsHandlingResizeEvent = true; | |||
2097 | } | |||
2098 | } else if (msg == eMouseDown && aVisitor.mEvent->IsTrusted()) { | |||
2099 | sMouseDown = true; | |||
2100 | } else if ((msg == eMouseUp || msg == eDragEnd) && | |||
2101 | aVisitor.mEvent->IsTrusted()) { | |||
2102 | sMouseDown = false; | |||
2103 | if (sDragServiceDisabled) { | |||
2104 | nsCOMPtr<nsIDragService> ds = | |||
2105 | do_GetService("@mozilla.org/widget/dragservice;1"); | |||
2106 | if (ds) { | |||
2107 | sDragServiceDisabled = false; | |||
2108 | ds->Unsuppress(); | |||
2109 | } | |||
2110 | } | |||
2111 | } | |||
2112 | ||||
2113 | aVisitor.SetParentTarget(GetParentTarget(), true); | |||
2114 | } | |||
2115 | ||||
2116 | void nsGlobalWindowInner::FireFrameLoadEvent() { | |||
2117 | // If we're not in a content frame, or are at a BrowsingContext tree boundary, | |||
2118 | // such as the content-chrome boundary, don't fire the "load" event. | |||
2119 | if (GetBrowsingContext()->IsTopContent() || | |||
2120 | GetBrowsingContext()->IsChrome()) { | |||
2121 | return; | |||
2122 | } | |||
2123 | ||||
2124 | // If embedder is same-process, fire the event on our embedder element. | |||
2125 | // | |||
2126 | // XXX: Bug 1440212 is looking into potentially changing this behaviour to act | |||
2127 | // more like the remote case when in-process. | |||
2128 | RefPtr<Element> element = GetBrowsingContext()->GetEmbedderElement(); | |||
2129 | if (element) { | |||
2130 | nsEventStatus status = nsEventStatus_eIgnore; | |||
2131 | WidgetEvent event(/* aIsTrusted = */ true, eLoad); | |||
2132 | event.mFlags.mBubbles = false; | |||
2133 | event.mFlags.mCancelable = false; | |||
2134 | ||||
2135 | // Most of the time we could get a pres context to pass in here, but not | |||
2136 | // always (i.e. if this window is not shown there won't be a pres context | |||
2137 | // available). Since we're not firing a GUI event we don't need a pres | |||
2138 | // context anyway so we just pass null as the pres context all the time. | |||
2139 | EventDispatcher::Dispatch(element, nullptr, &event, nullptr, &status); | |||
2140 | return; | |||
2141 | } | |||
2142 | ||||
2143 | // We don't have an in-process embedder. Try to get our `BrowserChild` actor | |||
2144 | // to send a message to that embedder. We want to double-check that our outer | |||
2145 | // window is actually the one at the root of this browserChild though, just in | |||
2146 | // case. | |||
2147 | RefPtr<BrowserChild> browserChild = | |||
2148 | BrowserChild::GetFrom(static_cast<nsPIDOMWindowInner*>(this)); | |||
2149 | if (browserChild && | |||
2150 | !GetBrowsingContext()->GetParentWindowContext()->IsInProcess()) { | |||
2151 | // Double-check that our outer window is actually at the root of this | |||
2152 | // `BrowserChild`, in case we're in an odd maybe-unhosted situation like a | |||
2153 | // print preview dialog. | |||
2154 | nsCOMPtr<nsPIDOMWindowOuter> rootOuter = | |||
2155 | do_GetInterface(browserChild->WebNavigation()); | |||
2156 | if (!rootOuter || rootOuter != GetOuterWindow()) { | |||
2157 | return; | |||
2158 | } | |||
2159 | ||||
2160 | mozilla::Unused << browserChild->SendMaybeFireEmbedderLoadEvents( | |||
2161 | EmbedderElementEventType::LoadEvent); | |||
2162 | } | |||
2163 | } | |||
2164 | ||||
2165 | nsresult nsGlobalWindowInner::PostHandleEvent(EventChainPostVisitor& aVisitor) { | |||
2166 | // Return early if there is nothing to do. | |||
2167 | switch (aVisitor.mEvent->mMessage) { | |||
2168 | case eResize: | |||
2169 | case eUnload: | |||
2170 | case eLoad: | |||
2171 | break; | |||
2172 | default: | |||
2173 | return NS_OK; | |||
2174 | } | |||
2175 | ||||
2176 | /* mChromeEventHandler and mContext go dangling in the middle of this | |||
2177 | function under some circumstances (events that destroy the window) | |||
2178 | without this addref. */ | |||
2179 | RefPtr<EventTarget> kungFuDeathGrip1(mChromeEventHandler); | |||
2180 | mozilla::Unused | |||
2181 | << kungFuDeathGrip1; // These aren't referred to through the function | |||
2182 | nsCOMPtr<nsIScriptContext> kungFuDeathGrip2(GetContextInternal()); | |||
2183 | mozilla::Unused | |||
2184 | << kungFuDeathGrip2; // These aren't referred to through the function | |||
2185 | ||||
2186 | if (aVisitor.mEvent->mMessage == eResize) { | |||
2187 | mIsHandlingResizeEvent = false; | |||
2188 | } else if (aVisitor.mEvent->mMessage == eUnload && | |||
2189 | aVisitor.mEvent->IsTrusted()) { | |||
2190 | // If any VR display presentation is active at unload, the next page | |||
2191 | // will receive a vrdisplayactive event to indicate that it should | |||
2192 | // immediately begin vr presentation. This should occur when navigating | |||
2193 | // forwards, navigating backwards, and on page reload. | |||
2194 | for (const auto& display : mVRDisplays) { | |||
2195 | if (display->IsPresenting()) { | |||
2196 | display->StartVRNavigation(); | |||
2197 | // Save this VR display ID to trigger vrdisplayactivate event | |||
2198 | // after the next load event. | |||
2199 | nsGlobalWindowOuter* outer = GetOuterWindowInternal(); | |||
2200 | if (outer) { | |||
2201 | outer->SetAutoActivateVRDisplayID(display->DisplayId()); | |||
2202 | } | |||
2203 | ||||
2204 | // XXX The WebVR 1.1 spec does not define which of multiple VR | |||
2205 | // presenting VR displays will be chosen during navigation. | |||
2206 | // As the underlying platform VR API's currently only allow a single | |||
2207 | // VR display, it is safe to choose the first VR display for now. | |||
2208 | break; | |||
2209 | } | |||
2210 | } | |||
2211 | mIsDocumentLoaded = false; | |||
2212 | // Tell the parent process that the document is not loaded. | |||
2213 | if (mWindowGlobalChild) { | |||
2214 | mWindowGlobalChild->SendUpdateDocumentHasLoaded(mIsDocumentLoaded); | |||
2215 | } | |||
2216 | } else if (aVisitor.mEvent->mMessage == eLoad && | |||
2217 | aVisitor.mEvent->IsTrusted()) { | |||
2218 | // This is page load event since load events don't propagate to |window|. | |||
2219 | // @see Document::GetEventTargetParent. | |||
2220 | mIsDocumentLoaded = true; | |||
2221 | // Tell the parent process that the document is loaded. | |||
2222 | if (mWindowGlobalChild) { | |||
2223 | mWindowGlobalChild->SendUpdateDocumentHasLoaded(mIsDocumentLoaded); | |||
2224 | } | |||
2225 | ||||
2226 | mTimeoutManager->OnDocumentLoaded(); | |||
2227 | ||||
2228 | MOZ_ASSERT(aVisitor.mEvent->IsTrusted())do { static_assert( mozilla::detail::AssertionConditionType< decltype(aVisitor.mEvent->IsTrusted())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aVisitor.mEvent->IsTrusted ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aVisitor.mEvent->IsTrusted()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 2228); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aVisitor.mEvent->IsTrusted()" ")"); do { *((volatile int*)__null) = 2228; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
2229 | FireFrameLoadEvent(); | |||
2230 | ||||
2231 | if (mVREventObserver) { | |||
2232 | mVREventObserver->NotifyAfterLoad(); | |||
2233 | } | |||
2234 | ||||
2235 | uint32_t autoActivateVRDisplayID = 0; | |||
2236 | nsGlobalWindowOuter* outer = GetOuterWindowInternal(); | |||
2237 | if (outer) { | |||
2238 | autoActivateVRDisplayID = outer->GetAutoActivateVRDisplayID(); | |||
2239 | } | |||
2240 | if (autoActivateVRDisplayID) { | |||
2241 | DispatchVRDisplayActivate(autoActivateVRDisplayID, | |||
2242 | VRDisplayEventReason::Navigation); | |||
2243 | } | |||
2244 | } | |||
2245 | ||||
2246 | return NS_OK; | |||
2247 | } | |||
2248 | ||||
2249 | nsresult nsGlobalWindowInner::DefineArgumentsProperty(nsIArray* aArguments) { | |||
2250 | nsIScriptContext* ctx = GetOuterWindowInternal()->mContext; | |||
2251 | NS_ENSURE_TRUE(aArguments && ctx, NS_ERROR_NOT_INITIALIZED)do { if ((__builtin_expect(!!(!(aArguments && ctx)), 0 ))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aArguments && ctx" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 2251); return NS_ERROR_NOT_INITIALIZED; } } while (false); | |||
2252 | ||||
2253 | JS::Rooted<JSObject*> obj(RootingCx(), GetWrapperPreserveColor()); | |||
2254 | return ctx->SetProperty(obj, "arguments", aArguments); | |||
2255 | } | |||
2256 | ||||
2257 | //***************************************************************************** | |||
2258 | // nsGlobalWindowInner::nsIScriptObjectPrincipal | |||
2259 | //***************************************************************************** | |||
2260 | ||||
2261 | nsIPrincipal* nsGlobalWindowInner::GetPrincipal() { | |||
2262 | if (mDoc) { | |||
2263 | // If we have a document, get the principal from the document | |||
2264 | return mDoc->NodePrincipal(); | |||
2265 | } | |||
2266 | ||||
2267 | if (mDocumentPrincipal) { | |||
2268 | return mDocumentPrincipal; | |||
2269 | } | |||
2270 | ||||
2271 | // If we don't have a principal and we don't have a document we | |||
2272 | // ask the parent window for the principal. This can happen when | |||
2273 | // loading a frameset that has a <frame src="javascript:xxx">, in | |||
2274 | // that case the global window is used in JS before we've loaded | |||
2275 | // a document into the window. | |||
2276 | ||||
2277 | nsCOMPtr<nsIScriptObjectPrincipal> objPrincipal = | |||
2278 | do_QueryInterface(GetInProcessParentInternal()); | |||
2279 | ||||
2280 | if (objPrincipal) { | |||
2281 | return objPrincipal->GetPrincipal(); | |||
2282 | } | |||
2283 | ||||
2284 | return nullptr; | |||
2285 | } | |||
2286 | ||||
2287 | nsIPrincipal* nsGlobalWindowInner::GetEffectiveCookiePrincipal() { | |||
2288 | if (mDoc) { | |||
2289 | // If we have a document, get the principal from the document | |||
2290 | return mDoc->EffectiveCookiePrincipal(); | |||
2291 | } | |||
2292 | ||||
2293 | if (mDocumentCookiePrincipal) { | |||
2294 | return mDocumentCookiePrincipal; | |||
2295 | } | |||
2296 | ||||
2297 | // If we don't have a cookie principal and we don't have a document we ask | |||
2298 | // the parent window for the cookie principal. | |||
2299 | ||||
2300 | nsCOMPtr<nsIScriptObjectPrincipal> objPrincipal = | |||
2301 | do_QueryInterface(GetInProcessParentInternal()); | |||
2302 | ||||
2303 | if (objPrincipal) { | |||
2304 | return objPrincipal->GetEffectiveCookiePrincipal(); | |||
2305 | } | |||
2306 | ||||
2307 | return nullptr; | |||
2308 | } | |||
2309 | ||||
2310 | nsIPrincipal* nsGlobalWindowInner::GetEffectiveStoragePrincipal() { | |||
2311 | if (mDoc) { | |||
2312 | // If we have a document, get the principal from the document | |||
2313 | return mDoc->EffectiveStoragePrincipal(); | |||
2314 | } | |||
2315 | ||||
2316 | if (mDocumentStoragePrincipal) { | |||
2317 | return mDocumentStoragePrincipal; | |||
2318 | } | |||
2319 | ||||
2320 | // If we don't have a cookie principal and we don't have a document we ask | |||
2321 | // the parent window for the cookie principal. | |||
2322 | ||||
2323 | nsCOMPtr<nsIScriptObjectPrincipal> objPrincipal = | |||
2324 | do_QueryInterface(GetInProcessParentInternal()); | |||
2325 | ||||
2326 | if (objPrincipal) { | |||
2327 | return objPrincipal->GetEffectiveStoragePrincipal(); | |||
2328 | } | |||
2329 | ||||
2330 | return nullptr; | |||
2331 | } | |||
2332 | ||||
2333 | nsIPrincipal* nsGlobalWindowInner::PartitionedPrincipal() { | |||
2334 | if (mDoc) { | |||
2335 | // If we have a document, get the principal from the document | |||
2336 | return mDoc->PartitionedPrincipal(); | |||
2337 | } | |||
2338 | ||||
2339 | if (mDocumentPartitionedPrincipal) { | |||
2340 | return mDocumentPartitionedPrincipal; | |||
2341 | } | |||
2342 | ||||
2343 | // If we don't have a partitioned principal and we don't have a document we | |||
2344 | // ask the parent window for the partitioned principal. | |||
2345 | ||||
2346 | nsCOMPtr<nsIScriptObjectPrincipal> objPrincipal = | |||
2347 | do_QueryInterface(GetInProcessParentInternal()); | |||
2348 | ||||
2349 | if (objPrincipal) { | |||
2350 | return objPrincipal->PartitionedPrincipal(); | |||
2351 | } | |||
2352 | ||||
2353 | return nullptr; | |||
2354 | } | |||
2355 | ||||
2356 | //***************************************************************************** | |||
2357 | // nsGlobalWindowInner::nsIDOMWindow | |||
2358 | //***************************************************************************** | |||
2359 | ||||
2360 | bool nsPIDOMWindowInner::AddAudioContext(AudioContext* aAudioContext) { | |||
2361 | mAudioContexts.AppendElement(aAudioContext); | |||
2362 | ||||
2363 | // Return true if the context should be muted and false if not. | |||
2364 | nsIDocShell* docShell = GetDocShell(); | |||
2365 | return docShell && !docShell->GetAllowMedia() && !aAudioContext->IsOffline(); | |||
2366 | } | |||
2367 | ||||
2368 | void nsPIDOMWindowInner::RemoveAudioContext(AudioContext* aAudioContext) { | |||
2369 | mAudioContexts.RemoveElement(aAudioContext); | |||
2370 | } | |||
2371 | ||||
2372 | void nsPIDOMWindowInner::MuteAudioContexts() { | |||
2373 | for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) { | |||
2374 | if (!mAudioContexts[i]->IsOffline()) { | |||
2375 | mAudioContexts[i]->Mute(); | |||
2376 | } | |||
2377 | } | |||
2378 | } | |||
2379 | ||||
2380 | void nsPIDOMWindowInner::UnmuteAudioContexts() { | |||
2381 | for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) { | |||
2382 | if (!mAudioContexts[i]->IsOffline()) { | |||
2383 | mAudioContexts[i]->Unmute(); | |||
2384 | } | |||
2385 | } | |||
2386 | } | |||
2387 | ||||
2388 | WindowProxyHolder nsGlobalWindowInner::Window() { | |||
2389 | return WindowProxyHolder(GetBrowsingContext()); | |||
2390 | } | |||
2391 | ||||
2392 | Navigator* nsPIDOMWindowInner::Navigator() { | |||
2393 | if (!mNavigator) { | |||
2394 | mNavigator = new mozilla::dom::Navigator(this); | |||
2395 | } | |||
2396 | ||||
2397 | return mNavigator; | |||
2398 | } | |||
2399 | ||||
2400 | MediaDevices* nsPIDOMWindowInner::GetExtantMediaDevices() const { | |||
2401 | return mNavigator ? mNavigator->GetExtantMediaDevices() : nullptr; | |||
2402 | } | |||
2403 | ||||
2404 | VisualViewport* nsGlobalWindowInner::VisualViewport() { | |||
2405 | if (!mVisualViewport) { | |||
2406 | mVisualViewport = new mozilla::dom::VisualViewport(this); | |||
2407 | } | |||
2408 | return mVisualViewport; | |||
2409 | } | |||
2410 | ||||
2411 | nsScreen* nsGlobalWindowInner::Screen() { | |||
2412 | if (!mScreen) { | |||
2413 | mScreen = new nsScreen(this); | |||
2414 | } | |||
2415 | return mScreen; | |||
2416 | } | |||
2417 | ||||
2418 | nsHistory* nsGlobalWindowInner::GetHistory(ErrorResult& aError) { | |||
2419 | if (!mHistory) { | |||
2420 | mHistory = new nsHistory(this); | |||
2421 | } | |||
2422 | return mHistory; | |||
2423 | } | |||
2424 | ||||
2425 | Navigation* nsGlobalWindowInner::Navigation() { | |||
2426 | if (!mNavigation && Navigation::IsAPIEnabled(nullptr, nullptr)) { | |||
2427 | mNavigation = new mozilla::dom::Navigation(); | |||
2428 | } | |||
2429 | ||||
2430 | return mNavigation; | |||
2431 | } | |||
2432 | ||||
2433 | CustomElementRegistry* nsGlobalWindowInner::CustomElements() { | |||
2434 | if (!mCustomElements) { | |||
2435 | mCustomElements = new CustomElementRegistry(this); | |||
2436 | } | |||
2437 | ||||
2438 | return mCustomElements; | |||
2439 | } | |||
2440 | ||||
2441 | CustomElementRegistry* nsGlobalWindowInner::GetExistingCustomElements() { | |||
2442 | return mCustomElements; | |||
2443 | } | |||
2444 | ||||
2445 | Performance* nsPIDOMWindowInner::GetPerformance() { | |||
2446 | CreatePerformanceObjectIfNeeded(); | |||
2447 | return mPerformance; | |||
2448 | } | |||
2449 | ||||
2450 | void nsPIDOMWindowInner::QueuePerformanceNavigationTiming() { | |||
2451 | CreatePerformanceObjectIfNeeded(); | |||
2452 | if (mPerformance) { | |||
2453 | mPerformance->QueueNavigationTimingEntry(); | |||
2454 | } | |||
2455 | } | |||
2456 | ||||
2457 | void nsPIDOMWindowInner::CreatePerformanceObjectIfNeeded() { | |||
2458 | if (mPerformance || !mDoc) { | |||
2459 | return; | |||
2460 | } | |||
2461 | RefPtr<nsDOMNavigationTiming> timing = mDoc->GetNavigationTiming(); | |||
2462 | nsCOMPtr<nsITimedChannel> timedChannel(do_QueryInterface(mDoc->GetChannel())); | |||
2463 | bool timingEnabled = false; | |||
2464 | if (!timedChannel || | |||
2465 | !NS_SUCCEEDED(timedChannel->GetTimingEnabled(&timingEnabled))((bool)(__builtin_expect(!!(!NS_FAILED_impl(timedChannel-> GetTimingEnabled(&timingEnabled))), 1))) || | |||
2466 | !timingEnabled) { | |||
2467 | timedChannel = nullptr; | |||
2468 | } | |||
2469 | if (timing) { | |||
2470 | mPerformance = Performance::CreateForMainThread(this, mDoc->NodePrincipal(), | |||
2471 | timing, timedChannel); | |||
2472 | } | |||
2473 | } | |||
2474 | ||||
2475 | bool nsPIDOMWindowInner::IsSecureContext() const { | |||
2476 | return nsGlobalWindowInner::Cast(this)->IsSecureContext(); | |||
2477 | } | |||
2478 | ||||
2479 | void nsPIDOMWindowInner::Suspend(bool aIncludeSubWindows) { | |||
2480 | nsGlobalWindowInner::Cast(this)->Suspend(aIncludeSubWindows); | |||
2481 | } | |||
2482 | ||||
2483 | void nsPIDOMWindowInner::Resume(bool aIncludeSubWindows) { | |||
2484 | nsGlobalWindowInner::Cast(this)->Resume(aIncludeSubWindows); | |||
2485 | } | |||
2486 | ||||
2487 | void nsPIDOMWindowInner::SyncStateFromParentWindow() { | |||
2488 | nsGlobalWindowInner::Cast(this)->SyncStateFromParentWindow(); | |||
2489 | } | |||
2490 | ||||
2491 | Maybe<ClientInfo> nsPIDOMWindowInner::GetClientInfo() const { | |||
2492 | return nsGlobalWindowInner::Cast(this)->GetClientInfo(); | |||
2493 | } | |||
2494 | ||||
2495 | Maybe<ClientState> nsPIDOMWindowInner::GetClientState() const { | |||
2496 | return nsGlobalWindowInner::Cast(this)->GetClientState(); | |||
2497 | } | |||
2498 | ||||
2499 | Maybe<ServiceWorkerDescriptor> nsPIDOMWindowInner::GetController() const { | |||
2500 | return nsGlobalWindowInner::Cast(this)->GetController(); | |||
2501 | } | |||
2502 | ||||
2503 | void nsPIDOMWindowInner::SetCsp(nsIContentSecurityPolicy* aCsp) { | |||
2504 | return nsGlobalWindowInner::Cast(this)->SetCsp(aCsp); | |||
2505 | } | |||
2506 | ||||
2507 | void nsPIDOMWindowInner::SetPreloadCsp(nsIContentSecurityPolicy* aPreloadCsp) { | |||
2508 | return nsGlobalWindowInner::Cast(this)->SetPreloadCsp(aPreloadCsp); | |||
2509 | } | |||
2510 | ||||
2511 | nsIContentSecurityPolicy* nsPIDOMWindowInner::GetCsp() { | |||
2512 | return nsGlobalWindowInner::Cast(this)->GetCsp(); | |||
2513 | } | |||
2514 | ||||
2515 | void nsPIDOMWindowInner::NoteCalledRegisterForServiceWorkerScope( | |||
2516 | const nsACString& aScope) { | |||
2517 | nsGlobalWindowInner::Cast(this)->NoteCalledRegisterForServiceWorkerScope( | |||
2518 | aScope); | |||
2519 | } | |||
2520 | ||||
2521 | void nsPIDOMWindowInner::NoteDOMContentLoaded() { | |||
2522 | nsGlobalWindowInner::Cast(this)->NoteDOMContentLoaded(); | |||
2523 | } | |||
2524 | ||||
2525 | bool nsGlobalWindowInner::ShouldReportForServiceWorkerScope( | |||
2526 | const nsAString& aScope) { | |||
2527 | bool result = false; | |||
2528 | ||||
2529 | nsPIDOMWindowOuter* topOuter = GetInProcessScriptableTop(); | |||
2530 | NS_ENSURE_TRUE(topOuter, false)do { if ((__builtin_expect(!!(!(topOuter)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "topOuter" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 2530); return false; } } while (false); | |||
2531 | ||||
2532 | nsGlobalWindowInner* topInner = | |||
2533 | nsGlobalWindowInner::Cast(topOuter->GetCurrentInnerWindow()); | |||
2534 | NS_ENSURE_TRUE(topInner, false)do { if ((__builtin_expect(!!(!(topInner)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "topInner" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 2534); return false; } } while (false); | |||
2535 | ||||
2536 | topInner->ShouldReportForServiceWorkerScopeInternal( | |||
2537 | NS_ConvertUTF16toUTF8(aScope), &result); | |||
2538 | return result; | |||
2539 | } | |||
2540 | ||||
2541 | InstallTriggerImpl* nsGlobalWindowInner::GetInstallTrigger() { | |||
2542 | if (!mInstallTrigger && | |||
2543 | !StaticPrefs::extensions_InstallTriggerImpl_enabled()) { | |||
2544 | // Return nullptr when InstallTriggerImpl is disabled by pref, | |||
2545 | // which does not yet break the "typeof InstallTrigger !== 'undefined" | |||
2546 | // "UA detection" use case, but prevents access to the InstallTriggerImpl | |||
2547 | // methods and properties. | |||
2548 | // | |||
2549 | // NOTE: a separate pref ("extensions.InstallTrigger.enabled"), associated | |||
2550 | // to this property using the [Pref] extended attribute in Window.webidl, | |||
2551 | // does instead hide the entire InstallTrigger property. | |||
2552 | // | |||
2553 | // See Bug 1754441 for more details about this deprecation. | |||
2554 | return nullptr; | |||
2555 | } | |||
2556 | if (!mInstallTrigger) { | |||
2557 | ErrorResult rv; | |||
2558 | mInstallTrigger = ConstructJSImplementation<InstallTriggerImpl>( | |||
2559 | "@mozilla.org/addons/installtrigger;1", this, rv); | |||
2560 | if (rv.Failed()) { | |||
2561 | rv.SuppressException(); | |||
2562 | return nullptr; | |||
2563 | } | |||
2564 | } | |||
2565 | ||||
2566 | return mInstallTrigger; | |||
2567 | } | |||
2568 | ||||
2569 | nsIDOMWindowUtils* nsGlobalWindowInner::GetWindowUtils(ErrorResult& aRv) { | |||
2570 | FORWARD_TO_OUTER_OR_THROW(WindowUtils, (), aRv, nullptr); | |||
2571 | } | |||
2572 | ||||
2573 | CallState nsGlobalWindowInner::ShouldReportForServiceWorkerScopeInternal( | |||
2574 | const nsACString& aScope, bool* aResultOut) { | |||
2575 | MOZ_DIAGNOSTIC_ASSERT(aResultOut)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aResultOut)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aResultOut))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aResultOut", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 2575); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aResultOut" ")"); do { *((volatile int*)__null) = 2575; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
2576 | ||||
2577 | // First check to see if this window is controlled. If so, then we have | |||
2578 | // found a match and are done. | |||
2579 | const Maybe<ServiceWorkerDescriptor> swd = GetController(); | |||
2580 | if (swd.isSome() && swd.ref().Scope() == aScope) { | |||
2581 | *aResultOut = true; | |||
2582 | return CallState::Stop; | |||
2583 | } | |||
2584 | ||||
2585 | // Next, check to see if this window has called | |||
2586 | // navigator.serviceWorker.register() for this scope. If so, then treat this | |||
2587 | // as a match so console reports appear in the devtools console. | |||
2588 | if (mClientSource && | |||
2589 | mClientSource->CalledRegisterForServiceWorkerScope(aScope)) { | |||
2590 | *aResultOut = true; | |||
2591 | return CallState::Stop; | |||
2592 | } | |||
2593 | ||||
2594 | // Finally check the current docshell nsILoadGroup to see if there are any | |||
2595 | // outstanding navigation requests. If so, match the scope against the | |||
2596 | // channel's URL. We want to show console reports during the FetchEvent | |||
2597 | // intercepting the navigation itself. | |||
2598 | nsCOMPtr<nsIDocumentLoader> loader(do_QueryInterface(GetDocShell())); | |||
2599 | if (loader) { | |||
2600 | nsCOMPtr<nsILoadGroup> loadgroup; | |||
2601 | Unused << loader->GetLoadGroup(getter_AddRefs(loadgroup)); | |||
2602 | if (loadgroup) { | |||
2603 | nsCOMPtr<nsISimpleEnumerator> iter; | |||
2604 | Unused << loadgroup->GetRequests(getter_AddRefs(iter)); | |||
2605 | if (iter) { | |||
2606 | nsCOMPtr<nsISupports> tmp; | |||
2607 | bool hasMore = true; | |||
2608 | // Check each network request in the load group. | |||
2609 | while (NS_SUCCEEDED(iter->HasMoreElements(&hasMore))((bool)(__builtin_expect(!!(!NS_FAILED_impl(iter->HasMoreElements (&hasMore))), 1))) && hasMore) { | |||
2610 | iter->GetNext(getter_AddRefs(tmp)); | |||
2611 | nsCOMPtr<nsIChannel> loadingChannel(do_QueryInterface(tmp)); | |||
2612 | // Ignore subresource requests. Logging for a subresource | |||
2613 | // FetchEvent should be handled above since the client is | |||
2614 | // already controlled. | |||
2615 | if (!loadingChannel || | |||
2616 | !nsContentUtils::IsNonSubresourceRequest(loadingChannel)) { | |||
2617 | continue; | |||
2618 | } | |||
2619 | nsCOMPtr<nsIURI> loadingURL; | |||
2620 | Unused << loadingChannel->GetURI(getter_AddRefs(loadingURL)); | |||
2621 | if (!loadingURL) { | |||
2622 | continue; | |||
2623 | } | |||
2624 | nsAutoCString loadingSpec; | |||
2625 | Unused << loadingURL->GetSpec(loadingSpec); | |||
2626 | // Perform a simple substring comparison to match the scope | |||
2627 | // against the channel URL. | |||
2628 | if (StringBeginsWith(loadingSpec, aScope)) { | |||
2629 | *aResultOut = true; | |||
2630 | return CallState::Stop; | |||
2631 | } | |||
2632 | } | |||
2633 | } | |||
2634 | } | |||
2635 | } | |||
2636 | ||||
2637 | // The current window doesn't care about this service worker, but maybe | |||
2638 | // one of our child frames does. | |||
2639 | return CallOnInProcessChildren( | |||
2640 | &nsGlobalWindowInner::ShouldReportForServiceWorkerScopeInternal, aScope, | |||
2641 | aResultOut); | |||
2642 | } | |||
2643 | ||||
2644 | void nsGlobalWindowInner::NoteCalledRegisterForServiceWorkerScope( | |||
2645 | const nsACString& aScope) { | |||
2646 | if (!mClientSource) { | |||
2647 | return; | |||
2648 | } | |||
2649 | ||||
2650 | mClientSource->NoteCalledRegisterForServiceWorkerScope(aScope); | |||
2651 | } | |||
2652 | ||||
2653 | void nsGlobalWindowInner::NoteDOMContentLoaded() { | |||
2654 | if (!mClientSource) { | |||
2655 | return; | |||
2656 | } | |||
2657 | ||||
2658 | mClientSource->NoteDOMContentLoaded(); | |||
2659 | } | |||
2660 | ||||
2661 | void nsGlobalWindowInner::UpdateTopInnerWindow() { | |||
2662 | if (IsTopInnerWindow() || !mTopInnerWindow) { | |||
2663 | return; | |||
2664 | } | |||
2665 | ||||
2666 | mTopInnerWindow->UpdateWebSocketCount(-(int32_t)mNumOfOpenWebSockets); | |||
2667 | } | |||
2668 | ||||
2669 | bool nsGlobalWindowInner::IsInSyncOperation() { | |||
2670 | return GetExtantDoc() && GetExtantDoc()->IsInSyncOperation(); | |||
2671 | } | |||
2672 | ||||
2673 | bool nsGlobalWindowInner::IsSharedMemoryAllowedInternal( | |||
2674 | nsIPrincipal* aPrincipal) const { | |||
2675 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 2675); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 2675; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
2676 | ||||
2677 | if (StaticPrefs:: | |||
2678 | dom_postMessage_sharedArrayBuffer_bypassCOOP_COEP_insecure_enabled()) { | |||
2679 | return true; | |||
2680 | } | |||
2681 | ||||
2682 | if (ExtensionPolicyService::GetSingleton().IsExtensionProcess()) { | |||
2683 | if (auto* basePrincipal = BasePrincipal::Cast(aPrincipal)) { | |||
2684 | if (auto* policy = basePrincipal->AddonPolicy()) { | |||
2685 | return policy->IsPrivileged(); | |||
2686 | } | |||
2687 | } | |||
2688 | } | |||
2689 | ||||
2690 | return CrossOriginIsolated(); | |||
2691 | } | |||
2692 | ||||
2693 | bool nsGlobalWindowInner::CrossOriginIsolated() const { | |||
2694 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 2694); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 2694; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
2695 | ||||
2696 | RefPtr<BrowsingContext> bc = GetBrowsingContext(); | |||
2697 | MOZ_DIAGNOSTIC_ASSERT(bc)do { static_assert( mozilla::detail::AssertionConditionType< decltype(bc)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(bc))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("bc", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 2697); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "bc" ")"); do { *((volatile int*)__null) = 2697; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
2698 | return bc->CrossOriginIsolated(); | |||
2699 | } | |||
2700 | ||||
2701 | WindowContext* TopWindowContext(nsPIDOMWindowInner& aWindow) { | |||
2702 | WindowContext* wc = aWindow.GetWindowContext(); | |||
2703 | if (!wc) { | |||
2704 | return nullptr; | |||
2705 | } | |||
2706 | ||||
2707 | return wc->TopWindowContext(); | |||
2708 | } | |||
2709 | ||||
2710 | void nsPIDOMWindowInner::AddPeerConnection() { | |||
2711 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 2711); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 2711; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
2712 | ++mActivePeerConnections; | |||
2713 | if (mActivePeerConnections == 1 && mWindowGlobalChild) { | |||
2714 | mWindowGlobalChild->SendUpdateActivePeerConnectionStatus( | |||
2715 | /*aIsAdded*/ true); | |||
2716 | ||||
2717 | // We need to present having active peer connections immediately. If we need | |||
2718 | // to wait for the parent process to come back with this information we | |||
2719 | // might start throttling. | |||
2720 | if (WindowContext* top = TopWindowContext(*this)) { | |||
2721 | top->TransientSetHasActivePeerConnections(); | |||
2722 | } | |||
2723 | } | |||
2724 | } | |||
2725 | ||||
2726 | void nsPIDOMWindowInner::RemovePeerConnection() { | |||
2727 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 2727); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 2727; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
2728 | MOZ_ASSERT(mActivePeerConnections > 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mActivePeerConnections > 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mActivePeerConnections > 0 ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "mActivePeerConnections > 0", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 2728); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mActivePeerConnections > 0" ")"); do { *((volatile int*)__null) = 2728; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
2729 | --mActivePeerConnections; | |||
2730 | if (mActivePeerConnections == 0 && mWindowGlobalChild) { | |||
2731 | mWindowGlobalChild->SendUpdateActivePeerConnectionStatus( | |||
2732 | /*aIsAdded*/ false); | |||
2733 | } | |||
2734 | } | |||
2735 | ||||
2736 | bool nsPIDOMWindowInner::HasActivePeerConnections() { | |||
2737 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 2737); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 2737; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
2738 | ||||
2739 | WindowContext* topWindowContext = TopWindowContext(*this); | |||
2740 | return topWindowContext && topWindowContext->GetHasActivePeerConnections(); | |||
2741 | } | |||
2742 | ||||
2743 | void nsPIDOMWindowInner::AddMediaKeysInstance(MediaKeys* aMediaKeys) { | |||
2744 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 2744); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 2744; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
2745 | mMediaKeysInstances.AppendElement(aMediaKeys); | |||
2746 | if (mWindowGlobalChild && mMediaKeysInstances.Length() == 1) { | |||
2747 | mWindowGlobalChild->BlockBFCacheFor(BFCacheStatus::CONTAINS_EME_CONTENT); | |||
2748 | } | |||
2749 | } | |||
2750 | ||||
2751 | void nsPIDOMWindowInner::RemoveMediaKeysInstance(MediaKeys* aMediaKeys) { | |||
2752 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 2752); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 2752; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
2753 | mMediaKeysInstances.RemoveElement(aMediaKeys); | |||
2754 | if (mWindowGlobalChild && mMediaKeysInstances.IsEmpty()) { | |||
2755 | mWindowGlobalChild->UnblockBFCacheFor(BFCacheStatus::CONTAINS_EME_CONTENT); | |||
2756 | } | |||
2757 | } | |||
2758 | ||||
2759 | bool nsPIDOMWindowInner::HasActiveMediaKeysInstance() { | |||
2760 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 2760); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 2760; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
2761 | return !mMediaKeysInstances.IsEmpty(); | |||
2762 | } | |||
2763 | ||||
2764 | bool nsPIDOMWindowInner::IsPlayingAudio() { | |||
2765 | for (uint32_t i = 0; i < mAudioContexts.Length(); i++) { | |||
2766 | if (mAudioContexts[i]->IsRunning()) { | |||
2767 | return true; | |||
2768 | } | |||
2769 | } | |||
2770 | RefPtr<AudioChannelService> acs = AudioChannelService::Get(); | |||
2771 | if (!acs) { | |||
2772 | return false; | |||
2773 | } | |||
2774 | auto outer = GetOuterWindow(); | |||
2775 | if (!outer) { | |||
2776 | // We've been unlinked and are about to die. Not a good time to pretend to | |||
2777 | // be playing audio. | |||
2778 | return false; | |||
2779 | } | |||
2780 | return acs->IsWindowActive(outer); | |||
2781 | } | |||
2782 | ||||
2783 | bool nsPIDOMWindowInner::IsDocumentLoaded() const { return mIsDocumentLoaded; } | |||
2784 | ||||
2785 | mozilla::dom::TimeoutManager* nsGlobalWindowInner::GetTimeoutManager() { | |||
2786 | return mTimeoutManager.get(); | |||
2787 | } | |||
2788 | ||||
2789 | bool nsGlobalWindowInner::IsRunningTimeout() { | |||
2790 | return GetTimeoutManager()->IsRunningTimeout(); | |||
2791 | } | |||
2792 | ||||
2793 | void nsPIDOMWindowInner::TryToCacheTopInnerWindow() { | |||
2794 | if (mHasTriedToCacheTopInnerWindow) { | |||
2795 | return; | |||
2796 | } | |||
2797 | ||||
2798 | nsGlobalWindowInner* window = nsGlobalWindowInner::Cast(this); | |||
2799 | ||||
2800 | MOZ_ASSERT(!window->IsDying())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!window->IsDying())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!window->IsDying()))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("!window->IsDying()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 2800); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!window->IsDying()" ")"); do { *((volatile int*)__null) = 2800; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
2801 | ||||
2802 | mHasTriedToCacheTopInnerWindow = true; | |||
2803 | ||||
2804 | MOZ_ASSERT(window)do { static_assert( mozilla::detail::AssertionConditionType< decltype(window)>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(window))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("window", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 2804); AnnotateMozCrashReason("MOZ_ASSERT" "(" "window" ")" ); do { *((volatile int*)__null) = 2804; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
2805 | ||||
2806 | if (nsCOMPtr<nsPIDOMWindowOuter> topOutter = | |||
2807 | window->GetInProcessScriptableTop()) { | |||
2808 | mTopInnerWindow = topOutter->GetCurrentInnerWindow(); | |||
2809 | } | |||
2810 | } | |||
2811 | ||||
2812 | void nsPIDOMWindowInner::UpdateActiveIndexedDBDatabaseCount(int32_t aDelta) { | |||
2813 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 2813); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 2813; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
2814 | ||||
2815 | if (aDelta == 0) { | |||
2816 | return; | |||
2817 | } | |||
2818 | ||||
2819 | // We count databases but not transactions because only active databases | |||
2820 | // could block throttling. | |||
2821 | uint32_t& counter = mTopInnerWindow | |||
2822 | ? mTopInnerWindow->mNumOfIndexedDBDatabases | |||
2823 | : mNumOfIndexedDBDatabases; | |||
2824 | ||||
2825 | counter += aDelta; | |||
2826 | } | |||
2827 | ||||
2828 | bool nsPIDOMWindowInner::HasActiveIndexedDBDatabases() { | |||
2829 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 2829); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 2829; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
2830 | ||||
2831 | return mTopInnerWindow ? mTopInnerWindow->mNumOfIndexedDBDatabases > 0 | |||
2832 | : mNumOfIndexedDBDatabases > 0; | |||
2833 | } | |||
2834 | ||||
2835 | void nsPIDOMWindowInner::UpdateWebSocketCount(int32_t aDelta) { | |||
2836 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 2836); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 2836; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
2837 | ||||
2838 | if (aDelta == 0) { | |||
2839 | return; | |||
2840 | } | |||
2841 | ||||
2842 | if (mTopInnerWindow && !IsTopInnerWindow()) { | |||
2843 | mTopInnerWindow->UpdateWebSocketCount(aDelta); | |||
2844 | } | |||
2845 | ||||
2846 | MOZ_DIAGNOSTIC_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(aDelta > 0 || ((aDelta + mNumOfOpenWebSockets) < mNumOfOpenWebSockets))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aDelta > 0 || ((aDelta + mNumOfOpenWebSockets ) < mNumOfOpenWebSockets)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aDelta > 0 || ((aDelta + mNumOfOpenWebSockets) < mNumOfOpenWebSockets)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 2847); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aDelta > 0 || ((aDelta + mNumOfOpenWebSockets) < mNumOfOpenWebSockets)" ")"); do { *((volatile int*)__null) = 2847; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
2847 | aDelta > 0 || ((aDelta + mNumOfOpenWebSockets) < mNumOfOpenWebSockets))do { static_assert( mozilla::detail::AssertionConditionType< decltype(aDelta > 0 || ((aDelta + mNumOfOpenWebSockets) < mNumOfOpenWebSockets))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aDelta > 0 || ((aDelta + mNumOfOpenWebSockets ) < mNumOfOpenWebSockets)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aDelta > 0 || ((aDelta + mNumOfOpenWebSockets) < mNumOfOpenWebSockets)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 2847); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aDelta > 0 || ((aDelta + mNumOfOpenWebSockets) < mNumOfOpenWebSockets)" ")"); do { *((volatile int*)__null) = 2847; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
2848 | ||||
2849 | mNumOfOpenWebSockets += aDelta; | |||
2850 | } | |||
2851 | ||||
2852 | bool nsPIDOMWindowInner::HasOpenWebSockets() const { | |||
2853 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 2853); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 2853; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
2854 | ||||
2855 | return mNumOfOpenWebSockets || | |||
2856 | (mTopInnerWindow && mTopInnerWindow->mNumOfOpenWebSockets); | |||
2857 | } | |||
2858 | ||||
2859 | bool nsPIDOMWindowInner::IsCurrentInnerWindow() const { | |||
2860 | if (mozilla::SessionHistoryInParent() && mBrowsingContext && | |||
2861 | mBrowsingContext->IsInBFCache()) { | |||
2862 | return false; | |||
2863 | } | |||
2864 | ||||
2865 | if (!mBrowsingContext || mBrowsingContext->IsDiscarded()) { | |||
2866 | // If our BrowsingContext has been discarded, we consider ourselves | |||
2867 | // still-current if we were current at the time it was discarded. | |||
2868 | return mOuterWindow && WasCurrentInnerWindow(); | |||
2869 | } | |||
2870 | ||||
2871 | nsPIDOMWindowOuter* outer = mBrowsingContext->GetDOMWindow(); | |||
2872 | return outer && outer->GetCurrentInnerWindow() == this; | |||
2873 | } | |||
2874 | ||||
2875 | bool nsPIDOMWindowInner::IsFullyActive() const { | |||
2876 | WindowContext* wc = GetWindowContext(); | |||
2877 | if (!wc || wc->IsDiscarded() || !wc->IsCurrent()) { | |||
2878 | return false; | |||
2879 | } | |||
2880 | return GetBrowsingContext()->AncestorsAreCurrent(); | |||
2881 | } | |||
2882 | ||||
2883 | void nsPIDOMWindowInner::SetAudioCapture(bool aCapture) { | |||
2884 | RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate(); | |||
2885 | if (service) { | |||
2886 | service->SetWindowAudioCaptured(GetOuterWindow(), mWindowID, aCapture); | |||
2887 | } | |||
2888 | } | |||
2889 | ||||
2890 | void nsGlobalWindowInner::SetActiveLoadingState(bool aIsLoading) { | |||
2891 | MOZ_LOG(do { const ::mozilla::LogModule* moz_real_module = gTimeoutLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print (moz_real_module, mozilla::LogLevel::Debug, "SetActiveLoadingState innerwindow %p: %d" , (void*)this, aIsLoading); } } while (0) | |||
2892 | gTimeoutLog, mozilla::LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gTimeoutLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print (moz_real_module, mozilla::LogLevel::Debug, "SetActiveLoadingState innerwindow %p: %d" , (void*)this, aIsLoading); } } while (0) | |||
2893 | ("SetActiveLoadingState innerwindow %p: %d", (void*)this, aIsLoading))do { const ::mozilla::LogModule* moz_real_module = gTimeoutLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print (moz_real_module, mozilla::LogLevel::Debug, "SetActiveLoadingState innerwindow %p: %d" , (void*)this, aIsLoading); } } while (0); | |||
2894 | if (GetBrowsingContext()) { | |||
2895 | // Setting loading on a discarded context has no effect. | |||
2896 | Unused << GetBrowsingContext()->SetLoading(aIsLoading); | |||
2897 | } | |||
2898 | ||||
2899 | if (!nsGlobalWindowInner::Cast(this)->IsChromeWindow()) { | |||
2900 | mTimeoutManager->SetLoading(aIsLoading); | |||
2901 | } | |||
2902 | ||||
2903 | HintIsLoading(aIsLoading); | |||
2904 | } | |||
2905 | ||||
2906 | void nsGlobalWindowInner::HintIsLoading(bool aIsLoading) { | |||
2907 | // Hint to tell the JS GC to use modified triggers during pageload. | |||
2908 | if (mHintedWasLoading != aIsLoading) { | |||
2909 | using namespace js::gc; | |||
2910 | SetPerformanceHint(danger::GetJSContext(), aIsLoading | |||
2911 | ? PerformanceHint::InPageLoad | |||
2912 | : PerformanceHint::Normal); | |||
2913 | mHintedWasLoading = aIsLoading; | |||
2914 | } | |||
2915 | } | |||
2916 | ||||
2917 | // nsISpeechSynthesisGetter | |||
2918 | ||||
2919 | #ifdef MOZ_WEBSPEECH1 | |||
2920 | SpeechSynthesis* nsGlobalWindowInner::GetSpeechSynthesis(ErrorResult& aError) { | |||
2921 | if (!mSpeechSynthesis) { | |||
2922 | mSpeechSynthesis = new SpeechSynthesis(this); | |||
2923 | } | |||
2924 | ||||
2925 | return mSpeechSynthesis; | |||
2926 | } | |||
2927 | ||||
2928 | bool nsGlobalWindowInner::HasActiveSpeechSynthesis() { | |||
2929 | if (mSpeechSynthesis) { | |||
2930 | return !mSpeechSynthesis->HasEmptyQueue(); | |||
2931 | } | |||
2932 | ||||
2933 | return false; | |||
2934 | } | |||
2935 | ||||
2936 | #endif | |||
2937 | ||||
2938 | mozilla::glean::Glean* nsGlobalWindowInner::Glean() { | |||
2939 | if (!mGlean) { | |||
2940 | mGlean = new mozilla::glean::Glean(this); | |||
2941 | } | |||
2942 | ||||
2943 | return mGlean; | |||
2944 | } | |||
2945 | ||||
2946 | mozilla::glean::GleanPings* nsGlobalWindowInner::GleanPings() { | |||
2947 | if (!mGleanPings) { | |||
2948 | mGleanPings = new mozilla::glean::GleanPings(); | |||
2949 | } | |||
2950 | ||||
2951 | return mGleanPings; | |||
2952 | } | |||
2953 | ||||
2954 | Nullable<WindowProxyHolder> nsGlobalWindowInner::GetParent( | |||
2955 | ErrorResult& aError) { | |||
2956 | FORWARD_TO_OUTER_OR_THROW(GetParentOuter, (), aError, nullptr); | |||
2957 | } | |||
2958 | ||||
2959 | /** | |||
2960 | * GetInProcessScriptableParent used to be called when a script read | |||
2961 | * window.parent. Under Fission, that is now handled by | |||
2962 | * BrowsingContext::GetParent, and the result is a WindowProxyHolder rather than | |||
2963 | * an actual global window. This method still exists for legacy callers which | |||
2964 | * relied on the old logic, and require in-process windows. However, it only | |||
2965 | * works correctly when no out-of-process frames exist between this window and | |||
2966 | * the top-level window, so it should not be used in new code. | |||
2967 | * | |||
2968 | * In contrast to GetRealParent, GetInProcessScriptableParent respects <iframe | |||
2969 | * mozbrowser> boundaries, so if |this| is contained by an <iframe | |||
2970 | * mozbrowser>, we will return |this| as its own parent. | |||
2971 | */ | |||
2972 | nsPIDOMWindowOuter* nsGlobalWindowInner::GetInProcessScriptableParent() { | |||
2973 | FORWARD_TO_OUTER(GetInProcessScriptableParent, (), nullptr); | |||
2974 | } | |||
2975 | ||||
2976 | /** | |||
2977 | * GetInProcessScriptableTop used to be called when a script read window.top. | |||
2978 | * Under Fission, that is now handled by BrowsingContext::Top, and the result is | |||
2979 | * a WindowProxyHolder rather than an actual global window. This method still | |||
2980 | * exists for legacy callers which relied on the old logic, and require | |||
2981 | * in-process windows. However, it only works correctly when no out-of-process | |||
2982 | * frames exist between this window and the top-level window, so it should not | |||
2983 | * be used in new code. | |||
2984 | * | |||
2985 | * In contrast to GetRealTop, GetInProcessScriptableTop respects <iframe | |||
2986 | * mozbrowser> boundaries. If we encounter a window owned by an <iframe | |||
2987 | * mozbrowser> while walking up the window hierarchy, we'll stop and return that | |||
2988 | * window. | |||
2989 | */ | |||
2990 | nsPIDOMWindowOuter* nsGlobalWindowInner::GetInProcessScriptableTop() { | |||
2991 | FORWARD_TO_OUTER(GetInProcessScriptableTop, (), nullptr); | |||
2992 | } | |||
2993 | ||||
2994 | void nsGlobalWindowInner::GetContent(JSContext* aCx, | |||
2995 | JS::MutableHandle<JSObject*> aRetval, | |||
2996 | CallerType aCallerType, | |||
2997 | ErrorResult& aError) { | |||
2998 | FORWARD_TO_OUTER_OR_THROW(GetContentOuter, | |||
2999 | (aCx, aRetval, aCallerType, aError), aError, ); | |||
3000 | } | |||
3001 | ||||
3002 | BarProp* nsGlobalWindowInner::GetMenubar(ErrorResult& aError) { | |||
3003 | if (!mMenubar) { | |||
3004 | mMenubar = new MenubarProp(this); | |||
3005 | } | |||
3006 | ||||
3007 | return mMenubar; | |||
3008 | } | |||
3009 | ||||
3010 | BarProp* nsGlobalWindowInner::GetToolbar(ErrorResult& aError) { | |||
3011 | if (!mToolbar) { | |||
3012 | mToolbar = new ToolbarProp(this); | |||
3013 | } | |||
3014 | ||||
3015 | return mToolbar; | |||
3016 | } | |||
3017 | ||||
3018 | BarProp* nsGlobalWindowInner::GetLocationbar(ErrorResult& aError) { | |||
3019 | if (!mLocationbar) { | |||
3020 | mLocationbar = new LocationbarProp(this); | |||
3021 | } | |||
3022 | return mLocationbar; | |||
3023 | } | |||
3024 | ||||
3025 | BarProp* nsGlobalWindowInner::GetPersonalbar(ErrorResult& aError) { | |||
3026 | if (!mPersonalbar) { | |||
3027 | mPersonalbar = new PersonalbarProp(this); | |||
3028 | } | |||
3029 | return mPersonalbar; | |||
3030 | } | |||
3031 | ||||
3032 | BarProp* nsGlobalWindowInner::GetStatusbar(ErrorResult& aError) { | |||
3033 | if (!mStatusbar) { | |||
3034 | mStatusbar = new StatusbarProp(this); | |||
3035 | } | |||
3036 | return mStatusbar; | |||
3037 | } | |||
3038 | ||||
3039 | BarProp* nsGlobalWindowInner::GetScrollbars(ErrorResult& aError) { | |||
3040 | if (!mScrollbars) { | |||
3041 | mScrollbars = new ScrollbarsProp(this); | |||
3042 | } | |||
3043 | ||||
3044 | return mScrollbars; | |||
3045 | } | |||
3046 | ||||
3047 | bool nsGlobalWindowInner::GetClosed(ErrorResult& aError) { | |||
3048 | // If we're called from JS (which is the only way we should be getting called | |||
3049 | // here) and we reach this point, that means our JS global is the current | |||
3050 | // target of the WindowProxy, which means that we are the "current inner" | |||
3051 | // of our outer. So if FORWARD_TO_OUTER fails to forward, that means the | |||
3052 | // outer is already torn down, which corresponds to the closed state. | |||
3053 | FORWARD_TO_OUTER(GetClosedOuter, (), true); | |||
3054 | } | |||
3055 | ||||
3056 | Nullable<WindowProxyHolder> nsGlobalWindowInner::IndexedGetter( | |||
3057 | uint32_t aIndex) { | |||
3058 | FORWARD_TO_OUTER(IndexedGetterOuter, (aIndex), nullptr); | |||
3059 | } | |||
3060 | ||||
3061 | namespace { | |||
3062 | ||||
3063 | struct InterfaceShimEntry { | |||
3064 | const char* geckoName; | |||
3065 | const char* domName; | |||
3066 | }; | |||
3067 | ||||
3068 | } // anonymous namespace | |||
3069 | ||||
3070 | // We add shims from Components.interfaces.nsIDOMFoo to window.Foo for each | |||
3071 | // interface that has interface constants that sites might be getting off | |||
3072 | // of Ci. | |||
3073 | const InterfaceShimEntry kInterfaceShimMap[] = { | |||
3074 | {"nsIXMLHttpRequest", "XMLHttpRequest"}, | |||
3075 | {"nsIDOMDOMException", "DOMException"}, | |||
3076 | {"nsIDOMNode", "Node"}, | |||
3077 | {"nsIDOMCSSRule", "CSSRule"}, | |||
3078 | {"nsIDOMEvent", "Event"}, | |||
3079 | {"nsIDOMNSEvent", "Event"}, | |||
3080 | {"nsIDOMKeyEvent", "KeyEvent"}, | |||
3081 | {"nsIDOMMouseEvent", "MouseEvent"}, | |||
3082 | {"nsIDOMMouseScrollEvent", "MouseScrollEvent"}, | |||
3083 | {"nsIDOMMutationEvent", "MutationEvent"}, | |||
3084 | {"nsIDOMUIEvent", "UIEvent"}, | |||
3085 | {"nsIDOMHTMLMediaElement", "HTMLMediaElement"}, | |||
3086 | {"nsIDOMRange", "Range"}, | |||
3087 | // Think about whether Ci.nsINodeFilter can just go away for websites! | |||
3088 | {"nsIDOMNodeFilter", "NodeFilter"}, | |||
3089 | {"nsIDOMXPathResult", "XPathResult"}}; | |||
3090 | ||||
3091 | bool nsGlobalWindowInner::ResolveComponentsShim( | |||
3092 | JSContext* aCx, JS::Handle<JSObject*> aGlobal, | |||
3093 | JS::MutableHandle<mozilla::Maybe<JS::PropertyDescriptor>> aDesc) { | |||
3094 | // Keep track of how often this happens. | |||
3095 | Telemetry::Accumulate(Telemetry::COMPONENTS_SHIM_ACCESSED_BY_CONTENT, true); | |||
3096 | ||||
3097 | // Warn once. | |||
3098 | nsCOMPtr<Document> doc = GetExtantDoc(); | |||
3099 | if (doc) { | |||
3100 | doc->WarnOnceAbout(DeprecatedOperations::eComponents, /* asError = */ true); | |||
3101 | } | |||
3102 | ||||
3103 | // Create a fake Components object. | |||
3104 | AssertSameCompartment(aCx, aGlobal); | |||
3105 | JS::Rooted<JSObject*> components(aCx, JS_NewPlainObject(aCx)); | |||
3106 | if (NS_WARN_IF(!components)NS_warn_if_impl(!components, "!components", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 3106)) { | |||
3107 | return false; | |||
3108 | } | |||
3109 | ||||
3110 | // Create a fake interfaces object. | |||
3111 | JS::Rooted<JSObject*> interfaces(aCx, JS_NewPlainObject(aCx)); | |||
3112 | if (NS_WARN_IF(!interfaces)NS_warn_if_impl(!interfaces, "!interfaces", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 3112)) { | |||
3113 | return false; | |||
3114 | } | |||
3115 | bool ok = | |||
3116 | JS_DefineProperty(aCx, components, "interfaces", interfaces, | |||
3117 | JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY); | |||
3118 | if (NS_WARN_IF(!ok)NS_warn_if_impl(!ok, "!ok", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 3118)) { | |||
3119 | return false; | |||
3120 | } | |||
3121 | ||||
3122 | // Define a bunch of shims from the Ci.nsIDOMFoo to window.Foo for DOM | |||
3123 | // interfaces with constants. | |||
3124 | for (uint32_t i = 0; i < ArrayLength(kInterfaceShimMap); ++i) { | |||
3125 | // Grab the names from the table. | |||
3126 | const char* geckoName = kInterfaceShimMap[i].geckoName; | |||
3127 | const char* domName = kInterfaceShimMap[i].domName; | |||
3128 | ||||
3129 | // Look up the appopriate interface object on the global. | |||
3130 | JS::Rooted<JS::Value> v(aCx, JS::UndefinedValue()); | |||
3131 | ok = JS_GetProperty(aCx, aGlobal, domName, &v); | |||
3132 | if (NS_WARN_IF(!ok)NS_warn_if_impl(!ok, "!ok", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 3132)) { | |||
3133 | return false; | |||
3134 | } | |||
3135 | if (!v.isObject()) { | |||
3136 | NS_WARNING("Unable to find interface object on global")NS_DebugBreak(NS_DEBUG_WARNING, "Unable to find interface object on global" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 3136); | |||
3137 | continue; | |||
3138 | } | |||
3139 | ||||
3140 | // Define the shim on the interfaces object. | |||
3141 | ok = JS_DefineProperty( | |||
3142 | aCx, interfaces, geckoName, v, | |||
3143 | JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY); | |||
3144 | if (NS_WARN_IF(!ok)NS_warn_if_impl(!ok, "!ok", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 3144)) { | |||
3145 | return false; | |||
3146 | } | |||
3147 | } | |||
3148 | ||||
3149 | aDesc.set(mozilla::Some(JS::PropertyDescriptor::Data( | |||
3150 | JS::ObjectValue(*components), | |||
3151 | {JS::PropertyAttribute::Configurable, JS::PropertyAttribute::Enumerable, | |||
3152 | JS::PropertyAttribute::Writable}))); | |||
3153 | return true; | |||
3154 | } | |||
3155 | ||||
3156 | #ifdef RELEASE_OR_BETA | |||
3157 | # define USE_CONTROLLERS_SHIM | |||
3158 | #endif | |||
3159 | ||||
3160 | #ifdef USE_CONTROLLERS_SHIM | |||
3161 | static const JSClass ControllersShimClass = {"Controllers", 0}; | |||
3162 | static const JSClass XULControllersShimClass = {"XULControllers", 0}; | |||
3163 | #endif | |||
3164 | ||||
3165 | bool nsGlobalWindowInner::DoResolve( | |||
3166 | JSContext* aCx, JS::Handle<JSObject*> aObj, JS::Handle<jsid> aId, | |||
3167 | JS::MutableHandle<mozilla::Maybe<JS::PropertyDescriptor>> aDesc) { | |||
3168 | // Note: Keep this in sync with MayResolve. | |||
3169 | ||||
3170 | // Note: The infallibleInit call in GlobalResolve depends on this check. | |||
3171 | if (!aId.isString()) { | |||
3172 | return true; | |||
3173 | } | |||
3174 | ||||
3175 | bool found; | |||
3176 | if (!WebIDLGlobalNameHash::DefineIfEnabled(aCx, aObj, aId, aDesc, &found)) { | |||
3177 | return false; | |||
3178 | } | |||
3179 | ||||
3180 | if (found) { | |||
3181 | return true; | |||
3182 | } | |||
3183 | ||||
3184 | // We support a cut-down Components.interfaces in case websites are | |||
3185 | // using Components.interfaces.nsIFoo.CONSTANT_NAME for the ones | |||
3186 | // that have constants. | |||
3187 | if (StaticPrefs::dom_use_components_shim() && | |||
3188 | aId == XPCJSRuntime::Get()->GetStringID(XPCJSContext::IDX_COMPONENTS)) { | |||
3189 | return ResolveComponentsShim(aCx, aObj, aDesc); | |||
3190 | } | |||
3191 | ||||
3192 | // We also support a "window.controllers" thing; apparently some | |||
3193 | // sites use it for browser-sniffing. See bug 1010577. | |||
3194 | #ifdef USE_CONTROLLERS_SHIM | |||
3195 | // Note: We use |aObj| rather than |this| to get the principal here, because | |||
3196 | // this is called during Window setup when the Document isn't necessarily | |||
3197 | // hooked up yet. | |||
3198 | if ((aId == XPCJSRuntime::Get()->GetStringID(XPCJSContext::IDX_CONTROLLERS) || | |||
3199 | aId == XPCJSRuntime::Get()->GetStringID( | |||
3200 | XPCJSContext::IDX_CONTROLLERS_CLASS)) && | |||
3201 | !xpc::IsXrayWrapper(aObj) && | |||
3202 | !nsContentUtils::ObjectPrincipal(aObj)->IsSystemPrincipal()) { | |||
3203 | if (GetExtantDoc()) { | |||
3204 | GetExtantDoc()->WarnOnceAbout( | |||
3205 | DeprecatedOperations::eWindow_Cc_ontrollers); | |||
3206 | } | |||
3207 | const JSClass* clazz; | |||
3208 | if (aId == | |||
3209 | XPCJSRuntime::Get()->GetStringID(XPCJSContext::IDX_CONTROLLERS)) { | |||
3210 | clazz = &XULControllersShimClass; | |||
3211 | } else { | |||
3212 | clazz = &ControllersShimClass; | |||
3213 | } | |||
3214 | MOZ_ASSERT(JS_IsGlobalObject(aObj))do { static_assert( mozilla::detail::AssertionConditionType< decltype(JS_IsGlobalObject(aObj))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(JS_IsGlobalObject(aObj)))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("JS_IsGlobalObject(aObj)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 3214); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JS_IsGlobalObject(aObj)" ")"); do { *((volatile int*)__null) = 3214; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
3215 | JS::Rooted<JSObject*> shim(aCx, JS_NewObject(aCx, clazz)); | |||
3216 | if (NS_WARN_IF(!shim)NS_warn_if_impl(!shim, "!shim", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 3216)) { | |||
3217 | return false; | |||
3218 | } | |||
3219 | ||||
3220 | aDesc.set(mozilla::Some(JS::PropertyDescriptor::Data( | |||
3221 | JS::ObjectValue(*shim), | |||
3222 | {JS::PropertyAttribute::Configurable, JS::PropertyAttribute::Enumerable, | |||
3223 | JS::PropertyAttribute::Writable}))); | |||
3224 | return true; | |||
3225 | } | |||
3226 | #endif | |||
3227 | ||||
3228 | return true; | |||
3229 | } | |||
3230 | ||||
3231 | /* static */ | |||
3232 | bool nsGlobalWindowInner::MayResolve(jsid aId) { | |||
3233 | // Note: This function does not fail and may not have any side-effects. | |||
3234 | // Note: Keep this in sync with DoResolve. | |||
3235 | if (!aId.isString()) { | |||
3236 | return false; | |||
3237 | } | |||
3238 | ||||
3239 | if (aId == XPCJSRuntime::Get()->GetStringID(XPCJSContext::IDX_COMPONENTS)) { | |||
3240 | return true; | |||
3241 | } | |||
3242 | ||||
3243 | if (aId == XPCJSRuntime::Get()->GetStringID(XPCJSContext::IDX_CONTROLLERS) || | |||
3244 | aId == XPCJSRuntime::Get()->GetStringID( | |||
3245 | XPCJSContext::IDX_CONTROLLERS_CLASS)) { | |||
3246 | // We only resolve .controllers/.Controllers in release builds and on | |||
3247 | // non-chrome windows, but let's not worry about any of that stuff. | |||
3248 | return true; | |||
3249 | } | |||
3250 | ||||
3251 | return WebIDLGlobalNameHash::MayResolve(aId); | |||
3252 | } | |||
3253 | ||||
3254 | void nsGlobalWindowInner::GetOwnPropertyNames( | |||
3255 | JSContext* aCx, JS::MutableHandleVector<jsid> aNames, bool aEnumerableOnly, | |||
3256 | ErrorResult& aRv) { | |||
3257 | if (aEnumerableOnly) { | |||
3258 | // The names we would return from here get defined on the window via one of | |||
3259 | // two codepaths. The ones coming from the WebIDLGlobalNameHash will end up | |||
3260 | // in the DefineConstructor function in BindingUtils, which always defines | |||
3261 | // things as non-enumerable. The ones coming from the script namespace | |||
3262 | // manager get defined by our resolve hook using FillPropertyDescriptor with | |||
3263 | // 0 for the property attributes, so non-enumerable as well. | |||
3264 | // | |||
3265 | // So in the aEnumerableOnly case we have nothing to do. | |||
3266 | return; | |||
3267 | } | |||
3268 | ||||
3269 | // "Components" is marked as enumerable but only resolved on demand :-/. | |||
3270 | // aNames.AppendElement(u"Components"_ns); | |||
3271 | ||||
3272 | JS::Rooted<JSObject*> wrapper(aCx, GetWrapper()); | |||
3273 | ||||
3274 | // There are actually two ways we can get called here: For normal | |||
3275 | // enumeration or for Xray enumeration. In the latter case, we want to | |||
3276 | // return all possible WebIDL names, because we don't really support | |||
3277 | // deleting these names off our Xray; trying to resolve them will just make | |||
3278 | // them come back. In the former case, we want to avoid returning deleted | |||
3279 | // names. But the JS engine already knows about the non-deleted | |||
3280 | // already-resolved names, so we can just return the so-far-unresolved ones. | |||
3281 | // | |||
3282 | // We can tell which case we're in by whether aCx is in our wrapper's | |||
3283 | // compartment. If not, we're in the Xray case. | |||
3284 | WebIDLGlobalNameHash::NameType nameType = | |||
3285 | js::IsObjectInContextCompartment(wrapper, aCx) | |||
3286 | ? WebIDLGlobalNameHash::UnresolvedNamesOnly | |||
3287 | : WebIDLGlobalNameHash::AllNames; | |||
3288 | if (!WebIDLGlobalNameHash::GetNames(aCx, wrapper, nameType, aNames)) { | |||
3289 | aRv.NoteJSContextException(aCx); | |||
3290 | } | |||
3291 | } | |||
3292 | ||||
3293 | /* static */ | |||
3294 | bool nsGlobalWindowInner::IsPrivilegedChromeWindow(JSContext*, JSObject* aObj) { | |||
3295 | // For now, have to deal with XPConnect objects here. | |||
3296 | nsGlobalWindowInner* win = xpc::WindowOrNull(aObj); | |||
3297 | return win && win->IsChromeWindow() && | |||
3298 | nsContentUtils::ObjectPrincipal(aObj) == | |||
3299 | nsContentUtils::GetSystemPrincipal(); | |||
3300 | } | |||
3301 | ||||
3302 | /* static */ | |||
3303 | bool nsGlobalWindowInner::DeviceSensorsEnabled(JSContext*, JSObject*) { | |||
3304 | return Preferences::GetBool("device.sensors.enabled"); | |||
3305 | } | |||
3306 | ||||
3307 | /* static */ | |||
3308 | bool nsGlobalWindowInner::CachesEnabled(JSContext* aCx, JSObject* aObj) { | |||
3309 | if (!IsSecureContextOrObjectIsFromSecureContext(aCx, aObj)) { | |||
3310 | return StaticPrefs::dom_caches_testing_enabled() || | |||
3311 | StaticPrefs::dom_serviceWorkers_testing_enabled(); | |||
3312 | } | |||
3313 | return true; | |||
3314 | } | |||
3315 | ||||
3316 | /* static */ | |||
3317 | bool nsGlobalWindowInner::IsSizeToContentEnabled(JSContext* aCx, JSObject*) { | |||
3318 | return StaticPrefs::dom_window_sizeToContent_enabled() || | |||
3319 | nsContentUtils::IsSystemCaller(aCx); | |||
3320 | } | |||
3321 | ||||
3322 | /* static */ | |||
3323 | bool nsGlobalWindowInner::IsGleanNeeded(JSContext* aCx, JSObject* aObj) { | |||
3324 | // Glean is needed in ChromeOnly contexts and also in privileged about pages. | |||
3325 | nsIPrincipal* principal = nsContentUtils::SubjectPrincipal(aCx); | |||
3326 | if (principal->IsSystemPrincipal()) { | |||
3327 | return true; | |||
3328 | } | |||
3329 | ||||
3330 | uint32_t flags = 0; | |||
3331 | if (NS_FAILED(principal->GetAboutModuleFlags(&flags))((bool)(__builtin_expect(!!(NS_FAILED_impl(principal->GetAboutModuleFlags (&flags))), 0)))) { | |||
3332 | return false; | |||
3333 | } | |||
3334 | return flags & nsIAboutModule::IS_SECURE_CHROME_UI; | |||
3335 | } | |||
3336 | ||||
3337 | Crypto* nsGlobalWindowInner::GetCrypto(ErrorResult& aError) { | |||
3338 | if (!mCrypto) { | |||
3339 | mCrypto = new Crypto(this); | |||
3340 | } | |||
3341 | return mCrypto; | |||
3342 | } | |||
3343 | ||||
3344 | nsIControllers* nsGlobalWindowInner::GetControllers(ErrorResult& aError) { | |||
3345 | FORWARD_TO_OUTER_OR_THROW(GetControllersOuter, (aError), aError, nullptr); | |||
3346 | } | |||
3347 | ||||
3348 | nsresult nsGlobalWindowInner::GetControllers(nsIControllers** aResult) { | |||
3349 | ErrorResult rv; | |||
3350 | nsCOMPtr<nsIControllers> controllers = GetControllers(rv); | |||
3351 | controllers.forget(aResult); | |||
3352 | ||||
3353 | return rv.StealNSResult(); | |||
3354 | } | |||
3355 | ||||
3356 | Nullable<WindowProxyHolder> nsGlobalWindowInner::GetOpenerWindow( | |||
3357 | ErrorResult& aError) { | |||
3358 | FORWARD_TO_OUTER_OR_THROW(GetOpenerWindowOuter, (), aError, nullptr); | |||
3359 | } | |||
3360 | ||||
3361 | void nsGlobalWindowInner::GetOpener(JSContext* aCx, | |||
3362 | JS::MutableHandle<JS::Value> aRetval, | |||
3363 | ErrorResult& aError) { | |||
3364 | Nullable<WindowProxyHolder> opener = GetOpenerWindow(aError); | |||
3365 | if (aError.Failed() || opener.IsNull()) { | |||
3366 | aRetval.setNull(); | |||
3367 | return; | |||
3368 | } | |||
3369 | ||||
3370 | if (!ToJSValue(aCx, opener.Value(), aRetval)) { | |||
3371 | aError.NoteJSContextException(aCx); | |||
3372 | } | |||
3373 | } | |||
3374 | ||||
3375 | void nsGlobalWindowInner::SetOpener(JSContext* aCx, | |||
3376 | JS::Handle<JS::Value> aOpener, | |||
3377 | ErrorResult& aError) { | |||
3378 | if (aOpener.isNull()) { | |||
3379 | RefPtr<BrowsingContext> bc(GetBrowsingContext()); | |||
3380 | if (!bc->IsDiscarded()) { | |||
3381 | bc->SetOpener(nullptr); | |||
3382 | } | |||
3383 | return; | |||
3384 | } | |||
3385 | ||||
3386 | // If something other than null is passed, just define aOpener on our inner | |||
3387 | // window's JS object, wrapped into the current compartment so that for Xrays | |||
3388 | // we define on the Xray expando object, but don't set it on the outer window, | |||
3389 | // so that it'll get reset on navigation. This is just like replaceable | |||
3390 | // properties, but we're not quite readonly. | |||
3391 | RedefineProperty(aCx, "opener", aOpener, aError); | |||
3392 | } | |||
3393 | ||||
3394 | void nsGlobalWindowInner::GetEvent(OwningEventOrUndefined& aRetval) { | |||
3395 | if (mEvent) { | |||
3396 | aRetval.SetAsEvent() = mEvent; | |||
3397 | } else { | |||
3398 | aRetval.SetUndefined(); | |||
3399 | } | |||
3400 | } | |||
3401 | ||||
3402 | void nsGlobalWindowInner::GetStatus(nsAString& aStatus, ErrorResult& aError) { | |||
3403 | FORWARD_TO_OUTER_OR_THROW(GetStatusOuter, (aStatus), aError, ); | |||
3404 | } | |||
3405 | ||||
3406 | void nsGlobalWindowInner::SetStatus(const nsAString& aStatus, | |||
3407 | ErrorResult& aError) { | |||
3408 | FORWARD_TO_OUTER_OR_THROW(SetStatusOuter, (aStatus), aError, ); | |||
3409 | } | |||
3410 | ||||
3411 | void nsGlobalWindowInner::GetName(nsAString& aName, ErrorResult& aError) { | |||
3412 | FORWARD_TO_OUTER_OR_THROW(GetNameOuter, (aName), aError, ); | |||
3413 | } | |||
3414 | ||||
3415 | void nsGlobalWindowInner::SetName(const nsAString& aName, | |||
3416 | mozilla::ErrorResult& aError) { | |||
3417 | FORWARD_TO_OUTER_OR_THROW(SetNameOuter, (aName, aError), aError, ); | |||
3418 | } | |||
3419 | ||||
3420 | double nsGlobalWindowInner::GetInnerWidth(ErrorResult& aError) { | |||
3421 | FORWARD_TO_OUTER_OR_THROW(GetInnerWidthOuter, (aError), aError, 0); | |||
3422 | } | |||
3423 | ||||
3424 | nsresult nsGlobalWindowInner::GetInnerWidth(double* aWidth) { | |||
3425 | ErrorResult rv; | |||
3426 | // Callee doesn't care about the caller type, but play it safe. | |||
3427 | *aWidth = GetInnerWidth(rv); | |||
3428 | return rv.StealNSResult(); | |||
3429 | } | |||
3430 | ||||
3431 | double nsGlobalWindowInner::GetInnerHeight(ErrorResult& aError) { | |||
3432 | // We ignore aCallerType; we only have that argument because some other things | |||
3433 | // called by GetReplaceableWindowCoord need it. If this ever changes, fix | |||
3434 | // nsresult nsGlobalWindowInner::GetInnerHeight(double* aInnerWidth) | |||
3435 | // to actually take a useful CallerType and pass it in here. | |||
3436 | FORWARD_TO_OUTER_OR_THROW(GetInnerHeightOuter, (aError), aError, 0); | |||
3437 | } | |||
3438 | ||||
3439 | nsresult nsGlobalWindowInner::GetInnerHeight(double* aHeight) { | |||
3440 | ErrorResult rv; | |||
3441 | // Callee doesn't care about the caller type, but play it safe. | |||
3442 | *aHeight = GetInnerHeight(rv); | |||
3443 | return rv.StealNSResult(); | |||
3444 | } | |||
3445 | ||||
3446 | int32_t nsGlobalWindowInner::GetOuterWidth(CallerType aCallerType, | |||
3447 | ErrorResult& aError) { | |||
3448 | FORWARD_TO_OUTER_OR_THROW(GetOuterWidthOuter, (aCallerType, aError), aError, | |||
3449 | 0); | |||
3450 | } | |||
3451 | ||||
3452 | int32_t nsGlobalWindowInner::GetOuterHeight(CallerType aCallerType, | |||
3453 | ErrorResult& aError) { | |||
3454 | FORWARD_TO_OUTER_OR_THROW(GetOuterHeightOuter, (aCallerType, aError), aError, | |||
3455 | 0); | |||
3456 | } | |||
3457 | ||||
3458 | double nsGlobalWindowInner::ScreenEdgeSlopX() const { | |||
3459 | FORWARD_TO_OUTER(ScreenEdgeSlopX, (), 0); | |||
3460 | } | |||
3461 | ||||
3462 | double nsGlobalWindowInner::ScreenEdgeSlopY() const { | |||
3463 | FORWARD_TO_OUTER(ScreenEdgeSlopY, (), 0); | |||
3464 | } | |||
3465 | ||||
3466 | int32_t nsGlobalWindowInner::GetScreenX(CallerType aCallerType, | |||
3467 | ErrorResult& aError) { | |||
3468 | FORWARD_TO_OUTER_OR_THROW(GetScreenXOuter, (aCallerType, aError), aError, 0); | |||
3469 | } | |||
3470 | ||||
3471 | int32_t nsGlobalWindowInner::GetScreenY(CallerType aCallerType, | |||
3472 | ErrorResult& aError) { | |||
3473 | FORWARD_TO_OUTER_OR_THROW(GetScreenYOuter, (aCallerType, aError), aError, 0); | |||
3474 | } | |||
3475 | ||||
3476 | float nsGlobalWindowInner::GetMozInnerScreenX(CallerType aCallerType, | |||
3477 | ErrorResult& aError) { | |||
3478 | FORWARD_TO_OUTER_OR_THROW(GetMozInnerScreenXOuter, (aCallerType), aError, 0); | |||
3479 | } | |||
3480 | ||||
3481 | float nsGlobalWindowInner::GetMozInnerScreenY(CallerType aCallerType, | |||
3482 | ErrorResult& aError) { | |||
3483 | FORWARD_TO_OUTER_OR_THROW(GetMozInnerScreenYOuter, (aCallerType), aError, 0); | |||
3484 | } | |||
3485 | ||||
3486 | static nsPresContext* GetPresContextForRatio(Document* aDoc) { | |||
3487 | if (nsPresContext* presContext = aDoc->GetPresContext()) { | |||
3488 | return presContext; | |||
3489 | } | |||
3490 | // We're in an undisplayed subdocument... There's not really an awesome way | |||
3491 | // to tell what the right DPI is from here, so we try to walk up our parent | |||
3492 | // document chain to the extent that the docs can observe each other. | |||
3493 | Document* doc = aDoc; | |||
3494 | while (doc->StyleOrLayoutObservablyDependsOnParentDocumentLayout()) { | |||
3495 | doc = doc->GetInProcessParentDocument(); | |||
3496 | if (nsPresContext* presContext = doc->GetPresContext()) { | |||
3497 | return presContext; | |||
3498 | } | |||
3499 | } | |||
3500 | return nullptr; | |||
3501 | } | |||
3502 | ||||
3503 | double nsGlobalWindowInner::GetDevicePixelRatio(CallerType aCallerType, | |||
3504 | ErrorResult& aError) { | |||
3505 | ENSURE_ACTIVE_DOCUMENT(aError, 0.0)do { if ((__builtin_expect(!!(!HasActiveDocument()), 0))) { aError .Throw(NS_ERROR_XPC_SECURITY_MANAGER_VETO); return 0.0; } } while (0); | |||
3506 | ||||
3507 | RefPtr<nsPresContext> presContext = GetPresContextForRatio(mDoc); | |||
3508 | if (NS_WARN_IF(!presContext)NS_warn_if_impl(!presContext, "!presContext", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 3508)) { | |||
3509 | // Still nothing, oh well. | |||
3510 | return 1.0; | |||
3511 | } | |||
3512 | ||||
3513 | if (nsIGlobalObject::ShouldResistFingerprinting( | |||
3514 | aCallerType, RFPTarget::WindowDevicePixelRatio)) { | |||
3515 | return 2.0; | |||
3516 | } | |||
3517 | ||||
3518 | if (aCallerType == CallerType::NonSystem) { | |||
3519 | float overrideDPPX = presContext->GetOverrideDPPX(); | |||
3520 | if (overrideDPPX > 0.0f) { | |||
3521 | return overrideDPPX; | |||
3522 | } | |||
3523 | } | |||
3524 | ||||
3525 | return double(AppUnitsPerCSSPixel()) / | |||
3526 | double(presContext->AppUnitsPerDevPixel()); | |||
3527 | } | |||
3528 | ||||
3529 | double nsGlobalWindowInner::GetDesktopToDeviceScale(ErrorResult& aError) { | |||
3530 | ENSURE_ACTIVE_DOCUMENT(aError, 0.0)do { if ((__builtin_expect(!!(!HasActiveDocument()), 0))) { aError .Throw(NS_ERROR_XPC_SECURITY_MANAGER_VETO); return 0.0; } } while (0); | |||
3531 | nsPresContext* presContext = GetPresContextForRatio(mDoc); | |||
3532 | if (!presContext) { | |||
3533 | return 1.0; | |||
3534 | } | |||
3535 | return presContext->DeviceContext()->GetDesktopToDeviceScale().scale; | |||
3536 | } | |||
3537 | ||||
3538 | uint32_t nsGlobalWindowInner::RequestAnimationFrame( | |||
3539 | FrameRequestCallback& aCallback, ErrorResult& aError) { | |||
3540 | if (!mDoc) { | |||
3541 | return 0; | |||
3542 | } | |||
3543 | ||||
3544 | if (GetWrapperPreserveColor()) { | |||
3545 | js::NotifyAnimationActivity(GetWrapperPreserveColor()); | |||
3546 | } | |||
3547 | ||||
3548 | DebuggerNotificationDispatch(this, | |||
3549 | DebuggerNotificationType::RequestAnimationFrame); | |||
3550 | ||||
3551 | uint32_t handle; | |||
3552 | aError = mDoc->ScheduleFrameRequestCallback(aCallback, &handle); | |||
3553 | return handle; | |||
3554 | } | |||
3555 | ||||
3556 | void nsGlobalWindowInner::CancelAnimationFrame(uint32_t aHandle, | |||
3557 | ErrorResult& aError) { | |||
3558 | if (!mDoc) { | |||
3559 | return; | |||
3560 | } | |||
3561 | ||||
3562 | DebuggerNotificationDispatch(this, | |||
3563 | DebuggerNotificationType::CancelAnimationFrame); | |||
3564 | ||||
3565 | mDoc->CancelFrameRequestCallback(aHandle); | |||
3566 | } | |||
3567 | ||||
3568 | already_AddRefed<MediaQueryList> nsGlobalWindowInner::MatchMedia( | |||
3569 | const nsACString& aMediaQueryList, CallerType aCallerType, | |||
3570 | ErrorResult& aError) { | |||
3571 | ENSURE_ACTIVE_DOCUMENT(aError, nullptr)do { if ((__builtin_expect(!!(!HasActiveDocument()), 0))) { aError .Throw(NS_ERROR_XPC_SECURITY_MANAGER_VETO); return nullptr; } } while (0); | |||
3572 | return mDoc->MatchMedia(aMediaQueryList, aCallerType); | |||
3573 | } | |||
3574 | ||||
3575 | int32_t nsGlobalWindowInner::GetScrollMinX(ErrorResult& aError) { | |||
3576 | FORWARD_TO_OUTER_OR_THROW(GetScrollBoundaryOuter, (eSideLeft), aError, 0); | |||
3577 | } | |||
3578 | ||||
3579 | int32_t nsGlobalWindowInner::GetScrollMinY(ErrorResult& aError) { | |||
3580 | FORWARD_TO_OUTER_OR_THROW(GetScrollBoundaryOuter, (eSideTop), aError, 0); | |||
3581 | } | |||
3582 | ||||
3583 | int32_t nsGlobalWindowInner::GetScrollMaxX(ErrorResult& aError) { | |||
3584 | FORWARD_TO_OUTER_OR_THROW(GetScrollBoundaryOuter, (eSideRight), aError, 0); | |||
3585 | } | |||
3586 | ||||
3587 | int32_t nsGlobalWindowInner::GetScrollMaxY(ErrorResult& aError) { | |||
3588 | FORWARD_TO_OUTER_OR_THROW(GetScrollBoundaryOuter, (eSideBottom), aError, 0); | |||
3589 | } | |||
3590 | ||||
3591 | double nsGlobalWindowInner::GetScrollX(ErrorResult& aError) { | |||
3592 | FORWARD_TO_OUTER_OR_THROW(GetScrollXOuter, (), aError, 0); | |||
3593 | } | |||
3594 | ||||
3595 | double nsGlobalWindowInner::GetScrollY(ErrorResult& aError) { | |||
3596 | FORWARD_TO_OUTER_OR_THROW(GetScrollYOuter, (), aError, 0); | |||
3597 | } | |||
3598 | ||||
3599 | uint32_t nsGlobalWindowInner::Length() { FORWARD_TO_OUTER(Length, (), 0); } | |||
3600 | ||||
3601 | Nullable<WindowProxyHolder> nsGlobalWindowInner::GetTop( | |||
3602 | mozilla::ErrorResult& aError) { | |||
3603 | FORWARD_TO_OUTER_OR_THROW(GetTopOuter, (), aError, nullptr); | |||
3604 | } | |||
3605 | ||||
3606 | already_AddRefed<BrowsingContext> nsGlobalWindowInner::GetChildWindow( | |||
3607 | const nsAString& aName) { | |||
3608 | if (GetOuterWindowInternal()) { | |||
3609 | return GetOuterWindowInternal()->GetChildWindow(aName); | |||
3610 | } | |||
3611 | return nullptr; | |||
3612 | } | |||
3613 | ||||
3614 | void nsGlobalWindowInner::RefreshRealmPrincipal() { | |||
3615 | JS::SetRealmPrincipals(js::GetNonCCWObjectRealm(GetWrapperPreserveColor()), | |||
3616 | nsJSPrincipals::get(mDoc->NodePrincipal())); | |||
3617 | } | |||
3618 | ||||
3619 | void nsGlobalWindowInner::RefreshReduceTimerPrecisionCallerType() { | |||
3620 | JS::SetRealmReduceTimerPrecisionCallerType( | |||
3621 | js::GetNonCCWObjectRealm(GetWrapperPreserveColor()), | |||
3622 | RTPCallerTypeToToken(GetRTPCallerType())); | |||
3623 | } | |||
3624 | ||||
3625 | already_AddRefed<nsIWidget> nsGlobalWindowInner::GetMainWidget() { | |||
3626 | FORWARD_TO_OUTER(GetMainWidget, (), nullptr); | |||
3627 | } | |||
3628 | ||||
3629 | nsIWidget* nsGlobalWindowInner::GetNearestWidget() const { | |||
3630 | if (GetOuterWindowInternal()) { | |||
3631 | return GetOuterWindowInternal()->GetNearestWidget(); | |||
3632 | } | |||
3633 | return nullptr; | |||
3634 | } | |||
3635 | ||||
3636 | void nsGlobalWindowInner::SetFullScreen(bool aFullscreen, | |||
3637 | mozilla::ErrorResult& aError) { | |||
3638 | FORWARD_TO_OUTER_OR_THROW(SetFullscreenOuter, (aFullscreen, aError), aError, | |||
3639 | /* void */); | |||
3640 | } | |||
3641 | ||||
3642 | bool nsGlobalWindowInner::GetFullScreen(ErrorResult& aError) { | |||
3643 | FORWARD_TO_OUTER_OR_THROW(GetFullscreenOuter, (), aError, false); | |||
3644 | } | |||
3645 | ||||
3646 | bool nsGlobalWindowInner::GetFullScreen() { | |||
3647 | ErrorResult dummy; | |||
3648 | bool fullscreen = GetFullScreen(dummy); | |||
3649 | dummy.SuppressException(); | |||
3650 | return fullscreen; | |||
3651 | } | |||
3652 | ||||
3653 | void nsGlobalWindowInner::Dump(const nsAString& aStr) { | |||
3654 | if (!nsJSUtils::DumpEnabled()) { | |||
3655 | return; | |||
3656 | } | |||
3657 | ||||
3658 | char* cstr = ToNewUTF8String(aStr); | |||
3659 | ||||
3660 | #if defined(XP_MACOSX) | |||
3661 | // have to convert \r to \n so that printing to the console works | |||
3662 | char *c = cstr, *cEnd = cstr + strlen(cstr); | |||
3663 | while (c < cEnd) { | |||
3664 | if (*c == '\r') *c = '\n'; | |||
3665 | c++; | |||
3666 | } | |||
3667 | #endif | |||
3668 | ||||
3669 | if (cstr) { | |||
3670 | MOZ_LOG(nsContentUtils::DOMDumpLog(), LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::DOMDumpLog(); if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail:: log_print(moz_real_module, LogLevel::Debug, "[Window.Dump] %s" , cstr); } } while (0) | |||
3671 | ("[Window.Dump] %s", cstr))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils ::DOMDumpLog(); if ((__builtin_expect(!!(mozilla::detail::log_test (moz_real_module, LogLevel::Debug)), 0))) { mozilla::detail:: log_print(moz_real_module, LogLevel::Debug, "[Window.Dump] %s" , cstr); } } while (0); | |||
3672 | #ifdef XP_WIN | |||
3673 | PrintToDebugger(cstr); | |||
3674 | #endif | |||
3675 | #ifdef ANDROID | |||
3676 | __android_log_write(ANDROID_LOG_INFO, "GeckoDump", cstr); | |||
3677 | #endif | |||
3678 | FILE* fp = gDumpFile ? gDumpFile : stdoutstdout; | |||
3679 | fputs(cstr, fp); | |||
3680 | fflush(fp); | |||
3681 | free(cstr); | |||
3682 | } | |||
3683 | } | |||
3684 | ||||
3685 | void nsGlobalWindowInner::Alert(nsIPrincipal& aSubjectPrincipal, | |||
3686 | ErrorResult& aError) { | |||
3687 | Alert(u""_ns, aSubjectPrincipal, aError); | |||
3688 | } | |||
3689 | ||||
3690 | void nsGlobalWindowInner::Alert(const nsAString& aMessage, | |||
3691 | nsIPrincipal& aSubjectPrincipal, | |||
3692 | ErrorResult& aError) { | |||
3693 | FORWARD_TO_OUTER_OR_THROW(AlertOuter, (aMessage, aSubjectPrincipal, aError), | |||
3694 | aError, ); | |||
3695 | } | |||
3696 | ||||
3697 | bool nsGlobalWindowInner::Confirm(const nsAString& aMessage, | |||
3698 | nsIPrincipal& aSubjectPrincipal, | |||
3699 | ErrorResult& aError) { | |||
3700 | FORWARD_TO_OUTER_OR_THROW(ConfirmOuter, (aMessage, aSubjectPrincipal, aError), | |||
3701 | aError, false); | |||
3702 | } | |||
3703 | ||||
3704 | already_AddRefed<Promise> nsGlobalWindowInner::Fetch( | |||
3705 | const RequestOrUTF8String& aInput, const RequestInit& aInit, | |||
3706 | CallerType aCallerType, ErrorResult& aRv) { | |||
3707 | return FetchRequest(this, aInput, aInit, aCallerType, aRv); | |||
3708 | } | |||
3709 | ||||
3710 | void nsGlobalWindowInner::Prompt(const nsAString& aMessage, | |||
3711 | const nsAString& aInitial, nsAString& aReturn, | |||
3712 | nsIPrincipal& aSubjectPrincipal, | |||
3713 | ErrorResult& aError) { | |||
3714 | FORWARD_TO_OUTER_OR_THROW( | |||
3715 | PromptOuter, (aMessage, aInitial, aReturn, aSubjectPrincipal, aError), | |||
3716 | aError, ); | |||
3717 | } | |||
3718 | ||||
3719 | void nsGlobalWindowInner::Focus(CallerType aCallerType, ErrorResult& aError) { | |||
3720 | FORWARD_TO_OUTER_OR_THROW(FocusOuter, | |||
3721 | (aCallerType, /* aFromOtherProcess */ false, | |||
3722 | nsFocusManager::GenerateFocusActionId()), | |||
3723 | aError, ); | |||
3724 | } | |||
3725 | ||||
3726 | nsresult nsGlobalWindowInner::Focus(CallerType aCallerType) { | |||
3727 | ErrorResult rv; | |||
3728 | Focus(aCallerType, rv); | |||
3729 | ||||
3730 | return rv.StealNSResult(); | |||
3731 | } | |||
3732 | ||||
3733 | void nsGlobalWindowInner::Blur(CallerType aCallerType, ErrorResult& aError) { | |||
3734 | FORWARD_TO_OUTER_OR_THROW(BlurOuter, (aCallerType), aError, ); | |||
3735 | } | |||
3736 | ||||
3737 | void nsGlobalWindowInner::Stop(ErrorResult& aError) { | |||
3738 | FORWARD_TO_OUTER_OR_THROW(StopOuter, (aError), aError, ); | |||
3739 | } | |||
3740 | ||||
3741 | void nsGlobalWindowInner::Print(ErrorResult& aError) { | |||
3742 | FORWARD_TO_OUTER_OR_THROW(PrintOuter, (aError), aError, ); | |||
3743 | } | |||
3744 | ||||
3745 | Nullable<WindowProxyHolder> nsGlobalWindowInner::PrintPreview( | |||
3746 | nsIPrintSettings* aSettings, nsIWebProgressListener* aListener, | |||
3747 | nsIDocShell* aDocShellToCloneInto, ErrorResult& aError) { | |||
3748 | FORWARD_TO_OUTER_OR_THROW( | |||
3749 | Print, | |||
3750 | (aSettings, | |||
3751 | /* aRemotePrintJob = */ nullptr, aListener, aDocShellToCloneInto, | |||
3752 | nsGlobalWindowOuter::IsPreview::Yes, | |||
3753 | nsGlobalWindowOuter::IsForWindowDotPrint::No, | |||
3754 | /* aPrintPreviewCallback = */ nullptr, nullptr, aError), | |||
3755 | aError, nullptr); | |||
3756 | } | |||
3757 | ||||
3758 | void nsGlobalWindowInner::MoveTo(int32_t aXPos, int32_t aYPos, | |||
3759 | CallerType aCallerType, ErrorResult& aError) { | |||
3760 | FORWARD_TO_OUTER_OR_THROW(MoveToOuter, (aXPos, aYPos, aCallerType, aError), | |||
3761 | aError, ); | |||
3762 | } | |||
3763 | ||||
3764 | void nsGlobalWindowInner::MoveBy(int32_t aXDif, int32_t aYDif, | |||
3765 | CallerType aCallerType, ErrorResult& aError) { | |||
3766 | FORWARD_TO_OUTER_OR_THROW(MoveByOuter, (aXDif, aYDif, aCallerType, aError), | |||
3767 | aError, ); | |||
3768 | } | |||
3769 | ||||
3770 | void nsGlobalWindowInner::ResizeTo(int32_t aWidth, int32_t aHeight, | |||
3771 | CallerType aCallerType, | |||
3772 | ErrorResult& aError) { | |||
3773 | FORWARD_TO_OUTER_OR_THROW(ResizeToOuter, | |||
3774 | (aWidth, aHeight, aCallerType, aError), aError, ); | |||
3775 | } | |||
3776 | ||||
3777 | void nsGlobalWindowInner::ResizeBy(int32_t aWidthDif, int32_t aHeightDif, | |||
3778 | CallerType aCallerType, | |||
3779 | ErrorResult& aError) { | |||
3780 | FORWARD_TO_OUTER_OR_THROW( | |||
3781 | ResizeByOuter, (aWidthDif, aHeightDif, aCallerType, aError), aError, ); | |||
3782 | } | |||
3783 | ||||
3784 | void nsGlobalWindowInner::SizeToContent(CallerType aCallerType, | |||
3785 | ErrorResult& aError) { | |||
3786 | FORWARD_TO_OUTER_OR_THROW(SizeToContentOuter, (aCallerType, {}, aError), | |||
3787 | aError, ); | |||
3788 | } | |||
3789 | ||||
3790 | void nsGlobalWindowInner::SizeToContentConstrained( | |||
3791 | const SizeToContentConstraints& aConstraints, ErrorResult& aError) { | |||
3792 | FORWARD_TO_OUTER_OR_THROW( | |||
3793 | SizeToContentOuter, (CallerType::System, aConstraints, aError), aError, ); | |||
3794 | } | |||
3795 | ||||
3796 | already_AddRefed<nsPIWindowRoot> nsGlobalWindowInner::GetTopWindowRoot() { | |||
3797 | nsGlobalWindowOuter* outer = GetOuterWindowInternal(); | |||
3798 | if (!outer) { | |||
3799 | return nullptr; | |||
3800 | } | |||
3801 | return outer->GetTopWindowRoot(); | |||
3802 | } | |||
3803 | ||||
3804 | void nsGlobalWindowInner::ScrollTo(double aXScroll, double aYScroll) { | |||
3805 | ScrollToOptions options; | |||
3806 | options.mLeft.Construct(aXScroll); | |||
3807 | options.mTop.Construct(aYScroll); | |||
3808 | ScrollTo(options); | |||
3809 | } | |||
3810 | ||||
3811 | void nsGlobalWindowInner::ScrollTo(const ScrollToOptions& aOptions) { | |||
3812 | Maybe<int32_t> left; | |||
3813 | Maybe<int32_t> top; | |||
3814 | if (aOptions.mLeft.WasPassed()) { | |||
3815 | left.emplace(static_cast<int32_t>( | |||
3816 | mozilla::ToZeroIfNonfinite(aOptions.mLeft.Value()))); | |||
3817 | } | |||
3818 | if (aOptions.mTop.WasPassed()) { | |||
3819 | top.emplace(static_cast<int32_t>( | |||
3820 | mozilla::ToZeroIfNonfinite(aOptions.mTop.Value()))); | |||
3821 | } | |||
3822 | ||||
3823 | // When scrolling to a non-zero offset, we need to determine whether that | |||
3824 | // position is within our scrollable range, so we need updated layout | |||
3825 | // information. | |||
3826 | if ((top && *top != 0) || (left && *left != 0)) { | |||
3827 | FlushPendingNotifications(FlushType::Layout); | |||
3828 | } | |||
3829 | ||||
3830 | ScrollContainerFrame* sf = GetScrollContainerFrame(); | |||
3831 | if (!sf) { | |||
3832 | return; | |||
3833 | } | |||
3834 | CSSIntPoint scrollPos = sf->GetRoundedScrollPositionCSSPixels(); | |||
3835 | if (left) { | |||
3836 | scrollPos.x = *left; | |||
3837 | } | |||
3838 | if (top) { | |||
3839 | scrollPos.y = *top; | |||
3840 | } | |||
3841 | // Here we calculate what the max pixel value is that we can | |||
3842 | // scroll to, we do this by dividing maxint with the pixel to | |||
3843 | // twips conversion factor, and subtracting 4, the 4 comes from | |||
3844 | // experimenting with this value, anything less makes the view | |||
3845 | // code not scroll correctly, I have no idea why. -- jst | |||
3846 | const int32_t maxpx = nsPresContext::AppUnitsToIntCSSPixels(0x7fffffff) - 4; | |||
3847 | if (scrollPos.x > maxpx) { | |||
3848 | scrollPos.x = maxpx; | |||
3849 | } | |||
3850 | if (scrollPos.y > maxpx) { | |||
3851 | scrollPos.y = maxpx; | |||
3852 | } | |||
3853 | auto scrollMode = sf->IsSmoothScroll(aOptions.mBehavior) | |||
3854 | ? ScrollMode::SmoothMsd | |||
3855 | : ScrollMode::Instant; | |||
3856 | sf->ScrollToCSSPixels(scrollPos, scrollMode); | |||
3857 | } | |||
3858 | ||||
3859 | void nsGlobalWindowInner::ScrollBy(double aXScrollDif, double aYScrollDif) { | |||
3860 | ScrollToOptions options; | |||
3861 | options.mLeft.Construct(aXScrollDif); | |||
3862 | options.mTop.Construct(aYScrollDif); | |||
3863 | // It seems like it would make more sense for ScrollBy to use | |||
3864 | // SMOOTH mode, but tests seem to depend on the synchronous behaviour. | |||
3865 | // Perhaps Web content does too. | |||
3866 | ScrollBy(options); | |||
3867 | } | |||
3868 | ||||
3869 | void nsGlobalWindowInner::ScrollBy(const ScrollToOptions& aOptions) { | |||
3870 | CSSIntPoint scrollDelta; | |||
3871 | if (aOptions.mLeft.WasPassed()) { | |||
3872 | scrollDelta.x = static_cast<int32_t>( | |||
3873 | mozilla::ToZeroIfNonfinite(aOptions.mLeft.Value())); | |||
3874 | } | |||
3875 | if (aOptions.mTop.WasPassed()) { | |||
3876 | scrollDelta.y = | |||
3877 | static_cast<int32_t>(mozilla::ToZeroIfNonfinite(aOptions.mTop.Value())); | |||
3878 | } | |||
3879 | ||||
3880 | if (!scrollDelta.x && !scrollDelta.y) { | |||
3881 | return; | |||
3882 | } | |||
3883 | ||||
3884 | FlushPendingNotifications(FlushType::Layout); | |||
3885 | ScrollContainerFrame* sf = GetScrollContainerFrame(); | |||
3886 | if (!sf) { | |||
3887 | return; | |||
3888 | } | |||
3889 | ||||
3890 | auto scrollMode = sf->IsSmoothScroll(aOptions.mBehavior) | |||
3891 | ? ScrollMode::SmoothMsd | |||
3892 | : ScrollMode::Instant; | |||
3893 | sf->ScrollByCSSPixels(scrollDelta, scrollMode); | |||
3894 | } | |||
3895 | ||||
3896 | void nsGlobalWindowInner::ScrollByLines(int32_t numLines, | |||
3897 | const ScrollOptions& aOptions) { | |||
3898 | if (!numLines) { | |||
3899 | return; | |||
3900 | } | |||
3901 | FlushPendingNotifications(FlushType::Layout); | |||
3902 | ScrollContainerFrame* sf = GetScrollContainerFrame(); | |||
3903 | if (!sf) { | |||
3904 | return; | |||
3905 | } | |||
3906 | // It seems like it would make more sense for ScrollByLines to use | |||
3907 | // SMOOTH mode, but tests seem to depend on the synchronous behaviour. | |||
3908 | // Perhaps Web content does too. | |||
3909 | ScrollMode scrollMode = sf->IsSmoothScroll(aOptions.mBehavior) | |||
3910 | ? ScrollMode::SmoothMsd | |||
3911 | : ScrollMode::Instant; | |||
3912 | sf->ScrollBy(nsIntPoint(0, numLines), ScrollUnit::LINES, scrollMode); | |||
3913 | } | |||
3914 | ||||
3915 | void nsGlobalWindowInner::ScrollByPages(int32_t numPages, | |||
3916 | const ScrollOptions& aOptions) { | |||
3917 | if (!numPages) { | |||
3918 | return; | |||
3919 | } | |||
3920 | FlushPendingNotifications(FlushType::Layout); | |||
3921 | ScrollContainerFrame* sf = GetScrollContainerFrame(); | |||
3922 | if (!sf) { | |||
3923 | return; | |||
3924 | } | |||
3925 | // It seems like it would make more sense for ScrollByPages to use | |||
3926 | // SMOOTH mode, but tests seem to depend on the synchronous behaviour. | |||
3927 | // Perhaps Web content does too. | |||
3928 | ScrollMode scrollMode = sf->IsSmoothScroll(aOptions.mBehavior) | |||
3929 | ? ScrollMode::SmoothMsd | |||
3930 | : ScrollMode::Instant; | |||
3931 | ||||
3932 | sf->ScrollBy(nsIntPoint(0, numPages), ScrollUnit::PAGES, scrollMode); | |||
3933 | } | |||
3934 | ||||
3935 | void nsGlobalWindowInner::MozScrollSnap() { | |||
3936 | FlushPendingNotifications(FlushType::Layout); | |||
3937 | if (ScrollContainerFrame* sf = GetScrollContainerFrame()) { | |||
3938 | sf->ScrollSnap(); | |||
3939 | } | |||
3940 | } | |||
3941 | ||||
3942 | void nsGlobalWindowInner::ClearTimeout(int32_t aHandle) { | |||
3943 | DebuggerNotificationDispatch(this, DebuggerNotificationType::ClearTimeout); | |||
3944 | ||||
3945 | if (aHandle > 0) { | |||
3946 | mTimeoutManager->ClearTimeout(aHandle, Timeout::Reason::eTimeoutOrInterval); | |||
3947 | } | |||
3948 | } | |||
3949 | ||||
3950 | void nsGlobalWindowInner::ClearInterval(int32_t aHandle) { | |||
3951 | DebuggerNotificationDispatch(this, DebuggerNotificationType::ClearInterval); | |||
3952 | ||||
3953 | if (aHandle > 0) { | |||
3954 | mTimeoutManager->ClearTimeout(aHandle, Timeout::Reason::eTimeoutOrInterval); | |||
3955 | } | |||
3956 | } | |||
3957 | ||||
3958 | void nsGlobalWindowInner::SetResizable(bool aResizable) const { | |||
3959 | // nop | |||
3960 | } | |||
3961 | ||||
3962 | void nsGlobalWindowInner::CaptureEvents() { | |||
3963 | if (mDoc) { | |||
3964 | mDoc->WarnOnceAbout(DeprecatedOperations::eUseOfCaptureEvents); | |||
3965 | } | |||
3966 | } | |||
3967 | ||||
3968 | void nsGlobalWindowInner::ReleaseEvents() { | |||
3969 | if (mDoc) { | |||
3970 | mDoc->WarnOnceAbout(DeprecatedOperations::eUseOfReleaseEvents); | |||
3971 | } | |||
3972 | } | |||
3973 | ||||
3974 | Nullable<WindowProxyHolder> nsGlobalWindowInner::Open(const nsAString& aUrl, | |||
3975 | const nsAString& aName, | |||
3976 | const nsAString& aOptions, | |||
3977 | ErrorResult& aError) { | |||
3978 | FORWARD_TO_OUTER_OR_THROW(OpenOuter, (aUrl, aName, aOptions, aError), aError, | |||
3979 | nullptr); | |||
3980 | } | |||
3981 | ||||
3982 | Nullable<WindowProxyHolder> nsGlobalWindowInner::OpenDialog( | |||
3983 | JSContext* aCx, const nsAString& aUrl, const nsAString& aName, | |||
3984 | const nsAString& aOptions, const Sequence<JS::Value>& aExtraArgument, | |||
3985 | ErrorResult& aError) { | |||
3986 | FORWARD_TO_OUTER_OR_THROW( | |||
3987 | OpenDialogOuter, (aCx, aUrl, aName, aOptions, aExtraArgument, aError), | |||
3988 | aError, nullptr); | |||
3989 | } | |||
3990 | ||||
3991 | WindowProxyHolder nsGlobalWindowInner::GetFrames(ErrorResult& aError) { | |||
3992 | FORWARD_TO_OUTER_OR_THROW(GetFramesOuter, (), aError, Window()); | |||
3993 | } | |||
3994 | ||||
3995 | void nsGlobalWindowInner::PostMessageMoz(JSContext* aCx, | |||
3996 | JS::Handle<JS::Value> aMessage, | |||
3997 | const nsAString& aTargetOrigin, | |||
3998 | JS::Handle<JS::Value> aTransfer, | |||
3999 | nsIPrincipal& aSubjectPrincipal, | |||
4000 | ErrorResult& aError) { | |||
4001 | FORWARD_TO_OUTER_OR_THROW( | |||
4002 | PostMessageMozOuter, | |||
4003 | (aCx, aMessage, aTargetOrigin, aTransfer, aSubjectPrincipal, aError), | |||
4004 | aError, ); | |||
4005 | } | |||
4006 | ||||
4007 | void nsGlobalWindowInner::PostMessageMoz(JSContext* aCx, | |||
4008 | JS::Handle<JS::Value> aMessage, | |||
4009 | const nsAString& aTargetOrigin, | |||
4010 | const Sequence<JSObject*>& aTransfer, | |||
4011 | nsIPrincipal& aSubjectPrincipal, | |||
4012 | ErrorResult& aRv) { | |||
4013 | JS::Rooted<JS::Value> transferArray(aCx, JS::UndefinedValue()); | |||
4014 | ||||
4015 | aRv = nsContentUtils::CreateJSValueFromSequenceOfObject(aCx, aTransfer, | |||
4016 | &transferArray); | |||
4017 | if (NS_WARN_IF(aRv.Failed())NS_warn_if_impl(aRv.Failed(), "aRv.Failed()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 4017)) { | |||
4018 | return; | |||
4019 | } | |||
4020 | ||||
4021 | PostMessageMoz(aCx, aMessage, aTargetOrigin, transferArray, aSubjectPrincipal, | |||
4022 | aRv); | |||
4023 | } | |||
4024 | ||||
4025 | void nsGlobalWindowInner::PostMessageMoz( | |||
4026 | JSContext* aCx, JS::Handle<JS::Value> aMessage, | |||
4027 | const WindowPostMessageOptions& aOptions, nsIPrincipal& aSubjectPrincipal, | |||
4028 | ErrorResult& aRv) { | |||
4029 | JS::Rooted<JS::Value> transferArray(aCx, JS::UndefinedValue()); | |||
4030 | ||||
4031 | aRv = nsContentUtils::CreateJSValueFromSequenceOfObject( | |||
4032 | aCx, aOptions.mTransfer, &transferArray); | |||
4033 | if (NS_WARN_IF(aRv.Failed())NS_warn_if_impl(aRv.Failed(), "aRv.Failed()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 4033)) { | |||
4034 | return; | |||
4035 | } | |||
4036 | ||||
4037 | PostMessageMoz(aCx, aMessage, aOptions.mTargetOrigin, transferArray, | |||
4038 | aSubjectPrincipal, aRv); | |||
4039 | } | |||
4040 | ||||
4041 | void nsGlobalWindowInner::Close(CallerType aCallerType, ErrorResult& aError) { | |||
4042 | FORWARD_TO_OUTER_OR_THROW(CloseOuter, (aCallerType == CallerType::System), | |||
4043 | aError, ); | |||
4044 | } | |||
4045 | ||||
4046 | nsresult nsGlobalWindowInner::Close() { | |||
4047 | FORWARD_TO_OUTER(Close, (), NS_ERROR_UNEXPECTED); | |||
4048 | } | |||
4049 | ||||
4050 | bool nsGlobalWindowInner::IsInModalState() { | |||
4051 | FORWARD_TO_OUTER(IsInModalState, (), false); | |||
4052 | } | |||
4053 | ||||
4054 | // static | |||
4055 | void nsGlobalWindowInner::NotifyDOMWindowDestroyed( | |||
4056 | nsGlobalWindowInner* aWindow) { | |||
4057 | nsCOMPtr<nsIObserverService> observerService = services::GetObserverService(); | |||
4058 | if (observerService) { | |||
4059 | observerService->NotifyObservers(ToSupports(aWindow), | |||
4060 | DOM_WINDOW_DESTROYED_TOPIC"dom-window-destroyed", nullptr); | |||
4061 | } | |||
4062 | } | |||
4063 | ||||
4064 | void nsGlobalWindowInner::NotifyWindowIDDestroyed(const char* aTopic) { | |||
4065 | nsCOMPtr<nsIRunnable> runnable = | |||
4066 | new WindowDestroyedEvent(this, mWindowID, aTopic); | |||
4067 | Dispatch(runnable.forget()); | |||
4068 | } | |||
4069 | ||||
4070 | // static | |||
4071 | void nsGlobalWindowInner::NotifyDOMWindowFrozen(nsGlobalWindowInner* aWindow) { | |||
4072 | if (aWindow) { | |||
4073 | nsCOMPtr<nsIObserverService> observerService = | |||
4074 | services::GetObserverService(); | |||
4075 | if (observerService) { | |||
4076 | observerService->NotifyObservers(ToSupports(aWindow), | |||
4077 | DOM_WINDOW_FROZEN_TOPIC"dom-window-frozen", nullptr); | |||
4078 | } | |||
4079 | } | |||
4080 | } | |||
4081 | ||||
4082 | // static | |||
4083 | void nsGlobalWindowInner::NotifyDOMWindowThawed(nsGlobalWindowInner* aWindow) { | |||
4084 | if (aWindow) { | |||
4085 | nsCOMPtr<nsIObserverService> observerService = | |||
4086 | services::GetObserverService(); | |||
4087 | if (observerService) { | |||
4088 | observerService->NotifyObservers(ToSupports(aWindow), | |||
4089 | DOM_WINDOW_THAWED_TOPIC"dom-window-thawed", nullptr); | |||
4090 | } | |||
4091 | } | |||
4092 | } | |||
4093 | ||||
4094 | Element* nsGlobalWindowInner::GetFrameElement(nsIPrincipal& aSubjectPrincipal, | |||
4095 | ErrorResult& aError) { | |||
4096 | FORWARD_TO_OUTER_OR_THROW(GetFrameElement, (aSubjectPrincipal), aError, | |||
4097 | nullptr); | |||
4098 | } | |||
4099 | ||||
4100 | Element* nsGlobalWindowInner::GetRealFrameElement(ErrorResult& aError) { | |||
4101 | FORWARD_TO_OUTER_OR_THROW(GetFrameElement, (), aError, nullptr); | |||
4102 | } | |||
4103 | ||||
4104 | void nsGlobalWindowInner::UpdateCommands(const nsAString& anAction) { | |||
4105 | if (GetOuterWindowInternal()) { | |||
4106 | GetOuterWindowInternal()->UpdateCommands(anAction); | |||
4107 | } | |||
4108 | } | |||
4109 | ||||
4110 | Selection* nsGlobalWindowInner::GetSelection(ErrorResult& aError) { | |||
4111 | FORWARD_TO_OUTER_OR_THROW(GetSelectionOuter, (), aError, nullptr); | |||
4112 | } | |||
4113 | ||||
4114 | WebTaskScheduler* nsGlobalWindowInner::Scheduler() { | |||
4115 | if (!mWebTaskScheduler) { | |||
4116 | mWebTaskScheduler = WebTaskScheduler::CreateForMainThread(this); | |||
4117 | } | |||
4118 | MOZ_ASSERT(mWebTaskScheduler)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mWebTaskScheduler)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mWebTaskScheduler))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mWebTaskScheduler" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 4118); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mWebTaskScheduler" ")"); do { *((volatile int*)__null) = 4118; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
4119 | return mWebTaskScheduler; | |||
4120 | } | |||
4121 | ||||
4122 | bool nsGlobalWindowInner::Find(const nsAString& aString, bool aCaseSensitive, | |||
4123 | bool aBackwards, bool aWrapAround, | |||
4124 | bool aWholeWord, bool aSearchInFrames, | |||
4125 | bool aShowDialog, ErrorResult& aError) { | |||
4126 | FORWARD_TO_OUTER_OR_THROW(FindOuter, | |||
4127 | (aString, aCaseSensitive, aBackwards, aWrapAround, | |||
4128 | aWholeWord, aSearchInFrames, aShowDialog, aError), | |||
4129 | aError, false); | |||
4130 | } | |||
4131 | ||||
4132 | void nsGlobalWindowInner::GetOrigin(nsAString& aOrigin) { | |||
4133 | nsContentUtils::GetWebExposedOriginSerialization(GetPrincipal(), aOrigin); | |||
4134 | } | |||
4135 | ||||
4136 | // See also AutoJSAPI::ReportException | |||
4137 | void nsGlobalWindowInner::ReportError(JSContext* aCx, | |||
4138 | JS::Handle<JS::Value> aError, | |||
4139 | CallerType aCallerType, | |||
4140 | ErrorResult& aRv) { | |||
4141 | if (MOZ_UNLIKELY(!HasActiveDocument())(__builtin_expect(!!(!HasActiveDocument()), 0))) { | |||
4142 | return aRv.Throw(NS_ERROR_XPC_SECURITY_MANAGER_VETO); | |||
4143 | } | |||
4144 | ||||
4145 | JS::ErrorReportBuilder jsReport(aCx); | |||
4146 | JS::ExceptionStack exnStack(aCx, aError, nullptr); | |||
4147 | if (!jsReport.init(aCx, exnStack, JS::ErrorReportBuilder::NoSideEffects)) { | |||
4148 | return aRv.NoteJSContextException(aCx); | |||
4149 | } | |||
4150 | ||||
4151 | RefPtr<xpc::ErrorReport> xpcReport = new xpc::ErrorReport(); | |||
4152 | bool isChrome = aCallerType == CallerType::System; | |||
4153 | xpcReport->Init(jsReport.report(), jsReport.toStringResult().c_str(), | |||
4154 | isChrome, WindowID()); | |||
4155 | ||||
4156 | JS::RootingContext* rcx = JS::RootingContext::get(aCx); | |||
4157 | DispatchScriptErrorEvent(this, rcx, xpcReport, exnStack.exception(), | |||
4158 | exnStack.stack()); | |||
4159 | } | |||
4160 | ||||
4161 | void nsGlobalWindowInner::Atob(const nsAString& aAsciiBase64String, | |||
4162 | nsAString& aBinaryData, ErrorResult& aError) { | |||
4163 | aError = nsContentUtils::Atob(aAsciiBase64String, aBinaryData); | |||
4164 | } | |||
4165 | ||||
4166 | void nsGlobalWindowInner::Btoa(const nsAString& aBinaryData, | |||
4167 | nsAString& aAsciiBase64String, | |||
4168 | ErrorResult& aError) { | |||
4169 | aError = nsContentUtils::Btoa(aBinaryData, aAsciiBase64String); | |||
4170 | } | |||
4171 | ||||
4172 | //***************************************************************************** | |||
4173 | // EventTarget | |||
4174 | //***************************************************************************** | |||
4175 | ||||
4176 | nsPIDOMWindowOuter* nsGlobalWindowInner::GetOwnerGlobalForBindingsInternal() { | |||
4177 | return nsPIDOMWindowOuter::GetFromCurrentInner(this); | |||
4178 | } | |||
4179 | ||||
4180 | bool nsGlobalWindowInner::DispatchEvent(Event& aEvent, CallerType aCallerType, | |||
4181 | ErrorResult& aRv) { | |||
4182 | if (!IsCurrentInnerWindow()) { | |||
4183 | NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "DispatchEvent called on non-current inner window, dropping. " "Please check the window in the caller instead.", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 4185) | |||
4184 | "DispatchEvent called on non-current inner window, dropping. "NS_DebugBreak(NS_DEBUG_WARNING, "DispatchEvent called on non-current inner window, dropping. " "Please check the window in the caller instead.", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 4185) | |||
4185 | "Please check the window in the caller instead.")NS_DebugBreak(NS_DEBUG_WARNING, "DispatchEvent called on non-current inner window, dropping. " "Please check the window in the caller instead.", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 4185); | |||
4186 | aRv.Throw(NS_ERROR_FAILURE); | |||
4187 | return false; | |||
4188 | } | |||
4189 | ||||
4190 | if (!mDoc) { | |||
4191 | aRv.Throw(NS_ERROR_FAILURE); | |||
4192 | return false; | |||
4193 | } | |||
4194 | ||||
4195 | // Obtain a presentation shell | |||
4196 | RefPtr<nsPresContext> presContext = mDoc->GetPresContext(); | |||
4197 | ||||
4198 | nsEventStatus status = nsEventStatus_eIgnore; | |||
4199 | nsresult rv = EventDispatcher::DispatchDOMEvent(this, nullptr, &aEvent, | |||
4200 | presContext, &status); | |||
4201 | bool retval = !aEvent.DefaultPrevented(aCallerType); | |||
4202 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
4203 | aRv.Throw(rv); | |||
4204 | } | |||
4205 | return retval; | |||
4206 | } | |||
4207 | ||||
4208 | mozilla::Maybe<mozilla::dom::EventCallbackDebuggerNotificationType> | |||
4209 | nsGlobalWindowInner::GetDebuggerNotificationType() const { | |||
4210 | return mozilla::Some( | |||
4211 | mozilla::dom::EventCallbackDebuggerNotificationType::Global); | |||
4212 | } | |||
4213 | ||||
4214 | bool nsGlobalWindowInner::ComputeDefaultWantsUntrusted(ErrorResult& aRv) { | |||
4215 | return !nsContentUtils::IsChromeDoc(mDoc); | |||
4216 | } | |||
4217 | ||||
4218 | EventListenerManager* nsGlobalWindowInner::GetOrCreateListenerManager() { | |||
4219 | if (!mListenerManager) { | |||
4220 | mListenerManager = | |||
4221 | new EventListenerManager(static_cast<EventTarget*>(this)); | |||
4222 | } | |||
4223 | ||||
4224 | return mListenerManager; | |||
4225 | } | |||
4226 | ||||
4227 | EventListenerManager* nsGlobalWindowInner::GetExistingListenerManager() const { | |||
4228 | return mListenerManager; | |||
4229 | } | |||
4230 | ||||
4231 | mozilla::dom::DebuggerNotificationManager* | |||
4232 | nsGlobalWindowInner::GetOrCreateDebuggerNotificationManager() { | |||
4233 | if (!mDebuggerNotificationManager) { | |||
4234 | mDebuggerNotificationManager = new DebuggerNotificationManager(this); | |||
4235 | } | |||
4236 | ||||
4237 | return mDebuggerNotificationManager; | |||
4238 | } | |||
4239 | ||||
4240 | mozilla::dom::DebuggerNotificationManager* | |||
4241 | nsGlobalWindowInner::GetExistingDebuggerNotificationManager() { | |||
4242 | return mDebuggerNotificationManager; | |||
4243 | } | |||
4244 | ||||
4245 | //***************************************************************************** | |||
4246 | // nsGlobalWindowInner::nsPIDOMWindow | |||
4247 | //***************************************************************************** | |||
4248 | ||||
4249 | Location* nsGlobalWindowInner::Location() { | |||
4250 | if (!mLocation) { | |||
4251 | mLocation = new dom::Location(this); | |||
4252 | } | |||
4253 | ||||
4254 | return mLocation; | |||
4255 | } | |||
4256 | ||||
4257 | void nsGlobalWindowInner::MaybeUpdateTouchState() { | |||
4258 | if (mMayHaveTouchEventListener) { | |||
4259 | nsCOMPtr<nsIObserverService> observerService = | |||
4260 | services::GetObserverService(); | |||
4261 | ||||
4262 | if (observerService) { | |||
4263 | observerService->NotifyObservers(static_cast<nsIDOMWindow*>(this), | |||
4264 | DOM_TOUCH_LISTENER_ADDED"dom-touch-listener-added", nullptr); | |||
4265 | } | |||
4266 | } | |||
4267 | } | |||
4268 | ||||
4269 | void nsGlobalWindowInner::EnableGamepadUpdates() { | |||
4270 | if (mHasGamepad) { | |||
4271 | RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService()); | |||
4272 | if (gamepadManager) { | |||
4273 | gamepadManager->AddListener(this); | |||
4274 | } | |||
4275 | } | |||
4276 | } | |||
4277 | ||||
4278 | void nsGlobalWindowInner::DisableGamepadUpdates() { | |||
4279 | if (mHasGamepad) { | |||
4280 | RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService()); | |||
4281 | if (gamepadManager) { | |||
4282 | gamepadManager->RemoveListener(this); | |||
4283 | } | |||
4284 | } | |||
4285 | } | |||
4286 | ||||
4287 | void nsGlobalWindowInner::EnableVRUpdates() { | |||
4288 | // We need to create a VREventObserver before we can either detect XR runtimes | |||
4289 | // or start an XR session | |||
4290 | if (!mVREventObserver && (mHasXRSession || mXRRuntimeDetectionInFlight)) { | |||
4291 | // Assert that we are not creating the observer while IsDying() as | |||
4292 | // that would result in a leak. VREventObserver holds a RefPtr to | |||
4293 | // this nsGlobalWindowInner and would prevent it from being deallocated. | |||
4294 | MOZ_ASSERT(!IsDying(),do { static_assert( mozilla::detail::AssertionConditionType< decltype(!IsDying())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!IsDying()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!IsDying()" " (" "Creating a VREventObserver for an nsGlobalWindow that is " "dying would cause it to leak." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 4296); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDying()" ") (" "Creating a VREventObserver for an nsGlobalWindow that is " "dying would cause it to leak." ")"); do { *((volatile int*) __null) = 4296; __attribute__((nomerge)) ::abort(); } while ( false); } } while (false) | |||
4295 | "Creating a VREventObserver for an nsGlobalWindow that is "do { static_assert( mozilla::detail::AssertionConditionType< decltype(!IsDying())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!IsDying()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!IsDying()" " (" "Creating a VREventObserver for an nsGlobalWindow that is " "dying would cause it to leak." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 4296); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDying()" ") (" "Creating a VREventObserver for an nsGlobalWindow that is " "dying would cause it to leak." ")"); do { *((volatile int*) __null) = 4296; __attribute__((nomerge)) ::abort(); } while ( false); } } while (false) | |||
4296 | "dying would cause it to leak.")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!IsDying())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!IsDying()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!IsDying()" " (" "Creating a VREventObserver for an nsGlobalWindow that is " "dying would cause it to leak." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 4296); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDying()" ") (" "Creating a VREventObserver for an nsGlobalWindow that is " "dying would cause it to leak." ")"); do { *((volatile int*) __null) = 4296; __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); | |||
4297 | mVREventObserver = new VREventObserver(this); | |||
4298 | } | |||
4299 | // If the content has an XR session, then we need to tell | |||
4300 | // VREventObserver that there is VR activity. | |||
4301 | if (mHasXRSession) { | |||
4302 | nsPIDOMWindowOuter* outer = GetOuterWindow(); | |||
4303 | if (outer && !outer->IsBackground()) { | |||
4304 | StartVRActivity(); | |||
4305 | } | |||
4306 | } | |||
4307 | } | |||
4308 | ||||
4309 | void nsGlobalWindowInner::DisableVRUpdates() { | |||
4310 | if (mVREventObserver) { | |||
4311 | mVREventObserver->DisconnectFromOwner(); | |||
4312 | mVREventObserver = nullptr; | |||
4313 | } | |||
4314 | } | |||
4315 | ||||
4316 | void nsGlobalWindowInner::ResetVRTelemetry(bool aUpdate) { | |||
4317 | if (mVREventObserver) { | |||
4318 | mVREventObserver->UpdateSpentTimeIn2DTelemetry(aUpdate); | |||
4319 | } | |||
4320 | } | |||
4321 | ||||
4322 | void nsGlobalWindowInner::StartVRActivity() { | |||
4323 | /** | |||
4324 | * If the content has an XR session, tell | |||
4325 | * the VREventObserver that the window is accessing | |||
4326 | * VR devices. | |||
4327 | * | |||
4328 | * It's possible to have a VREventObserver without | |||
4329 | * and XR session, if we are using it to get updates | |||
4330 | * about XR runtime enumeration. In this case, | |||
4331 | * we would not tell the VREventObserver that | |||
4332 | * we are accessing VR devices. | |||
4333 | */ | |||
4334 | if (mVREventObserver && mHasXRSession) { | |||
4335 | mVREventObserver->StartActivity(); | |||
4336 | } | |||
4337 | } | |||
4338 | ||||
4339 | void nsGlobalWindowInner::StopVRActivity() { | |||
4340 | /** | |||
4341 | * If the content has an XR session, tell | |||
4342 | * the VReventObserver that the window is no longer | |||
4343 | * accessing VR devices. This does not stop the | |||
4344 | * XR session itself, which may be resumed with | |||
4345 | * EnableVRUpdates. | |||
4346 | * It's possible to have a VREventObserver without | |||
4347 | * and XR session, if we are using it to get updates | |||
4348 | * about XR runtime enumeration. In this case, | |||
4349 | * we would not tell the VREventObserver that | |||
4350 | * we ending an activity that accesses VR devices. | |||
4351 | */ | |||
4352 | if (mVREventObserver && mHasXRSession) { | |||
4353 | mVREventObserver->StopActivity(); | |||
4354 | } | |||
4355 | } | |||
4356 | ||||
4357 | void nsGlobalWindowInner::SetFocusedElement(Element* aElement, | |||
4358 | uint32_t aFocusMethod, | |||
4359 | bool aNeedsFocus) { | |||
4360 | if (aElement && aElement->GetComposedDoc() != mDoc) { | |||
4361 | NS_WARNING("Trying to set focus to a node from a wrong document")NS_DebugBreak(NS_DEBUG_WARNING, "Trying to set focus to a node from a wrong document" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 4361); | |||
4362 | return; | |||
4363 | } | |||
4364 | ||||
4365 | if (IsDying()) { | |||
4366 | NS_ASSERTION(!aElement, "Trying to focus cleaned up window!")do { if (!(!aElement)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Trying to focus cleaned up window!" , "!aElement", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 4366); MOZ_PretendNoReturn(); } } while (0); | |||
4367 | aElement = nullptr; | |||
4368 | aNeedsFocus = false; | |||
4369 | } | |||
4370 | if (mFocusedElement != aElement) { | |||
4371 | UpdateCanvasFocus(false, aElement); | |||
4372 | mFocusedElement = aElement; | |||
4373 | // TODO: Maybe this should be set on refocus too? | |||
4374 | mFocusMethod = aFocusMethod & nsIFocusManager::METHOD_MASK; | |||
4375 | } | |||
4376 | ||||
4377 | if (mFocusedElement) { | |||
4378 | // if a node was focused by a keypress, turn on focus rings for the | |||
4379 | // window. | |||
4380 | if (mFocusMethod & nsIFocusManager::FLAG_BYKEY) { | |||
4381 | mUnknownFocusMethodShouldShowOutline = true; | |||
4382 | mFocusByKeyOccurred = true; | |||
4383 | } else if (nsFocusManager::GetFocusMoveActionCause(mFocusMethod) != | |||
4384 | widget::InputContextAction::CAUSE_UNKNOWN) { | |||
4385 | mUnknownFocusMethodShouldShowOutline = false; | |||
4386 | } else if (aFocusMethod & nsIFocusManager::FLAG_NOSHOWRING) { | |||
4387 | // If we get focused via script, and script has explicitly opted out of | |||
4388 | // outlines via FLAG_NOSHOWRING, we don't want to make a refocus start | |||
4389 | // showing outlines. | |||
4390 | mUnknownFocusMethodShouldShowOutline = false; | |||
4391 | } | |||
4392 | } | |||
4393 | ||||
4394 | if (aNeedsFocus) { | |||
4395 | mNeedsFocus = aNeedsFocus; | |||
4396 | } | |||
4397 | } | |||
4398 | ||||
4399 | uint32_t nsGlobalWindowInner::GetFocusMethod() { return mFocusMethod; } | |||
4400 | ||||
4401 | bool nsGlobalWindowInner::ShouldShowFocusRing() { | |||
4402 | if (mFocusByKeyOccurred && | |||
4403 | StaticPrefs::browser_display_always_show_rings_after_key_focus()) { | |||
4404 | return true; | |||
4405 | } | |||
4406 | return StaticPrefs::browser_display_show_focus_rings(); | |||
4407 | } | |||
4408 | ||||
4409 | bool nsGlobalWindowInner::TakeFocus(bool aFocus, uint32_t aFocusMethod) { | |||
4410 | if (IsDying()) { | |||
4411 | return false; | |||
4412 | } | |||
4413 | ||||
4414 | if (aFocus) { | |||
4415 | mFocusMethod = aFocusMethod & nsIFocusManager::METHOD_MASK; | |||
4416 | } | |||
4417 | ||||
4418 | if (mHasFocus != aFocus) { | |||
4419 | mHasFocus = aFocus; | |||
4420 | UpdateCanvasFocus(true, mFocusedElement); | |||
4421 | } | |||
4422 | ||||
4423 | // if mNeedsFocus is true, then the document has not yet received a | |||
4424 | // document-level focus event. If there is a root content node, then return | |||
4425 | // true to tell the calling focus manager that a focus event is expected. If | |||
4426 | // there is no root content node, the document hasn't loaded enough yet, or | |||
4427 | // there isn't one and there is no point in firing a focus event. | |||
4428 | if (aFocus && mNeedsFocus && mDoc && mDoc->GetRootElement() != nullptr) { | |||
4429 | mNeedsFocus = false; | |||
4430 | return true; | |||
4431 | } | |||
4432 | ||||
4433 | mNeedsFocus = false; | |||
4434 | return false; | |||
4435 | } | |||
4436 | ||||
4437 | void nsGlobalWindowInner::SetReadyForFocus() { | |||
4438 | bool oldNeedsFocus = mNeedsFocus; | |||
4439 | mNeedsFocus = false; | |||
4440 | ||||
4441 | if (RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager()) { | |||
4442 | nsCOMPtr<nsPIDOMWindowOuter> outerWindow = GetOuterWindow(); | |||
4443 | fm->WindowShown(outerWindow, oldNeedsFocus); | |||
4444 | } | |||
4445 | } | |||
4446 | ||||
4447 | void nsGlobalWindowInner::PageHidden() { | |||
4448 | // the window is being hidden, so tell the focus manager that the frame is | |||
4449 | // no longer valid. Use the persisted field to determine if the document | |||
4450 | // is being destroyed. | |||
4451 | ||||
4452 | if (RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager()) { | |||
4453 | nsCOMPtr<nsPIDOMWindowOuter> outerWindow = GetOuterWindow(); | |||
4454 | fm->WindowHidden(outerWindow, nsFocusManager::GenerateFocusActionId()); | |||
4455 | } | |||
4456 | ||||
4457 | mNeedsFocus = true; | |||
4458 | } | |||
4459 | ||||
4460 | class HashchangeCallback : public Runnable { | |||
4461 | public: | |||
4462 | HashchangeCallback(const nsAString& aOldURL, const nsAString& aNewURL, | |||
4463 | nsGlobalWindowInner* aWindow) | |||
4464 | : mozilla::Runnable("HashchangeCallback"), mWindow(aWindow) { | |||
4465 | MOZ_ASSERT(mWindow)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mWindow)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mWindow))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mWindow", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 4465); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mWindow" ")" ); do { *((volatile int*)__null) = 4465; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
4466 | mOldURL.Assign(aOldURL); | |||
4467 | mNewURL.Assign(aNewURL); | |||
4468 | } | |||
4469 | ||||
4470 | NS_IMETHODvirtual nsresult Run() override { | |||
4471 | MOZ_ASSERT(NS_IsMainThread(), "Should be called on the main thread.")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "Should be called on the main thread." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 4471); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "Should be called on the main thread." ")"); do { *((volatile int*)__null) = 4471; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); | |||
4472 | return mWindow->FireHashchange(mOldURL, mNewURL); | |||
4473 | } | |||
4474 | ||||
4475 | private: | |||
4476 | nsString mOldURL; | |||
4477 | nsString mNewURL; | |||
4478 | RefPtr<nsGlobalWindowInner> mWindow; | |||
4479 | }; | |||
4480 | ||||
4481 | nsresult nsGlobalWindowInner::DispatchAsyncHashchange(nsIURI* aOldURI, | |||
4482 | nsIURI* aNewURI) { | |||
4483 | // Make sure that aOldURI and aNewURI are identical up to the '#', and that | |||
4484 | // their hashes are different. | |||
4485 | bool equal = false; | |||
4486 | NS_ENSURE_STATE(NS_SUCCEEDED(aOldURI->EqualsExceptRef(aNewURI, &equal)) &&do { if ((__builtin_expect(!!(!(((bool)(__builtin_expect(!!(! NS_FAILED_impl(aOldURI->EqualsExceptRef(aNewURI, &equal ))), 1))) && equal)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING , "NS_ENSURE_TRUE(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aOldURI->EqualsExceptRef(aNewURI, &equal))), 1))) && equal" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 4487); return NS_ERROR_UNEXPECTED; } } while (false) | |||
4487 | equal)do { if ((__builtin_expect(!!(!(((bool)(__builtin_expect(!!(! NS_FAILED_impl(aOldURI->EqualsExceptRef(aNewURI, &equal ))), 1))) && equal)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING , "NS_ENSURE_TRUE(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aOldURI->EqualsExceptRef(aNewURI, &equal))), 1))) && equal" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 4487); return NS_ERROR_UNEXPECTED; } } while (false); | |||
4488 | nsAutoCString oldHash, newHash; | |||
4489 | bool oldHasHash, newHasHash; | |||
4490 | NS_ENSURE_STATE(NS_SUCCEEDED(aOldURI->GetRef(oldHash)) &&do { if ((__builtin_expect(!!(!(((bool)(__builtin_expect(!!(! NS_FAILED_impl(aOldURI->GetRef(oldHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl(aNewURI->GetRef (newHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl (aOldURI->GetHasRef(&oldHasHash))), 1))) && (( bool)(__builtin_expect(!!(!NS_FAILED_impl(aNewURI->GetHasRef (&newHasHash))), 1))) && (oldHasHash != newHasHash || !oldHash.Equals(newHash)))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING , "NS_ENSURE_TRUE(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aOldURI->GetRef(oldHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl(aNewURI->GetRef(newHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl(aOldURI->GetHasRef(&oldHasHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl(aNewURI->GetHasRef(&newHasHash))), 1))) && (oldHasHash != newHasHash || !oldHash.Equals(newHash))" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 4494); return NS_ERROR_UNEXPECTED; } } while (false) | |||
4491 | NS_SUCCEEDED(aNewURI->GetRef(newHash)) &&do { if ((__builtin_expect(!!(!(((bool)(__builtin_expect(!!(! NS_FAILED_impl(aOldURI->GetRef(oldHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl(aNewURI->GetRef (newHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl (aOldURI->GetHasRef(&oldHasHash))), 1))) && (( bool)(__builtin_expect(!!(!NS_FAILED_impl(aNewURI->GetHasRef (&newHasHash))), 1))) && (oldHasHash != newHasHash || !oldHash.Equals(newHash)))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING , "NS_ENSURE_TRUE(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aOldURI->GetRef(oldHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl(aNewURI->GetRef(newHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl(aOldURI->GetHasRef(&oldHasHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl(aNewURI->GetHasRef(&newHasHash))), 1))) && (oldHasHash != newHasHash || !oldHash.Equals(newHash))" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 4494); return NS_ERROR_UNEXPECTED; } } while (false) | |||
4492 | NS_SUCCEEDED(aOldURI->GetHasRef(&oldHasHash)) &&do { if ((__builtin_expect(!!(!(((bool)(__builtin_expect(!!(! NS_FAILED_impl(aOldURI->GetRef(oldHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl(aNewURI->GetRef (newHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl (aOldURI->GetHasRef(&oldHasHash))), 1))) && (( bool)(__builtin_expect(!!(!NS_FAILED_impl(aNewURI->GetHasRef (&newHasHash))), 1))) && (oldHasHash != newHasHash || !oldHash.Equals(newHash)))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING , "NS_ENSURE_TRUE(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aOldURI->GetRef(oldHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl(aNewURI->GetRef(newHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl(aOldURI->GetHasRef(&oldHasHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl(aNewURI->GetHasRef(&newHasHash))), 1))) && (oldHasHash != newHasHash || !oldHash.Equals(newHash))" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 4494); return NS_ERROR_UNEXPECTED; } } while (false) | |||
4493 | NS_SUCCEEDED(aNewURI->GetHasRef(&newHasHash)) &&do { if ((__builtin_expect(!!(!(((bool)(__builtin_expect(!!(! NS_FAILED_impl(aOldURI->GetRef(oldHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl(aNewURI->GetRef (newHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl (aOldURI->GetHasRef(&oldHasHash))), 1))) && (( bool)(__builtin_expect(!!(!NS_FAILED_impl(aNewURI->GetHasRef (&newHasHash))), 1))) && (oldHasHash != newHasHash || !oldHash.Equals(newHash)))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING , "NS_ENSURE_TRUE(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aOldURI->GetRef(oldHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl(aNewURI->GetRef(newHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl(aOldURI->GetHasRef(&oldHasHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl(aNewURI->GetHasRef(&newHasHash))), 1))) && (oldHasHash != newHasHash || !oldHash.Equals(newHash))" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 4494); return NS_ERROR_UNEXPECTED; } } while (false) | |||
4494 | (oldHasHash != newHasHash || !oldHash.Equals(newHash)))do { if ((__builtin_expect(!!(!(((bool)(__builtin_expect(!!(! NS_FAILED_impl(aOldURI->GetRef(oldHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl(aNewURI->GetRef (newHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl (aOldURI->GetHasRef(&oldHasHash))), 1))) && (( bool)(__builtin_expect(!!(!NS_FAILED_impl(aNewURI->GetHasRef (&newHasHash))), 1))) && (oldHasHash != newHasHash || !oldHash.Equals(newHash)))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING , "NS_ENSURE_TRUE(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aOldURI->GetRef(oldHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl(aNewURI->GetRef(newHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl(aOldURI->GetHasRef(&oldHasHash))), 1))) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl(aNewURI->GetHasRef(&newHasHash))), 1))) && (oldHasHash != newHasHash || !oldHash.Equals(newHash))" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 4494); return NS_ERROR_UNEXPECTED; } } while (false); | |||
4495 | ||||
4496 | nsAutoCString oldSpec, newSpec; | |||
4497 | nsresult rv = aOldURI->GetSpec(oldSpec); | |||
4498 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 4498); return rv; } } while (false); | |||
4499 | rv = aNewURI->GetSpec(newSpec); | |||
4500 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 4500); return rv; } } while (false); | |||
4501 | ||||
4502 | NS_ConvertUTF8toUTF16 oldWideSpec(oldSpec); | |||
4503 | NS_ConvertUTF8toUTF16 newWideSpec(newSpec); | |||
4504 | ||||
4505 | nsCOMPtr<nsIRunnable> callback = | |||
4506 | new HashchangeCallback(oldWideSpec, newWideSpec, this); | |||
4507 | return Dispatch(callback.forget()); | |||
4508 | } | |||
4509 | ||||
4510 | nsresult nsGlobalWindowInner::FireHashchange(const nsAString& aOldURL, | |||
4511 | const nsAString& aNewURL) { | |||
4512 | // Don't do anything if the window is frozen. | |||
4513 | if (IsFrozen()) { | |||
4514 | return NS_OK; | |||
4515 | } | |||
4516 | ||||
4517 | // Get a presentation shell for use in creating the hashchange event. | |||
4518 | NS_ENSURE_STATE(IsCurrentInnerWindow())do { if ((__builtin_expect(!!(!(IsCurrentInnerWindow())), 0)) ) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "IsCurrentInnerWindow()" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 4518); return NS_ERROR_UNEXPECTED; } } while (false); | |||
4519 | ||||
4520 | HashChangeEventInit init; | |||
4521 | init.mNewURL = aNewURL; | |||
4522 | init.mOldURL = aOldURL; | |||
4523 | ||||
4524 | RefPtr<HashChangeEvent> event = | |||
4525 | HashChangeEvent::Constructor(this, u"hashchange"_ns, init); | |||
4526 | ||||
4527 | event->SetTrusted(true); | |||
4528 | ||||
4529 | ErrorResult rv; | |||
4530 | DispatchEvent(*event, rv); | |||
4531 | return rv.StealNSResult(); | |||
4532 | } | |||
4533 | ||||
4534 | nsresult nsGlobalWindowInner::DispatchSyncPopState() { | |||
4535 | NS_ASSERTION(nsContentUtils::IsSafeToRunScript(),do { if (!(nsContentUtils::IsSafeToRunScript())) { NS_DebugBreak (NS_DEBUG_ASSERTION, "Must be safe to run script here.", "nsContentUtils::IsSafeToRunScript()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 4536); MOZ_PretendNoReturn(); } } while (0) | |||
4536 | "Must be safe to run script here.")do { if (!(nsContentUtils::IsSafeToRunScript())) { NS_DebugBreak (NS_DEBUG_ASSERTION, "Must be safe to run script here.", "nsContentUtils::IsSafeToRunScript()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 4536); MOZ_PretendNoReturn(); } } while (0); | |||
4537 | ||||
4538 | // Bail if the window is frozen. | |||
4539 | if (IsFrozen()) { | |||
4540 | return NS_OK; | |||
4541 | } | |||
4542 | ||||
4543 | AutoJSAPI jsapi; | |||
4544 | bool result = jsapi.Init(this); | |||
4545 | NS_ENSURE_TRUE(result, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(result)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "result" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 4545); return NS_ERROR_FAILURE; } } while (false); | |||
4546 | ||||
4547 | JSContext* cx = jsapi.cx(); | |||
4548 | ||||
4549 | // Get the document's pending state object -- it contains the data we're | |||
4550 | // going to send along with the popstate event. The object is serialized | |||
4551 | // using structured clone. | |||
4552 | JS::Rooted<JS::Value> stateJSValue(cx); | |||
4553 | nsresult rv = mDoc->GetStateObject(&stateJSValue); | |||
4554 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 4554); return rv; } } while (false); | |||
4555 | ||||
4556 | if (!JS_WrapValue(cx, &stateJSValue)) { | |||
4557 | return NS_ERROR_OUT_OF_MEMORY; | |||
4558 | } | |||
4559 | ||||
4560 | RootedDictionary<PopStateEventInit> init(cx); | |||
4561 | init.mState = stateJSValue; | |||
4562 | ||||
4563 | RefPtr<PopStateEvent> event = | |||
4564 | PopStateEvent::Constructor(this, u"popstate"_ns, init); | |||
4565 | event->SetTrusted(true); | |||
4566 | event->SetTarget(this); | |||
4567 | ||||
4568 | ErrorResult err; | |||
4569 | DispatchEvent(*event, err); | |||
4570 | return err.StealNSResult(); | |||
4571 | } | |||
4572 | ||||
4573 | //------------------------------------------------------- | |||
4574 | // Tells the HTMLFrame/CanvasFrame that is now has focus | |||
4575 | void nsGlobalWindowInner::UpdateCanvasFocus(bool aFocusChanged, | |||
4576 | nsIContent* aNewContent) { | |||
4577 | // this is called from the inner window so use GetDocShell | |||
4578 | nsIDocShell* docShell = GetDocShell(); | |||
4579 | if (!docShell) return; | |||
4580 | ||||
4581 | bool editable; | |||
4582 | docShell->GetEditable(&editable); | |||
4583 | if (editable) return; | |||
4584 | ||||
4585 | PresShell* presShell = docShell->GetPresShell(); | |||
4586 | if (!presShell || !mDoc) { | |||
4587 | return; | |||
4588 | } | |||
4589 | ||||
4590 | Element* rootElement = mDoc->GetRootElement(); | |||
4591 | if (rootElement) { | |||
4592 | if ((mHasFocus || aFocusChanged) && | |||
4593 | (mFocusedElement == rootElement || aNewContent == rootElement)) { | |||
4594 | nsCanvasFrame* canvasFrame = presShell->GetCanvasFrame(); | |||
4595 | if (canvasFrame) { | |||
4596 | canvasFrame->SetHasFocus(mHasFocus && rootElement == aNewContent); | |||
4597 | } | |||
4598 | } | |||
4599 | } else { | |||
4600 | // XXXbz I would expect that there is never a canvasFrame in this case... | |||
4601 | nsCanvasFrame* canvasFrame = presShell->GetCanvasFrame(); | |||
4602 | if (canvasFrame) { | |||
4603 | canvasFrame->SetHasFocus(false); | |||
4604 | } | |||
4605 | } | |||
4606 | } | |||
4607 | ||||
4608 | already_AddRefed<nsICSSDeclaration> nsGlobalWindowInner::GetComputedStyle( | |||
4609 | Element& aElt, const nsAString& aPseudoElt, ErrorResult& aError) { | |||
4610 | return GetComputedStyleHelper(aElt, aPseudoElt, false, aError); | |||
4611 | } | |||
4612 | ||||
4613 | already_AddRefed<nsICSSDeclaration> | |||
4614 | nsGlobalWindowInner::GetDefaultComputedStyle(Element& aElt, | |||
4615 | const nsAString& aPseudoElt, | |||
4616 | ErrorResult& aError) { | |||
4617 | return GetComputedStyleHelper(aElt, aPseudoElt, true, aError); | |||
4618 | } | |||
4619 | ||||
4620 | already_AddRefed<nsICSSDeclaration> nsGlobalWindowInner::GetComputedStyleHelper( | |||
4621 | Element& aElt, const nsAString& aPseudoElt, bool aDefaultStylesOnly, | |||
4622 | ErrorResult& aError) { | |||
4623 | FORWARD_TO_OUTER_OR_THROW(GetComputedStyleHelperOuter, | |||
4624 | (aElt, aPseudoElt, aDefaultStylesOnly, aError), | |||
4625 | aError, nullptr); | |||
4626 | } | |||
4627 | ||||
4628 | void nsGlobalWindowInner::MaybeNotifyStorageKeyUsed() { | |||
4629 | // Only notify once per window lifetime. | |||
4630 | if (hasNotifiedStorageKeyUsed) { | |||
4631 | return; | |||
4632 | } | |||
4633 | nsresult rv = | |||
4634 | BounceTrackingStorageObserver::OnInitialStorageAccess(GetWindowContext()); | |||
4635 | if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 4635)) { | |||
4636 | return; | |||
4637 | } | |||
4638 | hasNotifiedStorageKeyUsed = true; | |||
4639 | } | |||
4640 | ||||
4641 | Storage* nsGlobalWindowInner::GetSessionStorage(ErrorResult& aError) { | |||
4642 | nsIPrincipal* principal = GetPrincipal(); | |||
4643 | nsIPrincipal* storagePrincipal; | |||
4644 | if (StaticPrefs:: | |||
4645 | privacy_partition_always_partition_third_party_non_cookie_storage_exempt_sessionstorage()) { | |||
4646 | storagePrincipal = GetEffectiveCookiePrincipal(); | |||
4647 | } else { | |||
4648 | storagePrincipal = GetEffectiveStoragePrincipal(); | |||
4649 | } | |||
4650 | BrowsingContext* browsingContext = GetBrowsingContext(); | |||
4651 | ||||
4652 | if (!principal || !storagePrincipal || !browsingContext || | |||
4653 | !Storage::StoragePrefIsEnabled()) { | |||
4654 | return nullptr; | |||
4655 | } | |||
4656 | ||||
4657 | if (mSessionStorage) { | |||
4658 | MOZ_LOG(gDOMLeakPRLogInner, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogInner ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsGlobalWindowInner %p has %p sessionStorage" , this, mSessionStorage.get()); } } while (0) | |||
4659 | ("nsGlobalWindowInner %p has %p sessionStorage", this,do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogInner ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsGlobalWindowInner %p has %p sessionStorage" , this, mSessionStorage.get()); } } while (0) | |||
4660 | mSessionStorage.get()))do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogInner ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsGlobalWindowInner %p has %p sessionStorage" , this, mSessionStorage.get()); } } while (0); | |||
4661 | bool canAccess = | |||
4662 | principal->Subsumes(mSessionStorage->Principal()) && | |||
4663 | storagePrincipal->Subsumes(mSessionStorage->StoragePrincipal()); | |||
4664 | if (!canAccess) { | |||
4665 | mSessionStorage = nullptr; | |||
4666 | } | |||
4667 | } | |||
4668 | ||||
4669 | if (!mSessionStorage) { | |||
4670 | nsString documentURI; | |||
4671 | if (mDoc) { | |||
4672 | aError = mDoc->GetDocumentURI(documentURI); | |||
4673 | if (NS_WARN_IF(aError.Failed())NS_warn_if_impl(aError.Failed(), "aError.Failed()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 4673)) { | |||
4674 | return nullptr; | |||
4675 | } | |||
4676 | } | |||
4677 | ||||
4678 | if (!mDoc) { | |||
4679 | aError.Throw(NS_ERROR_FAILURE); | |||
4680 | return nullptr; | |||
4681 | } | |||
4682 | ||||
4683 | // If the document's sandboxed origin flag is set, then accessing | |||
4684 | // sessionStorage is prohibited. | |||
4685 | if (mDoc->GetSandboxFlags() & SANDBOXED_ORIGIN) { | |||
4686 | aError.ThrowSecurityError( | |||
4687 | "Forbidden in a sandboxed document without the 'allow-same-origin' " | |||
4688 | "flag."); | |||
4689 | return nullptr; | |||
4690 | } | |||
4691 | ||||
4692 | uint32_t rejectedReason = 0; | |||
4693 | StorageAccess access = StorageAllowedForWindow(this, &rejectedReason); | |||
4694 | ||||
4695 | // SessionStorage is an ephemeral per-tab per-origin storage that only lives | |||
4696 | // as long as the tab is open, although it may survive browser restarts | |||
4697 | // thanks to the session store. So we interpret storage access differently | |||
4698 | // than we would for persistent per-origin storage like LocalStorage and so | |||
4699 | // it may be okay to provide SessionStorage even when we receive a value of | |||
4700 | // eDeny. | |||
4701 | // | |||
4702 | // ContentBlocking::ShouldAllowAccessFor will return false for 3 main | |||
4703 | // reasons. | |||
4704 | // | |||
4705 | // 1. Cookies are entirely blocked due to a per-origin permission | |||
4706 | // (nsICookiePermission::ACCESS_DENY for the top-level principal or this | |||
4707 | // window's principal) or the very broad BEHAVIOR_REJECT. This will return | |||
4708 | // eDeny with a reason of STATE_COOKIES_BLOCKED_BY_PERMISSION or | |||
4709 | // STATE_COOKIES_BLOCKED_ALL. | |||
4710 | // | |||
4711 | // 2. Third-party cookies are limited via BEHAVIOR_REJECT_FOREIGN and | |||
4712 | // BEHAVIOR_LIMIT_FOREIGN and this is a third-party window. This will return | |||
4713 | // eDeny with a reason of STATE_COOKIES_BLOCKED_FOREIGN. | |||
4714 | // | |||
4715 | // 3. Tracking protection (BEHAVIOR_REJECT_TRACKER and | |||
4716 | // BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN) is in effect and | |||
4717 | // IsThirdPartyTrackingResourceWindow() returned true and there wasn't a | |||
4718 | // permission that allows it. This will return ePartitionTrackersOrDeny with | |||
4719 | // a reason of STATE_COOKIES_BLOCKED_TRACKER or | |||
4720 | // STATE_COOKIES_BLOCKED_SOCIALTRACKER. | |||
4721 | // | |||
4722 | // In the 1st case, the user has explicitly indicated that they don't want | |||
4723 | // to allow any storage to the origin or all origins and so we throw an | |||
4724 | // error and deny access to SessionStorage. In the 2nd case, a legacy | |||
4725 | // decision reasoned that there's no harm in providing SessionStorage | |||
4726 | // because the information is not durable and cannot escape the current tab. | |||
4727 | // The rationale is similar for the 3rd case. | |||
4728 | if (access == StorageAccess::eDeny && | |||
4729 | rejectedReason != | |||
4730 | nsIWebProgressListener::STATE_COOKIES_BLOCKED_FOREIGN) { | |||
4731 | aError.Throw(NS_ERROR_DOM_SECURITY_ERR); | |||
4732 | return nullptr; | |||
4733 | } | |||
4734 | ||||
4735 | const RefPtr<SessionStorageManager> storageManager = | |||
4736 | browsingContext->GetSessionStorageManager(); | |||
4737 | if (!storageManager) { | |||
4738 | aError.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); | |||
4739 | return nullptr; | |||
4740 | } | |||
4741 | ||||
4742 | RefPtr<Storage> storage; | |||
4743 | aError = storageManager->CreateStorage(this, principal, storagePrincipal, | |||
4744 | documentURI, IsPrivateBrowsing(), | |||
4745 | getter_AddRefs(storage)); | |||
4746 | if (aError.Failed()) { | |||
4747 | return nullptr; | |||
4748 | } | |||
4749 | ||||
4750 | mSessionStorage = storage; | |||
4751 | MOZ_ASSERT(mSessionStorage)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mSessionStorage)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mSessionStorage))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mSessionStorage" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 4751); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mSessionStorage" ")"); do { *((volatile int*)__null) = 4751; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
4752 | ||||
4753 | MOZ_LOG(gDOMLeakPRLogInner, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogInner ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsGlobalWindowInner %p tried to get a new sessionStorage %p" , this, mSessionStorage.get()); } } while (0) | |||
4754 | ("nsGlobalWindowInner %p tried to get a new sessionStorage %p",do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogInner ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsGlobalWindowInner %p tried to get a new sessionStorage %p" , this, mSessionStorage.get()); } } while (0) | |||
4755 | this, mSessionStorage.get()))do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogInner ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsGlobalWindowInner %p tried to get a new sessionStorage %p" , this, mSessionStorage.get()); } } while (0); | |||
4756 | ||||
4757 | if (!mSessionStorage) { | |||
4758 | aError.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); | |||
4759 | return nullptr; | |||
4760 | } | |||
4761 | } | |||
4762 | ||||
4763 | MaybeNotifyStorageKeyUsed(); | |||
4764 | ||||
4765 | MOZ_LOG(gDOMLeakPRLogInner, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogInner ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsGlobalWindowInner %p returns %p sessionStorage" , this, mSessionStorage.get()); } } while (0) | |||
4766 | ("nsGlobalWindowInner %p returns %p sessionStorage", this,do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogInner ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsGlobalWindowInner %p returns %p sessionStorage" , this, mSessionStorage.get()); } } while (0) | |||
4767 | mSessionStorage.get()))do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogInner ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsGlobalWindowInner %p returns %p sessionStorage" , this, mSessionStorage.get()); } } while (0); | |||
4768 | ||||
4769 | return mSessionStorage; | |||
4770 | } | |||
4771 | ||||
4772 | Storage* nsGlobalWindowInner::GetLocalStorage(ErrorResult& aError) { | |||
4773 | if (!Storage::StoragePrefIsEnabled()) { | |||
4774 | return nullptr; | |||
4775 | } | |||
4776 | ||||
4777 | // If the document's sandboxed origin flag is set, then accessing localStorage | |||
4778 | // is prohibited. | |||
4779 | if (mDoc && mDoc->GetSandboxFlags() & SANDBOXED_ORIGIN) { | |||
4780 | aError.ThrowSecurityError( | |||
4781 | "Forbidden in a sandboxed document without the 'allow-same-origin' " | |||
4782 | "flag."); | |||
4783 | return nullptr; | |||
4784 | } | |||
4785 | ||||
4786 | // LocalStorage needs to be exposed in every context except for sandboxes and | |||
4787 | // NullPrincipals (data: URLs, for instance). But we need to keep data | |||
4788 | // separate in some scenarios: private-browsing and partitioned trackers. | |||
4789 | // In private-browsing, LocalStorage keeps data in memory, and it shares | |||
4790 | // StorageEvents just with other origins in the same private-browsing | |||
4791 | // environment. | |||
4792 | // For Partitioned Trackers, we expose a partitioned LocalStorage, which | |||
4793 | // doesn't share data with other contexts, and it's just in memory. | |||
4794 | // Partitioned localStorage is available only for trackers listed in the | |||
4795 | // privacy.restrict3rdpartystorage.partitionedHosts pref. See | |||
4796 | // nsContentUtils::IsURIInPrefList to know the syntax for the pref value. | |||
4797 | // This is a temporary web-compatibility hack. | |||
4798 | ||||
4799 | StorageAccess access = StorageAllowedForWindow(this); | |||
4800 | ||||
4801 | // We allow partitioned localStorage only to some hosts. | |||
4802 | bool isolated = false; | |||
4803 | if (ShouldPartitionStorage(access)) { | |||
4804 | if (!mDoc) { | |||
4805 | access = StorageAccess::eDeny; | |||
4806 | } else if (!StoragePartitioningEnabled(access, mDoc->CookieJarSettings())) { | |||
4807 | static const char* kPrefName = | |||
4808 | "privacy.restrict3rdpartystorage.partitionedHosts"; | |||
4809 | ||||
4810 | bool isInList = false; | |||
4811 | mDoc->NodePrincipal()->IsURIInPrefList(kPrefName, &isInList); | |||
4812 | if (!isInList) { | |||
4813 | access = StorageAccess::eDeny; | |||
4814 | } else { | |||
4815 | isolated = true; | |||
4816 | } | |||
4817 | } | |||
4818 | } | |||
4819 | ||||
4820 | if (access == StorageAccess::eDeny) { | |||
4821 | aError.Throw(NS_ERROR_DOM_SECURITY_ERR); | |||
4822 | return nullptr; | |||
4823 | } | |||
4824 | ||||
4825 | nsCOMPtr<nsICookieJarSettings> cookieJarSettings; | |||
4826 | if (mDoc) { | |||
4827 | cookieJarSettings = mDoc->CookieJarSettings(); | |||
4828 | } else { | |||
4829 | cookieJarSettings = net::CookieJarSettings::GetBlockingAll( | |||
4830 | ShouldResistFingerprinting(RFPTarget::IsAlwaysEnabledForPrecompute)); | |||
4831 | } | |||
4832 | ||||
4833 | // Note that this behavior is observable: if we grant storage permission to a | |||
4834 | // tracker, we pass from the partitioned LocalStorage (or a partitioned cookie | |||
4835 | // jar) to the 'normal' one. The previous data is lost and the 2 | |||
4836 | // window.localStorage objects, before and after the permission granted, will | |||
4837 | // be different. | |||
4838 | if (mLocalStorage) { | |||
4839 | if ((mLocalStorage->Type() == (isolated ? Storage::ePartitionedLocalStorage | |||
4840 | : Storage::eLocalStorage)) && | |||
4841 | (mLocalStorage->StoragePrincipal() == GetEffectiveStoragePrincipal())) { | |||
4842 | return mLocalStorage; | |||
4843 | } | |||
4844 | ||||
4845 | // storage needs change | |||
4846 | mLocalStorage = nullptr; | |||
4847 | } | |||
4848 | ||||
4849 | MOZ_ASSERT(!mLocalStorage)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mLocalStorage)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mLocalStorage))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mLocalStorage" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 4849); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mLocalStorage" ")"); do { *((volatile int*)__null) = 4849; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
4850 | ||||
4851 | if (!isolated) { | |||
4852 | RefPtr<Storage> storage; | |||
4853 | ||||
4854 | if (NextGenLocalStorageEnabled()) { | |||
4855 | aError = LSObject::CreateForWindow(this, getter_AddRefs(storage)); | |||
4856 | } else { | |||
4857 | nsresult rv; | |||
4858 | nsCOMPtr<nsIDOMStorageManager> storageManager = | |||
4859 | do_GetService("@mozilla.org/dom/localStorage-manager;1", &rv); | |||
4860 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
4861 | aError.Throw(rv); | |||
4862 | return nullptr; | |||
4863 | } | |||
4864 | ||||
4865 | nsString documentURI; | |||
4866 | if (mDoc) { | |||
4867 | aError = mDoc->GetDocumentURI(documentURI); | |||
4868 | if (NS_WARN_IF(aError.Failed())NS_warn_if_impl(aError.Failed(), "aError.Failed()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 4868)) { | |||
4869 | return nullptr; | |||
4870 | } | |||
4871 | } | |||
4872 | ||||
4873 | nsIPrincipal* principal = GetPrincipal(); | |||
4874 | if (!principal) { | |||
4875 | aError.Throw(NS_ERROR_DOM_SECURITY_ERR); | |||
4876 | return nullptr; | |||
4877 | } | |||
4878 | ||||
4879 | nsIPrincipal* storagePrincipal = GetEffectiveStoragePrincipal(); | |||
4880 | if (!storagePrincipal) { | |||
4881 | aError.Throw(NS_ERROR_DOM_SECURITY_ERR); | |||
4882 | return nullptr; | |||
4883 | } | |||
4884 | ||||
4885 | aError = storageManager->CreateStorage(this, principal, storagePrincipal, | |||
4886 | documentURI, IsPrivateBrowsing(), | |||
4887 | getter_AddRefs(storage)); | |||
4888 | } | |||
4889 | ||||
4890 | if (aError.Failed()) { | |||
4891 | return nullptr; | |||
4892 | } | |||
4893 | ||||
4894 | mLocalStorage = storage; | |||
4895 | } else { | |||
4896 | nsresult rv; | |||
4897 | nsCOMPtr<nsIDOMSessionStorageManager> storageManager = | |||
4898 | do_GetService("@mozilla.org/dom/sessionStorage-manager;1", &rv); | |||
4899 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
4900 | aError.Throw(rv); | |||
4901 | return nullptr; | |||
4902 | } | |||
4903 | ||||
4904 | nsIPrincipal* principal = GetPrincipal(); | |||
4905 | if (!principal) { | |||
4906 | aError.Throw(NS_ERROR_DOM_SECURITY_ERR); | |||
4907 | return nullptr; | |||
4908 | } | |||
4909 | ||||
4910 | nsIPrincipal* storagePrincipal = GetEffectiveStoragePrincipal(); | |||
4911 | if (!storagePrincipal) { | |||
4912 | aError.Throw(NS_ERROR_DOM_SECURITY_ERR); | |||
4913 | return nullptr; | |||
4914 | } | |||
4915 | ||||
4916 | RefPtr<SessionStorageCache> cache; | |||
4917 | if (isolated) { | |||
4918 | cache = new SessionStorageCache(); | |||
4919 | } else { | |||
4920 | // This will clone the session storage if it exists. | |||
4921 | rv = storageManager->GetSessionStorageCache(principal, storagePrincipal, | |||
4922 | &cache); | |||
4923 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
4924 | aError.Throw(rv); | |||
4925 | return nullptr; | |||
4926 | } | |||
4927 | } | |||
4928 | ||||
4929 | mLocalStorage = | |||
4930 | new PartitionedLocalStorage(this, principal, storagePrincipal, cache); | |||
4931 | } | |||
4932 | ||||
4933 | MaybeNotifyStorageKeyUsed(); | |||
4934 | ||||
4935 | MOZ_ASSERT(mLocalStorage)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mLocalStorage)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mLocalStorage))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mLocalStorage", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 4935); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLocalStorage" ")"); do { *((volatile int*)__null) = 4935; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
4936 | MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(mLocalStorage->Type() == (isolated ? Storage::ePartitionedLocalStorage : Storage::eLocalStorage))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mLocalStorage->Type() == ( isolated ? Storage::ePartitionedLocalStorage : Storage::eLocalStorage )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mLocalStorage->Type() == (isolated ? Storage::ePartitionedLocalStorage : Storage::eLocalStorage)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 4938); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLocalStorage->Type() == (isolated ? Storage::ePartitionedLocalStorage : Storage::eLocalStorage)" ")"); do { *((volatile int*)__null) = 4938; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
4937 | mLocalStorage->Type() ==do { static_assert( mozilla::detail::AssertionConditionType< decltype(mLocalStorage->Type() == (isolated ? Storage::ePartitionedLocalStorage : Storage::eLocalStorage))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mLocalStorage->Type() == ( isolated ? Storage::ePartitionedLocalStorage : Storage::eLocalStorage )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mLocalStorage->Type() == (isolated ? Storage::ePartitionedLocalStorage : Storage::eLocalStorage)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 4938); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLocalStorage->Type() == (isolated ? Storage::ePartitionedLocalStorage : Storage::eLocalStorage)" ")"); do { *((volatile int*)__null) = 4938; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
4938 | (isolated ? Storage::ePartitionedLocalStorage : Storage::eLocalStorage))do { static_assert( mozilla::detail::AssertionConditionType< decltype(mLocalStorage->Type() == (isolated ? Storage::ePartitionedLocalStorage : Storage::eLocalStorage))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mLocalStorage->Type() == ( isolated ? Storage::ePartitionedLocalStorage : Storage::eLocalStorage )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mLocalStorage->Type() == (isolated ? Storage::ePartitionedLocalStorage : Storage::eLocalStorage)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 4938); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLocalStorage->Type() == (isolated ? Storage::ePartitionedLocalStorage : Storage::eLocalStorage)" ")"); do { *((volatile int*)__null) = 4938; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
4939 | return mLocalStorage; | |||
4940 | } | |||
4941 | ||||
4942 | IDBFactory* nsGlobalWindowInner::GetIndexedDB(JSContext* aCx, | |||
4943 | ErrorResult& aError) { | |||
4944 | if (!mIndexedDB) { | |||
4945 | // This may keep mIndexedDB null without setting an error. | |||
4946 | auto res = IDBFactory::CreateForWindow(this); | |||
4947 | if (res.isErr()) { | |||
4948 | aError = res.unwrapErr(); | |||
4949 | } else { | |||
4950 | mIndexedDB = res.unwrap(); | |||
4951 | } | |||
4952 | } | |||
4953 | ||||
4954 | MaybeNotifyStorageKeyUsed(); | |||
4955 | ||||
4956 | return mIndexedDB; | |||
4957 | } | |||
4958 | ||||
4959 | //***************************************************************************** | |||
4960 | // nsGlobalWindowInner::nsIInterfaceRequestor | |||
4961 | //***************************************************************************** | |||
4962 | ||||
4963 | NS_IMETHODIMPnsresult | |||
4964 | nsGlobalWindowInner::GetInterface(const nsIID& aIID, void** aSink) { | |||
4965 | nsGlobalWindowOuter* outer = GetOuterWindowInternal(); | |||
4966 | NS_ENSURE_TRUE(outer, NS_ERROR_NOT_INITIALIZED)do { if ((__builtin_expect(!!(!(outer)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "outer" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 4966); return NS_ERROR_NOT_INITIALIZED; } } while (false); | |||
4967 | ||||
4968 | nsresult rv = outer->GetInterfaceInternal(aIID, aSink); | |||
4969 | if (rv == NS_ERROR_NO_INTERFACE) { | |||
4970 | return QueryInterface(aIID, aSink); | |||
4971 | } | |||
4972 | return rv; | |||
4973 | } | |||
4974 | ||||
4975 | void nsGlobalWindowInner::GetInterface(JSContext* aCx, | |||
4976 | JS::Handle<JS::Value> aIID, | |||
4977 | JS::MutableHandle<JS::Value> aRetval, | |||
4978 | ErrorResult& aError) { | |||
4979 | dom::GetInterface(aCx, this, aIID, aRetval, aError); | |||
4980 | } | |||
4981 | ||||
4982 | already_AddRefed<CacheStorage> nsGlobalWindowInner::GetCaches( | |||
4983 | ErrorResult& aRv) { | |||
4984 | if (!mCacheStorage) { | |||
4985 | bool forceTrustedOrigin = | |||
4986 | GetBrowsingContext() && | |||
4987 | GetBrowsingContext()->Top()->GetServiceWorkersTestingEnabled(); | |||
4988 | mCacheStorage = CacheStorage::CreateOnMainThread( | |||
4989 | cache::DEFAULT_NAMESPACE, this, GetEffectiveStoragePrincipal(), | |||
4990 | forceTrustedOrigin, aRv); | |||
4991 | } | |||
4992 | ||||
4993 | RefPtr<CacheStorage> ref = mCacheStorage; | |||
4994 | return ref.forget(); | |||
4995 | } | |||
4996 | ||||
4997 | void nsGlobalWindowInner::FireOfflineStatusEventIfChanged() { | |||
4998 | if (!IsCurrentInnerWindow()) return; | |||
4999 | ||||
5000 | // Don't fire an event if the status hasn't changed | |||
5001 | if (mWasOffline == NS_IsOffline()) { | |||
5002 | return; | |||
5003 | } | |||
5004 | ||||
5005 | mWasOffline = !mWasOffline; | |||
5006 | ||||
5007 | nsAutoString name; | |||
5008 | if (mWasOffline) { | |||
5009 | name.AssignLiteral("offline"); | |||
5010 | } else { | |||
5011 | name.AssignLiteral("online"); | |||
5012 | } | |||
5013 | nsContentUtils::DispatchTrustedEvent(mDoc, this, name, CanBubble::eNo, | |||
5014 | Cancelable::eNo); | |||
5015 | } | |||
5016 | ||||
5017 | nsGlobalWindowInner::SlowScriptResponse | |||
5018 | nsGlobalWindowInner::ShowSlowScriptDialog(JSContext* aCx, | |||
5019 | const nsString& aAddonId, | |||
5020 | const double aDuration) { | |||
5021 | nsresult rv; | |||
5022 | ||||
5023 | if (Preferences::GetBool("dom.always_stop_slow_scripts")) { | |||
| ||||
5024 | return KillSlowScript; | |||
5025 | } | |||
5026 | ||||
5027 | // If it isn't safe to run script, then it isn't safe to bring up the prompt | |||
5028 | // (since that spins the event loop). In that (rare) case, we just kill the | |||
5029 | // script and report a warning. | |||
5030 | if (!nsContentUtils::IsSafeToRunScript()) { | |||
5031 | JS::WarnASCII(aCx, "A long running script was terminated"); | |||
5032 | return KillSlowScript; | |||
5033 | } | |||
5034 | ||||
5035 | // If our document is not active, just kill the script: we've been unloaded | |||
5036 | if (!HasActiveDocument()) { | |||
5037 | return KillSlowScript; | |||
5038 | } | |||
5039 | ||||
5040 | // Check if we should offer the option to debug | |||
5041 | JS::AutoFilename filename; | |||
5042 | uint32_t lineno; | |||
5043 | // Computing the line number can be very expensive (see bug 1330231 for | |||
5044 | // example), and we don't use the line number anywhere except than in the | |||
5045 | // parent process, so we avoid computing it elsewhere. This gives us most of | |||
5046 | // the wins we are interested in, since the source of the slowness here is | |||
5047 | // minified scripts which is more common in Web content that is loaded in the | |||
5048 | // content process. | |||
5049 | uint32_t* linenop = XRE_IsParentProcess() ? &lineno : nullptr; | |||
5050 | bool hasFrame = JS::DescribeScriptedCaller(aCx, &filename, linenop); | |||
5051 | ||||
5052 | // Record the slow script event if we haven't done so already for this inner | |||
5053 | // window (which represents a particular page to the user). | |||
5054 | if (!mHasHadSlowScript) { | |||
5055 | Telemetry::Accumulate(Telemetry::SLOW_SCRIPT_PAGE_COUNT, 1); | |||
5056 | } | |||
5057 | mHasHadSlowScript = true; | |||
5058 | ||||
5059 | // Override the cursor to something that we're sure the user can see. | |||
5060 | SetCursor("auto"_ns, IgnoreErrors()); | |||
5061 | ||||
5062 | if (XRE_IsContentProcess() && ProcessHangMonitor::Get()) { | |||
5063 | ProcessHangMonitor::SlowScriptAction action; | |||
5064 | RefPtr<ProcessHangMonitor> monitor = ProcessHangMonitor::Get(); | |||
5065 | nsIDocShell* docShell = GetDocShell(); | |||
5066 | nsCOMPtr<nsIBrowserChild> child = | |||
5067 | docShell ? docShell->GetBrowserChild() : nullptr; | |||
5068 | action = | |||
5069 | monitor->NotifySlowScript(child, filename.get(), aAddonId, aDuration); | |||
5070 | if (action == ProcessHangMonitor::Terminate) { | |||
5071 | return KillSlowScript; | |||
5072 | } | |||
5073 | ||||
5074 | if (action == ProcessHangMonitor::StartDebugger) { | |||
5075 | // Spin a nested event loop so that the debugger in the parent can fetch | |||
5076 | // any information it needs. Once the debugger has started, return to the | |||
5077 | // script. | |||
5078 | RefPtr<nsGlobalWindowOuter> outer = GetOuterWindowInternal(); | |||
5079 | outer->EnterModalState(); | |||
5080 | SpinEventLoopUntil("nsGlobalWindowInner::ShowSlowScriptDialog"_ns, [&]() { | |||
5081 | return monitor->IsDebuggerStartupComplete(); | |||
5082 | }); | |||
5083 | outer->LeaveModalState(); | |||
5084 | return ContinueSlowScript; | |||
5085 | } | |||
5086 | ||||
5087 | return ContinueSlowScriptAndKeepNotifying; | |||
5088 | } | |||
5089 | ||||
5090 | // Reached only on non-e10s - once per slow script dialog. | |||
5091 | // On e10s - we probe once at ProcessHangsMonitor.sys.mjs | |||
5092 | Telemetry::Accumulate(Telemetry::SLOW_SCRIPT_NOTICE_COUNT, 1); | |||
5093 | ||||
5094 | // Get the nsIPrompt interface from the docshell | |||
5095 | nsCOMPtr<nsIDocShell> ds = GetDocShell(); | |||
5096 | NS_ENSURE_TRUE(ds, KillSlowScript)do { if ((__builtin_expect(!!(!(ds)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING , "NS_ENSURE_TRUE(" "ds" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5096); return KillSlowScript; } } while (false); | |||
5097 | nsCOMPtr<nsIPrompt> prompt = do_GetInterface(ds); | |||
5098 | NS_ENSURE_TRUE(prompt, KillSlowScript)do { if ((__builtin_expect(!!(!(prompt)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "prompt" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5098); return KillSlowScript; } } while (false); | |||
5099 | ||||
5100 | // Prioritize the SlowScriptDebug interface over JSD1. | |||
5101 | nsCOMPtr<nsISlowScriptDebugCallback> debugCallback; | |||
5102 | ||||
5103 | if (hasFrame) { | |||
5104 | const char* debugCID = "@mozilla.org/dom/slow-script-debug;1"; | |||
5105 | nsCOMPtr<nsISlowScriptDebug> debugService = do_GetService(debugCID, &rv); | |||
5106 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { | |||
5107 | debugService->GetActivationHandler(getter_AddRefs(debugCallback)); | |||
5108 | } | |||
5109 | } | |||
5110 | ||||
5111 | bool failed = false; | |||
5112 | auto getString = [&](const char* name, | |||
5113 | nsContentUtils::PropertiesFile propFile = | |||
5114 | nsContentUtils::eDOM_PROPERTIES) { | |||
5115 | nsAutoString result; | |||
5116 | nsresult rv = nsContentUtils::GetLocalizedString(propFile, name, result); | |||
5117 | ||||
5118 | // GetStringFromName can return NS_OK and still give nullptr string | |||
5119 | failed = failed || NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || result.IsEmpty(); | |||
5120 | return result; | |||
5121 | }; | |||
5122 | ||||
5123 | bool isAddonScript = !aAddonId.IsEmpty(); | |||
5124 | bool showDebugButton = debugCallback && !isAddonScript; | |||
5125 | ||||
5126 | // Get localizable strings | |||
5127 | ||||
5128 | nsAutoString title, checkboxMsg, debugButton, msg; | |||
5129 | if (isAddonScript
| |||
5130 | title = getString("KillAddonScriptTitle"); | |||
5131 | checkboxMsg = getString("KillAddonScriptGlobalMessage"); | |||
5132 | ||||
5133 | auto appName = | |||
5134 | getString("brandShortName", nsContentUtils::eBRAND_PROPERTIES); | |||
5135 | ||||
5136 | nsCOMPtr<nsIAddonPolicyService> aps = | |||
5137 | do_GetService("@mozilla.org/addons/policy-service;1"); | |||
5138 | nsString addonName; | |||
5139 | if (!aps || NS_FAILED(aps->GetExtensionName(aAddonId, addonName))((bool)(__builtin_expect(!!(NS_FAILED_impl(aps->GetExtensionName (aAddonId, addonName))), 0)))) { | |||
5140 | addonName = aAddonId; | |||
5141 | } | |||
5142 | ||||
5143 | rv = nsContentUtils::FormatLocalizedString( | |||
5144 | msg, nsContentUtils::eDOM_PROPERTIES, "KillAddonScriptMessage", | |||
5145 | addonName, appName); | |||
5146 | ||||
5147 | failed = failed || NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))); | |||
5148 | } else { | |||
5149 | title = getString("KillScriptTitle"); | |||
5150 | checkboxMsg = getString("DontAskAgain"); | |||
5151 | ||||
5152 | if (showDebugButton
| |||
5153 | debugButton = getString("DebugScriptButton"); | |||
5154 | msg = getString("KillScriptWithDebugMessage"); | |||
5155 | } else { | |||
5156 | msg = getString("KillScriptMessage"); | |||
5157 | } | |||
5158 | } | |||
5159 | ||||
5160 | auto stopButton = getString("StopScriptButton"); | |||
5161 | auto waitButton = getString("WaitForScriptButton"); | |||
5162 | ||||
5163 | if (failed) { | |||
5164 | NS_ERROR("Failed to get localized strings.")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "Failed to get localized strings." , "Error", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5164); MOZ_PretendNoReturn(); } while (0); | |||
5165 | return ContinueSlowScript; | |||
5166 | } | |||
5167 | ||||
5168 | // Append file and line number information, if available | |||
5169 | if (filename.get()) { | |||
5170 | nsAutoString scriptLocation; | |||
5171 | // We want to drop the middle part of too-long locations. We'll | |||
5172 | // define "too-long" as longer than 60 UTF-16 code units. Just | |||
5173 | // have to be a bit careful about unpaired surrogates. | |||
5174 | NS_ConvertUTF8toUTF16 filenameUTF16(filename.get()); | |||
5175 | if (filenameUTF16.Length() > 60) { | |||
5176 | // XXXbz Do we need to insert any bidi overrides here? | |||
5177 | size_t cutStart = 30; | |||
5178 | size_t cutLength = filenameUTF16.Length() - 60; | |||
5179 | MOZ_ASSERT(cutLength > 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(cutLength > 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(cutLength > 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("cutLength > 0" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5179); AnnotateMozCrashReason("MOZ_ASSERT" "(" "cutLength > 0" ")"); do { *((volatile int*)__null) = 5179; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5180 | if (NS_IS_LOW_SURROGATE(filenameUTF16[cutStart])((uint32_t(filenameUTF16[cutStart]) & 0xFFFFFC00) == 0xDC00 )) { | |||
5181 | // Don't truncate before the low surrogate, in case it's preceded by a | |||
5182 | // high surrogate and forms a single Unicode character. Instead, just | |||
5183 | // include the low surrogate. | |||
5184 | ++cutStart; | |||
5185 | --cutLength; | |||
5186 | } | |||
5187 | if (NS_IS_LOW_SURROGATE(filenameUTF16[cutStart + cutLength])((uint32_t(filenameUTF16[cutStart + cutLength]) & 0xFFFFFC00 ) == 0xDC00)) { | |||
5188 | // Likewise, don't drop a trailing low surrogate here. We want to | |||
5189 | // increase cutLength, since it might be 0 already so we can't very well | |||
5190 | // decrease it. | |||
5191 | ++cutLength; | |||
5192 | } | |||
5193 | ||||
5194 | // Insert U+2026 HORIZONTAL ELLIPSIS | |||
5195 | filenameUTF16.ReplaceLiteral(cutStart, cutLength, u"\x2026"); | |||
5196 | } | |||
5197 | rv = nsContentUtils::FormatLocalizedString( | |||
5198 | scriptLocation, nsContentUtils::eDOM_PROPERTIES, "KillScriptLocation", | |||
5199 | filenameUTF16); | |||
5200 | ||||
5201 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { | |||
5202 | msg.AppendLiteral("\n\n"); | |||
5203 | msg.Append(scriptLocation); | |||
5204 | msg.Append(':'); | |||
5205 | msg.AppendInt(lineno); | |||
| ||||
5206 | } | |||
5207 | } | |||
5208 | ||||
5209 | uint32_t buttonFlags = nsIPrompt::BUTTON_POS_1_DEFAULT + | |||
5210 | (nsIPrompt::BUTTON_TITLE_IS_STRING * | |||
5211 | (nsIPrompt::BUTTON_POS_0 + nsIPrompt::BUTTON_POS_1)); | |||
5212 | ||||
5213 | // Add a third button if necessary. | |||
5214 | if (showDebugButton) | |||
5215 | buttonFlags += nsIPrompt::BUTTON_TITLE_IS_STRING * nsIPrompt::BUTTON_POS_2; | |||
5216 | ||||
5217 | bool checkboxValue = false; | |||
5218 | int32_t buttonPressed = 0; // In case the user exits dialog by clicking X. | |||
5219 | { | |||
5220 | // Null out the operation callback while we're re-entering JS here. | |||
5221 | AutoDisableJSInterruptCallback disabler(aCx); | |||
5222 | ||||
5223 | // Open the dialog. | |||
5224 | rv = prompt->ConfirmEx( | |||
5225 | title.get(), msg.get(), buttonFlags, waitButton.get(), stopButton.get(), | |||
5226 | debugButton.get(), checkboxMsg.get(), &checkboxValue, &buttonPressed); | |||
5227 | } | |||
5228 | ||||
5229 | if (buttonPressed == 0) { | |||
5230 | if (checkboxValue && !isAddonScript && NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) | |||
5231 | return AlwaysContinueSlowScript; | |||
5232 | return ContinueSlowScript; | |||
5233 | } | |||
5234 | ||||
5235 | if (buttonPressed == 2) { | |||
5236 | MOZ_RELEASE_ASSERT(debugCallback)do { static_assert( mozilla::detail::AssertionConditionType< decltype(debugCallback)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(debugCallback))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("debugCallback", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5236); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "debugCallback" ")"); do { *((volatile int*)__null) = 5236; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5237 | ||||
5238 | rv = debugCallback->HandleSlowScriptDebug(this); | |||
5239 | return NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) ? ContinueSlowScript : KillSlowScript; | |||
5240 | } | |||
5241 | ||||
5242 | JS_ClearPendingException(aCx); | |||
5243 | ||||
5244 | return KillSlowScript; | |||
5245 | } | |||
5246 | ||||
5247 | nsresult nsGlobalWindowInner::Observe(nsISupports* aSubject, const char* aTopic, | |||
5248 | const char16_t* aData) { | |||
5249 | if (!nsCRT::strcmp(aTopic, NS_IOSERVICE_OFFLINE_STATUS_TOPIC"network:offline-status-changed")) { | |||
5250 | if (!IsFrozen()) { | |||
5251 | // Fires an offline status event if the offline status has changed | |||
5252 | FireOfflineStatusEventIfChanged(); | |||
5253 | } | |||
5254 | return NS_OK; | |||
5255 | } | |||
5256 | ||||
5257 | if (!nsCRT::strcmp(aTopic, MEMORY_PRESSURE_OBSERVER_TOPIC"memory-pressure")) { | |||
5258 | if (mPerformance) { | |||
5259 | mPerformance->MemoryPressure(); | |||
5260 | } | |||
5261 | RemoveReportRecords(); | |||
5262 | return NS_OK; | |||
5263 | } | |||
5264 | ||||
5265 | if (!nsCRT::strcmp(aTopic, PERMISSION_CHANGED_TOPIC"perm-changed")) { | |||
5266 | nsCOMPtr<nsIPermission> perm(do_QueryInterface(aSubject)); | |||
5267 | if (!perm) { | |||
5268 | // A null permission indicates that the entire permission list | |||
5269 | // was cleared. | |||
5270 | MOZ_ASSERT(!nsCRT::strcmp(aData, u"cleared"))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!nsCRT::strcmp(aData, u"cleared"))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!nsCRT::strcmp(aData, u"cleared" )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!nsCRT::strcmp(aData, u\"cleared\")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5270); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!nsCRT::strcmp(aData, u\"cleared\")" ")"); do { *((volatile int*)__null) = 5270; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5271 | UpdatePermissions(); | |||
5272 | return NS_OK; | |||
5273 | } | |||
5274 | ||||
5275 | nsAutoCString type; | |||
5276 | perm->GetType(type); | |||
5277 | if (type == "autoplay-media"_ns) { | |||
5278 | UpdateAutoplayPermission(); | |||
5279 | } else if (type == "shortcuts"_ns) { | |||
5280 | UpdateShortcutsPermission(); | |||
5281 | } else if (type == "popup"_ns) { | |||
5282 | UpdatePopupPermission(); | |||
5283 | } | |||
5284 | ||||
5285 | if (!mDoc) { | |||
5286 | return NS_OK; | |||
5287 | } | |||
5288 | ||||
5289 | RefPtr<PermissionDelegateHandler> permDelegateHandler = | |||
5290 | mDoc->GetPermissionDelegateHandler(); | |||
5291 | ||||
5292 | if (permDelegateHandler) { | |||
5293 | permDelegateHandler->UpdateDelegatedPermission(type); | |||
5294 | } | |||
5295 | ||||
5296 | return NS_OK; | |||
5297 | } | |||
5298 | ||||
5299 | if (!nsCRT::strcmp(aTopic, "screen-information-changed")) { | |||
5300 | if (mScreen) { | |||
5301 | if (RefPtr<ScreenOrientation> orientation = | |||
5302 | mScreen->GetOrientationIfExists()) { | |||
5303 | orientation->MaybeChanged(); | |||
5304 | } | |||
5305 | } | |||
5306 | if (mHasOrientationChangeListeners) { | |||
5307 | int32_t oldAngle = mOrientationAngle; | |||
5308 | mOrientationAngle = Orientation(CallerType::System); | |||
5309 | if (mOrientationAngle != oldAngle && IsCurrentInnerWindow()) { | |||
5310 | nsCOMPtr<nsPIDOMWindowOuter> outer = GetOuterWindow(); | |||
5311 | outer->DispatchCustomEvent(u"orientationchange"_ns); | |||
5312 | } | |||
5313 | } | |||
5314 | return NS_OK; | |||
5315 | } | |||
5316 | ||||
5317 | if (!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID"nsPref:changed")) { | |||
5318 | MOZ_ASSERT(!NS_strcmp(aData, u"intl.accept_languages"))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!NS_strcmp(aData, u"intl.accept_languages"))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(!NS_strcmp(aData, u"intl.accept_languages")))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!NS_strcmp(aData, u\"intl.accept_languages\")" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5318); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_strcmp(aData, u\"intl.accept_languages\")" ")"); do { *((volatile int*)__null) = 5318; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5319 | ||||
5320 | // The user preferred languages have changed, we need to fire an event on | |||
5321 | // Window object and invalidate the cache for navigator.languages. It is | |||
5322 | // done for every change which can be a waste of cycles but those should be | |||
5323 | // fairly rare. | |||
5324 | // We MUST invalidate navigator.languages before sending the event in the | |||
5325 | // very likely situation where an event handler will try to read its value. | |||
5326 | ||||
5327 | if (mNavigator) { | |||
5328 | Navigator_Binding::ClearCachedLanguageValue(mNavigator); | |||
5329 | Navigator_Binding::ClearCachedLanguagesValue(mNavigator); | |||
5330 | } | |||
5331 | ||||
5332 | // The event has to be dispatched only to the current inner window. | |||
5333 | if (!IsCurrentInnerWindow()) { | |||
5334 | return NS_OK; | |||
5335 | } | |||
5336 | ||||
5337 | RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr); | |||
5338 | event->InitEvent(u"languagechange"_ns, false, false); | |||
5339 | event->SetTrusted(true); | |||
5340 | ||||
5341 | ErrorResult rv; | |||
5342 | DispatchEvent(*event, rv); | |||
5343 | return rv.StealNSResult(); | |||
5344 | } | |||
5345 | ||||
5346 | NS_WARNING("unrecognized topic in nsGlobalWindowInner::Observe")NS_DebugBreak(NS_DEBUG_WARNING, "unrecognized topic in nsGlobalWindowInner::Observe" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5346); | |||
5347 | return NS_ERROR_FAILURE; | |||
5348 | } | |||
5349 | ||||
5350 | void nsGlobalWindowInner::ObserveStorageNotification( | |||
5351 | StorageEvent* aEvent, const char16_t* aStorageType, bool aPrivateBrowsing) { | |||
5352 | MOZ_ASSERT(aEvent)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aEvent)>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(aEvent))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aEvent", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5352); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEvent" ")" ); do { *((volatile int*)__null) = 5352; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5353 | ||||
5354 | // The private browsing check must be done here again because this window | |||
5355 | // could have changed its state before the notification check and now. This | |||
5356 | // happens in case this window did have a docShell at that time. | |||
5357 | if (aPrivateBrowsing != IsPrivateBrowsing()) { | |||
5358 | return; | |||
5359 | } | |||
5360 | ||||
5361 | // LocalStorage can only exist on an inner window, and we don't want to | |||
5362 | // generate events on frozen or otherwise-navigated-away from windows. | |||
5363 | // (Actually, this code used to try and buffer events for frozen windows, | |||
5364 | // but it never worked, so we've removed it. See bug 1285898.) | |||
5365 | if (!IsCurrentInnerWindow() || IsFrozen()) { | |||
5366 | return; | |||
5367 | } | |||
5368 | ||||
5369 | nsIPrincipal* principal = GetPrincipal(); | |||
5370 | if (!principal) { | |||
5371 | return; | |||
5372 | } | |||
5373 | ||||
5374 | bool fireMozStorageChanged = false; | |||
5375 | nsAutoString eventType; | |||
5376 | eventType.AssignLiteral("storage"); | |||
5377 | ||||
5378 | if (!NS_strcmp(aStorageType, u"sessionStorage")) { | |||
5379 | RefPtr<Storage> changingStorage = aEvent->GetStorageArea(); | |||
5380 | MOZ_ASSERT(changingStorage)do { static_assert( mozilla::detail::AssertionConditionType< decltype(changingStorage)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(changingStorage))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("changingStorage" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5380); AnnotateMozCrashReason("MOZ_ASSERT" "(" "changingStorage" ")"); do { *((volatile int*)__null) = 5380; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5381 | ||||
5382 | bool check = false; | |||
5383 | ||||
5384 | if (const RefPtr<SessionStorageManager> storageManager = | |||
5385 | GetBrowsingContext()->GetSessionStorageManager()) { | |||
5386 | nsresult rv = storageManager->CheckStorage(GetEffectiveStoragePrincipal(), | |||
5387 | changingStorage, &check); | |||
5388 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { | |||
5389 | return; | |||
5390 | } | |||
5391 | } | |||
5392 | ||||
5393 | if (!check) { | |||
5394 | // This storage event is not coming from our storage or is coming | |||
5395 | // from a different docshell, i.e. it is a clone, ignore this event. | |||
5396 | return; | |||
5397 | } | |||
5398 | ||||
5399 | MOZ_LOG(do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogInner ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsGlobalWindowInner %p with sessionStorage %p passing event from %p" , this, mSessionStorage.get(), changingStorage.get()); } } while (0) | |||
5400 | gDOMLeakPRLogInner, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogInner ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsGlobalWindowInner %p with sessionStorage %p passing event from %p" , this, mSessionStorage.get(), changingStorage.get()); } } while (0) | |||
5401 | ("nsGlobalWindowInner %p with sessionStorage %p passing event from %p",do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogInner ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsGlobalWindowInner %p with sessionStorage %p passing event from %p" , this, mSessionStorage.get(), changingStorage.get()); } } while (0) | |||
5402 | this, mSessionStorage.get(), changingStorage.get()))do { const ::mozilla::LogModule* moz_real_module = gDOMLeakPRLogInner ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "nsGlobalWindowInner %p with sessionStorage %p passing event from %p" , this, mSessionStorage.get(), changingStorage.get()); } } while (0); | |||
5403 | ||||
5404 | fireMozStorageChanged = mSessionStorage == changingStorage; | |||
5405 | if (fireMozStorageChanged) { | |||
5406 | eventType.AssignLiteral("MozSessionStorageChanged"); | |||
5407 | } | |||
5408 | } | |||
5409 | ||||
5410 | else { | |||
5411 | MOZ_ASSERT(!NS_strcmp(aStorageType, u"localStorage"))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!NS_strcmp(aStorageType, u"localStorage"))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(!NS_strcmp(aStorageType, u"localStorage")))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!NS_strcmp(aStorageType, u\"localStorage\")" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5411); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_strcmp(aStorageType, u\"localStorage\")" ")"); do { *((volatile int*)__null) = 5411; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5412 | ||||
5413 | nsIPrincipal* storagePrincipal = GetEffectiveStoragePrincipal(); | |||
5414 | if (!storagePrincipal) { | |||
5415 | return; | |||
5416 | } | |||
5417 | ||||
5418 | MOZ_DIAGNOSTIC_ASSERT(StorageUtils::PrincipalsEqual(aEvent->GetPrincipal(),do { static_assert( mozilla::detail::AssertionConditionType< decltype(StorageUtils::PrincipalsEqual(aEvent->GetPrincipal (), storagePrincipal))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(StorageUtils::PrincipalsEqual (aEvent->GetPrincipal(), storagePrincipal)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("StorageUtils::PrincipalsEqual(aEvent->GetPrincipal(), storagePrincipal)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5419); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "StorageUtils::PrincipalsEqual(aEvent->GetPrincipal(), storagePrincipal)" ")"); do { *((volatile int*)__null) = 5419; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
5419 | storagePrincipal))do { static_assert( mozilla::detail::AssertionConditionType< decltype(StorageUtils::PrincipalsEqual(aEvent->GetPrincipal (), storagePrincipal))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(StorageUtils::PrincipalsEqual (aEvent->GetPrincipal(), storagePrincipal)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("StorageUtils::PrincipalsEqual(aEvent->GetPrincipal(), storagePrincipal)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5419); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "StorageUtils::PrincipalsEqual(aEvent->GetPrincipal(), storagePrincipal)" ")"); do { *((volatile int*)__null) = 5419; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5420 | ||||
5421 | fireMozStorageChanged = | |||
5422 | mLocalStorage && mLocalStorage == aEvent->GetStorageArea(); | |||
5423 | ||||
5424 | if (fireMozStorageChanged) { | |||
5425 | eventType.AssignLiteral("MozLocalStorageChanged"); | |||
5426 | } | |||
5427 | } | |||
5428 | ||||
5429 | // Clone the storage event included in the observer notification. We want | |||
5430 | // to dispatch clones rather than the original event. | |||
5431 | IgnoredErrorResult error; | |||
5432 | RefPtr<StorageEvent> clonedEvent = | |||
5433 | CloneStorageEvent(eventType, aEvent, error); | |||
5434 | if (error.Failed() || !clonedEvent) { | |||
5435 | return; | |||
5436 | } | |||
5437 | ||||
5438 | clonedEvent->SetTrusted(true); | |||
5439 | ||||
5440 | if (fireMozStorageChanged) { | |||
5441 | WidgetEvent* internalEvent = clonedEvent->WidgetEventPtr(); | |||
5442 | internalEvent->mFlags.mOnlyChromeDispatch = true; | |||
5443 | } | |||
5444 | ||||
5445 | DispatchEvent(*clonedEvent); | |||
5446 | } | |||
5447 | ||||
5448 | already_AddRefed<StorageEvent> nsGlobalWindowInner::CloneStorageEvent( | |||
5449 | const nsAString& aType, const RefPtr<StorageEvent>& aEvent, | |||
5450 | ErrorResult& aRv) { | |||
5451 | StorageEventInit dict; | |||
5452 | ||||
5453 | dict.mBubbles = aEvent->Bubbles(); | |||
5454 | dict.mCancelable = aEvent->Cancelable(); | |||
5455 | aEvent->GetKey(dict.mKey); | |||
5456 | aEvent->GetOldValue(dict.mOldValue); | |||
5457 | aEvent->GetNewValue(dict.mNewValue); | |||
5458 | aEvent->GetUrl(dict.mUrl); | |||
5459 | ||||
5460 | RefPtr<Storage> storageArea = aEvent->GetStorageArea(); | |||
5461 | ||||
5462 | RefPtr<Storage> storage; | |||
5463 | ||||
5464 | // If null, this is a localStorage event received by IPC. | |||
5465 | if (!storageArea) { | |||
5466 | storage = GetLocalStorage(aRv); | |||
5467 | if (!NextGenLocalStorageEnabled()) { | |||
5468 | if (aRv.Failed() || !storage) { | |||
5469 | return nullptr; | |||
5470 | } | |||
5471 | ||||
5472 | if (storage->Type() == Storage::eLocalStorage) { | |||
5473 | RefPtr<LocalStorage> localStorage = | |||
5474 | static_cast<LocalStorage*>(storage.get()); | |||
5475 | ||||
5476 | // We must apply the current change to the 'local' localStorage. | |||
5477 | localStorage->ApplyEvent(aEvent); | |||
5478 | } | |||
5479 | } | |||
5480 | } else if (storageArea->Type() == Storage::eSessionStorage) { | |||
5481 | storage = GetSessionStorage(aRv); | |||
5482 | } else { | |||
5483 | MOZ_ASSERT(storageArea->Type() == Storage::eLocalStorage)do { static_assert( mozilla::detail::AssertionConditionType< decltype(storageArea->Type() == Storage::eLocalStorage)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(storageArea->Type() == Storage::eLocalStorage))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("storageArea->Type() == Storage::eLocalStorage" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5483); AnnotateMozCrashReason("MOZ_ASSERT" "(" "storageArea->Type() == Storage::eLocalStorage" ")"); do { *((volatile int*)__null) = 5483; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5484 | storage = GetLocalStorage(aRv); | |||
5485 | } | |||
5486 | ||||
5487 | if (aRv.Failed() || !storage) { | |||
5488 | return nullptr; | |||
5489 | } | |||
5490 | ||||
5491 | if (storage->Type() == Storage::ePartitionedLocalStorage) { | |||
5492 | // This error message is not exposed. | |||
5493 | aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); | |||
5494 | return nullptr; | |||
5495 | } | |||
5496 | ||||
5497 | MOZ_ASSERT(storage)do { static_assert( mozilla::detail::AssertionConditionType< decltype(storage)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(storage))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("storage", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5497); AnnotateMozCrashReason("MOZ_ASSERT" "(" "storage" ")" ); do { *((volatile int*)__null) = 5497; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5498 | MOZ_ASSERT_IF(storageArea, storage->IsForkOf(storageArea))do { if (storageArea) { do { static_assert( mozilla::detail:: AssertionConditionType<decltype(storage->IsForkOf(storageArea ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(storage->IsForkOf(storageArea)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("storage->IsForkOf(storageArea)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5498); AnnotateMozCrashReason("MOZ_ASSERT" "(" "storage->IsForkOf(storageArea)" ")"); do { *((volatile int*)__null) = 5498; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
5499 | ||||
5500 | dict.mStorageArea = storage; | |||
5501 | ||||
5502 | RefPtr<StorageEvent> event = StorageEvent::Constructor(this, aType, dict); | |||
5503 | return event.forget(); | |||
5504 | } | |||
5505 | ||||
5506 | void nsGlobalWindowInner::Suspend(bool aIncludeSubWindows) { | |||
5507 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5507); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 5507; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5508 | ||||
5509 | // We can only safely suspend windows that are the current inner window. If | |||
5510 | // its not the current inner, then we are in one of two different cases. | |||
5511 | // Either we are in the bfcache or we are doomed window that is going away. | |||
5512 | // When a window becomes inactive we purposely avoid placing already suspended | |||
5513 | // windows into the bfcache. It only expects windows suspended due to the | |||
5514 | // Freeze() method which occurs while the window is still the current inner. | |||
5515 | // So we must not call Suspend() on bfcache windows at this point or this | |||
5516 | // invariant will be broken. If the window is doomed there is no point in | |||
5517 | // suspending it since it will soon be gone. | |||
5518 | if (!IsCurrentInnerWindow()) { | |||
5519 | return; | |||
5520 | } | |||
5521 | ||||
5522 | // All in-process descendants are also suspended. This ensure mSuspendDepth | |||
5523 | // is set properly and the timers are properly canceled for each in-process | |||
5524 | // descendant. | |||
5525 | if (aIncludeSubWindows) { | |||
5526 | CallOnInProcessDescendants(&nsGlobalWindowInner::Suspend, false); | |||
5527 | } | |||
5528 | ||||
5529 | mSuspendDepth += 1; | |||
5530 | if (mSuspendDepth != 1) { | |||
5531 | return; | |||
5532 | } | |||
5533 | ||||
5534 | if (mWindowGlobalChild) { | |||
5535 | mWindowGlobalChild->BlockBFCacheFor(BFCacheStatus::SUSPENDED); | |||
5536 | } | |||
5537 | ||||
5538 | nsCOMPtr<nsIDeviceSensors> ac = do_GetService(NS_DEVICE_SENSORS_CONTRACTID"@mozilla.org/devicesensors;1"); | |||
5539 | if (ac) { | |||
5540 | for (uint32_t i = 0; i < mEnabledSensors.Length(); i++) | |||
5541 | ac->RemoveWindowListener(mEnabledSensors[i], this); | |||
5542 | } | |||
5543 | DisableGamepadUpdates(); | |||
5544 | DisableVRUpdates(); | |||
5545 | ||||
5546 | SuspendWorkersForWindow(*this); | |||
5547 | ||||
5548 | for (RefPtr<mozilla::dom::SharedWorker> pinnedWorker : | |||
5549 | mSharedWorkers.ForwardRange()) { | |||
5550 | pinnedWorker->Suspend(); | |||
5551 | } | |||
5552 | ||||
5553 | SuspendIdleRequests(); | |||
5554 | ||||
5555 | mTimeoutManager->Suspend(); | |||
5556 | ||||
5557 | // Suspend all of the AudioContexts for this window | |||
5558 | for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) { | |||
5559 | mAudioContexts[i]->SuspendFromChrome(); | |||
5560 | } | |||
5561 | } | |||
5562 | ||||
5563 | void nsGlobalWindowInner::Resume(bool aIncludeSubWindows) { | |||
5564 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5564); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 5564; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5565 | ||||
5566 | // We can only safely resume a window if its the current inner window. If | |||
5567 | // its not the current inner, then we are in one of two different cases. | |||
5568 | // Either we are in the bfcache or we are doomed window that is going away. | |||
5569 | // If a window is suspended when it becomes inactive we purposely do not | |||
5570 | // put it in the bfcache, so Resume should never be needed in that case. | |||
5571 | // If the window is doomed then there is no point in resuming it. | |||
5572 | if (!IsCurrentInnerWindow()) { | |||
5573 | return; | |||
5574 | } | |||
5575 | ||||
5576 | // Resume all in-process descendants. This restores timers recursively | |||
5577 | // canceled in Suspend() and ensures all in-process descendants have the | |||
5578 | // correct mSuspendDepth. | |||
5579 | if (aIncludeSubWindows) { | |||
5580 | CallOnInProcessDescendants(&nsGlobalWindowInner::Resume, false); | |||
5581 | } | |||
5582 | ||||
5583 | if (mSuspendDepth == 0) { | |||
5584 | // Ignore if the window is not suspended. | |||
5585 | return; | |||
5586 | } | |||
5587 | ||||
5588 | mSuspendDepth -= 1; | |||
5589 | ||||
5590 | if (mSuspendDepth != 0) { | |||
5591 | return; | |||
5592 | } | |||
5593 | ||||
5594 | // We should not be able to resume a frozen window. It must be Thaw()'d | |||
5595 | // first. | |||
5596 | MOZ_ASSERT(mFreezeDepth == 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mFreezeDepth == 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mFreezeDepth == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mFreezeDepth == 0" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5596); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFreezeDepth == 0" ")"); do { *((volatile int*)__null) = 5596; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5597 | ||||
5598 | nsCOMPtr<nsIDeviceSensors> ac = do_GetService(NS_DEVICE_SENSORS_CONTRACTID"@mozilla.org/devicesensors;1"); | |||
5599 | if (ac) { | |||
5600 | for (uint32_t i = 0; i < mEnabledSensors.Length(); i++) | |||
5601 | ac->AddWindowListener(mEnabledSensors[i], this); | |||
5602 | } | |||
5603 | EnableGamepadUpdates(); | |||
5604 | EnableVRUpdates(); | |||
5605 | ||||
5606 | // Resume all of the AudioContexts for this window | |||
5607 | for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) { | |||
5608 | mAudioContexts[i]->ResumeFromChrome(); | |||
5609 | } | |||
5610 | ||||
5611 | if (RefPtr<MediaDevices> devices = GetExtantMediaDevices()) { | |||
5612 | devices->WindowResumed(); | |||
5613 | } | |||
5614 | ||||
5615 | mTimeoutManager->Resume(); | |||
5616 | ||||
5617 | ResumeIdleRequests(); | |||
5618 | ||||
5619 | // Resume all of the workers for this window. We must do this | |||
5620 | // after timeouts since workers may have queued events that can trigger | |||
5621 | // a setTimeout(). | |||
5622 | ResumeWorkersForWindow(*this); | |||
5623 | ||||
5624 | for (RefPtr<mozilla::dom::SharedWorker> pinnedWorker : | |||
5625 | mSharedWorkers.ForwardRange()) { | |||
5626 | pinnedWorker->Resume(); | |||
5627 | } | |||
5628 | ||||
5629 | if (mWindowGlobalChild) { | |||
5630 | mWindowGlobalChild->UnblockBFCacheFor(BFCacheStatus::SUSPENDED); | |||
5631 | } | |||
5632 | } | |||
5633 | ||||
5634 | bool nsGlobalWindowInner::IsSuspended() const { | |||
5635 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5635); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 5635; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5636 | return mSuspendDepth != 0; | |||
5637 | } | |||
5638 | ||||
5639 | void nsGlobalWindowInner::Freeze(bool aIncludeSubWindows) { | |||
5640 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5640); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 5640; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5641 | Suspend(aIncludeSubWindows); | |||
5642 | FreezeInternal(aIncludeSubWindows); | |||
5643 | } | |||
5644 | ||||
5645 | void nsGlobalWindowInner::FreezeInternal(bool aIncludeSubWindows) { | |||
5646 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5646); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 5646; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5647 | MOZ_DIAGNOSTIC_ASSERT(IsCurrentInnerWindow())do { static_assert( mozilla::detail::AssertionConditionType< decltype(IsCurrentInnerWindow())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsCurrentInnerWindow()))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("IsCurrentInnerWindow()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5647); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "IsCurrentInnerWindow()" ")"); do { *((volatile int*)__null) = 5647; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5648 | MOZ_DIAGNOSTIC_ASSERT(IsSuspended())do { static_assert( mozilla::detail::AssertionConditionType< decltype(IsSuspended())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsSuspended()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsSuspended()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5648); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "IsSuspended()" ")"); do { *((volatile int*)__null) = 5648; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5649 | ||||
5650 | HintIsLoading(false); | |||
5651 | ||||
5652 | if (aIncludeSubWindows) { | |||
5653 | CallOnInProcessChildren(&nsGlobalWindowInner::FreezeInternal, | |||
5654 | aIncludeSubWindows); | |||
5655 | } | |||
5656 | ||||
5657 | mFreezeDepth += 1; | |||
5658 | MOZ_ASSERT(mSuspendDepth >= mFreezeDepth)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mSuspendDepth >= mFreezeDepth)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mSuspendDepth >= mFreezeDepth ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "mSuspendDepth >= mFreezeDepth", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5658); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mSuspendDepth >= mFreezeDepth" ")"); do { *((volatile int*)__null) = 5658; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5659 | if (mFreezeDepth != 1) { | |||
5660 | return; | |||
5661 | } | |||
5662 | ||||
5663 | FreezeWorkersForWindow(*this); | |||
5664 | ||||
5665 | for (RefPtr<mozilla::dom::SharedWorker> pinnedWorker : | |||
5666 | mSharedWorkers.ForwardRange()) { | |||
5667 | pinnedWorker->Freeze(); | |||
5668 | } | |||
5669 | ||||
5670 | mTimeoutManager->Freeze(); | |||
5671 | if (mClientSource) { | |||
5672 | mClientSource->Freeze(); | |||
5673 | } | |||
5674 | ||||
5675 | NotifyDOMWindowFrozen(this); | |||
5676 | NotifyGlobalFrozen(); | |||
5677 | } | |||
5678 | ||||
5679 | void nsGlobalWindowInner::Thaw(bool aIncludeSubWindows) { | |||
5680 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5680); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 5680; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5681 | ThawInternal(aIncludeSubWindows); | |||
5682 | Resume(aIncludeSubWindows); | |||
5683 | } | |||
5684 | ||||
5685 | void nsGlobalWindowInner::ThawInternal(bool aIncludeSubWindows) { | |||
5686 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5686); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 5686; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5687 | MOZ_DIAGNOSTIC_ASSERT(IsCurrentInnerWindow())do { static_assert( mozilla::detail::AssertionConditionType< decltype(IsCurrentInnerWindow())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsCurrentInnerWindow()))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("IsCurrentInnerWindow()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5687); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "IsCurrentInnerWindow()" ")"); do { *((volatile int*)__null) = 5687; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5688 | MOZ_DIAGNOSTIC_ASSERT(IsSuspended())do { static_assert( mozilla::detail::AssertionConditionType< decltype(IsSuspended())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsSuspended()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsSuspended()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5688); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "IsSuspended()" ")"); do { *((volatile int*)__null) = 5688; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5689 | ||||
5690 | if (aIncludeSubWindows) { | |||
5691 | CallOnInProcessChildren(&nsGlobalWindowInner::ThawInternal, | |||
5692 | aIncludeSubWindows); | |||
5693 | } | |||
5694 | ||||
5695 | MOZ_ASSERT(mFreezeDepth != 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mFreezeDepth != 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mFreezeDepth != 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mFreezeDepth != 0" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5695); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFreezeDepth != 0" ")"); do { *((volatile int*)__null) = 5695; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5696 | mFreezeDepth -= 1; | |||
5697 | MOZ_ASSERT(mSuspendDepth >= mFreezeDepth)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mSuspendDepth >= mFreezeDepth)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mSuspendDepth >= mFreezeDepth ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "mSuspendDepth >= mFreezeDepth", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5697); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mSuspendDepth >= mFreezeDepth" ")"); do { *((volatile int*)__null) = 5697; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5698 | if (mFreezeDepth != 0) { | |||
5699 | return; | |||
5700 | } | |||
5701 | ||||
5702 | if (mClientSource) { | |||
5703 | mClientSource->Thaw(); | |||
5704 | } | |||
5705 | mTimeoutManager->Thaw(); | |||
5706 | ||||
5707 | ThawWorkersForWindow(*this); | |||
5708 | ||||
5709 | for (RefPtr<mozilla::dom::SharedWorker> pinnedWorker : | |||
5710 | mSharedWorkers.ForwardRange()) { | |||
5711 | pinnedWorker->Thaw(); | |||
5712 | } | |||
5713 | ||||
5714 | NotifyDOMWindowThawed(this); | |||
5715 | NotifyGlobalThawed(); | |||
5716 | } | |||
5717 | ||||
5718 | bool nsGlobalWindowInner::IsFrozen() const { | |||
5719 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5719); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 5719; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5720 | bool frozen = mFreezeDepth != 0; | |||
5721 | MOZ_ASSERT_IF(frozen, IsSuspended())do { if (frozen) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(IsSuspended())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsSuspended()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsSuspended()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5721); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsSuspended()" ")"); do { *((volatile int*)__null) = 5721; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
5722 | return frozen; | |||
5723 | } | |||
5724 | ||||
5725 | void nsGlobalWindowInner::SyncStateFromParentWindow() { | |||
5726 | // This method should only be called on an inner window that has been | |||
5727 | // assigned to an outer window already. | |||
5728 | MOZ_ASSERT(IsCurrentInnerWindow())do { static_assert( mozilla::detail::AssertionConditionType< decltype(IsCurrentInnerWindow())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsCurrentInnerWindow()))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("IsCurrentInnerWindow()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5728); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsCurrentInnerWindow()" ")"); do { *((volatile int*)__null) = 5728; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5729 | nsPIDOMWindowOuter* outer = GetOuterWindow(); | |||
5730 | MOZ_ASSERT(outer)do { static_assert( mozilla::detail::AssertionConditionType< decltype(outer)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(outer))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("outer", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5730); AnnotateMozCrashReason("MOZ_ASSERT" "(" "outer" ")") ; do { *((volatile int*)__null) = 5730; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5731 | ||||
5732 | // Attempt to find our parent windows. | |||
5733 | nsCOMPtr<Element> frame = outer->GetFrameElementInternal(); | |||
5734 | nsPIDOMWindowOuter* parentOuter = | |||
5735 | frame ? frame->OwnerDoc()->GetWindow() : nullptr; | |||
5736 | nsGlobalWindowInner* parentInner = | |||
5737 | parentOuter | |||
5738 | ? nsGlobalWindowInner::Cast(parentOuter->GetCurrentInnerWindow()) | |||
5739 | : nullptr; | |||
5740 | ||||
5741 | // If our outer is in a modal state, but our parent is not in a modal | |||
5742 | // state, then we must apply the suspend directly. If our parent is | |||
5743 | // in a modal state then we should get the suspend automatically | |||
5744 | // via the parentSuspendDepth application below. | |||
5745 | if ((!parentInner || !parentInner->IsInModalState()) && IsInModalState()) { | |||
5746 | Suspend(); | |||
5747 | } | |||
5748 | ||||
5749 | uint32_t parentFreezeDepth = parentInner ? parentInner->mFreezeDepth : 0; | |||
5750 | uint32_t parentSuspendDepth = parentInner ? parentInner->mSuspendDepth : 0; | |||
5751 | ||||
5752 | // Since every Freeze() calls Suspend(), the suspend count must | |||
5753 | // be equal or greater to the freeze count. | |||
5754 | MOZ_ASSERT(parentFreezeDepth <= parentSuspendDepth)do { static_assert( mozilla::detail::AssertionConditionType< decltype(parentFreezeDepth <= parentSuspendDepth)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(parentFreezeDepth <= parentSuspendDepth))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("parentFreezeDepth <= parentSuspendDepth" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5754); AnnotateMozCrashReason("MOZ_ASSERT" "(" "parentFreezeDepth <= parentSuspendDepth" ")"); do { *((volatile int*)__null) = 5754; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5755 | ||||
5756 | // First apply the Freeze() calls. | |||
5757 | for (uint32_t i = 0; i < parentFreezeDepth; ++i) { | |||
5758 | Freeze(); | |||
5759 | } | |||
5760 | ||||
5761 | // Now apply only the number of Suspend() calls to reach the target | |||
5762 | // suspend count after applying the Freeze() calls. | |||
5763 | for (uint32_t i = 0; i < (parentSuspendDepth - parentFreezeDepth); ++i) { | |||
5764 | Suspend(); | |||
5765 | } | |||
5766 | } | |||
5767 | ||||
5768 | void nsGlobalWindowInner::UpdateBackgroundState() { | |||
5769 | if (RefPtr<MediaDevices> devices = GetExtantMediaDevices()) { | |||
5770 | devices->BackgroundStateChanged(); | |||
5771 | } | |||
5772 | mTimeoutManager->UpdateBackgroundState(); | |||
5773 | ||||
5774 | UpdateWorkersBackgroundState(*this, IsBackgroundInternal()); | |||
5775 | } | |||
5776 | ||||
5777 | template <typename Method, typename... Args> | |||
5778 | CallState nsGlobalWindowInner::CallOnInProcessDescendantsInternal( | |||
5779 | BrowsingContext* aBrowsingContext, bool aChildOnly, Method aMethod, | |||
5780 | Args&&... aArgs) { | |||
5781 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5781); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 5781; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5782 | MOZ_ASSERT(aBrowsingContext)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aBrowsingContext)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aBrowsingContext))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aBrowsingContext" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5782); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBrowsingContext" ")"); do { *((volatile int*)__null) = 5782; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5783 | ||||
5784 | CallState state = CallState::Continue; | |||
5785 | for (const RefPtr<BrowsingContext>& bc : aBrowsingContext->Children()) { | |||
5786 | if (nsCOMPtr<nsPIDOMWindowOuter> pWin = bc->GetDOMWindow()) { | |||
5787 | auto* win = nsGlobalWindowOuter::Cast(pWin); | |||
5788 | if (nsGlobalWindowInner* inner = | |||
5789 | nsGlobalWindowInner::Cast(win->GetCurrentInnerWindow())) { | |||
5790 | // Call the descendant method using our helper CallDescendant() template | |||
5791 | // method. This allows us to handle both void returning methods and | |||
5792 | // methods that return CallState explicitly. For void returning methods | |||
5793 | // we assume CallState::Continue. | |||
5794 | using returnType = decltype((inner->*aMethod)(aArgs...)); | |||
5795 | state = CallDescendant<returnType>(inner, aMethod, aArgs...); | |||
5796 | ||||
5797 | if (state == CallState::Stop) { | |||
5798 | return state; | |||
5799 | } | |||
5800 | } | |||
5801 | } | |||
5802 | ||||
5803 | if (!aChildOnly) { | |||
5804 | state = CallOnInProcessDescendantsInternal(bc.get(), aChildOnly, aMethod, | |||
5805 | aArgs...); | |||
5806 | if (state == CallState::Stop) { | |||
5807 | return state; | |||
5808 | } | |||
5809 | } | |||
5810 | } | |||
5811 | ||||
5812 | return state; | |||
5813 | } | |||
5814 | ||||
5815 | Maybe<ClientInfo> nsGlobalWindowInner::GetClientInfo() const { | |||
5816 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5816); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 5816; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5817 | if (mDoc && mDoc->IsStaticDocument()) { | |||
5818 | if (Maybe<ClientInfo> info = mDoc->GetOriginalDocument()->GetClientInfo()) { | |||
5819 | return info; | |||
5820 | } | |||
5821 | } | |||
5822 | ||||
5823 | Maybe<ClientInfo> clientInfo; | |||
5824 | if (mClientSource) { | |||
5825 | clientInfo.emplace(mClientSource->Info()); | |||
5826 | } | |||
5827 | return clientInfo; | |||
5828 | } | |||
5829 | ||||
5830 | Maybe<ClientState> nsGlobalWindowInner::GetClientState() const { | |||
5831 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5831); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 5831; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5832 | if (mDoc && mDoc->IsStaticDocument()) { | |||
5833 | if (Maybe<ClientState> state = | |||
5834 | mDoc->GetOriginalDocument()->GetClientState()) { | |||
5835 | return state; | |||
5836 | } | |||
5837 | } | |||
5838 | ||||
5839 | Maybe<ClientState> clientState; | |||
5840 | if (mClientSource) { | |||
5841 | Result<ClientState, ErrorResult> res = mClientSource->SnapshotState(); | |||
5842 | if (res.isOk()) { | |||
5843 | clientState.emplace(res.unwrap()); | |||
5844 | } else { | |||
5845 | res.unwrapErr().SuppressException(); | |||
5846 | } | |||
5847 | } | |||
5848 | return clientState; | |||
5849 | } | |||
5850 | ||||
5851 | Maybe<ServiceWorkerDescriptor> nsGlobalWindowInner::GetController() const { | |||
5852 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5852); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 5852; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5853 | if (mDoc && mDoc->IsStaticDocument()) { | |||
5854 | if (Maybe<ServiceWorkerDescriptor> controller = | |||
5855 | mDoc->GetOriginalDocument()->GetController()) { | |||
5856 | return controller; | |||
5857 | } | |||
5858 | } | |||
5859 | ||||
5860 | Maybe<ServiceWorkerDescriptor> controller; | |||
5861 | if (mClientSource) { | |||
5862 | controller = mClientSource->GetController(); | |||
5863 | } | |||
5864 | return controller; | |||
5865 | } | |||
5866 | ||||
5867 | void nsGlobalWindowInner::SetCsp(nsIContentSecurityPolicy* aCsp) { | |||
5868 | if (!mClientSource) { | |||
5869 | return; | |||
5870 | } | |||
5871 | mClientSource->SetCsp(aCsp); | |||
5872 | // Also cache the CSP within the document | |||
5873 | mDoc->SetCsp(aCsp); | |||
5874 | ||||
5875 | if (mWindowGlobalChild) { | |||
5876 | mWindowGlobalChild->SendSetClientInfo(mClientSource->Info().ToIPC()); | |||
5877 | } | |||
5878 | } | |||
5879 | ||||
5880 | void nsGlobalWindowInner::SetPreloadCsp(nsIContentSecurityPolicy* aPreloadCsp) { | |||
5881 | if (!mClientSource) { | |||
5882 | return; | |||
5883 | } | |||
5884 | mClientSource->SetPreloadCsp(aPreloadCsp); | |||
5885 | // Also cache the preload CSP within the document | |||
5886 | mDoc->SetPreloadCsp(aPreloadCsp); | |||
5887 | ||||
5888 | if (mWindowGlobalChild) { | |||
5889 | mWindowGlobalChild->SendSetClientInfo(mClientSource->Info().ToIPC()); | |||
5890 | } | |||
5891 | } | |||
5892 | ||||
5893 | nsIContentSecurityPolicy* nsGlobalWindowInner::GetCsp() { | |||
5894 | if (mDoc) { | |||
5895 | return mDoc->GetCsp(); | |||
5896 | } | |||
5897 | ||||
5898 | // If the window is partially torn down and has its document nulled out, | |||
5899 | // we query the CSP we snapshot in FreeInnerObjects. | |||
5900 | if (mDocumentCsp) { | |||
5901 | return mDocumentCsp; | |||
5902 | } | |||
5903 | return nullptr; | |||
5904 | } | |||
5905 | ||||
5906 | RefPtr<ServiceWorker> nsGlobalWindowInner::GetOrCreateServiceWorker( | |||
5907 | const ServiceWorkerDescriptor& aDescriptor) { | |||
5908 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5908); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 5908; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5909 | RefPtr<ServiceWorker> ref; | |||
5910 | ForEachGlobalTeardownObserver( | |||
5911 | [&](GlobalTeardownObserver* aObserver, bool* aDoneOut) { | |||
5912 | RefPtr<ServiceWorker> sw = do_QueryObject(aObserver); | |||
5913 | if (!sw || !sw->Descriptor().Matches(aDescriptor)) { | |||
5914 | return; | |||
5915 | } | |||
5916 | ||||
5917 | ref = std::move(sw); | |||
5918 | *aDoneOut = true; | |||
5919 | }); | |||
5920 | ||||
5921 | if (!ref) { | |||
5922 | ref = ServiceWorker::Create(this, aDescriptor); | |||
5923 | } | |||
5924 | ||||
5925 | return ref; | |||
5926 | } | |||
5927 | ||||
5928 | RefPtr<mozilla::dom::ServiceWorkerRegistration> | |||
5929 | nsGlobalWindowInner::GetServiceWorkerRegistration( | |||
5930 | const mozilla::dom::ServiceWorkerRegistrationDescriptor& aDescriptor) | |||
5931 | const { | |||
5932 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5932); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 5932; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5933 | RefPtr<ServiceWorkerRegistration> ref; | |||
5934 | ForEachGlobalTeardownObserver( | |||
5935 | [&](GlobalTeardownObserver* aObserver, bool* aDoneOut) { | |||
5936 | RefPtr<ServiceWorkerRegistration> swr = do_QueryObject(aObserver); | |||
5937 | if (!swr || !swr->MatchesDescriptor(aDescriptor)) { | |||
5938 | return; | |||
5939 | } | |||
5940 | ||||
5941 | ref = std::move(swr); | |||
5942 | *aDoneOut = true; | |||
5943 | }); | |||
5944 | return ref; | |||
5945 | } | |||
5946 | ||||
5947 | RefPtr<ServiceWorkerRegistration> | |||
5948 | nsGlobalWindowInner::GetOrCreateServiceWorkerRegistration( | |||
5949 | const ServiceWorkerRegistrationDescriptor& aDescriptor) { | |||
5950 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 5950); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 5950; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
5951 | RefPtr<ServiceWorkerRegistration> ref = | |||
5952 | GetServiceWorkerRegistration(aDescriptor); | |||
5953 | if (!ref) { | |||
5954 | ref = ServiceWorkerRegistration::CreateForMainThread(this, aDescriptor); | |||
5955 | } | |||
5956 | return ref; | |||
5957 | } | |||
5958 | ||||
5959 | StorageAccess nsGlobalWindowInner::GetStorageAccess() { | |||
5960 | return StorageAllowedForWindow(this); | |||
5961 | } | |||
5962 | ||||
5963 | nsresult nsGlobalWindowInner::FireDelayedDOMEvents(bool aIncludeSubWindows) { | |||
5964 | // Fires an offline status event if the offline status has changed | |||
5965 | FireOfflineStatusEventIfChanged(); | |||
5966 | ||||
5967 | if (!aIncludeSubWindows) { | |||
5968 | return NS_OK; | |||
5969 | } | |||
5970 | ||||
5971 | nsCOMPtr<nsIDocShell> docShell = GetDocShell(); | |||
5972 | if (docShell) { | |||
5973 | int32_t childCount = 0; | |||
5974 | docShell->GetInProcessChildCount(&childCount); | |||
5975 | ||||
5976 | // Take a copy of the current children so that modifications to | |||
5977 | // the child list don't affect to the iteration. | |||
5978 | AutoTArray<nsCOMPtr<nsIDocShellTreeItem>, 8> children; | |||
5979 | for (int32_t i = 0; i < childCount; ++i) { | |||
5980 | nsCOMPtr<nsIDocShellTreeItem> childShell; | |||
5981 | docShell->GetInProcessChildAt(i, getter_AddRefs(childShell)); | |||
5982 | if (childShell) { | |||
5983 | children.AppendElement(childShell); | |||
5984 | } | |||
5985 | } | |||
5986 | ||||
5987 | for (nsCOMPtr<nsIDocShellTreeItem> childShell : children) { | |||
5988 | if (nsCOMPtr<nsPIDOMWindowOuter> pWin = childShell->GetWindow()) { | |||
5989 | auto* win = nsGlobalWindowOuter::Cast(pWin); | |||
5990 | win->FireDelayedDOMEvents(true); | |||
5991 | } | |||
5992 | } | |||
5993 | } | |||
5994 | ||||
5995 | return NS_OK; | |||
5996 | } | |||
5997 | ||||
5998 | //***************************************************************************** | |||
5999 | // nsGlobalWindowInner: Window Control Functions | |||
6000 | //***************************************************************************** | |||
6001 | ||||
6002 | nsPIDOMWindowOuter* nsGlobalWindowInner::GetInProcessParentInternal() { | |||
6003 | nsGlobalWindowOuter* outer = GetOuterWindowInternal(); | |||
6004 | if (!outer) { | |||
6005 | // No outer window available! | |||
6006 | return nullptr; | |||
6007 | } | |||
6008 | return outer->GetInProcessParentInternal(); | |||
6009 | } | |||
6010 | ||||
6011 | nsIPrincipal* nsGlobalWindowInner::GetTopLevelAntiTrackingPrincipal() { | |||
6012 | nsPIDOMWindowOuter* outerWindow = GetOuterWindowInternal(); | |||
6013 | if (!outerWindow) { | |||
6014 | return nullptr; | |||
6015 | } | |||
6016 | ||||
6017 | nsPIDOMWindowOuter* topLevelOuterWindow = | |||
6018 | GetBrowsingContext()->Top()->GetDOMWindow(); | |||
6019 | if (!topLevelOuterWindow) { | |||
6020 | return nullptr; | |||
6021 | } | |||
6022 | ||||
6023 | bool stopAtOurLevel = | |||
6024 | mDoc && mDoc->CookieJarSettings()->GetCookieBehavior() == | |||
6025 | nsICookieService::BEHAVIOR_REJECT_TRACKER; | |||
6026 | ||||
6027 | if (stopAtOurLevel && topLevelOuterWindow == outerWindow) { | |||
6028 | return nullptr; | |||
6029 | } | |||
6030 | ||||
6031 | nsPIDOMWindowInner* topLevelInnerWindow = | |||
6032 | topLevelOuterWindow->GetCurrentInnerWindow(); | |||
6033 | if (NS_WARN_IF(!topLevelInnerWindow)NS_warn_if_impl(!topLevelInnerWindow, "!topLevelInnerWindow", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 6033)) { | |||
6034 | return nullptr; | |||
6035 | } | |||
6036 | ||||
6037 | nsIPrincipal* topLevelPrincipal = | |||
6038 | nsGlobalWindowInner::Cast(topLevelInnerWindow)->GetPrincipal(); | |||
6039 | if (NS_WARN_IF(!topLevelPrincipal)NS_warn_if_impl(!topLevelPrincipal, "!topLevelPrincipal", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 6039)) { | |||
6040 | return nullptr; | |||
6041 | } | |||
6042 | ||||
6043 | return topLevelPrincipal; | |||
6044 | } | |||
6045 | ||||
6046 | nsIPrincipal* nsGlobalWindowInner::GetClientPrincipal() { | |||
6047 | return mClientSource ? mClientSource->GetPrincipal() : nullptr; | |||
6048 | } | |||
6049 | ||||
6050 | bool nsGlobalWindowInner::IsInFullScreenTransition() { | |||
6051 | if (!mIsChrome) { | |||
6052 | return false; | |||
6053 | } | |||
6054 | ||||
6055 | nsGlobalWindowOuter* outerWindow = GetOuterWindowInternal(); | |||
6056 | if (!outerWindow) { | |||
6057 | return false; | |||
6058 | } | |||
6059 | ||||
6060 | return outerWindow->mIsInFullScreenTransition; | |||
6061 | } | |||
6062 | ||||
6063 | //***************************************************************************** | |||
6064 | // nsGlobalWindowInner: Timeout Functions | |||
6065 | //***************************************************************************** | |||
6066 | ||||
6067 | class WindowScriptTimeoutHandler final : public ScriptTimeoutHandler { | |||
6068 | public: | |||
6069 | NS_DECL_ISUPPORTS_INHERITEDpublic: virtual nsresult QueryInterface(const nsIID& aIID , void** aInstancePtr) override; virtual MozExternalRefCountType AddRef(void) override; virtual MozExternalRefCountType Release (void) override; | |||
6070 | NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(WindowScriptTimeoutHandler,class cycleCollection : public ScriptTimeoutHandler::cycleCollection { public: constexpr explicit cycleCollection(Flags aFlags = 0 ) : ScriptTimeoutHandler::cycleCollection(aFlags) {} private: public: virtual nsresult TraverseNative(void* p, nsCycleCollectionTraversalCallback & cb) override; virtual const char* ClassName() override { return "WindowScriptTimeoutHandler"; }; static WindowScriptTimeoutHandler * Downcast(nsISupports* s) { return static_cast<WindowScriptTimeoutHandler *>(static_cast<ScriptTimeoutHandler*>( ScriptTimeoutHandler ::cycleCollection::Downcast(s))); } virtual void Unlink(void* p) override; static constexpr nsXPCOMCycleCollectionParticipant * GetParticipant() { return &WindowScriptTimeoutHandler:: _cycleCollectorGlobal; } }; virtual void CheckForRightParticipant () override { nsXPCOMCycleCollectionParticipant* p; CallQueryInterface (this, &p); do { static_assert( mozilla::detail::AssertionConditionType <decltype(p == &_cycleCollectorGlobal)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(p == &_cycleCollectorGlobal ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "p == &_cycleCollectorGlobal" " (" "WindowScriptTimeoutHandler" " should QI to its own CC participant" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 6071); AnnotateMozCrashReason("MOZ_ASSERT" "(" "p == &_cycleCollectorGlobal" ") (" "WindowScriptTimeoutHandler" " should QI to its own CC participant" ")"); do { *((volatile int*)__null) = 6071; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } static cycleCollection _cycleCollectorGlobal; | |||
6071 | ScriptTimeoutHandler)class cycleCollection : public ScriptTimeoutHandler::cycleCollection { public: constexpr explicit cycleCollection(Flags aFlags = 0 ) : ScriptTimeoutHandler::cycleCollection(aFlags) {} private: public: virtual nsresult TraverseNative(void* p, nsCycleCollectionTraversalCallback & cb) override; virtual const char* ClassName() override { return "WindowScriptTimeoutHandler"; }; static WindowScriptTimeoutHandler * Downcast(nsISupports* s) { return static_cast<WindowScriptTimeoutHandler *>(static_cast<ScriptTimeoutHandler*>( ScriptTimeoutHandler ::cycleCollection::Downcast(s))); } virtual void Unlink(void* p) override; static constexpr nsXPCOMCycleCollectionParticipant * GetParticipant() { return &WindowScriptTimeoutHandler:: _cycleCollectorGlobal; } }; virtual void CheckForRightParticipant () override { nsXPCOMCycleCollectionParticipant* p; CallQueryInterface (this, &p); do { static_assert( mozilla::detail::AssertionConditionType <decltype(p == &_cycleCollectorGlobal)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(p == &_cycleCollectorGlobal ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "p == &_cycleCollectorGlobal" " (" "WindowScriptTimeoutHandler" " should QI to its own CC participant" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 6071); AnnotateMozCrashReason("MOZ_ASSERT" "(" "p == &_cycleCollectorGlobal" ") (" "WindowScriptTimeoutHandler" " should QI to its own CC participant" ")"); do { *((volatile int*)__null) = 6071; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } static cycleCollection _cycleCollectorGlobal; | |||
6072 | ||||
6073 | WindowScriptTimeoutHandler(JSContext* aCx, nsIGlobalObject* aGlobal, | |||
6074 | const nsAString& aExpression) | |||
6075 | : ScriptTimeoutHandler(aCx, aGlobal, aExpression), | |||
6076 | mInitiatingScript(ScriptLoader::GetActiveScript(aCx)) {} | |||
6077 | ||||
6078 | MOZ_CAN_RUN_SCRIPT virtual bool Call(const char* aExecutionReason) override; | |||
6079 | ||||
6080 | private: | |||
6081 | virtual ~WindowScriptTimeoutHandler() = default; | |||
6082 | ||||
6083 | // Initiating script for use when evaluating mExpr on the main thread. | |||
6084 | RefPtr<JS::loader::LoadedScript> mInitiatingScript; | |||
6085 | }; | |||
6086 | ||||
6087 | NS_IMPL_CYCLE_COLLECTION_INHERITED(WindowScriptTimeoutHandler,WindowScriptTimeoutHandler::cycleCollection WindowScriptTimeoutHandler ::_cycleCollectorGlobal; void WindowScriptTimeoutHandler::cycleCollection ::Unlink(void* p) { WindowScriptTimeoutHandler* tmp = DowncastCCParticipant <WindowScriptTimeoutHandler>(p); nsISupports* s = static_cast <nsISupports*>(p); ScriptTimeoutHandler::cycleCollection ::Unlink(s); ImplCycleCollectionUnlink(tmp->mInitiatingScript ); (void)tmp; } nsresult WindowScriptTimeoutHandler::cycleCollection ::TraverseNative( void* p, nsCycleCollectionTraversalCallback & cb) { WindowScriptTimeoutHandler* tmp = DowncastCCParticipant <WindowScriptTimeoutHandler>(p); nsISupports* s = static_cast <nsISupports*>(p); if (ScriptTimeoutHandler::cycleCollection ::TraverseNative(s, cb) == NS_SUCCESS_INTERRUPTED_TRAVERSE) { return NS_SUCCESS_INTERRUPTED_TRAVERSE; } ImplCycleCollectionTraverse (cb, tmp->mInitiatingScript, "mInitiatingScript", 0); (void )tmp; return NS_OK; } | |||
6088 | ScriptTimeoutHandler, mInitiatingScript)WindowScriptTimeoutHandler::cycleCollection WindowScriptTimeoutHandler ::_cycleCollectorGlobal; void WindowScriptTimeoutHandler::cycleCollection ::Unlink(void* p) { WindowScriptTimeoutHandler* tmp = DowncastCCParticipant <WindowScriptTimeoutHandler>(p); nsISupports* s = static_cast <nsISupports*>(p); ScriptTimeoutHandler::cycleCollection ::Unlink(s); ImplCycleCollectionUnlink(tmp->mInitiatingScript ); (void)tmp; } nsresult WindowScriptTimeoutHandler::cycleCollection ::TraverseNative( void* p, nsCycleCollectionTraversalCallback & cb) { WindowScriptTimeoutHandler* tmp = DowncastCCParticipant <WindowScriptTimeoutHandler>(p); nsISupports* s = static_cast <nsISupports*>(p); if (ScriptTimeoutHandler::cycleCollection ::TraverseNative(s, cb) == NS_SUCCESS_INTERRUPTED_TRAVERSE) { return NS_SUCCESS_INTERRUPTED_TRAVERSE; } ImplCycleCollectionTraverse (cb, tmp->mInitiatingScript, "mInitiatingScript", 0); (void )tmp; return NS_OK; } | |||
6089 | ||||
6090 | NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WindowScriptTimeoutHandler)nsresult WindowScriptTimeoutHandler::QueryInterface(const nsIID & aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!" , "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 6090); MOZ_PretendNoReturn(); } } while (0); nsISupports* foundInterface ; if (TopThreeWordsEquals( aIID, (nsXPCOMCycleCollectionParticipant ::COMTypeInfo<nsXPCOMCycleCollectionParticipant, void>:: kIID), (nsCycleCollectionISupports::COMTypeInfo<nsCycleCollectionISupports , void>::kIID)) && (LowWordEquals(aIID, (nsXPCOMCycleCollectionParticipant ::COMTypeInfo<nsXPCOMCycleCollectionParticipant, void>:: kIID)) || LowWordEquals(aIID, (nsCycleCollectionISupports::COMTypeInfo <nsCycleCollectionISupports, void>::kIID)))) { if (LowWordEquals (aIID, (nsXPCOMCycleCollectionParticipant::COMTypeInfo<nsXPCOMCycleCollectionParticipant , void>::kIID))) { *aInstancePtr = WindowScriptTimeoutHandler ::cycleCollection::GetParticipant(); return NS_OK; } if (LowWordEquals (aIID, (nsCycleCollectionISupports::COMTypeInfo<nsCycleCollectionISupports , void>::kIID))) { *aInstancePtr = WindowScriptTimeoutHandler ::cycleCollection::Upcast(this); return NS_OK; } foundInterface = nullptr; } else | |||
6091 | NS_INTERFACE_MAP_END_INHERITING(ScriptTimeoutHandler)foundInterface = 0; nsresult status; if (!foundInterface) status = ScriptTimeoutHandler::QueryInterface(aIID, (void**)&foundInterface ); else { (foundInterface)->AddRef(); status = NS_OK; } *aInstancePtr = foundInterface; return status; } | |||
6092 | ||||
6093 | NS_IMPL_ADDREF_INHERITED(WindowScriptTimeoutHandler, ScriptTimeoutHandler)MozExternalRefCountType WindowScriptTimeoutHandler::AddRef(void ) { static_assert(!std::is_destructible_v<WindowScriptTimeoutHandler >, "Reference-counted class " "WindowScriptTimeoutHandler" " should not have a public destructor. " "Make this class's destructor non-public" ); nsrefcnt r = ScriptTimeoutHandler::AddRef(); if constexpr ( ::mozilla::detail::ShouldLogInheritedRefcnt<WindowScriptTimeoutHandler >) { NS_LogAddRef((this), (r), ("WindowScriptTimeoutHandler" ), (uint32_t)(sizeof(*this))); } return r; } | |||
6094 | NS_IMPL_RELEASE_INHERITED(WindowScriptTimeoutHandler, ScriptTimeoutHandler)MozExternalRefCountType WindowScriptTimeoutHandler::Release(void ) { nsrefcnt r = ScriptTimeoutHandler::Release(); if constexpr (::mozilla::detail::ShouldLogInheritedRefcnt<WindowScriptTimeoutHandler >) { NS_LogRelease((this), (r), ("WindowScriptTimeoutHandler" )); } return r; } | |||
6095 | ||||
6096 | bool WindowScriptTimeoutHandler::Call(const char* aExecutionReason) { | |||
6097 | // New script entry point required, due to the "Create a script" sub-step | |||
6098 | // of | |||
6099 | // http://www.whatwg.org/specs/web-apps/current-work/#timer-initialisation-steps | |||
6100 | nsAutoMicroTask mt; | |||
6101 | AutoEntryScript aes(mGlobal, aExecutionReason, true); | |||
6102 | JS::CompileOptions options(aes.cx()); | |||
6103 | options.setFileAndLine(mFileName.get(), mLineNo); | |||
6104 | options.setNoScriptRval(true); | |||
6105 | options.setIntroductionType("domTimer"); | |||
6106 | JS::Rooted<JSObject*> global(aes.cx(), mGlobal->GetGlobalJSObject()); | |||
6107 | { | |||
6108 | JSExecutionContext exec(aes.cx(), global, options); | |||
6109 | nsresult rv = exec.Compile(mExpr); | |||
6110 | ||||
6111 | JS::Rooted<JSScript*> script(aes.cx(), exec.MaybeGetScript()); | |||
6112 | if (script) { | |||
6113 | if (mInitiatingScript) { | |||
6114 | mInitiatingScript->AssociateWithScript(script); | |||
6115 | } | |||
6116 | ||||
6117 | rv = exec.ExecScript(); | |||
6118 | } | |||
6119 | ||||
6120 | if (rv == NS_SUCCESS_DOM_SCRIPT_EVALUATION_THREW_UNCATCHABLE) { | |||
6121 | return false; | |||
6122 | } | |||
6123 | } | |||
6124 | ||||
6125 | return true; | |||
6126 | }; | |||
6127 | ||||
6128 | nsGlobalWindowInner* nsGlobalWindowInner::InnerForSetTimeoutOrInterval( | |||
6129 | ErrorResult& aError) { | |||
6130 | nsGlobalWindowOuter* outer = GetOuterWindowInternal(); | |||
6131 | nsPIDOMWindowInner* currentInner = | |||
6132 | outer ? outer->GetCurrentInnerWindow() : this; | |||
6133 | ||||
6134 | // If forwardTo is not the window with an active document then we want the | |||
6135 | // call to setTimeout/Interval to be a noop, so return null but don't set an | |||
6136 | // error. | |||
6137 | return HasActiveDocument() ? nsGlobalWindowInner::Cast(currentInner) | |||
6138 | : nullptr; | |||
6139 | } | |||
6140 | ||||
6141 | int32_t nsGlobalWindowInner::SetTimeout(JSContext* aCx, Function& aFunction, | |||
6142 | int32_t aTimeout, | |||
6143 | const Sequence<JS::Value>& aArguments, | |||
6144 | ErrorResult& aError) { | |||
6145 | return SetTimeoutOrInterval(aCx, aFunction, aTimeout, aArguments, false, | |||
6146 | aError); | |||
6147 | } | |||
6148 | ||||
6149 | int32_t nsGlobalWindowInner::SetTimeout(JSContext* aCx, | |||
6150 | const nsAString& aHandler, | |||
6151 | int32_t aTimeout, | |||
6152 | const Sequence<JS::Value>& /* unused */, | |||
6153 | ErrorResult& aError) { | |||
6154 | return SetTimeoutOrInterval(aCx, aHandler, aTimeout, false, aError); | |||
6155 | } | |||
6156 | ||||
6157 | int32_t nsGlobalWindowInner::SetInterval(JSContext* aCx, Function& aFunction, | |||
6158 | const int32_t aTimeout, | |||
6159 | const Sequence<JS::Value>& aArguments, | |||
6160 | ErrorResult& aError) { | |||
6161 | return SetTimeoutOrInterval(aCx, aFunction, aTimeout, aArguments, true, | |||
6162 | aError); | |||
6163 | } | |||
6164 | ||||
6165 | int32_t nsGlobalWindowInner::SetInterval( | |||
6166 | JSContext* aCx, const nsAString& aHandler, const int32_t aTimeout, | |||
6167 | const Sequence<JS::Value>& /* unused */, ErrorResult& aError) { | |||
6168 | return SetTimeoutOrInterval(aCx, aHandler, aTimeout, true, aError); | |||
6169 | } | |||
6170 | ||||
6171 | int32_t nsGlobalWindowInner::SetTimeoutOrInterval( | |||
6172 | JSContext* aCx, Function& aFunction, int32_t aTimeout, | |||
6173 | const Sequence<JS::Value>& aArguments, bool aIsInterval, | |||
6174 | ErrorResult& aError) { | |||
6175 | nsGlobalWindowInner* inner = InnerForSetTimeoutOrInterval(aError); | |||
6176 | if (!inner) { | |||
6177 | return -1; | |||
6178 | } | |||
6179 | ||||
6180 | if (inner != this) { | |||
6181 | RefPtr<nsGlobalWindowInner> innerRef(inner); | |||
6182 | return innerRef->SetTimeoutOrInterval(aCx, aFunction, aTimeout, aArguments, | |||
6183 | aIsInterval, aError); | |||
6184 | } | |||
6185 | ||||
6186 | DebuggerNotificationDispatch( | |||
6187 | this, aIsInterval ? DebuggerNotificationType::SetInterval | |||
6188 | : DebuggerNotificationType::SetTimeout); | |||
6189 | ||||
6190 | if (!GetContextInternal() || !HasJSGlobal()) { | |||
6191 | // This window was already closed, or never properly initialized, | |||
6192 | // don't let a timer be scheduled on such a window. | |||
6193 | aError.Throw(NS_ERROR_NOT_INITIALIZED); | |||
6194 | return 0; | |||
6195 | } | |||
6196 | ||||
6197 | nsTArray<JS::Heap<JS::Value>> args; | |||
6198 | if (!args.AppendElements(aArguments, fallible)) { | |||
6199 | aError.Throw(NS_ERROR_OUT_OF_MEMORY); | |||
6200 | return 0; | |||
6201 | } | |||
6202 | ||||
6203 | RefPtr<TimeoutHandler> handler = | |||
6204 | new CallbackTimeoutHandler(aCx, this, &aFunction, std::move(args)); | |||
6205 | ||||
6206 | int32_t result; | |||
6207 | aError = | |||
6208 | mTimeoutManager->SetTimeout(handler, aTimeout, aIsInterval, | |||
6209 | Timeout::Reason::eTimeoutOrInterval, &result); | |||
6210 | return result; | |||
6211 | } | |||
6212 | ||||
6213 | int32_t nsGlobalWindowInner::SetTimeoutOrInterval(JSContext* aCx, | |||
6214 | const nsAString& aHandler, | |||
6215 | int32_t aTimeout, | |||
6216 | bool aIsInterval, | |||
6217 | ErrorResult& aError) { | |||
6218 | nsGlobalWindowInner* inner = InnerForSetTimeoutOrInterval(aError); | |||
6219 | if (!inner) { | |||
6220 | return -1; | |||
6221 | } | |||
6222 | ||||
6223 | if (inner != this) { | |||
6224 | RefPtr<nsGlobalWindowInner> innerRef(inner); | |||
6225 | return innerRef->SetTimeoutOrInterval(aCx, aHandler, aTimeout, aIsInterval, | |||
6226 | aError); | |||
6227 | } | |||
6228 | ||||
6229 | DebuggerNotificationDispatch( | |||
6230 | this, aIsInterval ? DebuggerNotificationType::SetInterval | |||
6231 | : DebuggerNotificationType::SetTimeout); | |||
6232 | ||||
6233 | if (!GetContextInternal() || !HasJSGlobal()) { | |||
6234 | // This window was already closed, or never properly initialized, | |||
6235 | // don't let a timer be scheduled on such a window. | |||
6236 | aError.Throw(NS_ERROR_NOT_INITIALIZED); | |||
6237 | return 0; | |||
6238 | } | |||
6239 | ||||
6240 | bool allowEval = false; | |||
6241 | aError = CSPEvalChecker::CheckForWindow(aCx, this, aHandler, &allowEval); | |||
6242 | if (NS_WARN_IF(aError.Failed())NS_warn_if_impl(aError.Failed(), "aError.Failed()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 6242) || !allowEval) { | |||
6243 | return 0; | |||
6244 | } | |||
6245 | ||||
6246 | RefPtr<TimeoutHandler> handler = | |||
6247 | new WindowScriptTimeoutHandler(aCx, this, aHandler); | |||
6248 | ||||
6249 | int32_t result; | |||
6250 | aError = | |||
6251 | mTimeoutManager->SetTimeout(handler, aTimeout, aIsInterval, | |||
6252 | Timeout::Reason::eTimeoutOrInterval, &result); | |||
6253 | return result; | |||
6254 | } | |||
6255 | ||||
6256 | static const char* GetTimeoutReasonString(Timeout* aTimeout) { | |||
6257 | switch (aTimeout->mReason) { | |||
6258 | case Timeout::Reason::eTimeoutOrInterval: | |||
6259 | if (aTimeout->mIsInterval) { | |||
6260 | return "setInterval handler"; | |||
6261 | } | |||
6262 | return "setTimeout handler"; | |||
6263 | case Timeout::Reason::eIdleCallbackTimeout: | |||
6264 | return "setIdleCallback handler (timed out)"; | |||
6265 | case Timeout::Reason::eAbortSignalTimeout: | |||
6266 | return "AbortSignal timeout"; | |||
6267 | case Timeout::Reason::eDelayedWebTaskTimeout: | |||
6268 | return "delayedWebTaskCallback handler (timed out)"; | |||
6269 | default: | |||
6270 | MOZ_CRASH("Unexpected enum value")do { do { } while (false); MOZ_ReportCrash("" "Unexpected enum value" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 6270); AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected enum value" ")"); do { *((volatile int*)__null) = 6270; __attribute__((nomerge )) ::abort(); } while (false); } while (false); | |||
6271 | return ""; | |||
6272 | } | |||
6273 | MOZ_CRASH("Unexpected enum value")do { do { } while (false); MOZ_ReportCrash("" "Unexpected enum value" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 6273); AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected enum value" ")"); do { *((volatile int*)__null) = 6273; __attribute__((nomerge )) ::abort(); } while (false); } while (false); | |||
6274 | return ""; | |||
6275 | } | |||
6276 | ||||
6277 | bool nsGlobalWindowInner::RunTimeoutHandler(Timeout* aTimeout, | |||
6278 | nsIScriptContext* aScx) { | |||
6279 | // Hold on to the timeout in case mExpr or mFunObj releases its | |||
6280 | // doc. | |||
6281 | // XXXbz Our caller guarantees it'll hold on to the timeout (because | |||
6282 | // we're MOZ_CAN_RUN_SCRIPT), so we can probably stop doing that... | |||
6283 | RefPtr<Timeout> timeout = aTimeout; | |||
6284 | Timeout* last_running_timeout = mTimeoutManager->BeginRunningTimeout(timeout); | |||
6285 | timeout->mRunning = true; | |||
6286 | ||||
6287 | // Push this timeout's popup control state, which should only be | |||
6288 | // enabled the first time a timeout fires that was created while | |||
6289 | // popups were enabled and with a delay less than | |||
6290 | // "dom.disable_open_click_delay". | |||
6291 | AutoPopupStatePusherAutoPopupStatePusherInternal popupStatePusher(timeout->mPopupState); | |||
6292 | ||||
6293 | // Clear the timeout's popup state, if any, to prevent interval | |||
6294 | // timeouts from repeatedly opening poups. | |||
6295 | timeout->mPopupState = PopupBlocker::openAbused; | |||
6296 | ||||
6297 | uint32_t nestingLevel = TimeoutManager::GetNestingLevel(); | |||
6298 | TimeoutManager::SetNestingLevel(timeout->mNestingLevel); | |||
6299 | ||||
6300 | const char* reason = GetTimeoutReasonString(timeout); | |||
6301 | ||||
6302 | nsCString str; | |||
6303 | if (profiler_thread_is_being_profiled_for_markers()) { | |||
6304 | TimeDuration originalInterval = timeout->When() - timeout->SubmitTime(); | |||
6305 | str.Append(reason); | |||
6306 | str.Append(" with interval "); | |||
6307 | str.AppendInt(int(originalInterval.ToMilliseconds())); | |||
6308 | str.Append("ms: "); | |||
6309 | nsCString handlerDescription; | |||
6310 | timeout->mScriptHandler->GetDescription(handlerDescription); | |||
6311 | str.Append(handlerDescription); | |||
6312 | } | |||
6313 | AUTO_PROFILER_MARKER_TEXT("setTimeout callback", DOM,AutoProfilerTextMarker raiiObject6317( "setTimeout callback", ::mozilla::baseprofiler::category::DOM, MarkerOptions(MarkerStack ::TakeBacktrace( timeout->TakeProfilerBacktrace()), MarkerInnerWindowId (mWindowID)), str) | |||
6314 | MarkerOptions(MarkerStack::TakeBacktrace(AutoProfilerTextMarker raiiObject6317( "setTimeout callback", ::mozilla::baseprofiler::category::DOM, MarkerOptions(MarkerStack ::TakeBacktrace( timeout->TakeProfilerBacktrace()), MarkerInnerWindowId (mWindowID)), str) | |||
6315 | timeout->TakeProfilerBacktrace()),AutoProfilerTextMarker raiiObject6317( "setTimeout callback", ::mozilla::baseprofiler::category::DOM, MarkerOptions(MarkerStack ::TakeBacktrace( timeout->TakeProfilerBacktrace()), MarkerInnerWindowId (mWindowID)), str) | |||
6316 | MarkerInnerWindowId(mWindowID)),AutoProfilerTextMarker raiiObject6317( "setTimeout callback", ::mozilla::baseprofiler::category::DOM, MarkerOptions(MarkerStack ::TakeBacktrace( timeout->TakeProfilerBacktrace()), MarkerInnerWindowId (mWindowID)), str) | |||
6317 | str)AutoProfilerTextMarker raiiObject6317( "setTimeout callback", ::mozilla::baseprofiler::category::DOM, MarkerOptions(MarkerStack ::TakeBacktrace( timeout->TakeProfilerBacktrace()), MarkerInnerWindowId (mWindowID)), str); | |||
6318 | ||||
6319 | bool abortIntervalHandler; | |||
6320 | { | |||
6321 | RefPtr<TimeoutHandler> handler(timeout->mScriptHandler); | |||
6322 | ||||
6323 | CallbackDebuggerNotificationGuard guard( | |||
6324 | this, timeout->mIsInterval | |||
6325 | ? DebuggerNotificationType::SetIntervalCallback | |||
6326 | : DebuggerNotificationType::SetTimeoutCallback); | |||
6327 | abortIntervalHandler = !handler->Call(reason); | |||
6328 | } | |||
6329 | ||||
6330 | // If we received an uncatchable exception, do not schedule the timeout again. | |||
6331 | // This allows the slow script dialog to break easy DoS attacks like | |||
6332 | // setInterval(function() { while(1); }, 100); | |||
6333 | if (abortIntervalHandler) { | |||
6334 | // If it wasn't an interval timer to begin with, this does nothing. If it | |||
6335 | // was, we'll treat it as a timeout that we just ran and discard it when | |||
6336 | // we return. | |||
6337 | timeout->mIsInterval = false; | |||
6338 | } | |||
6339 | ||||
6340 | // We ignore any failures from calling EvaluateString() on the context or | |||
6341 | // Call() on a Function here since we're in a loop | |||
6342 | // where we're likely to be running timeouts whose OS timers | |||
6343 | // didn't fire in time and we don't want to not fire those timers | |||
6344 | // now just because execution of one timer failed. We can't | |||
6345 | // propagate the error to anyone who cares about it from this | |||
6346 | // point anyway, and the script context should have already reported | |||
6347 | // the script error in the usual way - so we just drop it. | |||
6348 | ||||
6349 | TimeoutManager::SetNestingLevel(nestingLevel); | |||
6350 | ||||
6351 | mTimeoutManager->EndRunningTimeout(last_running_timeout); | |||
6352 | timeout->mRunning = false; | |||
6353 | ||||
6354 | return timeout->mCleared; | |||
6355 | } | |||
6356 | ||||
6357 | //***************************************************************************** | |||
6358 | // nsGlobalWindowInner: Helper Functions | |||
6359 | //***************************************************************************** | |||
6360 | ||||
6361 | already_AddRefed<nsIDocShellTreeOwner> nsGlobalWindowInner::GetTreeOwner() { | |||
6362 | FORWARD_TO_OUTER(GetTreeOwner, (), nullptr); | |||
6363 | } | |||
6364 | ||||
6365 | already_AddRefed<nsIWebBrowserChrome> | |||
6366 | nsGlobalWindowInner::GetWebBrowserChrome() { | |||
6367 | nsCOMPtr<nsIDocShellTreeOwner> treeOwner = GetTreeOwner(); | |||
6368 | ||||
6369 | nsCOMPtr<nsIWebBrowserChrome> browserChrome = do_GetInterface(treeOwner); | |||
6370 | return browserChrome.forget(); | |||
6371 | } | |||
6372 | ||||
6373 | ScrollContainerFrame* nsGlobalWindowInner::GetScrollContainerFrame() { | |||
6374 | FORWARD_TO_OUTER(GetScrollContainerFrame, (), nullptr); | |||
6375 | } | |||
6376 | ||||
6377 | bool nsGlobalWindowInner::IsPrivateBrowsing() { | |||
6378 | nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(GetDocShell()); | |||
6379 | return loadContext && loadContext->UsePrivateBrowsing(); | |||
6380 | } | |||
6381 | ||||
6382 | void nsGlobalWindowInner::FlushPendingNotifications(FlushType aType) { | |||
6383 | if (mDoc) { | |||
6384 | mDoc->FlushPendingNotifications(aType); | |||
6385 | } | |||
6386 | } | |||
6387 | ||||
6388 | void nsGlobalWindowInner::EnableDeviceSensor(uint32_t aType) { | |||
6389 | bool alreadyEnabled = false; | |||
6390 | for (uint32_t i = 0; i < mEnabledSensors.Length(); i++) { | |||
6391 | if (mEnabledSensors[i] == aType) { | |||
6392 | alreadyEnabled = true; | |||
6393 | break; | |||
6394 | } | |||
6395 | } | |||
6396 | ||||
6397 | mEnabledSensors.AppendElement(aType); | |||
6398 | ||||
6399 | if (alreadyEnabled) { | |||
6400 | return; | |||
6401 | } | |||
6402 | ||||
6403 | nsCOMPtr<nsIDeviceSensors> ac = do_GetService(NS_DEVICE_SENSORS_CONTRACTID"@mozilla.org/devicesensors;1"); | |||
6404 | if (ac) { | |||
6405 | ac->AddWindowListener(aType, this); | |||
6406 | } | |||
6407 | } | |||
6408 | ||||
6409 | void nsGlobalWindowInner::DisableDeviceSensor(uint32_t aType) { | |||
6410 | int32_t doomedElement = -1; | |||
6411 | int32_t listenerCount = 0; | |||
6412 | for (uint32_t i = 0; i < mEnabledSensors.Length(); i++) { | |||
6413 | if (mEnabledSensors[i] == aType) { | |||
6414 | doomedElement = i; | |||
6415 | listenerCount++; | |||
6416 | } | |||
6417 | } | |||
6418 | ||||
6419 | if (doomedElement == -1) { | |||
6420 | return; | |||
6421 | } | |||
6422 | ||||
6423 | mEnabledSensors.RemoveElementAt(doomedElement); | |||
6424 | ||||
6425 | if (listenerCount > 1) { | |||
6426 | return; | |||
6427 | } | |||
6428 | ||||
6429 | nsCOMPtr<nsIDeviceSensors> ac = do_GetService(NS_DEVICE_SENSORS_CONTRACTID"@mozilla.org/devicesensors;1"); | |||
6430 | if (ac) { | |||
6431 | ac->RemoveWindowListener(aType, this); | |||
6432 | } | |||
6433 | } | |||
6434 | ||||
6435 | #if defined(MOZ_WIDGET_ANDROID) | |||
6436 | void nsGlobalWindowInner::EnableOrientationChangeListener() { | |||
6437 | if (!ShouldResistFingerprinting(RFPTarget::ScreenOrientation)) { | |||
6438 | mHasOrientationChangeListeners = true; | |||
6439 | mOrientationAngle = Orientation(CallerType::System); | |||
6440 | } | |||
6441 | } | |||
6442 | ||||
6443 | void nsGlobalWindowInner::DisableOrientationChangeListener() { | |||
6444 | mHasOrientationChangeListeners = false; | |||
6445 | } | |||
6446 | #endif | |||
6447 | ||||
6448 | void nsGlobalWindowInner::SetHasGamepadEventListener( | |||
6449 | bool aHasGamepad /* = true*/) { | |||
6450 | mHasGamepad = aHasGamepad; | |||
6451 | if (aHasGamepad) { | |||
6452 | EnableGamepadUpdates(); | |||
6453 | } | |||
6454 | } | |||
6455 | ||||
6456 | void nsGlobalWindowInner::NotifyDetectXRRuntimesCompleted() { | |||
6457 | if (!mXRRuntimeDetectionInFlight) { | |||
6458 | return; | |||
6459 | } | |||
6460 | mXRRuntimeDetectionInFlight = false; | |||
6461 | if (mXRPermissionRequestInFlight) { | |||
6462 | return; | |||
6463 | } | |||
6464 | gfx::VRManagerChild* vm = gfx::VRManagerChild::Get(); | |||
6465 | bool supported = vm->RuntimeSupportsVR(); | |||
6466 | if (!supported) { | |||
6467 | // A VR runtime was not installed; we can suppress | |||
6468 | // the permission prompt | |||
6469 | OnXRPermissionRequestCancel(); | |||
6470 | return; | |||
6471 | } | |||
6472 | // A VR runtime was found. Display a permission prompt before | |||
6473 | // allowing it to be accessed. | |||
6474 | // Connect to the VRManager in order to receive the runtime | |||
6475 | // detection results. | |||
6476 | mXRPermissionRequestInFlight = true; | |||
6477 | RefPtr<XRPermissionRequest> request = | |||
6478 | new XRPermissionRequest(this, WindowID()); | |||
6479 | Unused << NS_WARN_IF(NS_FAILED(request->Start()))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(request ->Start())), 0))), "NS_FAILED(request->Start())", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 6479); | |||
6480 | } | |||
6481 | ||||
6482 | void nsGlobalWindowInner::RequestXRPermission() { | |||
6483 | if (IsDying()) { | |||
6484 | // Do not proceed if the window is dying, as that will result | |||
6485 | // in leaks of objects that get re-allocated after FreeInnerObjects | |||
6486 | // has been called, including mVREventObserver. | |||
6487 | return; | |||
6488 | } | |||
6489 | if (mXRPermissionGranted) { | |||
6490 | // Don't prompt redundantly once permission to | |||
6491 | // access XR devices has been granted. | |||
6492 | OnXRPermissionRequestAllow(); | |||
6493 | return; | |||
6494 | } | |||
6495 | if (mXRRuntimeDetectionInFlight || mXRPermissionRequestInFlight) { | |||
6496 | // Don't allow multiple simultaneous permissions requests; | |||
6497 | return; | |||
6498 | } | |||
6499 | // Before displaying a permission prompt, detect | |||
6500 | // if there is any VR runtime installed. | |||
6501 | gfx::VRManagerChild* vm = gfx::VRManagerChild::Get(); | |||
6502 | mXRRuntimeDetectionInFlight = true; | |||
6503 | EnableVRUpdates(); | |||
6504 | vm->DetectRuntimes(); | |||
6505 | } | |||
6506 | ||||
6507 | void nsGlobalWindowInner::OnXRPermissionRequestAllow() { | |||
6508 | mXRPermissionRequestInFlight = false; | |||
6509 | if (IsDying()) { | |||
6510 | // The window may have started dying while the permission request | |||
6511 | // is in flight. | |||
6512 | // Do not proceed if the window is dying, as that will result | |||
6513 | // in leaks of objects that get re-allocated after FreeInnerObjects | |||
6514 | // has been called, including mNavigator. | |||
6515 | return; | |||
6516 | } | |||
6517 | mXRPermissionGranted = true; | |||
6518 | ||||
6519 | NotifyHasXRSession(); | |||
6520 | ||||
6521 | dom::Navigator* nav = Navigator(); | |||
6522 | MOZ_ASSERT(nav != nullptr)do { static_assert( mozilla::detail::AssertionConditionType< decltype(nav != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(nav != nullptr))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("nav != nullptr" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 6522); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nav != nullptr" ")"); do { *((volatile int*)__null) = 6522; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
6523 | nav->OnXRPermissionRequestAllow(); | |||
6524 | } | |||
6525 | ||||
6526 | void nsGlobalWindowInner::OnXRPermissionRequestCancel() { | |||
6527 | mXRPermissionRequestInFlight = false; | |||
6528 | if (IsDying()) { | |||
6529 | // The window may have started dying while the permission request | |||
6530 | // is in flight. | |||
6531 | // Do not proceed if the window is dying, as that will result | |||
6532 | // in leaks of objects that get re-allocated after FreeInnerObjects | |||
6533 | // has been called, including mNavigator. | |||
6534 | return; | |||
6535 | } | |||
6536 | dom::Navigator* nav = Navigator(); | |||
6537 | MOZ_ASSERT(nav != nullptr)do { static_assert( mozilla::detail::AssertionConditionType< decltype(nav != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(nav != nullptr))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("nav != nullptr" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 6537); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nav != nullptr" ")"); do { *((volatile int*)__null) = 6537; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
6538 | nav->OnXRPermissionRequestCancel(); | |||
6539 | } | |||
6540 | ||||
6541 | void nsGlobalWindowInner::EventListenerAdded(nsAtom* aType) { | |||
6542 | if (aType == nsGkAtoms::onvrdisplayactivate || | |||
6543 | aType == nsGkAtoms::onvrdisplayconnect || | |||
6544 | aType == nsGkAtoms::onvrdisplaydeactivate || | |||
6545 | aType == nsGkAtoms::onvrdisplaydisconnect || | |||
6546 | aType == nsGkAtoms::onvrdisplaypresentchange) { | |||
6547 | RequestXRPermission(); | |||
6548 | } | |||
6549 | ||||
6550 | if (aType == nsGkAtoms::onvrdisplayactivate) { | |||
6551 | mHasVRDisplayActivateEvents = true; | |||
6552 | } | |||
6553 | ||||
6554 | if (aType == nsGkAtoms::onunload && mWindowGlobalChild) { | |||
6555 | if (++mUnloadOrBeforeUnloadListenerCount == 1) { | |||
6556 | mWindowGlobalChild->BlockBFCacheFor(BFCacheStatus::UNLOAD_LISTENER); | |||
6557 | } | |||
6558 | } | |||
6559 | ||||
6560 | if (aType == nsGkAtoms::onbeforeunload && mWindowGlobalChild) { | |||
6561 | if (!mozilla::SessionHistoryInParent() || | |||
6562 | !StaticPrefs:: | |||
6563 | docshell_shistory_bfcache_ship_allow_beforeunload_listeners()) { | |||
6564 | if (++mUnloadOrBeforeUnloadListenerCount == 1) { | |||
6565 | mWindowGlobalChild->BlockBFCacheFor( | |||
6566 | BFCacheStatus::BEFOREUNLOAD_LISTENER); | |||
6567 | } | |||
6568 | } | |||
6569 | if (!mDoc || !(mDoc->GetSandboxFlags() & SANDBOXED_MODALS)) { | |||
6570 | mWindowGlobalChild->BeforeUnloadAdded(); | |||
6571 | MOZ_ASSERT(mWindowGlobalChild->BeforeUnloadListeners() > 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mWindowGlobalChild->BeforeUnloadListeners() > 0 )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(mWindowGlobalChild->BeforeUnloadListeners() > 0 ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "mWindowGlobalChild->BeforeUnloadListeners() > 0", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 6571); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mWindowGlobalChild->BeforeUnloadListeners() > 0" ")"); do { *((volatile int*)__null) = 6571; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
6572 | } | |||
6573 | } | |||
6574 | ||||
6575 | // We need to initialize localStorage in order to receive notifications. | |||
6576 | if (aType == nsGkAtoms::onstorage) { | |||
6577 | ErrorResult rv; | |||
6578 | GetLocalStorage(rv); | |||
6579 | rv.SuppressException(); | |||
6580 | ||||
6581 | if (NextGenLocalStorageEnabled() && mLocalStorage && | |||
6582 | mLocalStorage->Type() == Storage::eLocalStorage) { | |||
6583 | auto object = static_cast<LSObject*>(mLocalStorage.get()); | |||
6584 | ||||
6585 | Unused << NS_WARN_IF(NS_FAILED(object->EnsureObserver()))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(object ->EnsureObserver())), 0))), "NS_FAILED(object->EnsureObserver())" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 6585); | |||
6586 | } | |||
6587 | } | |||
6588 | } | |||
6589 | ||||
6590 | void nsGlobalWindowInner::EventListenerRemoved(nsAtom* aType) { | |||
6591 | if (aType == nsGkAtoms::onunload && mWindowGlobalChild) { | |||
6592 | MOZ_ASSERT(mUnloadOrBeforeUnloadListenerCount > 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mUnloadOrBeforeUnloadListenerCount > 0)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(mUnloadOrBeforeUnloadListenerCount > 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mUnloadOrBeforeUnloadListenerCount > 0" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 6592); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mUnloadOrBeforeUnloadListenerCount > 0" ")"); do { *((volatile int*)__null) = 6592; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
6593 | if (--mUnloadOrBeforeUnloadListenerCount == 0) { | |||
6594 | mWindowGlobalChild->UnblockBFCacheFor(BFCacheStatus::UNLOAD_LISTENER); | |||
6595 | } | |||
6596 | } | |||
6597 | ||||
6598 | if (aType == nsGkAtoms::onbeforeunload && mWindowGlobalChild) { | |||
6599 | if (!mozilla::SessionHistoryInParent() || | |||
6600 | !StaticPrefs:: | |||
6601 | docshell_shistory_bfcache_ship_allow_beforeunload_listeners()) { | |||
6602 | if (--mUnloadOrBeforeUnloadListenerCount == 0) { | |||
6603 | mWindowGlobalChild->UnblockBFCacheFor( | |||
6604 | BFCacheStatus::BEFOREUNLOAD_LISTENER); | |||
6605 | } | |||
6606 | } | |||
6607 | if (!mDoc || !(mDoc->GetSandboxFlags() & SANDBOXED_MODALS)) { | |||
6608 | mWindowGlobalChild->BeforeUnloadRemoved(); | |||
6609 | MOZ_ASSERT(mWindowGlobalChild->BeforeUnloadListeners() >= 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mWindowGlobalChild->BeforeUnloadListeners() >= 0)>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(mWindowGlobalChild->BeforeUnloadListeners() >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mWindowGlobalChild->BeforeUnloadListeners() >= 0", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 6609); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mWindowGlobalChild->BeforeUnloadListeners() >= 0" ")"); do { *((volatile int*)__null) = 6609; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
6610 | } | |||
6611 | } | |||
6612 | ||||
6613 | if (aType == nsGkAtoms::onstorage) { | |||
6614 | if (NextGenLocalStorageEnabled() && mLocalStorage && | |||
6615 | mLocalStorage->Type() == Storage::eLocalStorage && | |||
6616 | // The remove event is fired even if this isn't the last listener, so | |||
6617 | // only remove if there are no other listeners left. | |||
6618 | mListenerManager && | |||
6619 | !mListenerManager->HasListenersFor(nsGkAtoms::onstorage)) { | |||
6620 | auto object = static_cast<LSObject*>(mLocalStorage.get()); | |||
6621 | ||||
6622 | object->DropObserver(); | |||
6623 | } | |||
6624 | } | |||
6625 | } | |||
6626 | ||||
6627 | void nsGlobalWindowInner::NotifyHasXRSession() { | |||
6628 | if (IsDying()) { | |||
6629 | // Do not proceed if the window is dying, as that will result | |||
6630 | // in leaks of objects that get re-allocated after FreeInnerObjects | |||
6631 | // has been called, including mVREventObserver. | |||
6632 | return; | |||
6633 | } | |||
6634 | if (mWindowGlobalChild && !mHasXRSession) { | |||
6635 | mWindowGlobalChild->BlockBFCacheFor(BFCacheStatus::HAS_USED_VR); | |||
6636 | } | |||
6637 | mHasXRSession = true; | |||
6638 | EnableVRUpdates(); | |||
6639 | } | |||
6640 | ||||
6641 | bool nsGlobalWindowInner::HasUsedVR() const { | |||
6642 | // Returns true only if content has enumerated and activated | |||
6643 | // XR devices. Detection of XR runtimes without activation | |||
6644 | // will not cause true to be returned. | |||
6645 | return mHasXRSession; | |||
6646 | } | |||
6647 | ||||
6648 | bool nsGlobalWindowInner::IsVRContentDetected() const { | |||
6649 | // Returns true only if the content will respond to | |||
6650 | // the VRDisplayActivate event. | |||
6651 | return mHasVRDisplayActivateEvents; | |||
6652 | } | |||
6653 | ||||
6654 | bool nsGlobalWindowInner::IsVRContentPresenting() const { | |||
6655 | for (const auto& display : mVRDisplays) { | |||
6656 | if (display->IsAnyPresenting(gfx::kVRGroupAll)) { | |||
6657 | return true; | |||
6658 | } | |||
6659 | } | |||
6660 | return false; | |||
6661 | } | |||
6662 | ||||
6663 | void nsGlobalWindowInner::AddSizeOfIncludingThis( | |||
6664 | nsWindowSizes& aWindowSizes) const { | |||
6665 | aWindowSizes.mDOMSizes.mDOMOtherSize += | |||
6666 | aWindowSizes.mState.mMallocSizeOf(this); | |||
6667 | aWindowSizes.mDOMSizes.mDOMOtherSize += | |||
6668 | nsIGlobalObject::ShallowSizeOfExcludingThis( | |||
6669 | aWindowSizes.mState.mMallocSizeOf); | |||
6670 | ||||
6671 | EventListenerManager* elm = GetExistingListenerManager(); | |||
6672 | if (elm) { | |||
6673 | aWindowSizes.mDOMSizes.mDOMOtherSize += | |||
6674 | elm->SizeOfIncludingThis(aWindowSizes.mState.mMallocSizeOf); | |||
6675 | aWindowSizes.mDOMEventListenersCount += elm->ListenerCount(); | |||
6676 | } | |||
6677 | if (mDoc) { | |||
6678 | // Multiple global windows can share a document. So only measure the | |||
6679 | // document if it (a) doesn't have a global window, or (b) it's the | |||
6680 | // primary document for the window. | |||
6681 | if (!mDoc->GetInnerWindow() || mDoc->GetInnerWindow() == this) { | |||
6682 | mDoc->DocAddSizeOfIncludingThis(aWindowSizes); | |||
6683 | } | |||
6684 | } | |||
6685 | ||||
6686 | if (mNavigator) { | |||
6687 | aWindowSizes.mDOMSizes.mDOMOtherSize += | |||
6688 | mNavigator->SizeOfIncludingThis(aWindowSizes.mState.mMallocSizeOf); | |||
6689 | } | |||
6690 | ||||
6691 | ForEachGlobalTeardownObserver([&](GlobalTeardownObserver* et, | |||
6692 | bool* aDoneOut) { | |||
6693 | if (nsCOMPtr<nsISizeOfEventTarget> iSizeOf = do_QueryObject(et)) { | |||
6694 | aWindowSizes.mDOMSizes.mDOMEventTargetsSize += | |||
6695 | iSizeOf->SizeOfEventTargetIncludingThis( | |||
6696 | aWindowSizes.mState.mMallocSizeOf); | |||
6697 | } | |||
6698 | if (nsCOMPtr<DOMEventTargetHelper> helper = do_QueryObject(et)) { | |||
6699 | if (EventListenerManager* elm = helper->GetExistingListenerManager()) { | |||
6700 | aWindowSizes.mDOMEventListenersCount += elm->ListenerCount(); | |||
6701 | } | |||
6702 | } | |||
6703 | ++aWindowSizes.mDOMEventTargetsCount; | |||
6704 | }); | |||
6705 | ||||
6706 | if (mPerformance) { | |||
6707 | aWindowSizes.mDOMSizes.mDOMPerformanceUserEntries = | |||
6708 | mPerformance->SizeOfUserEntries(aWindowSizes.mState.mMallocSizeOf); | |||
6709 | aWindowSizes.mDOMSizes.mDOMPerformanceResourceEntries = | |||
6710 | mPerformance->SizeOfResourceEntries(aWindowSizes.mState.mMallocSizeOf); | |||
6711 | aWindowSizes.mDOMSizes.mDOMPerformanceEventEntries = | |||
6712 | mPerformance->SizeOfEventEntries(aWindowSizes.mState.mMallocSizeOf); | |||
6713 | } | |||
6714 | } | |||
6715 | ||||
6716 | void nsGlobalWindowInner::RegisterDataDocumentForMemoryReporting( | |||
6717 | Document* aDocument) { | |||
6718 | aDocument->SetAddedToMemoryReportAsDataDocument(); | |||
6719 | mDataDocumentsForMemoryReporting.AppendElement(aDocument); | |||
6720 | } | |||
6721 | ||||
6722 | void nsGlobalWindowInner::UnregisterDataDocumentForMemoryReporting( | |||
6723 | Document* aDocument) { | |||
6724 | DebugOnly<bool> found = | |||
6725 | mDataDocumentsForMemoryReporting.RemoveElement(aDocument); | |||
6726 | MOZ_ASSERT(found)do { static_assert( mozilla::detail::AssertionConditionType< decltype(found)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(found))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("found", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 6726); AnnotateMozCrashReason("MOZ_ASSERT" "(" "found" ")") ; do { *((volatile int*)__null) = 6726; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
6727 | } | |||
6728 | ||||
6729 | void nsGlobalWindowInner::CollectDOMSizesForDataDocuments( | |||
6730 | nsWindowSizes& aSize) const { | |||
6731 | for (Document* doc : mDataDocumentsForMemoryReporting) { | |||
6732 | if (doc) { | |||
6733 | doc->DocAddSizeOfIncludingThis(aSize); | |||
6734 | } | |||
6735 | } | |||
6736 | } | |||
6737 | ||||
6738 | void nsGlobalWindowInner::AddGamepad(GamepadHandle aHandle, Gamepad* aGamepad) { | |||
6739 | // Create the index we will present to content based on which indices are | |||
6740 | // already taken, as required by the spec. | |||
6741 | // https://w3c.github.io/gamepad/gamepad.html#widl-Gamepad-index | |||
6742 | int index = 0; | |||
6743 | while (mGamepadIndexSet.Contains(index)) { | |||
6744 | ++index; | |||
6745 | } | |||
6746 | mGamepadIndexSet.Put(index); | |||
6747 | aGamepad->SetIndex(index); | |||
6748 | mGamepads.InsertOrUpdate(aHandle, RefPtr{aGamepad}); | |||
6749 | } | |||
6750 | ||||
6751 | void nsGlobalWindowInner::RemoveGamepad(GamepadHandle aHandle) { | |||
6752 | RefPtr<Gamepad> gamepad; | |||
6753 | if (!mGamepads.Get(aHandle, getter_AddRefs(gamepad))) { | |||
6754 | return; | |||
6755 | } | |||
6756 | // Free up the index we were using so it can be reused | |||
6757 | mGamepadIndexSet.Remove(gamepad->Index()); | |||
6758 | mGamepads.Remove(aHandle); | |||
6759 | } | |||
6760 | ||||
6761 | void nsGlobalWindowInner::GetGamepads(nsTArray<RefPtr<Gamepad>>& aGamepads) { | |||
6762 | aGamepads.Clear(); | |||
6763 | ||||
6764 | // navigator.getGamepads() always returns an empty array when | |||
6765 | // privacy.resistFingerprinting is true. | |||
6766 | if (ShouldResistFingerprinting(RFPTarget::Gamepad)) { | |||
6767 | return; | |||
6768 | } | |||
6769 | ||||
6770 | // mGamepads.Count() may not be sufficient, but it's not harmful. | |||
6771 | aGamepads.SetCapacity(mGamepads.Count()); | |||
6772 | for (const auto& entry : mGamepads) { | |||
6773 | Gamepad* gamepad = entry.GetWeak(); | |||
6774 | aGamepads.EnsureLengthAtLeast(gamepad->Index() + 1); | |||
6775 | aGamepads[gamepad->Index()] = gamepad; | |||
6776 | } | |||
6777 | } | |||
6778 | ||||
6779 | already_AddRefed<mozilla::dom::Promise> nsGlobalWindowInner::RequestAllGamepads( | |||
6780 | ErrorResult& aRv) { | |||
6781 | RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService()); | |||
6782 | ||||
6783 | if (!gamepadManager) { | |||
6784 | aRv.Throw(NS_ERROR_UNEXPECTED); | |||
6785 | return nullptr; | |||
6786 | } | |||
6787 | ||||
6788 | return gamepadManager->RequestAllGamepads(this, aRv); | |||
6789 | } | |||
6790 | ||||
6791 | already_AddRefed<Gamepad> nsGlobalWindowInner::GetGamepad( | |||
6792 | GamepadHandle aHandle) { | |||
6793 | RefPtr<Gamepad> gamepad; | |||
6794 | ||||
6795 | if (mGamepads.Get(aHandle, getter_AddRefs(gamepad))) { | |||
6796 | return gamepad.forget(); | |||
6797 | } | |||
6798 | ||||
6799 | return nullptr; | |||
6800 | } | |||
6801 | ||||
6802 | void nsGlobalWindowInner::SetHasSeenGamepadInput(bool aHasSeen) { | |||
6803 | mHasSeenGamepadInput = aHasSeen; | |||
6804 | } | |||
6805 | ||||
6806 | bool nsGlobalWindowInner::HasSeenGamepadInput() { return mHasSeenGamepadInput; } | |||
6807 | ||||
6808 | void nsGlobalWindowInner::SyncGamepadState() { | |||
6809 | if (mHasSeenGamepadInput) { | |||
6810 | RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService()); | |||
6811 | for (const auto& entry : mGamepads) { | |||
6812 | gamepadManager->SyncGamepadState(entry.GetKey(), this, entry.GetWeak()); | |||
6813 | } | |||
6814 | } | |||
6815 | } | |||
6816 | ||||
6817 | void nsGlobalWindowInner::StopGamepadHaptics() { | |||
6818 | if (mHasSeenGamepadInput) { | |||
6819 | RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService()); | |||
6820 | gamepadManager->StopHaptics(); | |||
6821 | } | |||
6822 | } | |||
6823 | ||||
6824 | bool nsGlobalWindowInner::UpdateVRDisplays( | |||
6825 | nsTArray<RefPtr<mozilla::dom::VRDisplay>>& aDevices) { | |||
6826 | VRDisplay::UpdateVRDisplays(mVRDisplays, this); | |||
6827 | aDevices = mVRDisplays.Clone(); | |||
6828 | return true; | |||
6829 | } | |||
6830 | ||||
6831 | void nsGlobalWindowInner::NotifyActiveVRDisplaysChanged() { | |||
6832 | if (mNavigator) { | |||
6833 | mNavigator->NotifyActiveVRDisplaysChanged(); | |||
6834 | } | |||
6835 | } | |||
6836 | ||||
6837 | void nsGlobalWindowInner::NotifyPresentationGenerationChanged( | |||
6838 | uint32_t aDisplayID) { | |||
6839 | for (const auto& display : mVRDisplays) { | |||
6840 | if (display->DisplayId() == aDisplayID) { | |||
6841 | display->OnPresentationGenerationChanged(); | |||
6842 | } | |||
6843 | } | |||
6844 | } | |||
6845 | ||||
6846 | void nsGlobalWindowInner::DispatchVRDisplayActivate( | |||
6847 | uint32_t aDisplayID, mozilla::dom::VRDisplayEventReason aReason) { | |||
6848 | // Ensure that our list of displays is up to date | |||
6849 | VRDisplay::UpdateVRDisplays(mVRDisplays, this); | |||
6850 | ||||
6851 | // Search for the display identified with aDisplayID and fire the | |||
6852 | // event if found. | |||
6853 | for (const auto& display : mVRDisplays) { | |||
6854 | if (display->DisplayId() == aDisplayID) { | |||
6855 | if (aReason != VRDisplayEventReason::Navigation && | |||
6856 | display->IsAnyPresenting(gfx::kVRGroupContent)) { | |||
6857 | // We only want to trigger this event if nobody is presenting to the | |||
6858 | // display already or when a page is loaded by navigating away | |||
6859 | // from a page with an active VR Presentation. | |||
6860 | continue; | |||
6861 | } | |||
6862 | ||||
6863 | VRDisplayEventInit init; | |||
6864 | init.mBubbles = false; | |||
6865 | init.mCancelable = false; | |||
6866 | init.mDisplay = display; | |||
6867 | init.mReason.Construct(aReason); | |||
6868 | ||||
6869 | RefPtr<VRDisplayEvent> event = | |||
6870 | VRDisplayEvent::Constructor(this, u"vrdisplayactivate"_ns, init); | |||
6871 | // vrdisplayactivate is a trusted event, allowing VRDisplay.requestPresent | |||
6872 | // to be used in response to link traversal, user request (chrome UX), and | |||
6873 | // HMD mounting detection sensors. | |||
6874 | event->SetTrusted(true); | |||
6875 | // VRDisplay.requestPresent normally requires a user gesture; however, an | |||
6876 | // exception is made to allow it to be called in response to | |||
6877 | // vrdisplayactivate during VR link traversal. | |||
6878 | display->StartHandlingVRNavigationEvent(); | |||
6879 | DispatchEvent(*event); | |||
6880 | display->StopHandlingVRNavigationEvent(); | |||
6881 | // Once we dispatch the event, we must not access any members as an event | |||
6882 | // listener can do anything, including closing windows. | |||
6883 | return; | |||
6884 | } | |||
6885 | } | |||
6886 | } | |||
6887 | ||||
6888 | void nsGlobalWindowInner::DispatchVRDisplayDeactivate( | |||
6889 | uint32_t aDisplayID, mozilla::dom::VRDisplayEventReason aReason) { | |||
6890 | // Ensure that our list of displays is up to date | |||
6891 | VRDisplay::UpdateVRDisplays(mVRDisplays, this); | |||
6892 | ||||
6893 | // Search for the display identified with aDisplayID and fire the | |||
6894 | // event if found. | |||
6895 | for (const auto& display : mVRDisplays) { | |||
6896 | if (display->DisplayId() == aDisplayID && display->IsPresenting()) { | |||
6897 | // We only want to trigger this event to content that is presenting to | |||
6898 | // the display already. | |||
6899 | ||||
6900 | VRDisplayEventInit init; | |||
6901 | init.mBubbles = false; | |||
6902 | init.mCancelable = false; | |||
6903 | init.mDisplay = display; | |||
6904 | init.mReason.Construct(aReason); | |||
6905 | ||||
6906 | RefPtr<VRDisplayEvent> event = | |||
6907 | VRDisplayEvent::Constructor(this, u"vrdisplaydeactivate"_ns, init); | |||
6908 | event->SetTrusted(true); | |||
6909 | DispatchEvent(*event); | |||
6910 | // Once we dispatch the event, we must not access any members as an event | |||
6911 | // listener can do anything, including closing windows. | |||
6912 | return; | |||
6913 | } | |||
6914 | } | |||
6915 | } | |||
6916 | ||||
6917 | void nsGlobalWindowInner::DispatchVRDisplayConnect(uint32_t aDisplayID) { | |||
6918 | // Ensure that our list of displays is up to date | |||
6919 | VRDisplay::UpdateVRDisplays(mVRDisplays, this); | |||
6920 | ||||
6921 | // Search for the display identified with aDisplayID and fire the | |||
6922 | // event if found. | |||
6923 | for (const auto& display : mVRDisplays) { | |||
6924 | if (display->DisplayId() == aDisplayID) { | |||
6925 | // Fire event even if not presenting to the display. | |||
6926 | VRDisplayEventInit init; | |||
6927 | init.mBubbles = false; | |||
6928 | init.mCancelable = false; | |||
6929 | init.mDisplay = display; | |||
6930 | // VRDisplayEvent.reason is not set for vrdisplayconnect | |||
6931 | ||||
6932 | RefPtr<VRDisplayEvent> event = | |||
6933 | VRDisplayEvent::Constructor(this, u"vrdisplayconnect"_ns, init); | |||
6934 | event->SetTrusted(true); | |||
6935 | DispatchEvent(*event); | |||
6936 | // Once we dispatch the event, we must not access any members as an event | |||
6937 | // listener can do anything, including closing windows. | |||
6938 | return; | |||
6939 | } | |||
6940 | } | |||
6941 | } | |||
6942 | ||||
6943 | void nsGlobalWindowInner::DispatchVRDisplayDisconnect(uint32_t aDisplayID) { | |||
6944 | // Ensure that our list of displays is up to date | |||
6945 | VRDisplay::UpdateVRDisplays(mVRDisplays, this); | |||
6946 | ||||
6947 | // Search for the display identified with aDisplayID and fire the | |||
6948 | // event if found. | |||
6949 | for (const auto& display : mVRDisplays) { | |||
6950 | if (display->DisplayId() == aDisplayID) { | |||
6951 | // Fire event even if not presenting to the display. | |||
6952 | VRDisplayEventInit init; | |||
6953 | init.mBubbles = false; | |||
6954 | init.mCancelable = false; | |||
6955 | init.mDisplay = display; | |||
6956 | // VRDisplayEvent.reason is not set for vrdisplaydisconnect | |||
6957 | ||||
6958 | RefPtr<VRDisplayEvent> event = | |||
6959 | VRDisplayEvent::Constructor(this, u"vrdisplaydisconnect"_ns, init); | |||
6960 | event->SetTrusted(true); | |||
6961 | DispatchEvent(*event); | |||
6962 | // Once we dispatch the event, we must not access any members as an event | |||
6963 | // listener can do anything, including closing windows. | |||
6964 | return; | |||
6965 | } | |||
6966 | } | |||
6967 | } | |||
6968 | ||||
6969 | void nsGlobalWindowInner::DispatchVRDisplayPresentChange(uint32_t aDisplayID) { | |||
6970 | // Ensure that our list of displays is up to date | |||
6971 | VRDisplay::UpdateVRDisplays(mVRDisplays, this); | |||
6972 | ||||
6973 | // Search for the display identified with aDisplayID and fire the | |||
6974 | // event if found. | |||
6975 | for (const auto& display : mVRDisplays) { | |||
6976 | if (display->DisplayId() == aDisplayID) { | |||
6977 | // Fire event even if not presenting to the display. | |||
6978 | VRDisplayEventInit init; | |||
6979 | init.mBubbles = false; | |||
6980 | init.mCancelable = false; | |||
6981 | init.mDisplay = display; | |||
6982 | // VRDisplayEvent.reason is not set for vrdisplaypresentchange | |||
6983 | RefPtr<VRDisplayEvent> event = | |||
6984 | VRDisplayEvent::Constructor(this, u"vrdisplaypresentchange"_ns, init); | |||
6985 | event->SetTrusted(true); | |||
6986 | DispatchEvent(*event); | |||
6987 | // Once we dispatch the event, we must not access any members as an event | |||
6988 | // listener can do anything, including closing windows. | |||
6989 | return; | |||
6990 | } | |||
6991 | } | |||
6992 | } | |||
6993 | ||||
6994 | enum WindowState { | |||
6995 | // These constants need to match the constants in Window.webidl | |||
6996 | STATE_MAXIMIZED = 1, | |||
6997 | STATE_MINIMIZED = 2, | |||
6998 | STATE_NORMAL = 3, | |||
6999 | STATE_FULLSCREEN = 4 | |||
7000 | }; | |||
7001 | ||||
7002 | uint16_t nsGlobalWindowInner::WindowState() { | |||
7003 | nsCOMPtr<nsIWidget> widget = GetMainWidget(); | |||
7004 | ||||
7005 | int32_t mode = widget ? widget->SizeMode() : 0; | |||
7006 | ||||
7007 | switch (mode) { | |||
7008 | case nsSizeMode_Minimized: | |||
7009 | return STATE_MINIMIZED; | |||
7010 | case nsSizeMode_Maximized: | |||
7011 | return STATE_MAXIMIZED; | |||
7012 | case nsSizeMode_Fullscreen: | |||
7013 | return STATE_FULLSCREEN; | |||
7014 | case nsSizeMode_Normal: | |||
7015 | return STATE_NORMAL; | |||
7016 | default: | |||
7017 | NS_WARNING("Illegal window state for this chrome window")NS_DebugBreak(NS_DEBUG_WARNING, "Illegal window state for this chrome window" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 7017); | |||
7018 | break; | |||
7019 | } | |||
7020 | ||||
7021 | return STATE_NORMAL; | |||
7022 | } | |||
7023 | ||||
7024 | bool nsGlobalWindowInner::IsFullyOccluded() { | |||
7025 | nsCOMPtr<nsIWidget> widget = GetMainWidget(); | |||
7026 | return widget && widget->IsFullyOccluded(); | |||
7027 | } | |||
7028 | ||||
7029 | void nsGlobalWindowInner::Maximize() { | |||
7030 | if (nsCOMPtr<nsIWidget> widget = GetMainWidget()) { | |||
7031 | widget->SetSizeMode(nsSizeMode_Maximized); | |||
7032 | } | |||
7033 | } | |||
7034 | ||||
7035 | void nsGlobalWindowInner::Minimize() { | |||
7036 | if (nsCOMPtr<nsIWidget> widget = GetMainWidget()) { | |||
7037 | widget->SetSizeMode(nsSizeMode_Minimized); | |||
7038 | } | |||
7039 | } | |||
7040 | ||||
7041 | void nsGlobalWindowInner::Restore() { | |||
7042 | if (nsCOMPtr<nsIWidget> widget = GetMainWidget()) { | |||
7043 | widget->SetSizeMode(nsSizeMode_Normal); | |||
7044 | } | |||
7045 | } | |||
7046 | ||||
7047 | void nsGlobalWindowInner::GetWorkspaceID(nsAString& workspaceID) { | |||
7048 | workspaceID.Truncate(); | |||
7049 | if (nsCOMPtr<nsIWidget> widget = GetMainWidget()) { | |||
7050 | return widget->GetWorkspaceID(workspaceID); | |||
7051 | } | |||
7052 | } | |||
7053 | ||||
7054 | void nsGlobalWindowInner::MoveToWorkspace(const nsAString& workspaceID) { | |||
7055 | if (nsCOMPtr<nsIWidget> widget = GetMainWidget()) { | |||
7056 | widget->MoveToWorkspace(workspaceID); | |||
7057 | } | |||
7058 | } | |||
7059 | ||||
7060 | void nsGlobalWindowInner::GetAttention(ErrorResult& aResult) { | |||
7061 | return GetAttentionWithCycleCount(-1, aResult); | |||
7062 | } | |||
7063 | ||||
7064 | void nsGlobalWindowInner::GetAttentionWithCycleCount(int32_t aCycleCount, | |||
7065 | ErrorResult& aError) { | |||
7066 | nsCOMPtr<nsIWidget> widget = GetMainWidget(); | |||
7067 | ||||
7068 | if (widget) { | |||
7069 | aError = widget->GetAttention(aCycleCount); | |||
7070 | } | |||
7071 | } | |||
7072 | ||||
7073 | already_AddRefed<Promise> nsGlobalWindowInner::PromiseDocumentFlushed( | |||
7074 | PromiseDocumentFlushedCallback& aCallback, ErrorResult& aError) { | |||
7075 | MOZ_RELEASE_ASSERT(IsChromeWindow())do { static_assert( mozilla::detail::AssertionConditionType< decltype(IsChromeWindow())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsChromeWindow()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsChromeWindow()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 7075); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "IsChromeWindow()" ")"); do { *((volatile int*)__null) = 7075; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
7076 | ||||
7077 | if (!IsCurrentInnerWindow()) { | |||
7078 | aError.ThrowInvalidStateError("Not the current inner window"); | |||
7079 | return nullptr; | |||
7080 | } | |||
7081 | if (!mDoc) { | |||
7082 | aError.ThrowInvalidStateError("No document"); | |||
7083 | return nullptr; | |||
7084 | } | |||
7085 | ||||
7086 | if (mIteratingDocumentFlushedResolvers) { | |||
7087 | aError.ThrowInvalidStateError("Already iterating through resolvers"); | |||
7088 | return nullptr; | |||
7089 | } | |||
7090 | ||||
7091 | PresShell* presShell = mDoc->GetPresShell(); | |||
7092 | if (!presShell) { | |||
7093 | aError.ThrowInvalidStateError("No pres shell"); | |||
7094 | return nullptr; | |||
7095 | } | |||
7096 | ||||
7097 | // We need to associate the lifetime of the Promise to the lifetime | |||
7098 | // of the caller's global. That way, if the window we're observing | |||
7099 | // refresh driver ticks on goes away before our observer is fired, | |||
7100 | // we can still resolve the Promise. | |||
7101 | nsIGlobalObject* global = GetIncumbentGlobal(); | |||
7102 | if (!global) { | |||
7103 | aError.ThrowInvalidStateError("No incumbent global"); | |||
7104 | return nullptr; | |||
7105 | } | |||
7106 | ||||
7107 | RefPtr<Promise> resultPromise = Promise::Create(global, aError); | |||
7108 | if (aError.Failed()) { | |||
7109 | return nullptr; | |||
7110 | } | |||
7111 | ||||
7112 | UniquePtr<PromiseDocumentFlushedResolver> flushResolver( | |||
7113 | new PromiseDocumentFlushedResolver(resultPromise, aCallback)); | |||
7114 | ||||
7115 | if (!presShell->NeedStyleFlush() && !presShell->NeedLayoutFlush()) { | |||
7116 | flushResolver->Call(); | |||
7117 | return resultPromise.forget(); | |||
7118 | } | |||
7119 | ||||
7120 | if (!TryToObserveRefresh()) { | |||
7121 | aError.ThrowInvalidStateError("Couldn't observe refresh"); | |||
7122 | return nullptr; | |||
7123 | } | |||
7124 | ||||
7125 | mDocumentFlushedResolvers.AppendElement(std::move(flushResolver)); | |||
7126 | return resultPromise.forget(); | |||
7127 | } | |||
7128 | ||||
7129 | bool nsGlobalWindowInner::TryToObserveRefresh() { | |||
7130 | if (mObservingRefresh) { | |||
7131 | return true; | |||
7132 | } | |||
7133 | ||||
7134 | if (!mDoc) { | |||
7135 | return false; | |||
7136 | } | |||
7137 | ||||
7138 | nsPresContext* pc = mDoc->GetPresContext(); | |||
7139 | if (!pc) { | |||
7140 | return false; | |||
7141 | } | |||
7142 | ||||
7143 | mObservingRefresh = true; | |||
7144 | auto observer = MakeRefPtr<ManagedPostRefreshObserver>( | |||
7145 | pc, [win = RefPtr{this}](bool aWasCanceled) { | |||
7146 | if (win->MaybeCallDocumentFlushedResolvers( | |||
7147 | /* aUntilExhaustion = */ aWasCanceled)) { | |||
7148 | return ManagedPostRefreshObserver::Unregister::No; | |||
7149 | } | |||
7150 | win->mObservingRefresh = false; | |||
7151 | return ManagedPostRefreshObserver::Unregister::Yes; | |||
7152 | }); | |||
7153 | pc->RegisterManagedPostRefreshObserver(observer.get()); | |||
7154 | return mObservingRefresh; | |||
7155 | } | |||
7156 | ||||
7157 | void nsGlobalWindowInner::CallDocumentFlushedResolvers(bool aUntilExhaustion) { | |||
7158 | while (true) { | |||
7159 | { | |||
7160 | // To coalesce MicroTask checkpoints inside callback call, enclose the | |||
7161 | // inner loop with nsAutoMicroTask, and perform a MicroTask checkpoint | |||
7162 | // after the loop. | |||
7163 | nsAutoMicroTask mt; | |||
7164 | ||||
7165 | mIteratingDocumentFlushedResolvers = true; | |||
7166 | ||||
7167 | auto resolvers = std::move(mDocumentFlushedResolvers); | |||
7168 | for (const auto& resolver : resolvers) { | |||
7169 | resolver->Call(); | |||
7170 | } | |||
7171 | ||||
7172 | mIteratingDocumentFlushedResolvers = false; | |||
7173 | } | |||
7174 | ||||
7175 | // Leaving nsAutoMicroTask above will perform MicroTask checkpoint, and | |||
7176 | // Promise callbacks there may create mDocumentFlushedResolvers items. | |||
7177 | ||||
7178 | // If there's no new resolvers, or we're not exhausting the queue, there's | |||
7179 | // nothing to do (we'll keep observing if there's any new observer). | |||
7180 | // | |||
7181 | // Otherwise, keep looping to call all promises. This case can happen while | |||
7182 | // destroying the window. This violates the constraint that the | |||
7183 | // promiseDocumentFlushed callback only ever run when no flush is needed, | |||
7184 | // but it's necessary to resolve the Promise returned by that. | |||
7185 | if (!aUntilExhaustion || mDocumentFlushedResolvers.IsEmpty()) { | |||
7186 | break; | |||
7187 | } | |||
7188 | } | |||
7189 | } | |||
7190 | ||||
7191 | bool nsGlobalWindowInner::MaybeCallDocumentFlushedResolvers( | |||
7192 | bool aUntilExhaustion) { | |||
7193 | MOZ_ASSERT(mDoc)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mDoc)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(mDoc))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("mDoc", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 7193); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDoc" ")"); do { *((volatile int*)__null) = 7193; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
7194 | ||||
7195 | PresShell* presShell = mDoc->GetPresShell(); | |||
7196 | if (!presShell || aUntilExhaustion) { | |||
7197 | CallDocumentFlushedResolvers(/* aUntilExhaustion = */ true); | |||
7198 | return false; | |||
7199 | } | |||
7200 | ||||
7201 | if (presShell->NeedStyleFlush() || presShell->NeedLayoutFlush()) { | |||
7202 | // By the time our observer fired, something has already invalidated | |||
7203 | // style or layout - or perhaps we're still in the middle of a flush that | |||
7204 | // was interrupted. In either case, we'll wait until the next refresh driver | |||
7205 | // tick instead and try again. | |||
7206 | return true; | |||
7207 | } | |||
7208 | ||||
7209 | CallDocumentFlushedResolvers(/* aUntilExhaustion = */ false); | |||
7210 | return !mDocumentFlushedResolvers.IsEmpty(); | |||
7211 | } | |||
7212 | ||||
7213 | already_AddRefed<nsWindowRoot> nsGlobalWindowInner::GetWindowRoot( | |||
7214 | mozilla::ErrorResult& aError) { | |||
7215 | FORWARD_TO_OUTER_OR_THROW(GetWindowRootOuter, (), aError, nullptr); | |||
7216 | } | |||
7217 | ||||
7218 | void nsGlobalWindowInner::SetCursor(const nsACString& aCursor, | |||
7219 | ErrorResult& aError) { | |||
7220 | FORWARD_TO_OUTER_OR_THROW(SetCursorOuter, (aCursor, aError), aError, ); | |||
7221 | } | |||
7222 | ||||
7223 | nsIBrowserDOMWindow* nsGlobalWindowInner::GetBrowserDOMWindow( | |||
7224 | ErrorResult& aError) { | |||
7225 | FORWARD_TO_OUTER_OR_THROW(GetBrowserDOMWindow, (), aError, nullptr); | |||
7226 | } | |||
7227 | ||||
7228 | void nsGlobalWindowInner::SetBrowserDOMWindow( | |||
7229 | nsIBrowserDOMWindow* aBrowserWindow, ErrorResult& aError) { | |||
7230 | FORWARD_TO_OUTER_OR_THROW(SetBrowserDOMWindowOuter, (aBrowserWindow), | |||
7231 | aError, ); | |||
7232 | } | |||
7233 | ||||
7234 | void nsGlobalWindowInner::NotifyDefaultButtonLoaded(Element& aDefaultButton, | |||
7235 | ErrorResult& aError) { | |||
7236 | // Don't snap to a disabled button. | |||
7237 | nsCOMPtr<nsIDOMXULControlElement> xulControl = aDefaultButton.AsXULControl(); | |||
7238 | if (!xulControl) { | |||
7239 | aError.Throw(NS_ERROR_FAILURE); | |||
7240 | return; | |||
7241 | } | |||
7242 | bool disabled; | |||
7243 | aError = xulControl->GetDisabled(&disabled); | |||
7244 | if (aError.Failed() || disabled) { | |||
7245 | return; | |||
7246 | } | |||
7247 | ||||
7248 | // Get the button rect in screen coordinates. | |||
7249 | nsIFrame* frame = aDefaultButton.GetPrimaryFrame(); | |||
7250 | if (!frame) { | |||
7251 | aError.Throw(NS_ERROR_FAILURE); | |||
7252 | return; | |||
7253 | } | |||
7254 | LayoutDeviceIntRect buttonRect = LayoutDeviceIntRect::FromAppUnitsToNearest( | |||
7255 | frame->GetScreenRectInAppUnits(), | |||
7256 | frame->PresContext()->AppUnitsPerDevPixel()); | |||
7257 | ||||
7258 | // Get the widget rect in screen coordinates. | |||
7259 | nsIWidget* widget = GetNearestWidget(); | |||
7260 | if (!widget) { | |||
7261 | aError.Throw(NS_ERROR_FAILURE); | |||
7262 | return; | |||
7263 | } | |||
7264 | LayoutDeviceIntRect widgetRect = widget->GetScreenBounds(); | |||
7265 | ||||
7266 | // Convert the buttonRect coordinates from screen to the widget. | |||
7267 | buttonRect -= widgetRect.TopLeft(); | |||
7268 | nsresult rv = widget->OnDefaultButtonLoaded(buttonRect); | |||
7269 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && rv != NS_ERROR_NOT_IMPLEMENTED) { | |||
7270 | aError.Throw(rv); | |||
7271 | } | |||
7272 | } | |||
7273 | ||||
7274 | ChromeMessageBroadcaster* nsGlobalWindowInner::MessageManager() { | |||
7275 | MOZ_ASSERT(IsChromeWindow())do { static_assert( mozilla::detail::AssertionConditionType< decltype(IsChromeWindow())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsChromeWindow()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsChromeWindow()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 7275); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsChromeWindow()" ")"); do { *((volatile int*)__null) = 7275; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
7276 | if (!mChromeFields.mMessageManager) { | |||
7277 | RefPtr<ChromeMessageBroadcaster> globalMM = | |||
7278 | nsFrameMessageManager::GetGlobalMessageManager(); | |||
7279 | mChromeFields.mMessageManager = new ChromeMessageBroadcaster(globalMM); | |||
7280 | } | |||
7281 | return mChromeFields.mMessageManager; | |||
7282 | } | |||
7283 | ||||
7284 | ChromeMessageBroadcaster* nsGlobalWindowInner::GetGroupMessageManager( | |||
7285 | const nsAString& aGroup) { | |||
7286 | MOZ_ASSERT(IsChromeWindow())do { static_assert( mozilla::detail::AssertionConditionType< decltype(IsChromeWindow())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsChromeWindow()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsChromeWindow()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 7286); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsChromeWindow()" ")"); do { *((volatile int*)__null) = 7286; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
7287 | ||||
7288 | return mChromeFields.mGroupMessageManagers | |||
7289 | .LookupOrInsertWith( | |||
7290 | aGroup, | |||
7291 | [&] { | |||
7292 | return MakeAndAddRef<ChromeMessageBroadcaster>(MessageManager()); | |||
7293 | }) | |||
7294 | .get(); | |||
7295 | } | |||
7296 | ||||
7297 | void nsGlobalWindowInner::InitWasOffline() { mWasOffline = NS_IsOffline(); } | |||
7298 | ||||
7299 | int16_t nsGlobalWindowInner::Orientation(CallerType aCallerType) { | |||
7300 | // GetOrientationAngle() returns 0, 90, 180 or 270. | |||
7301 | // window.orientation returns -90, 0, 90 or 180. | |||
7302 | if (nsIGlobalObject::ShouldResistFingerprinting( | |||
7303 | aCallerType, RFPTarget::ScreenOrientation)) { | |||
7304 | return 0; | |||
7305 | } | |||
7306 | int16_t angle = AssertedCast<int16_t>(Screen()->GetOrientationAngle()); | |||
7307 | return angle <= 180 ? angle : angle - 360; | |||
7308 | } | |||
7309 | ||||
7310 | already_AddRefed<Console> nsGlobalWindowInner::GetConsole(JSContext* aCx, | |||
7311 | ErrorResult& aRv) { | |||
7312 | if (!mConsole) { | |||
7313 | mConsole = Console::Create(aCx, this, aRv); | |||
7314 | if (NS_WARN_IF(aRv.Failed())NS_warn_if_impl(aRv.Failed(), "aRv.Failed()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 7314)) { | |||
7315 | return nullptr; | |||
7316 | } | |||
7317 | } | |||
7318 | ||||
7319 | RefPtr<Console> console = mConsole; | |||
7320 | return console.forget(); | |||
7321 | } | |||
7322 | ||||
7323 | bool nsGlobalWindowInner::IsSecureContext() const { | |||
7324 | JS::Realm* realm = js::GetNonCCWObjectRealm(GetWrapperPreserveColor()); | |||
7325 | return JS::GetIsSecureContext(realm); | |||
7326 | } | |||
7327 | ||||
7328 | External* nsGlobalWindowInner::External() { | |||
7329 | if (!mExternal) { | |||
7330 | mExternal = new dom::External(ToSupports(this)); | |||
7331 | } | |||
7332 | ||||
7333 | return mExternal; | |||
7334 | } | |||
7335 | ||||
7336 | void nsGlobalWindowInner::ClearDocumentDependentSlots(JSContext* aCx) { | |||
7337 | // If JSAPI OOMs here, there is basically nothing we can do to recover safely. | |||
7338 | if (!Window_Binding::ClearCachedDocumentValue(aCx, this) || | |||
7339 | !Window_Binding::ClearCachedPerformanceValue(aCx, this)) { | |||
7340 | MOZ_CRASH("Unhandlable OOM while clearing document dependent slots.")do { do { } while (false); MOZ_ReportCrash("" "Unhandlable OOM while clearing document dependent slots." , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 7340); AnnotateMozCrashReason("MOZ_CRASH(" "Unhandlable OOM while clearing document dependent slots." ")"); do { *((volatile int*)__null) = 7340; __attribute__((nomerge )) ::abort(); } while (false); } while (false); | |||
7341 | } | |||
7342 | } | |||
7343 | ||||
7344 | /* static */ | |||
7345 | JSObject* nsGlobalWindowInner::CreateNamedPropertiesObject( | |||
7346 | JSContext* aCx, JS::Handle<JSObject*> aProto) { | |||
7347 | return WindowNamedPropertiesHandler::Create(aCx, aProto); | |||
7348 | } | |||
7349 | ||||
7350 | void nsGlobalWindowInner::RedefineProperty(JSContext* aCx, | |||
7351 | const char* aPropName, | |||
7352 | JS::Handle<JS::Value> aValue, | |||
7353 | ErrorResult& aError) { | |||
7354 | JS::Rooted<JSObject*> thisObj(aCx, GetWrapperPreserveColor()); | |||
7355 | if (!thisObj) { | |||
7356 | aError.Throw(NS_ERROR_UNEXPECTED); | |||
7357 | return; | |||
7358 | } | |||
7359 | ||||
7360 | if (!JS_WrapObject(aCx, &thisObj) || | |||
7361 | !JS_DefineProperty(aCx, thisObj, aPropName, aValue, JSPROP_ENUMERATE)) { | |||
7362 | aError.Throw(NS_ERROR_FAILURE); | |||
7363 | } | |||
7364 | } | |||
7365 | ||||
7366 | void nsGlobalWindowInner::FireOnNewGlobalObject() { | |||
7367 | // AutoEntryScript required to invoke debugger hook, which is a | |||
7368 | // Gecko-specific concept at present. | |||
7369 | AutoEntryScript aes(this, "nsGlobalWindowInner report new global"); | |||
7370 | JS::Rooted<JSObject*> global(aes.cx(), GetWrapper()); | |||
7371 | JS_FireOnNewGlobalObject(aes.cx(), global); | |||
7372 | } | |||
7373 | ||||
7374 | #if defined(_WINDOWS_) && !defined(MOZ_WRAPPED_WINDOWS_H) | |||
7375 | # pragma message( \ | |||
7376 | "wrapper failure reason: " MOZ_WINDOWS_WRAPPER_DISABLED_REASON) | |||
7377 | # error "Never include unwrapped windows.h in this file!" | |||
7378 | #endif | |||
7379 | ||||
7380 | already_AddRefed<Promise> nsGlobalWindowInner::CreateImageBitmap( | |||
7381 | const ImageBitmapSource& aImage, const ImageBitmapOptions& aOptions, | |||
7382 | ErrorResult& aRv) { | |||
7383 | return ImageBitmap::Create(this, aImage, Nothing(), aOptions, aRv); | |||
7384 | } | |||
7385 | ||||
7386 | already_AddRefed<Promise> nsGlobalWindowInner::CreateImageBitmap( | |||
7387 | const ImageBitmapSource& aImage, int32_t aSx, int32_t aSy, int32_t aSw, | |||
7388 | int32_t aSh, const ImageBitmapOptions& aOptions, ErrorResult& aRv) { | |||
7389 | return ImageBitmap::Create( | |||
7390 | this, aImage, Some(gfx::IntRect(aSx, aSy, aSw, aSh)), aOptions, aRv); | |||
7391 | } | |||
7392 | ||||
7393 | // https://html.spec.whatwg.org/#structured-cloning | |||
7394 | void nsGlobalWindowInner::StructuredClone( | |||
7395 | JSContext* aCx, JS::Handle<JS::Value> aValue, | |||
7396 | const StructuredSerializeOptions& aOptions, | |||
7397 | JS::MutableHandle<JS::Value> aRetval, ErrorResult& aError) { | |||
7398 | nsContentUtils::StructuredClone(aCx, this, aValue, aOptions, aRetval, aError); | |||
7399 | } | |||
7400 | ||||
7401 | nsresult nsGlobalWindowInner::Dispatch( | |||
7402 | already_AddRefed<nsIRunnable>&& aRunnable) const { | |||
7403 | MOZ_RELEASE_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 7403); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 7403; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
7404 | return NS_DispatchToCurrentThread(std::move(aRunnable)); | |||
7405 | } | |||
7406 | ||||
7407 | nsISerialEventTarget* nsGlobalWindowInner::SerialEventTarget() const { | |||
7408 | MOZ_RELEASE_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 7408); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 7408; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
7409 | return GetMainThreadSerialEventTarget(); | |||
7410 | } | |||
7411 | ||||
7412 | Worklet* nsGlobalWindowInner::GetPaintWorklet(ErrorResult& aRv) { | |||
7413 | if (!mPaintWorklet) { | |||
7414 | nsIPrincipal* principal = GetPrincipal(); | |||
7415 | if (!principal) { | |||
7416 | aRv.Throw(NS_ERROR_FAILURE); | |||
7417 | return nullptr; | |||
7418 | } | |||
7419 | ||||
7420 | mPaintWorklet = PaintWorkletImpl::CreateWorklet(this, principal); | |||
7421 | } | |||
7422 | ||||
7423 | return mPaintWorklet; | |||
7424 | } | |||
7425 | ||||
7426 | void nsGlobalWindowInner::GetRegionalPrefsLocales( | |||
7427 | nsTArray<nsString>& aLocales) { | |||
7428 | MOZ_ASSERT(mozilla::intl::LocaleService::GetInstance())do { static_assert( mozilla::detail::AssertionConditionType< decltype(mozilla::intl::LocaleService::GetInstance())>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(mozilla::intl::LocaleService::GetInstance()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mozilla::intl::LocaleService::GetInstance()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 7428); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::intl::LocaleService::GetInstance()" ")"); do { *((volatile int*)__null) = 7428; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
7429 | ||||
7430 | AutoTArray<nsCString, 10> rpLocales; | |||
7431 | mozilla::intl::LocaleService::GetInstance()->GetRegionalPrefsLocales( | |||
7432 | rpLocales); | |||
7433 | ||||
7434 | for (const auto& loc : rpLocales) { | |||
7435 | aLocales.AppendElement(NS_ConvertUTF8toUTF16(loc)); | |||
7436 | } | |||
7437 | } | |||
7438 | ||||
7439 | void nsGlobalWindowInner::GetWebExposedLocales(nsTArray<nsString>& aLocales) { | |||
7440 | MOZ_ASSERT(mozilla::intl::LocaleService::GetInstance())do { static_assert( mozilla::detail::AssertionConditionType< decltype(mozilla::intl::LocaleService::GetInstance())>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(mozilla::intl::LocaleService::GetInstance()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mozilla::intl::LocaleService::GetInstance()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 7440); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::intl::LocaleService::GetInstance()" ")"); do { *((volatile int*)__null) = 7440; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
7441 | ||||
7442 | AutoTArray<nsCString, 10> rpLocales; | |||
7443 | mozilla::intl::LocaleService::GetInstance()->GetWebExposedLocales(rpLocales); | |||
7444 | ||||
7445 | for (const auto& loc : rpLocales) { | |||
7446 | aLocales.AppendElement(NS_ConvertUTF8toUTF16(loc)); | |||
7447 | } | |||
7448 | } | |||
7449 | ||||
7450 | IntlUtils* nsGlobalWindowInner::GetIntlUtils(ErrorResult& aError) { | |||
7451 | if (!mIntlUtils) { | |||
7452 | mIntlUtils = new IntlUtils(this); | |||
7453 | } | |||
7454 | ||||
7455 | return mIntlUtils; | |||
7456 | } | |||
7457 | ||||
7458 | void nsGlobalWindowInner::StoreSharedWorker(SharedWorker* aSharedWorker) { | |||
7459 | MOZ_ASSERT(aSharedWorker)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aSharedWorker)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aSharedWorker))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aSharedWorker", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 7459); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSharedWorker" ")"); do { *((volatile int*)__null) = 7459; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
7460 | MOZ_ASSERT(!mSharedWorkers.Contains(aSharedWorker))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mSharedWorkers.Contains(aSharedWorker))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(!mSharedWorkers.Contains(aSharedWorker)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mSharedWorkers.Contains(aSharedWorker)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 7460); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mSharedWorkers.Contains(aSharedWorker)" ")"); do { *((volatile int*)__null) = 7460; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
7461 | ||||
7462 | mSharedWorkers.AppendElement(aSharedWorker); | |||
7463 | } | |||
7464 | ||||
7465 | void nsGlobalWindowInner::ForgetSharedWorker(SharedWorker* aSharedWorker) { | |||
7466 | MOZ_ASSERT(aSharedWorker)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aSharedWorker)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aSharedWorker))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aSharedWorker", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 7466); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSharedWorker" ")"); do { *((volatile int*)__null) = 7466; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
7467 | MOZ_ASSERT(mSharedWorkers.Contains(aSharedWorker))do { static_assert( mozilla::detail::AssertionConditionType< decltype(mSharedWorkers.Contains(aSharedWorker))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(mSharedWorkers.Contains(aSharedWorker)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mSharedWorkers.Contains(aSharedWorker)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 7467); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mSharedWorkers.Contains(aSharedWorker)" ")"); do { *((volatile int*)__null) = 7467; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
7468 | ||||
7469 | mSharedWorkers.RemoveElement(aSharedWorker); | |||
7470 | } | |||
7471 | ||||
7472 | RefPtr<GenericPromise> nsGlobalWindowInner::StorageAccessPermissionChanged( | |||
7473 | bool aGranted) { | |||
7474 | // Invalidate cached StorageAllowed field so that calls to GetLocalStorage | |||
7475 | // give us the updated localStorage object. | |||
7476 | ClearStorageAllowedCache(); | |||
7477 | ||||
7478 | // If we're always partitioning non-cookie third party storage then | |||
7479 | // there is no need to clear it when the user accepts requestStorageAccess. | |||
7480 | if (StaticPrefs:: | |||
7481 | privacy_partition_always_partition_third_party_non_cookie_storage()) { | |||
7482 | // Just reset the active cookie and storage principals | |||
7483 | nsCOMPtr<nsICookieJarSettings> cjs; | |||
7484 | if (mDoc) { | |||
7485 | cjs = mDoc->CookieJarSettings(); | |||
7486 | } | |||
7487 | StorageAccess storageAccess = StorageAllowedForWindow(this); | |||
7488 | if (ShouldPartitionStorage(storageAccess) && | |||
7489 | StoragePartitioningEnabled(storageAccess, cjs)) { | |||
7490 | if (mDoc) { | |||
7491 | mDoc->ClearActiveCookieAndStoragePrincipals(); | |||
7492 | } | |||
7493 | // When storage access is granted the content process needs to request the | |||
7494 | // updated cookie list from the parent process. Otherwise the site won't | |||
7495 | // have access to unpartitioned cookies via document.cookie without a | |||
7496 | // reload. | |||
7497 | if (aGranted) { | |||
7498 | nsIChannel* channel = mDoc->GetChannel(); | |||
7499 | if (channel) { | |||
7500 | // The promise resolves when the updated cookie list has been received | |||
7501 | // from the parent. | |||
7502 | return ContentChild::UpdateCookieStatus(channel); | |||
7503 | } | |||
7504 | } | |||
7505 | } | |||
7506 | } | |||
7507 | ||||
7508 | PropagateStorageAccessPermissionGrantedToWorkers(*this); | |||
7509 | ||||
7510 | // If we have a partitioned localStorage, it's time to replace it with a real | |||
7511 | // one in order to receive notifications. | |||
7512 | ||||
7513 | if (mLocalStorage) { | |||
7514 | IgnoredErrorResult error; | |||
7515 | GetLocalStorage(error); | |||
7516 | if (NS_WARN_IF(error.Failed())NS_warn_if_impl(error.Failed(), "error.Failed()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 7516)) { | |||
7517 | return MozPromise<bool, nsresult, true>::CreateAndReject( | |||
7518 | error.StealNSResult(), __func__); | |||
7519 | } | |||
7520 | ||||
7521 | MOZ_ASSERT(mLocalStorage &&do { static_assert( mozilla::detail::AssertionConditionType< decltype(mLocalStorage && mLocalStorage->Type() == Storage::eLocalStorage)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mLocalStorage && mLocalStorage ->Type() == Storage::eLocalStorage))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mLocalStorage && mLocalStorage->Type() == Storage::eLocalStorage" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 7522); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLocalStorage && mLocalStorage->Type() == Storage::eLocalStorage" ")"); do { *((volatile int*)__null) = 7522; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) | |||
7522 | mLocalStorage->Type() == Storage::eLocalStorage)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mLocalStorage && mLocalStorage->Type() == Storage::eLocalStorage)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mLocalStorage && mLocalStorage ->Type() == Storage::eLocalStorage))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mLocalStorage && mLocalStorage->Type() == Storage::eLocalStorage" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 7522); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLocalStorage && mLocalStorage->Type() == Storage::eLocalStorage" ")"); do { *((volatile int*)__null) = 7522; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
7523 | ||||
7524 | if (NextGenLocalStorageEnabled() && mListenerManager && | |||
7525 | mListenerManager->HasListenersFor(nsGkAtoms::onstorage)) { | |||
7526 | auto object = static_cast<LSObject*>(mLocalStorage.get()); | |||
7527 | ||||
7528 | object->EnsureObserver(); | |||
7529 | } | |||
7530 | } | |||
7531 | ||||
7532 | // Reset the IndexedDB factory. | |||
7533 | mIndexedDB = nullptr; | |||
7534 | ||||
7535 | // Reset DOM Cache | |||
7536 | mCacheStorage = nullptr; | |||
7537 | ||||
7538 | // Reset the active cookie and storage principals | |||
7539 | if (mDoc) { | |||
7540 | mDoc->ClearActiveCookieAndStoragePrincipals(); | |||
7541 | if (mWindowGlobalChild) { | |||
7542 | // XXX(farre): This is a bit backwards, but clearing the cookie | |||
7543 | // principal might make us end up with a new effective storage | |||
7544 | // principal on the child side than on the parent side, which | |||
7545 | // means that we need to sync it. See bug 1705359. | |||
7546 | mWindowGlobalChild->SetDocumentPrincipal( | |||
7547 | mDoc->NodePrincipal(), mDoc->EffectiveStoragePrincipal()); | |||
7548 | } | |||
7549 | } | |||
7550 | ||||
7551 | // When storage access is granted the content process needs to request the | |||
7552 | // updated cookie list from the parent process. Otherwise the site won't have | |||
7553 | // access to unpartitioned cookies via document.cookie without a reload. | |||
7554 | if (aGranted) { | |||
7555 | nsIChannel* channel = mDoc->GetChannel(); | |||
7556 | if (channel) { | |||
7557 | // The promise resolves when the updated cookie list has been received | |||
7558 | // from the parent. | |||
7559 | return ContentChild::UpdateCookieStatus(channel); | |||
7560 | } | |||
7561 | } | |||
7562 | return MozPromise<bool, nsresult, true>::CreateAndResolve(true, __func__); | |||
7563 | } | |||
7564 | ||||
7565 | ContentMediaController* nsGlobalWindowInner::GetContentMediaController() { | |||
7566 | if (mContentMediaController) { | |||
7567 | return mContentMediaController; | |||
7568 | } | |||
7569 | if (!mBrowsingContext) { | |||
7570 | return nullptr; | |||
7571 | } | |||
7572 | ||||
7573 | mContentMediaController = new ContentMediaController(mBrowsingContext->Id()); | |||
7574 | return mContentMediaController; | |||
7575 | } | |||
7576 | ||||
7577 | void nsGlobalWindowInner::SetScrollMarks(const nsTArray<uint32_t>& aScrollMarks, | |||
7578 | bool aOnHScrollbar) { | |||
7579 | mScrollMarks.Assign(aScrollMarks); | |||
7580 | mScrollMarksOnHScrollbar = aOnHScrollbar; | |||
7581 | ||||
7582 | // Mark the scrollbar for repainting. | |||
7583 | if (mDoc) { | |||
7584 | PresShell* presShell = mDoc->GetPresShell(); | |||
7585 | if (presShell) { | |||
7586 | ScrollContainerFrame* sf = presShell->GetRootScrollContainerFrame(); | |||
7587 | if (sf) { | |||
7588 | sf->InvalidateScrollbars(); | |||
7589 | } | |||
7590 | } | |||
7591 | } | |||
7592 | } | |||
7593 | ||||
7594 | /* static */ | |||
7595 | already_AddRefed<nsGlobalWindowInner> nsGlobalWindowInner::Create( | |||
7596 | nsGlobalWindowOuter* aOuterWindow, bool aIsChrome, | |||
7597 | WindowGlobalChild* aActor) { | |||
7598 | RefPtr<nsGlobalWindowInner> window = | |||
7599 | new nsGlobalWindowInner(aOuterWindow, aActor); | |||
7600 | if (aIsChrome) { | |||
7601 | window->mIsChrome = true; | |||
7602 | window->mCleanMessageManager = true; | |||
7603 | } | |||
7604 | ||||
7605 | if (aActor) { | |||
7606 | aActor->InitWindowGlobal(window); | |||
7607 | } | |||
7608 | ||||
7609 | window->InitWasOffline(); | |||
7610 | return window.forget(); | |||
7611 | } | |||
7612 | ||||
7613 | JS::loader::ModuleLoaderBase* nsGlobalWindowInner::GetModuleLoader( | |||
7614 | JSContext* aCx) { | |||
7615 | Document* document = GetDocument(); | |||
7616 | if (!document) { | |||
7617 | return nullptr; | |||
7618 | } | |||
7619 | ||||
7620 | ScriptLoader* loader = document->ScriptLoader(); | |||
7621 | if (!loader) { | |||
7622 | return nullptr; | |||
7623 | } | |||
7624 | ||||
7625 | return loader->GetModuleLoader(); | |||
7626 | } | |||
7627 | ||||
7628 | void nsGlobalWindowInner::SetCurrentPasteDataTransfer( | |||
7629 | DataTransfer* aDataTransfer) { | |||
7630 | MOZ_ASSERT_IF(aDataTransfer, aDataTransfer->GetEventMessage() == ePaste)do { if (aDataTransfer) { do { static_assert( mozilla::detail ::AssertionConditionType<decltype(aDataTransfer->GetEventMessage () == ePaste)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(aDataTransfer->GetEventMessage () == ePaste))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aDataTransfer->GetEventMessage() == ePaste", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 7630); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDataTransfer->GetEventMessage() == ePaste" ")"); do { *((volatile int*)__null) = 7630; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
7631 | MOZ_ASSERT_IF(aDataTransfer, aDataTransfer->ClipboardType() ==do { if (aDataTransfer) { do { static_assert( mozilla::detail ::AssertionConditionType<decltype(aDataTransfer->ClipboardType () == Some(nsIClipboard::kGlobalClipboard))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aDataTransfer->ClipboardType () == Some(nsIClipboard::kGlobalClipboard)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aDataTransfer->ClipboardType() == Some(nsIClipboard::kGlobalClipboard)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 7632); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDataTransfer->ClipboardType() == Some(nsIClipboard::kGlobalClipboard)" ")"); do { *((volatile int*)__null) = 7632; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) | |||
7632 | Some(nsIClipboard::kGlobalClipboard))do { if (aDataTransfer) { do { static_assert( mozilla::detail ::AssertionConditionType<decltype(aDataTransfer->ClipboardType () == Some(nsIClipboard::kGlobalClipboard))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aDataTransfer->ClipboardType () == Some(nsIClipboard::kGlobalClipboard)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aDataTransfer->ClipboardType() == Some(nsIClipboard::kGlobalClipboard)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 7632); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDataTransfer->ClipboardType() == Some(nsIClipboard::kGlobalClipboard)" ")"); do { *((volatile int*)__null) = 7632; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
7633 | MOZ_ASSERT_IF(aDataTransfer, aDataTransfer->GetClipboardDataSnapshot())do { if (aDataTransfer) { do { static_assert( mozilla::detail ::AssertionConditionType<decltype(aDataTransfer->GetClipboardDataSnapshot ())>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aDataTransfer->GetClipboardDataSnapshot()))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("aDataTransfer->GetClipboardDataSnapshot()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 7633); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDataTransfer->GetClipboardDataSnapshot()" ")"); do { *((volatile int*)__null) = 7633; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); | |||
7634 | mCurrentPasteDataTransfer = aDataTransfer; | |||
7635 | } | |||
7636 | ||||
7637 | DataTransfer* nsGlobalWindowInner::GetCurrentPasteDataTransfer() const { | |||
7638 | return mCurrentPasteDataTransfer; | |||
7639 | } | |||
7640 | ||||
7641 | TrustedTypePolicyFactory* nsGlobalWindowInner::TrustedTypes() { | |||
7642 | if (!mTrustedTypePolicyFactory) { | |||
7643 | mTrustedTypePolicyFactory = MakeRefPtr<TrustedTypePolicyFactory>(this); | |||
7644 | } | |||
7645 | ||||
7646 | return mTrustedTypePolicyFactory; | |||
7647 | } | |||
7648 | ||||
7649 | nsIURI* nsPIDOMWindowInner::GetDocumentURI() const { | |||
7650 | return mDoc ? mDoc->GetDocumentURI() : mDocumentURI.get(); | |||
7651 | } | |||
7652 | ||||
7653 | nsIURI* nsPIDOMWindowInner::GetDocBaseURI() const { | |||
7654 | return mDoc ? mDoc->GetDocBaseURI() : mDocBaseURI.get(); | |||
7655 | } | |||
7656 | ||||
7657 | mozilla::dom::WindowContext* nsPIDOMWindowInner::GetWindowContext() const { | |||
7658 | return mWindowGlobalChild ? mWindowGlobalChild->WindowContext() : nullptr; | |||
7659 | } | |||
7660 | ||||
7661 | bool nsPIDOMWindowInner::RemoveFromBFCacheSync() { | |||
7662 | if (Document* doc = GetExtantDoc()) { | |||
7663 | return doc->RemoveFromBFCacheSync(); | |||
7664 | } | |||
7665 | return false; | |||
7666 | } | |||
7667 | ||||
7668 | void nsPIDOMWindowInner::MaybeCreateDoc() { | |||
7669 | // XXX: Forward to outer? | |||
7670 | MOZ_ASSERT(!mDoc)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mDoc)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(!mDoc))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("!mDoc", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 7670); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mDoc" ")") ; do { *((volatile int*)__null) = 7670; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
7671 | if (nsIDocShell* docShell = GetDocShell()) { | |||
7672 | // Note that |document| here is the same thing as our mDoc, but we | |||
7673 | // don't have to explicitly set the member variable because the docshell | |||
7674 | // has already called SetNewDocument(). | |||
7675 | nsCOMPtr<Document> document = docShell->GetDocument(); | |||
7676 | Unused << document; | |||
7677 | } | |||
7678 | } | |||
7679 | ||||
7680 | mozilla::dom::DocGroup* nsPIDOMWindowInner::GetDocGroup() const { | |||
7681 | Document* doc = GetExtantDoc(); | |||
7682 | if (doc) { | |||
7683 | return doc->GetDocGroup(); | |||
7684 | } | |||
7685 | return nullptr; | |||
7686 | } | |||
7687 | ||||
7688 | mozilla::dom::BrowsingContextGroup* | |||
7689 | nsPIDOMWindowInner::GetBrowsingContextGroup() const { | |||
7690 | return mBrowsingContext ? mBrowsingContext->Group() : nullptr; | |||
7691 | } | |||
7692 | ||||
7693 | nsIGlobalObject* nsPIDOMWindowInner::AsGlobal() { | |||
7694 | return nsGlobalWindowInner::Cast(this); | |||
7695 | } | |||
7696 | ||||
7697 | const nsIGlobalObject* nsPIDOMWindowInner::AsGlobal() const { | |||
7698 | return nsGlobalWindowInner::Cast(this); | |||
7699 | } | |||
7700 | ||||
7701 | RefPtr<GenericPromise> | |||
7702 | nsPIDOMWindowInner::SaveStorageAccessPermissionGranted() { | |||
7703 | WindowContext* wc = GetWindowContext(); | |||
7704 | if (wc) { | |||
7705 | Unused << wc->SetUsingStorageAccess(true); | |||
7706 | } | |||
7707 | ||||
7708 | return nsGlobalWindowInner::Cast(this)->StorageAccessPermissionChanged(true); | |||
7709 | } | |||
7710 | ||||
7711 | RefPtr<GenericPromise> | |||
7712 | nsPIDOMWindowInner::SaveStorageAccessPermissionRevoked() { | |||
7713 | WindowContext* wc = GetWindowContext(); | |||
7714 | if (wc) { | |||
7715 | Unused << wc->SetUsingStorageAccess(false); | |||
7716 | } | |||
7717 | ||||
7718 | return nsGlobalWindowInner::Cast(this)->StorageAccessPermissionChanged(false); | |||
7719 | } | |||
7720 | ||||
7721 | bool nsPIDOMWindowInner::UsingStorageAccess() { | |||
7722 | WindowContext* wc = GetWindowContext(); | |||
7723 | if (!wc) { | |||
7724 | return false; | |||
7725 | } | |||
7726 | ||||
7727 | return wc->GetUsingStorageAccess(); | |||
7728 | } | |||
7729 | ||||
7730 | nsPIDOMWindowInner::nsPIDOMWindowInner(nsPIDOMWindowOuter* aOuterWindow, | |||
7731 | WindowGlobalChild* aActor) | |||
7732 | : mMutationBits(0), | |||
7733 | mIsDocumentLoaded(false), | |||
7734 | mIsHandlingResizeEvent(false), | |||
7735 | mMayHaveDOMActivateEventListeners(false), | |||
7736 | mMayHavePaintEventListener(false), | |||
7737 | mMayHaveTouchEventListener(false), | |||
7738 | mMayHaveSelectionChangeEventListener(false), | |||
7739 | mMayHaveFormSelectEventListener(false), | |||
7740 | mMayHaveMouseEnterLeaveEventListener(false), | |||
7741 | mMayHavePointerEnterLeaveEventListener(false), | |||
7742 | mMayHaveTransitionEventListener(false), | |||
7743 | mMayHaveSMILTimeEventListener(false), | |||
7744 | mMayHaveBeforeInputEventListenerForTelemetry(false), | |||
7745 | mMutationObserverHasObservedNodeForTelemetry(false), | |||
7746 | mOuterWindow(aOuterWindow), | |||
7747 | mWindowID(0), | |||
7748 | mHasNotifiedGlobalCreated(false), | |||
7749 | mMarkedCCGeneration(0), | |||
7750 | mHasTriedToCacheTopInnerWindow(false), | |||
7751 | mNumOfIndexedDBDatabases(0), | |||
7752 | mNumOfOpenWebSockets(0), | |||
7753 | mEvent(nullptr), | |||
7754 | mWindowGlobalChild(aActor), | |||
7755 | mWasSuspendedByGroup(false) { | |||
7756 | MOZ_ASSERT(aOuterWindow)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aOuterWindow)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aOuterWindow))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aOuterWindow", "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 7756); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOuterWindow" ")"); do { *((volatile int*)__null) = 7756; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
7757 | mBrowsingContext = aOuterWindow->GetBrowsingContext(); | |||
7758 | ||||
7759 | if (mWindowGlobalChild) { | |||
7760 | mWindowID = aActor->InnerWindowId(); | |||
7761 | ||||
7762 | MOZ_ASSERT(mWindowGlobalChild->BrowsingContext() == mBrowsingContext)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mWindowGlobalChild->BrowsingContext() == mBrowsingContext )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(mWindowGlobalChild->BrowsingContext() == mBrowsingContext ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "mWindowGlobalChild->BrowsingContext() == mBrowsingContext" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/base/nsGlobalWindowInner.cpp" , 7762); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mWindowGlobalChild->BrowsingContext() == mBrowsingContext" ")"); do { *((volatile int*)__null) = 7762; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); | |||
7763 | } else { | |||
7764 | mWindowID = nsContentUtils::GenerateWindowId(); | |||
7765 | } | |||
7766 | } | |||
7767 | ||||
7768 | nsPIDOMWindowInner::~nsPIDOMWindowInner() = default; | |||
7769 | ||||
7770 | #undef FORWARD_TO_OUTER | |||
7771 | #undef FORWARD_TO_OUTER_OR_THROW | |||
7772 | #undef FORWARD_TO_OUTER_VOID |