Bumping gaia.json for 8 gaia revision(s) a=gaia-bump
[gecko.git] / dom / base / nsInProcessTabChildGlobal.cpp
blob04500690f86ca15e72c4dfe33188981780293d01
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;
29 bool
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,
36 bool aIsSync)
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];
43 async->Run();
45 if (mChromeMessageManager) {
46 SameProcessCpowHolder cpows(js::GetRuntime(aCx), aCpows);
47 nsRefPtr<nsFrameMessageManager> mm = mChromeMessageManager;
48 mm->ReceiveMessage(mOwner, aMessage, true, &aData, &cpows, aPrincipal,
49 aJSONRetVal);
51 return true;
54 class nsAsyncMessageToParent : public nsSameProcessAsyncMessageBase,
55 public nsRunnable
57 public:
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)
69 NS_IMETHOD Run()
71 if (mRun) {
72 return NS_OK;
75 mRun = true;
76 mTabChild->mASyncMessages.RemoveElement(this);
77 ReceiveMessage(mTabChild->mOwner, mTabChild->mChromeMessageManager);
78 return NS_OK;
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.
83 bool mRun;
86 bool
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);
97 return true;
100 nsInProcessTabChildGlobal::nsInProcessTabChildGlobal(nsIDocShell* aShell,
101 nsIContent* aOwner,
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);
112 if (browserFrame) {
113 mIsBrowserOrAppFrame = browserFrame->GetReallyIsBrowserOrApp();
115 else {
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.
129 NS_IMETHODIMP_(bool)
130 nsInProcessTabChildGlobal::MarkForCC()
132 return mMessageManager ? mMessageManager->MarkForCC() : false;
135 nsresult
136 nsInProcessTabChildGlobal::Init()
138 #ifdef DEBUG
139 nsresult rv =
140 #endif
141 InitTabChildGlobal();
142 NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
143 "Couldn't initialize nsInProcessTabChildGlobal");
144 mMessageManager = new nsFrameMessageManager(this,
145 nullptr,
146 dom::ipc::MM_CHILD);
147 return NS_OK;
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)
188 NS_IMETHODIMP
189 nsInProcessTabChildGlobal::GetContent(nsIDOMWindow** aContent)
191 *aContent = nullptr;
192 if (!mDocShell) {
193 return NS_OK;
196 nsCOMPtr<nsIDOMWindow> window = mDocShell->GetWindow();
197 window.swap(*aContent);
198 return NS_OK;
201 NS_IMETHODIMP
202 nsInProcessTabChildGlobal::GetDocShell(nsIDocShell** aDocShell)
204 NS_IF_ADDREF(*aDocShell = mDocShell);
205 return NS_OK;
208 NS_IMETHODIMP
209 nsInProcessTabChildGlobal::Btoa(const nsAString& aBinaryData,
210 nsAString& aAsciiBase64String)
212 return nsContentUtils::Btoa(aBinaryData, aAsciiBase64String);
215 NS_IMETHODIMP
216 nsInProcessTabChildGlobal::Atob(const nsAString& aAsciiString,
217 nsAString& aBinaryData)
219 return nsContentUtils::Atob(aAsciiString, aBinaryData);
223 NS_IMETHODIMP
224 nsInProcessTabChildGlobal::PrivateNoteIntentionalCrash()
226 return NS_ERROR_NOT_IMPLEMENTED;
229 void
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)
239 void
240 nsInProcessTabChildGlobal::DelayedDisconnect()
242 // Don't let the event escape
243 mOwner = nullptr;
245 // Fire the "unload" event
246 DOMEventTargetHelper::DispatchTrustedEvent(NS_LITERAL_STRING("unload"));
248 // Continue with the Disconnect cleanup
249 if (mDocShell) {
250 nsCOMPtr<nsPIDOMWindow> win = mDocShell->GetWindow();
251 if (win) {
252 MOZ_ASSERT(win->IsOuterWindow());
253 win->SetChromeEventHandler(win->GetChromeEventHandler());
256 mDocShell = nullptr;
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()
270 return mOwner;
273 nsresult
274 nsInProcessTabChildGlobal::PreHandleEvent(EventChainPreVisitor& aVisitor)
276 aVisitor.mCanHandle = true;
278 if (mIsBrowserOrAppFrame &&
279 (!mOwner || !nsContentUtils::IsInChromeDocshell(mOwner->OwnerDoc()))) {
280 if (mOwner) {
281 nsPIDOMWindow* innerWindow = mOwner->OwnerDoc()->GetInnerWindow();
282 if (innerWindow) {
283 aVisitor.mParentTarget = innerWindow->GetParentTarget();
286 } else {
287 aVisitor.mParentTarget = mOwner;
290 #ifdef DEBUG
291 if (mOwner) {
292 nsCOMPtr<nsIFrameLoaderOwner> owner = do_QueryInterface(mOwner);
293 nsRefPtr<nsFrameLoader> fl = owner->GetFrameLoader();
294 if (fl) {
295 NS_ASSERTION(this == fl->GetTabChildGlobalAsEventTarget(),
296 "Wrong event target!");
297 NS_ASSERTION(fl->mMessageManager == mChromeMessageManager,
298 "Wrong message manager!");
301 #endif
303 return NS_OK;
306 nsresult
307 nsInProcessTabChildGlobal::InitTabChildGlobal()
309 // If you change this, please change GetCompartmentName() in XPCJSRuntime.cpp
310 // accordingly.
311 nsAutoCString id;
312 id.AssignLiteral("inProcessTabChildGlobal");
313 nsIURI* uri = mOwner->OwnerDoc()->GetDocumentURI();
314 if (uri) {
315 nsAutoCString u;
316 uri->GetSpec(u);
317 id.AppendLiteral("?ownedBy=");
318 id.Append(u);
320 nsISupports* scopeSupports = NS_ISUPPORTS_CAST(EventTarget*, this);
321 NS_ENSURE_STATE(InitTabChildGlobalInternal(scopeSupports, id));
322 return NS_OK;
325 class nsAsyncScriptLoad : public nsRunnable
327 public:
328 nsAsyncScriptLoad(nsInProcessTabChildGlobal* aTabChild, const nsAString& aURL,
329 bool aRunInGlobalScope)
330 : mTabChild(aTabChild), mURL(aURL), mRunInGlobalScope(aRunInGlobalScope) {}
332 NS_IMETHOD Run()
334 mTabChild->LoadFrameScript(mURL, mRunInGlobalScope);
335 return NS_OK;
337 nsRefPtr<nsInProcessTabChildGlobal> mTabChild;
338 nsString mURL;
339 bool mRunInGlobalScope;
342 void
343 nsInProcessTabChildGlobal::LoadFrameScript(const nsAString& aURL, bool aRunInGlobalScope)
345 if (!nsContentUtils::IsSafeToRunScript()) {
346 nsContentUtils::AddScriptRunner(new nsAsyncScriptLoad(this, aURL, aRunInGlobalScope));
347 return;
349 if (!mInitialized) {
350 mInitialized = true;
351 Init();
353 bool tmp = mLoadingScript;
354 mLoadingScript = true;
355 LoadFrameScriptInternal(aURL, aRunInGlobalScope);
356 mLoadingScript = tmp;