Backed out changeset 2450366cf7ca (bug 1891629) for causing win msix mochitest failures
[gecko.git] / dom / base / InProcessBrowserChildMessageManager.cpp
blob830c57591bc27fe9df6148438040e5a968be4853
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 "InProcessBrowserChildMessageManager.h"
8 #include "nsContentUtils.h"
9 #include "nsDocShell.h"
10 #include "nsIInterfaceRequestorUtils.h"
11 #include "nsComponentManagerUtils.h"
12 #include "nsFrameLoader.h"
13 #include "nsFrameLoaderOwner.h"
14 #include "nsQueryObject.h"
15 #include "xpcpublic.h"
16 #include "mozilla/EventDispatcher.h"
17 #include "mozilla/dom/ChromeMessageSender.h"
18 #include "mozilla/dom/Document.h"
19 #include "mozilla/dom/MessageManagerBinding.h"
20 #include "mozilla/dom/SameProcessMessageQueue.h"
21 #include "mozilla/dom/ScriptLoader.h"
22 #include "mozilla/dom/WindowProxyHolder.h"
23 #include "mozilla/dom/JSActorService.h"
24 #include "mozilla/HoldDropJSObjects.h"
26 using namespace mozilla;
27 using namespace mozilla::dom;
28 using namespace mozilla::dom::ipc;
30 /* static */
31 already_AddRefed<InProcessBrowserChildMessageManager>
32 InProcessBrowserChildMessageManager::Create(nsDocShell* aShell,
33 nsIContent* aOwner,
34 nsFrameMessageManager* aChrome) {
35 RefPtr<InProcessBrowserChildMessageManager> mm =
36 new InProcessBrowserChildMessageManager(aShell, aOwner, aChrome);
38 NS_ENSURE_TRUE(mm->Init(), nullptr);
40 if (XRE_IsParentProcess()) {
41 RefPtr<JSActorService> wasvc = JSActorService::GetSingleton();
42 wasvc->RegisterChromeEventTarget(mm);
45 return mm.forget();
48 bool InProcessBrowserChildMessageManager::DoSendBlockingMessage(
49 const nsAString& aMessage, StructuredCloneData& aData,
50 nsTArray<StructuredCloneData>* aRetVal) {
51 SameProcessMessageQueue* queue = SameProcessMessageQueue::Get();
52 queue->Flush();
54 if (mChromeMessageManager) {
55 RefPtr<nsFrameMessageManager> mm = mChromeMessageManager;
56 RefPtr<nsFrameLoader> fl = GetFrameLoader();
57 mm->ReceiveMessage(mOwner, fl, aMessage, true, &aData, aRetVal,
58 IgnoreErrors());
60 return true;
63 class nsAsyncMessageToParent : public nsSameProcessAsyncMessageBase,
64 public SameProcessMessageQueue::Runnable {
65 public:
66 explicit nsAsyncMessageToParent(
67 InProcessBrowserChildMessageManager* aBrowserChild)
68 : mBrowserChild(aBrowserChild) {}
70 virtual nsresult HandleMessage() override {
71 RefPtr<nsFrameLoader> fl = mBrowserChild->GetFrameLoader();
72 ReceiveMessage(mBrowserChild->mOwner, fl,
73 mBrowserChild->mChromeMessageManager);
74 return NS_OK;
76 RefPtr<InProcessBrowserChildMessageManager> mBrowserChild;
79 nsresult InProcessBrowserChildMessageManager::DoSendAsyncMessage(
80 const nsAString& aMessage, StructuredCloneData& aData) {
81 SameProcessMessageQueue* queue = SameProcessMessageQueue::Get();
82 RefPtr<nsAsyncMessageToParent> ev = new nsAsyncMessageToParent(this);
84 nsresult rv = ev->Init(aMessage, aData);
85 if (NS_FAILED(rv)) {
86 return rv;
89 queue->Push(ev);
90 return NS_OK;
93 InProcessBrowserChildMessageManager::InProcessBrowserChildMessageManager(
94 nsDocShell* aShell, nsIContent* aOwner, nsFrameMessageManager* aChrome)
95 : ContentFrameMessageManager(new nsFrameMessageManager(this)),
96 mDocShell(aShell),
97 mLoadingScript(false),
98 mPreventEventsEscaping(false),
99 mOwner(aOwner),
100 mChromeMessageManager(aChrome) {
101 mozilla::HoldJSObjects(this);
104 InProcessBrowserChildMessageManager::~InProcessBrowserChildMessageManager() {
105 if (XRE_IsParentProcess()) {
106 JSActorService::UnregisterChromeEventTarget(this);
109 mozilla::DropJSObjects(this);
112 // This method isn't automatically forwarded safely because it's notxpcom, so
113 // the IDL binding doesn't know what value to return.
114 void InProcessBrowserChildMessageManager::MarkForCC() {
115 MarkScopesForCC();
116 MessageManagerGlobal::MarkForCC();
119 NS_IMPL_CYCLE_COLLECTION_CLASS(InProcessBrowserChildMessageManager)
121 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(
122 InProcessBrowserChildMessageManager, DOMEventTargetHelper)
123 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessageManager)
124 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocShell)
125 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
127 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(
128 InProcessBrowserChildMessageManager, DOMEventTargetHelper)
129 tmp->nsMessageManagerScriptExecutor::Trace(aCallbacks, aClosure);
130 NS_IMPL_CYCLE_COLLECTION_TRACE_END
132 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(
133 InProcessBrowserChildMessageManager, DOMEventTargetHelper)
134 if (XRE_IsParentProcess()) {
135 JSActorService::UnregisterChromeEventTarget(tmp);
138 NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessageManager)
139 NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocShell)
140 tmp->nsMessageManagerScriptExecutor::Unlink();
141 NS_IMPL_CYCLE_COLLECTION_UNLINK_WEAK_REFERENCE
142 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
144 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(InProcessBrowserChildMessageManager)
145 NS_INTERFACE_MAP_ENTRY(nsIMessageSender)
146 NS_INTERFACE_MAP_ENTRY(nsIInProcessContentFrameMessageManager)
147 NS_INTERFACE_MAP_ENTRY_CONCRETE(ContentFrameMessageManager)
148 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
149 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
151 NS_IMPL_ADDREF_INHERITED(InProcessBrowserChildMessageManager,
152 DOMEventTargetHelper)
153 NS_IMPL_RELEASE_INHERITED(InProcessBrowserChildMessageManager,
154 DOMEventTargetHelper)
156 JSObject* InProcessBrowserChildMessageManager::WrapObject(
157 JSContext* aCx, JS::Handle<JSObject*> aGivenProto) {
158 return ContentFrameMessageManager_Binding::Wrap(aCx, this, aGivenProto);
161 void InProcessBrowserChildMessageManager::CacheFrameLoader(
162 nsFrameLoader* aFrameLoader) {
163 mFrameLoader = aFrameLoader;
166 Nullable<WindowProxyHolder> InProcessBrowserChildMessageManager::GetContent(
167 ErrorResult& aError) {
168 if (!mDocShell) {
169 return nullptr;
171 return WindowProxyHolder(mDocShell->GetBrowsingContext());
174 already_AddRefed<nsIEventTarget>
175 InProcessBrowserChildMessageManager::GetTabEventTarget() {
176 nsCOMPtr<nsIEventTarget> target = GetMainThreadSerialEventTarget();
177 return target.forget();
180 void InProcessBrowserChildMessageManager::FireUnloadEvent() {
181 // We're called from Document::MaybeInitializeFinalizeFrameLoaders, so it
182 // should be safe to run script.
183 MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());
185 // Don't let the unload event propagate to chrome event handlers.
186 mPreventEventsEscaping = true;
187 DOMEventTargetHelper::DispatchTrustedEvent(u"unload"_ns);
189 // Allow events fired during docshell destruction (pagehide, unload) to
190 // propagate to the <browser> element since chrome code depends on this.
191 mPreventEventsEscaping = false;
194 void InProcessBrowserChildMessageManager::DisconnectEventListeners() {
195 if (mDocShell) {
196 if (nsCOMPtr<nsPIDOMWindowOuter> win = mDocShell->GetWindow()) {
197 win->SetChromeEventHandler(win->GetChromeEventHandler());
200 if (mListenerManager) {
201 mListenerManager->Disconnect();
204 mDocShell = nullptr;
207 void InProcessBrowserChildMessageManager::Disconnect() {
208 mChromeMessageManager = nullptr;
209 mOwner = nullptr;
210 if (mMessageManager) {
211 static_cast<nsFrameMessageManager*>(mMessageManager.get())->Disconnect();
212 mMessageManager = nullptr;
216 NS_IMETHODIMP_(nsIContent*)
217 InProcessBrowserChildMessageManager::GetOwnerContent() { return mOwner; }
219 void InProcessBrowserChildMessageManager::GetEventTargetParent(
220 EventChainPreVisitor& aVisitor) {
221 aVisitor.mForceContentDispatch = true;
222 aVisitor.mCanHandle = true;
224 if (mPreventEventsEscaping) {
225 aVisitor.SetParentTarget(nullptr, false);
226 return;
229 aVisitor.SetParentTarget(mOwner, false);
232 class nsAsyncScriptLoad : public Runnable {
233 public:
234 nsAsyncScriptLoad(InProcessBrowserChildMessageManager* aBrowserChild,
235 const nsAString& aURL, bool aRunInGlobalScope)
236 : mozilla::Runnable("nsAsyncScriptLoad"),
237 mBrowserChild(aBrowserChild),
238 mURL(aURL),
239 mRunInGlobalScope(aRunInGlobalScope) {}
241 NS_IMETHOD Run() override {
242 mBrowserChild->LoadFrameScript(mURL, mRunInGlobalScope);
243 return NS_OK;
245 RefPtr<InProcessBrowserChildMessageManager> mBrowserChild;
246 nsString mURL;
247 bool mRunInGlobalScope;
250 void InProcessBrowserChildMessageManager::LoadFrameScript(
251 const nsAString& aURL, bool aRunInGlobalScope) {
252 if (!nsContentUtils::IsSafeToRunScript()) {
253 nsContentUtils::AddScriptRunner(
254 new nsAsyncScriptLoad(this, aURL, aRunInGlobalScope));
255 return;
257 bool tmp = mLoadingScript;
258 mLoadingScript = true;
259 JS::Rooted<JSObject*> mm(mozilla::dom::RootingCx(), GetOrCreateWrapper());
260 LoadScriptInternal(mm, aURL, !aRunInGlobalScope);
261 mLoadingScript = tmp;
264 already_AddRefed<nsFrameLoader>
265 InProcessBrowserChildMessageManager::GetFrameLoader() {
266 RefPtr<nsFrameLoaderOwner> owner = do_QueryObject(mOwner);
267 RefPtr<nsFrameLoader> fl = owner ? owner->GetFrameLoader() : nullptr;
268 if (!fl) {
269 fl = mFrameLoader;
271 return fl.forget();