Bug 1908539 restrict MacOS platform audio processing to Nightly r=webrtc-reviewers...
[gecko.git] / dom / base / WindowDestroyedEvent.cpp
blobc2e57d159eec4d6c3ffd2135ec6faddb91f9e04c
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/. */
7 #include "WindowDestroyedEvent.h"
9 #include "nsJSUtils.h"
10 #include "jsapi.h"
11 #include "js/Wrapper.h"
12 #include "nsIPrincipal.h"
13 #include "nsISupportsPrimitives.h"
14 #include "nsIAppStartup.h"
15 #include "nsJSPrincipals.h"
16 #include "nsCOMPtr.h"
17 #include "nsContentUtils.h"
18 #include "nsGlobalWindowInner.h"
19 #include "nsGlobalWindowOuter.h"
20 #include "xpcpublic.h"
21 #include "mozilla/AppShutdown.h"
22 #include "mozilla/BasePrincipal.h"
23 #include "mozilla/Components.h"
24 #include "mozilla/ProfilerLabels.h"
25 #include "nsFocusManager.h"
27 namespace mozilla {
29 struct BrowserCompartmentMatcher : public js::CompartmentFilter {
30 bool match(JS::Compartment* aC) const override {
31 return !xpc::MightBeWebContentCompartment(aC);
35 WindowDestroyedEvent::WindowDestroyedEvent(nsGlobalWindowInner* aWindow,
36 uint64_t aID, const char* aTopic)
37 : mozilla::Runnable("WindowDestroyedEvent"),
38 mID(aID),
39 mPhase(Phase::Destroying),
40 mTopic(aTopic),
41 mIsInnerWindow(true) {
42 mWindow = do_GetWeakReference(aWindow);
45 WindowDestroyedEvent::WindowDestroyedEvent(nsGlobalWindowOuter* aWindow,
46 uint64_t aID, const char* aTopic)
47 : mozilla::Runnable("WindowDestroyedEvent"),
48 mID(aID),
49 mPhase(Phase::Destroying),
50 mTopic(aTopic),
51 mIsInnerWindow(false) {
52 mWindow = do_GetWeakReference(aWindow);
55 NS_IMETHODIMP
56 WindowDestroyedEvent::Run() {
57 AUTO_PROFILER_LABEL("WindowDestroyedEvent::Run", OTHER);
59 nsCOMPtr<nsPIDOMWindowOuter> nukedOuter;
61 nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
62 if (!observerService) {
63 return NS_OK;
66 nsCOMPtr<nsISupportsPRUint64> wrapper =
67 do_CreateInstance(NS_SUPPORTS_PRUINT64_CONTRACTID);
68 if (wrapper) {
69 wrapper->SetData(mID);
70 observerService->NotifyObservers(wrapper, mTopic.get(), nullptr);
73 switch (mPhase) {
74 case Phase::Destroying: {
75 bool skipNukeCrossCompartment = false;
76 #ifndef DEBUG
77 skipNukeCrossCompartment =
78 AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed);
79 #endif
81 if (!skipNukeCrossCompartment) {
82 // The compartment nuking phase might be too expensive, so do that
83 // part off of idle dispatch.
85 // For the compartment nuking phase, we dispatch either an
86 // inner-window-nuked or an outer-window-nuked notification.
87 // This will allow tests to wait for compartment nuking to happen.
88 if (mTopic.EqualsLiteral("inner-window-destroyed")) {
89 mTopic.AssignLiteral("inner-window-nuked");
90 } else if (mTopic.EqualsLiteral("outer-window-destroyed")) {
91 mTopic.AssignLiteral("outer-window-nuked");
93 mPhase = Phase::Nuking;
95 nsCOMPtr<nsIRunnable> copy(this);
96 NS_DispatchToCurrentThreadQueue(copy.forget(), 1000,
97 EventQueuePriority::Idle);
99 } break;
101 case Phase::Nuking: {
102 nsCOMPtr<nsISupports> window = do_QueryReferent(mWindow);
103 if (window) {
104 nsGlobalWindowInner* currentInner;
105 if (mIsInnerWindow) {
106 currentInner = nsGlobalWindowInner::FromSupports(window);
107 } else {
108 nsGlobalWindowOuter* outer =
109 nsGlobalWindowOuter::FromSupports(window);
110 currentInner =
111 nsGlobalWindowInner::Cast(outer->GetCurrentInnerWindow());
112 nukedOuter = outer;
114 NS_ENSURE_TRUE(currentInner, NS_OK);
116 dom::AutoJSAPI jsapi;
117 jsapi.Init();
118 JSContext* cx = jsapi.cx();
119 JS::Rooted<JSObject*> obj(cx, currentInner->GetGlobalJSObject());
120 if (obj && !js::IsSystemRealm(js::GetNonCCWObjectRealm(obj))) {
121 JS::Realm* realm = js::GetNonCCWObjectRealm(obj);
123 xpc::NukeJSStackFrames(realm);
125 nsCOMPtr<nsIPrincipal> pc =
126 nsJSPrincipals::get(JS::GetRealmPrincipals(realm));
128 if (BasePrincipal::Cast(pc)->AddonPolicy()) {
129 // We want to nuke all references to the add-on realm.
130 xpc::NukeAllWrappersForRealm(cx, realm,
131 mIsInnerWindow
132 ? js::DontNukeWindowReferences
133 : js::NukeWindowReferences);
134 } else {
135 // We only want to nuke wrappers for the chrome->content case
136 js::NukeCrossCompartmentWrappers(
137 cx, BrowserCompartmentMatcher(), realm,
138 mIsInnerWindow ? js::DontNukeWindowReferences
139 : js::NukeWindowReferences,
140 js::NukeIncomingReferences);
144 } break;
147 if (nukedOuter) {
148 nsFocusManager* fm = nsFocusManager::GetFocusManager();
149 if (fm) {
150 fm->WasNuked(nukedOuter);
154 return NS_OK;
157 } // namespace mozilla