dom/ipc/ContentParent.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/dom/ipc/ContentParent.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,3449 @@
     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 +#include "mozilla/DebugOnly.h"
    1.11 +
    1.12 +#include "base/basictypes.h"
    1.13 +
    1.14 +#include "ContentParent.h"
    1.15 +
    1.16 +#if defined(ANDROID) || defined(LINUX)
    1.17 +# include <sys/time.h>
    1.18 +# include <sys/resource.h>
    1.19 +#endif
    1.20 +
    1.21 +#ifdef MOZ_WIDGET_GONK
    1.22 +#include <sys/types.h>
    1.23 +#include <sys/wait.h>
    1.24 +#endif
    1.25 +
    1.26 +#include "chrome/common/process_watcher.h"
    1.27 +
    1.28 +#include "AppProcessChecker.h"
    1.29 +#include "AudioChannelService.h"
    1.30 +#include "CrashReporterParent.h"
    1.31 +#include "IHistory.h"
    1.32 +#include "IDBFactory.h"
    1.33 +#include "IndexedDBParent.h"
    1.34 +#include "IndexedDatabaseManager.h"
    1.35 +#include "mozIApplication.h"
    1.36 +#include "mozilla/ClearOnShutdown.h"
    1.37 +#include "mozilla/dom/asmjscache/AsmJSCache.h"
    1.38 +#include "mozilla/dom/Element.h"
    1.39 +#include "mozilla/dom/ExternalHelperAppParent.h"
    1.40 +#include "mozilla/dom/PFileDescriptorSetParent.h"
    1.41 +#include "mozilla/dom/PMemoryReportRequestParent.h"
    1.42 +#include "mozilla/dom/power/PowerManagerService.h"
    1.43 +#include "mozilla/dom/DOMStorageIPC.h"
    1.44 +#include "mozilla/dom/bluetooth/PBluetoothParent.h"
    1.45 +#include "mozilla/dom/PFMRadioParent.h"
    1.46 +#include "mozilla/dom/devicestorage/DeviceStorageRequestParent.h"
    1.47 +#include "mozilla/dom/FileSystemRequestParent.h"
    1.48 +#include "mozilla/dom/GeolocationBinding.h"
    1.49 +#include "mozilla/dom/FileDescriptorSetParent.h"
    1.50 +#include "mozilla/dom/telephony/TelephonyParent.h"
    1.51 +#include "mozilla/dom/time/DateCacheCleaner.h"
    1.52 +#include "SmsParent.h"
    1.53 +#include "mozilla/hal_sandbox/PHalParent.h"
    1.54 +#include "mozilla/ipc/BackgroundChild.h"
    1.55 +#include "mozilla/ipc/BackgroundParent.h"
    1.56 +#include "mozilla/ipc/TestShellParent.h"
    1.57 +#include "mozilla/ipc/InputStreamUtils.h"
    1.58 +#include "mozilla/layers/CompositorParent.h"
    1.59 +#include "mozilla/layers/ImageBridgeParent.h"
    1.60 +#include "mozilla/net/NeckoParent.h"
    1.61 +#include "mozilla/Preferences.h"
    1.62 +#include "mozilla/Services.h"
    1.63 +#include "mozilla/StaticPtr.h"
    1.64 +#include "mozilla/unused.h"
    1.65 +#include "nsAppRunner.h"
    1.66 +#include "nsAutoPtr.h"
    1.67 +#include "nsCDefaultURIFixup.h"
    1.68 +#include "nsCExternalHandlerService.h"
    1.69 +#include "nsCOMPtr.h"
    1.70 +#include "nsChromeRegistryChrome.h"
    1.71 +#include "nsConsoleMessage.h"
    1.72 +#include "nsConsoleService.h"
    1.73 +#include "nsDebugImpl.h"
    1.74 +#include "nsDOMFile.h"
    1.75 +#include "nsFrameMessageManager.h"
    1.76 +#include "nsHashPropertyBag.h"
    1.77 +#include "nsIAlertsService.h"
    1.78 +#include "nsIAppsService.h"
    1.79 +#include "nsIClipboard.h"
    1.80 +#include "nsIDOMGeoGeolocation.h"
    1.81 +#include "mozilla/dom/WakeLock.h"
    1.82 +#include "nsIDOMWindow.h"
    1.83 +#include "nsIExternalProtocolService.h"
    1.84 +#include "nsIGfxInfo.h"
    1.85 +#include "nsIIdleService.h"
    1.86 +#include "nsIMemoryReporter.h"
    1.87 +#include "nsIMozBrowserFrame.h"
    1.88 +#include "nsIMutable.h"
    1.89 +#include "nsIObserverService.h"
    1.90 +#include "nsIPresShell.h"
    1.91 +#include "nsIRemoteBlob.h"
    1.92 +#include "nsIScriptError.h"
    1.93 +#include "nsIStyleSheet.h"
    1.94 +#include "nsISupportsPrimitives.h"
    1.95 +#include "nsIURIFixup.h"
    1.96 +#include "nsIWindowWatcher.h"
    1.97 +#include "nsIXULRuntime.h"
    1.98 +#include "nsMemoryReporterManager.h"
    1.99 +#include "nsServiceManagerUtils.h"
   1.100 +#include "nsStyleSheetService.h"
   1.101 +#include "nsThreadUtils.h"
   1.102 +#include "nsToolkitCompsCID.h"
   1.103 +#include "nsWidgetsCID.h"
   1.104 +#include "PreallocatedProcessManager.h"
   1.105 +#include "ProcessPriorityManager.h"
   1.106 +#include "SandboxHal.h"
   1.107 +#include "StructuredCloneUtils.h"
   1.108 +#include "TabParent.h"
   1.109 +#include "URIUtils.h"
   1.110 +#include "nsIWebBrowserChrome.h"
   1.111 +#include "nsIDocShell.h"
   1.112 +#include "mozilla/net/NeckoMessageUtils.h"
   1.113 +#include "gfxPrefs.h"
   1.114 +
   1.115 +#if defined(ANDROID) || defined(LINUX)
   1.116 +#include "nsSystemInfo.h"
   1.117 +#endif
   1.118 +
   1.119 +#ifdef ANDROID
   1.120 +# include "gfxAndroidPlatform.h"
   1.121 +#endif
   1.122 +
   1.123 +#ifdef MOZ_PERMISSIONS
   1.124 +# include "nsPermissionManager.h"
   1.125 +#endif
   1.126 +
   1.127 +#ifdef MOZ_WIDGET_ANDROID
   1.128 +# include "AndroidBridge.h"
   1.129 +#endif
   1.130 +
   1.131 +#ifdef MOZ_WIDGET_GONK
   1.132 +#include "nsIVolume.h"
   1.133 +#include "nsIVolumeService.h"
   1.134 +#include "SpeakerManagerService.h"
   1.135 +using namespace mozilla::system;
   1.136 +#endif
   1.137 +
   1.138 +#ifdef MOZ_B2G_BT
   1.139 +#include "BluetoothParent.h"
   1.140 +#include "BluetoothService.h"
   1.141 +#endif
   1.142 +
   1.143 +#include "JavaScriptParent.h"
   1.144 +
   1.145 +#ifdef MOZ_B2G_FM
   1.146 +#include "mozilla/dom/FMRadioParent.h"
   1.147 +#endif
   1.148 +
   1.149 +#include "Crypto.h"
   1.150 +
   1.151 +#ifdef MOZ_WEBSPEECH
   1.152 +#include "mozilla/dom/SpeechSynthesisParent.h"
   1.153 +#endif
   1.154 +
   1.155 +#ifdef ENABLE_TESTS
   1.156 +#include "BackgroundChildImpl.h"
   1.157 +#include "mozilla/ipc/PBackgroundChild.h"
   1.158 +#include "nsIIPCBackgroundChildCreateCallback.h"
   1.159 +#endif
   1.160 +
   1.161 +static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID);
   1.162 +static const char* sClipboardTextFlavors[] = { kUnicodeMime };
   1.163 +
   1.164 +using base::ChildPrivileges;
   1.165 +using base::KillProcess;
   1.166 +using namespace mozilla::dom::bluetooth;
   1.167 +using namespace mozilla::dom::devicestorage;
   1.168 +using namespace mozilla::dom::indexedDB;
   1.169 +using namespace mozilla::dom::power;
   1.170 +using namespace mozilla::dom::mobilemessage;
   1.171 +using namespace mozilla::dom::telephony;
   1.172 +using namespace mozilla::hal;
   1.173 +using namespace mozilla::ipc;
   1.174 +using namespace mozilla::layers;
   1.175 +using namespace mozilla::net;
   1.176 +using namespace mozilla::jsipc;
   1.177 +
   1.178 +#ifdef ENABLE_TESTS
   1.179 +
   1.180 +class BackgroundTester MOZ_FINAL : public nsIIPCBackgroundChildCreateCallback,
   1.181 +                                   public nsIObserver
   1.182 +{
   1.183 +    static uint32_t sCallbackCount;
   1.184 +
   1.185 +private:
   1.186 +    ~BackgroundTester()
   1.187 +    { }
   1.188 +
   1.189 +    virtual void
   1.190 +    ActorCreated(PBackgroundChild* aActor) MOZ_OVERRIDE
   1.191 +    {
   1.192 +        MOZ_RELEASE_ASSERT(aActor,
   1.193 +                           "Failed to create a PBackgroundChild actor!");
   1.194 +
   1.195 +        NS_NAMED_LITERAL_CSTRING(testStr, "0123456789");
   1.196 +
   1.197 +        PBackgroundTestChild* testActor =
   1.198 +            aActor->SendPBackgroundTestConstructor(testStr);
   1.199 +        MOZ_RELEASE_ASSERT(testActor);
   1.200 +
   1.201 +        if (!sCallbackCount) {
   1.202 +            PBackgroundChild* existingBackgroundChild =
   1.203 +                BackgroundChild::GetForCurrentThread();
   1.204 +
   1.205 +            MOZ_RELEASE_ASSERT(existingBackgroundChild);
   1.206 +            MOZ_RELEASE_ASSERT(existingBackgroundChild == aActor);
   1.207 +
   1.208 +            bool ok =
   1.209 +                existingBackgroundChild->
   1.210 +                    SendPBackgroundTestConstructor(testStr);
   1.211 +            MOZ_RELEASE_ASSERT(ok);
   1.212 +
   1.213 +            // Callback 3.
   1.214 +            ok = BackgroundChild::GetOrCreateForCurrentThread(this);
   1.215 +            MOZ_RELEASE_ASSERT(ok);
   1.216 +        }
   1.217 +
   1.218 +        sCallbackCount++;
   1.219 +    }
   1.220 +
   1.221 +    virtual void
   1.222 +    ActorFailed() MOZ_OVERRIDE
   1.223 +    {
   1.224 +        MOZ_CRASH("Failed to create a PBackgroundChild actor!");
   1.225 +    }
   1.226 +
   1.227 +    NS_IMETHOD
   1.228 +    Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData)
   1.229 +            MOZ_OVERRIDE
   1.230 +    {
   1.231 +        nsCOMPtr<nsIObserverService> observerService =
   1.232 +            mozilla::services::GetObserverService();
   1.233 +        MOZ_RELEASE_ASSERT(observerService);
   1.234 +
   1.235 +        nsresult rv = observerService->RemoveObserver(this, aTopic);
   1.236 +        MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
   1.237 +
   1.238 +        if (!strcmp(aTopic, "profile-after-change")) {
   1.239 +            if (mozilla::Preferences::GetBool("pbackground.testing", false)) {
   1.240 +                rv = observerService->AddObserver(this, "xpcom-shutdown",
   1.241 +                                                  false);
   1.242 +                MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
   1.243 +
   1.244 +                // Callback 1.
   1.245 +                bool ok = BackgroundChild::GetOrCreateForCurrentThread(this);
   1.246 +                MOZ_RELEASE_ASSERT(ok);
   1.247 +
   1.248 +                BackgroundChildImpl::ThreadLocal* threadLocal =
   1.249 +                  BackgroundChildImpl::GetThreadLocalForCurrentThread();
   1.250 +                MOZ_RELEASE_ASSERT(threadLocal);
   1.251 +
   1.252 +                // Callback 2.
   1.253 +                ok = BackgroundChild::GetOrCreateForCurrentThread(this);
   1.254 +                MOZ_RELEASE_ASSERT(ok);
   1.255 +            }
   1.256 +
   1.257 +            return NS_OK;
   1.258 +        }
   1.259 +
   1.260 +        if (!strcmp(aTopic, "xpcom-shutdown")) {
   1.261 +            MOZ_RELEASE_ASSERT(sCallbackCount == 3);
   1.262 +
   1.263 +            return NS_OK;
   1.264 +        }
   1.265 +
   1.266 +        MOZ_CRASH("Unknown observer topic!");
   1.267 +    }
   1.268 +
   1.269 +public:
   1.270 +    NS_DECL_ISUPPORTS
   1.271 +};
   1.272 +
   1.273 +uint32_t BackgroundTester::sCallbackCount = 0;
   1.274 +
   1.275 +NS_IMPL_ISUPPORTS(BackgroundTester, nsIIPCBackgroundChildCreateCallback,
   1.276 +                  nsIObserver)
   1.277 +
   1.278 +#endif // ENABLE_TESTS
   1.279 +
   1.280 +void
   1.281 +MaybeTestPBackground()
   1.282 +{
   1.283 +#ifdef ENABLE_TESTS
   1.284 +    // This test relies on running the event loop and XPCShell does not always
   1.285 +    // do so. Bail out here if we detect that we're running in XPCShell.
   1.286 +    if (PR_GetEnv("XPCSHELL_TEST_PROFILE_DIR")) {
   1.287 +        return;
   1.288 +    }
   1.289 +
   1.290 +    // This is called too early at startup to test preferences directly. We have
   1.291 +    // to install an observer to be notified when preferences are available.
   1.292 +    nsCOMPtr<nsIObserverService> observerService =
   1.293 +        mozilla::services::GetObserverService();
   1.294 +    MOZ_RELEASE_ASSERT(observerService);
   1.295 +
   1.296 +    nsCOMPtr<nsIObserver> observer = new BackgroundTester();
   1.297 +    nsresult rv = observerService->AddObserver(observer, "profile-after-change",
   1.298 +                                               false);
   1.299 +    MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
   1.300 +#endif
   1.301 +}
   1.302 +
   1.303 +namespace mozilla {
   1.304 +namespace dom {
   1.305 +
   1.306 +#define NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC "ipc:network:set-offline"
   1.307 +
   1.308 +class MemoryReportRequestParent : public PMemoryReportRequestParent
   1.309 +{
   1.310 +public:
   1.311 +    MemoryReportRequestParent();
   1.312 +    virtual ~MemoryReportRequestParent();
   1.313 +
   1.314 +    virtual bool Recv__delete__(const uint32_t& generation, const InfallibleTArray<MemoryReport>& report);
   1.315 +private:
   1.316 +    ContentParent* Owner()
   1.317 +    {
   1.318 +        return static_cast<ContentParent*>(Manager());
   1.319 +    }
   1.320 +};
   1.321 +
   1.322 +MemoryReportRequestParent::MemoryReportRequestParent()
   1.323 +{
   1.324 +    MOZ_COUNT_CTOR(MemoryReportRequestParent);
   1.325 +}
   1.326 +
   1.327 +bool
   1.328 +MemoryReportRequestParent::Recv__delete__(const uint32_t& generation, const InfallibleTArray<MemoryReport>& childReports)
   1.329 +{
   1.330 +    nsRefPtr<nsMemoryReporterManager> mgr =
   1.331 +        nsMemoryReporterManager::GetOrCreate();
   1.332 +    if (mgr) {
   1.333 +        mgr->HandleChildReports(generation, childReports);
   1.334 +    }
   1.335 +    return true;
   1.336 +}
   1.337 +
   1.338 +MemoryReportRequestParent::~MemoryReportRequestParent()
   1.339 +{
   1.340 +    MOZ_COUNT_DTOR(MemoryReportRequestParent);
   1.341 +}
   1.342 +
   1.343 +// A memory reporter for ContentParent objects themselves.
   1.344 +class ContentParentsMemoryReporter MOZ_FINAL : public nsIMemoryReporter
   1.345 +{
   1.346 +public:
   1.347 +    NS_DECL_ISUPPORTS
   1.348 +    NS_DECL_NSIMEMORYREPORTER
   1.349 +};
   1.350 +
   1.351 +NS_IMPL_ISUPPORTS(ContentParentsMemoryReporter, nsIMemoryReporter)
   1.352 +
   1.353 +NS_IMETHODIMP
   1.354 +ContentParentsMemoryReporter::CollectReports(nsIMemoryReporterCallback* cb,
   1.355 +                                             nsISupports* aClosure)
   1.356 +{
   1.357 +    nsAutoTArray<ContentParent*, 16> cps;
   1.358 +    ContentParent::GetAllEvenIfDead(cps);
   1.359 +
   1.360 +    for (uint32_t i = 0; i < cps.Length(); i++) {
   1.361 +        ContentParent* cp = cps[i];
   1.362 +        MessageChannel* channel = cp->GetIPCChannel();
   1.363 +
   1.364 +        nsString friendlyName;
   1.365 +        cp->FriendlyName(friendlyName);
   1.366 +
   1.367 +        cp->AddRef();
   1.368 +        nsrefcnt refcnt = cp->Release();
   1.369 +
   1.370 +        const char* channelStr = "no channel";
   1.371 +        uint32_t numQueuedMessages = 0;
   1.372 +        if (channel) {
   1.373 +            if (channel->Unsound_IsClosed()) {
   1.374 +                channelStr = "closed channel";
   1.375 +            } else {
   1.376 +                channelStr = "open channel";
   1.377 +            }
   1.378 +            numQueuedMessages = channel->Unsound_NumQueuedMessages();
   1.379 +        }
   1.380 +
   1.381 +        nsPrintfCString path("queued-ipc-messages/content-parent"
   1.382 +                             "(%s, pid=%d, %s, 0x%p, refcnt=%d)",
   1.383 +                             NS_ConvertUTF16toUTF8(friendlyName).get(),
   1.384 +                             cp->Pid(), channelStr, cp, refcnt);
   1.385 +
   1.386 +        NS_NAMED_LITERAL_CSTRING(desc,
   1.387 +            "The number of unset IPC messages held in this ContentParent's "
   1.388 +            "channel.  A large value here might indicate that we're leaking "
   1.389 +            "messages.  Similarly, a ContentParent object for a process that's no "
   1.390 +            "longer running could indicate that we're leaking ContentParents.");
   1.391 +
   1.392 +        nsresult rv = cb->Callback(/* process */ EmptyCString(),
   1.393 +                                   path,
   1.394 +                                   KIND_OTHER,
   1.395 +                                   UNITS_COUNT,
   1.396 +                                   numQueuedMessages,
   1.397 +                                   desc,
   1.398 +                                   aClosure);
   1.399 +
   1.400 +        NS_ENSURE_SUCCESS(rv, rv);
   1.401 +    }
   1.402 +
   1.403 +    return NS_OK;
   1.404 +}
   1.405 +
   1.406 +nsDataHashtable<nsStringHashKey, ContentParent*>* ContentParent::sAppContentParents;
   1.407 +nsTArray<ContentParent*>* ContentParent::sNonAppContentParents;
   1.408 +nsTArray<ContentParent*>* ContentParent::sPrivateContent;
   1.409 +StaticAutoPtr<LinkedList<ContentParent> > ContentParent::sContentParents;
   1.410 +
   1.411 +// This is true when subprocess launching is enabled.  This is the
   1.412 +// case between StartUp() and ShutDown() or JoinAllSubprocesses().
   1.413 +static bool sCanLaunchSubprocesses;
   1.414 +
   1.415 +// The first content child has ID 1, so the chrome process can have ID 0.
   1.416 +static uint64_t gContentChildID = 1;
   1.417 +
   1.418 +// We want the prelaunched process to know that it's for apps, but not
   1.419 +// actually for any app in particular.  Use a magic manifest URL.
   1.420 +// Can't be a static constant.
   1.421 +#define MAGIC_PREALLOCATED_APP_MANIFEST_URL NS_LITERAL_STRING("{{template}}")
   1.422 +
   1.423 +static const char* sObserverTopics[] = {
   1.424 +    "xpcom-shutdown",
   1.425 +    NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC,
   1.426 +    "child-memory-reporter-request",
   1.427 +    "memory-pressure",
   1.428 +    "child-gc-request",
   1.429 +    "child-cc-request",
   1.430 +    "child-mmu-request",
   1.431 +    "last-pb-context-exited",
   1.432 +    "file-watcher-update",
   1.433 +#ifdef MOZ_WIDGET_GONK
   1.434 +    NS_VOLUME_STATE_CHANGED,
   1.435 +    "phone-state-changed",
   1.436 +#endif
   1.437 +#ifdef ACCESSIBILITY
   1.438 +    "a11y-init-or-shutdown",
   1.439 +#endif
   1.440 +};
   1.441 +
   1.442 +/* static */ already_AddRefed<ContentParent>
   1.443 +ContentParent::RunNuwaProcess()
   1.444 +{
   1.445 +    MOZ_ASSERT(NS_IsMainThread());
   1.446 +    nsRefPtr<ContentParent> nuwaProcess =
   1.447 +        new ContentParent(/* aApp = */ nullptr,
   1.448 +                          /* aIsForBrowser = */ false,
   1.449 +                          /* aIsForPreallocated = */ true,
   1.450 +                          PROCESS_PRIORITY_BACKGROUND,
   1.451 +                          /* aIsNuwaProcess = */ true);
   1.452 +    nuwaProcess->Init();
   1.453 +    return nuwaProcess.forget();
   1.454 +}
   1.455 +
   1.456 +// PreallocateAppProcess is called by the PreallocatedProcessManager.
   1.457 +// ContentParent then takes this process back within
   1.458 +// MaybeTakePreallocatedAppProcess.
   1.459 +/*static*/ already_AddRefed<ContentParent>
   1.460 +ContentParent::PreallocateAppProcess()
   1.461 +{
   1.462 +    nsRefPtr<ContentParent> process =
   1.463 +        new ContentParent(/* app = */ nullptr,
   1.464 +                          /* isForBrowserElement = */ false,
   1.465 +                          /* isForPreallocated = */ true,
   1.466 +                          PROCESS_PRIORITY_PREALLOC);
   1.467 +    process->Init();
   1.468 +    return process.forget();
   1.469 +}
   1.470 +
   1.471 +/*static*/ already_AddRefed<ContentParent>
   1.472 +ContentParent::MaybeTakePreallocatedAppProcess(const nsAString& aAppManifestURL,
   1.473 +                                               ProcessPriority aInitialPriority)
   1.474 +{
   1.475 +    nsRefPtr<ContentParent> process = PreallocatedProcessManager::Take();
   1.476 +    if (!process) {
   1.477 +        return nullptr;
   1.478 +    }
   1.479 +
   1.480 +    if (!process->SetPriorityAndCheckIsAlive(aInitialPriority)) {
   1.481 +        // Kill the process just in case it's not actually dead; we don't want
   1.482 +        // to "leak" this process!
   1.483 +        process->KillHard();
   1.484 +        return nullptr;
   1.485 +    }
   1.486 +    process->TransformPreallocatedIntoApp(aAppManifestURL);
   1.487 +
   1.488 +    return process.forget();
   1.489 +}
   1.490 +
   1.491 +/*static*/ void
   1.492 +ContentParent::StartUp()
   1.493 +{
   1.494 +    if (XRE_GetProcessType() != GeckoProcessType_Default) {
   1.495 +        return;
   1.496 +    }
   1.497 +
   1.498 +    // Note: This reporter measures all ContentParents.
   1.499 +    RegisterStrongMemoryReporter(new ContentParentsMemoryReporter());
   1.500 +
   1.501 +    mozilla::dom::time::InitializeDateCacheCleaner();
   1.502 +
   1.503 +    BackgroundChild::Startup();
   1.504 +
   1.505 +    sCanLaunchSubprocesses = true;
   1.506 +
   1.507 +    // Try to preallocate a process that we can transform into an app later.
   1.508 +    PreallocatedProcessManager::AllocateAfterDelay();
   1.509 +
   1.510 +    // Test the PBackground infrastructure on ENABLE_TESTS builds when a special
   1.511 +    // testing preference is set.
   1.512 +    MaybeTestPBackground();
   1.513 +}
   1.514 +
   1.515 +/*static*/ void
   1.516 +ContentParent::ShutDown()
   1.517 +{
   1.518 +    // No-op for now.  We rely on normal process shutdown and
   1.519 +    // ClearOnShutdown() to clean up our state.
   1.520 +    sCanLaunchSubprocesses = false;
   1.521 +}
   1.522 +
   1.523 +/*static*/ void
   1.524 +ContentParent::JoinProcessesIOThread(const nsTArray<ContentParent*>* aProcesses,
   1.525 +                                     Monitor* aMonitor, bool* aDone)
   1.526 +{
   1.527 +    const nsTArray<ContentParent*>& processes = *aProcesses;
   1.528 +    for (uint32_t i = 0; i < processes.Length(); ++i) {
   1.529 +        if (GeckoChildProcessHost* process = processes[i]->mSubprocess) {
   1.530 +            process->Join();
   1.531 +        }
   1.532 +    }
   1.533 +    {
   1.534 +        MonitorAutoLock lock(*aMonitor);
   1.535 +        *aDone = true;
   1.536 +        lock.Notify();
   1.537 +    }
   1.538 +    // Don't touch any arguments to this function from now on.
   1.539 +}
   1.540 +
   1.541 +/*static*/ void
   1.542 +ContentParent::JoinAllSubprocesses()
   1.543 +{
   1.544 +    MOZ_ASSERT(NS_IsMainThread());
   1.545 +
   1.546 +    nsAutoTArray<ContentParent*, 8> processes;
   1.547 +    GetAll(processes);
   1.548 +    if (processes.IsEmpty()) {
   1.549 +        printf_stderr("There are no live subprocesses.");
   1.550 +        return;
   1.551 +    }
   1.552 +
   1.553 +    printf_stderr("Subprocesses are still alive.  Doing emergency join.\n");
   1.554 +
   1.555 +    bool done = false;
   1.556 +    Monitor monitor("mozilla.dom.ContentParent.JoinAllSubprocesses");
   1.557 +    XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
   1.558 +                                     NewRunnableFunction(
   1.559 +                                         &ContentParent::JoinProcessesIOThread,
   1.560 +                                         &processes, &monitor, &done));
   1.561 +    {
   1.562 +        MonitorAutoLock lock(monitor);
   1.563 +        while (!done) {
   1.564 +            lock.Wait();
   1.565 +        }
   1.566 +    }
   1.567 +
   1.568 +    sCanLaunchSubprocesses = false;
   1.569 +}
   1.570 +
   1.571 +/*static*/ already_AddRefed<ContentParent>
   1.572 +ContentParent::GetNewOrUsed(bool aForBrowserElement)
   1.573 +{
   1.574 +    if (!sNonAppContentParents)
   1.575 +        sNonAppContentParents = new nsTArray<ContentParent*>();
   1.576 +
   1.577 +    int32_t maxContentProcesses = Preferences::GetInt("dom.ipc.processCount", 1);
   1.578 +    if (maxContentProcesses < 1)
   1.579 +        maxContentProcesses = 1;
   1.580 +
   1.581 +    if (sNonAppContentParents->Length() >= uint32_t(maxContentProcesses)) {
   1.582 +        uint32_t idx = rand() % sNonAppContentParents->Length();
   1.583 +        nsRefPtr<ContentParent> p = (*sNonAppContentParents)[idx];
   1.584 +        NS_ASSERTION(p->IsAlive(), "Non-alive contentparent in sNonAppContentParents?");
   1.585 +        return p.forget();
   1.586 +    }
   1.587 +
   1.588 +    // Try to take and transform the preallocated process into browser.
   1.589 +    nsRefPtr<ContentParent> p = PreallocatedProcessManager::Take();
   1.590 +    if (p) {
   1.591 +        p->TransformPreallocatedIntoBrowser();
   1.592 +    } else {
   1.593 +      // Failed in using the preallocated process: fork from the chrome process.
   1.594 +#ifdef MOZ_NUWA_PROCESS
   1.595 +        if (Preferences::GetBool("dom.ipc.processPrelaunch.enabled", false)) {
   1.596 +            // Wait until the Nuwa process forks a new process.
   1.597 +            return nullptr;
   1.598 +        }
   1.599 +#endif
   1.600 +        p = new ContentParent(/* app = */ nullptr,
   1.601 +                              aForBrowserElement,
   1.602 +                              /* isForPreallocated = */ false,
   1.603 +                              PROCESS_PRIORITY_FOREGROUND);
   1.604 +    }
   1.605 +
   1.606 +    p->Init();
   1.607 +    sNonAppContentParents->AppendElement(p);
   1.608 +    return p.forget();
   1.609 +}
   1.610 +
   1.611 +/*static*/ ProcessPriority
   1.612 +ContentParent::GetInitialProcessPriority(Element* aFrameElement)
   1.613 +{
   1.614 +    // Frames with mozapptype == critical which are expecting a system message
   1.615 +    // get FOREGROUND_HIGH priority.
   1.616 +
   1.617 +    if (!aFrameElement) {
   1.618 +        return PROCESS_PRIORITY_FOREGROUND;
   1.619 +    }
   1.620 +
   1.621 +    if (aFrameElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::mozapptype,
   1.622 +                                   NS_LITERAL_STRING("keyboard"), eCaseMatters)) {
   1.623 +        return PROCESS_PRIORITY_FOREGROUND_KEYBOARD;
   1.624 +    } else if (!aFrameElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::mozapptype,
   1.625 +                                           NS_LITERAL_STRING("critical"), eCaseMatters)) {
   1.626 +        return PROCESS_PRIORITY_FOREGROUND;
   1.627 +    }
   1.628 +
   1.629 +    nsCOMPtr<nsIMozBrowserFrame> browserFrame =
   1.630 +        do_QueryInterface(aFrameElement);
   1.631 +    if (!browserFrame) {
   1.632 +        return PROCESS_PRIORITY_FOREGROUND;
   1.633 +    }
   1.634 +
   1.635 +    return browserFrame->GetIsExpectingSystemMessage() ?
   1.636 +               PROCESS_PRIORITY_FOREGROUND_HIGH :
   1.637 +               PROCESS_PRIORITY_FOREGROUND;
   1.638 +}
   1.639 +
   1.640 +bool
   1.641 +ContentParent::PreallocatedProcessReady()
   1.642 +{
   1.643 +#ifdef MOZ_NUWA_PROCESS
   1.644 +    return PreallocatedProcessManager::PreallocatedProcessReady();
   1.645 +#else
   1.646 +    return true;
   1.647 +#endif
   1.648 +}
   1.649 +
   1.650 +void
   1.651 +ContentParent::RunAfterPreallocatedProcessReady(nsIRunnable* aRequest)
   1.652 +{
   1.653 +#ifdef MOZ_NUWA_PROCESS
   1.654 +    PreallocatedProcessManager::RunAfterPreallocatedProcessReady(aRequest);
   1.655 +#endif
   1.656 +}
   1.657 +
   1.658 +/*static*/ TabParent*
   1.659 +ContentParent::CreateBrowserOrApp(const TabContext& aContext,
   1.660 +                                  Element* aFrameElement)
   1.661 +{
   1.662 +    if (!sCanLaunchSubprocesses) {
   1.663 +        return nullptr;
   1.664 +    }
   1.665 +
   1.666 +    if (aContext.IsBrowserElement() || !aContext.HasOwnApp()) {
   1.667 +        if (nsRefPtr<ContentParent> cp = GetNewOrUsed(aContext.IsBrowserElement())) {
   1.668 +            uint32_t chromeFlags = 0;
   1.669 +
   1.670 +            // Propagate the private-browsing status of the element's parent
   1.671 +            // docshell to the remote docshell, via the chrome flags.
   1.672 +            nsCOMPtr<Element> frameElement = do_QueryInterface(aFrameElement);
   1.673 +            MOZ_ASSERT(frameElement);
   1.674 +            nsIDocShell* docShell =
   1.675 +                frameElement->OwnerDoc()->GetWindow()->GetDocShell();
   1.676 +            MOZ_ASSERT(docShell);
   1.677 +            nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(docShell);
   1.678 +            if (loadContext && loadContext->UsePrivateBrowsing()) {
   1.679 +                chromeFlags |= nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW;
   1.680 +            }
   1.681 +            bool affectLifetime;
   1.682 +            docShell->GetAffectPrivateSessionLifetime(&affectLifetime);
   1.683 +            if (affectLifetime) {
   1.684 +                chromeFlags |= nsIWebBrowserChrome::CHROME_PRIVATE_LIFETIME;
   1.685 +            }
   1.686 +
   1.687 +            nsRefPtr<TabParent> tp(new TabParent(cp, aContext, chromeFlags));
   1.688 +            tp->SetOwnerElement(aFrameElement);
   1.689 +
   1.690 +            PBrowserParent* browser = cp->SendPBrowserConstructor(
   1.691 +                // DeallocPBrowserParent() releases this ref.
   1.692 +                tp.forget().take(),
   1.693 +                aContext.AsIPCTabContext(),
   1.694 +                chromeFlags);
   1.695 +            return static_cast<TabParent*>(browser);
   1.696 +        }
   1.697 +        return nullptr;
   1.698 +    }
   1.699 +
   1.700 +    // If we got here, we have an app and we're not a browser element.  ownApp
   1.701 +    // shouldn't be null, because we otherwise would have gone into the
   1.702 +    // !HasOwnApp() branch above.
   1.703 +    nsCOMPtr<mozIApplication> ownApp = aContext.GetOwnApp();
   1.704 +
   1.705 +    if (!sAppContentParents) {
   1.706 +        sAppContentParents =
   1.707 +            new nsDataHashtable<nsStringHashKey, ContentParent*>();
   1.708 +    }
   1.709 +
   1.710 +    // Each app gets its own ContentParent instance unless it shares it with
   1.711 +    // a parent app.
   1.712 +    nsAutoString manifestURL;
   1.713 +    if (NS_FAILED(ownApp->GetManifestURL(manifestURL))) {
   1.714 +        NS_ERROR("Failed to get manifest URL");
   1.715 +        return nullptr;
   1.716 +    }
   1.717 +
   1.718 +    ProcessPriority initialPriority = GetInitialProcessPriority(aFrameElement);
   1.719 +    nsRefPtr<ContentParent> p = sAppContentParents->Get(manifestURL);
   1.720 +
   1.721 +    if (!p && Preferences::GetBool("dom.ipc.reuse_parent_app")) {
   1.722 +        nsAutoString parentAppURL;
   1.723 +        aFrameElement->GetAttr(kNameSpaceID_None,
   1.724 +                               nsGkAtoms::parentapp, parentAppURL);
   1.725 +        nsAdoptingString systemAppURL =
   1.726 +            Preferences::GetString("browser.homescreenURL");
   1.727 +        nsCOMPtr<nsIAppsService> appsService =
   1.728 +            do_GetService(APPS_SERVICE_CONTRACTID);
   1.729 +        if (!parentAppURL.IsEmpty() &&
   1.730 +            !parentAppURL.Equals(systemAppURL) &&
   1.731 +            appsService) {
   1.732 +            nsCOMPtr<mozIApplication> parentApp;
   1.733 +            nsCOMPtr<mozIApplication> app;
   1.734 +            appsService->GetAppByManifestURL(parentAppURL,
   1.735 +                                             getter_AddRefs(parentApp));
   1.736 +            appsService->GetAppByManifestURL(manifestURL,
   1.737 +                                             getter_AddRefs(app));
   1.738 +
   1.739 +            // Only let certified apps re-use the same process.
   1.740 +            unsigned short parentAppStatus = 0;
   1.741 +            unsigned short appStatus = 0;
   1.742 +            if (app &&
   1.743 +                NS_SUCCEEDED(app->GetAppStatus(&appStatus)) &&
   1.744 +                appStatus == nsIPrincipal::APP_STATUS_CERTIFIED &&
   1.745 +                parentApp &&
   1.746 +                NS_SUCCEEDED(parentApp->GetAppStatus(&parentAppStatus)) &&
   1.747 +                parentAppStatus == nsIPrincipal::APP_STATUS_CERTIFIED) {
   1.748 +                // Check if we can re-use the process of the parent app.
   1.749 +                p = sAppContentParents->Get(parentAppURL);
   1.750 +            }
   1.751 +        }
   1.752 +    }
   1.753 +
   1.754 +    if (p) {
   1.755 +        // Check that the process is still alive and set its priority.
   1.756 +        // Hopefully the process won't die after this point, if this call
   1.757 +        // succeeds.
   1.758 +        if (!p->SetPriorityAndCheckIsAlive(initialPriority)) {
   1.759 +            p = nullptr;
   1.760 +        }
   1.761 +    }
   1.762 +
   1.763 +    if (!p) {
   1.764 +        p = MaybeTakePreallocatedAppProcess(manifestURL,
   1.765 +                                            initialPriority);
   1.766 +        if (!p) {
   1.767 +#ifdef MOZ_NUWA_PROCESS
   1.768 +            if (Preferences::GetBool("dom.ipc.processPrelaunch.enabled",
   1.769 +                                     false)) {
   1.770 +                // Returning nullptr from here so the frame loader will retry
   1.771 +                // later when we have a spare process.
   1.772 +                return nullptr;
   1.773 +            }
   1.774 +#endif
   1.775 +            NS_WARNING("Unable to use pre-allocated app process");
   1.776 +            p = new ContentParent(ownApp,
   1.777 +                                  /* isForBrowserElement = */ false,
   1.778 +                                  /* isForPreallocated = */ false,
   1.779 +                                  initialPriority);
   1.780 +            p->Init();
   1.781 +        }
   1.782 +        sAppContentParents->Put(manifestURL, p);
   1.783 +    }
   1.784 +
   1.785 +    uint32_t chromeFlags = 0;
   1.786 +
   1.787 +    nsRefPtr<TabParent> tp = new TabParent(p, aContext, chromeFlags);
   1.788 +    tp->SetOwnerElement(aFrameElement);
   1.789 +    PBrowserParent* browser = p->SendPBrowserConstructor(
   1.790 +        // DeallocPBrowserParent() releases this ref.
   1.791 +        nsRefPtr<TabParent>(tp).forget().take(),
   1.792 +        aContext.AsIPCTabContext(),
   1.793 +        chromeFlags);
   1.794 +
   1.795 +    p->MaybeTakeCPUWakeLock(aFrameElement);
   1.796 +
   1.797 +    return static_cast<TabParent*>(browser);
   1.798 +}
   1.799 +
   1.800 +void
   1.801 +ContentParent::GetAll(nsTArray<ContentParent*>& aArray)
   1.802 +{
   1.803 +    aArray.Clear();
   1.804 +
   1.805 +    if (!sContentParents) {
   1.806 +        return;
   1.807 +    }
   1.808 +
   1.809 +    for (ContentParent* cp = sContentParents->getFirst(); cp;
   1.810 +         cp = cp->LinkedListElement<ContentParent>::getNext()) {
   1.811 +        if (cp->mIsAlive) {
   1.812 +            aArray.AppendElement(cp);
   1.813 +        }
   1.814 +    }
   1.815 +}
   1.816 +
   1.817 +void
   1.818 +ContentParent::GetAllEvenIfDead(nsTArray<ContentParent*>& aArray)
   1.819 +{
   1.820 +    aArray.Clear();
   1.821 +
   1.822 +    if (!sContentParents) {
   1.823 +        return;
   1.824 +    }
   1.825 +
   1.826 +    for (ContentParent* cp = sContentParents->getFirst(); cp;
   1.827 +         cp = cp->LinkedListElement<ContentParent>::getNext()) {
   1.828 +        aArray.AppendElement(cp);
   1.829 +    }
   1.830 +}
   1.831 +
   1.832 +void
   1.833 +ContentParent::Init()
   1.834 +{
   1.835 +    nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   1.836 +    if (obs) {
   1.837 +        size_t length = ArrayLength(sObserverTopics);
   1.838 +        for (size_t i = 0; i < length; ++i) {
   1.839 +            obs->AddObserver(this, sObserverTopics[i], false);
   1.840 +        }
   1.841 +    }
   1.842 +    Preferences::AddStrongObserver(this, "");
   1.843 +    if (obs) {
   1.844 +        obs->NotifyObservers(static_cast<nsIObserver*>(this), "ipc:content-created", nullptr);
   1.845 +    }
   1.846 +
   1.847 +#ifdef ACCESSIBILITY
   1.848 +    // If accessibility is running in chrome process then start it in content
   1.849 +    // process.
   1.850 +    if (nsIPresShell::IsAccessibilityActive()) {
   1.851 +        unused << SendActivateA11y();
   1.852 +    }
   1.853 +#endif
   1.854 +
   1.855 +    DebugOnly<FileUpdateDispatcher*> observer = FileUpdateDispatcher::GetSingleton();
   1.856 +    NS_ASSERTION(observer, "FileUpdateDispatcher is null");
   1.857 +}
   1.858 +
   1.859 +namespace {
   1.860 +
   1.861 +class SystemMessageHandledListener MOZ_FINAL
   1.862 +    : public nsITimerCallback
   1.863 +    , public LinkedListElement<SystemMessageHandledListener>
   1.864 +{
   1.865 +public:
   1.866 +    NS_DECL_ISUPPORTS
   1.867 +
   1.868 +    SystemMessageHandledListener() {}
   1.869 +
   1.870 +    static void OnSystemMessageHandled()
   1.871 +    {
   1.872 +        if (!sListeners) {
   1.873 +            return;
   1.874 +        }
   1.875 +
   1.876 +        SystemMessageHandledListener* listener = sListeners->popFirst();
   1.877 +        if (!listener) {
   1.878 +            return;
   1.879 +        }
   1.880 +
   1.881 +        // Careful: ShutDown() may delete |this|.
   1.882 +        listener->ShutDown();
   1.883 +    }
   1.884 +
   1.885 +    void Init(WakeLock* aWakeLock)
   1.886 +    {
   1.887 +        MOZ_ASSERT(!mWakeLock);
   1.888 +        MOZ_ASSERT(!mTimer);
   1.889 +
   1.890 +        // mTimer keeps a strong reference to |this|.  When this object's
   1.891 +        // destructor runs, it will remove itself from the LinkedList.
   1.892 +
   1.893 +        if (!sListeners) {
   1.894 +            sListeners = new LinkedList<SystemMessageHandledListener>();
   1.895 +            ClearOnShutdown(&sListeners);
   1.896 +        }
   1.897 +        sListeners->insertBack(this);
   1.898 +
   1.899 +        mWakeLock = aWakeLock;
   1.900 +
   1.901 +        mTimer = do_CreateInstance("@mozilla.org/timer;1");
   1.902 +
   1.903 +        uint32_t timeoutSec =
   1.904 +            Preferences::GetInt("dom.ipc.systemMessageCPULockTimeoutSec", 30);
   1.905 +        mTimer->InitWithCallback(this, timeoutSec * 1000,
   1.906 +                                 nsITimer::TYPE_ONE_SHOT);
   1.907 +    }
   1.908 +
   1.909 +    NS_IMETHOD Notify(nsITimer* aTimer)
   1.910 +    {
   1.911 +        // Careful: ShutDown() may delete |this|.
   1.912 +        ShutDown();
   1.913 +        return NS_OK;
   1.914 +    }
   1.915 +
   1.916 +private:
   1.917 +    static StaticAutoPtr<LinkedList<SystemMessageHandledListener> > sListeners;
   1.918 +
   1.919 +    void ShutDown()
   1.920 +    {
   1.921 +        nsRefPtr<SystemMessageHandledListener> kungFuDeathGrip = this;
   1.922 +
   1.923 +        ErrorResult rv;
   1.924 +        mWakeLock->Unlock(rv);
   1.925 +
   1.926 +        if (mTimer) {
   1.927 +            mTimer->Cancel();
   1.928 +            mTimer = nullptr;
   1.929 +        }
   1.930 +    }
   1.931 +
   1.932 +    nsRefPtr<WakeLock> mWakeLock;
   1.933 +    nsCOMPtr<nsITimer> mTimer;
   1.934 +};
   1.935 +
   1.936 +StaticAutoPtr<LinkedList<SystemMessageHandledListener> >
   1.937 +    SystemMessageHandledListener::sListeners;
   1.938 +
   1.939 +NS_IMPL_ISUPPORTS(SystemMessageHandledListener,
   1.940 +                  nsITimerCallback)
   1.941 +
   1.942 +} // anonymous namespace
   1.943 +
   1.944 +void
   1.945 +ContentParent::MaybeTakeCPUWakeLock(Element* aFrameElement)
   1.946 +{
   1.947 +    // Take the CPU wake lock on behalf of this processs if it's expecting a
   1.948 +    // system message.  We'll release the CPU lock once the message is
   1.949 +    // delivered, or after some period of time, which ever comes first.
   1.950 +
   1.951 +    nsCOMPtr<nsIMozBrowserFrame> browserFrame =
   1.952 +        do_QueryInterface(aFrameElement);
   1.953 +    if (!browserFrame ||
   1.954 +        !browserFrame->GetIsExpectingSystemMessage()) {
   1.955 +        return;
   1.956 +    }
   1.957 +
   1.958 +    nsRefPtr<PowerManagerService> pms = PowerManagerService::GetInstance();
   1.959 +    nsRefPtr<WakeLock> lock =
   1.960 +        pms->NewWakeLockOnBehalfOfProcess(NS_LITERAL_STRING("cpu"), this);
   1.961 +
   1.962 +    // This object's Init() function keeps it alive.
   1.963 +    nsRefPtr<SystemMessageHandledListener> listener =
   1.964 +        new SystemMessageHandledListener();
   1.965 +    listener->Init(lock);
   1.966 +}
   1.967 +
   1.968 +bool
   1.969 +ContentParent::SetPriorityAndCheckIsAlive(ProcessPriority aPriority)
   1.970 +{
   1.971 +    ProcessPriorityManager::SetProcessPriority(this, aPriority);
   1.972 +
   1.973 +    // Now that we've set this process's priority, check whether the process is
   1.974 +    // still alive.  Hopefully we've set the priority to FOREGROUND*, so the
   1.975 +    // process won't unexpectedly crash after this point!
   1.976 +    //
   1.977 +    // Bug 943174: use waitid() with WNOWAIT so that, if the process
   1.978 +    // did exit, we won't consume its zombie and confuse the
   1.979 +    // GeckoChildProcessHost dtor.  Also, if the process isn't a
   1.980 +    // direct child because of Nuwa this will fail with ECHILD, and we
   1.981 +    // need to assume the child is alive in that case rather than
   1.982 +    // assuming it's dead (as is otherwise a reasonable fallback).
   1.983 +#ifdef MOZ_WIDGET_GONK
   1.984 +    siginfo_t info;
   1.985 +    info.si_pid = 0;
   1.986 +    if (waitid(P_PID, Pid(), &info, WNOWAIT | WNOHANG | WEXITED) == 0
   1.987 +        && info.si_pid != 0) {
   1.988 +        return false;
   1.989 +    }
   1.990 +#endif
   1.991 +
   1.992 +    return true;
   1.993 +}
   1.994 +
   1.995 +// Helper for ContentParent::TransformPreallocatedIntoApp.
   1.996 +static void
   1.997 +TryGetNameFromManifestURL(const nsAString& aManifestURL,
   1.998 +                          nsAString& aName)
   1.999 +{
  1.1000 +    aName.Truncate();
  1.1001 +    if (aManifestURL.IsEmpty() ||
  1.1002 +        aManifestURL == MAGIC_PREALLOCATED_APP_MANIFEST_URL) {
  1.1003 +        return;
  1.1004 +    }
  1.1005 +
  1.1006 +    nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
  1.1007 +    NS_ENSURE_TRUE_VOID(appsService);
  1.1008 +
  1.1009 +    nsCOMPtr<mozIApplication> app;
  1.1010 +    appsService->GetAppByManifestURL(aManifestURL, getter_AddRefs(app));
  1.1011 +
  1.1012 +    if (!app) {
  1.1013 +        return;
  1.1014 +    }
  1.1015 +
  1.1016 +    app->GetName(aName);
  1.1017 +}
  1.1018 +
  1.1019 +void
  1.1020 +ContentParent::TransformPreallocatedIntoApp(const nsAString& aAppManifestURL)
  1.1021 +{
  1.1022 +    MOZ_ASSERT(IsPreallocated());
  1.1023 +    mAppManifestURL = aAppManifestURL;
  1.1024 +    TryGetNameFromManifestURL(aAppManifestURL, mAppName);
  1.1025 +}
  1.1026 +
  1.1027 +void
  1.1028 +ContentParent::TransformPreallocatedIntoBrowser()
  1.1029 +{
  1.1030 +    // Reset mAppManifestURL, mIsForBrowser and mOSPrivileges for browser.
  1.1031 +    mAppManifestURL.Truncate();
  1.1032 +    mIsForBrowser = true;
  1.1033 +}
  1.1034 +
  1.1035 +void
  1.1036 +ContentParent::ShutDownProcess(bool aCloseWithError)
  1.1037 +{
  1.1038 +    const InfallibleTArray<PIndexedDBParent*>& idbParents =
  1.1039 +        ManagedPIndexedDBParent();
  1.1040 +    for (uint32_t i = 0; i < idbParents.Length(); ++i) {
  1.1041 +        static_cast<IndexedDBParent*>(idbParents[i])->Disconnect();
  1.1042 +    }
  1.1043 +
  1.1044 +    // If Close() fails with an error, we'll end up back in this function, but
  1.1045 +    // with aCloseWithError = true.  It's important that we call
  1.1046 +    // CloseWithError() in this case; see bug 895204.
  1.1047 +
  1.1048 +    if (!aCloseWithError && !mCalledClose) {
  1.1049 +        // Close() can only be called once: It kicks off the destruction
  1.1050 +        // sequence.
  1.1051 +        mCalledClose = true;
  1.1052 +        Close();
  1.1053 +    }
  1.1054 +
  1.1055 +    if (aCloseWithError && !mCalledCloseWithError) {
  1.1056 +        MessageChannel* channel = GetIPCChannel();
  1.1057 +        if (channel) {
  1.1058 +            mCalledCloseWithError = true;
  1.1059 +            channel->CloseWithError();
  1.1060 +        }
  1.1061 +    }
  1.1062 +
  1.1063 +    // NB: must MarkAsDead() here so that this isn't accidentally
  1.1064 +    // returned from Get*() while in the midst of shutdown.
  1.1065 +    MarkAsDead();
  1.1066 +
  1.1067 +    // A ContentParent object might not get freed until after XPCOM shutdown has
  1.1068 +    // shut down the cycle collector.  But by then it's too late to release any
  1.1069 +    // CC'ed objects, so we need to null them out here, while we still can.  See
  1.1070 +    // bug 899761.
  1.1071 +    if (mMessageManager) {
  1.1072 +      mMessageManager->Disconnect();
  1.1073 +      mMessageManager = nullptr;
  1.1074 +    }
  1.1075 +}
  1.1076 +
  1.1077 +void
  1.1078 +ContentParent::MarkAsDead()
  1.1079 +{
  1.1080 +    if (!mAppManifestURL.IsEmpty()) {
  1.1081 +        if (sAppContentParents) {
  1.1082 +            sAppContentParents->Remove(mAppManifestURL);
  1.1083 +            if (!sAppContentParents->Count()) {
  1.1084 +                delete sAppContentParents;
  1.1085 +                sAppContentParents = nullptr;
  1.1086 +            }
  1.1087 +        }
  1.1088 +    } else if (sNonAppContentParents) {
  1.1089 +        sNonAppContentParents->RemoveElement(this);
  1.1090 +        if (!sNonAppContentParents->Length()) {
  1.1091 +            delete sNonAppContentParents;
  1.1092 +            sNonAppContentParents = nullptr;
  1.1093 +        }
  1.1094 +    }
  1.1095 +
  1.1096 +    if (sPrivateContent) {
  1.1097 +        sPrivateContent->RemoveElement(this);
  1.1098 +        if (!sPrivateContent->Length()) {
  1.1099 +            delete sPrivateContent;
  1.1100 +            sPrivateContent = nullptr;
  1.1101 +        }
  1.1102 +    }
  1.1103 +
  1.1104 +    mIsAlive = false;
  1.1105 +}
  1.1106 +
  1.1107 +void
  1.1108 +ContentParent::OnChannelError()
  1.1109 +{
  1.1110 +    nsRefPtr<ContentParent> content(this);
  1.1111 +#ifdef MOZ_NUWA_PROCESS
  1.1112 +    // Handle app or Nuwa process exit before normal channel error handling.
  1.1113 +    PreallocatedProcessManager::MaybeForgetSpare(this);
  1.1114 +#endif
  1.1115 +    PContentParent::OnChannelError();
  1.1116 +}
  1.1117 +
  1.1118 +void
  1.1119 +ContentParent::OnChannelConnected(int32_t pid)
  1.1120 +{
  1.1121 +    ProcessHandle handle;
  1.1122 +    if (!base::OpenPrivilegedProcessHandle(pid, &handle)) {
  1.1123 +        NS_WARNING("Can't open handle to child process.");
  1.1124 +    }
  1.1125 +    else {
  1.1126 +        // we need to close the existing handle before setting a new one.
  1.1127 +        base::CloseProcessHandle(OtherProcess());
  1.1128 +        SetOtherProcess(handle);
  1.1129 +
  1.1130 +#if defined(ANDROID) || defined(LINUX)
  1.1131 +        // Check nice preference
  1.1132 +        int32_t nice = Preferences::GetInt("dom.ipc.content.nice", 0);
  1.1133 +
  1.1134 +        // Environment variable overrides preference
  1.1135 +        char* relativeNicenessStr = getenv("MOZ_CHILD_PROCESS_RELATIVE_NICENESS");
  1.1136 +        if (relativeNicenessStr) {
  1.1137 +            nice = atoi(relativeNicenessStr);
  1.1138 +        }
  1.1139 +
  1.1140 +        /* make the GUI thread have higher priority on single-cpu devices */
  1.1141 +        nsCOMPtr<nsIPropertyBag2> infoService = do_GetService(NS_SYSTEMINFO_CONTRACTID);
  1.1142 +        if (infoService) {
  1.1143 +            int32_t cpus;
  1.1144 +            nsresult rv = infoService->GetPropertyAsInt32(NS_LITERAL_STRING("cpucount"), &cpus);
  1.1145 +            if (NS_FAILED(rv)) {
  1.1146 +                cpus = 1;
  1.1147 +            }
  1.1148 +            if (nice != 0 && cpus == 1) {
  1.1149 +                setpriority(PRIO_PROCESS, pid, getpriority(PRIO_PROCESS, pid) + nice);
  1.1150 +            }
  1.1151 +        }
  1.1152 +#endif
  1.1153 +    }
  1.1154 +
  1.1155 +    // Set a reply timeout. The only time the parent process will actually
  1.1156 +    // timeout is through urgent messages (which are used by CPOWs).
  1.1157 +    SetReplyTimeoutMs(Preferences::GetInt("dom.ipc.cpow.timeout", 3000));
  1.1158 +}
  1.1159 +
  1.1160 +void
  1.1161 +ContentParent::ProcessingError(Result what)
  1.1162 +{
  1.1163 +    if (MsgDropped == what) {
  1.1164 +        // Messages sent after crashes etc. are not a big deal.
  1.1165 +        return;
  1.1166 +    }
  1.1167 +    // Other errors are big deals.
  1.1168 +    KillHard();
  1.1169 +}
  1.1170 +
  1.1171 +namespace {
  1.1172 +
  1.1173 +void
  1.1174 +DelayedDeleteSubprocess(GeckoChildProcessHost* aSubprocess)
  1.1175 +{
  1.1176 +    XRE_GetIOMessageLoop()
  1.1177 +        ->PostTask(FROM_HERE,
  1.1178 +                   new DeleteTask<GeckoChildProcessHost>(aSubprocess));
  1.1179 +}
  1.1180 +
  1.1181 +// This runnable only exists to delegate ownership of the
  1.1182 +// ContentParent to this runnable, until it's deleted by the event
  1.1183 +// system.
  1.1184 +struct DelayedDeleteContentParentTask : public nsRunnable
  1.1185 +{
  1.1186 +    DelayedDeleteContentParentTask(ContentParent* aObj) : mObj(aObj) { }
  1.1187 +
  1.1188 +    // No-op
  1.1189 +    NS_IMETHODIMP Run() { return NS_OK; }
  1.1190 +
  1.1191 +    nsRefPtr<ContentParent> mObj;
  1.1192 +};
  1.1193 +
  1.1194 +}
  1.1195 +
  1.1196 +void
  1.1197 +ContentParent::ActorDestroy(ActorDestroyReason why)
  1.1198 +{
  1.1199 +    if (mForceKillTask) {
  1.1200 +        mForceKillTask->Cancel();
  1.1201 +        mForceKillTask = nullptr;
  1.1202 +    }
  1.1203 +
  1.1204 +    nsRefPtr<nsFrameMessageManager> ppm = mMessageManager;
  1.1205 +    if (ppm) {
  1.1206 +      ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()),
  1.1207 +                          CHILD_PROCESS_SHUTDOWN_MESSAGE, false,
  1.1208 +                          nullptr, nullptr, nullptr, nullptr);
  1.1209 +    }
  1.1210 +    nsRefPtr<ContentParent> kungFuDeathGrip(this);
  1.1211 +    nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
  1.1212 +    if (obs) {
  1.1213 +        size_t length = ArrayLength(sObserverTopics);
  1.1214 +        for (size_t i = 0; i < length; ++i) {
  1.1215 +            obs->RemoveObserver(static_cast<nsIObserver*>(this),
  1.1216 +                                sObserverTopics[i]);
  1.1217 +        }
  1.1218 +    }
  1.1219 +
  1.1220 +    if (ppm) {
  1.1221 +      ppm->Disconnect();
  1.1222 +    }
  1.1223 +
  1.1224 +    // Tell the memory reporter manager that this ContentParent is going away.
  1.1225 +    nsRefPtr<nsMemoryReporterManager> mgr =
  1.1226 +        nsMemoryReporterManager::GetOrCreate();
  1.1227 +#ifdef MOZ_NUWA_PROCESS
  1.1228 +    bool isMemoryChild = !IsNuwaProcess();
  1.1229 +#else
  1.1230 +    bool isMemoryChild = true;
  1.1231 +#endif
  1.1232 +    if (mgr && isMemoryChild) {
  1.1233 +        mgr->DecrementNumChildProcesses();
  1.1234 +    }
  1.1235 +
  1.1236 +    // remove the global remote preferences observers
  1.1237 +    Preferences::RemoveObserver(this, "");
  1.1238 +
  1.1239 +    RecvRemoveGeolocationListener();
  1.1240 +
  1.1241 +    mConsoleService = nullptr;
  1.1242 +
  1.1243 +    MarkAsDead();
  1.1244 +
  1.1245 +    if (obs) {
  1.1246 +        nsRefPtr<nsHashPropertyBag> props = new nsHashPropertyBag();
  1.1247 +
  1.1248 +        props->SetPropertyAsUint64(NS_LITERAL_STRING("childID"), mChildID);
  1.1249 +
  1.1250 +        if (AbnormalShutdown == why) {
  1.1251 +            props->SetPropertyAsBool(NS_LITERAL_STRING("abnormal"), true);
  1.1252 +
  1.1253 +#ifdef MOZ_CRASHREPORTER
  1.1254 +            // There's a window in which child processes can crash
  1.1255 +            // after IPC is established, but before a crash reporter
  1.1256 +            // is created.
  1.1257 +            if (ManagedPCrashReporterParent().Length() > 0) {
  1.1258 +                CrashReporterParent* crashReporter =
  1.1259 +                    static_cast<CrashReporterParent*>(ManagedPCrashReporterParent()[0]);
  1.1260 +
  1.1261 +                // If we're an app process, always stomp the latest URI
  1.1262 +                // loaded in the child process with our manifest URL.  We
  1.1263 +                // would rather associate the crashes with apps than
  1.1264 +                // random child windows loaded in them.
  1.1265 +                //
  1.1266 +                // XXX would be nice if we could get both ...
  1.1267 +                if (!mAppManifestURL.IsEmpty()) {
  1.1268 +                    crashReporter->AnnotateCrashReport(NS_LITERAL_CSTRING("URL"),
  1.1269 +                                                       NS_ConvertUTF16toUTF8(mAppManifestURL));
  1.1270 +                }
  1.1271 +
  1.1272 +                crashReporter->GenerateCrashReport(this, nullptr);
  1.1273 +
  1.1274 +                nsAutoString dumpID(crashReporter->ChildDumpID());
  1.1275 +                props->SetPropertyAsAString(NS_LITERAL_STRING("dumpID"), dumpID);
  1.1276 +            }
  1.1277 +#endif
  1.1278 +        }
  1.1279 +        obs->NotifyObservers((nsIPropertyBag2*) props, "ipc:content-shutdown", nullptr);
  1.1280 +    }
  1.1281 +
  1.1282 +    mIdleListeners.Clear();
  1.1283 +
  1.1284 +    // If the child process was terminated due to a SIGKIL, ShutDownProcess
  1.1285 +    // might not have been called yet.  We must call it to ensure that our
  1.1286 +    // channel is closed, etc.
  1.1287 +    ShutDownProcess(/* closeWithError */ true);
  1.1288 +
  1.1289 +    MessageLoop::current()->
  1.1290 +        PostTask(FROM_HERE,
  1.1291 +                 NewRunnableFunction(DelayedDeleteSubprocess, mSubprocess));
  1.1292 +    mSubprocess = nullptr;
  1.1293 +
  1.1294 +    // IPDL rules require actors to live on past ActorDestroy, but it
  1.1295 +    // may be that the kungFuDeathGrip above is the last reference to
  1.1296 +    // |this|.  If so, when we go out of scope here, we're deleted and
  1.1297 +    // all hell breaks loose.
  1.1298 +    //
  1.1299 +    // This runnable ensures that a reference to |this| lives on at
  1.1300 +    // least until after the current task finishes running.
  1.1301 +    NS_DispatchToCurrentThread(new DelayedDeleteContentParentTask(this));
  1.1302 +}
  1.1303 +
  1.1304 +void
  1.1305 +ContentParent::NotifyTabDestroying(PBrowserParent* aTab)
  1.1306 +{
  1.1307 +    // There can be more than one PBrowser for a given app process
  1.1308 +    // because of popup windows.  PBrowsers can also destroy
  1.1309 +    // concurrently.  When all the PBrowsers are destroying, kick off
  1.1310 +    // another task to ensure the child process *really* shuts down,
  1.1311 +    // even if the PBrowsers themselves never finish destroying.
  1.1312 +    int32_t numLiveTabs = ManagedPBrowserParent().Length();
  1.1313 +    ++mNumDestroyingTabs;
  1.1314 +    if (mNumDestroyingTabs != numLiveTabs) {
  1.1315 +        return;
  1.1316 +    }
  1.1317 +
  1.1318 +    // We're dying now, so prevent this content process from being
  1.1319 +    // recycled during its shutdown procedure.
  1.1320 +    MarkAsDead();
  1.1321 +
  1.1322 +    MOZ_ASSERT(!mForceKillTask);
  1.1323 +    int32_t timeoutSecs =
  1.1324 +        Preferences::GetInt("dom.ipc.tabs.shutdownTimeoutSecs", 5);
  1.1325 +    if (timeoutSecs > 0) {
  1.1326 +        MessageLoop::current()->PostDelayedTask(
  1.1327 +            FROM_HERE,
  1.1328 +            mForceKillTask = NewRunnableMethod(this, &ContentParent::KillHard),
  1.1329 +            timeoutSecs * 1000);
  1.1330 +    }
  1.1331 +}
  1.1332 +
  1.1333 +void
  1.1334 +ContentParent::NotifyTabDestroyed(PBrowserParent* aTab,
  1.1335 +                                  bool aNotifiedDestroying)
  1.1336 +{
  1.1337 +    if (aNotifiedDestroying) {
  1.1338 +        --mNumDestroyingTabs;
  1.1339 +    }
  1.1340 +
  1.1341 +    // There can be more than one PBrowser for a given app process
  1.1342 +    // because of popup windows.  When the last one closes, shut
  1.1343 +    // us down.
  1.1344 +    if (ManagedPBrowserParent().Length() == 1) {
  1.1345 +        MessageLoop::current()->PostTask(
  1.1346 +            FROM_HERE,
  1.1347 +            NewRunnableMethod(this, &ContentParent::ShutDownProcess,
  1.1348 +                              /* force */ false));
  1.1349 +    }
  1.1350 +}
  1.1351 +
  1.1352 +jsipc::JavaScriptParent*
  1.1353 +ContentParent::GetCPOWManager()
  1.1354 +{
  1.1355 +    if (ManagedPJavaScriptParent().Length()) {
  1.1356 +        return static_cast<JavaScriptParent*>(ManagedPJavaScriptParent()[0]);
  1.1357 +    }
  1.1358 +    JavaScriptParent* actor = static_cast<JavaScriptParent*>(SendPJavaScriptConstructor());
  1.1359 +    return actor;
  1.1360 +}
  1.1361 +
  1.1362 +TestShellParent*
  1.1363 +ContentParent::CreateTestShell()
  1.1364 +{
  1.1365 +  return static_cast<TestShellParent*>(SendPTestShellConstructor());
  1.1366 +}
  1.1367 +
  1.1368 +bool
  1.1369 +ContentParent::DestroyTestShell(TestShellParent* aTestShell)
  1.1370 +{
  1.1371 +    return PTestShellParent::Send__delete__(aTestShell);
  1.1372 +}
  1.1373 +
  1.1374 +TestShellParent*
  1.1375 +ContentParent::GetTestShellSingleton()
  1.1376 +{
  1.1377 +    if (!ManagedPTestShellParent().Length())
  1.1378 +        return nullptr;
  1.1379 +    return static_cast<TestShellParent*>(ManagedPTestShellParent()[0]);
  1.1380 +}
  1.1381 +
  1.1382 +void
  1.1383 +ContentParent::InitializeMembers()
  1.1384 +{
  1.1385 +    mSubprocess = nullptr;
  1.1386 +    mChildID = gContentChildID++;
  1.1387 +    mGeolocationWatchID = -1;
  1.1388 +    mForceKillTask = nullptr;
  1.1389 +    mNumDestroyingTabs = 0;
  1.1390 +    mIsAlive = true;
  1.1391 +    mSendPermissionUpdates = false;
  1.1392 +    mCalledClose = false;
  1.1393 +    mCalledCloseWithError = false;
  1.1394 +    mCalledKillHard = false;
  1.1395 +}
  1.1396 +
  1.1397 +ContentParent::ContentParent(mozIApplication* aApp,
  1.1398 +                             bool aIsForBrowser,
  1.1399 +                             bool aIsForPreallocated,
  1.1400 +                             ProcessPriority aInitialPriority /* = PROCESS_PRIORITY_FOREGROUND */,
  1.1401 +                             bool aIsNuwaProcess /* = false */)
  1.1402 +    : mIsForBrowser(aIsForBrowser)
  1.1403 +    , mIsNuwaProcess(aIsNuwaProcess)
  1.1404 +{
  1.1405 +    InitializeMembers();  // Perform common initialization.
  1.1406 +
  1.1407 +    // No more than one of !!aApp, aIsForBrowser, aIsForPreallocated should be
  1.1408 +    // true.
  1.1409 +    MOZ_ASSERT(!!aApp + aIsForBrowser + aIsForPreallocated <= 1);
  1.1410 +
  1.1411 +    // Only the preallocated process uses Nuwa.
  1.1412 +    MOZ_ASSERT_IF(aIsNuwaProcess, aIsForPreallocated);
  1.1413 +
  1.1414 +    // Insert ourselves into the global linked list of ContentParent objects.
  1.1415 +    if (!sContentParents) {
  1.1416 +        sContentParents = new LinkedList<ContentParent>();
  1.1417 +    }
  1.1418 +    if (!aIsNuwaProcess) {
  1.1419 +        sContentParents->insertBack(this);
  1.1420 +    }
  1.1421 +
  1.1422 +    if (aApp) {
  1.1423 +        aApp->GetManifestURL(mAppManifestURL);
  1.1424 +        aApp->GetName(mAppName);
  1.1425 +    } else if (aIsForPreallocated) {
  1.1426 +        mAppManifestURL = MAGIC_PREALLOCATED_APP_MANIFEST_URL;
  1.1427 +    }
  1.1428 +
  1.1429 +    // From this point on, NS_WARNING, NS_ASSERTION, etc. should print out the
  1.1430 +    // PID along with the warning.
  1.1431 +    nsDebugImpl::SetMultiprocessMode("Parent");
  1.1432 +
  1.1433 +    NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
  1.1434 +    ChildPrivileges privs = aIsNuwaProcess
  1.1435 +        ? base::PRIVILEGES_INHERIT
  1.1436 +        : base::PRIVILEGES_DEFAULT;
  1.1437 +    mSubprocess = new GeckoChildProcessHost(GeckoProcessType_Content, privs);
  1.1438 +    mSubprocess->SetSandboxEnabled(ShouldSandboxContentProcesses());
  1.1439 +
  1.1440 +    IToplevelProtocol::SetTransport(mSubprocess->GetChannel());
  1.1441 +
  1.1442 +    if (!aIsNuwaProcess) {
  1.1443 +        // Tell the memory reporter manager that this ContentParent exists.
  1.1444 +        nsRefPtr<nsMemoryReporterManager> mgr =
  1.1445 +            nsMemoryReporterManager::GetOrCreate();
  1.1446 +        if (mgr) {
  1.1447 +            mgr->IncrementNumChildProcesses();
  1.1448 +        }
  1.1449 +    }
  1.1450 +
  1.1451 +    std::vector<std::string> extraArgs;
  1.1452 +    if (aIsNuwaProcess) {
  1.1453 +        extraArgs.push_back("-nuwa");
  1.1454 +    }
  1.1455 +    mSubprocess->LaunchAndWaitForProcessHandle(extraArgs);
  1.1456 +
  1.1457 +    Open(mSubprocess->GetChannel(), mSubprocess->GetOwnedChildProcessHandle());
  1.1458 +
  1.1459 +    InitInternal(aInitialPriority,
  1.1460 +                 true, /* Setup off-main thread compositing */
  1.1461 +                 true  /* Send registered chrome */);
  1.1462 +}
  1.1463 +
  1.1464 +#ifdef MOZ_NUWA_PROCESS
  1.1465 +static const mozilla::ipc::FileDescriptor*
  1.1466 +FindFdProtocolFdMapping(const nsTArray<ProtocolFdMapping>& aFds,
  1.1467 +                        ProtocolId aProtoId)
  1.1468 +{
  1.1469 +    for (unsigned int i = 0; i < aFds.Length(); i++) {
  1.1470 +        if (aFds[i].protocolId() == aProtoId) {
  1.1471 +            return &aFds[i].fd();
  1.1472 +        }
  1.1473 +    }
  1.1474 +    return nullptr;
  1.1475 +}
  1.1476 +
  1.1477 +/**
  1.1478 + * This constructor is used for new content process cloned from a template.
  1.1479 + *
  1.1480 + * For Nuwa.
  1.1481 + */
  1.1482 +ContentParent::ContentParent(ContentParent* aTemplate,
  1.1483 +                             const nsAString& aAppManifestURL,
  1.1484 +                             base::ProcessHandle aPid,
  1.1485 +                             const nsTArray<ProtocolFdMapping>& aFds)
  1.1486 +    : mAppManifestURL(aAppManifestURL)
  1.1487 +    , mIsForBrowser(false)
  1.1488 +    , mIsNuwaProcess(false)
  1.1489 +{
  1.1490 +    InitializeMembers();  // Perform common initialization.
  1.1491 +
  1.1492 +    sContentParents->insertBack(this);
  1.1493 +
  1.1494 +    // From this point on, NS_WARNING, NS_ASSERTION, etc. should print out the
  1.1495 +    // PID along with the warning.
  1.1496 +    nsDebugImpl::SetMultiprocessMode("Parent");
  1.1497 +
  1.1498 +    NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
  1.1499 +
  1.1500 +    const FileDescriptor* fd = FindFdProtocolFdMapping(aFds, GetProtocolId());
  1.1501 +
  1.1502 +    NS_ASSERTION(fd != nullptr, "IPC Channel for PContent is necessary!");
  1.1503 +    mSubprocess = new GeckoExistingProcessHost(GeckoProcessType_Content,
  1.1504 +                                               aPid,
  1.1505 +                                               *fd);
  1.1506 +
  1.1507 +    // Tell the memory reporter manager that this ContentParent exists.
  1.1508 +    nsRefPtr<nsMemoryReporterManager> mgr =
  1.1509 +        nsMemoryReporterManager::GetOrCreate();
  1.1510 +    if (mgr) {
  1.1511 +        mgr->IncrementNumChildProcesses();
  1.1512 +    }
  1.1513 +
  1.1514 +    mSubprocess->LaunchAndWaitForProcessHandle();
  1.1515 +
  1.1516 +    // Clone actors routed by aTemplate for this instance.
  1.1517 +    IToplevelProtocol::SetTransport(mSubprocess->GetChannel());
  1.1518 +    ProtocolCloneContext cloneContext;
  1.1519 +    cloneContext.SetContentParent(this);
  1.1520 +    CloneManagees(aTemplate, &cloneContext);
  1.1521 +    CloneOpenedToplevels(aTemplate, aFds, aPid, &cloneContext);
  1.1522 +
  1.1523 +    Open(mSubprocess->GetChannel(),
  1.1524 +         mSubprocess->GetChildProcessHandle());
  1.1525 +
  1.1526 +    // Set the subprocess's priority (bg if we're a preallocated process, fg
  1.1527 +    // otherwise).  We do this first because we're likely /lowering/ its CPU and
  1.1528 +    // memory priority, which it has inherited from this process.
  1.1529 +    ProcessPriority priority;
  1.1530 +    if (IsPreallocated()) {
  1.1531 +        priority = PROCESS_PRIORITY_PREALLOC;
  1.1532 +    } else {
  1.1533 +        priority = PROCESS_PRIORITY_FOREGROUND;
  1.1534 +    }
  1.1535 +
  1.1536 +    InitInternal(priority,
  1.1537 +                 false, /* Setup Off-main thread compositing */
  1.1538 +                 false  /* Send registered chrome */);
  1.1539 +}
  1.1540 +#endif  // MOZ_NUWA_PROCESS
  1.1541 +
  1.1542 +ContentParent::~ContentParent()
  1.1543 +{
  1.1544 +    if (mForceKillTask) {
  1.1545 +        mForceKillTask->Cancel();
  1.1546 +    }
  1.1547 +
  1.1548 +    if (OtherProcess())
  1.1549 +        base::CloseProcessHandle(OtherProcess());
  1.1550 +
  1.1551 +    NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
  1.1552 +
  1.1553 +    // We should be removed from all these lists in ActorDestroy.
  1.1554 +    MOZ_ASSERT(!sPrivateContent || !sPrivateContent->Contains(this));
  1.1555 +    if (mAppManifestURL.IsEmpty()) {
  1.1556 +        MOZ_ASSERT(!sNonAppContentParents ||
  1.1557 +                   !sNonAppContentParents->Contains(this));
  1.1558 +    } else {
  1.1559 +        // In general, we expect sAppContentParents->Get(mAppManifestURL) to be
  1.1560 +        // nullptr.  But it could be that we created another ContentParent for
  1.1561 +        // this app after we did this->ActorDestroy(), so the right check is
  1.1562 +        // that sAppContentParents->Get(mAppManifestURL) != this.
  1.1563 +        MOZ_ASSERT(!sAppContentParents ||
  1.1564 +                   sAppContentParents->Get(mAppManifestURL) != this);
  1.1565 +    }
  1.1566 +}
  1.1567 +
  1.1568 +void
  1.1569 +ContentParent::InitInternal(ProcessPriority aInitialPriority,
  1.1570 +                            bool aSetupOffMainThreadCompositing,
  1.1571 +                            bool aSendRegisteredChrome)
  1.1572 +{
  1.1573 +    // Set the subprocess's priority.  We do this early on because we're likely
  1.1574 +    // /lowering/ the process's CPU and memory priority, which it has inherited
  1.1575 +    // from this process.
  1.1576 +    //
  1.1577 +    // This call can cause us to send IPC messages to the child process, so it
  1.1578 +    // must come after the Open() call above.
  1.1579 +    ProcessPriorityManager::SetProcessPriority(this, aInitialPriority);
  1.1580 +
  1.1581 +    if (aSetupOffMainThreadCompositing) {
  1.1582 +        // NB: internally, this will send an IPC message to the child
  1.1583 +        // process to get it to create the CompositorChild.  This
  1.1584 +        // message goes through the regular IPC queue for this
  1.1585 +        // channel, so delivery will happen-before any other messages
  1.1586 +        // we send.  The CompositorChild must be created before any
  1.1587 +        // PBrowsers are created, because they rely on the Compositor
  1.1588 +        // already being around.  (Creation is async, so can't happen
  1.1589 +        // on demand.)
  1.1590 +        bool useOffMainThreadCompositing = !!CompositorParent::CompositorLoop();
  1.1591 +        if (useOffMainThreadCompositing) {
  1.1592 +            DebugOnly<bool> opened = PCompositor::Open(this);
  1.1593 +            MOZ_ASSERT(opened);
  1.1594 +
  1.1595 +            if (gfxPrefs::AsyncVideoEnabled()) {
  1.1596 +                opened = PImageBridge::Open(this);
  1.1597 +                MOZ_ASSERT(opened);
  1.1598 +            }
  1.1599 +        }
  1.1600 +    }
  1.1601 +
  1.1602 +    if (aSendRegisteredChrome) {
  1.1603 +        nsCOMPtr<nsIChromeRegistry> registrySvc = nsChromeRegistry::GetService();
  1.1604 +        nsChromeRegistryChrome* chromeRegistry =
  1.1605 +            static_cast<nsChromeRegistryChrome*>(registrySvc.get());
  1.1606 +        chromeRegistry->SendRegisteredChrome(this);
  1.1607 +    }
  1.1608 +
  1.1609 +    mMessageManager = nsFrameMessageManager::NewProcessMessageManager(this);
  1.1610 +
  1.1611 +    if (gAppData) {
  1.1612 +        nsCString version(gAppData->version);
  1.1613 +        nsCString buildID(gAppData->buildID);
  1.1614 +        nsCString name(gAppData->name);
  1.1615 +        nsCString UAName(gAppData->UAName);
  1.1616 +
  1.1617 +        // Sending all information to content process.
  1.1618 +        unused << SendAppInfo(version, buildID, name, UAName);
  1.1619 +    }
  1.1620 +
  1.1621 +    nsStyleSheetService *sheetService = nsStyleSheetService::GetInstance();
  1.1622 +    if (sheetService) {
  1.1623 +        // This looks like a lot of work, but in a normal browser session we just
  1.1624 +        // send two loads.
  1.1625 +
  1.1626 +        nsCOMArray<nsIStyleSheet>& agentSheets = *sheetService->AgentStyleSheets();
  1.1627 +        for (uint32_t i = 0; i < agentSheets.Length(); i++) {
  1.1628 +            URIParams uri;
  1.1629 +            SerializeURI(agentSheets[i]->GetSheetURI(), uri);
  1.1630 +            unused << SendLoadAndRegisterSheet(uri, nsIStyleSheetService::AGENT_SHEET);
  1.1631 +        }
  1.1632 +
  1.1633 +        nsCOMArray<nsIStyleSheet>& userSheets = *sheetService->UserStyleSheets();
  1.1634 +        for (uint32_t i = 0; i < userSheets.Length(); i++) {
  1.1635 +            URIParams uri;
  1.1636 +            SerializeURI(userSheets[i]->GetSheetURI(), uri);
  1.1637 +            unused << SendLoadAndRegisterSheet(uri, nsIStyleSheetService::USER_SHEET);
  1.1638 +        }
  1.1639 +
  1.1640 +        nsCOMArray<nsIStyleSheet>& authorSheets = *sheetService->AuthorStyleSheets();
  1.1641 +        for (uint32_t i = 0; i < authorSheets.Length(); i++) {
  1.1642 +            URIParams uri;
  1.1643 +            SerializeURI(authorSheets[i]->GetSheetURI(), uri);
  1.1644 +            unused << SendLoadAndRegisterSheet(uri, nsIStyleSheetService::AUTHOR_SHEET);
  1.1645 +        }
  1.1646 +    }
  1.1647 +
  1.1648 +#ifdef MOZ_CONTENT_SANDBOX
  1.1649 +    bool shouldSandbox = true;
  1.1650 +#ifdef MOZ_NUWA_PROCESS
  1.1651 +    if (IsNuwaProcess()) {
  1.1652 +        shouldSandbox = false;
  1.1653 +    }
  1.1654 +#endif
  1.1655 +    if (shouldSandbox && !SendSetProcessSandbox()) {
  1.1656 +        KillHard();
  1.1657 +    }
  1.1658 +#endif
  1.1659 +}
  1.1660 +
  1.1661 +bool
  1.1662 +ContentParent::IsAlive()
  1.1663 +{
  1.1664 +    return mIsAlive;
  1.1665 +}
  1.1666 +
  1.1667 +bool
  1.1668 +ContentParent::IsForApp()
  1.1669 +{
  1.1670 +    return !mAppManifestURL.IsEmpty();
  1.1671 +}
  1.1672 +
  1.1673 +#ifdef MOZ_NUWA_PROCESS
  1.1674 +bool
  1.1675 +ContentParent::IsNuwaProcess()
  1.1676 +{
  1.1677 +    return mIsNuwaProcess;
  1.1678 +}
  1.1679 +#endif
  1.1680 +
  1.1681 +int32_t
  1.1682 +ContentParent::Pid()
  1.1683 +{
  1.1684 +    if (!mSubprocess || !mSubprocess->GetChildProcessHandle()) {
  1.1685 +        return -1;
  1.1686 +    }
  1.1687 +    return base::GetProcId(mSubprocess->GetChildProcessHandle());
  1.1688 +}
  1.1689 +
  1.1690 +bool
  1.1691 +ContentParent::RecvReadPrefsArray(InfallibleTArray<PrefSetting>* aPrefs)
  1.1692 +{
  1.1693 +    Preferences::GetPreferences(aPrefs);
  1.1694 +    return true;
  1.1695 +}
  1.1696 +
  1.1697 +bool
  1.1698 +ContentParent::RecvReadFontList(InfallibleTArray<FontListEntry>* retValue)
  1.1699 +{
  1.1700 +#ifdef ANDROID
  1.1701 +    gfxAndroidPlatform::GetPlatform()->GetFontList(retValue);
  1.1702 +#endif
  1.1703 +    return true;
  1.1704 +}
  1.1705 +
  1.1706 +bool
  1.1707 +ContentParent::RecvReadPermissions(InfallibleTArray<IPC::Permission>* aPermissions)
  1.1708 +{
  1.1709 +#ifdef MOZ_PERMISSIONS
  1.1710 +    nsCOMPtr<nsIPermissionManager> permissionManagerIface =
  1.1711 +        do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
  1.1712 +    nsPermissionManager* permissionManager =
  1.1713 +        static_cast<nsPermissionManager*>(permissionManagerIface.get());
  1.1714 +    NS_ABORT_IF_FALSE(permissionManager,
  1.1715 +                 "We have no permissionManager in the Chrome process !");
  1.1716 +
  1.1717 +    nsCOMPtr<nsISimpleEnumerator> enumerator;
  1.1718 +    DebugOnly<nsresult> rv = permissionManager->GetEnumerator(getter_AddRefs(enumerator));
  1.1719 +    NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv), "Could not get enumerator!");
  1.1720 +    while(1) {
  1.1721 +        bool hasMore;
  1.1722 +        enumerator->HasMoreElements(&hasMore);
  1.1723 +        if (!hasMore)
  1.1724 +            break;
  1.1725 +
  1.1726 +        nsCOMPtr<nsISupports> supp;
  1.1727 +        enumerator->GetNext(getter_AddRefs(supp));
  1.1728 +        nsCOMPtr<nsIPermission> perm = do_QueryInterface(supp);
  1.1729 +
  1.1730 +        nsCString host;
  1.1731 +        perm->GetHost(host);
  1.1732 +        uint32_t appId;
  1.1733 +        perm->GetAppId(&appId);
  1.1734 +        bool isInBrowserElement;
  1.1735 +        perm->GetIsInBrowserElement(&isInBrowserElement);
  1.1736 +        nsCString type;
  1.1737 +        perm->GetType(type);
  1.1738 +        uint32_t capability;
  1.1739 +        perm->GetCapability(&capability);
  1.1740 +        uint32_t expireType;
  1.1741 +        perm->GetExpireType(&expireType);
  1.1742 +        int64_t expireTime;
  1.1743 +        perm->GetExpireTime(&expireTime);
  1.1744 +
  1.1745 +        aPermissions->AppendElement(IPC::Permission(host, appId,
  1.1746 +                                                    isInBrowserElement, type,
  1.1747 +                                                    capability, expireType,
  1.1748 +                                                    expireTime));
  1.1749 +    }
  1.1750 +
  1.1751 +    // Ask for future changes
  1.1752 +    mSendPermissionUpdates = true;
  1.1753 +#endif
  1.1754 +
  1.1755 +    return true;
  1.1756 +}
  1.1757 +
  1.1758 +bool
  1.1759 +ContentParent::RecvSetClipboardText(const nsString& text,
  1.1760 +                                       const bool& isPrivateData,
  1.1761 +                                       const int32_t& whichClipboard)
  1.1762 +{
  1.1763 +    nsresult rv;
  1.1764 +    nsCOMPtr<nsIClipboard> clipboard(do_GetService(kCClipboardCID, &rv));
  1.1765 +    NS_ENSURE_SUCCESS(rv, true);
  1.1766 +
  1.1767 +    nsCOMPtr<nsISupportsString> dataWrapper =
  1.1768 +        do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
  1.1769 +    NS_ENSURE_SUCCESS(rv, true);
  1.1770 +
  1.1771 +    rv = dataWrapper->SetData(text);
  1.1772 +    NS_ENSURE_SUCCESS(rv, true);
  1.1773 +
  1.1774 +    nsCOMPtr<nsITransferable> trans = do_CreateInstance("@mozilla.org/widget/transferable;1", &rv);
  1.1775 +    NS_ENSURE_SUCCESS(rv, true);
  1.1776 +    trans->Init(nullptr);
  1.1777 +
  1.1778 +    // If our data flavor has already been added, this will fail. But we don't care
  1.1779 +    trans->AddDataFlavor(kUnicodeMime);
  1.1780 +    trans->SetIsPrivateData(isPrivateData);
  1.1781 +
  1.1782 +    nsCOMPtr<nsISupports> nsisupportsDataWrapper =
  1.1783 +        do_QueryInterface(dataWrapper);
  1.1784 +
  1.1785 +    rv = trans->SetTransferData(kUnicodeMime, nsisupportsDataWrapper,
  1.1786 +                                text.Length() * sizeof(char16_t));
  1.1787 +    NS_ENSURE_SUCCESS(rv, true);
  1.1788 +
  1.1789 +    clipboard->SetData(trans, nullptr, whichClipboard);
  1.1790 +    return true;
  1.1791 +}
  1.1792 +
  1.1793 +bool
  1.1794 +ContentParent::RecvGetClipboardText(const int32_t& whichClipboard, nsString* text)
  1.1795 +{
  1.1796 +    nsresult rv;
  1.1797 +    nsCOMPtr<nsIClipboard> clipboard(do_GetService(kCClipboardCID, &rv));
  1.1798 +    NS_ENSURE_SUCCESS(rv, true);
  1.1799 +
  1.1800 +    nsCOMPtr<nsITransferable> trans = do_CreateInstance("@mozilla.org/widget/transferable;1", &rv);
  1.1801 +    NS_ENSURE_SUCCESS(rv, true);
  1.1802 +    trans->Init(nullptr);
  1.1803 +    trans->AddDataFlavor(kUnicodeMime);
  1.1804 +
  1.1805 +    clipboard->GetData(trans, whichClipboard);
  1.1806 +    nsCOMPtr<nsISupports> tmp;
  1.1807 +    uint32_t len;
  1.1808 +    rv = trans->GetTransferData(kUnicodeMime, getter_AddRefs(tmp), &len);
  1.1809 +    if (NS_FAILED(rv))
  1.1810 +        return true;
  1.1811 +
  1.1812 +    nsCOMPtr<nsISupportsString> supportsString = do_QueryInterface(tmp);
  1.1813 +    // No support for non-text data
  1.1814 +    if (!supportsString)
  1.1815 +        return true;
  1.1816 +    supportsString->GetData(*text);
  1.1817 +    return true;
  1.1818 +}
  1.1819 +
  1.1820 +bool
  1.1821 +ContentParent::RecvEmptyClipboard(const int32_t& whichClipboard)
  1.1822 +{
  1.1823 +    nsresult rv;
  1.1824 +    nsCOMPtr<nsIClipboard> clipboard(do_GetService(kCClipboardCID, &rv));
  1.1825 +    NS_ENSURE_SUCCESS(rv, true);
  1.1826 +
  1.1827 +    clipboard->EmptyClipboard(whichClipboard);
  1.1828 +
  1.1829 +    return true;
  1.1830 +}
  1.1831 +
  1.1832 +bool
  1.1833 +ContentParent::RecvClipboardHasText(const int32_t& whichClipboard, bool* hasText)
  1.1834 +{
  1.1835 +    nsresult rv;
  1.1836 +    nsCOMPtr<nsIClipboard> clipboard(do_GetService(kCClipboardCID, &rv));
  1.1837 +    NS_ENSURE_SUCCESS(rv, true);
  1.1838 +
  1.1839 +    clipboard->HasDataMatchingFlavors(sClipboardTextFlavors, 1,
  1.1840 +                                      whichClipboard, hasText);
  1.1841 +    return true;
  1.1842 +}
  1.1843 +
  1.1844 +bool
  1.1845 +ContentParent::RecvGetSystemColors(const uint32_t& colorsCount, InfallibleTArray<uint32_t>* colors)
  1.1846 +{
  1.1847 +#ifdef MOZ_WIDGET_ANDROID
  1.1848 +    NS_ASSERTION(AndroidBridge::Bridge() != nullptr, "AndroidBridge is not available");
  1.1849 +    if (AndroidBridge::Bridge() == nullptr) {
  1.1850 +        // Do not fail - the colors won't be right, but it's not critical
  1.1851 +        return true;
  1.1852 +    }
  1.1853 +
  1.1854 +    colors->AppendElements(colorsCount);
  1.1855 +
  1.1856 +    // The array elements correspond to the members of AndroidSystemColors structure,
  1.1857 +    // so just pass the pointer to the elements buffer
  1.1858 +    AndroidBridge::Bridge()->GetSystemColors((AndroidSystemColors*)colors->Elements());
  1.1859 +#endif
  1.1860 +    return true;
  1.1861 +}
  1.1862 +
  1.1863 +bool
  1.1864 +ContentParent::RecvGetIconForExtension(const nsCString& aFileExt, const uint32_t& aIconSize, InfallibleTArray<uint8_t>* bits)
  1.1865 +{
  1.1866 +#ifdef MOZ_WIDGET_ANDROID
  1.1867 +    NS_ASSERTION(AndroidBridge::Bridge() != nullptr, "AndroidBridge is not available");
  1.1868 +    if (AndroidBridge::Bridge() == nullptr) {
  1.1869 +        // Do not fail - just no icon will be shown
  1.1870 +        return true;
  1.1871 +    }
  1.1872 +
  1.1873 +    bits->AppendElements(aIconSize * aIconSize * 4);
  1.1874 +
  1.1875 +    AndroidBridge::Bridge()->GetIconForExtension(aFileExt, aIconSize, bits->Elements());
  1.1876 +#endif
  1.1877 +    return true;
  1.1878 +}
  1.1879 +
  1.1880 +bool
  1.1881 +ContentParent::RecvGetShowPasswordSetting(bool* showPassword)
  1.1882 +{
  1.1883 +    // default behavior is to show the last password character
  1.1884 +    *showPassword = true;
  1.1885 +#ifdef MOZ_WIDGET_ANDROID
  1.1886 +    NS_ASSERTION(AndroidBridge::Bridge() != nullptr, "AndroidBridge is not available");
  1.1887 +
  1.1888 +    *showPassword = mozilla::widget::android::GeckoAppShell::GetShowPasswordSetting();
  1.1889 +#endif
  1.1890 +    return true;
  1.1891 +}
  1.1892 +
  1.1893 +bool
  1.1894 +ContentParent::RecvFirstIdle()
  1.1895 +{
  1.1896 +    // When the ContentChild goes idle, it sends us a FirstIdle message
  1.1897 +    // which we use as a good time to prelaunch another process. If we
  1.1898 +    // prelaunch any sooner than this, then we'll be competing with the
  1.1899 +    // child process and slowing it down.
  1.1900 +    PreallocatedProcessManager::AllocateAfterDelay();
  1.1901 +    return true;
  1.1902 +}
  1.1903 +
  1.1904 +bool
  1.1905 +ContentParent::RecvAudioChannelGetState(const AudioChannel& aChannel,
  1.1906 +                                        const bool& aElementHidden,
  1.1907 +                                        const bool& aElementWasHidden,
  1.1908 +                                        AudioChannelState* aState)
  1.1909 +{
  1.1910 +    nsRefPtr<AudioChannelService> service =
  1.1911 +        AudioChannelService::GetAudioChannelService();
  1.1912 +    *aState = AUDIO_CHANNEL_STATE_NORMAL;
  1.1913 +    if (service) {
  1.1914 +        *aState = service->GetStateInternal(aChannel, mChildID,
  1.1915 +                                            aElementHidden, aElementWasHidden);
  1.1916 +    }
  1.1917 +    return true;
  1.1918 +}
  1.1919 +
  1.1920 +bool
  1.1921 +ContentParent::RecvAudioChannelRegisterType(const AudioChannel& aChannel,
  1.1922 +                                            const bool& aWithVideo)
  1.1923 +{
  1.1924 +    nsRefPtr<AudioChannelService> service =
  1.1925 +        AudioChannelService::GetAudioChannelService();
  1.1926 +    if (service) {
  1.1927 +        service->RegisterType(aChannel, mChildID, aWithVideo);
  1.1928 +    }
  1.1929 +    return true;
  1.1930 +}
  1.1931 +
  1.1932 +bool
  1.1933 +ContentParent::RecvAudioChannelUnregisterType(const AudioChannel& aChannel,
  1.1934 +                                              const bool& aElementHidden,
  1.1935 +                                              const bool& aWithVideo)
  1.1936 +{
  1.1937 +    nsRefPtr<AudioChannelService> service =
  1.1938 +        AudioChannelService::GetAudioChannelService();
  1.1939 +    if (service) {
  1.1940 +        service->UnregisterType(aChannel, aElementHidden, mChildID, aWithVideo);
  1.1941 +    }
  1.1942 +    return true;
  1.1943 +}
  1.1944 +
  1.1945 +bool
  1.1946 +ContentParent::RecvAudioChannelChangedNotification()
  1.1947 +{
  1.1948 +    nsRefPtr<AudioChannelService> service =
  1.1949 +        AudioChannelService::GetAudioChannelService();
  1.1950 +    if (service) {
  1.1951 +       service->SendAudioChannelChangedNotification(ChildID());
  1.1952 +    }
  1.1953 +    return true;
  1.1954 +}
  1.1955 +
  1.1956 +bool
  1.1957 +ContentParent::RecvAudioChannelChangeDefVolChannel(const int32_t& aChannel,
  1.1958 +                                                   const bool& aHidden)
  1.1959 +{
  1.1960 +    nsRefPtr<AudioChannelService> service =
  1.1961 +        AudioChannelService::GetAudioChannelService();
  1.1962 +    if (service) {
  1.1963 +       service->SetDefaultVolumeControlChannelInternal(aChannel,
  1.1964 +                                                       aHidden, mChildID);
  1.1965 +    }
  1.1966 +    return true;
  1.1967 +}
  1.1968 +
  1.1969 +bool
  1.1970 +ContentParent::RecvBroadcastVolume(const nsString& aVolumeName)
  1.1971 +{
  1.1972 +#ifdef MOZ_WIDGET_GONK
  1.1973 +    nsresult rv;
  1.1974 +    nsCOMPtr<nsIVolumeService> vs = do_GetService(NS_VOLUMESERVICE_CONTRACTID, &rv);
  1.1975 +    if (vs) {
  1.1976 +        vs->BroadcastVolume(aVolumeName);
  1.1977 +    }
  1.1978 +    return true;
  1.1979 +#else
  1.1980 +    NS_WARNING("ContentParent::RecvBroadcastVolume shouldn't be called when MOZ_WIDGET_GONK is not defined");
  1.1981 +    return false;
  1.1982 +#endif
  1.1983 +}
  1.1984 +
  1.1985 +bool
  1.1986 +ContentParent::RecvNuwaReady()
  1.1987 +{
  1.1988 +#ifdef MOZ_NUWA_PROCESS
  1.1989 +    if (!IsNuwaProcess()) {
  1.1990 +        NS_ERROR(
  1.1991 +            nsPrintfCString(
  1.1992 +                "Terminating child process %d for unauthorized IPC message: NuwaReady",
  1.1993 +                Pid()).get());
  1.1994 +
  1.1995 +        KillHard();
  1.1996 +        return false;
  1.1997 +    }
  1.1998 +    PreallocatedProcessManager::OnNuwaReady();
  1.1999 +    return true;
  1.2000 +#else
  1.2001 +    NS_ERROR("ContentParent::RecvNuwaReady() not implemented!");
  1.2002 +    return false;
  1.2003 +#endif
  1.2004 +}
  1.2005 +
  1.2006 +bool
  1.2007 +ContentParent::RecvAddNewProcess(const uint32_t& aPid,
  1.2008 +                                 const InfallibleTArray<ProtocolFdMapping>& aFds)
  1.2009 +{
  1.2010 +#ifdef MOZ_NUWA_PROCESS
  1.2011 +    if (!IsNuwaProcess()) {
  1.2012 +        NS_ERROR(
  1.2013 +            nsPrintfCString(
  1.2014 +                "Terminating child process %d for unauthorized IPC message: "
  1.2015 +                "AddNewProcess(%d)", Pid(), aPid).get());
  1.2016 +
  1.2017 +        KillHard();
  1.2018 +        return false;
  1.2019 +    }
  1.2020 +    nsRefPtr<ContentParent> content;
  1.2021 +    content = new ContentParent(this,
  1.2022 +                                MAGIC_PREALLOCATED_APP_MANIFEST_URL,
  1.2023 +                                aPid,
  1.2024 +                                aFds);
  1.2025 +    content->Init();
  1.2026 +    PreallocatedProcessManager::PublishSpareProcess(content);
  1.2027 +    return true;
  1.2028 +#else
  1.2029 +    NS_ERROR("ContentParent::RecvAddNewProcess() not implemented!");
  1.2030 +    return false;
  1.2031 +#endif
  1.2032 +}
  1.2033 +
  1.2034 +// We want ContentParent to show up in CC logs for debugging purposes, but we
  1.2035 +// don't actually cycle collect it.
  1.2036 +NS_IMPL_CYCLE_COLLECTION_0(ContentParent)
  1.2037 +
  1.2038 +NS_IMPL_CYCLE_COLLECTING_ADDREF(ContentParent)
  1.2039 +NS_IMPL_CYCLE_COLLECTING_RELEASE(ContentParent)
  1.2040 +
  1.2041 +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ContentParent)
  1.2042 +  NS_INTERFACE_MAP_ENTRY(nsIObserver)
  1.2043 +  NS_INTERFACE_MAP_ENTRY(nsIDOMGeoPositionCallback)
  1.2044 +  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver)
  1.2045 +NS_INTERFACE_MAP_END
  1.2046 +
  1.2047 +NS_IMETHODIMP
  1.2048 +ContentParent::Observe(nsISupports* aSubject,
  1.2049 +                       const char* aTopic,
  1.2050 +                       const char16_t* aData)
  1.2051 +{
  1.2052 +    if (!strcmp(aTopic, "xpcom-shutdown") && mSubprocess) {
  1.2053 +        ShutDownProcess(/* closeWithError */ false);
  1.2054 +        NS_ASSERTION(!mSubprocess, "Close should have nulled mSubprocess");
  1.2055 +    }
  1.2056 +
  1.2057 +    if (!mIsAlive || !mSubprocess)
  1.2058 +        return NS_OK;
  1.2059 +
  1.2060 +    // listening for memory pressure event
  1.2061 +    if (!strcmp(aTopic, "memory-pressure") &&
  1.2062 +        !StringEndsWith(nsDependentString(aData),
  1.2063 +                        NS_LITERAL_STRING("-no-forward"))) {
  1.2064 +        unused << SendFlushMemory(nsDependentString(aData));
  1.2065 +    }
  1.2066 +    // listening for remotePrefs...
  1.2067 +    else if (!strcmp(aTopic, "nsPref:changed")) {
  1.2068 +        // We know prefs are ASCII here.
  1.2069 +        NS_LossyConvertUTF16toASCII strData(aData);
  1.2070 +
  1.2071 +        PrefSetting pref(strData, null_t(), null_t());
  1.2072 +        Preferences::GetPreference(&pref);
  1.2073 +        if (!SendPreferenceUpdate(pref)) {
  1.2074 +            return NS_ERROR_NOT_AVAILABLE;
  1.2075 +        }
  1.2076 +    }
  1.2077 +    else if (!strcmp(aTopic, NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC)) {
  1.2078 +      NS_ConvertUTF16toUTF8 dataStr(aData);
  1.2079 +      const char *offline = dataStr.get();
  1.2080 +      if (!SendSetOffline(!strcmp(offline, "true") ? true : false))
  1.2081 +          return NS_ERROR_NOT_AVAILABLE;
  1.2082 +    }
  1.2083 +    // listening for alert notifications
  1.2084 +    else if (!strcmp(aTopic, "alertfinished") ||
  1.2085 +             !strcmp(aTopic, "alertclickcallback") ||
  1.2086 +             !strcmp(aTopic, "alertshow") ) {
  1.2087 +        if (!SendNotifyAlertsObserver(nsDependentCString(aTopic),
  1.2088 +                                      nsDependentString(aData)))
  1.2089 +            return NS_ERROR_NOT_AVAILABLE;
  1.2090 +    }
  1.2091 +    else if (!strcmp(aTopic, "child-memory-reporter-request")) {
  1.2092 +        bool isNuwa = false;
  1.2093 +#ifdef MOZ_NUWA_PROCESS
  1.2094 +        isNuwa = IsNuwaProcess();
  1.2095 +#endif
  1.2096 +        if (!isNuwa) {
  1.2097 +            unsigned generation;
  1.2098 +            int minimize, identOffset = -1;
  1.2099 +            nsDependentString msg(aData);
  1.2100 +            NS_ConvertUTF16toUTF8 cmsg(msg);
  1.2101 +
  1.2102 +            if (sscanf(cmsg.get(),
  1.2103 +                       "generation=%x minimize=%d DMDident=%n",
  1.2104 +                       &generation, &minimize, &identOffset) < 2
  1.2105 +                || identOffset < 0) {
  1.2106 +                return NS_ERROR_INVALID_ARG;
  1.2107 +            }
  1.2108 +            // The pre-%n part of the string should be all ASCII, so the byte
  1.2109 +            // offset in identOffset should be correct as a char offset.
  1.2110 +            MOZ_ASSERT(cmsg[identOffset - 1] == '=');
  1.2111 +            unused << SendPMemoryReportRequestConstructor(
  1.2112 +              generation, minimize, nsString(Substring(msg, identOffset)));
  1.2113 +        }
  1.2114 +    }
  1.2115 +    else if (!strcmp(aTopic, "child-gc-request")){
  1.2116 +        unused << SendGarbageCollect();
  1.2117 +    }
  1.2118 +    else if (!strcmp(aTopic, "child-cc-request")){
  1.2119 +        unused << SendCycleCollect();
  1.2120 +    }
  1.2121 +    else if (!strcmp(aTopic, "child-mmu-request")){
  1.2122 +        unused << SendMinimizeMemoryUsage();
  1.2123 +    }
  1.2124 +    else if (!strcmp(aTopic, "last-pb-context-exited")) {
  1.2125 +        unused << SendLastPrivateDocShellDestroyed();
  1.2126 +    }
  1.2127 +    else if (!strcmp(aTopic, "file-watcher-update")) {
  1.2128 +        nsCString creason;
  1.2129 +        CopyUTF16toUTF8(aData, creason);
  1.2130 +        DeviceStorageFile* file = static_cast<DeviceStorageFile*>(aSubject);
  1.2131 +
  1.2132 +        unused << SendFilePathUpdate(file->mStorageType, file->mStorageName, file->mPath, creason);
  1.2133 +    }
  1.2134 +#ifdef MOZ_WIDGET_GONK
  1.2135 +    else if(!strcmp(aTopic, NS_VOLUME_STATE_CHANGED)) {
  1.2136 +        nsCOMPtr<nsIVolume> vol = do_QueryInterface(aSubject);
  1.2137 +        if (!vol) {
  1.2138 +            return NS_ERROR_NOT_AVAILABLE;
  1.2139 +        }
  1.2140 +
  1.2141 +        nsString volName;
  1.2142 +        nsString mountPoint;
  1.2143 +        int32_t  state;
  1.2144 +        int32_t  mountGeneration;
  1.2145 +        bool     isMediaPresent;
  1.2146 +        bool     isSharing;
  1.2147 +        bool     isFormatting;
  1.2148 +
  1.2149 +        vol->GetName(volName);
  1.2150 +        vol->GetMountPoint(mountPoint);
  1.2151 +        vol->GetState(&state);
  1.2152 +        vol->GetMountGeneration(&mountGeneration);
  1.2153 +        vol->GetIsMediaPresent(&isMediaPresent);
  1.2154 +        vol->GetIsSharing(&isSharing);
  1.2155 +        vol->GetIsFormatting(&isFormatting);
  1.2156 +
  1.2157 +        unused << SendFileSystemUpdate(volName, mountPoint, state,
  1.2158 +                                       mountGeneration, isMediaPresent,
  1.2159 +                                       isSharing, isFormatting);
  1.2160 +    } else if (!strcmp(aTopic, "phone-state-changed")) {
  1.2161 +        nsString state(aData);
  1.2162 +        unused << SendNotifyPhoneStateChange(state);
  1.2163 +    }
  1.2164 +#endif
  1.2165 +#ifdef ACCESSIBILITY
  1.2166 +    // Make sure accessibility is running in content process when accessibility
  1.2167 +    // gets initiated in chrome process.
  1.2168 +    else if (aData && (*aData == '1') &&
  1.2169 +             !strcmp(aTopic, "a11y-init-or-shutdown")) {
  1.2170 +        unused << SendActivateA11y();
  1.2171 +    }
  1.2172 +#endif
  1.2173 +
  1.2174 +    return NS_OK;
  1.2175 +}
  1.2176 +
  1.2177 +PCompositorParent*
  1.2178 +ContentParent::AllocPCompositorParent(mozilla::ipc::Transport* aTransport,
  1.2179 +                                      base::ProcessId aOtherProcess)
  1.2180 +{
  1.2181 +    return CompositorParent::Create(aTransport, aOtherProcess);
  1.2182 +}
  1.2183 +
  1.2184 +PImageBridgeParent*
  1.2185 +ContentParent::AllocPImageBridgeParent(mozilla::ipc::Transport* aTransport,
  1.2186 +                                       base::ProcessId aOtherProcess)
  1.2187 +{
  1.2188 +    return ImageBridgeParent::Create(aTransport, aOtherProcess);
  1.2189 +}
  1.2190 +
  1.2191 +PBackgroundParent*
  1.2192 +ContentParent::AllocPBackgroundParent(Transport* aTransport,
  1.2193 +                                      ProcessId aOtherProcess)
  1.2194 +{
  1.2195 +    return BackgroundParent::Alloc(this, aTransport, aOtherProcess);
  1.2196 +}
  1.2197 +
  1.2198 +bool
  1.2199 +ContentParent::RecvGetProcessAttributes(uint64_t* aId,
  1.2200 +                                        bool* aIsForApp, bool* aIsForBrowser)
  1.2201 +{
  1.2202 +    *aId = mChildID;
  1.2203 +    *aIsForApp = IsForApp();
  1.2204 +    *aIsForBrowser = mIsForBrowser;
  1.2205 +
  1.2206 +    return true;
  1.2207 +}
  1.2208 +
  1.2209 +bool
  1.2210 +ContentParent::RecvGetXPCOMProcessAttributes(bool* aIsOffline)
  1.2211 +{
  1.2212 +    nsCOMPtr<nsIIOService> io(do_GetIOService());
  1.2213 +    NS_ASSERTION(io, "No IO service?");
  1.2214 +    DebugOnly<nsresult> rv = io->GetOffline(aIsOffline);
  1.2215 +    NS_ASSERTION(NS_SUCCEEDED(rv), "Failed getting offline?");
  1.2216 +
  1.2217 +    return true;
  1.2218 +}
  1.2219 +
  1.2220 +mozilla::jsipc::PJavaScriptParent *
  1.2221 +ContentParent::AllocPJavaScriptParent()
  1.2222 +{
  1.2223 +    mozilla::jsipc::JavaScriptParent *parent = new mozilla::jsipc::JavaScriptParent();
  1.2224 +    if (!parent->init()) {
  1.2225 +        delete parent;
  1.2226 +        return nullptr;
  1.2227 +    }
  1.2228 +    return parent;
  1.2229 +}
  1.2230 +
  1.2231 +bool
  1.2232 +ContentParent::DeallocPJavaScriptParent(PJavaScriptParent *parent)
  1.2233 +{
  1.2234 +    static_cast<mozilla::jsipc::JavaScriptParent *>(parent)->decref();
  1.2235 +    return true;
  1.2236 +}
  1.2237 +
  1.2238 +PBrowserParent*
  1.2239 +ContentParent::AllocPBrowserParent(const IPCTabContext& aContext,
  1.2240 +                                   const uint32_t &aChromeFlags)
  1.2241 +{
  1.2242 +    unused << aChromeFlags;
  1.2243 +
  1.2244 +    const IPCTabAppBrowserContext& appBrowser = aContext.appBrowserContext();
  1.2245 +
  1.2246 +    // We don't trust the IPCTabContext we receive from the child, so we'll bail
  1.2247 +    // if we receive an IPCTabContext that's not a PopupIPCTabContext.
  1.2248 +    // (PopupIPCTabContext lets the child process prove that it has access to
  1.2249 +    // the app it's trying to open.)
  1.2250 +    if (appBrowser.type() != IPCTabAppBrowserContext::TPopupIPCTabContext) {
  1.2251 +        NS_ERROR("Unexpected IPCTabContext type.  Aborting AllocPBrowserParent.");
  1.2252 +        return nullptr;
  1.2253 +    }
  1.2254 +
  1.2255 +    const PopupIPCTabContext& popupContext = appBrowser.get_PopupIPCTabContext();
  1.2256 +    TabParent* opener = static_cast<TabParent*>(popupContext.openerParent());
  1.2257 +    if (!opener) {
  1.2258 +        NS_ERROR("Got null opener from child; aborting AllocPBrowserParent.");
  1.2259 +        return nullptr;
  1.2260 +    }
  1.2261 +
  1.2262 +    // Popup windows of isBrowser frames must be isBrowser if the parent
  1.2263 +    // isBrowser.  Allocating a !isBrowser frame with same app ID would allow
  1.2264 +    // the content to access data it's not supposed to.
  1.2265 +    if (!popupContext.isBrowserElement() && opener->IsBrowserElement()) {
  1.2266 +        NS_ERROR("Child trying to escalate privileges!  Aborting AllocPBrowserParent.");
  1.2267 +        return nullptr;
  1.2268 +    }
  1.2269 +
  1.2270 +    MaybeInvalidTabContext tc(aContext);
  1.2271 +    if (!tc.IsValid()) {
  1.2272 +        NS_ERROR(nsPrintfCString("Child passed us an invalid TabContext.  (%s)  "
  1.2273 +                                 "Aborting AllocPBrowserParent.",
  1.2274 +                                 tc.GetInvalidReason()).get());
  1.2275 +        return nullptr;
  1.2276 +    }
  1.2277 +
  1.2278 +    TabParent* parent = new TabParent(this, tc.GetTabContext(), aChromeFlags);
  1.2279 +
  1.2280 +    // We release this ref in DeallocPBrowserParent()
  1.2281 +    NS_ADDREF(parent);
  1.2282 +    return parent;
  1.2283 +}
  1.2284 +
  1.2285 +bool
  1.2286 +ContentParent::DeallocPBrowserParent(PBrowserParent* frame)
  1.2287 +{
  1.2288 +    TabParent* parent = static_cast<TabParent*>(frame);
  1.2289 +    NS_RELEASE(parent);
  1.2290 +    return true;
  1.2291 +}
  1.2292 +
  1.2293 +PDeviceStorageRequestParent*
  1.2294 +ContentParent::AllocPDeviceStorageRequestParent(const DeviceStorageParams& aParams)
  1.2295 +{
  1.2296 +  nsRefPtr<DeviceStorageRequestParent> result = new DeviceStorageRequestParent(aParams);
  1.2297 +  if (!result->EnsureRequiredPermissions(this)) {
  1.2298 +      return nullptr;
  1.2299 +  }
  1.2300 +  result->Dispatch();
  1.2301 +  return result.forget().take();
  1.2302 +}
  1.2303 +
  1.2304 +bool
  1.2305 +ContentParent::DeallocPDeviceStorageRequestParent(PDeviceStorageRequestParent* doomed)
  1.2306 +{
  1.2307 +  DeviceStorageRequestParent *parent = static_cast<DeviceStorageRequestParent*>(doomed);
  1.2308 +  NS_RELEASE(parent);
  1.2309 +  return true;
  1.2310 +}
  1.2311 +
  1.2312 +PFileSystemRequestParent*
  1.2313 +ContentParent::AllocPFileSystemRequestParent(const FileSystemParams& aParams)
  1.2314 +{
  1.2315 +  nsRefPtr<FileSystemRequestParent> result = new FileSystemRequestParent();
  1.2316 +  if (!result->Dispatch(this, aParams)) {
  1.2317 +    return nullptr;
  1.2318 +  }
  1.2319 +  return result.forget().take();
  1.2320 +}
  1.2321 +
  1.2322 +bool
  1.2323 +ContentParent::DeallocPFileSystemRequestParent(PFileSystemRequestParent* doomed)
  1.2324 +{
  1.2325 +  FileSystemRequestParent* parent = static_cast<FileSystemRequestParent*>(doomed);
  1.2326 +  NS_RELEASE(parent);
  1.2327 +  return true;
  1.2328 +}
  1.2329 +
  1.2330 +PBlobParent*
  1.2331 +ContentParent::AllocPBlobParent(const BlobConstructorParams& aParams)
  1.2332 +{
  1.2333 +  return BlobParent::Create(this, aParams);
  1.2334 +}
  1.2335 +
  1.2336 +bool
  1.2337 +ContentParent::DeallocPBlobParent(PBlobParent* aActor)
  1.2338 +{
  1.2339 +  delete aActor;
  1.2340 +  return true;
  1.2341 +}
  1.2342 +
  1.2343 +BlobParent*
  1.2344 +ContentParent::GetOrCreateActorForBlob(nsIDOMBlob* aBlob)
  1.2345 +{
  1.2346 +  MOZ_ASSERT(NS_IsMainThread());
  1.2347 +  MOZ_ASSERT(aBlob);
  1.2348 +
  1.2349 +  // If the blob represents a remote blob for this ContentParent then we can
  1.2350 +  // simply pass its actor back here.
  1.2351 +  if (nsCOMPtr<nsIRemoteBlob> remoteBlob = do_QueryInterface(aBlob)) {
  1.2352 +    if (BlobParent* actor = static_cast<BlobParent*>(
  1.2353 +          static_cast<PBlobParent*>(remoteBlob->GetPBlob()))) {
  1.2354 +      if (static_cast<ContentParent*>(actor->Manager()) == this) {
  1.2355 +        return actor;
  1.2356 +      }
  1.2357 +    }
  1.2358 +  }
  1.2359 +
  1.2360 +  // XXX This is only safe so long as all blob implementations in our tree
  1.2361 +  //     inherit nsDOMFileBase. If that ever changes then this will need to grow
  1.2362 +  //     a real interface or something.
  1.2363 +  const nsDOMFileBase* blob = static_cast<nsDOMFileBase*>(aBlob);
  1.2364 +
  1.2365 +  // We often pass blobs that are multipart but that only contain one sub-blob
  1.2366 +  // (WebActivities does this a bunch). Unwrap to reduce the number of actors
  1.2367 +  // that we have to maintain.
  1.2368 +  const nsTArray<nsCOMPtr<nsIDOMBlob> >* subBlobs = blob->GetSubBlobs();
  1.2369 +  if (subBlobs && subBlobs->Length() == 1) {
  1.2370 +    const nsCOMPtr<nsIDOMBlob>& subBlob = subBlobs->ElementAt(0);
  1.2371 +    MOZ_ASSERT(subBlob);
  1.2372 +
  1.2373 +    // We can only take this shortcut if the multipart and the sub-blob are both
  1.2374 +    // Blob objects or both File objects.
  1.2375 +    nsCOMPtr<nsIDOMFile> multipartBlobAsFile = do_QueryInterface(aBlob);
  1.2376 +    nsCOMPtr<nsIDOMFile> subBlobAsFile = do_QueryInterface(subBlob);
  1.2377 +    if (!multipartBlobAsFile == !subBlobAsFile) {
  1.2378 +      // The wrapping might have been unnecessary, see if we can simply pass an
  1.2379 +      // existing remote blob for this ContentParent.
  1.2380 +      if (nsCOMPtr<nsIRemoteBlob> remoteSubBlob = do_QueryInterface(subBlob)) {
  1.2381 +        BlobParent* actor =
  1.2382 +          static_cast<BlobParent*>(
  1.2383 +            static_cast<PBlobParent*>(remoteSubBlob->GetPBlob()));
  1.2384 +        MOZ_ASSERT(actor);
  1.2385 +
  1.2386 +        if (static_cast<ContentParent*>(actor->Manager()) == this) {
  1.2387 +          return actor;
  1.2388 +        }
  1.2389 +      }
  1.2390 +
  1.2391 +      // No need to add a reference here since the original blob must have a
  1.2392 +      // strong reference in the caller and it must also have a strong reference
  1.2393 +      // to this sub-blob.
  1.2394 +      aBlob = subBlob;
  1.2395 +      blob = static_cast<nsDOMFileBase*>(aBlob);
  1.2396 +      subBlobs = blob->GetSubBlobs();
  1.2397 +    }
  1.2398 +  }
  1.2399 +
  1.2400 +  // All blobs shared between processes must be immutable.
  1.2401 +  nsCOMPtr<nsIMutable> mutableBlob = do_QueryInterface(aBlob);
  1.2402 +  if (!mutableBlob || NS_FAILED(mutableBlob->SetMutable(false))) {
  1.2403 +    NS_WARNING("Failed to make blob immutable!");
  1.2404 +    return nullptr;
  1.2405 +  }
  1.2406 +
  1.2407 +  ChildBlobConstructorParams params;
  1.2408 +
  1.2409 +  if (blob->IsSizeUnknown() || blob->IsDateUnknown()) {
  1.2410 +    // We don't want to call GetSize or GetLastModifiedDate
  1.2411 +    // yet since that may stat a file on the main thread
  1.2412 +    // here. Instead we'll learn the size lazily from the
  1.2413 +    // other process.
  1.2414 +    params = MysteryBlobConstructorParams();
  1.2415 +  }
  1.2416 +  else {
  1.2417 +    nsString contentType;
  1.2418 +    nsresult rv = aBlob->GetType(contentType);
  1.2419 +    NS_ENSURE_SUCCESS(rv, nullptr);
  1.2420 +
  1.2421 +    uint64_t length;
  1.2422 +    rv = aBlob->GetSize(&length);
  1.2423 +    NS_ENSURE_SUCCESS(rv, nullptr);
  1.2424 +
  1.2425 +    nsCOMPtr<nsIDOMFile> file = do_QueryInterface(aBlob);
  1.2426 +    if (file) {
  1.2427 +      FileBlobConstructorParams fileParams;
  1.2428 +
  1.2429 +      rv = file->GetMozLastModifiedDate(&fileParams.modDate());
  1.2430 +      NS_ENSURE_SUCCESS(rv, nullptr);
  1.2431 +
  1.2432 +      rv = file->GetName(fileParams.name());
  1.2433 +      NS_ENSURE_SUCCESS(rv, nullptr);
  1.2434 +
  1.2435 +      fileParams.contentType() = contentType;
  1.2436 +      fileParams.length() = length;
  1.2437 +
  1.2438 +      params = fileParams;
  1.2439 +    } else {
  1.2440 +      NormalBlobConstructorParams blobParams;
  1.2441 +      blobParams.contentType() = contentType;
  1.2442 +      blobParams.length() = length;
  1.2443 +      params = blobParams;
  1.2444 +    }
  1.2445 +  }
  1.2446 +
  1.2447 +  BlobParent* actor = BlobParent::Create(this, aBlob);
  1.2448 +  NS_ENSURE_TRUE(actor, nullptr);
  1.2449 +
  1.2450 +  return SendPBlobConstructor(actor, params) ? actor : nullptr;
  1.2451 +}
  1.2452 +
  1.2453 +void
  1.2454 +ContentParent::KillHard()
  1.2455 +{
  1.2456 +    // On Windows, calling KillHard multiple times causes problems - the
  1.2457 +    // process handle becomes invalid on the first call, causing a second call
  1.2458 +    // to crash our process - more details in bug 890840.
  1.2459 +    if (mCalledKillHard) {
  1.2460 +        return;
  1.2461 +    }
  1.2462 +    mCalledKillHard = true;
  1.2463 +    mForceKillTask = nullptr;
  1.2464 +    // This ensures the process is eventually killed, but doesn't
  1.2465 +    // immediately KILLITWITHFIRE because we want to get a minidump if
  1.2466 +    // possible.  After a timeout though, the process is forceably
  1.2467 +    // killed.
  1.2468 +    if (!KillProcess(OtherProcess(), 1, false)) {
  1.2469 +        NS_WARNING("failed to kill subprocess!");
  1.2470 +    }
  1.2471 +    mSubprocess->SetAlreadyDead();
  1.2472 +    XRE_GetIOMessageLoop()->PostTask(
  1.2473 +        FROM_HERE,
  1.2474 +        NewRunnableFunction(&ProcessWatcher::EnsureProcessTerminated,
  1.2475 +                            OtherProcess(), /*force=*/true));
  1.2476 +    //We do clean-up here 
  1.2477 +    MessageLoop::current()->PostDelayedTask(
  1.2478 +        FROM_HERE,
  1.2479 +        NewRunnableMethod(this, &ContentParent::ShutDownProcess,
  1.2480 +                          /* closeWithError */ true),
  1.2481 +        3000);
  1.2482 +    // We've now closed the OtherProcess() handle, so must set it to null to
  1.2483 +    // prevent our dtor closing it twice.
  1.2484 +    SetOtherProcess(0);
  1.2485 +}
  1.2486 +
  1.2487 +bool
  1.2488 +ContentParent::IsPreallocated()
  1.2489 +{
  1.2490 +    return mAppManifestURL == MAGIC_PREALLOCATED_APP_MANIFEST_URL;
  1.2491 +}
  1.2492 +
  1.2493 +void
  1.2494 +ContentParent::FriendlyName(nsAString& aName)
  1.2495 +{
  1.2496 +    aName.Truncate();
  1.2497 +#ifdef MOZ_NUWA_PROCESS
  1.2498 +    if (IsNuwaProcess()) {
  1.2499 +        aName.AssignLiteral("(Nuwa)");
  1.2500 +    } else
  1.2501 +#endif
  1.2502 +    if (IsPreallocated()) {
  1.2503 +        aName.AssignLiteral("(Preallocated)");
  1.2504 +    } else if (mIsForBrowser) {
  1.2505 +        aName.AssignLiteral("Browser");
  1.2506 +    } else if (!mAppName.IsEmpty()) {
  1.2507 +        aName = mAppName;
  1.2508 +    } else if (!mAppManifestURL.IsEmpty()) {
  1.2509 +        aName.AssignLiteral("Unknown app: ");
  1.2510 +        aName.Append(mAppManifestURL);
  1.2511 +    } else {
  1.2512 +        aName.AssignLiteral("???");
  1.2513 +    }
  1.2514 +}
  1.2515 +
  1.2516 +PCrashReporterParent*
  1.2517 +ContentParent::AllocPCrashReporterParent(const NativeThreadId& tid,
  1.2518 +                                         const uint32_t& processType)
  1.2519 +{
  1.2520 +#ifdef MOZ_CRASHREPORTER
  1.2521 +  return new CrashReporterParent();
  1.2522 +#else
  1.2523 +  return nullptr;
  1.2524 +#endif
  1.2525 +}
  1.2526 +
  1.2527 +bool
  1.2528 +ContentParent::RecvPCrashReporterConstructor(PCrashReporterParent* actor,
  1.2529 +                                             const NativeThreadId& tid,
  1.2530 +                                             const uint32_t& processType)
  1.2531 +{
  1.2532 +  static_cast<CrashReporterParent*>(actor)->SetChildData(tid, processType);
  1.2533 +  return true;
  1.2534 +}
  1.2535 +
  1.2536 +bool
  1.2537 +ContentParent::DeallocPCrashReporterParent(PCrashReporterParent* crashreporter)
  1.2538 +{
  1.2539 +  delete crashreporter;
  1.2540 +  return true;
  1.2541 +}
  1.2542 +
  1.2543 +hal_sandbox::PHalParent*
  1.2544 +ContentParent::AllocPHalParent()
  1.2545 +{
  1.2546 +    return hal_sandbox::CreateHalParent();
  1.2547 +}
  1.2548 +
  1.2549 +bool
  1.2550 +ContentParent::DeallocPHalParent(hal_sandbox::PHalParent* aHal)
  1.2551 +{
  1.2552 +    delete aHal;
  1.2553 +    return true;
  1.2554 +}
  1.2555 +
  1.2556 +PIndexedDBParent*
  1.2557 +ContentParent::AllocPIndexedDBParent()
  1.2558 +{
  1.2559 +  return new IndexedDBParent(this);
  1.2560 +}
  1.2561 +
  1.2562 +bool
  1.2563 +ContentParent::DeallocPIndexedDBParent(PIndexedDBParent* aActor)
  1.2564 +{
  1.2565 +  delete aActor;
  1.2566 +  return true;
  1.2567 +}
  1.2568 +
  1.2569 +bool
  1.2570 +ContentParent::RecvPIndexedDBConstructor(PIndexedDBParent* aActor)
  1.2571 +{
  1.2572 +  nsRefPtr<IndexedDatabaseManager> mgr = IndexedDatabaseManager::GetOrCreate();
  1.2573 +  NS_ENSURE_TRUE(mgr, false);
  1.2574 +
  1.2575 +  if (!IndexedDatabaseManager::IsMainProcess()) {
  1.2576 +    NS_RUNTIMEABORT("Not supported yet!");
  1.2577 +  }
  1.2578 +
  1.2579 +  nsRefPtr<IDBFactory> factory;
  1.2580 +  nsresult rv = IDBFactory::Create(this, getter_AddRefs(factory));
  1.2581 +  NS_ENSURE_SUCCESS(rv, false);
  1.2582 +
  1.2583 +  NS_ASSERTION(factory, "This should never be null!");
  1.2584 +
  1.2585 +  IndexedDBParent* actor = static_cast<IndexedDBParent*>(aActor);
  1.2586 +  actor->mFactory = factory;
  1.2587 +  actor->mASCIIOrigin = factory->GetASCIIOrigin();
  1.2588 +
  1.2589 +  return true;
  1.2590 +}
  1.2591 +
  1.2592 +PMemoryReportRequestParent*
  1.2593 +ContentParent::AllocPMemoryReportRequestParent(const uint32_t& generation,
  1.2594 +                                               const bool &minimizeMemoryUsage,
  1.2595 +                                               const nsString &aDMDDumpIdent)
  1.2596 +{
  1.2597 +  MemoryReportRequestParent* parent = new MemoryReportRequestParent();
  1.2598 +  return parent;
  1.2599 +}
  1.2600 +
  1.2601 +bool
  1.2602 +ContentParent::DeallocPMemoryReportRequestParent(PMemoryReportRequestParent* actor)
  1.2603 +{
  1.2604 +  delete actor;
  1.2605 +  return true;
  1.2606 +}
  1.2607 +
  1.2608 +PTestShellParent*
  1.2609 +ContentParent::AllocPTestShellParent()
  1.2610 +{
  1.2611 +  return new TestShellParent();
  1.2612 +}
  1.2613 +
  1.2614 +bool
  1.2615 +ContentParent::DeallocPTestShellParent(PTestShellParent* shell)
  1.2616 +{
  1.2617 +  delete shell;
  1.2618 +  return true;
  1.2619 +}
  1.2620 +
  1.2621 +PNeckoParent*
  1.2622 +ContentParent::AllocPNeckoParent()
  1.2623 +{
  1.2624 +    return new NeckoParent();
  1.2625 +}
  1.2626 +
  1.2627 +bool
  1.2628 +ContentParent::DeallocPNeckoParent(PNeckoParent* necko)
  1.2629 +{
  1.2630 +    delete necko;
  1.2631 +    return true;
  1.2632 +}
  1.2633 +
  1.2634 +PExternalHelperAppParent*
  1.2635 +ContentParent::AllocPExternalHelperAppParent(const OptionalURIParams& uri,
  1.2636 +                                             const nsCString& aMimeContentType,
  1.2637 +                                             const nsCString& aContentDisposition,
  1.2638 +                                             const uint32_t& aContentDispositionHint,
  1.2639 +                                             const nsString& aContentDispositionFilename,
  1.2640 +                                             const bool& aForceSave,
  1.2641 +                                             const int64_t& aContentLength,
  1.2642 +                                             const OptionalURIParams& aReferrer,
  1.2643 +                                             PBrowserParent* aBrowser)
  1.2644 +{
  1.2645 +    ExternalHelperAppParent *parent = new ExternalHelperAppParent(uri, aContentLength);
  1.2646 +    parent->AddRef();
  1.2647 +    parent->Init(this, 
  1.2648 +                 aMimeContentType, 
  1.2649 +                 aContentDisposition,
  1.2650 +                 aContentDispositionHint,
  1.2651 +                 aContentDispositionFilename,
  1.2652 +                 aForceSave, 
  1.2653 +                 aReferrer, 
  1.2654 +                 aBrowser);
  1.2655 +    return parent;
  1.2656 +}
  1.2657 +
  1.2658 +bool
  1.2659 +ContentParent::DeallocPExternalHelperAppParent(PExternalHelperAppParent* aService)
  1.2660 +{
  1.2661 +    ExternalHelperAppParent *parent = static_cast<ExternalHelperAppParent *>(aService);
  1.2662 +    parent->Release();
  1.2663 +    return true;
  1.2664 +}
  1.2665 +
  1.2666 +PSmsParent*
  1.2667 +ContentParent::AllocPSmsParent()
  1.2668 +{
  1.2669 +    if (!AssertAppProcessPermission(this, "sms")) {
  1.2670 +        return nullptr;
  1.2671 +    }
  1.2672 +
  1.2673 +    SmsParent* parent = new SmsParent();
  1.2674 +    parent->AddRef();
  1.2675 +    return parent;
  1.2676 +}
  1.2677 +
  1.2678 +bool
  1.2679 +ContentParent::DeallocPSmsParent(PSmsParent* aSms)
  1.2680 +{
  1.2681 +    static_cast<SmsParent*>(aSms)->Release();
  1.2682 +    return true;
  1.2683 +}
  1.2684 +
  1.2685 +PTelephonyParent*
  1.2686 +ContentParent::AllocPTelephonyParent()
  1.2687 +{
  1.2688 +    if (!AssertAppProcessPermission(this, "telephony")) {
  1.2689 +        return nullptr;
  1.2690 +    }
  1.2691 +
  1.2692 +    TelephonyParent* actor = new TelephonyParent();
  1.2693 +    NS_ADDREF(actor);
  1.2694 +    return actor;
  1.2695 +}
  1.2696 +
  1.2697 +bool
  1.2698 +ContentParent::DeallocPTelephonyParent(PTelephonyParent* aActor)
  1.2699 +{
  1.2700 +    static_cast<TelephonyParent*>(aActor)->Release();
  1.2701 +    return true;
  1.2702 +}
  1.2703 +
  1.2704 +PStorageParent*
  1.2705 +ContentParent::AllocPStorageParent()
  1.2706 +{
  1.2707 +    return new DOMStorageDBParent();
  1.2708 +}
  1.2709 +
  1.2710 +bool
  1.2711 +ContentParent::DeallocPStorageParent(PStorageParent* aActor)
  1.2712 +{
  1.2713 +    DOMStorageDBParent* child = static_cast<DOMStorageDBParent*>(aActor);
  1.2714 +    child->ReleaseIPDLReference();
  1.2715 +    return true;
  1.2716 +}
  1.2717 +
  1.2718 +PBluetoothParent*
  1.2719 +ContentParent::AllocPBluetoothParent()
  1.2720 +{
  1.2721 +#ifdef MOZ_B2G_BT
  1.2722 +    if (!AssertAppProcessPermission(this, "bluetooth")) {
  1.2723 +        return nullptr;
  1.2724 +    }
  1.2725 +    return new mozilla::dom::bluetooth::BluetoothParent();
  1.2726 +#else
  1.2727 +    MOZ_CRASH("No support for bluetooth on this platform!");
  1.2728 +#endif
  1.2729 +}
  1.2730 +
  1.2731 +bool
  1.2732 +ContentParent::DeallocPBluetoothParent(PBluetoothParent* aActor)
  1.2733 +{
  1.2734 +#ifdef MOZ_B2G_BT
  1.2735 +    delete aActor;
  1.2736 +    return true;
  1.2737 +#else
  1.2738 +    MOZ_CRASH("No support for bluetooth on this platform!");
  1.2739 +#endif
  1.2740 +}
  1.2741 +
  1.2742 +bool
  1.2743 +ContentParent::RecvPBluetoothConstructor(PBluetoothParent* aActor)
  1.2744 +{
  1.2745 +#ifdef MOZ_B2G_BT
  1.2746 +    nsRefPtr<BluetoothService> btService = BluetoothService::Get();
  1.2747 +    NS_ENSURE_TRUE(btService, false);
  1.2748 +
  1.2749 +    return static_cast<BluetoothParent*>(aActor)->InitWithService(btService);
  1.2750 +#else
  1.2751 +    MOZ_CRASH("No support for bluetooth on this platform!");
  1.2752 +#endif
  1.2753 +}
  1.2754 +
  1.2755 +PFMRadioParent*
  1.2756 +ContentParent::AllocPFMRadioParent()
  1.2757 +{
  1.2758 +#ifdef MOZ_B2G_FM
  1.2759 +    if (!AssertAppProcessPermission(this, "fmradio")) {
  1.2760 +        return nullptr;
  1.2761 +    }
  1.2762 +    return new FMRadioParent();
  1.2763 +#else
  1.2764 +    NS_WARNING("No support for FMRadio on this platform!");
  1.2765 +    return nullptr;
  1.2766 +#endif
  1.2767 +}
  1.2768 +
  1.2769 +bool
  1.2770 +ContentParent::DeallocPFMRadioParent(PFMRadioParent* aActor)
  1.2771 +{
  1.2772 +#ifdef MOZ_B2G_FM
  1.2773 +    delete aActor;
  1.2774 +    return true;
  1.2775 +#else
  1.2776 +    NS_WARNING("No support for FMRadio on this platform!");
  1.2777 +    return false;
  1.2778 +#endif
  1.2779 +}
  1.2780 +
  1.2781 +asmjscache::PAsmJSCacheEntryParent*
  1.2782 +ContentParent::AllocPAsmJSCacheEntryParent(
  1.2783 +                                    const asmjscache::OpenMode& aOpenMode,
  1.2784 +                                    const asmjscache::WriteParams& aWriteParams,
  1.2785 +                                    const IPC::Principal& aPrincipal)
  1.2786 +{
  1.2787 +  return asmjscache::AllocEntryParent(aOpenMode, aWriteParams, aPrincipal);
  1.2788 +}
  1.2789 +
  1.2790 +bool
  1.2791 +ContentParent::DeallocPAsmJSCacheEntryParent(PAsmJSCacheEntryParent* aActor)
  1.2792 +{
  1.2793 +  asmjscache::DeallocEntryParent(aActor);
  1.2794 +  return true;
  1.2795 +}
  1.2796 +
  1.2797 +PSpeechSynthesisParent*
  1.2798 +ContentParent::AllocPSpeechSynthesisParent()
  1.2799 +{
  1.2800 +#ifdef MOZ_WEBSPEECH
  1.2801 +    return new mozilla::dom::SpeechSynthesisParent();
  1.2802 +#else
  1.2803 +    return nullptr;
  1.2804 +#endif
  1.2805 +}
  1.2806 +
  1.2807 +bool
  1.2808 +ContentParent::DeallocPSpeechSynthesisParent(PSpeechSynthesisParent* aActor)
  1.2809 +{
  1.2810 +#ifdef MOZ_WEBSPEECH
  1.2811 +    delete aActor;
  1.2812 +    return true;
  1.2813 +#else
  1.2814 +    return false;
  1.2815 +#endif
  1.2816 +}
  1.2817 +
  1.2818 +bool
  1.2819 +ContentParent::RecvPSpeechSynthesisConstructor(PSpeechSynthesisParent* aActor)
  1.2820 +{
  1.2821 +#ifdef MOZ_WEBSPEECH
  1.2822 +    return true;
  1.2823 +#else
  1.2824 +    return false;
  1.2825 +#endif
  1.2826 +}
  1.2827 +
  1.2828 +bool
  1.2829 +ContentParent::RecvSpeakerManagerGetSpeakerStatus(bool* aValue)
  1.2830 +{
  1.2831 +#ifdef MOZ_WIDGET_GONK
  1.2832 +  *aValue = false;
  1.2833 +  nsRefPtr<SpeakerManagerService> service =
  1.2834 +    SpeakerManagerService::GetSpeakerManagerService();
  1.2835 +  if (service) {
  1.2836 +    *aValue = service->GetSpeakerStatus();
  1.2837 +  }
  1.2838 +  return true;
  1.2839 +#endif
  1.2840 +  return false;
  1.2841 +}
  1.2842 +
  1.2843 +bool
  1.2844 +ContentParent::RecvSpeakerManagerForceSpeaker(const bool& aEnable)
  1.2845 +{
  1.2846 +#ifdef MOZ_WIDGET_GONK
  1.2847 +  nsRefPtr<SpeakerManagerService> service =
  1.2848 +    SpeakerManagerService::GetSpeakerManagerService();
  1.2849 +  if (service) {
  1.2850 +    service->ForceSpeaker(aEnable, mChildID);
  1.2851 +  }
  1.2852 +  return true;
  1.2853 +#endif
  1.2854 +  return false;
  1.2855 +}
  1.2856 +
  1.2857 +bool
  1.2858 +ContentParent::RecvStartVisitedQuery(const URIParams& aURI)
  1.2859 +{
  1.2860 +    nsCOMPtr<nsIURI> newURI = DeserializeURI(aURI);
  1.2861 +    if (!newURI) {
  1.2862 +        return false;
  1.2863 +    }
  1.2864 +    nsCOMPtr<IHistory> history = services::GetHistoryService();
  1.2865 +    if (history) {
  1.2866 +        history->RegisterVisitedCallback(newURI, nullptr);
  1.2867 +    }
  1.2868 +    return true;
  1.2869 +}
  1.2870 +
  1.2871 +
  1.2872 +bool
  1.2873 +ContentParent::RecvVisitURI(const URIParams& uri,
  1.2874 +                            const OptionalURIParams& referrer,
  1.2875 +                            const uint32_t& flags)
  1.2876 +{
  1.2877 +    nsCOMPtr<nsIURI> ourURI = DeserializeURI(uri);
  1.2878 +    if (!ourURI) {
  1.2879 +        return false;
  1.2880 +    }
  1.2881 +    nsCOMPtr<nsIURI> ourReferrer = DeserializeURI(referrer);
  1.2882 +    nsCOMPtr<IHistory> history = services::GetHistoryService();
  1.2883 +    if (history) {
  1.2884 +        history->VisitURI(ourURI, ourReferrer, flags);
  1.2885 +    }
  1.2886 +    return true;
  1.2887 +}
  1.2888 +
  1.2889 +
  1.2890 +bool
  1.2891 +ContentParent::RecvSetURITitle(const URIParams& uri,
  1.2892 +                               const nsString& title)
  1.2893 +{
  1.2894 +    nsCOMPtr<nsIURI> ourURI = DeserializeURI(uri);
  1.2895 +    if (!ourURI) {
  1.2896 +        return false;
  1.2897 +    }
  1.2898 +    nsCOMPtr<IHistory> history = services::GetHistoryService();
  1.2899 +    if (history) {
  1.2900 +        history->SetURITitle(ourURI, title);
  1.2901 +    }
  1.2902 +    return true;
  1.2903 +}
  1.2904 +
  1.2905 +bool
  1.2906 +ContentParent::RecvGetRandomValues(const uint32_t& length,
  1.2907 +                                   InfallibleTArray<uint8_t>* randomValues)
  1.2908 +{
  1.2909 +    uint8_t* buf = Crypto::GetRandomValues(length);
  1.2910 +    if (!buf) {
  1.2911 +        return true;
  1.2912 +    }
  1.2913 +
  1.2914 +    randomValues->SetCapacity(length);
  1.2915 +    randomValues->SetLength(length);
  1.2916 +
  1.2917 +    memcpy(randomValues->Elements(), buf, length);
  1.2918 +
  1.2919 +    NS_Free(buf);
  1.2920 +
  1.2921 +    return true;
  1.2922 +}
  1.2923 +
  1.2924 +bool
  1.2925 +ContentParent::RecvLoadURIExternal(const URIParams& uri)
  1.2926 +{
  1.2927 +    nsCOMPtr<nsIExternalProtocolService> extProtService(do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID));
  1.2928 +    if (!extProtService) {
  1.2929 +        return true;
  1.2930 +    }
  1.2931 +    nsCOMPtr<nsIURI> ourURI = DeserializeURI(uri);
  1.2932 +    if (!ourURI) {
  1.2933 +        return false;
  1.2934 +    }
  1.2935 +    extProtService->LoadURI(ourURI, nullptr);
  1.2936 +    return true;
  1.2937 +}
  1.2938 +
  1.2939 +bool
  1.2940 +ContentParent::RecvShowAlertNotification(const nsString& aImageUrl, const nsString& aTitle,
  1.2941 +                                         const nsString& aText, const bool& aTextClickable,
  1.2942 +                                         const nsString& aCookie, const nsString& aName,
  1.2943 +                                         const nsString& aBidi, const nsString& aLang,
  1.2944 +                                         const IPC::Principal& aPrincipal)
  1.2945 +{
  1.2946 +#ifdef MOZ_CHILD_PERMISSIONS
  1.2947 +    uint32_t permission = mozilla::CheckPermission(this, aPrincipal,
  1.2948 +                                                   "desktop-notification");
  1.2949 +    if (permission != nsIPermissionManager::ALLOW_ACTION) {
  1.2950 +        return true;
  1.2951 +    }
  1.2952 +#endif /* MOZ_CHILD_PERMISSIONS */
  1.2953 +
  1.2954 +    nsCOMPtr<nsIAlertsService> sysAlerts(do_GetService(NS_ALERTSERVICE_CONTRACTID));
  1.2955 +    if (sysAlerts) {
  1.2956 +        sysAlerts->ShowAlertNotification(aImageUrl, aTitle, aText, aTextClickable,
  1.2957 +                                         aCookie, this, aName, aBidi, aLang, aPrincipal);
  1.2958 +    }
  1.2959 +    return true;
  1.2960 +}
  1.2961 +
  1.2962 +bool
  1.2963 +ContentParent::RecvCloseAlert(const nsString& aName,
  1.2964 +                              const IPC::Principal& aPrincipal)
  1.2965 +{
  1.2966 +#ifdef MOZ_CHILD_PERMISSIONS
  1.2967 +    uint32_t permission = mozilla::CheckPermission(this, aPrincipal,
  1.2968 +                                                   "desktop-notification");
  1.2969 +    if (permission != nsIPermissionManager::ALLOW_ACTION) {
  1.2970 +        return true;
  1.2971 +    }
  1.2972 +#endif
  1.2973 +
  1.2974 +    nsCOMPtr<nsIAlertsService> sysAlerts(do_GetService(NS_ALERTSERVICE_CONTRACTID));
  1.2975 +    if (sysAlerts) {
  1.2976 +        sysAlerts->CloseAlert(aName, aPrincipal);
  1.2977 +    }
  1.2978 +
  1.2979 +    return true;
  1.2980 +}
  1.2981 +
  1.2982 +bool
  1.2983 +ContentParent::RecvSyncMessage(const nsString& aMsg,
  1.2984 +                               const ClonedMessageData& aData,
  1.2985 +                               const InfallibleTArray<CpowEntry>& aCpows,
  1.2986 +                               const IPC::Principal& aPrincipal,
  1.2987 +                               InfallibleTArray<nsString>* aRetvals)
  1.2988 +{
  1.2989 +  nsIPrincipal* principal = aPrincipal;
  1.2990 +  if (!Preferences::GetBool("dom.testing.ignore_ipc_principal", false) &&
  1.2991 +      principal && !AssertAppPrincipal(this, principal)) {
  1.2992 +    return false;
  1.2993 +  }
  1.2994 +
  1.2995 +  nsRefPtr<nsFrameMessageManager> ppm = mMessageManager;
  1.2996 +  if (ppm) {
  1.2997 +    StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData);
  1.2998 +    CpowIdHolder cpows(GetCPOWManager(), aCpows);
  1.2999 +
  1.3000 +    ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()),
  1.3001 +                        aMsg, true, &cloneData, &cpows, aPrincipal, aRetvals);
  1.3002 +  }
  1.3003 +  return true;
  1.3004 +}
  1.3005 +
  1.3006 +bool
  1.3007 +ContentParent::AnswerRpcMessage(const nsString& aMsg,
  1.3008 +                                const ClonedMessageData& aData,
  1.3009 +                                const InfallibleTArray<CpowEntry>& aCpows,
  1.3010 +                                const IPC::Principal& aPrincipal,
  1.3011 +                                InfallibleTArray<nsString>* aRetvals)
  1.3012 +{
  1.3013 +  nsIPrincipal* principal = aPrincipal;
  1.3014 +  if (!Preferences::GetBool("dom.testing.ignore_ipc_principal", false) &&
  1.3015 +      principal && !AssertAppPrincipal(this, principal)) {
  1.3016 +    return false;
  1.3017 +  }
  1.3018 +
  1.3019 +  nsRefPtr<nsFrameMessageManager> ppm = mMessageManager;
  1.3020 +  if (ppm) {
  1.3021 +    StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData);
  1.3022 +    CpowIdHolder cpows(GetCPOWManager(), aCpows);
  1.3023 +    ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()),
  1.3024 +                        aMsg, true, &cloneData, &cpows, aPrincipal, aRetvals);
  1.3025 +  }
  1.3026 +  return true;
  1.3027 +}
  1.3028 +
  1.3029 +bool
  1.3030 +ContentParent::RecvAsyncMessage(const nsString& aMsg,
  1.3031 +                                const ClonedMessageData& aData,
  1.3032 +                                const InfallibleTArray<CpowEntry>& aCpows,
  1.3033 +                                const IPC::Principal& aPrincipal)
  1.3034 +{
  1.3035 +  nsIPrincipal* principal = aPrincipal;
  1.3036 +  if (!Preferences::GetBool("dom.testing.ignore_ipc_principal", false) &&
  1.3037 +      principal && !AssertAppPrincipal(this, principal)) {
  1.3038 +    return false;
  1.3039 +  }
  1.3040 +
  1.3041 +  nsRefPtr<nsFrameMessageManager> ppm = mMessageManager;
  1.3042 +  if (ppm) {
  1.3043 +    StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData);
  1.3044 +    CpowIdHolder cpows(GetCPOWManager(), aCpows);
  1.3045 +    ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()),
  1.3046 +                        aMsg, false, &cloneData, &cpows, aPrincipal, nullptr);
  1.3047 +  }
  1.3048 +  return true;
  1.3049 +}
  1.3050 +
  1.3051 +bool
  1.3052 +ContentParent::RecvFilePathUpdateNotify(const nsString& aType,
  1.3053 +                                        const nsString& aStorageName,
  1.3054 +                                        const nsString& aFilePath,
  1.3055 +                                        const nsCString& aReason)
  1.3056 +{
  1.3057 +    nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(aType,
  1.3058 +                                                            aStorageName,
  1.3059 +                                                            aFilePath);
  1.3060 +
  1.3061 +    nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
  1.3062 +    if (!obs) {
  1.3063 +        return false;
  1.3064 +    }
  1.3065 +    obs->NotifyObservers(dsf, "file-watcher-update",
  1.3066 +                         NS_ConvertASCIItoUTF16(aReason).get());
  1.3067 +    return true;
  1.3068 +}
  1.3069 +
  1.3070 +static int32_t
  1.3071 +AddGeolocationListener(nsIDOMGeoPositionCallback* watcher, bool highAccuracy)
  1.3072 +{
  1.3073 +  nsCOMPtr<nsIDOMGeoGeolocation> geo = do_GetService("@mozilla.org/geolocation;1");
  1.3074 +  if (!geo) {
  1.3075 +    return -1;
  1.3076 +  }
  1.3077 +
  1.3078 +  PositionOptions* options = new PositionOptions();
  1.3079 +  options->mTimeout = 0;
  1.3080 +  options->mMaximumAge = 0;
  1.3081 +  options->mEnableHighAccuracy = highAccuracy;
  1.3082 +  int32_t retval = 1;
  1.3083 +  geo->WatchPosition(watcher, nullptr, options, &retval);
  1.3084 +  return retval;
  1.3085 +}
  1.3086 +
  1.3087 +bool
  1.3088 +ContentParent::RecvAddGeolocationListener(const IPC::Principal& aPrincipal,
  1.3089 +                                          const bool& aHighAccuracy)
  1.3090 +{
  1.3091 +#ifdef MOZ_CHILD_PERMISSIONS
  1.3092 +  if (!Preferences::GetBool("dom.testing.ignore_ipc_principal", false)) {
  1.3093 +    uint32_t permission = mozilla::CheckPermission(this, aPrincipal,
  1.3094 +                                                   "geolocation");
  1.3095 +    if (permission != nsIPermissionManager::ALLOW_ACTION) {
  1.3096 +      return true;
  1.3097 +    }
  1.3098 +  }
  1.3099 +#endif /* MOZ_CHILD_PERMISSIONS */
  1.3100 +
  1.3101 +  // To ensure no geolocation updates are skipped, we always force the
  1.3102 +  // creation of a new listener.
  1.3103 +  RecvRemoveGeolocationListener();
  1.3104 +  mGeolocationWatchID = AddGeolocationListener(this, aHighAccuracy);
  1.3105 +  return true;
  1.3106 +}
  1.3107 +
  1.3108 +bool
  1.3109 +ContentParent::RecvRemoveGeolocationListener()
  1.3110 +{
  1.3111 +  if (mGeolocationWatchID != -1) {
  1.3112 +    nsCOMPtr<nsIDOMGeoGeolocation> geo = do_GetService("@mozilla.org/geolocation;1");
  1.3113 +    if (!geo) {
  1.3114 +      return true;
  1.3115 +    }
  1.3116 +    geo->ClearWatch(mGeolocationWatchID);
  1.3117 +    mGeolocationWatchID = -1;
  1.3118 +  }
  1.3119 +  return true;
  1.3120 +}
  1.3121 +
  1.3122 +bool
  1.3123 +ContentParent::RecvSetGeolocationHigherAccuracy(const bool& aEnable)
  1.3124 +{
  1.3125 +  // This should never be called without a listener already present,
  1.3126 +  // so this check allows us to forgo securing privileges.
  1.3127 +  if (mGeolocationWatchID != -1) {
  1.3128 +    RecvRemoveGeolocationListener();
  1.3129 +    mGeolocationWatchID = AddGeolocationListener(this, aEnable);
  1.3130 +  }
  1.3131 +  return true;
  1.3132 +}
  1.3133 +
  1.3134 +NS_IMETHODIMP
  1.3135 +ContentParent::HandleEvent(nsIDOMGeoPosition* postion)
  1.3136 +{
  1.3137 +  unused << SendGeolocationUpdate(GeoPosition(postion));
  1.3138 +  return NS_OK;
  1.3139 +}
  1.3140 +
  1.3141 +nsConsoleService *
  1.3142 +ContentParent::GetConsoleService()
  1.3143 +{
  1.3144 +    if (mConsoleService) {
  1.3145 +        return mConsoleService.get();
  1.3146 +    }
  1.3147 +
  1.3148 +    // Get the ConsoleService by CID rather than ContractID, so that we
  1.3149 +    // can cast the returned pointer to an nsConsoleService (rather than
  1.3150 +    // just an nsIConsoleService). This allows us to call the non-idl function
  1.3151 +    // nsConsoleService::LogMessageWithMode.
  1.3152 +    NS_DEFINE_CID(consoleServiceCID, NS_CONSOLESERVICE_CID);
  1.3153 +    nsCOMPtr<nsConsoleService>  consoleService(do_GetService(consoleServiceCID));
  1.3154 +    mConsoleService = consoleService;
  1.3155 +    return mConsoleService.get();
  1.3156 +}
  1.3157 +
  1.3158 +bool
  1.3159 +ContentParent::RecvConsoleMessage(const nsString& aMessage)
  1.3160 +{
  1.3161 +  nsRefPtr<nsConsoleService> consoleService = GetConsoleService();
  1.3162 +  if (!consoleService) {
  1.3163 +    return true;
  1.3164 +  }
  1.3165 +  
  1.3166 +  nsRefPtr<nsConsoleMessage> msg(new nsConsoleMessage(aMessage.get()));
  1.3167 +  consoleService->LogMessageWithMode(msg, nsConsoleService::SuppressLog);
  1.3168 +  return true;
  1.3169 +}
  1.3170 +
  1.3171 +bool
  1.3172 +ContentParent::RecvScriptError(const nsString& aMessage,
  1.3173 +                                      const nsString& aSourceName,
  1.3174 +                                      const nsString& aSourceLine,
  1.3175 +                                      const uint32_t& aLineNumber,
  1.3176 +                                      const uint32_t& aColNumber,
  1.3177 +                                      const uint32_t& aFlags,
  1.3178 +                                      const nsCString& aCategory)
  1.3179 +{
  1.3180 +  nsRefPtr<nsConsoleService> consoleService = GetConsoleService();
  1.3181 +  if (!consoleService) {
  1.3182 +    return true;
  1.3183 +  }
  1.3184 +
  1.3185 +  nsCOMPtr<nsIScriptError> msg(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
  1.3186 +  nsresult rv = msg->Init(aMessage, aSourceName, aSourceLine,
  1.3187 +                          aLineNumber, aColNumber, aFlags, aCategory.get());
  1.3188 +  if (NS_FAILED(rv))
  1.3189 +    return true;
  1.3190 +
  1.3191 +  consoleService->LogMessageWithMode(msg, nsConsoleService::SuppressLog);
  1.3192 +  return true;
  1.3193 +}
  1.3194 +
  1.3195 +bool
  1.3196 +ContentParent::RecvPrivateDocShellsExist(const bool& aExist)
  1.3197 +{
  1.3198 +  if (!sPrivateContent)
  1.3199 +    sPrivateContent = new nsTArray<ContentParent*>();
  1.3200 +  if (aExist) {
  1.3201 +    sPrivateContent->AppendElement(this);
  1.3202 +  } else {
  1.3203 +    sPrivateContent->RemoveElement(this);
  1.3204 +    if (!sPrivateContent->Length()) {
  1.3205 +      nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
  1.3206 +      obs->NotifyObservers(nullptr, "last-pb-context-exited", nullptr);
  1.3207 +      delete sPrivateContent;
  1.3208 +      sPrivateContent = nullptr;
  1.3209 +    }
  1.3210 +  }
  1.3211 +  return true;
  1.3212 +}
  1.3213 +
  1.3214 +bool
  1.3215 +ContentParent::DoSendAsyncMessage(JSContext* aCx,
  1.3216 +                                  const nsAString& aMessage,
  1.3217 +                                  const mozilla::dom::StructuredCloneData& aData,
  1.3218 +                                  JS::Handle<JSObject *> aCpows,
  1.3219 +                                  nsIPrincipal* aPrincipal)
  1.3220 +{
  1.3221 +  ClonedMessageData data;
  1.3222 +  if (!BuildClonedMessageDataForParent(this, aData, data)) {
  1.3223 +    return false;
  1.3224 +  }
  1.3225 +  InfallibleTArray<CpowEntry> cpows;
  1.3226 +  if (!GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) {
  1.3227 +    return false;
  1.3228 +  }
  1.3229 +  return SendAsyncMessage(nsString(aMessage), data, cpows, aPrincipal);
  1.3230 +}
  1.3231 +
  1.3232 +bool
  1.3233 +ContentParent::CheckPermission(const nsAString& aPermission)
  1.3234 +{
  1.3235 +  return AssertAppProcessPermission(this, NS_ConvertUTF16toUTF8(aPermission).get());
  1.3236 +}
  1.3237 +
  1.3238 +bool
  1.3239 +ContentParent::CheckManifestURL(const nsAString& aManifestURL)
  1.3240 +{
  1.3241 +  return AssertAppProcessManifestURL(this, NS_ConvertUTF16toUTF8(aManifestURL).get());
  1.3242 +}
  1.3243 +
  1.3244 +bool
  1.3245 +ContentParent::CheckAppHasPermission(const nsAString& aPermission)
  1.3246 +{
  1.3247 +  return AssertAppHasPermission(this, NS_ConvertUTF16toUTF8(aPermission).get());
  1.3248 +}
  1.3249 +
  1.3250 +bool
  1.3251 +ContentParent::CheckAppHasStatus(unsigned short aStatus)
  1.3252 +{
  1.3253 +  return AssertAppHasStatus(this, aStatus);
  1.3254 +}
  1.3255 +
  1.3256 +bool
  1.3257 +ContentParent::RecvSystemMessageHandled()
  1.3258 +{
  1.3259 +    SystemMessageHandledListener::OnSystemMessageHandled();
  1.3260 +    return true;
  1.3261 +}
  1.3262 +
  1.3263 +bool
  1.3264 +ContentParent::RecvCreateFakeVolume(const nsString& fsName, const nsString& mountPoint)
  1.3265 +{
  1.3266 +#ifdef MOZ_WIDGET_GONK
  1.3267 +  nsresult rv;
  1.3268 +  nsCOMPtr<nsIVolumeService> vs = do_GetService(NS_VOLUMESERVICE_CONTRACTID, &rv);
  1.3269 +  if (vs) {
  1.3270 +    vs->CreateFakeVolume(fsName, mountPoint);
  1.3271 +  }
  1.3272 +  return true;
  1.3273 +#else
  1.3274 +  NS_WARNING("ContentParent::RecvCreateFakeVolume shouldn't be called when MOZ_WIDGET_GONK is not defined");
  1.3275 +  return false;
  1.3276 +#endif
  1.3277 +}
  1.3278 +
  1.3279 +bool
  1.3280 +ContentParent::RecvSetFakeVolumeState(const nsString& fsName, const int32_t& fsState)
  1.3281 +{
  1.3282 +#ifdef MOZ_WIDGET_GONK
  1.3283 +  nsresult rv;
  1.3284 +  nsCOMPtr<nsIVolumeService> vs = do_GetService(NS_VOLUMESERVICE_CONTRACTID, &rv);
  1.3285 +  if (vs) {
  1.3286 +    vs->SetFakeVolumeState(fsName, fsState);
  1.3287 +  }
  1.3288 +  return true;
  1.3289 +#else
  1.3290 +  NS_WARNING("ContentParent::RecvSetFakeVolumeState shouldn't be called when MOZ_WIDGET_GONK is not defined");
  1.3291 +  return false;
  1.3292 +#endif
  1.3293 +}
  1.3294 +
  1.3295 +bool
  1.3296 +ContentParent::RecvKeywordToURI(const nsCString& aKeyword, OptionalInputStreamParams* aPostData,
  1.3297 +                                OptionalURIParams* aURI)
  1.3298 +{
  1.3299 +  nsCOMPtr<nsIURIFixup> fixup = do_GetService(NS_URIFIXUP_CONTRACTID);
  1.3300 +  if (!fixup) {
  1.3301 +    return true;
  1.3302 +  }
  1.3303 +
  1.3304 +  nsCOMPtr<nsIInputStream> postData;
  1.3305 +  nsCOMPtr<nsIURI> uri;
  1.3306 +  if (NS_FAILED(fixup->KeywordToURI(aKeyword, getter_AddRefs(postData),
  1.3307 +                                    getter_AddRefs(uri)))) {
  1.3308 +    return true;
  1.3309 +  }
  1.3310 +
  1.3311 +  nsTArray<mozilla::ipc::FileDescriptor> fds;
  1.3312 +  SerializeInputStream(postData, *aPostData, fds);
  1.3313 +  MOZ_ASSERT(fds.IsEmpty());
  1.3314 +
  1.3315 +  SerializeURI(uri, *aURI);
  1.3316 +  return true;
  1.3317 +}
  1.3318 +
  1.3319 +bool
  1.3320 +ContentParent::ShouldContinueFromReplyTimeout()
  1.3321 +{
  1.3322 +  // The only time ContentParent sends blocking messages is for CPOWs, so
  1.3323 +  // timeouts should only ever occur in electrolysis-enabled sessions.
  1.3324 +  MOZ_ASSERT(BrowserTabsRemote());
  1.3325 +  return false;
  1.3326 +}
  1.3327 +
  1.3328 +bool
  1.3329 +ContentParent::ShouldSandboxContentProcesses()
  1.3330 +{
  1.3331 +#ifdef MOZ_CONTENT_SANDBOX
  1.3332 +  return !PR_GetEnv("MOZ_DISABLE_CONTENT_SANDBOX");
  1.3333 +#else
  1.3334 +  return true;
  1.3335 +#endif
  1.3336 +}
  1.3337 +
  1.3338 +bool
  1.3339 +ContentParent::RecvRecordingDeviceEvents(const nsString& aRecordingStatus,
  1.3340 +                                         const nsString& aPageURL,
  1.3341 +                                         const bool& aIsAudio,
  1.3342 +                                         const bool& aIsVideo)
  1.3343 +{
  1.3344 +    nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
  1.3345 +    if (obs) {
  1.3346 +        // recording-device-ipc-events needs to gather more information from content process
  1.3347 +        nsRefPtr<nsHashPropertyBag> props = new nsHashPropertyBag();
  1.3348 +        props->SetPropertyAsUint64(NS_LITERAL_STRING("childID"), ChildID());
  1.3349 +        props->SetPropertyAsBool(NS_LITERAL_STRING("isApp"), IsForApp());
  1.3350 +        props->SetPropertyAsBool(NS_LITERAL_STRING("isAudio"), aIsAudio);
  1.3351 +        props->SetPropertyAsBool(NS_LITERAL_STRING("isVideo"), aIsVideo);
  1.3352 +
  1.3353 +        nsString requestURL = IsForApp() ? AppManifestURL() : aPageURL;
  1.3354 +        props->SetPropertyAsAString(NS_LITERAL_STRING("requestURL"), requestURL);
  1.3355 +
  1.3356 +        obs->NotifyObservers((nsIPropertyBag2*) props,
  1.3357 +                             "recording-device-ipc-events",
  1.3358 +                             aRecordingStatus.get());
  1.3359 +    } else {
  1.3360 +        NS_WARNING("Could not get the Observer service for ContentParent::RecvRecordingDeviceEvents.");
  1.3361 +    }
  1.3362 +    return true;
  1.3363 +}
  1.3364 +
  1.3365 +bool
  1.3366 +ContentParent::RecvGetGraphicsFeatureStatus(const int32_t& aFeature,
  1.3367 +                                            int32_t* aStatus,
  1.3368 +                                            bool* aSuccess)
  1.3369 +{
  1.3370 +    nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
  1.3371 +    if (!gfxInfo) {
  1.3372 +        *aSuccess = false;
  1.3373 +        return true;
  1.3374 +    }
  1.3375 +
  1.3376 +    *aSuccess = NS_SUCCEEDED(gfxInfo->GetFeatureStatus(aFeature, aStatus));
  1.3377 +    return true;
  1.3378 +}
  1.3379 +
  1.3380 +bool
  1.3381 +ContentParent::RecvAddIdleObserver(const uint64_t& aObserver, const uint32_t& aIdleTimeInS)
  1.3382 +{
  1.3383 +  nsresult rv;
  1.3384 +  nsCOMPtr<nsIIdleService> idleService =
  1.3385 +    do_GetService("@mozilla.org/widget/idleservice;1", &rv);
  1.3386 +  NS_ENSURE_SUCCESS(rv, false);
  1.3387 +
  1.3388 +  nsRefPtr<ParentIdleListener> listener = new ParentIdleListener(this, aObserver);
  1.3389 +  mIdleListeners.Put(aObserver, listener);
  1.3390 +  idleService->AddIdleObserver(listener, aIdleTimeInS);
  1.3391 +  return true;
  1.3392 +}
  1.3393 +
  1.3394 +bool
  1.3395 +ContentParent::RecvRemoveIdleObserver(const uint64_t& aObserver, const uint32_t& aIdleTimeInS)
  1.3396 +{
  1.3397 +  nsresult rv;
  1.3398 +  nsCOMPtr<nsIIdleService> idleService =
  1.3399 +    do_GetService("@mozilla.org/widget/idleservice;1", &rv);
  1.3400 +  NS_ENSURE_SUCCESS(rv, false);
  1.3401 +
  1.3402 +  nsRefPtr<ParentIdleListener> listener;
  1.3403 +  bool found = mIdleListeners.Get(aObserver, &listener);
  1.3404 +  if (found) {
  1.3405 +    mIdleListeners.Remove(aObserver);
  1.3406 +    idleService->RemoveIdleObserver(listener, aIdleTimeInS);
  1.3407 +  }
  1.3408 +
  1.3409 +  return true;
  1.3410 +}
  1.3411 +
  1.3412 +bool
  1.3413 +ContentParent::RecvBackUpXResources(const FileDescriptor& aXSocketFd)
  1.3414 +{
  1.3415 +#ifndef MOZ_X11
  1.3416 +    NS_RUNTIMEABORT("This message only makes sense on X11 platforms");
  1.3417 +#else
  1.3418 +    NS_ABORT_IF_FALSE(0 > mChildXSocketFdDup.get(),
  1.3419 +                      "Already backed up X resources??");
  1.3420 +    mChildXSocketFdDup.forget();
  1.3421 +    if (aXSocketFd.IsValid()) {
  1.3422 +      mChildXSocketFdDup.reset(aXSocketFd.PlatformHandle());
  1.3423 +    }
  1.3424 +#endif
  1.3425 +    return true;
  1.3426 +}
  1.3427 +
  1.3428 +PFileDescriptorSetParent*
  1.3429 +ContentParent::AllocPFileDescriptorSetParent(const FileDescriptor& aFD)
  1.3430 +{
  1.3431 +    return new FileDescriptorSetParent(aFD);
  1.3432 +}
  1.3433 +
  1.3434 +bool
  1.3435 +ContentParent::DeallocPFileDescriptorSetParent(PFileDescriptorSetParent* aActor)
  1.3436 +{
  1.3437 +    delete static_cast<FileDescriptorSetParent*>(aActor);
  1.3438 +    return true;
  1.3439 +}
  1.3440 +
  1.3441 +} // namespace dom
  1.3442 +} // namespace mozilla
  1.3443 +
  1.3444 +NS_IMPL_ISUPPORTS(ParentIdleListener, nsIObserver)
  1.3445 +
  1.3446 +NS_IMETHODIMP
  1.3447 +ParentIdleListener::Observe(nsISupports*, const char* aTopic, const char16_t* aData) {
  1.3448 +  mozilla::unused << mParent->SendNotifyIdleObserver(mObserver,
  1.3449 +                                                     nsDependentCString(aTopic),
  1.3450 +                                                     nsDependentString(aData));
  1.3451 +  return NS_OK;
  1.3452 +}

mercurial