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
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.
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
45 #include "nsQAppInstance.h"
48 #include "ContentChild.h"
49 #include "CrashReporterChild.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"
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"
91 #if defined(ANDROID) || defined(LINUX)
93 #include <sys/resource.h>
94 // TODO: For other platforms that support setpriority, figure out
95 // appropriate values of niceness
96 static const int kRelativeNiceness
= 10;
99 #include "nsAccelerometer.h"
105 using namespace mozilla::ipc
;
106 using namespace mozilla::net
;
107 using namespace mozilla::places
;
108 using namespace mozilla::docshell
;
116 AlertObserver(nsIObserver
*aObserver
, const nsString
& aData
)
117 : mObserver(aObserver
)
124 bool ShouldRemoveFrom(nsIObserver
* aObserver
,
125 const nsString
& aData
) const
127 return (mObserver
== aObserver
&&
131 bool Observes(const nsString
& aData
) const
133 return mData
.Equals(aData
);
136 bool Notify(const nsCString
& aType
) const
138 mObserver
->Observe(nsnull
, aType
.get(), mData
.get());
143 nsCOMPtr
<nsIObserver
> mObserver
;
147 class ConsoleListener
: public nsIConsoleListener
150 ConsoleListener(ContentChild
* aChild
)
154 NS_DECL_NSICONSOLELISTENER
157 ContentChild
* mChild
;
158 friend class ContentChild
;
161 NS_IMPL_ISUPPORTS1(ConsoleListener
, nsIConsoleListener
)
164 ConsoleListener::Observe(nsIConsoleMessage
* aMessage
)
169 nsCOMPtr
<nsIScriptError
> scriptError
= do_QueryInterface(aMessage
);
171 nsString msg
, sourceName
, sourceLine
;
172 nsXPIDLCString category
;
173 PRUint32 lineNum
, colNum
, flags
;
175 nsresult rv
= scriptError
->GetErrorMessage(msg
);
176 NS_ENSURE_SUCCESS(rv
, rv
);
177 rv
= scriptError
->GetSourceName(sourceName
);
178 NS_ENSURE_SUCCESS(rv
, rv
);
179 rv
= scriptError
->GetSourceLine(sourceLine
);
180 NS_ENSURE_SUCCESS(rv
, rv
);
181 rv
= scriptError
->GetCategory(getter_Copies(category
));
182 NS_ENSURE_SUCCESS(rv
, rv
);
183 rv
= scriptError
->GetLineNumber(&lineNum
);
184 NS_ENSURE_SUCCESS(rv
, rv
);
185 rv
= scriptError
->GetColumnNumber(&colNum
);
186 NS_ENSURE_SUCCESS(rv
, rv
);
187 rv
= scriptError
->GetFlags(&flags
);
188 NS_ENSURE_SUCCESS(rv
, rv
);
189 mChild
->SendScriptError(msg
, sourceName
, sourceLine
,
190 lineNum
, colNum
, flags
, category
);
195 nsresult rv
= aMessage
->GetMessageMoz(getter_Copies(msg
));
196 NS_ENSURE_SUCCESS(rv
, rv
);
197 mChild
->SendConsoleMessage(msg
);
201 ContentChild
* ContentChild::sSingleton
;
203 ContentChild::ContentChild()
210 ContentChild::~ContentChild()
215 ContentChild::Init(MessageLoop
* aIOLoop
,
216 base::ProcessHandle aParentHandle
,
217 IPC::Channel
* aChannel
)
219 #ifdef MOZ_WIDGET_GTK2
221 gtk_init(NULL
, NULL
);
226 nsQAppInstance::AddRef();
230 // Do this after initializing GDK, or GDK will install its own handler.
231 XRE_InstallX11ErrorHandler();
234 NS_ASSERTION(!sSingleton
, "only one ContentChild per child");
236 #if defined(ANDROID) || defined(LINUX)
237 // XXX We change the behavior of Linux child processes here. That
238 // means that, not just in Fennec, but also in Firefox, once it has
239 // child processes, those will be niced. IOW, Firefox with child processes
240 // will have different performance profiles on Linux than other
241 // platforms. This may alter Talos results and so forth.
242 char* relativeNicenessStr
= getenv("MOZ_CHILD_PROCESS_RELATIVE_NICENESS");
243 setpriority(PRIO_PROCESS
, 0, getpriority(PRIO_PROCESS
, 0) +
244 (relativeNicenessStr
? atoi(relativeNicenessStr
) :
248 Open(aChannel
, aParentHandle
, aIOLoop
);
252 PCrashReporterChild
* crashreporter
= SendPCrashReporterConstructor();
253 InfallibleTArray
<Mapping
> mappings
;
254 const struct mapping_info
*info
= getLibraryMapping();
256 mappings
.AppendElement(Mapping(nsDependentCString(info
->name
),
257 nsDependentCString(info
->file_id
),
263 crashreporter
->SendAddLibraryMappings(mappings
);
270 ContentChild::InitXPCOM()
272 nsCOMPtr
<nsIConsoleService
> svc(do_GetService(NS_CONSOLESERVICE_CONTRACTID
));
274 NS_WARNING("Couldn't acquire console service");
278 mConsoleListener
= new ConsoleListener(this);
279 if (NS_FAILED(svc
->RegisterListener(mConsoleListener
)))
280 NS_WARNING("Couldn't register console listener for child process");
284 ContentChild::AllocPBrowser(const PRUint32
& aChromeFlags
)
286 nsRefPtr
<TabChild
> iframe
= new TabChild(aChromeFlags
);
287 return NS_SUCCEEDED(iframe
->Init()) ? iframe
.forget().get() : NULL
;
291 ContentChild::DeallocPBrowser(PBrowserChild
* iframe
)
293 TabChild
* child
= static_cast<TabChild
*>(iframe
);
299 ContentChild::AllocPCrashReporter()
301 return new CrashReporterChild();
305 ContentChild::DeallocPCrashReporter(PCrashReporterChild
* crashreporter
)
307 delete crashreporter
;
312 ContentChild::AllocPTestShell()
314 return new TestShellChild();
318 ContentChild::DeallocPTestShell(PTestShellChild
* shell
)
325 ContentChild::RecvPTestShellConstructor(PTestShellChild
* actor
)
327 actor
->SendPContextWrapperConstructor()->SendPObjectWrapperConstructor(true);
332 ContentChild::AllocPAudio(const PRInt32
& numChannels
,
334 const PRInt32
& format
)
336 AudioChild
*child
= new AudioChild();
342 ContentChild::DeallocPAudio(PAudioChild
* doomed
)
344 AudioChild
*child
= static_cast<AudioChild
*>(doomed
);
350 ContentChild::AllocPNecko()
352 return new NeckoChild();
356 ContentChild::DeallocPNecko(PNeckoChild
* necko
)
362 PExternalHelperAppChild
*
363 ContentChild::AllocPExternalHelperApp(const IPC::URI
& uri
,
364 const nsCString
& aMimeContentType
,
365 const nsCString
& aContentDisposition
,
366 const bool& aForceSave
,
367 const PRInt64
& aContentLength
,
368 const IPC::URI
& aReferrer
)
370 ExternalHelperAppChild
*child
= new ExternalHelperAppChild();
376 ContentChild::DeallocPExternalHelperApp(PExternalHelperAppChild
* aService
)
378 ExternalHelperAppChild
*child
= static_cast<ExternalHelperAppChild
*>(aService
);
384 ContentChild::AllocPStorage(const StorageConstructData
& aData
)
386 NS_NOTREACHED("We should never be manually allocating PStorageChild actors");
391 ContentChild::DeallocPStorage(PStorageChild
* aActor
)
393 StorageChild
* child
= static_cast<StorageChild
*>(aActor
);
394 child
->ReleaseIPDLReference();
399 ContentChild::RecvRegisterChrome(const InfallibleTArray
<ChromePackage
>& packages
,
400 const InfallibleTArray
<ResourceMapping
>& resources
,
401 const InfallibleTArray
<OverrideMapping
>& overrides
)
403 nsCOMPtr
<nsIChromeRegistry
> registrySvc
= nsChromeRegistry::GetService();
404 nsChromeRegistryContent
* chromeRegistry
=
405 static_cast<nsChromeRegistryContent
*>(registrySvc
.get());
406 chromeRegistry
->RegisterRemoteChrome(packages
, resources
, overrides
);
411 ContentChild::RecvSetOffline(const PRBool
& offline
)
413 nsCOMPtr
<nsIIOService
> io (do_GetIOService());
414 NS_ASSERTION(io
, "IO Service can not be null");
416 io
->SetOffline(offline
);
422 ContentChild::ActorDestroy(ActorDestroyReason why
)
424 if (AbnormalShutdown
== why
) {
425 NS_WARNING("shutting down early because of crash!");
430 // In release builds, there's no point in the content process
431 // going through the full XPCOM shutdown path, because it doesn't
432 // keep persistent state.
436 mAlertObservers
.Clear();
438 nsCOMPtr
<nsIConsoleService
> svc(do_GetService(NS_CONSOLESERVICE_CONTRACTID
));
440 svc
->UnregisterListener(mConsoleListener
);
441 mConsoleListener
->mChild
= nsnull
;
444 XRE_ShutdownChildProcess();
448 ContentChild::ProcessingError(Result what
)
456 case MsgPayloadError
:
457 case MsgProcessingError
:
460 NS_RUNTIMEABORT("aborting because of fatal error");
463 NS_RUNTIMEABORT("not reached");
468 ContentChild::QuickExit()
470 NS_WARNING("content process _exit()ing");
475 ContentChild::AddRemoteAlertObserver(const nsString
& aData
,
476 nsIObserver
* aObserver
)
478 NS_ASSERTION(aObserver
, "Adding a null observer?");
479 mAlertObservers
.AppendElement(new AlertObserver(aObserver
, aData
));
484 ContentChild::RecvPreferenceUpdate(const PrefTuple
& aPref
)
486 nsCOMPtr
<nsIPrefServiceInternal
> prefs
= do_GetService("@mozilla.org/preferences-service;1");
490 prefs
->SetPreference(&aPref
);
496 ContentChild::RecvNotifyAlertsObserver(const nsCString
& aType
, const nsString
& aData
)
498 for (PRUint32 i
= 0; i
< mAlertObservers
.Length();
499 /*we mutate the array during the loop; ++i iff no mutation*/) {
500 AlertObserver
* observer
= mAlertObservers
[i
];
501 if (observer
->Observes(aData
) && observer
->Notify(aType
)) {
502 // if aType == alertfinished, this alert is done. we can
503 // remove the observer.
504 if (aType
.Equals(nsDependentCString("alertfinished"))) {
505 mAlertObservers
.RemoveElementAt(i
);
515 ContentChild::RecvNotifyVisited(const IPC::URI
& aURI
)
517 nsCOMPtr
<nsIURI
> newURI(aURI
);
518 History::GetService()->NotifyVisited(newURI
);
524 ContentChild::RecvAsyncMessage(const nsString
& aMsg
, const nsString
& aJSON
)
526 nsRefPtr
<nsFrameMessageManager
> cpm
= nsFrameMessageManager::sChildProcessManager
;
528 cpm
->ReceiveMessage(static_cast<nsIContentFrameMessageManager
*>(cpm
.get()),
529 aMsg
, PR_FALSE
, aJSON
, nsnull
, nsnull
);
535 ContentChild::RecvGeolocationUpdate(const GeoPosition
& somewhere
)
537 nsCOMPtr
<nsIGeolocationUpdate
> gs
= do_GetService("@mozilla.org/geolocation/service;1");
541 nsCOMPtr
<nsIDOMGeoPosition
> position
= somewhere
;
542 gs
->Update(position
);
547 ContentChild::RecvAddPermission(const IPC::Permission
& permission
)
550 nsRefPtr
<nsPermissionManager
> permissionManager
=
551 nsPermissionManager::GetSingleton();
552 NS_ABORT_IF_FALSE(permissionManager
,
553 "We have no permissionManager in the Content process !");
555 permissionManager
->AddInternal(nsCString(permission
.host
),
556 nsCString(permission
.type
),
557 permission
.capability
,
559 permission
.expireType
,
560 permission
.expireTime
,
561 nsPermissionManager::eNotify
,
562 nsPermissionManager::eNoDBOperation
);
568 ContentChild::RecvAccelerationChanged(const double& x
, const double& y
,
571 nsCOMPtr
<nsIAccelerometerUpdate
> acu
=
572 do_GetService(NS_ACCELEROMETER_CONTRACTID
);
574 acu
->AccelerationChanged(x
, y
, z
);
579 ContentChild::RecvScreenSizeChanged(const gfxIntSize
& size
)
584 NS_RUNTIMEABORT("Message currently only expected on android");
590 ContentChild::RecvFlushMemory(const nsString
& reason
)
592 nsCOMPtr
<nsIObserverService
> os
=
593 mozilla::services::GetObserverService();
595 os
->NotifyObservers(nsnull
, "memory-pressure", reason
.get());
600 } // namespace mozilla