Backed out 35 changesets (bug 941158, bug 972518, bug 959520, bug 986063, bug 948895...
[gecko.git] / content / base / src / nsInProcessTabChildGlobal.cpp
blobf6e89831f1c439d67a107a4f0ca469bfab1a9dff
1 /* -*- Mode: C++; c-basic-offset: 4; 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 "nsEventDispatcher.h"
12 #include "nsIComponentManager.h"
13 #include "nsIServiceManager.h"
14 #include "nsIJSRuntimeService.h"
15 #include "nsComponentManagerUtils.h"
16 #include "nsNetUtil.h"
17 #include "nsScriptLoader.h"
18 #include "nsFrameLoader.h"
19 #include "xpcpublic.h"
20 #include "nsIMozBrowserFrame.h"
21 #include "nsDOMClassInfoID.h"
22 #include "mozilla/dom/StructuredCloneUtils.h"
23 #include "js/StructuredClone.h"
25 using mozilla::dom::StructuredCloneData;
26 using mozilla::dom::StructuredCloneClosure;
28 bool
29 nsInProcessTabChildGlobal::DoSendBlockingMessage(JSContext* aCx,
30 const nsAString& aMessage,
31 const mozilla::dom::StructuredCloneData& aData,
32 JS::Handle<JSObject *> aCpows,
33 nsIPrincipal* aPrincipal,
34 InfallibleTArray<nsString>* aJSONRetVal,
35 bool aIsSync)
37 nsTArray<nsCOMPtr<nsIRunnable> > asyncMessages;
38 asyncMessages.SwapElements(mASyncMessages);
39 uint32_t len = asyncMessages.Length();
40 for (uint32_t i = 0; i < len; ++i) {
41 nsCOMPtr<nsIRunnable> async = asyncMessages[i];
42 async->Run();
44 if (mChromeMessageManager) {
45 SameProcessCpowHolder cpows(js::GetRuntime(aCx), aCpows);
46 nsRefPtr<nsFrameMessageManager> mm = mChromeMessageManager;
47 mm->ReceiveMessage(mOwner, aMessage, true, &aData, &cpows, aPrincipal,
48 aJSONRetVal);
50 return true;
53 class nsAsyncMessageToParent : public nsRunnable
55 public:
56 nsAsyncMessageToParent(JSContext* aCx,
57 nsInProcessTabChildGlobal* aTabChild,
58 const nsAString& aMessage,
59 const StructuredCloneData& aData,
60 JS::Handle<JSObject *> aCpows,
61 nsIPrincipal* aPrincipal)
62 : mRuntime(js::GetRuntime(aCx)),
63 mTabChild(aTabChild),
64 mMessage(aMessage),
65 mCpows(aCpows),
66 mPrincipal(aPrincipal),
67 mRun(false)
69 if (aData.mDataLength && !mData.copy(aData.mData, aData.mDataLength)) {
70 NS_RUNTIMEABORT("OOM");
72 if (mCpows && !js_AddObjectRoot(mRuntime, &mCpows)) {
73 NS_RUNTIMEABORT("OOM");
75 mClosure = aData.mClosure;
78 ~nsAsyncMessageToParent()
80 if (mCpows) {
81 JS_RemoveObjectRootRT(mRuntime, &mCpows);
85 NS_IMETHOD Run()
87 if (mRun) {
88 return NS_OK;
91 mRun = true;
92 mTabChild->mASyncMessages.RemoveElement(this);
93 if (mTabChild->mChromeMessageManager) {
94 StructuredCloneData data;
95 data.mData = mData.data();
96 data.mDataLength = mData.nbytes();
97 data.mClosure = mClosure;
99 SameProcessCpowHolder cpows(mRuntime, JS::Handle<JSObject *>::fromMarkedLocation(&mCpows));
101 nsRefPtr<nsFrameMessageManager> mm = mTabChild->mChromeMessageManager;
102 mm->ReceiveMessage(mTabChild->mOwner, mMessage, false, &data, &cpows,
103 mPrincipal, nullptr);
105 return NS_OK;
107 JSRuntime* mRuntime;
108 nsRefPtr<nsInProcessTabChildGlobal> mTabChild;
109 nsString mMessage;
110 JSAutoStructuredCloneBuffer mData;
111 StructuredCloneClosure mClosure;
112 JSObject* mCpows;
113 nsCOMPtr<nsIPrincipal> mPrincipal;
114 // True if this runnable has already been called. This can happen if DoSendSyncMessage
115 // is called while waiting for an asynchronous message send.
116 bool mRun;
119 bool
120 nsInProcessTabChildGlobal::DoSendAsyncMessage(JSContext* aCx,
121 const nsAString& aMessage,
122 const StructuredCloneData& aData,
123 JS::Handle<JSObject *> aCpows,
124 nsIPrincipal* aPrincipal)
126 nsCOMPtr<nsIRunnable> ev =
127 new nsAsyncMessageToParent(aCx, this, aMessage, aData, aCpows, aPrincipal);
128 mASyncMessages.AppendElement(ev);
129 NS_DispatchToCurrentThread(ev);
130 return true;
133 nsInProcessTabChildGlobal::nsInProcessTabChildGlobal(nsIDocShell* aShell,
134 nsIContent* aOwner,
135 nsFrameMessageManager* aChrome)
136 : mDocShell(aShell), mInitialized(false), mLoadingScript(false),
137 mDelayedDisconnect(false), mOwner(aOwner), mChromeMessageManager(aChrome)
140 // If owner corresponds to an <iframe mozbrowser> or <iframe mozapp>, we'll
141 // have to tweak our PreHandleEvent implementation.
142 nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(mOwner);
143 if (browserFrame) {
144 mIsBrowserOrAppFrame = browserFrame->GetReallyIsBrowserOrApp();
146 else {
147 mIsBrowserOrAppFrame = false;
151 nsInProcessTabChildGlobal::~nsInProcessTabChildGlobal()
155 /* [notxpcom] boolean markForCC (); */
156 // This method isn't automatically forwarded safely because it's notxpcom, so
157 // the IDL binding doesn't know what value to return.
158 NS_IMETHODIMP_(bool)
159 nsInProcessTabChildGlobal::MarkForCC()
161 return mMessageManager ? mMessageManager->MarkForCC() : false;
164 nsresult
165 nsInProcessTabChildGlobal::Init()
167 #ifdef DEBUG
168 nsresult rv =
169 #endif
170 InitTabChildGlobal();
171 NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
172 "Couldn't initialize nsInProcessTabChildGlobal");
173 mMessageManager = new nsFrameMessageManager(this,
174 nullptr,
175 mozilla::dom::ipc::MM_CHILD);
176 return NS_OK;
179 NS_IMPL_CYCLE_COLLECTION_INHERITED_2(nsInProcessTabChildGlobal,
180 nsDOMEventTargetHelper,
181 mMessageManager,
182 mGlobal)
184 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsInProcessTabChildGlobal)
185 NS_INTERFACE_MAP_ENTRY(nsIMessageListenerManager)
186 NS_INTERFACE_MAP_ENTRY(nsIMessageSender)
187 NS_INTERFACE_MAP_ENTRY(nsISyncMessageSender)
188 NS_INTERFACE_MAP_ENTRY(nsIContentFrameMessageManager)
189 NS_INTERFACE_MAP_ENTRY(nsIInProcessContentFrameMessageManager)
190 NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
191 NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)
192 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
193 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ContentFrameMessageManager)
194 NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
196 NS_IMPL_ADDREF_INHERITED(nsInProcessTabChildGlobal, nsDOMEventTargetHelper)
197 NS_IMPL_RELEASE_INHERITED(nsInProcessTabChildGlobal, nsDOMEventTargetHelper)
199 NS_IMETHODIMP
200 nsInProcessTabChildGlobal::GetContent(nsIDOMWindow** aContent)
202 *aContent = nullptr;
203 nsCOMPtr<nsIDOMWindow> window = do_GetInterface(mDocShell);
204 window.swap(*aContent);
205 return NS_OK;
208 NS_IMETHODIMP
209 nsInProcessTabChildGlobal::GetDocShell(nsIDocShell** aDocShell)
211 NS_IF_ADDREF(*aDocShell = mDocShell);
212 return NS_OK;
215 NS_IMETHODIMP
216 nsInProcessTabChildGlobal::Btoa(const nsAString& aBinaryData,
217 nsAString& aAsciiBase64String)
219 return nsContentUtils::Btoa(aBinaryData, aAsciiBase64String);
222 NS_IMETHODIMP
223 nsInProcessTabChildGlobal::Atob(const nsAString& aAsciiString,
224 nsAString& aBinaryData)
226 return nsContentUtils::Atob(aAsciiString, aBinaryData);
230 NS_IMETHODIMP
231 nsInProcessTabChildGlobal::PrivateNoteIntentionalCrash()
233 return NS_ERROR_NOT_IMPLEMENTED;
236 void
237 nsInProcessTabChildGlobal::Disconnect()
239 // Let the frame scripts know the child is being closed. We do any other
240 // cleanup after the event has been fired. See DelayedDisconnect
241 nsContentUtils::AddScriptRunner(
242 NS_NewRunnableMethod(this, &nsInProcessTabChildGlobal::DelayedDisconnect)
246 void
247 nsInProcessTabChildGlobal::DelayedDisconnect()
249 // Don't let the event escape
250 mOwner = nullptr;
252 // Fire the "unload" event
253 nsDOMEventTargetHelper::DispatchTrustedEvent(NS_LITERAL_STRING("unload"));
255 // Continue with the Disconnect cleanup
256 nsCOMPtr<nsIDOMWindow> win = do_GetInterface(mDocShell);
257 nsCOMPtr<nsPIDOMWindow> pwin = do_QueryInterface(win);
258 if (pwin) {
259 pwin->SetChromeEventHandler(pwin->GetChromeEventHandler());
261 mDocShell = nullptr;
262 mChromeMessageManager = nullptr;
263 if (mMessageManager) {
264 static_cast<nsFrameMessageManager*>(mMessageManager.get())->Disconnect();
265 mMessageManager = nullptr;
267 if (mListenerManager) {
268 mListenerManager->Disconnect();
271 if (!mLoadingScript) {
272 ReleaseWrapper(static_cast<EventTarget*>(this));
273 mGlobal = nullptr;
274 } else {
275 mDelayedDisconnect = true;
279 NS_IMETHODIMP_(nsIContent *)
280 nsInProcessTabChildGlobal::GetOwnerContent()
282 return mOwner;
285 nsresult
286 nsInProcessTabChildGlobal::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
288 aVisitor.mCanHandle = true;
290 if (mIsBrowserOrAppFrame &&
291 (!mOwner || !nsContentUtils::IsInChromeDocshell(mOwner->OwnerDoc()))) {
292 if (mOwner) {
293 nsPIDOMWindow* innerWindow = mOwner->OwnerDoc()->GetInnerWindow();
294 if (innerWindow) {
295 aVisitor.mParentTarget = innerWindow->GetParentTarget();
298 } else {
299 aVisitor.mParentTarget = mOwner;
302 #ifdef DEBUG
303 if (mOwner) {
304 nsCOMPtr<nsIFrameLoaderOwner> owner = do_QueryInterface(mOwner);
305 nsRefPtr<nsFrameLoader> fl = owner->GetFrameLoader();
306 if (fl) {
307 NS_ASSERTION(this == fl->GetTabChildGlobalAsEventTarget(),
308 "Wrong event target!");
309 NS_ASSERTION(fl->mMessageManager == mChromeMessageManager,
310 "Wrong message manager!");
313 #endif
315 return NS_OK;
318 nsresult
319 nsInProcessTabChildGlobal::InitTabChildGlobal()
321 nsAutoCString id;
322 id.AssignLiteral("inProcessTabChildGlobal");
323 nsIURI* uri = mOwner->OwnerDoc()->GetDocumentURI();
324 if (uri) {
325 nsAutoCString u;
326 uri->GetSpec(u);
327 id.AppendLiteral("?ownedBy=");
328 id.Append(u);
330 nsISupports* scopeSupports = NS_ISUPPORTS_CAST(EventTarget*, this);
331 NS_ENSURE_STATE(InitTabChildGlobalInternal(scopeSupports, id));
332 return NS_OK;
335 class nsAsyncScriptLoad : public nsRunnable
337 public:
338 nsAsyncScriptLoad(nsInProcessTabChildGlobal* aTabChild, const nsAString& aURL)
339 : mTabChild(aTabChild), mURL(aURL) {}
341 NS_IMETHOD Run()
343 mTabChild->LoadFrameScript(mURL);
344 return NS_OK;
346 nsRefPtr<nsInProcessTabChildGlobal> mTabChild;
347 nsString mURL;
350 void
351 nsInProcessTabChildGlobal::LoadFrameScript(const nsAString& aURL)
353 if (!nsContentUtils::IsSafeToRunScript()) {
354 nsContentUtils::AddScriptRunner(new nsAsyncScriptLoad(this, aURL));
355 return;
357 if (!mInitialized) {
358 mInitialized = true;
359 Init();
361 bool tmp = mLoadingScript;
362 mLoadingScript = true;
363 LoadFrameScriptInternal(aURL);
364 mLoadingScript = tmp;
365 if (!mLoadingScript && mDelayedDisconnect) {
366 mDelayedDisconnect = false;
367 Disconnect();