Bumping manifests a=b2g-bump
[gecko.git] / dom / ipc / ContentChild.cpp
blob25d6b7aea0dda0fdff6065b4c9d922617a671d93
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 /* 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 #ifdef MOZ_WIDGET_GTK
8 #include <gtk/gtk.h>
9 #endif
11 #ifdef MOZ_WIDGET_QT
12 #include "nsQAppInstance.h"
13 #endif
15 #include "ContentChild.h"
16 #include "CrashReporterChild.h"
17 #include "FileDescriptorSetChild.h"
18 #include "TabChild.h"
20 #include "mozilla/Attributes.h"
21 #include "mozilla/Preferences.h"
22 #include "mozilla/dom/ContentBridgeChild.h"
23 #include "mozilla/dom/ContentBridgeParent.h"
24 #include "mozilla/dom/DOMStorageIPC.h"
25 #include "mozilla/dom/ExternalHelperAppChild.h"
26 #include "mozilla/dom/PCrashReporterChild.h"
27 #include "mozilla/dom/Promise.h"
28 #include "mozilla/dom/asmjscache/AsmJSCache.h"
29 #include "mozilla/dom/asmjscache/PAsmJSCacheEntryChild.h"
30 #include "mozilla/dom/nsIContentChild.h"
31 #include "mozilla/hal_sandbox/PHalChild.h"
32 #include "mozilla/ipc/BackgroundChild.h"
33 #include "mozilla/ipc/FileDescriptorUtils.h"
34 #include "mozilla/ipc/GeckoChildProcessHost.h"
35 #include "mozilla/ipc/TestShellChild.h"
36 #include "mozilla/layers/CompositorChild.h"
37 #include "mozilla/layers/ImageBridgeChild.h"
38 #include "mozilla/layers/PCompositorChild.h"
39 #include "mozilla/layers/SharedBufferManagerChild.h"
40 #include "mozilla/net/NeckoChild.h"
42 #if defined(MOZ_CONTENT_SANDBOX)
43 #if defined(XP_WIN)
44 #define TARGET_SANDBOX_EXPORTS
45 #include "mozilla/sandboxTarget.h"
46 #elif defined(XP_LINUX)
47 #include "mozilla/Sandbox.h"
48 #endif
49 #endif
51 #include "mozilla/unused.h"
53 #include "nsIConsoleListener.h"
54 #include "nsICycleCollectorListener.h"
55 #include "nsIIPCBackgroundChildCreateCallback.h"
56 #include "nsIInterfaceRequestorUtils.h"
57 #include "nsIMemoryReporter.h"
58 #include "nsIMemoryInfoDumper.h"
59 #include "nsIMutable.h"
60 #include "nsIObserverService.h"
61 #include "nsIScriptSecurityManager.h"
62 #include "nsScreenManagerProxy.h"
63 #include "nsMemoryInfoDumper.h"
64 #include "nsServiceManagerUtils.h"
65 #include "nsStyleSheetService.h"
66 #include "nsXULAppAPI.h"
67 #include "nsIScriptError.h"
68 #include "nsIConsoleService.h"
69 #include "nsJSEnvironment.h"
70 #include "SandboxHal.h"
71 #include "nsDebugImpl.h"
72 #include "nsHashPropertyBag.h"
73 #include "nsLayoutStylesheetCache.h"
74 #include "nsIJSRuntimeService.h"
75 #include "nsThreadManager.h"
76 #include "nsAnonymousTemporaryFile.h"
78 #include "IHistory.h"
79 #include "nsNetUtil.h"
81 #include "base/message_loop.h"
82 #include "base/process_util.h"
83 #include "base/task.h"
85 #include "nsChromeRegistryContent.h"
86 #include "nsFrameMessageManager.h"
88 #include "nsIGeolocationProvider.h"
89 #include "mozilla/dom/PMemoryReportRequestChild.h"
90 #include "mozilla/dom/PCycleCollectWithLogsChild.h"
92 #ifdef MOZ_PERMISSIONS
93 #include "nsIScriptSecurityManager.h"
94 #include "nsPermission.h"
95 #include "nsPermissionManager.h"
96 #endif
98 #include "PermissionMessageUtils.h"
100 #if defined(MOZ_WIDGET_ANDROID)
101 #include "APKOpen.h"
102 #endif
104 #if defined(MOZ_WIDGET_GONK)
105 #include "nsVolume.h"
106 #include "nsVolumeService.h"
107 #include "SpeakerManagerService.h"
108 #endif
110 #ifdef XP_WIN
111 #include <process.h>
112 #define getpid _getpid
113 #endif
115 #ifdef MOZ_X11
116 #include "mozilla/X11Util.h"
117 #endif
119 #ifdef ACCESSIBILITY
120 #include "nsIAccessibilityService.h"
121 #endif
123 #ifdef MOZ_NUWA_PROCESS
124 #include <setjmp.h>
125 #include "ipc/Nuwa.h"
126 #endif
128 #include "mozilla/dom/indexedDB/PIndexedDBChild.h"
129 #include "mozilla/dom/mobilemessage/SmsChild.h"
130 #include "mozilla/dom/devicestorage/DeviceStorageRequestChild.h"
131 #include "mozilla/dom/PFileSystemRequestChild.h"
132 #include "mozilla/dom/FileSystemTaskBase.h"
133 #include "mozilla/dom/bluetooth/PBluetoothChild.h"
134 #include "mozilla/dom/PFMRadioChild.h"
135 #include "mozilla/ipc/InputStreamUtils.h"
137 #ifdef MOZ_WEBSPEECH
138 #include "mozilla/dom/PSpeechSynthesisChild.h"
139 #endif
141 #include "nsDOMFile.h"
142 #include "nsIRemoteBlob.h"
143 #include "ProcessUtils.h"
144 #include "StructuredCloneUtils.h"
145 #include "URIUtils.h"
146 #include "nsContentUtils.h"
147 #include "nsIPrincipal.h"
148 #include "nsDeviceStorage.h"
149 #include "AudioChannelService.h"
150 #include "JavaScriptChild.h"
151 #include "mozilla/dom/DataStoreService.h"
152 #include "mozilla/dom/telephony/PTelephonyChild.h"
153 #include "mozilla/dom/time/DateCacheCleaner.h"
154 #include "mozilla/net/NeckoMessageUtils.h"
155 #include "mozilla/RemoteSpellCheckEngineChild.h"
157 using namespace base;
158 using namespace mozilla;
159 using namespace mozilla::docshell;
160 using namespace mozilla::dom::bluetooth;
161 using namespace mozilla::dom::devicestorage;
162 using namespace mozilla::dom::ipc;
163 using namespace mozilla::dom::mobilemessage;
164 using namespace mozilla::dom::indexedDB;
165 using namespace mozilla::dom::telephony;
166 using namespace mozilla::hal_sandbox;
167 using namespace mozilla::ipc;
168 using namespace mozilla::layers;
169 using namespace mozilla::net;
170 using namespace mozilla::jsipc;
171 #if defined(MOZ_WIDGET_GONK)
172 using namespace mozilla::system;
173 #endif
174 using namespace mozilla::widget;
176 #ifdef MOZ_NUWA_PROCESS
177 static bool sNuwaForking = false;
179 // The size of the reserved stack (in unsigned ints). It's used to reserve space
180 // to push sigsetjmp() in NuwaCheckpointCurrentThread() to higher in the stack
181 // so that after it returns and do other work we don't garble the stack we want
182 // to preserve in NuwaCheckpointCurrentThread().
183 #define RESERVED_INT_STACK 128
185 // A sentinel value for checking whether RESERVED_INT_STACK is large enough.
186 #define STACK_SENTINEL_VALUE 0xdeadbeef
187 #endif
189 namespace mozilla {
190 namespace dom {
192 class MemoryReportRequestChild : public PMemoryReportRequestChild,
193 public nsIRunnable
195 public:
196 NS_DECL_ISUPPORTS
198 MemoryReportRequestChild(uint32_t aGeneration, bool aAnonymize,
199 const FileDescriptor& aDMDFile);
200 NS_IMETHOD Run();
201 private:
202 virtual ~MemoryReportRequestChild();
204 uint32_t mGeneration;
205 bool mAnonymize;
206 FileDescriptor mDMDFile;
209 NS_IMPL_ISUPPORTS(MemoryReportRequestChild, nsIRunnable)
211 MemoryReportRequestChild::MemoryReportRequestChild(
212 uint32_t aGeneration, bool aAnonymize, const FileDescriptor& aDMDFile)
213 : mGeneration(aGeneration), mAnonymize(aAnonymize),
214 mDMDFile(aDMDFile)
216 MOZ_COUNT_CTOR(MemoryReportRequestChild);
219 MemoryReportRequestChild::~MemoryReportRequestChild()
221 MOZ_COUNT_DTOR(MemoryReportRequestChild);
224 // IPC sender for remote GC/CC logging.
225 class CycleCollectWithLogsChild MOZ_FINAL
226 : public PCycleCollectWithLogsChild
227 , public nsICycleCollectorLogSink
229 public:
230 NS_DECL_ISUPPORTS
232 CycleCollectWithLogsChild(const FileDescriptor& aGCLog,
233 const FileDescriptor& aCCLog)
235 mGCLog = FileDescriptorToFILE(aGCLog, "w");
236 mCCLog = FileDescriptorToFILE(aCCLog, "w");
239 NS_IMETHOD Open(FILE** aGCLog, FILE** aCCLog) MOZ_OVERRIDE
241 if (NS_WARN_IF(!mGCLog) || NS_WARN_IF(!mCCLog)) {
242 return NS_ERROR_FAILURE;
244 *aGCLog = mGCLog;
245 *aCCLog = mCCLog;
246 return NS_OK;
249 NS_IMETHOD CloseGCLog() MOZ_OVERRIDE
251 MOZ_ASSERT(mGCLog);
252 fclose(mGCLog);
253 mGCLog = nullptr;
254 SendCloseGCLog();
255 return NS_OK;
258 NS_IMETHOD CloseCCLog() MOZ_OVERRIDE
260 MOZ_ASSERT(mCCLog);
261 fclose(mCCLog);
262 mCCLog = nullptr;
263 SendCloseCCLog();
264 return NS_OK;
267 NS_IMETHOD GetFilenameIdentifier(nsAString& aIdentifier) MOZ_OVERRIDE
269 return UnimplementedProperty();
272 NS_IMETHOD SetFilenameIdentifier(const nsAString& aIdentifier) MOZ_OVERRIDE
274 return UnimplementedProperty();
277 NS_IMETHOD GetProcessIdentifier(int32_t *aIdentifier) MOZ_OVERRIDE
279 return UnimplementedProperty();
282 NS_IMETHOD SetProcessIdentifier(int32_t aIdentifier) MOZ_OVERRIDE
284 return UnimplementedProperty();
287 NS_IMETHOD GetGcLog(nsIFile** aPath) MOZ_OVERRIDE
289 return UnimplementedProperty();
292 NS_IMETHOD GetCcLog(nsIFile** aPath) MOZ_OVERRIDE
294 return UnimplementedProperty();
297 private:
298 ~CycleCollectWithLogsChild()
300 if (mGCLog) {
301 fclose(mGCLog);
302 mGCLog = nullptr;
304 if (mCCLog) {
305 fclose(mCCLog);
306 mCCLog = nullptr;
308 // The XPCOM refcount drives the IPC lifecycle; see also
309 // DeallocPCycleCollectWithLogsChild.
310 unused << Send__delete__(this);
313 nsresult UnimplementedProperty()
315 MOZ_ASSERT(false, "This object is a remote GC/CC logger;"
316 " this property isn't meaningful.");
317 return NS_ERROR_UNEXPECTED;
320 FILE* mGCLog;
321 FILE* mCCLog;
324 NS_IMPL_ISUPPORTS(CycleCollectWithLogsChild, nsICycleCollectorLogSink);
326 class AlertObserver
328 public:
330 AlertObserver(nsIObserver *aObserver, const nsString& aData)
331 : mObserver(aObserver)
332 , mData(aData)
336 ~AlertObserver() {}
338 bool ShouldRemoveFrom(nsIObserver* aObserver,
339 const nsString& aData) const
341 return (mObserver == aObserver &&
342 mData == aData);
345 bool Observes(const nsString& aData) const
347 return mData.Equals(aData);
350 bool Notify(const nsCString& aType) const
352 mObserver->Observe(nullptr, aType.get(), mData.get());
353 return true;
356 private:
357 nsCOMPtr<nsIObserver> mObserver;
358 nsString mData;
361 class ConsoleListener MOZ_FINAL : public nsIConsoleListener
363 public:
364 explicit ConsoleListener(ContentChild* aChild)
365 : mChild(aChild) {}
367 NS_DECL_ISUPPORTS
368 NS_DECL_NSICONSOLELISTENER
370 private:
371 ~ConsoleListener() {}
373 ContentChild* mChild;
374 friend class ContentChild;
377 NS_IMPL_ISUPPORTS(ConsoleListener, nsIConsoleListener)
379 NS_IMETHODIMP
380 ConsoleListener::Observe(nsIConsoleMessage* aMessage)
382 if (!mChild)
383 return NS_OK;
385 nsCOMPtr<nsIScriptError> scriptError = do_QueryInterface(aMessage);
386 if (scriptError) {
387 nsString msg, sourceName, sourceLine;
388 nsXPIDLCString category;
389 uint32_t lineNum, colNum, flags;
391 nsresult rv = scriptError->GetErrorMessage(msg);
392 NS_ENSURE_SUCCESS(rv, rv);
393 rv = scriptError->GetSourceName(sourceName);
394 NS_ENSURE_SUCCESS(rv, rv);
395 rv = scriptError->GetSourceLine(sourceLine);
396 NS_ENSURE_SUCCESS(rv, rv);
398 // Before we send the error to the parent process (which
399 // involves copying the memory), truncate any long lines. CSS
400 // errors in particular share the memory for long lines with
401 // repeated errors, but the IPC communication we're about to do
402 // will break that sharing, so we better truncate now.
403 if (sourceLine.Length() > 1000) {
404 sourceLine.Truncate(1000);
407 rv = scriptError->GetCategory(getter_Copies(category));
408 NS_ENSURE_SUCCESS(rv, rv);
409 rv = scriptError->GetLineNumber(&lineNum);
410 NS_ENSURE_SUCCESS(rv, rv);
411 rv = scriptError->GetColumnNumber(&colNum);
412 NS_ENSURE_SUCCESS(rv, rv);
413 rv = scriptError->GetFlags(&flags);
414 NS_ENSURE_SUCCESS(rv, rv);
415 mChild->SendScriptError(msg, sourceName, sourceLine,
416 lineNum, colNum, flags, category);
417 return NS_OK;
420 nsXPIDLString msg;
421 nsresult rv = aMessage->GetMessageMoz(getter_Copies(msg));
422 NS_ENSURE_SUCCESS(rv, rv);
423 mChild->SendConsoleMessage(msg);
424 return NS_OK;
427 class SystemMessageHandledObserver MOZ_FINAL : public nsIObserver
429 ~SystemMessageHandledObserver() {}
431 public:
432 NS_DECL_ISUPPORTS
433 NS_DECL_NSIOBSERVER
435 void Init();
438 void SystemMessageHandledObserver::Init()
440 nsCOMPtr<nsIObserverService> os =
441 mozilla::services::GetObserverService();
443 if (os) {
444 os->AddObserver(this, "handle-system-messages-done",
445 /* ownsWeak */ false);
449 NS_IMETHODIMP
450 SystemMessageHandledObserver::Observe(nsISupports* aSubject,
451 const char* aTopic,
452 const char16_t* aData)
454 if (ContentChild::GetSingleton()) {
455 ContentChild::GetSingleton()->SendSystemMessageHandled();
457 return NS_OK;
460 NS_IMPL_ISUPPORTS(SystemMessageHandledObserver, nsIObserver)
462 class BackgroundChildPrimer MOZ_FINAL :
463 public nsIIPCBackgroundChildCreateCallback
465 public:
466 BackgroundChildPrimer()
469 NS_DECL_ISUPPORTS
471 private:
472 ~BackgroundChildPrimer()
475 virtual void
476 ActorCreated(PBackgroundChild* aActor) MOZ_OVERRIDE
478 MOZ_ASSERT(aActor, "Failed to create a PBackgroundChild actor!");
481 virtual void
482 ActorFailed() MOZ_OVERRIDE
484 MOZ_CRASH("Failed to create a PBackgroundChild actor!");
488 NS_IMPL_ISUPPORTS(BackgroundChildPrimer, nsIIPCBackgroundChildCreateCallback)
490 ContentChild* ContentChild::sSingleton;
492 // Performs initialization that is not fork-safe, i.e. that must be done after
493 // forking from the Nuwa process.
494 static void
495 InitOnContentProcessCreated()
497 #ifdef MOZ_NUWA_PROCESS
498 // Wait until we are forked from Nuwa
499 if (IsNuwaProcess()) {
500 return;
502 #endif
504 // This will register cross-process observer.
505 mozilla::dom::time::InitializeDateCacheCleaner();
508 ContentChild::ContentChild()
509 : mID(uint64_t(-1))
510 #ifdef ANDROID
511 ,mScreenSize(0, 0)
512 #endif
513 , mCanOverrideProcessName(true)
515 // This process is a content process, so it's clearly running in
516 // multiprocess mode!
517 nsDebugImpl::SetMultiprocessMode("Child");
520 ContentChild::~ContentChild()
524 NS_INTERFACE_MAP_BEGIN(ContentChild)
525 NS_INTERFACE_MAP_ENTRY(nsIContentChild)
526 NS_INTERFACE_MAP_ENTRY(nsISupports)
527 NS_INTERFACE_MAP_END
529 bool
530 ContentChild::Init(MessageLoop* aIOLoop,
531 base::ProcessHandle aParentHandle,
532 IPC::Channel* aChannel)
534 #ifdef MOZ_WIDGET_GTK
535 // sigh
536 gtk_init(nullptr, nullptr);
537 #endif
539 #ifdef MOZ_WIDGET_QT
540 // sigh, seriously
541 nsQAppInstance::AddRef();
542 #endif
544 #ifdef MOZ_X11
545 // Do this after initializing GDK, or GDK will install its own handler.
546 XRE_InstallX11ErrorHandler();
547 #endif
549 #ifdef MOZ_NUWA_PROCESS
550 SetTransport(aChannel);
551 #endif
553 NS_ASSERTION(!sSingleton, "only one ContentChild per child");
555 // Once we start sending IPC messages, we need the thread manager to be
556 // initialized so we can deal with the responses. Do that here before we
557 // try to construct the crash reporter.
558 nsresult rv = nsThreadManager::get()->Init();
559 if (NS_WARN_IF(NS_FAILED(rv))) {
560 return false;
563 Open(aChannel, aParentHandle, aIOLoop);
564 sSingleton = this;
566 // Make sure there's an nsAutoScriptBlocker on the stack when dispatching
567 // urgent messages.
568 GetIPCChannel()->BlockScripts();
570 #ifdef MOZ_X11
571 // Send the parent our X socket to act as a proxy reference for our X
572 // resources.
573 int xSocketFd = ConnectionNumber(DefaultXDisplay());
574 SendBackUpXResources(FileDescriptor(xSocketFd));
575 #endif
577 #ifdef MOZ_CRASHREPORTER
578 SendPCrashReporterConstructor(CrashReporter::CurrentThreadId(),
579 XRE_GetProcessType());
580 #endif
582 GetCPOWManager();
584 SendGetProcessAttributes(&mID, &mIsForApp, &mIsForBrowser);
585 InitProcessAttributes();
587 return true;
590 void
591 ContentChild::InitProcessAttributes()
593 #ifdef MOZ_WIDGET_GONK
594 #ifdef MOZ_NUWA_PROCESS
595 if (IsNuwaProcess()) {
596 SetProcessName(NS_LITERAL_STRING("(Nuwa)"), false);
597 return;
599 #endif
600 if (mIsForApp && !mIsForBrowser) {
601 SetProcessName(NS_LITERAL_STRING("(Preallocated app)"), false);
602 } else {
603 SetProcessName(NS_LITERAL_STRING("Browser"), false);
605 #else
606 SetProcessName(NS_LITERAL_STRING("Web Content"), true);
607 #endif
610 void
611 ContentChild::SetProcessName(const nsAString& aName, bool aDontOverride)
613 if (!mCanOverrideProcessName) {
614 return;
617 char* name;
618 if ((name = PR_GetEnv("MOZ_DEBUG_APP_PROCESS")) &&
619 aName.EqualsASCII(name)) {
620 #ifdef OS_POSIX
621 printf_stderr("\n\nCHILDCHILDCHILDCHILD\n [%s] debug me @%d\n\n", name, getpid());
622 sleep(30);
623 #elif defined(OS_WIN)
624 // Windows has a decent JIT debugging story, so NS_DebugBreak does the
625 // right thing.
626 NS_DebugBreak(NS_DEBUG_BREAK,
627 "Invoking NS_DebugBreak() to debug child process",
628 nullptr, __FILE__, __LINE__);
629 #endif
632 mProcessName = aName;
633 mozilla::ipc::SetThisProcessName(NS_LossyConvertUTF16toASCII(aName).get());
635 if (aDontOverride) {
636 mCanOverrideProcessName = false;
640 void
641 ContentChild::GetProcessName(nsAString& aName)
643 aName.Assign(mProcessName);
646 void
647 ContentChild::GetProcessName(nsACString& aName)
649 aName.Assign(NS_ConvertUTF16toUTF8(mProcessName));
652 /* static */ void
653 ContentChild::AppendProcessId(nsACString& aName)
655 if (!aName.IsEmpty()) {
656 aName.Append(' ');
658 unsigned pid = getpid();
659 aName.Append(nsPrintfCString("(pid %u)", pid));
662 void
663 ContentChild::InitXPCOM()
665 // Do this as early as possible to get the parent process to initialize the
666 // background thread since we'll likely need database information very soon.
667 BackgroundChild::Startup();
669 nsCOMPtr<nsIIPCBackgroundChildCreateCallback> callback =
670 new BackgroundChildPrimer();
671 if (!BackgroundChild::GetOrCreateForCurrentThread(callback)) {
672 MOZ_CRASH("Failed to create PBackgroundChild!");
675 nsCOMPtr<nsIConsoleService> svc(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
676 if (!svc) {
677 NS_WARNING("Couldn't acquire console service");
678 return;
681 mConsoleListener = new ConsoleListener(this);
682 if (NS_FAILED(svc->RegisterListener(mConsoleListener)))
683 NS_WARNING("Couldn't register console listener for child process");
685 bool isOffline;
686 SendGetXPCOMProcessAttributes(&isOffline);
687 RecvSetOffline(isOffline);
689 DebugOnly<FileUpdateDispatcher*> observer = FileUpdateDispatcher::GetSingleton();
690 NS_ASSERTION(observer, "FileUpdateDispatcher is null");
692 // This object is held alive by the observer service.
693 nsRefPtr<SystemMessageHandledObserver> sysMsgObserver =
694 new SystemMessageHandledObserver();
695 sysMsgObserver->Init();
697 InitOnContentProcessCreated();
700 PMemoryReportRequestChild*
701 ContentChild::AllocPMemoryReportRequestChild(const uint32_t& aGeneration,
702 const bool &aAnonymize,
703 const bool &aMinimizeMemoryUsage,
704 const FileDescriptor& aDMDFile)
706 MemoryReportRequestChild *actor =
707 new MemoryReportRequestChild(aGeneration, aAnonymize, aDMDFile);
708 actor->AddRef();
709 return actor;
712 // This is just a wrapper for InfallibleTArray<MemoryReport> that implements
713 // nsISupports, so it can be passed to nsIMemoryReporter::CollectReports.
714 class MemoryReportsWrapper MOZ_FINAL : public nsISupports {
715 ~MemoryReportsWrapper() {}
716 public:
717 NS_DECL_ISUPPORTS
718 explicit MemoryReportsWrapper(InfallibleTArray<MemoryReport>* r) : mReports(r) { }
719 InfallibleTArray<MemoryReport> *mReports;
721 NS_IMPL_ISUPPORTS0(MemoryReportsWrapper)
723 class MemoryReportCallback MOZ_FINAL : public nsIMemoryReporterCallback
725 public:
726 NS_DECL_ISUPPORTS
728 explicit MemoryReportCallback(const nsACString& aProcess)
729 : mProcess(aProcess)
733 NS_IMETHOD Callback(const nsACString &aProcess, const nsACString &aPath,
734 int32_t aKind, int32_t aUnits, int64_t aAmount,
735 const nsACString &aDescription,
736 nsISupports *aiWrappedReports)
738 MemoryReportsWrapper *wrappedReports =
739 static_cast<MemoryReportsWrapper *>(aiWrappedReports);
741 MemoryReport memreport(mProcess, nsCString(aPath), aKind, aUnits,
742 aAmount, nsCString(aDescription));
743 wrappedReports->mReports->AppendElement(memreport);
744 return NS_OK;
746 private:
747 ~MemoryReportCallback() {}
749 const nsCString mProcess;
751 NS_IMPL_ISUPPORTS(
752 MemoryReportCallback
753 , nsIMemoryReporterCallback
756 bool
757 ContentChild::RecvPMemoryReportRequestConstructor(
758 PMemoryReportRequestChild* aChild,
759 const uint32_t& aGeneration,
760 const bool& aAnonymize,
761 const bool& aMinimizeMemoryUsage,
762 const FileDescriptor& aDMDFile)
764 MemoryReportRequestChild *actor =
765 static_cast<MemoryReportRequestChild*>(aChild);
766 nsresult rv;
768 if (aMinimizeMemoryUsage) {
769 nsCOMPtr<nsIMemoryReporterManager> mgr = do_GetService("@mozilla.org/memory-reporter-manager;1");
770 rv = mgr->MinimizeMemoryUsage(actor);
771 // mgr will eventually call actor->Run()
772 } else {
773 rv = actor->Run();
776 return !NS_WARN_IF(NS_FAILED(rv));
779 NS_IMETHODIMP MemoryReportRequestChild::Run()
781 ContentChild *child = static_cast<ContentChild*>(Manager());
782 nsCOMPtr<nsIMemoryReporterManager> mgr = do_GetService("@mozilla.org/memory-reporter-manager;1");
784 InfallibleTArray<MemoryReport> reports;
786 nsCString process;
787 child->GetProcessName(process);
788 child->AppendProcessId(process);
790 // Run the reporters. The callback will turn each measurement into a
791 // MemoryReport.
792 nsRefPtr<MemoryReportsWrapper> wrappedReports =
793 new MemoryReportsWrapper(&reports);
794 nsRefPtr<MemoryReportCallback> cb = new MemoryReportCallback(process);
795 mgr->GetReportsForThisProcessExtended(cb, wrappedReports, mAnonymize,
796 FileDescriptorToFILE(mDMDFile, "wb"));
798 bool sent = Send__delete__(this, mGeneration, reports);
799 return sent ? NS_OK : NS_ERROR_FAILURE;
802 bool
803 ContentChild::RecvAudioChannelNotify()
805 nsRefPtr<AudioChannelService> service =
806 AudioChannelService::GetAudioChannelService();
807 if (service) {
808 service->Notify();
810 return true;
813 bool
814 ContentChild::RecvDataStoreNotify(const uint32_t& aAppId,
815 const nsString& aName,
816 const nsString& aManifestURL)
818 nsRefPtr<DataStoreService> service = DataStoreService::GetOrCreate();
819 if (NS_WARN_IF(!service)) {
820 return false;
823 nsresult rv = service->EnableDataStore(aAppId, aName, aManifestURL);
824 if (NS_WARN_IF(NS_FAILED(rv))) {
825 return false;
828 return true;
831 bool
832 ContentChild::DeallocPMemoryReportRequestChild(PMemoryReportRequestChild* actor)
834 static_cast<MemoryReportRequestChild*>(actor)->Release();
835 return true;
838 PCycleCollectWithLogsChild*
839 ContentChild::AllocPCycleCollectWithLogsChild(const bool& aDumpAllTraces,
840 const FileDescriptor& aGCLog,
841 const FileDescriptor& aCCLog)
843 CycleCollectWithLogsChild* actor = new CycleCollectWithLogsChild(aGCLog, aCCLog);
844 // Return actor with refcount 0, which is safe because it has a non-XPCOM type.
845 return actor;
848 bool
849 ContentChild::RecvPCycleCollectWithLogsConstructor(PCycleCollectWithLogsChild* aActor,
850 const bool& aDumpAllTraces,
851 const FileDescriptor& aGCLog,
852 const FileDescriptor& aCCLog)
854 // Take a reference here, where the XPCOM type is regained.
855 nsRefPtr<CycleCollectWithLogsChild> sink = static_cast<CycleCollectWithLogsChild*>(aActor);
856 nsCOMPtr<nsIMemoryInfoDumper> dumper = do_GetService("@mozilla.org/memory-info-dumper;1");
858 dumper->DumpGCAndCCLogsToSink(aDumpAllTraces, sink);
860 // The actor's destructor is called when the last reference goes away...
861 return true;
864 bool
865 ContentChild::DeallocPCycleCollectWithLogsChild(PCycleCollectWithLogsChild* /* aActor */)
867 // ...so when we get here, there's nothing for us to do.
869 // Also, we're already in ~CycleCollectWithLogsChild (q.v.) at
870 // this point, so we shouldn't touch the actor in any case.
871 return true;
874 PContentBridgeChild*
875 ContentChild::AllocPContentBridgeChild(mozilla::ipc::Transport* aTransport,
876 base::ProcessId aOtherProcess)
878 return ContentBridgeChild::Create(aTransport, aOtherProcess);
881 PContentBridgeParent*
882 ContentChild::AllocPContentBridgeParent(mozilla::ipc::Transport* aTransport,
883 base::ProcessId aOtherProcess)
885 MOZ_ASSERT(!mLastBridge);
886 mLastBridge = static_cast<ContentBridgeParent*>(
887 ContentBridgeParent::Create(aTransport, aOtherProcess));
888 return mLastBridge;
891 PCompositorChild*
892 ContentChild::AllocPCompositorChild(mozilla::ipc::Transport* aTransport,
893 base::ProcessId aOtherProcess)
895 return CompositorChild::Create(aTransport, aOtherProcess);
898 PSharedBufferManagerChild*
899 ContentChild::AllocPSharedBufferManagerChild(mozilla::ipc::Transport* aTransport,
900 base::ProcessId aOtherProcess)
902 return SharedBufferManagerChild::StartUpInChildProcess(aTransport, aOtherProcess);
905 PImageBridgeChild*
906 ContentChild::AllocPImageBridgeChild(mozilla::ipc::Transport* aTransport,
907 base::ProcessId aOtherProcess)
909 return ImageBridgeChild::StartUpInChildProcess(aTransport, aOtherProcess);
912 PBackgroundChild*
913 ContentChild::AllocPBackgroundChild(Transport* aTransport,
914 ProcessId aOtherProcess)
916 return BackgroundChild::Alloc(aTransport, aOtherProcess);
919 bool
920 ContentChild::RecvSetProcessSandbox()
922 // We may want to move the sandbox initialization somewhere else
923 // at some point; see bug 880808.
924 #if defined(MOZ_CONTENT_SANDBOX)
925 #if defined(XP_LINUX)
926 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 19
927 // For B2G >= KitKat, sandboxing is mandatory; this has already
928 // been enforced by ContentParent::StartUp().
929 MOZ_ASSERT(CanSandboxContentProcess());
930 #else
931 // Otherwise, sandboxing is best-effort.
932 if (!CanSandboxContentProcess()) {
933 return true;
935 #endif
936 SetContentProcessSandbox();
937 #elif defined(XP_WIN)
938 mozilla::SandboxTarget::Instance()->StartSandbox();
939 #endif
940 #endif
941 return true;
944 bool
945 ContentChild::RecvSpeakerManagerNotify()
947 #ifdef MOZ_WIDGET_GONK
948 // Only notify the process which has the SpeakerManager instance.
949 nsRefPtr<SpeakerManagerService> service =
950 SpeakerManagerService::GetSpeakerManagerService();
951 if (service) {
952 service->Notify();
954 return true;
955 #endif
956 return false;
959 static CancelableTask* sFirstIdleTask;
961 static void FirstIdle(void)
963 MOZ_ASSERT(sFirstIdleTask);
964 sFirstIdleTask = nullptr;
965 ContentChild::GetSingleton()->SendFirstIdle();
968 mozilla::jsipc::PJavaScriptChild *
969 ContentChild::AllocPJavaScriptChild()
971 MOZ_ASSERT(!ManagedPJavaScriptChild().Length());
973 return nsIContentChild::AllocPJavaScriptChild();
976 bool
977 ContentChild::DeallocPJavaScriptChild(PJavaScriptChild *aChild)
979 return nsIContentChild::DeallocPJavaScriptChild(aChild);
982 PBrowserChild*
983 ContentChild::AllocPBrowserChild(const IPCTabContext& aContext,
984 const uint32_t& aChromeFlags,
985 const uint64_t& aID,
986 const bool& aIsForApp,
987 const bool& aIsForBrowser)
989 return nsIContentChild::AllocPBrowserChild(aContext,
990 aChromeFlags,
991 aID,
992 aIsForApp,
993 aIsForBrowser);
996 bool
997 ContentChild::SendPBrowserConstructor(PBrowserChild* aActor,
998 const IPCTabContext& aContext,
999 const uint32_t& aChromeFlags,
1000 const uint64_t& aID,
1001 const bool& aIsForApp,
1002 const bool& aIsForBrowser)
1004 return PContentChild::SendPBrowserConstructor(aActor,
1005 aContext,
1006 aChromeFlags,
1007 aID,
1008 aIsForApp,
1009 aIsForBrowser);
1012 bool
1013 ContentChild::RecvPBrowserConstructor(PBrowserChild* aActor,
1014 const IPCTabContext& aContext,
1015 const uint32_t& aChromeFlags,
1016 const uint64_t& aID,
1017 const bool& aIsForApp,
1018 const bool& aIsForBrowser)
1020 // This runs after AllocPBrowserChild() returns and the IPC machinery for this
1021 // PBrowserChild has been set up.
1023 nsCOMPtr<nsIObserverService> os = services::GetObserverService();
1024 if (os) {
1025 nsITabChild* tc =
1026 static_cast<nsITabChild*>(static_cast<TabChild*>(aActor));
1027 os->NotifyObservers(tc, "tab-child-created", nullptr);
1030 static bool hasRunOnce = false;
1031 if (!hasRunOnce) {
1032 hasRunOnce = true;
1034 MOZ_ASSERT(!sFirstIdleTask);
1035 sFirstIdleTask = NewRunnableFunction(FirstIdle);
1036 MessageLoop::current()->PostIdleTask(FROM_HERE, sFirstIdleTask);
1038 // Redo InitProcessAttributes() when the app or browser is really
1039 // launching so the attributes will be correct.
1040 mID = aID;
1041 mIsForApp = aIsForApp;
1042 mIsForBrowser = aIsForBrowser;
1043 InitProcessAttributes();
1046 return true;
1049 PFileDescriptorSetChild*
1050 ContentChild::AllocPFileDescriptorSetChild(const FileDescriptor& aFD)
1052 return new FileDescriptorSetChild(aFD);
1055 bool
1056 ContentChild::DeallocPFileDescriptorSetChild(PFileDescriptorSetChild* aActor)
1058 delete static_cast<FileDescriptorSetChild*>(aActor);
1059 return true;
1062 bool
1063 ContentChild::DeallocPBrowserChild(PBrowserChild* aIframe)
1065 return nsIContentChild::DeallocPBrowserChild(aIframe);
1068 PBlobChild*
1069 ContentChild::AllocPBlobChild(const BlobConstructorParams& aParams)
1071 return nsIContentChild::AllocPBlobChild(aParams);
1074 mozilla::PRemoteSpellcheckEngineChild *
1075 ContentChild::AllocPRemoteSpellcheckEngineChild()
1077 NS_NOTREACHED("Default Constructor for PRemoteSpellcheckEngineChilf should never be called");
1078 return nullptr;
1081 bool
1082 ContentChild::DeallocPRemoteSpellcheckEngineChild(PRemoteSpellcheckEngineChild *child)
1084 delete child;
1085 return true;
1088 bool
1089 ContentChild::DeallocPBlobChild(PBlobChild* aActor)
1091 return nsIContentChild::DeallocPBlobChild(aActor);
1094 PBlobChild*
1095 ContentChild::SendPBlobConstructor(PBlobChild* aActor,
1096 const BlobConstructorParams& aParams)
1098 return PContentChild::SendPBlobConstructor(aActor, aParams);
1101 PCrashReporterChild*
1102 ContentChild::AllocPCrashReporterChild(const mozilla::dom::NativeThreadId& id,
1103 const uint32_t& processType)
1105 #ifdef MOZ_CRASHREPORTER
1106 return new CrashReporterChild();
1107 #else
1108 return nullptr;
1109 #endif
1112 bool
1113 ContentChild::DeallocPCrashReporterChild(PCrashReporterChild* crashreporter)
1115 delete crashreporter;
1116 return true;
1119 PHalChild*
1120 ContentChild::AllocPHalChild()
1122 return CreateHalChild();
1125 bool
1126 ContentChild::DeallocPHalChild(PHalChild* aHal)
1128 delete aHal;
1129 return true;
1132 PIndexedDBChild*
1133 ContentChild::AllocPIndexedDBChild()
1135 NS_NOTREACHED("Should never get here!");
1136 return nullptr;
1139 bool
1140 ContentChild::DeallocPIndexedDBChild(PIndexedDBChild* aActor)
1142 delete aActor;
1143 return true;
1146 asmjscache::PAsmJSCacheEntryChild*
1147 ContentChild::AllocPAsmJSCacheEntryChild(
1148 const asmjscache::OpenMode& aOpenMode,
1149 const asmjscache::WriteParams& aWriteParams,
1150 const IPC::Principal& aPrincipal)
1152 NS_NOTREACHED("Should never get here!");
1153 return nullptr;
1156 bool
1157 ContentChild::DeallocPAsmJSCacheEntryChild(PAsmJSCacheEntryChild* aActor)
1159 asmjscache::DeallocEntryChild(aActor);
1160 return true;
1163 PTestShellChild*
1164 ContentChild::AllocPTestShellChild()
1166 return new TestShellChild();
1169 bool
1170 ContentChild::DeallocPTestShellChild(PTestShellChild* shell)
1172 delete shell;
1173 return true;
1176 jsipc::JavaScriptChild *
1177 ContentChild::GetCPOWManager()
1179 if (ManagedPJavaScriptChild().Length()) {
1180 return static_cast<JavaScriptChild*>(ManagedPJavaScriptChild()[0]);
1182 JavaScriptChild* actor = static_cast<JavaScriptChild*>(SendPJavaScriptConstructor());
1183 return actor;
1186 bool
1187 ContentChild::RecvPTestShellConstructor(PTestShellChild* actor)
1189 return true;
1192 PDeviceStorageRequestChild*
1193 ContentChild::AllocPDeviceStorageRequestChild(const DeviceStorageParams& aParams)
1195 return new DeviceStorageRequestChild();
1198 bool
1199 ContentChild::DeallocPDeviceStorageRequestChild(PDeviceStorageRequestChild* aDeviceStorage)
1201 delete aDeviceStorage;
1202 return true;
1205 PFileSystemRequestChild*
1206 ContentChild::AllocPFileSystemRequestChild(const FileSystemParams& aParams)
1208 NS_NOTREACHED("Should never get here!");
1209 return nullptr;
1212 bool
1213 ContentChild::DeallocPFileSystemRequestChild(PFileSystemRequestChild* aFileSystem)
1215 mozilla::dom::FileSystemTaskBase* child =
1216 static_cast<mozilla::dom::FileSystemTaskBase*>(aFileSystem);
1217 // The reference is increased in FileSystemTaskBase::Start of
1218 // FileSystemTaskBase.cpp. We should decrease it after IPC.
1219 NS_RELEASE(child);
1220 return true;
1223 PNeckoChild*
1224 ContentChild::AllocPNeckoChild()
1226 return new NeckoChild();
1229 bool
1230 ContentChild::DeallocPNeckoChild(PNeckoChild* necko)
1232 delete necko;
1233 return true;
1236 PScreenManagerChild*
1237 ContentChild::AllocPScreenManagerChild(uint32_t* aNumberOfScreens,
1238 float* aSystemDefaultScale,
1239 bool* aSuccess)
1241 // The ContentParent should never attempt to allocate the
1242 // nsScreenManagerProxy. Instead, the nsScreenManagerProxy
1243 // service is requested and instantiated via XPCOM, and the
1244 // constructor of nsScreenManagerProxy sets up the IPC connection.
1245 NS_NOTREACHED("Should never get here!");
1246 return nullptr;
1249 bool
1250 ContentChild::DeallocPScreenManagerChild(PScreenManagerChild* aService)
1252 // nsScreenManagerProxy is AddRef'd in its constructor.
1253 nsScreenManagerProxy *child = static_cast<nsScreenManagerProxy*>(aService);
1254 child->Release();
1255 return true;
1258 PExternalHelperAppChild*
1259 ContentChild::AllocPExternalHelperAppChild(const OptionalURIParams& uri,
1260 const nsCString& aMimeContentType,
1261 const nsCString& aContentDisposition,
1262 const uint32_t& aContentDispositionHint,
1263 const nsString& aContentDispositionFilename,
1264 const bool& aForceSave,
1265 const int64_t& aContentLength,
1266 const OptionalURIParams& aReferrer,
1267 PBrowserChild* aBrowser)
1269 ExternalHelperAppChild *child = new ExternalHelperAppChild();
1270 child->AddRef();
1271 return child;
1274 bool
1275 ContentChild::DeallocPExternalHelperAppChild(PExternalHelperAppChild* aService)
1277 ExternalHelperAppChild *child = static_cast<ExternalHelperAppChild*>(aService);
1278 child->Release();
1279 return true;
1282 PSmsChild*
1283 ContentChild::AllocPSmsChild()
1285 return new SmsChild();
1288 bool
1289 ContentChild::DeallocPSmsChild(PSmsChild* aSms)
1291 delete aSms;
1292 return true;
1295 PTelephonyChild*
1296 ContentChild::AllocPTelephonyChild()
1298 MOZ_CRASH("No one should be allocating PTelephonyChild actors");
1301 bool
1302 ContentChild::DeallocPTelephonyChild(PTelephonyChild* aActor)
1304 delete aActor;
1305 return true;
1308 PStorageChild*
1309 ContentChild::AllocPStorageChild()
1311 NS_NOTREACHED("We should never be manually allocating PStorageChild actors");
1312 return nullptr;
1315 bool
1316 ContentChild::DeallocPStorageChild(PStorageChild* aActor)
1318 DOMStorageDBChild* child = static_cast<DOMStorageDBChild*>(aActor);
1319 child->ReleaseIPDLReference();
1320 return true;
1323 PBluetoothChild*
1324 ContentChild::AllocPBluetoothChild()
1326 #ifdef MOZ_B2G_BT
1327 MOZ_CRASH("No one should be allocating PBluetoothChild actors");
1328 #else
1329 MOZ_CRASH("No support for bluetooth on this platform!");
1330 #endif
1333 bool
1334 ContentChild::DeallocPBluetoothChild(PBluetoothChild* aActor)
1336 #ifdef MOZ_B2G_BT
1337 delete aActor;
1338 return true;
1339 #else
1340 MOZ_CRASH("No support for bluetooth on this platform!");
1341 #endif
1344 PFMRadioChild*
1345 ContentChild::AllocPFMRadioChild()
1347 #ifdef MOZ_B2G_FM
1348 NS_RUNTIMEABORT("No one should be allocating PFMRadioChild actors");
1349 return nullptr;
1350 #else
1351 NS_RUNTIMEABORT("No support for FMRadio on this platform!");
1352 return nullptr;
1353 #endif
1356 bool
1357 ContentChild::DeallocPFMRadioChild(PFMRadioChild* aActor)
1359 #ifdef MOZ_B2G_FM
1360 delete aActor;
1361 return true;
1362 #else
1363 NS_RUNTIMEABORT("No support for FMRadio on this platform!");
1364 return false;
1365 #endif
1368 PSpeechSynthesisChild*
1369 ContentChild::AllocPSpeechSynthesisChild()
1371 #ifdef MOZ_WEBSPEECH
1372 MOZ_CRASH("No one should be allocating PSpeechSynthesisChild actors");
1373 #else
1374 return nullptr;
1375 #endif
1378 bool
1379 ContentChild::DeallocPSpeechSynthesisChild(PSpeechSynthesisChild* aActor)
1381 #ifdef MOZ_WEBSPEECH
1382 delete aActor;
1383 return true;
1384 #else
1385 return false;
1386 #endif
1389 bool
1390 ContentChild::RecvRegisterChrome(const InfallibleTArray<ChromePackage>& packages,
1391 const InfallibleTArray<ResourceMapping>& resources,
1392 const InfallibleTArray<OverrideMapping>& overrides,
1393 const nsCString& locale,
1394 const bool& reset)
1396 nsCOMPtr<nsIChromeRegistry> registrySvc = nsChromeRegistry::GetService();
1397 nsChromeRegistryContent* chromeRegistry =
1398 static_cast<nsChromeRegistryContent*>(registrySvc.get());
1399 chromeRegistry->RegisterRemoteChrome(packages, resources, overrides,
1400 locale, reset);
1401 return true;
1404 bool
1405 ContentChild::RecvRegisterChromeItem(const ChromeRegistryItem& item)
1407 nsCOMPtr<nsIChromeRegistry> registrySvc = nsChromeRegistry::GetService();
1408 nsChromeRegistryContent* chromeRegistry =
1409 static_cast<nsChromeRegistryContent*>(registrySvc.get());
1410 switch (item.type()) {
1411 case ChromeRegistryItem::TChromePackage:
1412 chromeRegistry->RegisterPackage(item.get_ChromePackage());
1413 break;
1415 case ChromeRegistryItem::TOverrideMapping:
1416 chromeRegistry->RegisterOverride(item.get_OverrideMapping());
1417 break;
1419 default:
1420 MOZ_ASSERT(false, "bad chrome item");
1421 return false;
1424 return true;
1427 bool
1428 ContentChild::RecvSetOffline(const bool& offline)
1430 nsCOMPtr<nsIIOService> io (do_GetIOService());
1431 NS_ASSERTION(io, "IO Service can not be null");
1433 io->SetOffline(offline);
1435 return true;
1438 void
1439 ContentChild::ActorDestroy(ActorDestroyReason why)
1441 if (AbnormalShutdown == why) {
1442 NS_WARNING("shutting down early because of crash!");
1443 QuickExit();
1446 #ifndef DEBUG
1447 // In release builds, there's no point in the content process
1448 // going through the full XPCOM shutdown path, because it doesn't
1449 // keep persistent state.
1450 QuickExit();
1451 #endif
1453 if (sFirstIdleTask) {
1454 sFirstIdleTask->Cancel();
1457 mAlertObservers.Clear();
1459 mIdleObservers.Clear();
1461 nsCOMPtr<nsIConsoleService> svc(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
1462 if (svc) {
1463 svc->UnregisterListener(mConsoleListener);
1464 mConsoleListener->mChild = nullptr;
1467 #ifdef MOZ_NUWA_PROCESS
1468 if (IsNuwaProcess()) {
1469 // The Nuwa cannot go through the full XPCOM shutdown path or deadlock
1470 // will result.
1471 QuickExit();
1473 #endif
1475 XRE_ShutdownChildProcess();
1478 void
1479 ContentChild::ProcessingError(Result what)
1481 switch (what) {
1482 case MsgDropped:
1483 QuickExit();
1485 case MsgNotKnown:
1486 NS_RUNTIMEABORT("aborting because of MsgNotKnown");
1487 case MsgNotAllowed:
1488 NS_RUNTIMEABORT("aborting because of MsgNotAllowed");
1489 case MsgPayloadError:
1490 NS_RUNTIMEABORT("aborting because of MsgPayloadError");
1491 case MsgProcessingError:
1492 NS_RUNTIMEABORT("aborting because of MsgProcessingError");
1493 case MsgRouteError:
1494 NS_RUNTIMEABORT("aborting because of MsgRouteError");
1495 case MsgValueError:
1496 NS_RUNTIMEABORT("aborting because of MsgValueError");
1498 default:
1499 NS_RUNTIMEABORT("not reached");
1503 void
1504 ContentChild::QuickExit()
1506 NS_WARNING("content process _exit()ing");
1507 _exit(0);
1510 nsresult
1511 ContentChild::AddRemoteAlertObserver(const nsString& aData,
1512 nsIObserver* aObserver)
1514 NS_ASSERTION(aObserver, "Adding a null observer?");
1515 mAlertObservers.AppendElement(new AlertObserver(aObserver, aData));
1516 return NS_OK;
1520 bool
1521 ContentChild::RecvSystemMemoryAvailable(const uint64_t& aGetterId,
1522 const uint32_t& aMemoryAvailable)
1524 nsRefPtr<Promise> p = dont_AddRef(reinterpret_cast<Promise*>(aGetterId));
1526 if (!aMemoryAvailable) {
1527 p->MaybeReject(NS_ERROR_NOT_AVAILABLE);
1528 return true;
1531 p->MaybeResolve((int)aMemoryAvailable);
1532 return true;
1535 bool
1536 ContentChild::RecvPreferenceUpdate(const PrefSetting& aPref)
1538 Preferences::SetPreference(aPref);
1539 return true;
1542 bool
1543 ContentChild::RecvNotifyAlertsObserver(const nsCString& aType, const nsString& aData)
1545 for (uint32_t i = 0; i < mAlertObservers.Length();
1546 /*we mutate the array during the loop; ++i iff no mutation*/) {
1547 AlertObserver* observer = mAlertObservers[i];
1548 if (observer->Observes(aData) && observer->Notify(aType)) {
1549 // if aType == alertfinished, this alert is done. we can
1550 // remove the observer.
1551 if (aType.Equals(nsDependentCString("alertfinished"))) {
1552 mAlertObservers.RemoveElementAt(i);
1553 continue;
1556 ++i;
1558 return true;
1561 bool
1562 ContentChild::RecvNotifyVisited(const URIParams& aURI)
1564 nsCOMPtr<nsIURI> newURI = DeserializeURI(aURI);
1565 if (!newURI) {
1566 return false;
1568 nsCOMPtr<IHistory> history = services::GetHistoryService();
1569 if (history) {
1570 history->NotifyVisited(newURI);
1572 return true;
1575 bool
1576 ContentChild::RecvAsyncMessage(const nsString& aMsg,
1577 const ClonedMessageData& aData,
1578 const InfallibleTArray<CpowEntry>& aCpows,
1579 const IPC::Principal& aPrincipal)
1581 nsRefPtr<nsFrameMessageManager> cpm = nsFrameMessageManager::sChildProcessManager;
1582 if (cpm) {
1583 StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForChild(aData);
1584 CpowIdHolder cpows(GetCPOWManager(), aCpows);
1585 cpm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(cpm.get()),
1586 aMsg, false, &cloneData, &cpows, aPrincipal, nullptr);
1588 return true;
1591 bool
1592 ContentChild::RecvGeolocationUpdate(const GeoPosition& somewhere)
1594 nsCOMPtr<nsIGeolocationUpdate> gs = do_GetService("@mozilla.org/geolocation/service;1");
1595 if (!gs) {
1596 return true;
1598 nsCOMPtr<nsIDOMGeoPosition> position = somewhere;
1599 gs->Update(position);
1600 return true;
1603 bool
1604 ContentChild::RecvAddPermission(const IPC::Permission& permission)
1606 #if MOZ_PERMISSIONS
1607 nsCOMPtr<nsIPermissionManager> permissionManagerIface =
1608 services::GetPermissionManager();
1609 nsPermissionManager* permissionManager =
1610 static_cast<nsPermissionManager*>(permissionManagerIface.get());
1611 NS_ABORT_IF_FALSE(permissionManager,
1612 "We have no permissionManager in the Content process !");
1614 nsCOMPtr<nsIURI> uri;
1615 NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("http://") + nsCString(permission.host));
1616 NS_ENSURE_TRUE(uri, true);
1618 nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
1619 MOZ_ASSERT(secMan);
1621 nsCOMPtr<nsIPrincipal> principal;
1622 nsresult rv = secMan->GetAppCodebasePrincipal(uri, permission.appId,
1623 permission.isInBrowserElement,
1624 getter_AddRefs(principal));
1625 NS_ENSURE_SUCCESS(rv, true);
1627 permissionManager->AddInternal(principal,
1628 nsCString(permission.type),
1629 permission.capability,
1631 permission.expireType,
1632 permission.expireTime,
1633 nsPermissionManager::eNotify,
1634 nsPermissionManager::eNoDBOperation);
1635 #endif
1637 return true;
1640 bool
1641 ContentChild::RecvScreenSizeChanged(const gfxIntSize& size)
1643 #ifdef ANDROID
1644 mScreenSize = size;
1645 #else
1646 NS_RUNTIMEABORT("Message currently only expected on android");
1647 #endif
1648 return true;
1651 bool
1652 ContentChild::RecvFlushMemory(const nsString& reason)
1654 #ifdef MOZ_NUWA_PROCESS
1655 if (IsNuwaProcess()) {
1656 // Don't flush memory in the nuwa process: the GC thread could be frozen.
1657 return true;
1659 #endif
1660 nsCOMPtr<nsIObserverService> os =
1661 mozilla::services::GetObserverService();
1662 if (os)
1663 os->NotifyObservers(nullptr, "memory-pressure", reason.get());
1664 return true;
1667 bool
1668 ContentChild::RecvActivateA11y()
1670 #ifdef ACCESSIBILITY
1671 // Start accessibility in content process if it's running in chrome
1672 // process.
1673 nsCOMPtr<nsIAccessibilityService> accService =
1674 services::GetAccessibilityService();
1675 #endif
1676 return true;
1679 bool
1680 ContentChild::RecvGarbageCollect()
1682 // Rebroadcast the "child-gc-request" so that workers will GC.
1683 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
1684 if (obs) {
1685 obs->NotifyObservers(nullptr, "child-gc-request", nullptr);
1687 nsJSContext::GarbageCollectNow(JS::gcreason::DOM_IPC);
1688 return true;
1691 bool
1692 ContentChild::RecvCycleCollect()
1694 // Rebroadcast the "child-cc-request" so that workers will CC.
1695 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
1696 if (obs) {
1697 obs->NotifyObservers(nullptr, "child-cc-request", nullptr);
1699 nsJSContext::CycleCollectNow();
1700 return true;
1703 #ifdef MOZ_NUWA_PROCESS
1704 static void
1705 OnFinishNuwaPreparation ()
1707 MakeNuwaProcess();
1709 #endif
1711 static void
1712 PreloadSlowThings()
1714 // This fetches and creates all the built-in stylesheets.
1715 nsLayoutStylesheetCache::UserContentSheet();
1717 TabChild::PreloadSlowThings();
1721 bool
1722 ContentChild::RecvAppInfo(const nsCString& version, const nsCString& buildID,
1723 const nsCString& name, const nsCString& UAName)
1725 mAppInfo.version.Assign(version);
1726 mAppInfo.buildID.Assign(buildID);
1727 mAppInfo.name.Assign(name);
1728 mAppInfo.UAName.Assign(UAName);
1730 if (!Preferences::GetBool("dom.ipc.processPrelaunch.enabled", false)) {
1731 return true;
1734 // If we're part of the mozbrowser machinery, go ahead and start
1735 // preloading things. We can only do this for mozbrowser because
1736 // PreloadSlowThings() may set the docshell of the first TabChild
1737 // inactive, and we can only safely restore it to active from
1738 // BrowserElementChild.js.
1739 if ((mIsForApp || mIsForBrowser)
1740 #ifdef MOZ_NUWA_PROCESS
1741 && !IsNuwaProcess()
1742 #endif
1744 PreloadSlowThings();
1747 #ifdef MOZ_NUWA_PROCESS
1748 if (IsNuwaProcess()) {
1749 ContentChild::GetSingleton()->RecvGarbageCollect();
1750 MessageLoop::current()->PostTask(
1751 FROM_HERE, NewRunnableFunction(OnFinishNuwaPreparation));
1753 #endif
1755 return true;
1758 bool
1759 ContentChild::RecvLastPrivateDocShellDestroyed()
1761 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
1762 obs->NotifyObservers(nullptr, "last-pb-context-exited", nullptr);
1763 return true;
1766 bool
1767 ContentChild::RecvFilePathUpdate(const nsString& aStorageType,
1768 const nsString& aStorageName,
1769 const nsString& aPath,
1770 const nsCString& aReason)
1772 nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(aStorageType, aStorageName, aPath);
1774 nsString reason;
1775 CopyASCIItoUTF16(aReason, reason);
1776 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
1777 obs->NotifyObservers(dsf, "file-watcher-update", reason.get());
1778 return true;
1781 bool
1782 ContentChild::RecvFileSystemUpdate(const nsString& aFsName,
1783 const nsString& aVolumeName,
1784 const int32_t& aState,
1785 const int32_t& aMountGeneration,
1786 const bool& aIsMediaPresent,
1787 const bool& aIsSharing,
1788 const bool& aIsFormatting,
1789 const bool& aIsFake,
1790 const bool& aIsUnmounting)
1792 #ifdef MOZ_WIDGET_GONK
1793 nsRefPtr<nsVolume> volume = new nsVolume(aFsName, aVolumeName, aState,
1794 aMountGeneration, aIsMediaPresent,
1795 aIsSharing, aIsFormatting, aIsFake,
1796 aIsUnmounting);
1798 nsRefPtr<nsVolumeService> vs = nsVolumeService::GetSingleton();
1799 if (vs) {
1800 vs->UpdateVolume(volume);
1802 #else
1803 // Remove warnings about unused arguments
1804 unused << aFsName;
1805 unused << aVolumeName;
1806 unused << aState;
1807 unused << aMountGeneration;
1808 unused << aIsMediaPresent;
1809 unused << aIsSharing;
1810 unused << aIsFormatting;
1811 unused << aIsFake;
1812 unused << aIsUnmounting;
1813 #endif
1814 return true;
1817 bool
1818 ContentChild::RecvNotifyProcessPriorityChanged(
1819 const hal::ProcessPriority& aPriority)
1821 nsCOMPtr<nsIObserverService> os = services::GetObserverService();
1822 NS_ENSURE_TRUE(os, true);
1824 nsRefPtr<nsHashPropertyBag> props = new nsHashPropertyBag();
1825 props->SetPropertyAsInt32(NS_LITERAL_STRING("priority"),
1826 static_cast<int32_t>(aPriority));
1828 os->NotifyObservers(static_cast<nsIPropertyBag2*>(props),
1829 "ipc:process-priority-changed", nullptr);
1830 return true;
1833 bool
1834 ContentChild::RecvMinimizeMemoryUsage()
1836 #ifdef MOZ_NUWA_PROCESS
1837 if (IsNuwaProcess()) {
1838 // Don't minimize memory in the nuwa process: it will perform GC, but the
1839 // GC thread could be frozen.
1840 return true;
1842 #endif
1843 nsCOMPtr<nsIMemoryReporterManager> mgr =
1844 do_GetService("@mozilla.org/memory-reporter-manager;1");
1845 NS_ENSURE_TRUE(mgr, true);
1847 mgr->MinimizeMemoryUsage(/* callback = */ nullptr);
1848 return true;
1851 bool
1852 ContentChild::RecvNotifyPhoneStateChange(const nsString& aState)
1854 nsCOMPtr<nsIObserverService> os = services::GetObserverService();
1855 if (os) {
1856 os->NotifyObservers(nullptr, "phone-state-changed", aState.get());
1858 return true;
1861 void
1862 ContentChild::AddIdleObserver(nsIObserver* aObserver, uint32_t aIdleTimeInS)
1864 MOZ_ASSERT(aObserver, "null idle observer");
1865 // Make sure aObserver isn't released while we wait for the parent
1866 aObserver->AddRef();
1867 SendAddIdleObserver(reinterpret_cast<uint64_t>(aObserver), aIdleTimeInS);
1868 mIdleObservers.PutEntry(aObserver);
1871 void
1872 ContentChild::RemoveIdleObserver(nsIObserver* aObserver, uint32_t aIdleTimeInS)
1874 MOZ_ASSERT(aObserver, "null idle observer");
1875 SendRemoveIdleObserver(reinterpret_cast<uint64_t>(aObserver), aIdleTimeInS);
1876 aObserver->Release();
1877 mIdleObservers.RemoveEntry(aObserver);
1880 bool
1881 ContentChild::RecvNotifyIdleObserver(const uint64_t& aObserver,
1882 const nsCString& aTopic,
1883 const nsString& aTimeStr)
1885 nsIObserver* observer = reinterpret_cast<nsIObserver*>(aObserver);
1886 if (mIdleObservers.Contains(observer)) {
1887 observer->Observe(nullptr, aTopic.get(), aTimeStr.get());
1888 } else {
1889 NS_WARNING("Received notification for an idle observer that was removed.");
1891 return true;
1894 bool
1895 ContentChild::RecvLoadAndRegisterSheet(const URIParams& aURI, const uint32_t& aType)
1897 nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
1898 if (!uri) {
1899 return true;
1902 nsStyleSheetService *sheetService = nsStyleSheetService::GetInstance();
1903 if (sheetService) {
1904 sheetService->LoadAndRegisterSheet(uri, aType);
1907 return true;
1910 bool
1911 ContentChild::RecvUnregisterSheet(const URIParams& aURI, const uint32_t& aType)
1913 nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
1914 if (!uri) {
1915 return true;
1918 nsStyleSheetService *sheetService = nsStyleSheetService::GetInstance();
1919 if (sheetService) {
1920 sheetService->UnregisterSheet(uri, aType);
1923 return true;
1926 #ifdef MOZ_NUWA_PROCESS
1927 class CallNuwaSpawn : public nsRunnable
1929 public:
1930 NS_IMETHOD Run()
1932 NuwaSpawn();
1933 if (IsNuwaProcess()) {
1934 return NS_OK;
1937 // In the new process.
1938 ContentChild* child = ContentChild::GetSingleton();
1939 child->SetProcessName(NS_LITERAL_STRING("(Preallocated app)"), false);
1940 mozilla::ipc::Transport* transport = child->GetTransport();
1941 int fd = transport->GetFileDescriptor();
1942 transport->ResetFileDescriptor(fd);
1944 IToplevelProtocol* toplevel = child->GetFirstOpenedActors();
1945 while (toplevel != nullptr) {
1946 transport = toplevel->GetTransport();
1947 fd = transport->GetFileDescriptor();
1948 transport->ResetFileDescriptor(fd);
1950 toplevel = toplevel->getNext();
1953 // Perform other after-fork initializations.
1954 InitOnContentProcessCreated();
1956 return NS_OK;
1960 static void
1961 DoNuwaFork()
1963 NS_ASSERTION(NuwaSpawnPrepare != nullptr,
1964 "NuwaSpawnPrepare() is not available!");
1965 NuwaSpawnPrepare(); // NuwaSpawn will be blocked.
1968 nsCOMPtr<nsIRunnable> callSpawn(new CallNuwaSpawn());
1969 NS_DispatchToMainThread(callSpawn);
1972 // IOThread should be blocked here for waiting NuwaSpawn().
1973 NS_ASSERTION(NuwaSpawnWait != nullptr,
1974 "NuwaSpawnWait() is not available!");
1975 NuwaSpawnWait(); // Now! NuwaSpawn can go.
1976 // Here, we can make sure the spawning was finished.
1980 * This function should keep IO thread in a stable state and freeze it
1981 * until the spawning is finished.
1983 static void
1984 RunNuwaFork()
1986 if (NuwaCheckpointCurrentThread()) {
1987 DoNuwaFork();
1990 #endif
1992 bool
1993 ContentChild::RecvNuwaFork()
1995 #ifdef MOZ_NUWA_PROCESS
1996 if (sNuwaForking) { // No reentry.
1997 return true;
1999 sNuwaForking = true;
2001 // We want to ensure that the PBackground actor gets cloned in the Nuwa
2002 // process before we freeze. Also, we have to do this to avoid deadlock.
2003 // Protocols that are "opened" (e.g. PBackground, PCompositor) block the
2004 // main thread to wait for the IPC thread during the open operation.
2005 // NuwaSpawnWait() blocks the IPC thread to wait for the main thread when
2006 // the Nuwa process is forked. Unless we ensure that the two cannot happen
2007 // at the same time then we risk deadlock. Spinning the event loop here
2008 // guarantees the ordering is safe for PBackground.
2009 while (!BackgroundChild::GetForCurrentThread()) {
2010 if (NS_WARN_IF(!NS_ProcessNextEvent())) {
2011 return false;
2015 MessageLoop* ioloop = XRE_GetIOMessageLoop();
2016 ioloop->PostTask(FROM_HERE, NewRunnableFunction(RunNuwaFork));
2017 return true;
2018 #else
2019 return false; // Makes the underlying IPC channel abort.
2020 #endif
2023 bool
2024 ContentChild::RecvOnAppThemeChanged()
2026 nsCOMPtr<nsIObserverService> os = services::GetObserverService();
2027 if (os) {
2028 os->NotifyObservers(nullptr, "app-theme-changed", nullptr);
2030 return true;
2033 } // namespace dom
2034 } // namespace mozilla
2036 extern "C" {
2038 #if defined(MOZ_NUWA_PROCESS)
2039 NS_EXPORT void
2040 GetProtoFdInfos(NuwaProtoFdInfo* aInfoList,
2041 size_t aInfoListSize,
2042 size_t* aInfoSize)
2044 size_t i = 0;
2046 mozilla::dom::ContentChild* content =
2047 mozilla::dom::ContentChild::GetSingleton();
2048 aInfoList[i].protoId = content->GetProtocolId();
2049 aInfoList[i].originFd =
2050 content->GetTransport()->GetFileDescriptor();
2051 i++;
2053 for (IToplevelProtocol* actor = content->GetFirstOpenedActors();
2054 actor != nullptr;
2055 actor = actor->getNext()) {
2056 if (i >= aInfoListSize) {
2057 NS_RUNTIMEABORT("Too many top level protocols!");
2060 aInfoList[i].protoId = actor->GetProtocolId();
2061 aInfoList[i].originFd =
2062 actor->GetTransport()->GetFileDescriptor();
2063 i++;
2066 if (i > NUWA_TOPLEVEL_MAX) {
2067 NS_RUNTIMEABORT("Too many top level protocols!");
2069 *aInfoSize = i;
2072 class RunAddNewIPCProcess : public nsRunnable
2074 public:
2075 RunAddNewIPCProcess(pid_t aPid,
2076 nsTArray<mozilla::ipc::ProtocolFdMapping>& aMaps)
2077 : mPid(aPid)
2079 mMaps.SwapElements(aMaps);
2082 NS_IMETHOD Run()
2084 mozilla::dom::ContentChild::GetSingleton()->
2085 SendAddNewProcess(mPid, mMaps);
2087 MOZ_ASSERT(sNuwaForking);
2088 sNuwaForking = false;
2090 return NS_OK;
2093 private:
2094 pid_t mPid;
2095 nsTArray<mozilla::ipc::ProtocolFdMapping> mMaps;
2099 * AddNewIPCProcess() is called by Nuwa process to tell the parent
2100 * process that a new process is created.
2102 * In the newly created process, ResetContentChildTransport() is called to
2103 * reset fd for the IPC Channel and the session.
2105 NS_EXPORT void
2106 AddNewIPCProcess(pid_t aPid, NuwaProtoFdInfo* aInfoList, size_t aInfoListSize)
2108 nsTArray<mozilla::ipc::ProtocolFdMapping> maps;
2110 for (size_t i = 0; i < aInfoListSize; i++) {
2111 int _fd = aInfoList[i].newFds[NUWA_NEWFD_PARENT];
2112 mozilla::ipc::FileDescriptor fd(_fd);
2113 mozilla::ipc::ProtocolFdMapping map(aInfoList[i].protoId, fd);
2114 maps.AppendElement(map);
2117 nsRefPtr<RunAddNewIPCProcess> runner = new RunAddNewIPCProcess(aPid, maps);
2118 NS_DispatchToMainThread(runner);
2121 NS_EXPORT void
2122 OnNuwaProcessReady()
2124 mozilla::dom::ContentChild* content =
2125 mozilla::dom::ContentChild::GetSingleton();
2126 content->SendNuwaReady();
2129 NS_EXPORT void
2130 AfterNuwaFork()
2132 SetCurrentProcessPrivileges(base::PRIVILEGES_DEFAULT);
2135 #endif // MOZ_NUWA_PROCESS