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
;
31 already_AddRefed
<InProcessBrowserChildMessageManager
>
32 InProcessBrowserChildMessageManager::Create(nsDocShell
* aShell
,
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
);
48 bool InProcessBrowserChildMessageManager::DoSendBlockingMessage(
49 const nsAString
& aMessage
, StructuredCloneData
& aData
,
50 nsTArray
<StructuredCloneData
>* aRetVal
) {
51 SameProcessMessageQueue
* queue
= SameProcessMessageQueue::Get();
54 if (mChromeMessageManager
) {
55 RefPtr
<nsFrameMessageManager
> mm
= mChromeMessageManager
;
56 RefPtr
<nsFrameLoader
> fl
= GetFrameLoader();
57 mm
->ReceiveMessage(mOwner
, fl
, aMessage
, true, &aData
, aRetVal
,
63 class nsAsyncMessageToParent
: public nsSameProcessAsyncMessageBase
,
64 public SameProcessMessageQueue::Runnable
{
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
);
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
);
93 InProcessBrowserChildMessageManager::InProcessBrowserChildMessageManager(
94 nsDocShell
* aShell
, nsIContent
* aOwner
, nsFrameMessageManager
* aChrome
)
95 : ContentFrameMessageManager(new nsFrameMessageManager(this)),
97 mLoadingScript(false),
98 mPreventEventsEscaping(false),
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() {
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
) {
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() {
196 if (nsCOMPtr
<nsPIDOMWindowOuter
> win
= mDocShell
->GetWindow()) {
197 win
->SetChromeEventHandler(win
->GetChromeEventHandler());
200 if (mListenerManager
) {
201 mListenerManager
->Disconnect();
207 void InProcessBrowserChildMessageManager::Disconnect() {
208 mChromeMessageManager
= 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);
229 aVisitor
.SetParentTarget(mOwner
, false);
232 class nsAsyncScriptLoad
: public Runnable
{
234 nsAsyncScriptLoad(InProcessBrowserChildMessageManager
* aBrowserChild
,
235 const nsAString
& aURL
, bool aRunInGlobalScope
)
236 : mozilla::Runnable("nsAsyncScriptLoad"),
237 mBrowserChild(aBrowserChild
),
239 mRunInGlobalScope(aRunInGlobalScope
) {}
241 NS_IMETHOD
Run() override
{
242 mBrowserChild
->LoadFrameScript(mURL
, mRunInGlobalScope
);
245 RefPtr
<InProcessBrowserChildMessageManager
> mBrowserChild
;
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
));
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;