1 /* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8; -*- */
2 /* vim: set sw=4 ts=8 et 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 "nsInProcessTabChildGlobal.h"
8 #include "nsContentUtils.h"
9 #include "nsIScriptSecurityManager.h"
10 #include "nsIInterfaceRequestorUtils.h"
11 #include "nsIComponentManager.h"
12 #include "nsIServiceManager.h"
13 #include "nsIJSRuntimeService.h"
14 #include "nsComponentManagerUtils.h"
15 #include "nsNetUtil.h"
16 #include "nsScriptLoader.h"
17 #include "nsFrameLoader.h"
18 #include "xpcpublic.h"
19 #include "nsIMozBrowserFrame.h"
20 #include "nsDOMClassInfoID.h"
21 #include "mozilla/EventDispatcher.h"
22 #include "mozilla/dom/StructuredCloneUtils.h"
23 #include "js/StructuredClone.h"
25 using mozilla::dom::StructuredCloneData
;
26 using mozilla::dom::StructuredCloneClosure
;
27 using namespace mozilla
;
30 nsInProcessTabChildGlobal::DoSendBlockingMessage(JSContext
* aCx
,
31 const nsAString
& aMessage
,
32 const dom::StructuredCloneData
& aData
,
33 JS::Handle
<JSObject
*> aCpows
,
34 nsIPrincipal
* aPrincipal
,
35 InfallibleTArray
<nsString
>* aJSONRetVal
,
38 nsTArray
<nsCOMPtr
<nsIRunnable
> > asyncMessages
;
39 asyncMessages
.SwapElements(mASyncMessages
);
40 uint32_t len
= asyncMessages
.Length();
41 for (uint32_t i
= 0; i
< len
; ++i
) {
42 nsCOMPtr
<nsIRunnable
> async
= asyncMessages
[i
];
45 if (mChromeMessageManager
) {
46 SameProcessCpowHolder
cpows(js::GetRuntime(aCx
), aCpows
);
47 nsRefPtr
<nsFrameMessageManager
> mm
= mChromeMessageManager
;
48 mm
->ReceiveMessage(mOwner
, aMessage
, true, &aData
, &cpows
, aPrincipal
,
54 class nsAsyncMessageToParent
: public nsSameProcessAsyncMessageBase
,
58 nsAsyncMessageToParent(JSContext
* aCx
,
59 nsInProcessTabChildGlobal
* aTabChild
,
60 const nsAString
& aMessage
,
61 const StructuredCloneData
& aData
,
62 JS::Handle
<JSObject
*> aCpows
,
63 nsIPrincipal
* aPrincipal
)
64 : nsSameProcessAsyncMessageBase(aCx
, aMessage
, aData
, aCpows
, aPrincipal
),
65 mTabChild(aTabChild
), mRun(false)
76 mTabChild
->mASyncMessages
.RemoveElement(this);
77 ReceiveMessage(mTabChild
->mOwner
, mTabChild
->mChromeMessageManager
);
80 nsRefPtr
<nsInProcessTabChildGlobal
> mTabChild
;
81 // True if this runnable has already been called. This can happen if DoSendSyncMessage
82 // is called while waiting for an asynchronous message send.
87 nsInProcessTabChildGlobal::DoSendAsyncMessage(JSContext
* aCx
,
88 const nsAString
& aMessage
,
89 const StructuredCloneData
& aData
,
90 JS::Handle
<JSObject
*> aCpows
,
91 nsIPrincipal
* aPrincipal
)
93 nsCOMPtr
<nsIRunnable
> ev
=
94 new nsAsyncMessageToParent(aCx
, this, aMessage
, aData
, aCpows
, aPrincipal
);
95 mASyncMessages
.AppendElement(ev
);
96 NS_DispatchToCurrentThread(ev
);
100 nsInProcessTabChildGlobal::nsInProcessTabChildGlobal(nsIDocShell
* aShell
,
102 nsFrameMessageManager
* aChrome
)
103 : mDocShell(aShell
), mInitialized(false), mLoadingScript(false),
104 mOwner(aOwner
), mChromeMessageManager(aChrome
)
106 SetIsNotDOMBinding();
107 mozilla::HoldJSObjects(this);
109 // If owner corresponds to an <iframe mozbrowser> or <iframe mozapp>, we'll
110 // have to tweak our PreHandleEvent implementation.
111 nsCOMPtr
<nsIMozBrowserFrame
> browserFrame
= do_QueryInterface(mOwner
);
113 mIsBrowserOrAppFrame
= browserFrame
->GetReallyIsBrowserOrApp();
116 mIsBrowserOrAppFrame
= false;
120 nsInProcessTabChildGlobal::~nsInProcessTabChildGlobal()
122 mAnonymousGlobalScopes
.Clear();
123 mozilla::DropJSObjects(this);
126 /* [notxpcom] boolean markForCC (); */
127 // This method isn't automatically forwarded safely because it's notxpcom, so
128 // the IDL binding doesn't know what value to return.
130 nsInProcessTabChildGlobal::MarkForCC()
132 return mMessageManager
? mMessageManager
->MarkForCC() : false;
136 nsInProcessTabChildGlobal::Init()
141 InitTabChildGlobal();
142 NS_WARN_IF_FALSE(NS_SUCCEEDED(rv
),
143 "Couldn't initialize nsInProcessTabChildGlobal");
144 mMessageManager
= new nsFrameMessageManager(this,
150 NS_IMPL_CYCLE_COLLECTION_CLASS(nsInProcessTabChildGlobal
)
153 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsInProcessTabChildGlobal
,
154 DOMEventTargetHelper
)
155 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessageManager
)
156 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobal
)
157 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
159 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(nsInProcessTabChildGlobal
,
160 DOMEventTargetHelper
)
161 for (uint32_t i
= 0; i
< tmp
->mAnonymousGlobalScopes
.Length(); ++i
) {
162 NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mAnonymousGlobalScopes
[i
])
164 NS_IMPL_CYCLE_COLLECTION_TRACE_END
166 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsInProcessTabChildGlobal
,
167 DOMEventTargetHelper
)
168 NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessageManager
)
169 NS_IMPL_CYCLE_COLLECTION_UNLINK(mGlobal
)
170 NS_IMPL_CYCLE_COLLECTION_UNLINK(mAnonymousGlobalScopes
)
171 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
173 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsInProcessTabChildGlobal
)
174 NS_INTERFACE_MAP_ENTRY(nsIMessageListenerManager
)
175 NS_INTERFACE_MAP_ENTRY(nsIMessageSender
)
176 NS_INTERFACE_MAP_ENTRY(nsISyncMessageSender
)
177 NS_INTERFACE_MAP_ENTRY(nsIContentFrameMessageManager
)
178 NS_INTERFACE_MAP_ENTRY(nsIInProcessContentFrameMessageManager
)
179 NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal
)
180 NS_INTERFACE_MAP_ENTRY(nsIGlobalObject
)
181 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference
)
182 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ContentFrameMessageManager
)
183 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper
)
185 NS_IMPL_ADDREF_INHERITED(nsInProcessTabChildGlobal
, DOMEventTargetHelper
)
186 NS_IMPL_RELEASE_INHERITED(nsInProcessTabChildGlobal
, DOMEventTargetHelper
)
189 nsInProcessTabChildGlobal::GetContent(nsIDOMWindow
** aContent
)
196 nsCOMPtr
<nsIDOMWindow
> window
= mDocShell
->GetWindow();
197 window
.swap(*aContent
);
202 nsInProcessTabChildGlobal::GetDocShell(nsIDocShell
** aDocShell
)
204 NS_IF_ADDREF(*aDocShell
= mDocShell
);
209 nsInProcessTabChildGlobal::Btoa(const nsAString
& aBinaryData
,
210 nsAString
& aAsciiBase64String
)
212 return nsContentUtils::Btoa(aBinaryData
, aAsciiBase64String
);
216 nsInProcessTabChildGlobal::Atob(const nsAString
& aAsciiString
,
217 nsAString
& aBinaryData
)
219 return nsContentUtils::Atob(aAsciiString
, aBinaryData
);
224 nsInProcessTabChildGlobal::PrivateNoteIntentionalCrash()
226 return NS_ERROR_NOT_IMPLEMENTED
;
230 nsInProcessTabChildGlobal::Disconnect()
232 // Let the frame scripts know the child is being closed. We do any other
233 // cleanup after the event has been fired. See DelayedDisconnect
234 nsContentUtils::AddScriptRunner(
235 NS_NewRunnableMethod(this, &nsInProcessTabChildGlobal::DelayedDisconnect
)
240 nsInProcessTabChildGlobal::DelayedDisconnect()
242 // Don't let the event escape
245 // Fire the "unload" event
246 DOMEventTargetHelper::DispatchTrustedEvent(NS_LITERAL_STRING("unload"));
248 // Continue with the Disconnect cleanup
250 nsCOMPtr
<nsPIDOMWindow
> win
= mDocShell
->GetWindow();
252 MOZ_ASSERT(win
->IsOuterWindow());
253 win
->SetChromeEventHandler(win
->GetChromeEventHandler());
257 mChromeMessageManager
= nullptr;
258 if (mMessageManager
) {
259 static_cast<nsFrameMessageManager
*>(mMessageManager
.get())->Disconnect();
260 mMessageManager
= nullptr;
262 if (mListenerManager
) {
263 mListenerManager
->Disconnect();
267 NS_IMETHODIMP_(nsIContent
*)
268 nsInProcessTabChildGlobal::GetOwnerContent()
274 nsInProcessTabChildGlobal::PreHandleEvent(EventChainPreVisitor
& aVisitor
)
276 aVisitor
.mCanHandle
= true;
278 if (mIsBrowserOrAppFrame
&&
279 (!mOwner
|| !nsContentUtils::IsInChromeDocshell(mOwner
->OwnerDoc()))) {
281 nsPIDOMWindow
* innerWindow
= mOwner
->OwnerDoc()->GetInnerWindow();
283 aVisitor
.mParentTarget
= innerWindow
->GetParentTarget();
287 aVisitor
.mParentTarget
= mOwner
;
292 nsCOMPtr
<nsIFrameLoaderOwner
> owner
= do_QueryInterface(mOwner
);
293 nsRefPtr
<nsFrameLoader
> fl
= owner
->GetFrameLoader();
295 NS_ASSERTION(this == fl
->GetTabChildGlobalAsEventTarget(),
296 "Wrong event target!");
297 NS_ASSERTION(fl
->mMessageManager
== mChromeMessageManager
,
298 "Wrong message manager!");
307 nsInProcessTabChildGlobal::InitTabChildGlobal()
309 // If you change this, please change GetCompartmentName() in XPCJSRuntime.cpp
312 id
.AssignLiteral("inProcessTabChildGlobal");
313 nsIURI
* uri
= mOwner
->OwnerDoc()->GetDocumentURI();
317 id
.AppendLiteral("?ownedBy=");
320 nsISupports
* scopeSupports
= NS_ISUPPORTS_CAST(EventTarget
*, this);
321 NS_ENSURE_STATE(InitTabChildGlobalInternal(scopeSupports
, id
));
325 class nsAsyncScriptLoad
: public nsRunnable
328 nsAsyncScriptLoad(nsInProcessTabChildGlobal
* aTabChild
, const nsAString
& aURL
,
329 bool aRunInGlobalScope
)
330 : mTabChild(aTabChild
), mURL(aURL
), mRunInGlobalScope(aRunInGlobalScope
) {}
334 mTabChild
->LoadFrameScript(mURL
, mRunInGlobalScope
);
337 nsRefPtr
<nsInProcessTabChildGlobal
> mTabChild
;
339 bool mRunInGlobalScope
;
343 nsInProcessTabChildGlobal::LoadFrameScript(const nsAString
& aURL
, bool aRunInGlobalScope
)
345 if (!nsContentUtils::IsSafeToRunScript()) {
346 nsContentUtils::AddScriptRunner(new nsAsyncScriptLoad(this, aURL
, aRunInGlobalScope
));
353 bool tmp
= mLoadingScript
;
354 mLoadingScript
= true;
355 LoadFrameScriptInternal(aURL
, aRunInGlobalScope
);
356 mLoadingScript
= tmp
;