dom/ipc/ContentChild.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     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/dom/asmjscache/AsmJSCache.h"
    22 #include "mozilla/dom/asmjscache/PAsmJSCacheEntryChild.h"
    23 #include "mozilla/dom/ExternalHelperAppChild.h"
    24 #include "mozilla/dom/PCrashReporterChild.h"
    25 #include "mozilla/dom/DOMStorageIPC.h"
    26 #include "mozilla/hal_sandbox/PHalChild.h"
    27 #include "mozilla/ipc/BackgroundChild.h"
    28 #include "mozilla/ipc/GeckoChildProcessHost.h"
    29 #include "mozilla/ipc/TestShellChild.h"
    30 #include "mozilla/layers/CompositorChild.h"
    31 #include "mozilla/layers/ImageBridgeChild.h"
    32 #include "mozilla/layers/PCompositorChild.h"
    33 #include "mozilla/net/NeckoChild.h"
    34 #include "mozilla/Preferences.h"
    36 #if defined(MOZ_CONTENT_SANDBOX)
    37 #if defined(XP_WIN)
    38 #define TARGET_SANDBOX_EXPORTS
    39 #include "mozilla/sandboxTarget.h"
    40 #elif defined(XP_LINUX)
    41 #include "mozilla/Sandbox.h"
    42 #endif
    43 #endif
    45 #include "mozilla/unused.h"
    47 #include "nsIConsoleListener.h"
    48 #include "nsIIPCBackgroundChildCreateCallback.h"
    49 #include "nsIInterfaceRequestorUtils.h"
    50 #include "nsIMemoryReporter.h"
    51 #include "nsIMemoryInfoDumper.h"
    52 #include "nsIMutable.h"
    53 #include "nsIObserverService.h"
    54 #include "nsIScriptSecurityManager.h"
    55 #include "nsServiceManagerUtils.h"
    56 #include "nsStyleSheetService.h"
    57 #include "nsXULAppAPI.h"
    58 #include "nsIScriptError.h"
    59 #include "nsIConsoleService.h"
    60 #include "nsJSEnvironment.h"
    61 #include "SandboxHal.h"
    62 #include "nsDebugImpl.h"
    63 #include "nsHashPropertyBag.h"
    64 #include "nsLayoutStylesheetCache.h"
    65 #include "nsIJSRuntimeService.h"
    66 #include "nsThreadManager.h"
    68 #include "IHistory.h"
    69 #include "nsNetUtil.h"
    71 #include "base/message_loop.h"
    72 #include "base/process_util.h"
    73 #include "base/task.h"
    75 #include "nsChromeRegistryContent.h"
    76 #include "nsFrameMessageManager.h"
    78 #include "nsIGeolocationProvider.h"
    79 #include "mozilla/dom/PMemoryReportRequestChild.h"
    81 #ifdef MOZ_PERMISSIONS
    82 #include "nsIScriptSecurityManager.h"
    83 #include "nsPermission.h"
    84 #include "nsPermissionManager.h"
    85 #endif
    87 #include "PermissionMessageUtils.h"
    89 #if defined(MOZ_WIDGET_ANDROID)
    90 #include "APKOpen.h"
    91 #endif
    93 #if defined(MOZ_WIDGET_GONK)
    94 #include "nsVolume.h"
    95 #include "nsVolumeService.h"
    96 #include "SpeakerManagerService.h"
    97 #endif
    99 #ifdef XP_WIN
   100 #include <process.h>
   101 #define getpid _getpid
   102 #endif
   104 #ifdef MOZ_X11
   105 #include "mozilla/X11Util.h"
   106 #endif
   108 #ifdef ACCESSIBILITY
   109 #include "nsIAccessibilityService.h"
   110 #endif
   112 #ifdef MOZ_NUWA_PROCESS
   113 #include <setjmp.h>
   114 #include "ipc/Nuwa.h"
   115 #endif
   117 #include "mozilla/dom/indexedDB/PIndexedDBChild.h"
   118 #include "mozilla/dom/mobilemessage/SmsChild.h"
   119 #include "mozilla/dom/devicestorage/DeviceStorageRequestChild.h"
   120 #include "mozilla/dom/PFileSystemRequestChild.h"
   121 #include "mozilla/dom/FileSystemTaskBase.h"
   122 #include "mozilla/dom/bluetooth/PBluetoothChild.h"
   123 #include "mozilla/dom/PFMRadioChild.h"
   124 #include "mozilla/ipc/InputStreamUtils.h"
   126 #ifdef MOZ_WEBSPEECH
   127 #include "mozilla/dom/PSpeechSynthesisChild.h"
   128 #endif
   130 #include "nsDOMFile.h"
   131 #include "nsIRemoteBlob.h"
   132 #include "ProcessUtils.h"
   133 #include "StructuredCloneUtils.h"
   134 #include "URIUtils.h"
   135 #include "nsContentUtils.h"
   136 #include "nsIPrincipal.h"
   137 #include "nsDeviceStorage.h"
   138 #include "AudioChannelService.h"
   139 #include "JavaScriptChild.h"
   140 #include "mozilla/dom/telephony/PTelephonyChild.h"
   141 #include "mozilla/dom/time/DateCacheCleaner.h"
   142 #include "mozilla/net/NeckoMessageUtils.h"
   144 using namespace base;
   145 using namespace mozilla;
   146 using namespace mozilla::docshell;
   147 using namespace mozilla::dom::bluetooth;
   148 using namespace mozilla::dom::devicestorage;
   149 using namespace mozilla::dom::ipc;
   150 using namespace mozilla::dom::mobilemessage;
   151 using namespace mozilla::dom::indexedDB;
   152 using namespace mozilla::dom::telephony;
   153 using namespace mozilla::hal_sandbox;
   154 using namespace mozilla::ipc;
   155 using namespace mozilla::layers;
   156 using namespace mozilla::net;
   157 using namespace mozilla::jsipc;
   158 #if defined(MOZ_WIDGET_GONK)
   159 using namespace mozilla::system;
   160 #endif
   162 #ifdef MOZ_NUWA_PROCESS
   163 static bool sNuwaForking = false;
   165 // The size of the reserved stack (in unsigned ints). It's used to reserve space
   166 // to push sigsetjmp() in NuwaCheckpointCurrentThread() to higher in the stack
   167 // so that after it returns and do other work we don't garble the stack we want
   168 // to preserve in NuwaCheckpointCurrentThread().
   169 #define RESERVED_INT_STACK 128
   171 // A sentinel value for checking whether RESERVED_INT_STACK is large enough.
   172 #define STACK_SENTINEL_VALUE 0xdeadbeef
   173 #endif
   175 namespace mozilla {
   176 namespace dom {
   178 class MemoryReportRequestChild : public PMemoryReportRequestChild,
   179                                  public nsIRunnable
   180 {
   181 public:
   182     NS_DECL_ISUPPORTS
   184     MemoryReportRequestChild(uint32_t aGeneration, const nsAString& aDMDDumpIdent);
   185     virtual ~MemoryReportRequestChild();
   186     NS_IMETHOD Run();
   187 private:
   188     uint32_t mGeneration;
   189     nsString mDMDDumpIdent;
   190 };
   192 NS_IMPL_ISUPPORTS(MemoryReportRequestChild, nsIRunnable)
   194 MemoryReportRequestChild::MemoryReportRequestChild(uint32_t aGeneration, const nsAString& aDMDDumpIdent)
   195 : mGeneration(aGeneration), mDMDDumpIdent(aDMDDumpIdent)
   196 {
   197     MOZ_COUNT_CTOR(MemoryReportRequestChild);
   198 }
   200 MemoryReportRequestChild::~MemoryReportRequestChild()
   201 {
   202     MOZ_COUNT_DTOR(MemoryReportRequestChild);
   203 }
   205 class AlertObserver
   206 {
   207 public:
   209     AlertObserver(nsIObserver *aObserver, const nsString& aData)
   210         : mObserver(aObserver)
   211         , mData(aData)
   212     {
   213     }
   215     ~AlertObserver() {}
   217     bool ShouldRemoveFrom(nsIObserver* aObserver,
   218                           const nsString& aData) const
   219     {
   220         return (mObserver == aObserver &&
   221                 mData == aData);
   222     }
   224     bool Observes(const nsString& aData) const
   225     {
   226         return mData.Equals(aData);
   227     }
   229     bool Notify(const nsCString& aType) const
   230     {
   231         mObserver->Observe(nullptr, aType.get(), mData.get());
   232         return true;
   233     }
   235 private:
   236     nsCOMPtr<nsIObserver> mObserver;
   237     nsString mData;
   238 };
   240 class ConsoleListener MOZ_FINAL : public nsIConsoleListener
   241 {
   242 public:
   243     ConsoleListener(ContentChild* aChild)
   244     : mChild(aChild) {}
   246     NS_DECL_ISUPPORTS
   247     NS_DECL_NSICONSOLELISTENER
   249 private:
   250     ContentChild* mChild;
   251     friend class ContentChild;
   252 };
   254 NS_IMPL_ISUPPORTS(ConsoleListener, nsIConsoleListener)
   256 NS_IMETHODIMP
   257 ConsoleListener::Observe(nsIConsoleMessage* aMessage)
   258 {
   259     if (!mChild)
   260         return NS_OK;
   262     nsCOMPtr<nsIScriptError> scriptError = do_QueryInterface(aMessage);
   263     if (scriptError) {
   264         nsString msg, sourceName, sourceLine;
   265         nsXPIDLCString category;
   266         uint32_t lineNum, colNum, flags;
   268         nsresult rv = scriptError->GetErrorMessage(msg);
   269         NS_ENSURE_SUCCESS(rv, rv);
   270         rv = scriptError->GetSourceName(sourceName);
   271         NS_ENSURE_SUCCESS(rv, rv);
   272         rv = scriptError->GetSourceLine(sourceLine);
   273         NS_ENSURE_SUCCESS(rv, rv);
   275         // Before we send the error to the parent process (which
   276         // involves copying the memory), truncate any long lines.  CSS
   277         // errors in particular share the memory for long lines with
   278         // repeated errors, but the IPC communication we're about to do
   279         // will break that sharing, so we better truncate now.
   280         if (sourceLine.Length() > 1000) {
   281             sourceLine.Truncate(1000);
   282         }
   284         rv = scriptError->GetCategory(getter_Copies(category));
   285         NS_ENSURE_SUCCESS(rv, rv);
   286         rv = scriptError->GetLineNumber(&lineNum);
   287         NS_ENSURE_SUCCESS(rv, rv);
   288         rv = scriptError->GetColumnNumber(&colNum);
   289         NS_ENSURE_SUCCESS(rv, rv);
   290         rv = scriptError->GetFlags(&flags);
   291         NS_ENSURE_SUCCESS(rv, rv);
   292         mChild->SendScriptError(msg, sourceName, sourceLine,
   293                                lineNum, colNum, flags, category);
   294         return NS_OK;
   295     }
   297     nsXPIDLString msg;
   298     nsresult rv = aMessage->GetMessageMoz(getter_Copies(msg));
   299     NS_ENSURE_SUCCESS(rv, rv);
   300     mChild->SendConsoleMessage(msg);
   301     return NS_OK;
   302 }
   304 class SystemMessageHandledObserver MOZ_FINAL : public nsIObserver
   305 {
   306 public:
   307     NS_DECL_ISUPPORTS
   308     NS_DECL_NSIOBSERVER
   310     void Init();
   311 };
   313 void SystemMessageHandledObserver::Init()
   314 {
   315     nsCOMPtr<nsIObserverService> os =
   316         mozilla::services::GetObserverService();
   318     if (os) {
   319         os->AddObserver(this, "handle-system-messages-done",
   320                         /* ownsWeak */ false);
   321     }
   322 }
   324 NS_IMETHODIMP
   325 SystemMessageHandledObserver::Observe(nsISupports* aSubject,
   326                                       const char* aTopic,
   327                                       const char16_t* aData)
   328 {
   329     if (ContentChild::GetSingleton()) {
   330         ContentChild::GetSingleton()->SendSystemMessageHandled();
   331     }
   332     return NS_OK;
   333 }
   335 NS_IMPL_ISUPPORTS(SystemMessageHandledObserver, nsIObserver)
   337 class BackgroundChildPrimer MOZ_FINAL :
   338   public nsIIPCBackgroundChildCreateCallback
   339 {
   340 public:
   341     BackgroundChildPrimer()
   342     { }
   344     NS_DECL_ISUPPORTS
   346 private:
   347     ~BackgroundChildPrimer()
   348     { }
   350     virtual void
   351     ActorCreated(PBackgroundChild* aActor) MOZ_OVERRIDE
   352     {
   353         MOZ_ASSERT(aActor, "Failed to create a PBackgroundChild actor!");
   354     }
   356     virtual void
   357     ActorFailed() MOZ_OVERRIDE
   358     {
   359         MOZ_CRASH("Failed to create a PBackgroundChild actor!");
   360     }
   361 };
   363 NS_IMPL_ISUPPORTS(BackgroundChildPrimer, nsIIPCBackgroundChildCreateCallback)
   365 ContentChild* ContentChild::sSingleton;
   367 // Performs initialization that is not fork-safe, i.e. that must be done after
   368 // forking from the Nuwa process.
   369 static void
   370 InitOnContentProcessCreated()
   371 {
   372     // This will register cross-process observer.
   373     mozilla::dom::time::InitializeDateCacheCleaner();
   374 }
   376 ContentChild::ContentChild()
   377  : mID(uint64_t(-1))
   378 #ifdef ANDROID
   379    ,mScreenSize(0, 0)
   380 #endif
   381    , mCanOverrideProcessName(true)
   382 {
   383     // This process is a content process, so it's clearly running in
   384     // multiprocess mode!
   385     nsDebugImpl::SetMultiprocessMode("Child");
   386 }
   388 ContentChild::~ContentChild()
   389 {
   390 }
   392 bool
   393 ContentChild::Init(MessageLoop* aIOLoop,
   394                    base::ProcessHandle aParentHandle,
   395                    IPC::Channel* aChannel)
   396 {
   397 #ifdef MOZ_WIDGET_GTK
   398     // sigh
   399     gtk_init(nullptr, nullptr);
   400 #endif
   402 #ifdef MOZ_WIDGET_QT
   403     // sigh, seriously
   404     nsQAppInstance::AddRef();
   405 #endif
   407 #ifdef MOZ_X11
   408     // Do this after initializing GDK, or GDK will install its own handler.
   409     XRE_InstallX11ErrorHandler();
   410 #endif
   412 #ifdef MOZ_NUWA_PROCESS
   413     SetTransport(aChannel);
   414 #endif
   416     NS_ASSERTION(!sSingleton, "only one ContentChild per child");
   418     // Once we start sending IPC messages, we need the thread manager to be
   419     // initialized so we can deal with the responses. Do that here before we
   420     // try to construct the crash reporter.
   421     nsresult rv = nsThreadManager::get()->Init();
   422     if (NS_WARN_IF(NS_FAILED(rv))) {
   423         return false;
   424     }
   426     Open(aChannel, aParentHandle, aIOLoop);
   427     sSingleton = this;
   429 #ifdef MOZ_X11
   430     // Send the parent our X socket to act as a proxy reference for our X
   431     // resources.
   432     int xSocketFd = ConnectionNumber(DefaultXDisplay());
   433     SendBackUpXResources(FileDescriptor(xSocketFd));
   434 #endif
   436 #ifdef MOZ_CRASHREPORTER
   437     SendPCrashReporterConstructor(CrashReporter::CurrentThreadId(),
   438                                   XRE_GetProcessType());
   439 #endif
   441     GetCPOWManager();
   443     InitProcessAttributes();
   445     return true;
   446 }
   448 void
   449 ContentChild::InitProcessAttributes()
   450 {
   451     SendGetProcessAttributes(&mID, &mIsForApp, &mIsForBrowser);
   453 #ifdef MOZ_NUWA_PROCESS
   454     if (IsNuwaProcess()) {
   455         SetProcessName(NS_LITERAL_STRING("(Nuwa)"), false);
   456         return;
   457     }
   458 #endif
   459     if (mIsForApp && !mIsForBrowser) {
   460         SetProcessName(NS_LITERAL_STRING("(Preallocated app)"), false);
   461     } else {
   462         SetProcessName(NS_LITERAL_STRING("Browser"), false);
   463     }
   465 }
   467 void
   468 ContentChild::SetProcessName(const nsAString& aName, bool aDontOverride)
   469 {
   470     if (!mCanOverrideProcessName) {
   471         return;
   472     }
   474     char* name;
   475     if ((name = PR_GetEnv("MOZ_DEBUG_APP_PROCESS")) &&
   476         aName.EqualsASCII(name)) {
   477 #ifdef OS_POSIX
   478         printf_stderr("\n\nCHILDCHILDCHILDCHILD\n  [%s] debug me @%d\n\n", name, getpid());
   479         sleep(30);
   480 #elif defined(OS_WIN)
   481         // Windows has a decent JIT debugging story, so NS_DebugBreak does the
   482         // right thing.
   483         NS_DebugBreak(NS_DEBUG_BREAK,
   484                       "Invoking NS_DebugBreak() to debug child process",
   485                       nullptr, __FILE__, __LINE__);
   486 #endif
   487     }
   489     mProcessName = aName;
   490     mozilla::ipc::SetThisProcessName(NS_LossyConvertUTF16toASCII(aName).get());
   492     if (aDontOverride) {
   493         mCanOverrideProcessName = false;
   494     }
   495 }
   497 void
   498 ContentChild::GetProcessName(nsAString& aName)
   499 {
   500     aName.Assign(mProcessName);
   501 }
   503 void
   504 ContentChild::GetProcessName(nsACString& aName)
   505 {
   506     aName.Assign(NS_ConvertUTF16toUTF8(mProcessName));
   507 }
   509 /* static */ void
   510 ContentChild::AppendProcessId(nsACString& aName)
   511 {
   512     if (!aName.IsEmpty()) {
   513         aName.AppendLiteral(" ");
   514     }
   515     unsigned pid = getpid();
   516     aName.Append(nsPrintfCString("(pid %u)", pid));
   517 }
   519 void
   520 ContentChild::InitXPCOM()
   521 {
   522     // Do this as early as possible to get the parent process to initialize the
   523     // background thread since we'll likely need database information very soon.
   524     BackgroundChild::Startup();
   526     nsCOMPtr<nsIIPCBackgroundChildCreateCallback> callback =
   527         new BackgroundChildPrimer();
   528     if (!BackgroundChild::GetOrCreateForCurrentThread(callback)) {
   529         MOZ_CRASH("Failed to create PBackgroundChild!");
   530     }
   532     nsCOMPtr<nsIConsoleService> svc(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
   533     if (!svc) {
   534         NS_WARNING("Couldn't acquire console service");
   535         return;
   536     }
   538     mConsoleListener = new ConsoleListener(this);
   539     if (NS_FAILED(svc->RegisterListener(mConsoleListener)))
   540         NS_WARNING("Couldn't register console listener for child process");
   542     bool isOffline;
   543     SendGetXPCOMProcessAttributes(&isOffline);
   544     RecvSetOffline(isOffline);
   546     DebugOnly<FileUpdateDispatcher*> observer = FileUpdateDispatcher::GetSingleton();
   547     NS_ASSERTION(observer, "FileUpdateDispatcher is null");
   549     // This object is held alive by the observer service.
   550     nsRefPtr<SystemMessageHandledObserver> sysMsgObserver =
   551         new SystemMessageHandledObserver();
   552     sysMsgObserver->Init();
   554 #ifndef MOZ_NUWA_PROCESS
   555     InitOnContentProcessCreated();
   556 #endif
   557 }
   559 PMemoryReportRequestChild*
   560 ContentChild::AllocPMemoryReportRequestChild(const uint32_t& generation,
   561                                              const bool &minimizeMemoryUsage,
   562                                              const nsString& aDMDDumpIdent)
   563 {
   564     MemoryReportRequestChild *actor = new MemoryReportRequestChild(generation, aDMDDumpIdent);
   565     actor->AddRef();
   566     return actor;
   567 }
   569 // This is just a wrapper for InfallibleTArray<MemoryReport> that implements
   570 // nsISupports, so it can be passed to nsIMemoryReporter::CollectReports.
   571 class MemoryReportsWrapper MOZ_FINAL : public nsISupports {
   572 public:
   573     NS_DECL_ISUPPORTS
   574     MemoryReportsWrapper(InfallibleTArray<MemoryReport> *r) : mReports(r) { }
   575     InfallibleTArray<MemoryReport> *mReports;
   576 };
   577 NS_IMPL_ISUPPORTS0(MemoryReportsWrapper)
   579 class MemoryReportCallback MOZ_FINAL : public nsIMemoryReporterCallback
   580 {
   581 public:
   582     NS_DECL_ISUPPORTS
   584     MemoryReportCallback(const nsACString &aProcess)
   585     : mProcess(aProcess)
   586     {
   587     }
   589     NS_IMETHOD Callback(const nsACString &aProcess, const nsACString &aPath,
   590                         int32_t aKind, int32_t aUnits, int64_t aAmount,
   591                         const nsACString &aDescription,
   592                         nsISupports *aiWrappedReports)
   593     {
   594         MemoryReportsWrapper *wrappedReports =
   595             static_cast<MemoryReportsWrapper *>(aiWrappedReports);
   597         MemoryReport memreport(mProcess, nsCString(aPath), aKind, aUnits,
   598                                aAmount, nsCString(aDescription));
   599         wrappedReports->mReports->AppendElement(memreport);
   600         return NS_OK;
   601     }
   602 private:
   603     const nsCString mProcess;
   604 };
   605 NS_IMPL_ISUPPORTS(
   606   MemoryReportCallback
   607 , nsIMemoryReporterCallback
   608 )
   610 bool
   611 ContentChild::RecvPMemoryReportRequestConstructor(
   612     PMemoryReportRequestChild* child,
   613     const uint32_t& generation,
   614     const bool& minimizeMemoryUsage,
   615     const nsString& aDMDDumpIdent)
   616 {
   617     MemoryReportRequestChild *actor = static_cast<MemoryReportRequestChild*>(child);
   618     nsresult rv;
   620     if (minimizeMemoryUsage) {
   621         nsCOMPtr<nsIMemoryReporterManager> mgr = do_GetService("@mozilla.org/memory-reporter-manager;1");
   622         rv = mgr->MinimizeMemoryUsage(actor);
   623         // mgr will eventually call actor->Run()
   624     } else {
   625         rv = actor->Run();
   626     }
   628     return !NS_WARN_IF(NS_FAILED(rv));
   629 }
   631 NS_IMETHODIMP MemoryReportRequestChild::Run()
   632 {
   633     ContentChild *child = static_cast<ContentChild*>(Manager());
   634     nsCOMPtr<nsIMemoryReporterManager> mgr = do_GetService("@mozilla.org/memory-reporter-manager;1");
   636     InfallibleTArray<MemoryReport> reports;
   638     nsCString process;
   639     child->GetProcessName(process);
   640     child->AppendProcessId(process);
   642     // Run the reporters.  The callback will turn each measurement into a
   643     // MemoryReport.
   644     nsRefPtr<MemoryReportsWrapper> wrappedReports =
   645         new MemoryReportsWrapper(&reports);
   646     nsRefPtr<MemoryReportCallback> cb = new MemoryReportCallback(process);
   647     mgr->GetReportsForThisProcessExtended(cb, wrappedReports, mDMDDumpIdent);
   649     bool sent = Send__delete__(this, mGeneration, reports);
   650     return sent ? NS_OK : NS_ERROR_FAILURE;
   651 }
   653 bool
   654 ContentChild::RecvAudioChannelNotify()
   655 {
   656     nsRefPtr<AudioChannelService> service =
   657         AudioChannelService::GetAudioChannelService();
   658     if (service) {
   659         service->Notify();
   660     }
   661     return true;
   662 }
   664 bool
   665 ContentChild::DeallocPMemoryReportRequestChild(PMemoryReportRequestChild* actor)
   666 {
   667     static_cast<MemoryReportRequestChild*>(actor)->Release();
   668     return true;
   669 }
   671 bool
   672 ContentChild::RecvDumpGCAndCCLogsToFile(const nsString& aIdentifier,
   673                                         const bool& aDumpAllTraces,
   674                                         const bool& aDumpChildProcesses)
   675 {
   676     nsCOMPtr<nsIMemoryInfoDumper> dumper = do_GetService("@mozilla.org/memory-info-dumper;1");
   678     nsString gcLogPath, ccLogPath;
   679     dumper->DumpGCAndCCLogsToFile(aIdentifier, aDumpAllTraces,
   680                                   aDumpChildProcesses, gcLogPath, ccLogPath);
   681     return true;
   682 }
   684 PCompositorChild*
   685 ContentChild::AllocPCompositorChild(mozilla::ipc::Transport* aTransport,
   686                                     base::ProcessId aOtherProcess)
   687 {
   688     return CompositorChild::Create(aTransport, aOtherProcess);
   689 }
   691 PImageBridgeChild*
   692 ContentChild::AllocPImageBridgeChild(mozilla::ipc::Transport* aTransport,
   693                                      base::ProcessId aOtherProcess)
   694 {
   695     return ImageBridgeChild::StartUpInChildProcess(aTransport, aOtherProcess);
   696 }
   698 PBackgroundChild*
   699 ContentChild::AllocPBackgroundChild(Transport* aTransport,
   700                                     ProcessId aOtherProcess)
   701 {
   702     return BackgroundChild::Alloc(aTransport, aOtherProcess);
   703 }
   705 bool
   706 ContentChild::RecvSetProcessSandbox()
   707 {
   708   // We may want to move the sandbox initialization somewhere else
   709   // at some point; see bug 880808.
   710 #if defined(MOZ_CONTENT_SANDBOX)
   711 #if defined(XP_LINUX)
   712   SetCurrentProcessSandbox();
   713 #elif defined(XP_WIN)
   714   mozilla::SandboxTarget::Instance()->StartSandbox();
   715 #endif
   716 #endif
   717   return true;
   718 }
   720 bool
   721 ContentChild::RecvSpeakerManagerNotify()
   722 {
   723 #ifdef MOZ_WIDGET_GONK
   724   nsRefPtr<SpeakerManagerService> service =
   725     SpeakerManagerService::GetSpeakerManagerService();
   726   if (service) {
   727     service->Notify();
   728   }
   729   return true;
   730 #endif
   731   return false;
   732 }
   734 static CancelableTask* sFirstIdleTask;
   736 static void FirstIdle(void)
   737 {
   738     MOZ_ASSERT(sFirstIdleTask);
   739     sFirstIdleTask = nullptr;
   740     ContentChild::GetSingleton()->SendFirstIdle();
   741 }
   743 mozilla::jsipc::PJavaScriptChild *
   744 ContentChild::AllocPJavaScriptChild()
   745 {
   746     nsCOMPtr<nsIJSRuntimeService> svc = do_GetService("@mozilla.org/js/xpc/RuntimeService;1");
   747     NS_ENSURE_TRUE(svc, nullptr);
   749     JSRuntime *rt;
   750     svc->GetRuntime(&rt);
   751     NS_ENSURE_TRUE(svc, nullptr);
   753     mozilla::jsipc::JavaScriptChild *child = new mozilla::jsipc::JavaScriptChild(rt);
   754     if (!child->init()) {
   755         delete child;
   756         return nullptr;
   757     }
   758     return child;
   759 }
   761 bool
   762 ContentChild::DeallocPJavaScriptChild(PJavaScriptChild *child)
   763 {
   764     delete child;
   765     return true;
   766 }
   768 PBrowserChild*
   769 ContentChild::AllocPBrowserChild(const IPCTabContext& aContext,
   770                                  const uint32_t& aChromeFlags)
   771 {
   772     // We'll happily accept any kind of IPCTabContext here; we don't need to
   773     // check that it's of a certain type for security purposes, because we
   774     // believe whatever the parent process tells us.
   776     MaybeInvalidTabContext tc(aContext);
   777     if (!tc.IsValid()) {
   778         NS_ERROR(nsPrintfCString("Received an invalid TabContext from "
   779                                  "the parent process. (%s)  Crashing...",
   780                                  tc.GetInvalidReason()).get());
   781         MOZ_CRASH("Invalid TabContext received from the parent process.");
   782     }
   784     nsRefPtr<TabChild> child = TabChild::Create(this, tc.GetTabContext(), aChromeFlags);
   786     // The ref here is released in DeallocPBrowserChild.
   787     return child.forget().take();
   788 }
   790 bool
   791 ContentChild::RecvPBrowserConstructor(PBrowserChild* actor,
   792                                       const IPCTabContext& context,
   793                                       const uint32_t& chromeFlags)
   794 {
   795     // This runs after AllocPBrowserChild() returns and the IPC machinery for this
   796     // PBrowserChild has been set up.
   798     nsCOMPtr<nsIObserverService> os = services::GetObserverService();
   799     if (os) {
   800         nsITabChild* tc =
   801             static_cast<nsITabChild*>(static_cast<TabChild*>(actor));
   802         os->NotifyObservers(tc, "tab-child-created", nullptr);
   803     }
   805     static bool hasRunOnce = false;
   806     if (!hasRunOnce) {
   807         hasRunOnce = true;
   809         MOZ_ASSERT(!sFirstIdleTask);
   810         sFirstIdleTask = NewRunnableFunction(FirstIdle);
   811         MessageLoop::current()->PostIdleTask(FROM_HERE, sFirstIdleTask);
   813         // Redo InitProcessAttributes() when the app or browser is really
   814         // launching so the attributes will be correct.
   815         InitProcessAttributes();
   816     }
   818     return true;
   819 }
   821 PFileDescriptorSetChild*
   822 ContentChild::AllocPFileDescriptorSetChild(const FileDescriptor& aFD)
   823 {
   824     return new FileDescriptorSetChild(aFD);
   825 }
   827 bool
   828 ContentChild::DeallocPFileDescriptorSetChild(PFileDescriptorSetChild* aActor)
   829 {
   830     delete static_cast<FileDescriptorSetChild*>(aActor);
   831     return true;
   832 }
   834 bool
   835 ContentChild::DeallocPBrowserChild(PBrowserChild* iframe)
   836 {
   837     TabChild* child = static_cast<TabChild*>(iframe);
   838     NS_RELEASE(child);
   839     return true;
   840 }
   842 PBlobChild*
   843 ContentChild::AllocPBlobChild(const BlobConstructorParams& aParams)
   844 {
   845   return BlobChild::Create(this, aParams);
   846 }
   848 bool
   849 ContentChild::DeallocPBlobChild(PBlobChild* aActor)
   850 {
   851   delete aActor;
   852   return true;
   853 }
   855 BlobChild*
   856 ContentChild::GetOrCreateActorForBlob(nsIDOMBlob* aBlob)
   857 {
   858   MOZ_ASSERT(NS_IsMainThread());
   859   MOZ_ASSERT(aBlob);
   861   // If the blob represents a remote blob then we can simply pass its actor back
   862   // here.
   863   if (nsCOMPtr<nsIRemoteBlob> remoteBlob = do_QueryInterface(aBlob)) {
   864     BlobChild* actor =
   865       static_cast<BlobChild*>(
   866         static_cast<PBlobChild*>(remoteBlob->GetPBlob()));
   867     MOZ_ASSERT(actor);
   868     return actor;
   869   }
   871   // XXX This is only safe so long as all blob implementations in our tree
   872   //     inherit nsDOMFileBase. If that ever changes then this will need to grow
   873   //     a real interface or something.
   874   const nsDOMFileBase* blob = static_cast<nsDOMFileBase*>(aBlob);
   876   // We often pass blobs that are multipart but that only contain one sub-blob
   877   // (WebActivities does this a bunch). Unwrap to reduce the number of actors
   878   // that we have to maintain.
   879   const nsTArray<nsCOMPtr<nsIDOMBlob> >* subBlobs = blob->GetSubBlobs();
   880   if (subBlobs && subBlobs->Length() == 1) {
   881     const nsCOMPtr<nsIDOMBlob>& subBlob = subBlobs->ElementAt(0);
   882     MOZ_ASSERT(subBlob);
   884     // We can only take this shortcut if the multipart and the sub-blob are both
   885     // Blob objects or both File objects.
   886     nsCOMPtr<nsIDOMFile> multipartBlobAsFile = do_QueryInterface(aBlob);
   887     nsCOMPtr<nsIDOMFile> subBlobAsFile = do_QueryInterface(subBlob);
   888     if (!multipartBlobAsFile == !subBlobAsFile) {
   889       // The wrapping was unnecessary, see if we can simply pass an existing
   890       // remote blob.
   891       if (nsCOMPtr<nsIRemoteBlob> remoteBlob = do_QueryInterface(subBlob)) {
   892         BlobChild* actor =
   893           static_cast<BlobChild*>(
   894             static_cast<PBlobChild*>(remoteBlob->GetPBlob()));
   895         MOZ_ASSERT(actor);
   896         return actor;
   897       }
   899       // No need to add a reference here since the original blob must have a
   900       // strong reference in the caller and it must also have a strong reference
   901       // to this sub-blob.
   902       aBlob = subBlob;
   903       blob = static_cast<nsDOMFileBase*>(aBlob);
   904       subBlobs = blob->GetSubBlobs();
   905     }
   906   }
   908   // All blobs shared between processes must be immutable.
   909   nsCOMPtr<nsIMutable> mutableBlob = do_QueryInterface(aBlob);
   910   if (!mutableBlob || NS_FAILED(mutableBlob->SetMutable(false))) {
   911     NS_WARNING("Failed to make blob immutable!");
   912     return nullptr;
   913   }
   915   ParentBlobConstructorParams params;
   917   if (blob->IsSizeUnknown() || blob->IsDateUnknown()) {
   918     // We don't want to call GetSize or GetLastModifiedDate
   919     // yet since that may stat a file on the main thread
   920     // here. Instead we'll learn the size lazily from the
   921     // other process.
   922     params.blobParams() = MysteryBlobConstructorParams();
   923     params.optionalInputStreamParams() = void_t();
   924   }
   925   else {
   926     nsString contentType;
   927     nsresult rv = aBlob->GetType(contentType);
   928     NS_ENSURE_SUCCESS(rv, nullptr);
   930     uint64_t length;
   931     rv = aBlob->GetSize(&length);
   932     NS_ENSURE_SUCCESS(rv, nullptr);
   934     nsCOMPtr<nsIInputStream> stream;
   935     rv = aBlob->GetInternalStream(getter_AddRefs(stream));
   936     NS_ENSURE_SUCCESS(rv, nullptr);
   938     InputStreamParams inputStreamParams;
   939     nsTArray<mozilla::ipc::FileDescriptor> fds;
   940     SerializeInputStream(stream, inputStreamParams, fds);
   941     MOZ_ASSERT(fds.IsEmpty());
   943     params.optionalInputStreamParams() = inputStreamParams;
   945     nsCOMPtr<nsIDOMFile> file = do_QueryInterface(aBlob);
   946     if (file) {
   947       FileBlobConstructorParams fileParams;
   949       rv = file->GetName(fileParams.name());
   950       NS_ENSURE_SUCCESS(rv, nullptr);
   952       rv = file->GetMozLastModifiedDate(&fileParams.modDate());
   953       NS_ENSURE_SUCCESS(rv, nullptr);
   955       fileParams.contentType() = contentType;
   956       fileParams.length() = length;
   958       params.blobParams() = fileParams;
   959     } else {
   960       NormalBlobConstructorParams blobParams;
   961       blobParams.contentType() = contentType;
   962       blobParams.length() = length;
   963       params.blobParams() = blobParams;
   964     }
   965   }
   967   BlobChild* actor = BlobChild::Create(this, aBlob);
   968   NS_ENSURE_TRUE(actor, nullptr);
   970   return SendPBlobConstructor(actor, params) ? actor : nullptr;
   971 }
   973 PCrashReporterChild*
   974 ContentChild::AllocPCrashReporterChild(const mozilla::dom::NativeThreadId& id,
   975                                        const uint32_t& processType)
   976 {
   977 #ifdef MOZ_CRASHREPORTER
   978     return new CrashReporterChild();
   979 #else
   980     return nullptr;
   981 #endif
   982 }
   984 bool
   985 ContentChild::DeallocPCrashReporterChild(PCrashReporterChild* crashreporter)
   986 {
   987     delete crashreporter;
   988     return true;
   989 }
   991 PHalChild*
   992 ContentChild::AllocPHalChild()
   993 {
   994     return CreateHalChild();
   995 }
   997 bool
   998 ContentChild::DeallocPHalChild(PHalChild* aHal)
   999 {
  1000     delete aHal;
  1001     return true;
  1004 PIndexedDBChild*
  1005 ContentChild::AllocPIndexedDBChild()
  1007   NS_NOTREACHED("Should never get here!");
  1008   return nullptr;
  1011 bool
  1012 ContentChild::DeallocPIndexedDBChild(PIndexedDBChild* aActor)
  1014   delete aActor;
  1015   return true;
  1018 asmjscache::PAsmJSCacheEntryChild*
  1019 ContentChild::AllocPAsmJSCacheEntryChild(
  1020                                     const asmjscache::OpenMode& aOpenMode,
  1021                                     const asmjscache::WriteParams& aWriteParams,
  1022                                     const IPC::Principal& aPrincipal)
  1024   NS_NOTREACHED("Should never get here!");
  1025   return nullptr;
  1028 bool
  1029 ContentChild::DeallocPAsmJSCacheEntryChild(PAsmJSCacheEntryChild* aActor)
  1031   asmjscache::DeallocEntryChild(aActor);
  1032   return true;
  1035 PTestShellChild*
  1036 ContentChild::AllocPTestShellChild()
  1038     return new TestShellChild();
  1041 bool
  1042 ContentChild::DeallocPTestShellChild(PTestShellChild* shell)
  1044     delete shell;
  1045     return true;
  1048 jsipc::JavaScriptChild *
  1049 ContentChild::GetCPOWManager()
  1051     if (ManagedPJavaScriptChild().Length()) {
  1052         return static_cast<JavaScriptChild*>(ManagedPJavaScriptChild()[0]);
  1054     JavaScriptChild* actor = static_cast<JavaScriptChild*>(SendPJavaScriptConstructor());
  1055     return actor;
  1058 bool
  1059 ContentChild::RecvPTestShellConstructor(PTestShellChild* actor)
  1061     return true;
  1064 PDeviceStorageRequestChild*
  1065 ContentChild::AllocPDeviceStorageRequestChild(const DeviceStorageParams& aParams)
  1067     return new DeviceStorageRequestChild();
  1070 bool
  1071 ContentChild::DeallocPDeviceStorageRequestChild(PDeviceStorageRequestChild* aDeviceStorage)
  1073     delete aDeviceStorage;
  1074     return true;
  1077 PFileSystemRequestChild*
  1078 ContentChild::AllocPFileSystemRequestChild(const FileSystemParams& aParams)
  1080     NS_NOTREACHED("Should never get here!");
  1081     return nullptr;
  1084 bool
  1085 ContentChild::DeallocPFileSystemRequestChild(PFileSystemRequestChild* aFileSystem)
  1087     mozilla::dom::FileSystemTaskBase* child =
  1088       static_cast<mozilla::dom::FileSystemTaskBase*>(aFileSystem);
  1089     // The reference is increased in FileSystemTaskBase::Start of
  1090     // FileSystemTaskBase.cpp. We should decrease it after IPC.
  1091     NS_RELEASE(child);
  1092     return true;
  1095 PNeckoChild*
  1096 ContentChild::AllocPNeckoChild()
  1098     return new NeckoChild();
  1101 bool
  1102 ContentChild::DeallocPNeckoChild(PNeckoChild* necko)
  1104     delete necko;
  1105     return true;
  1108 PExternalHelperAppChild*
  1109 ContentChild::AllocPExternalHelperAppChild(const OptionalURIParams& uri,
  1110                                            const nsCString& aMimeContentType,
  1111                                            const nsCString& aContentDisposition,
  1112                                            const uint32_t& aContentDispositionHint,
  1113                                            const nsString& aContentDispositionFilename,
  1114                                            const bool& aForceSave,
  1115                                            const int64_t& aContentLength,
  1116                                            const OptionalURIParams& aReferrer,
  1117                                            PBrowserChild* aBrowser)
  1119     ExternalHelperAppChild *child = new ExternalHelperAppChild();
  1120     child->AddRef();
  1121     return child;
  1124 bool
  1125 ContentChild::DeallocPExternalHelperAppChild(PExternalHelperAppChild* aService)
  1127     ExternalHelperAppChild *child = static_cast<ExternalHelperAppChild*>(aService);
  1128     child->Release();
  1129     return true;
  1132 PSmsChild*
  1133 ContentChild::AllocPSmsChild()
  1135     return new SmsChild();
  1138 bool
  1139 ContentChild::DeallocPSmsChild(PSmsChild* aSms)
  1141     delete aSms;
  1142     return true;
  1145 PTelephonyChild*
  1146 ContentChild::AllocPTelephonyChild()
  1148     MOZ_CRASH("No one should be allocating PTelephonyChild actors");
  1151 bool
  1152 ContentChild::DeallocPTelephonyChild(PTelephonyChild* aActor)
  1154     delete aActor;
  1155     return true;
  1158 PStorageChild*
  1159 ContentChild::AllocPStorageChild()
  1161     NS_NOTREACHED("We should never be manually allocating PStorageChild actors");
  1162     return nullptr;
  1165 bool
  1166 ContentChild::DeallocPStorageChild(PStorageChild* aActor)
  1168     DOMStorageDBChild* child = static_cast<DOMStorageDBChild*>(aActor);
  1169     child->ReleaseIPDLReference();
  1170     return true;
  1173 PBluetoothChild*
  1174 ContentChild::AllocPBluetoothChild()
  1176 #ifdef MOZ_B2G_BT
  1177     MOZ_CRASH("No one should be allocating PBluetoothChild actors");
  1178 #else
  1179     MOZ_CRASH("No support for bluetooth on this platform!");
  1180 #endif
  1183 bool
  1184 ContentChild::DeallocPBluetoothChild(PBluetoothChild* aActor)
  1186 #ifdef MOZ_B2G_BT
  1187     delete aActor;
  1188     return true;
  1189 #else
  1190     MOZ_CRASH("No support for bluetooth on this platform!");
  1191 #endif
  1194 PFMRadioChild*
  1195 ContentChild::AllocPFMRadioChild()
  1197 #ifdef MOZ_B2G_FM
  1198     NS_RUNTIMEABORT("No one should be allocating PFMRadioChild actors");
  1199     return nullptr;
  1200 #else
  1201     NS_RUNTIMEABORT("No support for FMRadio on this platform!");
  1202     return nullptr;
  1203 #endif
  1206 bool
  1207 ContentChild::DeallocPFMRadioChild(PFMRadioChild* aActor)
  1209 #ifdef MOZ_B2G_FM
  1210     delete aActor;
  1211     return true;
  1212 #else
  1213     NS_RUNTIMEABORT("No support for FMRadio on this platform!");
  1214     return false;
  1215 #endif
  1218 PSpeechSynthesisChild*
  1219 ContentChild::AllocPSpeechSynthesisChild()
  1221 #ifdef MOZ_WEBSPEECH
  1222     MOZ_CRASH("No one should be allocating PSpeechSynthesisChild actors");
  1223 #else
  1224     return nullptr;
  1225 #endif
  1228 bool
  1229 ContentChild::DeallocPSpeechSynthesisChild(PSpeechSynthesisChild* aActor)
  1231 #ifdef MOZ_WEBSPEECH
  1232     delete aActor;
  1233     return true;
  1234 #else
  1235     return false;
  1236 #endif
  1239 bool
  1240 ContentChild::RecvRegisterChrome(const InfallibleTArray<ChromePackage>& packages,
  1241                                  const InfallibleTArray<ResourceMapping>& resources,
  1242                                  const InfallibleTArray<OverrideMapping>& overrides,
  1243                                  const nsCString& locale)
  1245     nsCOMPtr<nsIChromeRegistry> registrySvc = nsChromeRegistry::GetService();
  1246     nsChromeRegistryContent* chromeRegistry =
  1247         static_cast<nsChromeRegistryContent*>(registrySvc.get());
  1248     chromeRegistry->RegisterRemoteChrome(packages, resources, overrides, locale);
  1249     return true;
  1252 bool
  1253 ContentChild::RecvSetOffline(const bool& offline)
  1255   nsCOMPtr<nsIIOService> io (do_GetIOService());
  1256   NS_ASSERTION(io, "IO Service can not be null");
  1258   io->SetOffline(offline);
  1260   return true;
  1263 void
  1264 ContentChild::ActorDestroy(ActorDestroyReason why)
  1266     if (AbnormalShutdown == why) {
  1267         NS_WARNING("shutting down early because of crash!");
  1268         QuickExit();
  1271 #ifndef DEBUG
  1272     // In release builds, there's no point in the content process
  1273     // going through the full XPCOM shutdown path, because it doesn't
  1274     // keep persistent state.
  1275     QuickExit();
  1276 #endif
  1278     if (sFirstIdleTask) {
  1279         sFirstIdleTask->Cancel();
  1282     mAlertObservers.Clear();
  1284     mIdleObservers.Clear();
  1286     nsCOMPtr<nsIConsoleService> svc(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
  1287     if (svc) {
  1288         svc->UnregisterListener(mConsoleListener);
  1289         mConsoleListener->mChild = nullptr;
  1292     XRE_ShutdownChildProcess();
  1295 void
  1296 ContentChild::ProcessingError(Result what)
  1298     switch (what) {
  1299     case MsgDropped:
  1300         QuickExit();
  1302     case MsgNotKnown:
  1303         NS_RUNTIMEABORT("aborting because of MsgNotKnown");
  1304     case MsgNotAllowed:
  1305         NS_RUNTIMEABORT("aborting because of MsgNotAllowed");
  1306     case MsgPayloadError:
  1307         NS_RUNTIMEABORT("aborting because of MsgPayloadError");
  1308     case MsgProcessingError:
  1309         NS_RUNTIMEABORT("aborting because of MsgProcessingError");
  1310     case MsgRouteError:
  1311         NS_RUNTIMEABORT("aborting because of MsgRouteError");
  1312     case MsgValueError:
  1313         NS_RUNTIMEABORT("aborting because of MsgValueError");
  1315     default:
  1316         NS_RUNTIMEABORT("not reached");
  1320 void
  1321 ContentChild::QuickExit()
  1323     NS_WARNING("content process _exit()ing");
  1324     _exit(0);
  1327 nsresult
  1328 ContentChild::AddRemoteAlertObserver(const nsString& aData,
  1329                                      nsIObserver* aObserver)
  1331     NS_ASSERTION(aObserver, "Adding a null observer?");
  1332     mAlertObservers.AppendElement(new AlertObserver(aObserver, aData));
  1333     return NS_OK;
  1336 bool
  1337 ContentChild::RecvPreferenceUpdate(const PrefSetting& aPref)
  1339     Preferences::SetPreference(aPref);
  1340     return true;
  1343 bool
  1344 ContentChild::RecvNotifyAlertsObserver(const nsCString& aType, const nsString& aData)
  1346     for (uint32_t i = 0; i < mAlertObservers.Length();
  1347          /*we mutate the array during the loop; ++i iff no mutation*/) {
  1348         AlertObserver* observer = mAlertObservers[i];
  1349         if (observer->Observes(aData) && observer->Notify(aType)) {
  1350             // if aType == alertfinished, this alert is done.  we can
  1351             // remove the observer.
  1352             if (aType.Equals(nsDependentCString("alertfinished"))) {
  1353                 mAlertObservers.RemoveElementAt(i);
  1354                 continue;
  1357         ++i;
  1359     return true;
  1362 bool
  1363 ContentChild::RecvNotifyVisited(const URIParams& aURI)
  1365     nsCOMPtr<nsIURI> newURI = DeserializeURI(aURI);
  1366     if (!newURI) {
  1367         return false;
  1369     nsCOMPtr<IHistory> history = services::GetHistoryService();
  1370     if (history) {
  1371       history->NotifyVisited(newURI);
  1373     return true;
  1376 bool
  1377 ContentChild::RecvAsyncMessage(const nsString& aMsg,
  1378                                const ClonedMessageData& aData,
  1379                                const InfallibleTArray<CpowEntry>& aCpows,
  1380                                const IPC::Principal& aPrincipal)
  1382   nsRefPtr<nsFrameMessageManager> cpm = nsFrameMessageManager::sChildProcessManager;
  1383   if (cpm) {
  1384     StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForChild(aData);
  1385     CpowIdHolder cpows(GetCPOWManager(), aCpows);
  1386     cpm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(cpm.get()),
  1387                         aMsg, false, &cloneData, &cpows, aPrincipal, nullptr);
  1389   return true;
  1392 bool
  1393 ContentChild::RecvGeolocationUpdate(const GeoPosition& somewhere)
  1395   nsCOMPtr<nsIGeolocationUpdate> gs = do_GetService("@mozilla.org/geolocation/service;1");
  1396   if (!gs) {
  1397     return true;
  1399   nsCOMPtr<nsIDOMGeoPosition> position = somewhere;
  1400   gs->Update(position);
  1401   return true;
  1404 bool
  1405 ContentChild::RecvAddPermission(const IPC::Permission& permission)
  1407 #if MOZ_PERMISSIONS
  1408   nsCOMPtr<nsIPermissionManager> permissionManagerIface =
  1409       do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
  1410   nsPermissionManager* permissionManager =
  1411       static_cast<nsPermissionManager*>(permissionManagerIface.get());
  1412   NS_ABORT_IF_FALSE(permissionManager, 
  1413                    "We have no permissionManager in the Content process !");
  1415   nsCOMPtr<nsIURI> uri;
  1416   NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("http://") + nsCString(permission.host));
  1417   NS_ENSURE_TRUE(uri, true);
  1419   nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
  1420   MOZ_ASSERT(secMan);
  1422   nsCOMPtr<nsIPrincipal> principal;
  1423   nsresult rv = secMan->GetAppCodebasePrincipal(uri, permission.appId,
  1424                                                 permission.isInBrowserElement,
  1425                                                 getter_AddRefs(principal));
  1426   NS_ENSURE_SUCCESS(rv, true);
  1428   permissionManager->AddInternal(principal,
  1429                                  nsCString(permission.type),
  1430                                  permission.capability,
  1431                                  0,
  1432                                  permission.expireType,
  1433                                  permission.expireTime,
  1434                                  nsPermissionManager::eNotify,
  1435                                  nsPermissionManager::eNoDBOperation);
  1436 #endif
  1438   return true;
  1441 bool
  1442 ContentChild::RecvScreenSizeChanged(const gfxIntSize& size)
  1444 #ifdef ANDROID
  1445     mScreenSize = size;
  1446 #else
  1447     NS_RUNTIMEABORT("Message currently only expected on android");
  1448 #endif
  1449   return true;
  1452 bool
  1453 ContentChild::RecvFlushMemory(const nsString& reason)
  1455 #ifdef MOZ_NUWA_PROCESS
  1456     if (IsNuwaProcess()) {
  1457         // Don't flush memory in the nuwa process: the GC thread could be frozen.
  1458         return true;
  1460 #endif
  1461     nsCOMPtr<nsIObserverService> os =
  1462         mozilla::services::GetObserverService();
  1463     if (os)
  1464         os->NotifyObservers(nullptr, "memory-pressure", reason.get());
  1465     return true;
  1468 bool
  1469 ContentChild::RecvActivateA11y()
  1471 #ifdef ACCESSIBILITY
  1472     // Start accessibility in content process if it's running in chrome
  1473     // process.
  1474     nsCOMPtr<nsIAccessibilityService> accService =
  1475         do_GetService("@mozilla.org/accessibilityService;1");
  1476 #endif
  1477     return true;
  1480 bool
  1481 ContentChild::RecvGarbageCollect()
  1483     // Rebroadcast the "child-gc-request" so that workers will GC.
  1484     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
  1485     if (obs) {
  1486         obs->NotifyObservers(nullptr, "child-gc-request", nullptr);
  1488     nsJSContext::GarbageCollectNow(JS::gcreason::DOM_IPC);
  1489     return true;
  1492 bool
  1493 ContentChild::RecvCycleCollect()
  1495     // Rebroadcast the "child-cc-request" so that workers will CC.
  1496     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
  1497     if (obs) {
  1498         obs->NotifyObservers(nullptr, "child-cc-request", nullptr);
  1500     nsJSContext::CycleCollectNow();
  1501     return true;
  1504 #ifdef MOZ_NUWA_PROCESS
  1505 static void
  1506 OnFinishNuwaPreparation ()
  1508     MakeNuwaProcess();
  1510 #endif
  1512 static void
  1513 PreloadSlowThings()
  1515     // This fetches and creates all the built-in stylesheets.
  1516     nsLayoutStylesheetCache::UserContentSheet();
  1518     TabChild::PreloadSlowThings();
  1522 bool
  1523 ContentChild::RecvAppInfo(const nsCString& version, const nsCString& buildID,
  1524                           const nsCString& name, const nsCString& UAName)
  1526     mAppInfo.version.Assign(version);
  1527     mAppInfo.buildID.Assign(buildID);
  1528     mAppInfo.name.Assign(name);
  1529     mAppInfo.UAName.Assign(UAName);
  1531     if (!Preferences::GetBool("dom.ipc.processPrelaunch.enabled", false)) {
  1532         return true;
  1535     // If we're part of the mozbrowser machinery, go ahead and start
  1536     // preloading things.  We can only do this for mozbrowser because
  1537     // PreloadSlowThings() may set the docshell of the first TabChild
  1538     // inactive, and we can only safely restore it to active from
  1539     // BrowserElementChild.js.
  1540     if ((mIsForApp || mIsForBrowser)
  1541 #ifdef MOZ_NUWA_PROCESS
  1542         && !IsNuwaProcess()
  1543 #endif
  1544        ) {
  1545         PreloadSlowThings();
  1548 #ifdef MOZ_NUWA_PROCESS
  1549     if (IsNuwaProcess()) {
  1550         ContentChild::GetSingleton()->RecvGarbageCollect();
  1551         MessageLoop::current()->PostTask(
  1552             FROM_HERE, NewRunnableFunction(OnFinishNuwaPreparation));
  1554 #endif
  1556     return true;
  1559 bool
  1560 ContentChild::RecvLastPrivateDocShellDestroyed()
  1562     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
  1563     obs->NotifyObservers(nullptr, "last-pb-context-exited", nullptr);
  1564     return true;
  1567 bool
  1568 ContentChild::RecvFilePathUpdate(const nsString& aStorageType,
  1569                                  const nsString& aStorageName,
  1570                                  const nsString& aPath,
  1571                                  const nsCString& aReason)
  1573     nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(aStorageType, aStorageName, aPath);
  1575     nsString reason;
  1576     CopyASCIItoUTF16(aReason, reason);
  1577     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
  1578     obs->NotifyObservers(dsf, "file-watcher-update", reason.get());
  1579     return true;
  1582 bool
  1583 ContentChild::RecvFileSystemUpdate(const nsString& aFsName,
  1584                                    const nsString& aVolumeName,
  1585                                    const int32_t& aState,
  1586                                    const int32_t& aMountGeneration,
  1587                                    const bool& aIsMediaPresent,
  1588                                    const bool& aIsSharing,
  1589                                    const bool& aIsFormatting)
  1591 #ifdef MOZ_WIDGET_GONK
  1592     nsRefPtr<nsVolume> volume = new nsVolume(aFsName, aVolumeName, aState,
  1593                                              aMountGeneration, aIsMediaPresent,
  1594                                              aIsSharing, aIsFormatting);
  1596     nsRefPtr<nsVolumeService> vs = nsVolumeService::GetSingleton();
  1597     if (vs) {
  1598         vs->UpdateVolume(volume);
  1600 #else
  1601     // Remove warnings about unused arguments
  1602     unused << aFsName;
  1603     unused << aVolumeName;
  1604     unused << aState;
  1605     unused << aMountGeneration;
  1606     unused << aIsMediaPresent;
  1607     unused << aIsSharing;
  1608     unused << aIsFormatting;
  1609 #endif
  1610     return true;
  1613 bool
  1614 ContentChild::RecvNotifyProcessPriorityChanged(
  1615     const hal::ProcessPriority& aPriority)
  1617     nsCOMPtr<nsIObserverService> os = services::GetObserverService();
  1618     NS_ENSURE_TRUE(os, true);
  1620     nsRefPtr<nsHashPropertyBag> props = new nsHashPropertyBag();
  1621     props->SetPropertyAsInt32(NS_LITERAL_STRING("priority"),
  1622                               static_cast<int32_t>(aPriority));
  1624     os->NotifyObservers(static_cast<nsIPropertyBag2*>(props),
  1625                         "ipc:process-priority-changed",  nullptr);
  1626     return true;
  1629 bool
  1630 ContentChild::RecvMinimizeMemoryUsage()
  1632 #ifdef MOZ_NUWA_PROCESS
  1633     if (IsNuwaProcess()) {
  1634         // Don't minimize memory in the nuwa process: it will perform GC, but the
  1635         // GC thread could be frozen.
  1636         return true;
  1638 #endif
  1639     nsCOMPtr<nsIMemoryReporterManager> mgr =
  1640         do_GetService("@mozilla.org/memory-reporter-manager;1");
  1641     NS_ENSURE_TRUE(mgr, true);
  1643     mgr->MinimizeMemoryUsage(/* callback = */ nullptr);
  1644     return true;
  1647 bool
  1648 ContentChild::RecvNotifyPhoneStateChange(const nsString& aState)
  1650   nsCOMPtr<nsIObserverService> os = services::GetObserverService();
  1651   if (os) {
  1652     os->NotifyObservers(nullptr, "phone-state-changed", aState.get());
  1654   return true;
  1657 void
  1658 ContentChild::AddIdleObserver(nsIObserver* aObserver, uint32_t aIdleTimeInS)
  1660   MOZ_ASSERT(aObserver, "null idle observer");
  1661   // Make sure aObserver isn't released while we wait for the parent
  1662   aObserver->AddRef();
  1663   SendAddIdleObserver(reinterpret_cast<uint64_t>(aObserver), aIdleTimeInS);
  1664   mIdleObservers.PutEntry(aObserver);
  1667 void
  1668 ContentChild::RemoveIdleObserver(nsIObserver* aObserver, uint32_t aIdleTimeInS)
  1670   MOZ_ASSERT(aObserver, "null idle observer");
  1671   SendRemoveIdleObserver(reinterpret_cast<uint64_t>(aObserver), aIdleTimeInS);
  1672   aObserver->Release();
  1673   mIdleObservers.RemoveEntry(aObserver);
  1676 bool
  1677 ContentChild::RecvNotifyIdleObserver(const uint64_t& aObserver,
  1678                                      const nsCString& aTopic,
  1679                                      const nsString& aTimeStr)
  1681   nsIObserver* observer = reinterpret_cast<nsIObserver*>(aObserver);
  1682   if (mIdleObservers.Contains(observer)) {
  1683     observer->Observe(nullptr, aTopic.get(), aTimeStr.get());
  1684   } else {
  1685     NS_WARNING("Received notification for an idle observer that was removed.");
  1687   return true;
  1690 bool
  1691 ContentChild::RecvLoadAndRegisterSheet(const URIParams& aURI, const uint32_t& aType)
  1693     nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
  1694     if (!uri) {
  1695         return true;
  1698     nsStyleSheetService *sheetService = nsStyleSheetService::GetInstance();
  1699     if (sheetService) {
  1700         sheetService->LoadAndRegisterSheet(uri, aType);
  1703     return true;
  1706 bool
  1707 ContentChild::RecvUnregisterSheet(const URIParams& aURI, const uint32_t& aType)
  1709     nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
  1710     if (!uri) {
  1711         return true;
  1714     nsStyleSheetService *sheetService = nsStyleSheetService::GetInstance();
  1715     if (sheetService) {
  1716         sheetService->UnregisterSheet(uri, aType);
  1719     return true;
  1722 #ifdef MOZ_NUWA_PROCESS
  1723 class CallNuwaSpawn : public nsRunnable
  1725 public:
  1726     NS_IMETHOD Run()
  1728         NuwaSpawn();
  1729         if (IsNuwaProcess()) {
  1730             return NS_OK;
  1733         // In the new process.
  1734         ContentChild* child = ContentChild::GetSingleton();
  1735         child->SetProcessName(NS_LITERAL_STRING("(Preallocated app)"), false);
  1736         mozilla::ipc::Transport* transport = child->GetTransport();
  1737         int fd = transport->GetFileDescriptor();
  1738         transport->ResetFileDescriptor(fd);
  1740         IToplevelProtocol* toplevel = child->GetFirstOpenedActors();
  1741         while (toplevel != nullptr) {
  1742             transport = toplevel->GetTransport();
  1743             fd = transport->GetFileDescriptor();
  1744             transport->ResetFileDescriptor(fd);
  1746             toplevel = toplevel->getNext();
  1749         // Perform other after-fork initializations.
  1750         InitOnContentProcessCreated();
  1752         return NS_OK;
  1754 };
  1756 static void
  1757 DoNuwaFork()
  1759     NS_ASSERTION(NuwaSpawnPrepare != nullptr,
  1760                  "NuwaSpawnPrepare() is not available!");
  1761     NuwaSpawnPrepare();       // NuwaSpawn will be blocked.
  1764         nsCOMPtr<nsIRunnable> callSpawn(new CallNuwaSpawn());
  1765         NS_DispatchToMainThread(callSpawn);
  1768     // IOThread should be blocked here for waiting NuwaSpawn().
  1769     NS_ASSERTION(NuwaSpawnWait != nullptr,
  1770                  "NuwaSpawnWait() is not available!");
  1771     NuwaSpawnWait();        // Now! NuwaSpawn can go.
  1772     // Here, we can make sure the spawning was finished.
  1775 /**
  1776  * This function should keep IO thread in a stable state and freeze it
  1777  * until the spawning is finished.
  1778  */
  1779 static void
  1780 RunNuwaFork()
  1782     if (NuwaCheckpointCurrentThread()) {
  1783       DoNuwaFork();
  1786 #endif
  1788 bool
  1789 ContentChild::RecvNuwaFork()
  1791 #ifdef MOZ_NUWA_PROCESS
  1792     if (sNuwaForking) {           // No reentry.
  1793         return true;
  1795     sNuwaForking = true;
  1797     // We want to ensure that the PBackground actor gets cloned in the Nuwa
  1798     // process before we freeze. Also, we have to do this to avoid deadlock.
  1799     // Protocols that are "opened" (e.g. PBackground, PCompositor) block the
  1800     // main thread to wait for the IPC thread during the open operation.
  1801     // NuwaSpawnWait() blocks the IPC thread to wait for the main thread when
  1802     // the Nuwa process is forked. Unless we ensure that the two cannot happen
  1803     // at the same time then we risk deadlock. Spinning the event loop here
  1804     // guarantees the ordering is safe for PBackground.
  1805     while (!BackgroundChild::GetForCurrentThread()) {
  1806         if (NS_WARN_IF(!NS_ProcessNextEvent())) {
  1807             return false;
  1811     MessageLoop* ioloop = XRE_GetIOMessageLoop();
  1812     ioloop->PostTask(FROM_HERE, NewRunnableFunction(RunNuwaFork));
  1813     return true;
  1814 #else
  1815     return false; // Makes the underlying IPC channel abort.
  1816 #endif
  1819 } // namespace dom
  1820 } // namespace mozilla
  1822 extern "C" {
  1824 #if defined(MOZ_NUWA_PROCESS)
  1825 NS_EXPORT void
  1826 GetProtoFdInfos(NuwaProtoFdInfo* aInfoList,
  1827                 size_t aInfoListSize,
  1828                 size_t* aInfoSize)
  1830     size_t i = 0;
  1832     mozilla::dom::ContentChild* content =
  1833         mozilla::dom::ContentChild::GetSingleton();
  1834     aInfoList[i].protoId = content->GetProtocolId();
  1835     aInfoList[i].originFd =
  1836         content->GetTransport()->GetFileDescriptor();
  1837     i++;
  1839     for (IToplevelProtocol* actor = content->GetFirstOpenedActors();
  1840          actor != nullptr;
  1841          actor = actor->getNext()) {
  1842         if (i >= aInfoListSize) {
  1843             NS_RUNTIMEABORT("Too many top level protocols!");
  1846         aInfoList[i].protoId = actor->GetProtocolId();
  1847         aInfoList[i].originFd =
  1848             actor->GetTransport()->GetFileDescriptor();
  1849         i++;
  1852     if (i > NUWA_TOPLEVEL_MAX) {
  1853         NS_RUNTIMEABORT("Too many top level protocols!");
  1855     *aInfoSize = i;
  1858 class RunAddNewIPCProcess : public nsRunnable
  1860 public:
  1861     RunAddNewIPCProcess(pid_t aPid,
  1862                         nsTArray<mozilla::ipc::ProtocolFdMapping>& aMaps)
  1863         : mPid(aPid)
  1865         mMaps.SwapElements(aMaps);
  1868     NS_IMETHOD Run()
  1870         mozilla::dom::ContentChild::GetSingleton()->
  1871             SendAddNewProcess(mPid, mMaps);
  1873         MOZ_ASSERT(sNuwaForking);
  1874         sNuwaForking = false;
  1876         return NS_OK;
  1879 private:
  1880     pid_t mPid;
  1881     nsTArray<mozilla::ipc::ProtocolFdMapping> mMaps;
  1882 };
  1884 /**
  1885  * AddNewIPCProcess() is called by Nuwa process to tell the parent
  1886  * process that a new process is created.
  1888  * In the newly created process, ResetContentChildTransport() is called to
  1889  * reset fd for the IPC Channel and the session.
  1890  */
  1891 NS_EXPORT void
  1892 AddNewIPCProcess(pid_t aPid, NuwaProtoFdInfo* aInfoList, size_t aInfoListSize)
  1894     nsTArray<mozilla::ipc::ProtocolFdMapping> maps;
  1896     for (size_t i = 0; i < aInfoListSize; i++) {
  1897         int _fd = aInfoList[i].newFds[NUWA_NEWFD_PARENT];
  1898         mozilla::ipc::FileDescriptor fd(_fd);
  1899         mozilla::ipc::ProtocolFdMapping map(aInfoList[i].protoId, fd);
  1900         maps.AppendElement(map);
  1903     nsRefPtr<RunAddNewIPCProcess> runner = new RunAddNewIPCProcess(aPid, maps);
  1904     NS_DispatchToMainThread(runner);
  1907 NS_EXPORT void
  1908 OnNuwaProcessReady()
  1910     mozilla::dom::ContentChild* content =
  1911         mozilla::dom::ContentChild::GetSingleton();
  1912     content->SendNuwaReady();
  1915 NS_EXPORT void
  1916 AfterNuwaFork()
  1918     SetCurrentProcessPrivileges(base::PRIVILEGES_DEFAULT);
  1921 #endif // MOZ_NUWA_PROCESS

mercurial