Merge mozilla-central and tracemonkey. (a=blockers)
[mozilla-central.git] / dom / ipc / ContentChild.cpp
blob7e3a9b6cc4c8f01d292d2d13055c32e3ccfca416
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* vim: set sw=4 ts=8 et tw=80 : */
3 /* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
16 * The Original Code is Mozilla Content App.
18 * The Initial Developer of the Original Code is
19 * The Mozilla Foundation.
20 * Portions created by the Initial Developer are Copyright (C) 2009
21 * the Initial Developer. All Rights Reserved.
23 * Contributor(s):
24 * Frederic Plourde <frederic.plourde@collabora.co.uk>
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
40 #ifdef MOZ_WIDGET_GTK2
41 #include <gtk/gtk.h>
42 #endif
44 #ifdef MOZ_WIDGET_QT
45 #include "nsQAppInstance.h"
46 #endif
48 #include "ContentChild.h"
49 #include "CrashReporterChild.h"
50 #include "TabChild.h"
51 #include "AudioChild.h"
53 #include "mozilla/ipc/TestShellChild.h"
54 #include "mozilla/net/NeckoChild.h"
55 #include "mozilla/ipc/XPCShellEnvironment.h"
56 #include "mozilla/jsipc/PContextWrapperChild.h"
57 #include "mozilla/dom/ExternalHelperAppChild.h"
58 #include "mozilla/dom/StorageChild.h"
59 #include "mozilla/dom/PCrashReporterChild.h"
61 #include "nsAudioStream.h"
63 #include "nsIObserverService.h"
64 #include "nsTObserverArray.h"
65 #include "nsIObserver.h"
66 #include "nsIPrefService.h"
67 #include "nsServiceManagerUtils.h"
68 #include "nsXULAppAPI.h"
69 #include "nsWeakReference.h"
70 #include "nsIScriptError.h"
71 #include "nsIConsoleService.h"
73 #include "History.h"
74 #include "nsDocShellCID.h"
75 #include "nsNetUtil.h"
77 #include "base/message_loop.h"
78 #include "base/task.h"
80 #include "nsChromeRegistryContent.h"
81 #include "mozilla/chrome/RegistryMessageUtils.h"
82 #include "nsFrameMessageManager.h"
84 #include "nsIGeolocationProvider.h"
86 #ifdef MOZ_PERMISSIONS
87 #include "nsPermission.h"
88 #include "nsPermissionManager.h"
89 #endif
91 #include "nsAccelerometer.h"
93 #if defined(ANDROID)
94 #include "APKOpen.h"
95 #endif
97 using namespace mozilla::ipc;
98 using namespace mozilla::net;
99 using namespace mozilla::places;
100 using namespace mozilla::docshell;
102 namespace mozilla {
103 namespace dom {
104 class AlertObserver
106 public:
108 AlertObserver(nsIObserver *aObserver, const nsString& aData)
109 : mObserver(aObserver)
110 , mData(aData)
114 ~AlertObserver() {}
116 bool ShouldRemoveFrom(nsIObserver* aObserver,
117 const nsString& aData) const
119 return (mObserver == aObserver &&
120 mData == aData);
123 bool Observes(const nsString& aData) const
125 return mData.Equals(aData);
128 bool Notify(const nsCString& aType) const
130 mObserver->Observe(nsnull, aType.get(), mData.get());
131 return true;
134 private:
135 nsCOMPtr<nsIObserver> mObserver;
136 nsString mData;
139 class ConsoleListener : public nsIConsoleListener
141 public:
142 ConsoleListener(ContentChild* aChild)
143 : mChild(aChild) {}
145 NS_DECL_ISUPPORTS
146 NS_DECL_NSICONSOLELISTENER
148 private:
149 ContentChild* mChild;
150 friend class ContentChild;
153 NS_IMPL_ISUPPORTS1(ConsoleListener, nsIConsoleListener)
155 NS_IMETHODIMP
156 ConsoleListener::Observe(nsIConsoleMessage* aMessage)
158 if (!mChild)
159 return NS_OK;
161 nsCOMPtr<nsIScriptError> scriptError = do_QueryInterface(aMessage);
162 if (scriptError) {
163 nsString msg, sourceName, sourceLine;
164 nsXPIDLCString category;
165 PRUint32 lineNum, colNum, flags;
167 nsresult rv = scriptError->GetErrorMessage(msg);
168 NS_ENSURE_SUCCESS(rv, rv);
169 rv = scriptError->GetSourceName(sourceName);
170 NS_ENSURE_SUCCESS(rv, rv);
171 rv = scriptError->GetSourceLine(sourceLine);
172 NS_ENSURE_SUCCESS(rv, rv);
173 rv = scriptError->GetCategory(getter_Copies(category));
174 NS_ENSURE_SUCCESS(rv, rv);
175 rv = scriptError->GetLineNumber(&lineNum);
176 NS_ENSURE_SUCCESS(rv, rv);
177 rv = scriptError->GetColumnNumber(&colNum);
178 NS_ENSURE_SUCCESS(rv, rv);
179 rv = scriptError->GetFlags(&flags);
180 NS_ENSURE_SUCCESS(rv, rv);
181 mChild->SendScriptError(msg, sourceName, sourceLine,
182 lineNum, colNum, flags, category);
183 return NS_OK;
186 nsXPIDLString msg;
187 nsresult rv = aMessage->GetMessageMoz(getter_Copies(msg));
188 NS_ENSURE_SUCCESS(rv, rv);
189 mChild->SendConsoleMessage(msg);
190 return NS_OK;
193 ContentChild* ContentChild::sSingleton;
195 ContentChild::ContentChild()
196 #ifdef ANDROID
197 : mScreenSize(0, 0)
198 #endif
202 ContentChild::~ContentChild()
206 bool
207 ContentChild::Init(MessageLoop* aIOLoop,
208 base::ProcessHandle aParentHandle,
209 IPC::Channel* aChannel)
211 #ifdef MOZ_WIDGET_GTK2
212 // sigh
213 gtk_init(NULL, NULL);
214 #endif
216 #ifdef MOZ_WIDGET_QT
217 // sigh, seriously
218 nsQAppInstance::AddRef();
219 #endif
221 #ifdef MOZ_X11
222 // Do this after initializing GDK, or GDK will install its own handler.
223 XRE_InstallX11ErrorHandler();
224 #endif
226 NS_ASSERTION(!sSingleton, "only one ContentChild per child");
228 Open(aChannel, aParentHandle, aIOLoop);
229 sSingleton = this;
231 #if defined(ANDROID)
232 PCrashReporterChild* crashreporter = SendPCrashReporterConstructor();
233 InfallibleTArray<Mapping> mappings;
234 const struct mapping_info *info = getLibraryMapping();
235 while (info->name) {
236 mappings.AppendElement(Mapping(nsDependentCString(info->name),
237 nsDependentCString(info->file_id),
238 info->base,
239 info->len,
240 info->offset));
241 info++;
243 crashreporter->SendAddLibraryMappings(mappings);
244 #endif
246 return true;
249 void
250 ContentChild::InitXPCOM()
252 nsCOMPtr<nsIConsoleService> svc(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
253 if (!svc) {
254 NS_WARNING("Couldn't acquire console service");
255 return;
258 mConsoleListener = new ConsoleListener(this);
259 if (NS_FAILED(svc->RegisterListener(mConsoleListener)))
260 NS_WARNING("Couldn't register console listener for child process");
263 PBrowserChild*
264 ContentChild::AllocPBrowser(const PRUint32& aChromeFlags)
266 nsRefPtr<TabChild> iframe = new TabChild(aChromeFlags);
267 return NS_SUCCEEDED(iframe->Init()) ? iframe.forget().get() : NULL;
270 bool
271 ContentChild::DeallocPBrowser(PBrowserChild* iframe)
273 TabChild* child = static_cast<TabChild*>(iframe);
274 NS_RELEASE(child);
275 return true;
278 PCrashReporterChild*
279 ContentChild::AllocPCrashReporter()
281 return new CrashReporterChild();
284 bool
285 ContentChild::DeallocPCrashReporter(PCrashReporterChild* crashreporter)
287 delete crashreporter;
288 return true;
291 PTestShellChild*
292 ContentChild::AllocPTestShell()
294 return new TestShellChild();
297 bool
298 ContentChild::DeallocPTestShell(PTestShellChild* shell)
300 delete shell;
301 return true;
304 bool
305 ContentChild::RecvPTestShellConstructor(PTestShellChild* actor)
307 actor->SendPContextWrapperConstructor()->SendPObjectWrapperConstructor(true);
308 return true;
311 PAudioChild*
312 ContentChild::AllocPAudio(const PRInt32& numChannels,
313 const PRInt32& rate,
314 const PRInt32& format)
316 AudioChild *child = new AudioChild();
317 NS_ADDREF(child);
318 return child;
321 bool
322 ContentChild::DeallocPAudio(PAudioChild* doomed)
324 AudioChild *child = static_cast<AudioChild*>(doomed);
325 NS_RELEASE(child);
326 return true;
329 PNeckoChild*
330 ContentChild::AllocPNecko()
332 return new NeckoChild();
335 bool
336 ContentChild::DeallocPNecko(PNeckoChild* necko)
338 delete necko;
339 return true;
342 PExternalHelperAppChild*
343 ContentChild::AllocPExternalHelperApp(const IPC::URI& uri,
344 const nsCString& aMimeContentType,
345 const nsCString& aContentDisposition,
346 const bool& aForceSave,
347 const PRInt64& aContentLength,
348 const IPC::URI& aReferrer)
350 ExternalHelperAppChild *child = new ExternalHelperAppChild();
351 child->AddRef();
352 return child;
355 bool
356 ContentChild::DeallocPExternalHelperApp(PExternalHelperAppChild* aService)
358 ExternalHelperAppChild *child = static_cast<ExternalHelperAppChild*>(aService);
359 child->Release();
360 return true;
363 PStorageChild*
364 ContentChild::AllocPStorage(const StorageConstructData& aData)
366 NS_NOTREACHED("We should never be manually allocating PStorageChild actors");
367 return nsnull;
370 bool
371 ContentChild::DeallocPStorage(PStorageChild* aActor)
373 StorageChild* child = static_cast<StorageChild*>(aActor);
374 child->ReleaseIPDLReference();
375 return true;
378 bool
379 ContentChild::RecvRegisterChrome(const InfallibleTArray<ChromePackage>& packages,
380 const InfallibleTArray<ResourceMapping>& resources,
381 const InfallibleTArray<OverrideMapping>& overrides,
382 const nsCString& locale)
384 nsCOMPtr<nsIChromeRegistry> registrySvc = nsChromeRegistry::GetService();
385 nsChromeRegistryContent* chromeRegistry =
386 static_cast<nsChromeRegistryContent*>(registrySvc.get());
387 chromeRegistry->RegisterRemoteChrome(packages, resources, overrides, locale);
388 return true;
391 bool
392 ContentChild::RecvSetOffline(const PRBool& offline)
394 nsCOMPtr<nsIIOService> io (do_GetIOService());
395 NS_ASSERTION(io, "IO Service can not be null");
397 io->SetOffline(offline);
399 return true;
402 void
403 ContentChild::ActorDestroy(ActorDestroyReason why)
405 if (AbnormalShutdown == why) {
406 NS_WARNING("shutting down early because of crash!");
407 QuickExit();
410 #ifndef DEBUG
411 // In release builds, there's no point in the content process
412 // going through the full XPCOM shutdown path, because it doesn't
413 // keep persistent state.
414 QuickExit();
415 #endif
417 mAlertObservers.Clear();
419 nsCOMPtr<nsIConsoleService> svc(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
420 if (svc) {
421 svc->UnregisterListener(mConsoleListener);
422 mConsoleListener->mChild = nsnull;
425 XRE_ShutdownChildProcess();
428 void
429 ContentChild::ProcessingError(Result what)
431 switch (what) {
432 case MsgDropped:
433 QuickExit();
435 case MsgNotKnown:
436 case MsgNotAllowed:
437 case MsgPayloadError:
438 case MsgProcessingError:
439 case MsgRouteError:
440 case MsgValueError:
441 NS_RUNTIMEABORT("aborting because of fatal error");
443 default:
444 NS_RUNTIMEABORT("not reached");
448 void
449 ContentChild::QuickExit()
451 NS_WARNING("content process _exit()ing");
452 _exit(0);
455 nsresult
456 ContentChild::AddRemoteAlertObserver(const nsString& aData,
457 nsIObserver* aObserver)
459 NS_ASSERTION(aObserver, "Adding a null observer?");
460 mAlertObservers.AppendElement(new AlertObserver(aObserver, aData));
461 return NS_OK;
464 bool
465 ContentChild::RecvPreferenceUpdate(const PrefTuple& aPref)
467 nsCOMPtr<nsIPrefServiceInternal> prefs = do_GetService("@mozilla.org/preferences-service;1");
468 if (!prefs)
469 return false;
471 prefs->SetPreference(&aPref);
473 return true;
476 bool
477 ContentChild::RecvClearUserPreference(const nsCString& aPrefName)
479 nsCOMPtr<nsIPrefServiceInternal> prefs = do_GetService("@mozilla.org/preferences-service;1");
480 if (!prefs)
481 return false;
483 prefs->ClearContentPref(aPrefName);
485 return true;
488 bool
489 ContentChild::RecvNotifyAlertsObserver(const nsCString& aType, const nsString& aData)
491 for (PRUint32 i = 0; i < mAlertObservers.Length();
492 /*we mutate the array during the loop; ++i iff no mutation*/) {
493 AlertObserver* observer = mAlertObservers[i];
494 if (observer->Observes(aData) && observer->Notify(aType)) {
495 // if aType == alertfinished, this alert is done. we can
496 // remove the observer.
497 if (aType.Equals(nsDependentCString("alertfinished"))) {
498 mAlertObservers.RemoveElementAt(i);
499 continue;
502 ++i;
504 return true;
507 bool
508 ContentChild::RecvNotifyVisited(const IPC::URI& aURI)
510 nsCOMPtr<nsIURI> newURI(aURI);
511 History::GetService()->NotifyVisited(newURI);
512 return true;
516 bool
517 ContentChild::RecvAsyncMessage(const nsString& aMsg, const nsString& aJSON)
519 nsRefPtr<nsFrameMessageManager> cpm = nsFrameMessageManager::sChildProcessManager;
520 if (cpm) {
521 cpm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(cpm.get()),
522 aMsg, PR_FALSE, aJSON, nsnull, nsnull);
524 return true;
527 bool
528 ContentChild::RecvGeolocationUpdate(const GeoPosition& somewhere)
530 nsCOMPtr<nsIGeolocationUpdate> gs = do_GetService("@mozilla.org/geolocation/service;1");
531 if (!gs) {
532 return true;
534 nsCOMPtr<nsIDOMGeoPosition> position = somewhere;
535 gs->Update(position);
536 return true;
539 bool
540 ContentChild::RecvAddPermission(const IPC::Permission& permission)
542 #if MOZ_PERMISSIONS
543 nsRefPtr<nsPermissionManager> permissionManager =
544 nsPermissionManager::GetSingleton();
545 NS_ABORT_IF_FALSE(permissionManager,
546 "We have no permissionManager in the Content process !");
548 permissionManager->AddInternal(nsCString(permission.host),
549 nsCString(permission.type),
550 permission.capability,
552 permission.expireType,
553 permission.expireTime,
554 nsPermissionManager::eNotify,
555 nsPermissionManager::eNoDBOperation);
556 #endif
558 return true;
560 bool
561 ContentChild::RecvAccelerationChanged(const double& x, const double& y,
562 const double& z)
564 nsCOMPtr<nsIAccelerometerUpdate> acu =
565 do_GetService(NS_ACCELEROMETER_CONTRACTID);
566 if (acu)
567 acu->AccelerationChanged(x, y, z);
568 return true;
571 bool
572 ContentChild::RecvScreenSizeChanged(const gfxIntSize& size)
574 #ifdef ANDROID
575 mScreenSize = size;
576 #else
577 NS_RUNTIMEABORT("Message currently only expected on android");
578 #endif
579 return true;
582 bool
583 ContentChild::RecvFlushMemory(const nsString& reason)
585 nsCOMPtr<nsIObserverService> os =
586 mozilla::services::GetObserverService();
587 if (os)
588 os->NotifyObservers(nsnull, "memory-pressure", reason.get());
589 return true;
592 } // namespace dom
593 } // namespace mozilla