dom/ipc/ContentChild.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/dom/ipc/ContentChild.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1923 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     1.5 +/* vim: set sw=4 ts=8 et tw=80 : */
     1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#ifdef MOZ_WIDGET_GTK
    1.11 +#include <gtk/gtk.h>
    1.12 +#endif
    1.13 +
    1.14 +#ifdef MOZ_WIDGET_QT
    1.15 +#include "nsQAppInstance.h"
    1.16 +#endif
    1.17 +
    1.18 +#include "ContentChild.h"
    1.19 +#include "CrashReporterChild.h"
    1.20 +#include "FileDescriptorSetChild.h"
    1.21 +#include "TabChild.h"
    1.22 +
    1.23 +#include "mozilla/Attributes.h"
    1.24 +#include "mozilla/dom/asmjscache/AsmJSCache.h"
    1.25 +#include "mozilla/dom/asmjscache/PAsmJSCacheEntryChild.h"
    1.26 +#include "mozilla/dom/ExternalHelperAppChild.h"
    1.27 +#include "mozilla/dom/PCrashReporterChild.h"
    1.28 +#include "mozilla/dom/DOMStorageIPC.h"
    1.29 +#include "mozilla/hal_sandbox/PHalChild.h"
    1.30 +#include "mozilla/ipc/BackgroundChild.h"
    1.31 +#include "mozilla/ipc/GeckoChildProcessHost.h"
    1.32 +#include "mozilla/ipc/TestShellChild.h"
    1.33 +#include "mozilla/layers/CompositorChild.h"
    1.34 +#include "mozilla/layers/ImageBridgeChild.h"
    1.35 +#include "mozilla/layers/PCompositorChild.h"
    1.36 +#include "mozilla/net/NeckoChild.h"
    1.37 +#include "mozilla/Preferences.h"
    1.38 +
    1.39 +#if defined(MOZ_CONTENT_SANDBOX)
    1.40 +#if defined(XP_WIN)
    1.41 +#define TARGET_SANDBOX_EXPORTS
    1.42 +#include "mozilla/sandboxTarget.h"
    1.43 +#elif defined(XP_LINUX)
    1.44 +#include "mozilla/Sandbox.h"
    1.45 +#endif
    1.46 +#endif
    1.47 +
    1.48 +#include "mozilla/unused.h"
    1.49 +
    1.50 +#include "nsIConsoleListener.h"
    1.51 +#include "nsIIPCBackgroundChildCreateCallback.h"
    1.52 +#include "nsIInterfaceRequestorUtils.h"
    1.53 +#include "nsIMemoryReporter.h"
    1.54 +#include "nsIMemoryInfoDumper.h"
    1.55 +#include "nsIMutable.h"
    1.56 +#include "nsIObserverService.h"
    1.57 +#include "nsIScriptSecurityManager.h"
    1.58 +#include "nsServiceManagerUtils.h"
    1.59 +#include "nsStyleSheetService.h"
    1.60 +#include "nsXULAppAPI.h"
    1.61 +#include "nsIScriptError.h"
    1.62 +#include "nsIConsoleService.h"
    1.63 +#include "nsJSEnvironment.h"
    1.64 +#include "SandboxHal.h"
    1.65 +#include "nsDebugImpl.h"
    1.66 +#include "nsHashPropertyBag.h"
    1.67 +#include "nsLayoutStylesheetCache.h"
    1.68 +#include "nsIJSRuntimeService.h"
    1.69 +#include "nsThreadManager.h"
    1.70 +
    1.71 +#include "IHistory.h"
    1.72 +#include "nsNetUtil.h"
    1.73 +
    1.74 +#include "base/message_loop.h"
    1.75 +#include "base/process_util.h"
    1.76 +#include "base/task.h"
    1.77 +
    1.78 +#include "nsChromeRegistryContent.h"
    1.79 +#include "nsFrameMessageManager.h"
    1.80 +
    1.81 +#include "nsIGeolocationProvider.h"
    1.82 +#include "mozilla/dom/PMemoryReportRequestChild.h"
    1.83 +
    1.84 +#ifdef MOZ_PERMISSIONS
    1.85 +#include "nsIScriptSecurityManager.h"
    1.86 +#include "nsPermission.h"
    1.87 +#include "nsPermissionManager.h"
    1.88 +#endif
    1.89 +
    1.90 +#include "PermissionMessageUtils.h"
    1.91 +
    1.92 +#if defined(MOZ_WIDGET_ANDROID)
    1.93 +#include "APKOpen.h"
    1.94 +#endif
    1.95 +
    1.96 +#if defined(MOZ_WIDGET_GONK)
    1.97 +#include "nsVolume.h"
    1.98 +#include "nsVolumeService.h"
    1.99 +#include "SpeakerManagerService.h"
   1.100 +#endif
   1.101 +
   1.102 +#ifdef XP_WIN
   1.103 +#include <process.h>
   1.104 +#define getpid _getpid
   1.105 +#endif
   1.106 +
   1.107 +#ifdef MOZ_X11
   1.108 +#include "mozilla/X11Util.h"
   1.109 +#endif
   1.110 +
   1.111 +#ifdef ACCESSIBILITY
   1.112 +#include "nsIAccessibilityService.h"
   1.113 +#endif
   1.114 +
   1.115 +#ifdef MOZ_NUWA_PROCESS
   1.116 +#include <setjmp.h>
   1.117 +#include "ipc/Nuwa.h"
   1.118 +#endif
   1.119 +
   1.120 +#include "mozilla/dom/indexedDB/PIndexedDBChild.h"
   1.121 +#include "mozilla/dom/mobilemessage/SmsChild.h"
   1.122 +#include "mozilla/dom/devicestorage/DeviceStorageRequestChild.h"
   1.123 +#include "mozilla/dom/PFileSystemRequestChild.h"
   1.124 +#include "mozilla/dom/FileSystemTaskBase.h"
   1.125 +#include "mozilla/dom/bluetooth/PBluetoothChild.h"
   1.126 +#include "mozilla/dom/PFMRadioChild.h"
   1.127 +#include "mozilla/ipc/InputStreamUtils.h"
   1.128 +
   1.129 +#ifdef MOZ_WEBSPEECH
   1.130 +#include "mozilla/dom/PSpeechSynthesisChild.h"
   1.131 +#endif
   1.132 +
   1.133 +#include "nsDOMFile.h"
   1.134 +#include "nsIRemoteBlob.h"
   1.135 +#include "ProcessUtils.h"
   1.136 +#include "StructuredCloneUtils.h"
   1.137 +#include "URIUtils.h"
   1.138 +#include "nsContentUtils.h"
   1.139 +#include "nsIPrincipal.h"
   1.140 +#include "nsDeviceStorage.h"
   1.141 +#include "AudioChannelService.h"
   1.142 +#include "JavaScriptChild.h"
   1.143 +#include "mozilla/dom/telephony/PTelephonyChild.h"
   1.144 +#include "mozilla/dom/time/DateCacheCleaner.h"
   1.145 +#include "mozilla/net/NeckoMessageUtils.h"
   1.146 +
   1.147 +using namespace base;
   1.148 +using namespace mozilla;
   1.149 +using namespace mozilla::docshell;
   1.150 +using namespace mozilla::dom::bluetooth;
   1.151 +using namespace mozilla::dom::devicestorage;
   1.152 +using namespace mozilla::dom::ipc;
   1.153 +using namespace mozilla::dom::mobilemessage;
   1.154 +using namespace mozilla::dom::indexedDB;
   1.155 +using namespace mozilla::dom::telephony;
   1.156 +using namespace mozilla::hal_sandbox;
   1.157 +using namespace mozilla::ipc;
   1.158 +using namespace mozilla::layers;
   1.159 +using namespace mozilla::net;
   1.160 +using namespace mozilla::jsipc;
   1.161 +#if defined(MOZ_WIDGET_GONK)
   1.162 +using namespace mozilla::system;
   1.163 +#endif
   1.164 +
   1.165 +#ifdef MOZ_NUWA_PROCESS
   1.166 +static bool sNuwaForking = false;
   1.167 +
   1.168 +// The size of the reserved stack (in unsigned ints). It's used to reserve space
   1.169 +// to push sigsetjmp() in NuwaCheckpointCurrentThread() to higher in the stack
   1.170 +// so that after it returns and do other work we don't garble the stack we want
   1.171 +// to preserve in NuwaCheckpointCurrentThread().
   1.172 +#define RESERVED_INT_STACK 128
   1.173 +
   1.174 +// A sentinel value for checking whether RESERVED_INT_STACK is large enough.
   1.175 +#define STACK_SENTINEL_VALUE 0xdeadbeef
   1.176 +#endif
   1.177 +
   1.178 +namespace mozilla {
   1.179 +namespace dom {
   1.180 +
   1.181 +class MemoryReportRequestChild : public PMemoryReportRequestChild,
   1.182 +                                 public nsIRunnable
   1.183 +{
   1.184 +public:
   1.185 +    NS_DECL_ISUPPORTS
   1.186 +
   1.187 +    MemoryReportRequestChild(uint32_t aGeneration, const nsAString& aDMDDumpIdent);
   1.188 +    virtual ~MemoryReportRequestChild();
   1.189 +    NS_IMETHOD Run();
   1.190 +private:
   1.191 +    uint32_t mGeneration;
   1.192 +    nsString mDMDDumpIdent;
   1.193 +};
   1.194 +
   1.195 +NS_IMPL_ISUPPORTS(MemoryReportRequestChild, nsIRunnable)
   1.196 +
   1.197 +MemoryReportRequestChild::MemoryReportRequestChild(uint32_t aGeneration, const nsAString& aDMDDumpIdent)
   1.198 +: mGeneration(aGeneration), mDMDDumpIdent(aDMDDumpIdent)
   1.199 +{
   1.200 +    MOZ_COUNT_CTOR(MemoryReportRequestChild);
   1.201 +}
   1.202 +
   1.203 +MemoryReportRequestChild::~MemoryReportRequestChild()
   1.204 +{
   1.205 +    MOZ_COUNT_DTOR(MemoryReportRequestChild);
   1.206 +}
   1.207 +
   1.208 +class AlertObserver
   1.209 +{
   1.210 +public:
   1.211 +
   1.212 +    AlertObserver(nsIObserver *aObserver, const nsString& aData)
   1.213 +        : mObserver(aObserver)
   1.214 +        , mData(aData)
   1.215 +    {
   1.216 +    }
   1.217 +
   1.218 +    ~AlertObserver() {}
   1.219 +
   1.220 +    bool ShouldRemoveFrom(nsIObserver* aObserver,
   1.221 +                          const nsString& aData) const
   1.222 +    {
   1.223 +        return (mObserver == aObserver &&
   1.224 +                mData == aData);
   1.225 +    }
   1.226 +
   1.227 +    bool Observes(const nsString& aData) const
   1.228 +    {
   1.229 +        return mData.Equals(aData);
   1.230 +    }
   1.231 +
   1.232 +    bool Notify(const nsCString& aType) const
   1.233 +    {
   1.234 +        mObserver->Observe(nullptr, aType.get(), mData.get());
   1.235 +        return true;
   1.236 +    }
   1.237 +
   1.238 +private:
   1.239 +    nsCOMPtr<nsIObserver> mObserver;
   1.240 +    nsString mData;
   1.241 +};
   1.242 +
   1.243 +class ConsoleListener MOZ_FINAL : public nsIConsoleListener
   1.244 +{
   1.245 +public:
   1.246 +    ConsoleListener(ContentChild* aChild)
   1.247 +    : mChild(aChild) {}
   1.248 +
   1.249 +    NS_DECL_ISUPPORTS
   1.250 +    NS_DECL_NSICONSOLELISTENER
   1.251 +
   1.252 +private:
   1.253 +    ContentChild* mChild;
   1.254 +    friend class ContentChild;
   1.255 +};
   1.256 +
   1.257 +NS_IMPL_ISUPPORTS(ConsoleListener, nsIConsoleListener)
   1.258 +
   1.259 +NS_IMETHODIMP
   1.260 +ConsoleListener::Observe(nsIConsoleMessage* aMessage)
   1.261 +{
   1.262 +    if (!mChild)
   1.263 +        return NS_OK;
   1.264 +    
   1.265 +    nsCOMPtr<nsIScriptError> scriptError = do_QueryInterface(aMessage);
   1.266 +    if (scriptError) {
   1.267 +        nsString msg, sourceName, sourceLine;
   1.268 +        nsXPIDLCString category;
   1.269 +        uint32_t lineNum, colNum, flags;
   1.270 +
   1.271 +        nsresult rv = scriptError->GetErrorMessage(msg);
   1.272 +        NS_ENSURE_SUCCESS(rv, rv);
   1.273 +        rv = scriptError->GetSourceName(sourceName);
   1.274 +        NS_ENSURE_SUCCESS(rv, rv);
   1.275 +        rv = scriptError->GetSourceLine(sourceLine);
   1.276 +        NS_ENSURE_SUCCESS(rv, rv);
   1.277 +
   1.278 +        // Before we send the error to the parent process (which
   1.279 +        // involves copying the memory), truncate any long lines.  CSS
   1.280 +        // errors in particular share the memory for long lines with
   1.281 +        // repeated errors, but the IPC communication we're about to do
   1.282 +        // will break that sharing, so we better truncate now.
   1.283 +        if (sourceLine.Length() > 1000) {
   1.284 +            sourceLine.Truncate(1000);
   1.285 +        }
   1.286 +
   1.287 +        rv = scriptError->GetCategory(getter_Copies(category));
   1.288 +        NS_ENSURE_SUCCESS(rv, rv);
   1.289 +        rv = scriptError->GetLineNumber(&lineNum);
   1.290 +        NS_ENSURE_SUCCESS(rv, rv);
   1.291 +        rv = scriptError->GetColumnNumber(&colNum);
   1.292 +        NS_ENSURE_SUCCESS(rv, rv);
   1.293 +        rv = scriptError->GetFlags(&flags);
   1.294 +        NS_ENSURE_SUCCESS(rv, rv);
   1.295 +        mChild->SendScriptError(msg, sourceName, sourceLine,
   1.296 +                               lineNum, colNum, flags, category);
   1.297 +        return NS_OK;
   1.298 +    }
   1.299 +
   1.300 +    nsXPIDLString msg;
   1.301 +    nsresult rv = aMessage->GetMessageMoz(getter_Copies(msg));
   1.302 +    NS_ENSURE_SUCCESS(rv, rv);
   1.303 +    mChild->SendConsoleMessage(msg);
   1.304 +    return NS_OK;
   1.305 +}
   1.306 +
   1.307 +class SystemMessageHandledObserver MOZ_FINAL : public nsIObserver
   1.308 +{
   1.309 +public:
   1.310 +    NS_DECL_ISUPPORTS
   1.311 +    NS_DECL_NSIOBSERVER
   1.312 +
   1.313 +    void Init();
   1.314 +};
   1.315 +
   1.316 +void SystemMessageHandledObserver::Init()
   1.317 +{
   1.318 +    nsCOMPtr<nsIObserverService> os =
   1.319 +        mozilla::services::GetObserverService();
   1.320 +
   1.321 +    if (os) {
   1.322 +        os->AddObserver(this, "handle-system-messages-done",
   1.323 +                        /* ownsWeak */ false);
   1.324 +    }
   1.325 +}
   1.326 +
   1.327 +NS_IMETHODIMP
   1.328 +SystemMessageHandledObserver::Observe(nsISupports* aSubject,
   1.329 +                                      const char* aTopic,
   1.330 +                                      const char16_t* aData)
   1.331 +{
   1.332 +    if (ContentChild::GetSingleton()) {
   1.333 +        ContentChild::GetSingleton()->SendSystemMessageHandled();
   1.334 +    }
   1.335 +    return NS_OK;
   1.336 +}
   1.337 +
   1.338 +NS_IMPL_ISUPPORTS(SystemMessageHandledObserver, nsIObserver)
   1.339 +
   1.340 +class BackgroundChildPrimer MOZ_FINAL :
   1.341 +  public nsIIPCBackgroundChildCreateCallback
   1.342 +{
   1.343 +public:
   1.344 +    BackgroundChildPrimer()
   1.345 +    { }
   1.346 +
   1.347 +    NS_DECL_ISUPPORTS
   1.348 +
   1.349 +private:
   1.350 +    ~BackgroundChildPrimer()
   1.351 +    { }
   1.352 +
   1.353 +    virtual void
   1.354 +    ActorCreated(PBackgroundChild* aActor) MOZ_OVERRIDE
   1.355 +    {
   1.356 +        MOZ_ASSERT(aActor, "Failed to create a PBackgroundChild actor!");
   1.357 +    }
   1.358 +
   1.359 +    virtual void
   1.360 +    ActorFailed() MOZ_OVERRIDE
   1.361 +    {
   1.362 +        MOZ_CRASH("Failed to create a PBackgroundChild actor!");
   1.363 +    }
   1.364 +};
   1.365 +
   1.366 +NS_IMPL_ISUPPORTS(BackgroundChildPrimer, nsIIPCBackgroundChildCreateCallback)
   1.367 +
   1.368 +ContentChild* ContentChild::sSingleton;
   1.369 +
   1.370 +// Performs initialization that is not fork-safe, i.e. that must be done after
   1.371 +// forking from the Nuwa process.
   1.372 +static void
   1.373 +InitOnContentProcessCreated()
   1.374 +{
   1.375 +    // This will register cross-process observer.
   1.376 +    mozilla::dom::time::InitializeDateCacheCleaner();
   1.377 +}
   1.378 +
   1.379 +ContentChild::ContentChild()
   1.380 + : mID(uint64_t(-1))
   1.381 +#ifdef ANDROID
   1.382 +   ,mScreenSize(0, 0)
   1.383 +#endif
   1.384 +   , mCanOverrideProcessName(true)
   1.385 +{
   1.386 +    // This process is a content process, so it's clearly running in
   1.387 +    // multiprocess mode!
   1.388 +    nsDebugImpl::SetMultiprocessMode("Child");
   1.389 +}
   1.390 +
   1.391 +ContentChild::~ContentChild()
   1.392 +{
   1.393 +}
   1.394 +
   1.395 +bool
   1.396 +ContentChild::Init(MessageLoop* aIOLoop,
   1.397 +                   base::ProcessHandle aParentHandle,
   1.398 +                   IPC::Channel* aChannel)
   1.399 +{
   1.400 +#ifdef MOZ_WIDGET_GTK
   1.401 +    // sigh
   1.402 +    gtk_init(nullptr, nullptr);
   1.403 +#endif
   1.404 +
   1.405 +#ifdef MOZ_WIDGET_QT
   1.406 +    // sigh, seriously
   1.407 +    nsQAppInstance::AddRef();
   1.408 +#endif
   1.409 +
   1.410 +#ifdef MOZ_X11
   1.411 +    // Do this after initializing GDK, or GDK will install its own handler.
   1.412 +    XRE_InstallX11ErrorHandler();
   1.413 +#endif
   1.414 +
   1.415 +#ifdef MOZ_NUWA_PROCESS
   1.416 +    SetTransport(aChannel);
   1.417 +#endif
   1.418 +
   1.419 +    NS_ASSERTION(!sSingleton, "only one ContentChild per child");
   1.420 +
   1.421 +    // Once we start sending IPC messages, we need the thread manager to be
   1.422 +    // initialized so we can deal with the responses. Do that here before we
   1.423 +    // try to construct the crash reporter.
   1.424 +    nsresult rv = nsThreadManager::get()->Init();
   1.425 +    if (NS_WARN_IF(NS_FAILED(rv))) {
   1.426 +        return false;
   1.427 +    }
   1.428 +
   1.429 +    Open(aChannel, aParentHandle, aIOLoop);
   1.430 +    sSingleton = this;
   1.431 +
   1.432 +#ifdef MOZ_X11
   1.433 +    // Send the parent our X socket to act as a proxy reference for our X
   1.434 +    // resources.
   1.435 +    int xSocketFd = ConnectionNumber(DefaultXDisplay());
   1.436 +    SendBackUpXResources(FileDescriptor(xSocketFd));
   1.437 +#endif
   1.438 +
   1.439 +#ifdef MOZ_CRASHREPORTER
   1.440 +    SendPCrashReporterConstructor(CrashReporter::CurrentThreadId(),
   1.441 +                                  XRE_GetProcessType());
   1.442 +#endif
   1.443 +
   1.444 +    GetCPOWManager();
   1.445 +
   1.446 +    InitProcessAttributes();
   1.447 +
   1.448 +    return true;
   1.449 +}
   1.450 +
   1.451 +void
   1.452 +ContentChild::InitProcessAttributes()
   1.453 +{
   1.454 +    SendGetProcessAttributes(&mID, &mIsForApp, &mIsForBrowser);
   1.455 +
   1.456 +#ifdef MOZ_NUWA_PROCESS
   1.457 +    if (IsNuwaProcess()) {
   1.458 +        SetProcessName(NS_LITERAL_STRING("(Nuwa)"), false);
   1.459 +        return;
   1.460 +    }
   1.461 +#endif
   1.462 +    if (mIsForApp && !mIsForBrowser) {
   1.463 +        SetProcessName(NS_LITERAL_STRING("(Preallocated app)"), false);
   1.464 +    } else {
   1.465 +        SetProcessName(NS_LITERAL_STRING("Browser"), false);
   1.466 +    }
   1.467 +
   1.468 +}
   1.469 +
   1.470 +void
   1.471 +ContentChild::SetProcessName(const nsAString& aName, bool aDontOverride)
   1.472 +{
   1.473 +    if (!mCanOverrideProcessName) {
   1.474 +        return;
   1.475 +    }
   1.476 +
   1.477 +    char* name;
   1.478 +    if ((name = PR_GetEnv("MOZ_DEBUG_APP_PROCESS")) &&
   1.479 +        aName.EqualsASCII(name)) {
   1.480 +#ifdef OS_POSIX
   1.481 +        printf_stderr("\n\nCHILDCHILDCHILDCHILD\n  [%s] debug me @%d\n\n", name, getpid());
   1.482 +        sleep(30);
   1.483 +#elif defined(OS_WIN)
   1.484 +        // Windows has a decent JIT debugging story, so NS_DebugBreak does the
   1.485 +        // right thing.
   1.486 +        NS_DebugBreak(NS_DEBUG_BREAK,
   1.487 +                      "Invoking NS_DebugBreak() to debug child process",
   1.488 +                      nullptr, __FILE__, __LINE__);
   1.489 +#endif
   1.490 +    }
   1.491 +
   1.492 +    mProcessName = aName;
   1.493 +    mozilla::ipc::SetThisProcessName(NS_LossyConvertUTF16toASCII(aName).get());
   1.494 +
   1.495 +    if (aDontOverride) {
   1.496 +        mCanOverrideProcessName = false;
   1.497 +    }
   1.498 +}
   1.499 +
   1.500 +void
   1.501 +ContentChild::GetProcessName(nsAString& aName)
   1.502 +{
   1.503 +    aName.Assign(mProcessName);
   1.504 +}
   1.505 +
   1.506 +void
   1.507 +ContentChild::GetProcessName(nsACString& aName)
   1.508 +{
   1.509 +    aName.Assign(NS_ConvertUTF16toUTF8(mProcessName));
   1.510 +}
   1.511 +
   1.512 +/* static */ void
   1.513 +ContentChild::AppendProcessId(nsACString& aName)
   1.514 +{
   1.515 +    if (!aName.IsEmpty()) {
   1.516 +        aName.AppendLiteral(" ");
   1.517 +    }
   1.518 +    unsigned pid = getpid();
   1.519 +    aName.Append(nsPrintfCString("(pid %u)", pid));
   1.520 +}
   1.521 +
   1.522 +void
   1.523 +ContentChild::InitXPCOM()
   1.524 +{
   1.525 +    // Do this as early as possible to get the parent process to initialize the
   1.526 +    // background thread since we'll likely need database information very soon.
   1.527 +    BackgroundChild::Startup();
   1.528 +
   1.529 +    nsCOMPtr<nsIIPCBackgroundChildCreateCallback> callback =
   1.530 +        new BackgroundChildPrimer();
   1.531 +    if (!BackgroundChild::GetOrCreateForCurrentThread(callback)) {
   1.532 +        MOZ_CRASH("Failed to create PBackgroundChild!");
   1.533 +    }
   1.534 +
   1.535 +    nsCOMPtr<nsIConsoleService> svc(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
   1.536 +    if (!svc) {
   1.537 +        NS_WARNING("Couldn't acquire console service");
   1.538 +        return;
   1.539 +    }
   1.540 +
   1.541 +    mConsoleListener = new ConsoleListener(this);
   1.542 +    if (NS_FAILED(svc->RegisterListener(mConsoleListener)))
   1.543 +        NS_WARNING("Couldn't register console listener for child process");
   1.544 +
   1.545 +    bool isOffline;
   1.546 +    SendGetXPCOMProcessAttributes(&isOffline);
   1.547 +    RecvSetOffline(isOffline);
   1.548 +
   1.549 +    DebugOnly<FileUpdateDispatcher*> observer = FileUpdateDispatcher::GetSingleton();
   1.550 +    NS_ASSERTION(observer, "FileUpdateDispatcher is null");
   1.551 +
   1.552 +    // This object is held alive by the observer service.
   1.553 +    nsRefPtr<SystemMessageHandledObserver> sysMsgObserver =
   1.554 +        new SystemMessageHandledObserver();
   1.555 +    sysMsgObserver->Init();
   1.556 +
   1.557 +#ifndef MOZ_NUWA_PROCESS
   1.558 +    InitOnContentProcessCreated();
   1.559 +#endif
   1.560 +}
   1.561 +
   1.562 +PMemoryReportRequestChild*
   1.563 +ContentChild::AllocPMemoryReportRequestChild(const uint32_t& generation,
   1.564 +                                             const bool &minimizeMemoryUsage,
   1.565 +                                             const nsString& aDMDDumpIdent)
   1.566 +{
   1.567 +    MemoryReportRequestChild *actor = new MemoryReportRequestChild(generation, aDMDDumpIdent);
   1.568 +    actor->AddRef();
   1.569 +    return actor;
   1.570 +}
   1.571 +
   1.572 +// This is just a wrapper for InfallibleTArray<MemoryReport> that implements
   1.573 +// nsISupports, so it can be passed to nsIMemoryReporter::CollectReports.
   1.574 +class MemoryReportsWrapper MOZ_FINAL : public nsISupports {
   1.575 +public:
   1.576 +    NS_DECL_ISUPPORTS
   1.577 +    MemoryReportsWrapper(InfallibleTArray<MemoryReport> *r) : mReports(r) { }
   1.578 +    InfallibleTArray<MemoryReport> *mReports;
   1.579 +};
   1.580 +NS_IMPL_ISUPPORTS0(MemoryReportsWrapper)
   1.581 +
   1.582 +class MemoryReportCallback MOZ_FINAL : public nsIMemoryReporterCallback
   1.583 +{
   1.584 +public:
   1.585 +    NS_DECL_ISUPPORTS
   1.586 +
   1.587 +    MemoryReportCallback(const nsACString &aProcess)
   1.588 +    : mProcess(aProcess)
   1.589 +    {
   1.590 +    }
   1.591 +
   1.592 +    NS_IMETHOD Callback(const nsACString &aProcess, const nsACString &aPath,
   1.593 +                        int32_t aKind, int32_t aUnits, int64_t aAmount,
   1.594 +                        const nsACString &aDescription,
   1.595 +                        nsISupports *aiWrappedReports)
   1.596 +    {
   1.597 +        MemoryReportsWrapper *wrappedReports =
   1.598 +            static_cast<MemoryReportsWrapper *>(aiWrappedReports);
   1.599 +
   1.600 +        MemoryReport memreport(mProcess, nsCString(aPath), aKind, aUnits,
   1.601 +                               aAmount, nsCString(aDescription));
   1.602 +        wrappedReports->mReports->AppendElement(memreport);
   1.603 +        return NS_OK;
   1.604 +    }
   1.605 +private:
   1.606 +    const nsCString mProcess;
   1.607 +};
   1.608 +NS_IMPL_ISUPPORTS(
   1.609 +  MemoryReportCallback
   1.610 +, nsIMemoryReporterCallback
   1.611 +)
   1.612 +
   1.613 +bool
   1.614 +ContentChild::RecvPMemoryReportRequestConstructor(
   1.615 +    PMemoryReportRequestChild* child,
   1.616 +    const uint32_t& generation,
   1.617 +    const bool& minimizeMemoryUsage,
   1.618 +    const nsString& aDMDDumpIdent)
   1.619 +{
   1.620 +    MemoryReportRequestChild *actor = static_cast<MemoryReportRequestChild*>(child);
   1.621 +    nsresult rv;
   1.622 +
   1.623 +    if (minimizeMemoryUsage) {
   1.624 +        nsCOMPtr<nsIMemoryReporterManager> mgr = do_GetService("@mozilla.org/memory-reporter-manager;1");
   1.625 +        rv = mgr->MinimizeMemoryUsage(actor);
   1.626 +        // mgr will eventually call actor->Run()
   1.627 +    } else {
   1.628 +        rv = actor->Run();
   1.629 +    }
   1.630 +
   1.631 +    return !NS_WARN_IF(NS_FAILED(rv));
   1.632 +}
   1.633 +
   1.634 +NS_IMETHODIMP MemoryReportRequestChild::Run()
   1.635 +{
   1.636 +    ContentChild *child = static_cast<ContentChild*>(Manager());
   1.637 +    nsCOMPtr<nsIMemoryReporterManager> mgr = do_GetService("@mozilla.org/memory-reporter-manager;1");
   1.638 +
   1.639 +    InfallibleTArray<MemoryReport> reports;
   1.640 +
   1.641 +    nsCString process;
   1.642 +    child->GetProcessName(process);
   1.643 +    child->AppendProcessId(process);
   1.644 +
   1.645 +    // Run the reporters.  The callback will turn each measurement into a
   1.646 +    // MemoryReport.
   1.647 +    nsRefPtr<MemoryReportsWrapper> wrappedReports =
   1.648 +        new MemoryReportsWrapper(&reports);
   1.649 +    nsRefPtr<MemoryReportCallback> cb = new MemoryReportCallback(process);
   1.650 +    mgr->GetReportsForThisProcessExtended(cb, wrappedReports, mDMDDumpIdent);
   1.651 +
   1.652 +    bool sent = Send__delete__(this, mGeneration, reports);
   1.653 +    return sent ? NS_OK : NS_ERROR_FAILURE;
   1.654 +}
   1.655 +
   1.656 +bool
   1.657 +ContentChild::RecvAudioChannelNotify()
   1.658 +{
   1.659 +    nsRefPtr<AudioChannelService> service =
   1.660 +        AudioChannelService::GetAudioChannelService();
   1.661 +    if (service) {
   1.662 +        service->Notify();
   1.663 +    }
   1.664 +    return true;
   1.665 +}
   1.666 +
   1.667 +bool
   1.668 +ContentChild::DeallocPMemoryReportRequestChild(PMemoryReportRequestChild* actor)
   1.669 +{
   1.670 +    static_cast<MemoryReportRequestChild*>(actor)->Release();
   1.671 +    return true;
   1.672 +}
   1.673 +
   1.674 +bool
   1.675 +ContentChild::RecvDumpGCAndCCLogsToFile(const nsString& aIdentifier,
   1.676 +                                        const bool& aDumpAllTraces,
   1.677 +                                        const bool& aDumpChildProcesses)
   1.678 +{
   1.679 +    nsCOMPtr<nsIMemoryInfoDumper> dumper = do_GetService("@mozilla.org/memory-info-dumper;1");
   1.680 +
   1.681 +    nsString gcLogPath, ccLogPath;
   1.682 +    dumper->DumpGCAndCCLogsToFile(aIdentifier, aDumpAllTraces,
   1.683 +                                  aDumpChildProcesses, gcLogPath, ccLogPath);
   1.684 +    return true;
   1.685 +}
   1.686 +
   1.687 +PCompositorChild*
   1.688 +ContentChild::AllocPCompositorChild(mozilla::ipc::Transport* aTransport,
   1.689 +                                    base::ProcessId aOtherProcess)
   1.690 +{
   1.691 +    return CompositorChild::Create(aTransport, aOtherProcess);
   1.692 +}
   1.693 +
   1.694 +PImageBridgeChild*
   1.695 +ContentChild::AllocPImageBridgeChild(mozilla::ipc::Transport* aTransport,
   1.696 +                                     base::ProcessId aOtherProcess)
   1.697 +{
   1.698 +    return ImageBridgeChild::StartUpInChildProcess(aTransport, aOtherProcess);
   1.699 +}
   1.700 +
   1.701 +PBackgroundChild*
   1.702 +ContentChild::AllocPBackgroundChild(Transport* aTransport,
   1.703 +                                    ProcessId aOtherProcess)
   1.704 +{
   1.705 +    return BackgroundChild::Alloc(aTransport, aOtherProcess);
   1.706 +}
   1.707 +
   1.708 +bool
   1.709 +ContentChild::RecvSetProcessSandbox()
   1.710 +{
   1.711 +  // We may want to move the sandbox initialization somewhere else
   1.712 +  // at some point; see bug 880808.
   1.713 +#if defined(MOZ_CONTENT_SANDBOX)
   1.714 +#if defined(XP_LINUX)
   1.715 +  SetCurrentProcessSandbox();
   1.716 +#elif defined(XP_WIN)
   1.717 +  mozilla::SandboxTarget::Instance()->StartSandbox();
   1.718 +#endif
   1.719 +#endif
   1.720 +  return true;
   1.721 +}
   1.722 +
   1.723 +bool
   1.724 +ContentChild::RecvSpeakerManagerNotify()
   1.725 +{
   1.726 +#ifdef MOZ_WIDGET_GONK
   1.727 +  nsRefPtr<SpeakerManagerService> service =
   1.728 +    SpeakerManagerService::GetSpeakerManagerService();
   1.729 +  if (service) {
   1.730 +    service->Notify();
   1.731 +  }
   1.732 +  return true;
   1.733 +#endif
   1.734 +  return false;
   1.735 +}
   1.736 +
   1.737 +static CancelableTask* sFirstIdleTask;
   1.738 +
   1.739 +static void FirstIdle(void)
   1.740 +{
   1.741 +    MOZ_ASSERT(sFirstIdleTask);
   1.742 +    sFirstIdleTask = nullptr;
   1.743 +    ContentChild::GetSingleton()->SendFirstIdle();
   1.744 +}
   1.745 +
   1.746 +mozilla::jsipc::PJavaScriptChild *
   1.747 +ContentChild::AllocPJavaScriptChild()
   1.748 +{
   1.749 +    nsCOMPtr<nsIJSRuntimeService> svc = do_GetService("@mozilla.org/js/xpc/RuntimeService;1");
   1.750 +    NS_ENSURE_TRUE(svc, nullptr);
   1.751 +
   1.752 +    JSRuntime *rt;
   1.753 +    svc->GetRuntime(&rt);
   1.754 +    NS_ENSURE_TRUE(svc, nullptr);
   1.755 +
   1.756 +    mozilla::jsipc::JavaScriptChild *child = new mozilla::jsipc::JavaScriptChild(rt);
   1.757 +    if (!child->init()) {
   1.758 +        delete child;
   1.759 +        return nullptr;
   1.760 +    }
   1.761 +    return child;
   1.762 +}
   1.763 +
   1.764 +bool
   1.765 +ContentChild::DeallocPJavaScriptChild(PJavaScriptChild *child)
   1.766 +{
   1.767 +    delete child;
   1.768 +    return true;
   1.769 +}
   1.770 +
   1.771 +PBrowserChild*
   1.772 +ContentChild::AllocPBrowserChild(const IPCTabContext& aContext,
   1.773 +                                 const uint32_t& aChromeFlags)
   1.774 +{
   1.775 +    // We'll happily accept any kind of IPCTabContext here; we don't need to
   1.776 +    // check that it's of a certain type for security purposes, because we
   1.777 +    // believe whatever the parent process tells us.
   1.778 +
   1.779 +    MaybeInvalidTabContext tc(aContext);
   1.780 +    if (!tc.IsValid()) {
   1.781 +        NS_ERROR(nsPrintfCString("Received an invalid TabContext from "
   1.782 +                                 "the parent process. (%s)  Crashing...",
   1.783 +                                 tc.GetInvalidReason()).get());
   1.784 +        MOZ_CRASH("Invalid TabContext received from the parent process.");
   1.785 +    }
   1.786 +
   1.787 +    nsRefPtr<TabChild> child = TabChild::Create(this, tc.GetTabContext(), aChromeFlags);
   1.788 +
   1.789 +    // The ref here is released in DeallocPBrowserChild.
   1.790 +    return child.forget().take();
   1.791 +}
   1.792 +
   1.793 +bool
   1.794 +ContentChild::RecvPBrowserConstructor(PBrowserChild* actor,
   1.795 +                                      const IPCTabContext& context,
   1.796 +                                      const uint32_t& chromeFlags)
   1.797 +{
   1.798 +    // This runs after AllocPBrowserChild() returns and the IPC machinery for this
   1.799 +    // PBrowserChild has been set up.
   1.800 +
   1.801 +    nsCOMPtr<nsIObserverService> os = services::GetObserverService();
   1.802 +    if (os) {
   1.803 +        nsITabChild* tc =
   1.804 +            static_cast<nsITabChild*>(static_cast<TabChild*>(actor));
   1.805 +        os->NotifyObservers(tc, "tab-child-created", nullptr);
   1.806 +    }
   1.807 +
   1.808 +    static bool hasRunOnce = false;
   1.809 +    if (!hasRunOnce) {
   1.810 +        hasRunOnce = true;
   1.811 +
   1.812 +        MOZ_ASSERT(!sFirstIdleTask);
   1.813 +        sFirstIdleTask = NewRunnableFunction(FirstIdle);
   1.814 +        MessageLoop::current()->PostIdleTask(FROM_HERE, sFirstIdleTask);
   1.815 +
   1.816 +        // Redo InitProcessAttributes() when the app or browser is really
   1.817 +        // launching so the attributes will be correct.
   1.818 +        InitProcessAttributes();
   1.819 +    }
   1.820 +
   1.821 +    return true;
   1.822 +}
   1.823 +
   1.824 +PFileDescriptorSetChild*
   1.825 +ContentChild::AllocPFileDescriptorSetChild(const FileDescriptor& aFD)
   1.826 +{
   1.827 +    return new FileDescriptorSetChild(aFD);
   1.828 +}
   1.829 +
   1.830 +bool
   1.831 +ContentChild::DeallocPFileDescriptorSetChild(PFileDescriptorSetChild* aActor)
   1.832 +{
   1.833 +    delete static_cast<FileDescriptorSetChild*>(aActor);
   1.834 +    return true;
   1.835 +}
   1.836 +
   1.837 +bool
   1.838 +ContentChild::DeallocPBrowserChild(PBrowserChild* iframe)
   1.839 +{
   1.840 +    TabChild* child = static_cast<TabChild*>(iframe);
   1.841 +    NS_RELEASE(child);
   1.842 +    return true;
   1.843 +}
   1.844 +
   1.845 +PBlobChild*
   1.846 +ContentChild::AllocPBlobChild(const BlobConstructorParams& aParams)
   1.847 +{
   1.848 +  return BlobChild::Create(this, aParams);
   1.849 +}
   1.850 +
   1.851 +bool
   1.852 +ContentChild::DeallocPBlobChild(PBlobChild* aActor)
   1.853 +{
   1.854 +  delete aActor;
   1.855 +  return true;
   1.856 +}
   1.857 +
   1.858 +BlobChild*
   1.859 +ContentChild::GetOrCreateActorForBlob(nsIDOMBlob* aBlob)
   1.860 +{
   1.861 +  MOZ_ASSERT(NS_IsMainThread());
   1.862 +  MOZ_ASSERT(aBlob);
   1.863 +
   1.864 +  // If the blob represents a remote blob then we can simply pass its actor back
   1.865 +  // here.
   1.866 +  if (nsCOMPtr<nsIRemoteBlob> remoteBlob = do_QueryInterface(aBlob)) {
   1.867 +    BlobChild* actor =
   1.868 +      static_cast<BlobChild*>(
   1.869 +        static_cast<PBlobChild*>(remoteBlob->GetPBlob()));
   1.870 +    MOZ_ASSERT(actor);
   1.871 +    return actor;
   1.872 +  }
   1.873 +
   1.874 +  // XXX This is only safe so long as all blob implementations in our tree
   1.875 +  //     inherit nsDOMFileBase. If that ever changes then this will need to grow
   1.876 +  //     a real interface or something.
   1.877 +  const nsDOMFileBase* blob = static_cast<nsDOMFileBase*>(aBlob);
   1.878 +
   1.879 +  // We often pass blobs that are multipart but that only contain one sub-blob
   1.880 +  // (WebActivities does this a bunch). Unwrap to reduce the number of actors
   1.881 +  // that we have to maintain.
   1.882 +  const nsTArray<nsCOMPtr<nsIDOMBlob> >* subBlobs = blob->GetSubBlobs();
   1.883 +  if (subBlobs && subBlobs->Length() == 1) {
   1.884 +    const nsCOMPtr<nsIDOMBlob>& subBlob = subBlobs->ElementAt(0);
   1.885 +    MOZ_ASSERT(subBlob);
   1.886 +
   1.887 +    // We can only take this shortcut if the multipart and the sub-blob are both
   1.888 +    // Blob objects or both File objects.
   1.889 +    nsCOMPtr<nsIDOMFile> multipartBlobAsFile = do_QueryInterface(aBlob);
   1.890 +    nsCOMPtr<nsIDOMFile> subBlobAsFile = do_QueryInterface(subBlob);
   1.891 +    if (!multipartBlobAsFile == !subBlobAsFile) {
   1.892 +      // The wrapping was unnecessary, see if we can simply pass an existing
   1.893 +      // remote blob.
   1.894 +      if (nsCOMPtr<nsIRemoteBlob> remoteBlob = do_QueryInterface(subBlob)) {
   1.895 +        BlobChild* actor =
   1.896 +          static_cast<BlobChild*>(
   1.897 +            static_cast<PBlobChild*>(remoteBlob->GetPBlob()));
   1.898 +        MOZ_ASSERT(actor);
   1.899 +        return actor;
   1.900 +      }
   1.901 +
   1.902 +      // No need to add a reference here since the original blob must have a
   1.903 +      // strong reference in the caller and it must also have a strong reference
   1.904 +      // to this sub-blob.
   1.905 +      aBlob = subBlob;
   1.906 +      blob = static_cast<nsDOMFileBase*>(aBlob);
   1.907 +      subBlobs = blob->GetSubBlobs();
   1.908 +    }
   1.909 +  }
   1.910 +
   1.911 +  // All blobs shared between processes must be immutable.
   1.912 +  nsCOMPtr<nsIMutable> mutableBlob = do_QueryInterface(aBlob);
   1.913 +  if (!mutableBlob || NS_FAILED(mutableBlob->SetMutable(false))) {
   1.914 +    NS_WARNING("Failed to make blob immutable!");
   1.915 +    return nullptr;
   1.916 +  }
   1.917 +
   1.918 +  ParentBlobConstructorParams params;
   1.919 +
   1.920 +  if (blob->IsSizeUnknown() || blob->IsDateUnknown()) {
   1.921 +    // We don't want to call GetSize or GetLastModifiedDate
   1.922 +    // yet since that may stat a file on the main thread
   1.923 +    // here. Instead we'll learn the size lazily from the
   1.924 +    // other process.
   1.925 +    params.blobParams() = MysteryBlobConstructorParams();
   1.926 +    params.optionalInputStreamParams() = void_t();
   1.927 +  }
   1.928 +  else {
   1.929 +    nsString contentType;
   1.930 +    nsresult rv = aBlob->GetType(contentType);
   1.931 +    NS_ENSURE_SUCCESS(rv, nullptr);
   1.932 +
   1.933 +    uint64_t length;
   1.934 +    rv = aBlob->GetSize(&length);
   1.935 +    NS_ENSURE_SUCCESS(rv, nullptr);
   1.936 +
   1.937 +    nsCOMPtr<nsIInputStream> stream;
   1.938 +    rv = aBlob->GetInternalStream(getter_AddRefs(stream));
   1.939 +    NS_ENSURE_SUCCESS(rv, nullptr);
   1.940 +
   1.941 +    InputStreamParams inputStreamParams;
   1.942 +    nsTArray<mozilla::ipc::FileDescriptor> fds;
   1.943 +    SerializeInputStream(stream, inputStreamParams, fds);
   1.944 +    MOZ_ASSERT(fds.IsEmpty());
   1.945 +
   1.946 +    params.optionalInputStreamParams() = inputStreamParams;
   1.947 +
   1.948 +    nsCOMPtr<nsIDOMFile> file = do_QueryInterface(aBlob);
   1.949 +    if (file) {
   1.950 +      FileBlobConstructorParams fileParams;
   1.951 +
   1.952 +      rv = file->GetName(fileParams.name());
   1.953 +      NS_ENSURE_SUCCESS(rv, nullptr);
   1.954 +
   1.955 +      rv = file->GetMozLastModifiedDate(&fileParams.modDate());
   1.956 +      NS_ENSURE_SUCCESS(rv, nullptr);
   1.957 +
   1.958 +      fileParams.contentType() = contentType;
   1.959 +      fileParams.length() = length;
   1.960 +
   1.961 +      params.blobParams() = fileParams;
   1.962 +    } else {
   1.963 +      NormalBlobConstructorParams blobParams;
   1.964 +      blobParams.contentType() = contentType;
   1.965 +      blobParams.length() = length;
   1.966 +      params.blobParams() = blobParams;
   1.967 +    }
   1.968 +  }
   1.969 +
   1.970 +  BlobChild* actor = BlobChild::Create(this, aBlob);
   1.971 +  NS_ENSURE_TRUE(actor, nullptr);
   1.972 +
   1.973 +  return SendPBlobConstructor(actor, params) ? actor : nullptr;
   1.974 +}
   1.975 +
   1.976 +PCrashReporterChild*
   1.977 +ContentChild::AllocPCrashReporterChild(const mozilla::dom::NativeThreadId& id,
   1.978 +                                       const uint32_t& processType)
   1.979 +{
   1.980 +#ifdef MOZ_CRASHREPORTER
   1.981 +    return new CrashReporterChild();
   1.982 +#else
   1.983 +    return nullptr;
   1.984 +#endif
   1.985 +}
   1.986 +
   1.987 +bool
   1.988 +ContentChild::DeallocPCrashReporterChild(PCrashReporterChild* crashreporter)
   1.989 +{
   1.990 +    delete crashreporter;
   1.991 +    return true;
   1.992 +}
   1.993 +
   1.994 +PHalChild*
   1.995 +ContentChild::AllocPHalChild()
   1.996 +{
   1.997 +    return CreateHalChild();
   1.998 +}
   1.999 +
  1.1000 +bool
  1.1001 +ContentChild::DeallocPHalChild(PHalChild* aHal)
  1.1002 +{
  1.1003 +    delete aHal;
  1.1004 +    return true;
  1.1005 +}
  1.1006 +
  1.1007 +PIndexedDBChild*
  1.1008 +ContentChild::AllocPIndexedDBChild()
  1.1009 +{
  1.1010 +  NS_NOTREACHED("Should never get here!");
  1.1011 +  return nullptr;
  1.1012 +}
  1.1013 +
  1.1014 +bool
  1.1015 +ContentChild::DeallocPIndexedDBChild(PIndexedDBChild* aActor)
  1.1016 +{
  1.1017 +  delete aActor;
  1.1018 +  return true;
  1.1019 +}
  1.1020 +
  1.1021 +asmjscache::PAsmJSCacheEntryChild*
  1.1022 +ContentChild::AllocPAsmJSCacheEntryChild(
  1.1023 +                                    const asmjscache::OpenMode& aOpenMode,
  1.1024 +                                    const asmjscache::WriteParams& aWriteParams,
  1.1025 +                                    const IPC::Principal& aPrincipal)
  1.1026 +{
  1.1027 +  NS_NOTREACHED("Should never get here!");
  1.1028 +  return nullptr;
  1.1029 +}
  1.1030 +
  1.1031 +bool
  1.1032 +ContentChild::DeallocPAsmJSCacheEntryChild(PAsmJSCacheEntryChild* aActor)
  1.1033 +{
  1.1034 +  asmjscache::DeallocEntryChild(aActor);
  1.1035 +  return true;
  1.1036 +}
  1.1037 +
  1.1038 +PTestShellChild*
  1.1039 +ContentChild::AllocPTestShellChild()
  1.1040 +{
  1.1041 +    return new TestShellChild();
  1.1042 +}
  1.1043 +
  1.1044 +bool
  1.1045 +ContentChild::DeallocPTestShellChild(PTestShellChild* shell)
  1.1046 +{
  1.1047 +    delete shell;
  1.1048 +    return true;
  1.1049 +}
  1.1050 +
  1.1051 +jsipc::JavaScriptChild *
  1.1052 +ContentChild::GetCPOWManager()
  1.1053 +{
  1.1054 +    if (ManagedPJavaScriptChild().Length()) {
  1.1055 +        return static_cast<JavaScriptChild*>(ManagedPJavaScriptChild()[0]);
  1.1056 +    }
  1.1057 +    JavaScriptChild* actor = static_cast<JavaScriptChild*>(SendPJavaScriptConstructor());
  1.1058 +    return actor;
  1.1059 +}
  1.1060 +
  1.1061 +bool
  1.1062 +ContentChild::RecvPTestShellConstructor(PTestShellChild* actor)
  1.1063 +{
  1.1064 +    return true;
  1.1065 +}
  1.1066 +
  1.1067 +PDeviceStorageRequestChild*
  1.1068 +ContentChild::AllocPDeviceStorageRequestChild(const DeviceStorageParams& aParams)
  1.1069 +{
  1.1070 +    return new DeviceStorageRequestChild();
  1.1071 +}
  1.1072 +
  1.1073 +bool
  1.1074 +ContentChild::DeallocPDeviceStorageRequestChild(PDeviceStorageRequestChild* aDeviceStorage)
  1.1075 +{
  1.1076 +    delete aDeviceStorage;
  1.1077 +    return true;
  1.1078 +}
  1.1079 +
  1.1080 +PFileSystemRequestChild*
  1.1081 +ContentChild::AllocPFileSystemRequestChild(const FileSystemParams& aParams)
  1.1082 +{
  1.1083 +    NS_NOTREACHED("Should never get here!");
  1.1084 +    return nullptr;
  1.1085 +}
  1.1086 +
  1.1087 +bool
  1.1088 +ContentChild::DeallocPFileSystemRequestChild(PFileSystemRequestChild* aFileSystem)
  1.1089 +{
  1.1090 +    mozilla::dom::FileSystemTaskBase* child =
  1.1091 +      static_cast<mozilla::dom::FileSystemTaskBase*>(aFileSystem);
  1.1092 +    // The reference is increased in FileSystemTaskBase::Start of
  1.1093 +    // FileSystemTaskBase.cpp. We should decrease it after IPC.
  1.1094 +    NS_RELEASE(child);
  1.1095 +    return true;
  1.1096 +}
  1.1097 +
  1.1098 +PNeckoChild*
  1.1099 +ContentChild::AllocPNeckoChild()
  1.1100 +{
  1.1101 +    return new NeckoChild();
  1.1102 +}
  1.1103 +
  1.1104 +bool
  1.1105 +ContentChild::DeallocPNeckoChild(PNeckoChild* necko)
  1.1106 +{
  1.1107 +    delete necko;
  1.1108 +    return true;
  1.1109 +}
  1.1110 +
  1.1111 +PExternalHelperAppChild*
  1.1112 +ContentChild::AllocPExternalHelperAppChild(const OptionalURIParams& uri,
  1.1113 +                                           const nsCString& aMimeContentType,
  1.1114 +                                           const nsCString& aContentDisposition,
  1.1115 +                                           const uint32_t& aContentDispositionHint,
  1.1116 +                                           const nsString& aContentDispositionFilename,
  1.1117 +                                           const bool& aForceSave,
  1.1118 +                                           const int64_t& aContentLength,
  1.1119 +                                           const OptionalURIParams& aReferrer,
  1.1120 +                                           PBrowserChild* aBrowser)
  1.1121 +{
  1.1122 +    ExternalHelperAppChild *child = new ExternalHelperAppChild();
  1.1123 +    child->AddRef();
  1.1124 +    return child;
  1.1125 +}
  1.1126 +
  1.1127 +bool
  1.1128 +ContentChild::DeallocPExternalHelperAppChild(PExternalHelperAppChild* aService)
  1.1129 +{
  1.1130 +    ExternalHelperAppChild *child = static_cast<ExternalHelperAppChild*>(aService);
  1.1131 +    child->Release();
  1.1132 +    return true;
  1.1133 +}
  1.1134 +
  1.1135 +PSmsChild*
  1.1136 +ContentChild::AllocPSmsChild()
  1.1137 +{
  1.1138 +    return new SmsChild();
  1.1139 +}
  1.1140 +
  1.1141 +bool
  1.1142 +ContentChild::DeallocPSmsChild(PSmsChild* aSms)
  1.1143 +{
  1.1144 +    delete aSms;
  1.1145 +    return true;
  1.1146 +}
  1.1147 +
  1.1148 +PTelephonyChild*
  1.1149 +ContentChild::AllocPTelephonyChild()
  1.1150 +{
  1.1151 +    MOZ_CRASH("No one should be allocating PTelephonyChild actors");
  1.1152 +}
  1.1153 +
  1.1154 +bool
  1.1155 +ContentChild::DeallocPTelephonyChild(PTelephonyChild* aActor)
  1.1156 +{
  1.1157 +    delete aActor;
  1.1158 +    return true;
  1.1159 +}
  1.1160 +
  1.1161 +PStorageChild*
  1.1162 +ContentChild::AllocPStorageChild()
  1.1163 +{
  1.1164 +    NS_NOTREACHED("We should never be manually allocating PStorageChild actors");
  1.1165 +    return nullptr;
  1.1166 +}
  1.1167 +
  1.1168 +bool
  1.1169 +ContentChild::DeallocPStorageChild(PStorageChild* aActor)
  1.1170 +{
  1.1171 +    DOMStorageDBChild* child = static_cast<DOMStorageDBChild*>(aActor);
  1.1172 +    child->ReleaseIPDLReference();
  1.1173 +    return true;
  1.1174 +}
  1.1175 +
  1.1176 +PBluetoothChild*
  1.1177 +ContentChild::AllocPBluetoothChild()
  1.1178 +{
  1.1179 +#ifdef MOZ_B2G_BT
  1.1180 +    MOZ_CRASH("No one should be allocating PBluetoothChild actors");
  1.1181 +#else
  1.1182 +    MOZ_CRASH("No support for bluetooth on this platform!");
  1.1183 +#endif
  1.1184 +}
  1.1185 +
  1.1186 +bool
  1.1187 +ContentChild::DeallocPBluetoothChild(PBluetoothChild* aActor)
  1.1188 +{
  1.1189 +#ifdef MOZ_B2G_BT
  1.1190 +    delete aActor;
  1.1191 +    return true;
  1.1192 +#else
  1.1193 +    MOZ_CRASH("No support for bluetooth on this platform!");
  1.1194 +#endif
  1.1195 +}
  1.1196 +
  1.1197 +PFMRadioChild*
  1.1198 +ContentChild::AllocPFMRadioChild()
  1.1199 +{
  1.1200 +#ifdef MOZ_B2G_FM
  1.1201 +    NS_RUNTIMEABORT("No one should be allocating PFMRadioChild actors");
  1.1202 +    return nullptr;
  1.1203 +#else
  1.1204 +    NS_RUNTIMEABORT("No support for FMRadio on this platform!");
  1.1205 +    return nullptr;
  1.1206 +#endif
  1.1207 +}
  1.1208 +
  1.1209 +bool
  1.1210 +ContentChild::DeallocPFMRadioChild(PFMRadioChild* aActor)
  1.1211 +{
  1.1212 +#ifdef MOZ_B2G_FM
  1.1213 +    delete aActor;
  1.1214 +    return true;
  1.1215 +#else
  1.1216 +    NS_RUNTIMEABORT("No support for FMRadio on this platform!");
  1.1217 +    return false;
  1.1218 +#endif
  1.1219 +}
  1.1220 +
  1.1221 +PSpeechSynthesisChild*
  1.1222 +ContentChild::AllocPSpeechSynthesisChild()
  1.1223 +{
  1.1224 +#ifdef MOZ_WEBSPEECH
  1.1225 +    MOZ_CRASH("No one should be allocating PSpeechSynthesisChild actors");
  1.1226 +#else
  1.1227 +    return nullptr;
  1.1228 +#endif
  1.1229 +}
  1.1230 +
  1.1231 +bool
  1.1232 +ContentChild::DeallocPSpeechSynthesisChild(PSpeechSynthesisChild* aActor)
  1.1233 +{
  1.1234 +#ifdef MOZ_WEBSPEECH
  1.1235 +    delete aActor;
  1.1236 +    return true;
  1.1237 +#else
  1.1238 +    return false;
  1.1239 +#endif
  1.1240 +}
  1.1241 +
  1.1242 +bool
  1.1243 +ContentChild::RecvRegisterChrome(const InfallibleTArray<ChromePackage>& packages,
  1.1244 +                                 const InfallibleTArray<ResourceMapping>& resources,
  1.1245 +                                 const InfallibleTArray<OverrideMapping>& overrides,
  1.1246 +                                 const nsCString& locale)
  1.1247 +{
  1.1248 +    nsCOMPtr<nsIChromeRegistry> registrySvc = nsChromeRegistry::GetService();
  1.1249 +    nsChromeRegistryContent* chromeRegistry =
  1.1250 +        static_cast<nsChromeRegistryContent*>(registrySvc.get());
  1.1251 +    chromeRegistry->RegisterRemoteChrome(packages, resources, overrides, locale);
  1.1252 +    return true;
  1.1253 +}
  1.1254 +
  1.1255 +bool
  1.1256 +ContentChild::RecvSetOffline(const bool& offline)
  1.1257 +{
  1.1258 +  nsCOMPtr<nsIIOService> io (do_GetIOService());
  1.1259 +  NS_ASSERTION(io, "IO Service can not be null");
  1.1260 +
  1.1261 +  io->SetOffline(offline);
  1.1262 +
  1.1263 +  return true;
  1.1264 +}
  1.1265 +
  1.1266 +void
  1.1267 +ContentChild::ActorDestroy(ActorDestroyReason why)
  1.1268 +{
  1.1269 +    if (AbnormalShutdown == why) {
  1.1270 +        NS_WARNING("shutting down early because of crash!");
  1.1271 +        QuickExit();
  1.1272 +    }
  1.1273 +
  1.1274 +#ifndef DEBUG
  1.1275 +    // In release builds, there's no point in the content process
  1.1276 +    // going through the full XPCOM shutdown path, because it doesn't
  1.1277 +    // keep persistent state.
  1.1278 +    QuickExit();
  1.1279 +#endif
  1.1280 +
  1.1281 +    if (sFirstIdleTask) {
  1.1282 +        sFirstIdleTask->Cancel();
  1.1283 +    }
  1.1284 +
  1.1285 +    mAlertObservers.Clear();
  1.1286 +
  1.1287 +    mIdleObservers.Clear();
  1.1288 +
  1.1289 +    nsCOMPtr<nsIConsoleService> svc(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
  1.1290 +    if (svc) {
  1.1291 +        svc->UnregisterListener(mConsoleListener);
  1.1292 +        mConsoleListener->mChild = nullptr;
  1.1293 +    }
  1.1294 +
  1.1295 +    XRE_ShutdownChildProcess();
  1.1296 +}
  1.1297 +
  1.1298 +void
  1.1299 +ContentChild::ProcessingError(Result what)
  1.1300 +{
  1.1301 +    switch (what) {
  1.1302 +    case MsgDropped:
  1.1303 +        QuickExit();
  1.1304 +
  1.1305 +    case MsgNotKnown:
  1.1306 +        NS_RUNTIMEABORT("aborting because of MsgNotKnown");
  1.1307 +    case MsgNotAllowed:
  1.1308 +        NS_RUNTIMEABORT("aborting because of MsgNotAllowed");
  1.1309 +    case MsgPayloadError:
  1.1310 +        NS_RUNTIMEABORT("aborting because of MsgPayloadError");
  1.1311 +    case MsgProcessingError:
  1.1312 +        NS_RUNTIMEABORT("aborting because of MsgProcessingError");
  1.1313 +    case MsgRouteError:
  1.1314 +        NS_RUNTIMEABORT("aborting because of MsgRouteError");
  1.1315 +    case MsgValueError:
  1.1316 +        NS_RUNTIMEABORT("aborting because of MsgValueError");
  1.1317 +
  1.1318 +    default:
  1.1319 +        NS_RUNTIMEABORT("not reached");
  1.1320 +    }
  1.1321 +}
  1.1322 +
  1.1323 +void
  1.1324 +ContentChild::QuickExit()
  1.1325 +{
  1.1326 +    NS_WARNING("content process _exit()ing");
  1.1327 +    _exit(0);
  1.1328 +}
  1.1329 +
  1.1330 +nsresult
  1.1331 +ContentChild::AddRemoteAlertObserver(const nsString& aData,
  1.1332 +                                     nsIObserver* aObserver)
  1.1333 +{
  1.1334 +    NS_ASSERTION(aObserver, "Adding a null observer?");
  1.1335 +    mAlertObservers.AppendElement(new AlertObserver(aObserver, aData));
  1.1336 +    return NS_OK;
  1.1337 +}
  1.1338 +
  1.1339 +bool
  1.1340 +ContentChild::RecvPreferenceUpdate(const PrefSetting& aPref)
  1.1341 +{
  1.1342 +    Preferences::SetPreference(aPref);
  1.1343 +    return true;
  1.1344 +}
  1.1345 +
  1.1346 +bool
  1.1347 +ContentChild::RecvNotifyAlertsObserver(const nsCString& aType, const nsString& aData)
  1.1348 +{
  1.1349 +    for (uint32_t i = 0; i < mAlertObservers.Length();
  1.1350 +         /*we mutate the array during the loop; ++i iff no mutation*/) {
  1.1351 +        AlertObserver* observer = mAlertObservers[i];
  1.1352 +        if (observer->Observes(aData) && observer->Notify(aType)) {
  1.1353 +            // if aType == alertfinished, this alert is done.  we can
  1.1354 +            // remove the observer.
  1.1355 +            if (aType.Equals(nsDependentCString("alertfinished"))) {
  1.1356 +                mAlertObservers.RemoveElementAt(i);
  1.1357 +                continue;
  1.1358 +            }
  1.1359 +        }
  1.1360 +        ++i;
  1.1361 +    }
  1.1362 +    return true;
  1.1363 +}
  1.1364 +
  1.1365 +bool
  1.1366 +ContentChild::RecvNotifyVisited(const URIParams& aURI)
  1.1367 +{
  1.1368 +    nsCOMPtr<nsIURI> newURI = DeserializeURI(aURI);
  1.1369 +    if (!newURI) {
  1.1370 +        return false;
  1.1371 +    }
  1.1372 +    nsCOMPtr<IHistory> history = services::GetHistoryService();
  1.1373 +    if (history) {
  1.1374 +      history->NotifyVisited(newURI);
  1.1375 +    }
  1.1376 +    return true;
  1.1377 +}
  1.1378 +
  1.1379 +bool
  1.1380 +ContentChild::RecvAsyncMessage(const nsString& aMsg,
  1.1381 +                               const ClonedMessageData& aData,
  1.1382 +                               const InfallibleTArray<CpowEntry>& aCpows,
  1.1383 +                               const IPC::Principal& aPrincipal)
  1.1384 +{
  1.1385 +  nsRefPtr<nsFrameMessageManager> cpm = nsFrameMessageManager::sChildProcessManager;
  1.1386 +  if (cpm) {
  1.1387 +    StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForChild(aData);
  1.1388 +    CpowIdHolder cpows(GetCPOWManager(), aCpows);
  1.1389 +    cpm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(cpm.get()),
  1.1390 +                        aMsg, false, &cloneData, &cpows, aPrincipal, nullptr);
  1.1391 +  }
  1.1392 +  return true;
  1.1393 +}
  1.1394 +
  1.1395 +bool
  1.1396 +ContentChild::RecvGeolocationUpdate(const GeoPosition& somewhere)
  1.1397 +{
  1.1398 +  nsCOMPtr<nsIGeolocationUpdate> gs = do_GetService("@mozilla.org/geolocation/service;1");
  1.1399 +  if (!gs) {
  1.1400 +    return true;
  1.1401 +  }
  1.1402 +  nsCOMPtr<nsIDOMGeoPosition> position = somewhere;
  1.1403 +  gs->Update(position);
  1.1404 +  return true;
  1.1405 +}
  1.1406 +
  1.1407 +bool
  1.1408 +ContentChild::RecvAddPermission(const IPC::Permission& permission)
  1.1409 +{
  1.1410 +#if MOZ_PERMISSIONS
  1.1411 +  nsCOMPtr<nsIPermissionManager> permissionManagerIface =
  1.1412 +      do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
  1.1413 +  nsPermissionManager* permissionManager =
  1.1414 +      static_cast<nsPermissionManager*>(permissionManagerIface.get());
  1.1415 +  NS_ABORT_IF_FALSE(permissionManager, 
  1.1416 +                   "We have no permissionManager in the Content process !");
  1.1417 +
  1.1418 +  nsCOMPtr<nsIURI> uri;
  1.1419 +  NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("http://") + nsCString(permission.host));
  1.1420 +  NS_ENSURE_TRUE(uri, true);
  1.1421 +
  1.1422 +  nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
  1.1423 +  MOZ_ASSERT(secMan);
  1.1424 +
  1.1425 +  nsCOMPtr<nsIPrincipal> principal;
  1.1426 +  nsresult rv = secMan->GetAppCodebasePrincipal(uri, permission.appId,
  1.1427 +                                                permission.isInBrowserElement,
  1.1428 +                                                getter_AddRefs(principal));
  1.1429 +  NS_ENSURE_SUCCESS(rv, true);
  1.1430 +
  1.1431 +  permissionManager->AddInternal(principal,
  1.1432 +                                 nsCString(permission.type),
  1.1433 +                                 permission.capability,
  1.1434 +                                 0,
  1.1435 +                                 permission.expireType,
  1.1436 +                                 permission.expireTime,
  1.1437 +                                 nsPermissionManager::eNotify,
  1.1438 +                                 nsPermissionManager::eNoDBOperation);
  1.1439 +#endif
  1.1440 +
  1.1441 +  return true;
  1.1442 +}
  1.1443 +
  1.1444 +bool
  1.1445 +ContentChild::RecvScreenSizeChanged(const gfxIntSize& size)
  1.1446 +{
  1.1447 +#ifdef ANDROID
  1.1448 +    mScreenSize = size;
  1.1449 +#else
  1.1450 +    NS_RUNTIMEABORT("Message currently only expected on android");
  1.1451 +#endif
  1.1452 +  return true;
  1.1453 +}
  1.1454 +
  1.1455 +bool
  1.1456 +ContentChild::RecvFlushMemory(const nsString& reason)
  1.1457 +{
  1.1458 +#ifdef MOZ_NUWA_PROCESS
  1.1459 +    if (IsNuwaProcess()) {
  1.1460 +        // Don't flush memory in the nuwa process: the GC thread could be frozen.
  1.1461 +        return true;
  1.1462 +    }
  1.1463 +#endif
  1.1464 +    nsCOMPtr<nsIObserverService> os =
  1.1465 +        mozilla::services::GetObserverService();
  1.1466 +    if (os)
  1.1467 +        os->NotifyObservers(nullptr, "memory-pressure", reason.get());
  1.1468 +    return true;
  1.1469 +}
  1.1470 +
  1.1471 +bool
  1.1472 +ContentChild::RecvActivateA11y()
  1.1473 +{
  1.1474 +#ifdef ACCESSIBILITY
  1.1475 +    // Start accessibility in content process if it's running in chrome
  1.1476 +    // process.
  1.1477 +    nsCOMPtr<nsIAccessibilityService> accService =
  1.1478 +        do_GetService("@mozilla.org/accessibilityService;1");
  1.1479 +#endif
  1.1480 +    return true;
  1.1481 +}
  1.1482 +
  1.1483 +bool
  1.1484 +ContentChild::RecvGarbageCollect()
  1.1485 +{
  1.1486 +    // Rebroadcast the "child-gc-request" so that workers will GC.
  1.1487 +    nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
  1.1488 +    if (obs) {
  1.1489 +        obs->NotifyObservers(nullptr, "child-gc-request", nullptr);
  1.1490 +    }
  1.1491 +    nsJSContext::GarbageCollectNow(JS::gcreason::DOM_IPC);
  1.1492 +    return true;
  1.1493 +}
  1.1494 +
  1.1495 +bool
  1.1496 +ContentChild::RecvCycleCollect()
  1.1497 +{
  1.1498 +    // Rebroadcast the "child-cc-request" so that workers will CC.
  1.1499 +    nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
  1.1500 +    if (obs) {
  1.1501 +        obs->NotifyObservers(nullptr, "child-cc-request", nullptr);
  1.1502 +    }
  1.1503 +    nsJSContext::CycleCollectNow();
  1.1504 +    return true;
  1.1505 +}
  1.1506 +
  1.1507 +#ifdef MOZ_NUWA_PROCESS
  1.1508 +static void
  1.1509 +OnFinishNuwaPreparation ()
  1.1510 +{
  1.1511 +    MakeNuwaProcess();
  1.1512 +}
  1.1513 +#endif
  1.1514 +
  1.1515 +static void
  1.1516 +PreloadSlowThings()
  1.1517 +{
  1.1518 +    // This fetches and creates all the built-in stylesheets.
  1.1519 +    nsLayoutStylesheetCache::UserContentSheet();
  1.1520 +
  1.1521 +    TabChild::PreloadSlowThings();
  1.1522 +
  1.1523 +}
  1.1524 +
  1.1525 +bool
  1.1526 +ContentChild::RecvAppInfo(const nsCString& version, const nsCString& buildID,
  1.1527 +                          const nsCString& name, const nsCString& UAName)
  1.1528 +{
  1.1529 +    mAppInfo.version.Assign(version);
  1.1530 +    mAppInfo.buildID.Assign(buildID);
  1.1531 +    mAppInfo.name.Assign(name);
  1.1532 +    mAppInfo.UAName.Assign(UAName);
  1.1533 +
  1.1534 +    if (!Preferences::GetBool("dom.ipc.processPrelaunch.enabled", false)) {
  1.1535 +        return true;
  1.1536 +    }
  1.1537 +
  1.1538 +    // If we're part of the mozbrowser machinery, go ahead and start
  1.1539 +    // preloading things.  We can only do this for mozbrowser because
  1.1540 +    // PreloadSlowThings() may set the docshell of the first TabChild
  1.1541 +    // inactive, and we can only safely restore it to active from
  1.1542 +    // BrowserElementChild.js.
  1.1543 +    if ((mIsForApp || mIsForBrowser)
  1.1544 +#ifdef MOZ_NUWA_PROCESS
  1.1545 +        && !IsNuwaProcess()
  1.1546 +#endif
  1.1547 +       ) {
  1.1548 +        PreloadSlowThings();
  1.1549 +    }
  1.1550 +
  1.1551 +#ifdef MOZ_NUWA_PROCESS
  1.1552 +    if (IsNuwaProcess()) {
  1.1553 +        ContentChild::GetSingleton()->RecvGarbageCollect();
  1.1554 +        MessageLoop::current()->PostTask(
  1.1555 +            FROM_HERE, NewRunnableFunction(OnFinishNuwaPreparation));
  1.1556 +    }
  1.1557 +#endif
  1.1558 +
  1.1559 +    return true;
  1.1560 +}
  1.1561 +
  1.1562 +bool
  1.1563 +ContentChild::RecvLastPrivateDocShellDestroyed()
  1.1564 +{
  1.1565 +    nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
  1.1566 +    obs->NotifyObservers(nullptr, "last-pb-context-exited", nullptr);
  1.1567 +    return true;
  1.1568 +}
  1.1569 +
  1.1570 +bool
  1.1571 +ContentChild::RecvFilePathUpdate(const nsString& aStorageType,
  1.1572 +                                 const nsString& aStorageName,
  1.1573 +                                 const nsString& aPath,
  1.1574 +                                 const nsCString& aReason)
  1.1575 +{
  1.1576 +    nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(aStorageType, aStorageName, aPath);
  1.1577 +
  1.1578 +    nsString reason;
  1.1579 +    CopyASCIItoUTF16(aReason, reason);
  1.1580 +    nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
  1.1581 +    obs->NotifyObservers(dsf, "file-watcher-update", reason.get());
  1.1582 +    return true;
  1.1583 +}
  1.1584 +
  1.1585 +bool
  1.1586 +ContentChild::RecvFileSystemUpdate(const nsString& aFsName,
  1.1587 +                                   const nsString& aVolumeName,
  1.1588 +                                   const int32_t& aState,
  1.1589 +                                   const int32_t& aMountGeneration,
  1.1590 +                                   const bool& aIsMediaPresent,
  1.1591 +                                   const bool& aIsSharing,
  1.1592 +                                   const bool& aIsFormatting)
  1.1593 +{
  1.1594 +#ifdef MOZ_WIDGET_GONK
  1.1595 +    nsRefPtr<nsVolume> volume = new nsVolume(aFsName, aVolumeName, aState,
  1.1596 +                                             aMountGeneration, aIsMediaPresent,
  1.1597 +                                             aIsSharing, aIsFormatting);
  1.1598 +
  1.1599 +    nsRefPtr<nsVolumeService> vs = nsVolumeService::GetSingleton();
  1.1600 +    if (vs) {
  1.1601 +        vs->UpdateVolume(volume);
  1.1602 +    }
  1.1603 +#else
  1.1604 +    // Remove warnings about unused arguments
  1.1605 +    unused << aFsName;
  1.1606 +    unused << aVolumeName;
  1.1607 +    unused << aState;
  1.1608 +    unused << aMountGeneration;
  1.1609 +    unused << aIsMediaPresent;
  1.1610 +    unused << aIsSharing;
  1.1611 +    unused << aIsFormatting;
  1.1612 +#endif
  1.1613 +    return true;
  1.1614 +}
  1.1615 +
  1.1616 +bool
  1.1617 +ContentChild::RecvNotifyProcessPriorityChanged(
  1.1618 +    const hal::ProcessPriority& aPriority)
  1.1619 +{
  1.1620 +    nsCOMPtr<nsIObserverService> os = services::GetObserverService();
  1.1621 +    NS_ENSURE_TRUE(os, true);
  1.1622 +
  1.1623 +    nsRefPtr<nsHashPropertyBag> props = new nsHashPropertyBag();
  1.1624 +    props->SetPropertyAsInt32(NS_LITERAL_STRING("priority"),
  1.1625 +                              static_cast<int32_t>(aPriority));
  1.1626 +
  1.1627 +    os->NotifyObservers(static_cast<nsIPropertyBag2*>(props),
  1.1628 +                        "ipc:process-priority-changed",  nullptr);
  1.1629 +    return true;
  1.1630 +}
  1.1631 +
  1.1632 +bool
  1.1633 +ContentChild::RecvMinimizeMemoryUsage()
  1.1634 +{
  1.1635 +#ifdef MOZ_NUWA_PROCESS
  1.1636 +    if (IsNuwaProcess()) {
  1.1637 +        // Don't minimize memory in the nuwa process: it will perform GC, but the
  1.1638 +        // GC thread could be frozen.
  1.1639 +        return true;
  1.1640 +    }
  1.1641 +#endif
  1.1642 +    nsCOMPtr<nsIMemoryReporterManager> mgr =
  1.1643 +        do_GetService("@mozilla.org/memory-reporter-manager;1");
  1.1644 +    NS_ENSURE_TRUE(mgr, true);
  1.1645 +
  1.1646 +    mgr->MinimizeMemoryUsage(/* callback = */ nullptr);
  1.1647 +    return true;
  1.1648 +}
  1.1649 +
  1.1650 +bool
  1.1651 +ContentChild::RecvNotifyPhoneStateChange(const nsString& aState)
  1.1652 +{
  1.1653 +  nsCOMPtr<nsIObserverService> os = services::GetObserverService();
  1.1654 +  if (os) {
  1.1655 +    os->NotifyObservers(nullptr, "phone-state-changed", aState.get());
  1.1656 +  }
  1.1657 +  return true;
  1.1658 +}
  1.1659 +
  1.1660 +void
  1.1661 +ContentChild::AddIdleObserver(nsIObserver* aObserver, uint32_t aIdleTimeInS)
  1.1662 +{
  1.1663 +  MOZ_ASSERT(aObserver, "null idle observer");
  1.1664 +  // Make sure aObserver isn't released while we wait for the parent
  1.1665 +  aObserver->AddRef();
  1.1666 +  SendAddIdleObserver(reinterpret_cast<uint64_t>(aObserver), aIdleTimeInS);
  1.1667 +  mIdleObservers.PutEntry(aObserver);
  1.1668 +}
  1.1669 +
  1.1670 +void
  1.1671 +ContentChild::RemoveIdleObserver(nsIObserver* aObserver, uint32_t aIdleTimeInS)
  1.1672 +{
  1.1673 +  MOZ_ASSERT(aObserver, "null idle observer");
  1.1674 +  SendRemoveIdleObserver(reinterpret_cast<uint64_t>(aObserver), aIdleTimeInS);
  1.1675 +  aObserver->Release();
  1.1676 +  mIdleObservers.RemoveEntry(aObserver);
  1.1677 +}
  1.1678 +
  1.1679 +bool
  1.1680 +ContentChild::RecvNotifyIdleObserver(const uint64_t& aObserver,
  1.1681 +                                     const nsCString& aTopic,
  1.1682 +                                     const nsString& aTimeStr)
  1.1683 +{
  1.1684 +  nsIObserver* observer = reinterpret_cast<nsIObserver*>(aObserver);
  1.1685 +  if (mIdleObservers.Contains(observer)) {
  1.1686 +    observer->Observe(nullptr, aTopic.get(), aTimeStr.get());
  1.1687 +  } else {
  1.1688 +    NS_WARNING("Received notification for an idle observer that was removed.");
  1.1689 +  }
  1.1690 +  return true;
  1.1691 +}
  1.1692 +
  1.1693 +bool
  1.1694 +ContentChild::RecvLoadAndRegisterSheet(const URIParams& aURI, const uint32_t& aType)
  1.1695 +{
  1.1696 +    nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
  1.1697 +    if (!uri) {
  1.1698 +        return true;
  1.1699 +    }
  1.1700 +
  1.1701 +    nsStyleSheetService *sheetService = nsStyleSheetService::GetInstance();
  1.1702 +    if (sheetService) {
  1.1703 +        sheetService->LoadAndRegisterSheet(uri, aType);
  1.1704 +    }
  1.1705 +
  1.1706 +    return true;
  1.1707 +}
  1.1708 +
  1.1709 +bool
  1.1710 +ContentChild::RecvUnregisterSheet(const URIParams& aURI, const uint32_t& aType)
  1.1711 +{
  1.1712 +    nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
  1.1713 +    if (!uri) {
  1.1714 +        return true;
  1.1715 +    }
  1.1716 +
  1.1717 +    nsStyleSheetService *sheetService = nsStyleSheetService::GetInstance();
  1.1718 +    if (sheetService) {
  1.1719 +        sheetService->UnregisterSheet(uri, aType);
  1.1720 +    }
  1.1721 +
  1.1722 +    return true;
  1.1723 +}
  1.1724 +
  1.1725 +#ifdef MOZ_NUWA_PROCESS
  1.1726 +class CallNuwaSpawn : public nsRunnable
  1.1727 +{
  1.1728 +public:
  1.1729 +    NS_IMETHOD Run()
  1.1730 +    {
  1.1731 +        NuwaSpawn();
  1.1732 +        if (IsNuwaProcess()) {
  1.1733 +            return NS_OK;
  1.1734 +        }
  1.1735 +
  1.1736 +        // In the new process.
  1.1737 +        ContentChild* child = ContentChild::GetSingleton();
  1.1738 +        child->SetProcessName(NS_LITERAL_STRING("(Preallocated app)"), false);
  1.1739 +        mozilla::ipc::Transport* transport = child->GetTransport();
  1.1740 +        int fd = transport->GetFileDescriptor();
  1.1741 +        transport->ResetFileDescriptor(fd);
  1.1742 +
  1.1743 +        IToplevelProtocol* toplevel = child->GetFirstOpenedActors();
  1.1744 +        while (toplevel != nullptr) {
  1.1745 +            transport = toplevel->GetTransport();
  1.1746 +            fd = transport->GetFileDescriptor();
  1.1747 +            transport->ResetFileDescriptor(fd);
  1.1748 +
  1.1749 +            toplevel = toplevel->getNext();
  1.1750 +        }
  1.1751 +
  1.1752 +        // Perform other after-fork initializations.
  1.1753 +        InitOnContentProcessCreated();
  1.1754 +
  1.1755 +        return NS_OK;
  1.1756 +    }
  1.1757 +};
  1.1758 +
  1.1759 +static void
  1.1760 +DoNuwaFork()
  1.1761 +{
  1.1762 +    NS_ASSERTION(NuwaSpawnPrepare != nullptr,
  1.1763 +                 "NuwaSpawnPrepare() is not available!");
  1.1764 +    NuwaSpawnPrepare();       // NuwaSpawn will be blocked.
  1.1765 +
  1.1766 +    {
  1.1767 +        nsCOMPtr<nsIRunnable> callSpawn(new CallNuwaSpawn());
  1.1768 +        NS_DispatchToMainThread(callSpawn);
  1.1769 +    }
  1.1770 +
  1.1771 +    // IOThread should be blocked here for waiting NuwaSpawn().
  1.1772 +    NS_ASSERTION(NuwaSpawnWait != nullptr,
  1.1773 +                 "NuwaSpawnWait() is not available!");
  1.1774 +    NuwaSpawnWait();        // Now! NuwaSpawn can go.
  1.1775 +    // Here, we can make sure the spawning was finished.
  1.1776 +}
  1.1777 +
  1.1778 +/**
  1.1779 + * This function should keep IO thread in a stable state and freeze it
  1.1780 + * until the spawning is finished.
  1.1781 + */
  1.1782 +static void
  1.1783 +RunNuwaFork()
  1.1784 +{
  1.1785 +    if (NuwaCheckpointCurrentThread()) {
  1.1786 +      DoNuwaFork();
  1.1787 +    }
  1.1788 +}
  1.1789 +#endif
  1.1790 +
  1.1791 +bool
  1.1792 +ContentChild::RecvNuwaFork()
  1.1793 +{
  1.1794 +#ifdef MOZ_NUWA_PROCESS
  1.1795 +    if (sNuwaForking) {           // No reentry.
  1.1796 +        return true;
  1.1797 +    }
  1.1798 +    sNuwaForking = true;
  1.1799 +
  1.1800 +    // We want to ensure that the PBackground actor gets cloned in the Nuwa
  1.1801 +    // process before we freeze. Also, we have to do this to avoid deadlock.
  1.1802 +    // Protocols that are "opened" (e.g. PBackground, PCompositor) block the
  1.1803 +    // main thread to wait for the IPC thread during the open operation.
  1.1804 +    // NuwaSpawnWait() blocks the IPC thread to wait for the main thread when
  1.1805 +    // the Nuwa process is forked. Unless we ensure that the two cannot happen
  1.1806 +    // at the same time then we risk deadlock. Spinning the event loop here
  1.1807 +    // guarantees the ordering is safe for PBackground.
  1.1808 +    while (!BackgroundChild::GetForCurrentThread()) {
  1.1809 +        if (NS_WARN_IF(!NS_ProcessNextEvent())) {
  1.1810 +            return false;
  1.1811 +        }
  1.1812 +    }
  1.1813 +
  1.1814 +    MessageLoop* ioloop = XRE_GetIOMessageLoop();
  1.1815 +    ioloop->PostTask(FROM_HERE, NewRunnableFunction(RunNuwaFork));
  1.1816 +    return true;
  1.1817 +#else
  1.1818 +    return false; // Makes the underlying IPC channel abort.
  1.1819 +#endif
  1.1820 +}
  1.1821 +
  1.1822 +} // namespace dom
  1.1823 +} // namespace mozilla
  1.1824 +
  1.1825 +extern "C" {
  1.1826 +
  1.1827 +#if defined(MOZ_NUWA_PROCESS)
  1.1828 +NS_EXPORT void
  1.1829 +GetProtoFdInfos(NuwaProtoFdInfo* aInfoList,
  1.1830 +                size_t aInfoListSize,
  1.1831 +                size_t* aInfoSize)
  1.1832 +{
  1.1833 +    size_t i = 0;
  1.1834 +
  1.1835 +    mozilla::dom::ContentChild* content =
  1.1836 +        mozilla::dom::ContentChild::GetSingleton();
  1.1837 +    aInfoList[i].protoId = content->GetProtocolId();
  1.1838 +    aInfoList[i].originFd =
  1.1839 +        content->GetTransport()->GetFileDescriptor();
  1.1840 +    i++;
  1.1841 +
  1.1842 +    for (IToplevelProtocol* actor = content->GetFirstOpenedActors();
  1.1843 +         actor != nullptr;
  1.1844 +         actor = actor->getNext()) {
  1.1845 +        if (i >= aInfoListSize) {
  1.1846 +            NS_RUNTIMEABORT("Too many top level protocols!");
  1.1847 +        }
  1.1848 +
  1.1849 +        aInfoList[i].protoId = actor->GetProtocolId();
  1.1850 +        aInfoList[i].originFd =
  1.1851 +            actor->GetTransport()->GetFileDescriptor();
  1.1852 +        i++;
  1.1853 +    }
  1.1854 +
  1.1855 +    if (i > NUWA_TOPLEVEL_MAX) {
  1.1856 +        NS_RUNTIMEABORT("Too many top level protocols!");
  1.1857 +    }
  1.1858 +    *aInfoSize = i;
  1.1859 +}
  1.1860 +
  1.1861 +class RunAddNewIPCProcess : public nsRunnable
  1.1862 +{
  1.1863 +public:
  1.1864 +    RunAddNewIPCProcess(pid_t aPid,
  1.1865 +                        nsTArray<mozilla::ipc::ProtocolFdMapping>& aMaps)
  1.1866 +        : mPid(aPid)
  1.1867 +    {
  1.1868 +        mMaps.SwapElements(aMaps);
  1.1869 +    }
  1.1870 +
  1.1871 +    NS_IMETHOD Run()
  1.1872 +    {
  1.1873 +        mozilla::dom::ContentChild::GetSingleton()->
  1.1874 +            SendAddNewProcess(mPid, mMaps);
  1.1875 +
  1.1876 +        MOZ_ASSERT(sNuwaForking);
  1.1877 +        sNuwaForking = false;
  1.1878 +
  1.1879 +        return NS_OK;
  1.1880 +    }
  1.1881 +
  1.1882 +private:
  1.1883 +    pid_t mPid;
  1.1884 +    nsTArray<mozilla::ipc::ProtocolFdMapping> mMaps;
  1.1885 +};
  1.1886 +
  1.1887 +/**
  1.1888 + * AddNewIPCProcess() is called by Nuwa process to tell the parent
  1.1889 + * process that a new process is created.
  1.1890 + *
  1.1891 + * In the newly created process, ResetContentChildTransport() is called to
  1.1892 + * reset fd for the IPC Channel and the session.
  1.1893 + */
  1.1894 +NS_EXPORT void
  1.1895 +AddNewIPCProcess(pid_t aPid, NuwaProtoFdInfo* aInfoList, size_t aInfoListSize)
  1.1896 +{
  1.1897 +    nsTArray<mozilla::ipc::ProtocolFdMapping> maps;
  1.1898 +
  1.1899 +    for (size_t i = 0; i < aInfoListSize; i++) {
  1.1900 +        int _fd = aInfoList[i].newFds[NUWA_NEWFD_PARENT];
  1.1901 +        mozilla::ipc::FileDescriptor fd(_fd);
  1.1902 +        mozilla::ipc::ProtocolFdMapping map(aInfoList[i].protoId, fd);
  1.1903 +        maps.AppendElement(map);
  1.1904 +    }
  1.1905 +
  1.1906 +    nsRefPtr<RunAddNewIPCProcess> runner = new RunAddNewIPCProcess(aPid, maps);
  1.1907 +    NS_DispatchToMainThread(runner);
  1.1908 +}
  1.1909 +
  1.1910 +NS_EXPORT void
  1.1911 +OnNuwaProcessReady()
  1.1912 +{
  1.1913 +    mozilla::dom::ContentChild* content =
  1.1914 +        mozilla::dom::ContentChild::GetSingleton();
  1.1915 +    content->SendNuwaReady();
  1.1916 +}
  1.1917 +
  1.1918 +NS_EXPORT void
  1.1919 +AfterNuwaFork()
  1.1920 +{
  1.1921 +    SetCurrentProcessPrivileges(base::PRIVILEGES_DEFAULT);
  1.1922 +}
  1.1923 +
  1.1924 +#endif // MOZ_NUWA_PROCESS
  1.1925 +
  1.1926 +}

mercurial