dom/ipc/ContentParent.cpp

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

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

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

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     2 /* vim: set sw=4 ts=8 et tw=80 : */
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #include "mozilla/DebugOnly.h"
     9 #include "base/basictypes.h"
    11 #include "ContentParent.h"
    13 #if defined(ANDROID) || defined(LINUX)
    14 # include <sys/time.h>
    15 # include <sys/resource.h>
    16 #endif
    18 #ifdef MOZ_WIDGET_GONK
    19 #include <sys/types.h>
    20 #include <sys/wait.h>
    21 #endif
    23 #include "chrome/common/process_watcher.h"
    25 #include "AppProcessChecker.h"
    26 #include "AudioChannelService.h"
    27 #include "CrashReporterParent.h"
    28 #include "IHistory.h"
    29 #include "IDBFactory.h"
    30 #include "IndexedDBParent.h"
    31 #include "IndexedDatabaseManager.h"
    32 #include "mozIApplication.h"
    33 #include "mozilla/ClearOnShutdown.h"
    34 #include "mozilla/dom/asmjscache/AsmJSCache.h"
    35 #include "mozilla/dom/Element.h"
    36 #include "mozilla/dom/ExternalHelperAppParent.h"
    37 #include "mozilla/dom/PFileDescriptorSetParent.h"
    38 #include "mozilla/dom/PMemoryReportRequestParent.h"
    39 #include "mozilla/dom/power/PowerManagerService.h"
    40 #include "mozilla/dom/DOMStorageIPC.h"
    41 #include "mozilla/dom/bluetooth/PBluetoothParent.h"
    42 #include "mozilla/dom/PFMRadioParent.h"
    43 #include "mozilla/dom/devicestorage/DeviceStorageRequestParent.h"
    44 #include "mozilla/dom/FileSystemRequestParent.h"
    45 #include "mozilla/dom/GeolocationBinding.h"
    46 #include "mozilla/dom/FileDescriptorSetParent.h"
    47 #include "mozilla/dom/telephony/TelephonyParent.h"
    48 #include "mozilla/dom/time/DateCacheCleaner.h"
    49 #include "SmsParent.h"
    50 #include "mozilla/hal_sandbox/PHalParent.h"
    51 #include "mozilla/ipc/BackgroundChild.h"
    52 #include "mozilla/ipc/BackgroundParent.h"
    53 #include "mozilla/ipc/TestShellParent.h"
    54 #include "mozilla/ipc/InputStreamUtils.h"
    55 #include "mozilla/layers/CompositorParent.h"
    56 #include "mozilla/layers/ImageBridgeParent.h"
    57 #include "mozilla/net/NeckoParent.h"
    58 #include "mozilla/Preferences.h"
    59 #include "mozilla/Services.h"
    60 #include "mozilla/StaticPtr.h"
    61 #include "mozilla/unused.h"
    62 #include "nsAppRunner.h"
    63 #include "nsAutoPtr.h"
    64 #include "nsCDefaultURIFixup.h"
    65 #include "nsCExternalHandlerService.h"
    66 #include "nsCOMPtr.h"
    67 #include "nsChromeRegistryChrome.h"
    68 #include "nsConsoleMessage.h"
    69 #include "nsConsoleService.h"
    70 #include "nsDebugImpl.h"
    71 #include "nsDOMFile.h"
    72 #include "nsFrameMessageManager.h"
    73 #include "nsHashPropertyBag.h"
    74 #include "nsIAlertsService.h"
    75 #include "nsIAppsService.h"
    76 #include "nsIClipboard.h"
    77 #include "nsIDOMGeoGeolocation.h"
    78 #include "mozilla/dom/WakeLock.h"
    79 #include "nsIDOMWindow.h"
    80 #include "nsIExternalProtocolService.h"
    81 #include "nsIGfxInfo.h"
    82 #include "nsIIdleService.h"
    83 #include "nsIMemoryReporter.h"
    84 #include "nsIMozBrowserFrame.h"
    85 #include "nsIMutable.h"
    86 #include "nsIObserverService.h"
    87 #include "nsIPresShell.h"
    88 #include "nsIRemoteBlob.h"
    89 #include "nsIScriptError.h"
    90 #include "nsIStyleSheet.h"
    91 #include "nsISupportsPrimitives.h"
    92 #include "nsIURIFixup.h"
    93 #include "nsIWindowWatcher.h"
    94 #include "nsIXULRuntime.h"
    95 #include "nsMemoryReporterManager.h"
    96 #include "nsServiceManagerUtils.h"
    97 #include "nsStyleSheetService.h"
    98 #include "nsThreadUtils.h"
    99 #include "nsToolkitCompsCID.h"
   100 #include "nsWidgetsCID.h"
   101 #include "PreallocatedProcessManager.h"
   102 #include "ProcessPriorityManager.h"
   103 #include "SandboxHal.h"
   104 #include "StructuredCloneUtils.h"
   105 #include "TabParent.h"
   106 #include "URIUtils.h"
   107 #include "nsIWebBrowserChrome.h"
   108 #include "nsIDocShell.h"
   109 #include "mozilla/net/NeckoMessageUtils.h"
   110 #include "gfxPrefs.h"
   112 #if defined(ANDROID) || defined(LINUX)
   113 #include "nsSystemInfo.h"
   114 #endif
   116 #ifdef ANDROID
   117 # include "gfxAndroidPlatform.h"
   118 #endif
   120 #ifdef MOZ_PERMISSIONS
   121 # include "nsPermissionManager.h"
   122 #endif
   124 #ifdef MOZ_WIDGET_ANDROID
   125 # include "AndroidBridge.h"
   126 #endif
   128 #ifdef MOZ_WIDGET_GONK
   129 #include "nsIVolume.h"
   130 #include "nsIVolumeService.h"
   131 #include "SpeakerManagerService.h"
   132 using namespace mozilla::system;
   133 #endif
   135 #ifdef MOZ_B2G_BT
   136 #include "BluetoothParent.h"
   137 #include "BluetoothService.h"
   138 #endif
   140 #include "JavaScriptParent.h"
   142 #ifdef MOZ_B2G_FM
   143 #include "mozilla/dom/FMRadioParent.h"
   144 #endif
   146 #include "Crypto.h"
   148 #ifdef MOZ_WEBSPEECH
   149 #include "mozilla/dom/SpeechSynthesisParent.h"
   150 #endif
   152 #ifdef ENABLE_TESTS
   153 #include "BackgroundChildImpl.h"
   154 #include "mozilla/ipc/PBackgroundChild.h"
   155 #include "nsIIPCBackgroundChildCreateCallback.h"
   156 #endif
   158 static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID);
   159 static const char* sClipboardTextFlavors[] = { kUnicodeMime };
   161 using base::ChildPrivileges;
   162 using base::KillProcess;
   163 using namespace mozilla::dom::bluetooth;
   164 using namespace mozilla::dom::devicestorage;
   165 using namespace mozilla::dom::indexedDB;
   166 using namespace mozilla::dom::power;
   167 using namespace mozilla::dom::mobilemessage;
   168 using namespace mozilla::dom::telephony;
   169 using namespace mozilla::hal;
   170 using namespace mozilla::ipc;
   171 using namespace mozilla::layers;
   172 using namespace mozilla::net;
   173 using namespace mozilla::jsipc;
   175 #ifdef ENABLE_TESTS
   177 class BackgroundTester MOZ_FINAL : public nsIIPCBackgroundChildCreateCallback,
   178                                    public nsIObserver
   179 {
   180     static uint32_t sCallbackCount;
   182 private:
   183     ~BackgroundTester()
   184     { }
   186     virtual void
   187     ActorCreated(PBackgroundChild* aActor) MOZ_OVERRIDE
   188     {
   189         MOZ_RELEASE_ASSERT(aActor,
   190                            "Failed to create a PBackgroundChild actor!");
   192         NS_NAMED_LITERAL_CSTRING(testStr, "0123456789");
   194         PBackgroundTestChild* testActor =
   195             aActor->SendPBackgroundTestConstructor(testStr);
   196         MOZ_RELEASE_ASSERT(testActor);
   198         if (!sCallbackCount) {
   199             PBackgroundChild* existingBackgroundChild =
   200                 BackgroundChild::GetForCurrentThread();
   202             MOZ_RELEASE_ASSERT(existingBackgroundChild);
   203             MOZ_RELEASE_ASSERT(existingBackgroundChild == aActor);
   205             bool ok =
   206                 existingBackgroundChild->
   207                     SendPBackgroundTestConstructor(testStr);
   208             MOZ_RELEASE_ASSERT(ok);
   210             // Callback 3.
   211             ok = BackgroundChild::GetOrCreateForCurrentThread(this);
   212             MOZ_RELEASE_ASSERT(ok);
   213         }
   215         sCallbackCount++;
   216     }
   218     virtual void
   219     ActorFailed() MOZ_OVERRIDE
   220     {
   221         MOZ_CRASH("Failed to create a PBackgroundChild actor!");
   222     }
   224     NS_IMETHOD
   225     Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData)
   226             MOZ_OVERRIDE
   227     {
   228         nsCOMPtr<nsIObserverService> observerService =
   229             mozilla::services::GetObserverService();
   230         MOZ_RELEASE_ASSERT(observerService);
   232         nsresult rv = observerService->RemoveObserver(this, aTopic);
   233         MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
   235         if (!strcmp(aTopic, "profile-after-change")) {
   236             if (mozilla::Preferences::GetBool("pbackground.testing", false)) {
   237                 rv = observerService->AddObserver(this, "xpcom-shutdown",
   238                                                   false);
   239                 MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
   241                 // Callback 1.
   242                 bool ok = BackgroundChild::GetOrCreateForCurrentThread(this);
   243                 MOZ_RELEASE_ASSERT(ok);
   245                 BackgroundChildImpl::ThreadLocal* threadLocal =
   246                   BackgroundChildImpl::GetThreadLocalForCurrentThread();
   247                 MOZ_RELEASE_ASSERT(threadLocal);
   249                 // Callback 2.
   250                 ok = BackgroundChild::GetOrCreateForCurrentThread(this);
   251                 MOZ_RELEASE_ASSERT(ok);
   252             }
   254             return NS_OK;
   255         }
   257         if (!strcmp(aTopic, "xpcom-shutdown")) {
   258             MOZ_RELEASE_ASSERT(sCallbackCount == 3);
   260             return NS_OK;
   261         }
   263         MOZ_CRASH("Unknown observer topic!");
   264     }
   266 public:
   267     NS_DECL_ISUPPORTS
   268 };
   270 uint32_t BackgroundTester::sCallbackCount = 0;
   272 NS_IMPL_ISUPPORTS(BackgroundTester, nsIIPCBackgroundChildCreateCallback,
   273                   nsIObserver)
   275 #endif // ENABLE_TESTS
   277 void
   278 MaybeTestPBackground()
   279 {
   280 #ifdef ENABLE_TESTS
   281     // This test relies on running the event loop and XPCShell does not always
   282     // do so. Bail out here if we detect that we're running in XPCShell.
   283     if (PR_GetEnv("XPCSHELL_TEST_PROFILE_DIR")) {
   284         return;
   285     }
   287     // This is called too early at startup to test preferences directly. We have
   288     // to install an observer to be notified when preferences are available.
   289     nsCOMPtr<nsIObserverService> observerService =
   290         mozilla::services::GetObserverService();
   291     MOZ_RELEASE_ASSERT(observerService);
   293     nsCOMPtr<nsIObserver> observer = new BackgroundTester();
   294     nsresult rv = observerService->AddObserver(observer, "profile-after-change",
   295                                                false);
   296     MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
   297 #endif
   298 }
   300 namespace mozilla {
   301 namespace dom {
   303 #define NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC "ipc:network:set-offline"
   305 class MemoryReportRequestParent : public PMemoryReportRequestParent
   306 {
   307 public:
   308     MemoryReportRequestParent();
   309     virtual ~MemoryReportRequestParent();
   311     virtual bool Recv__delete__(const uint32_t& generation, const InfallibleTArray<MemoryReport>& report);
   312 private:
   313     ContentParent* Owner()
   314     {
   315         return static_cast<ContentParent*>(Manager());
   316     }
   317 };
   319 MemoryReportRequestParent::MemoryReportRequestParent()
   320 {
   321     MOZ_COUNT_CTOR(MemoryReportRequestParent);
   322 }
   324 bool
   325 MemoryReportRequestParent::Recv__delete__(const uint32_t& generation, const InfallibleTArray<MemoryReport>& childReports)
   326 {
   327     nsRefPtr<nsMemoryReporterManager> mgr =
   328         nsMemoryReporterManager::GetOrCreate();
   329     if (mgr) {
   330         mgr->HandleChildReports(generation, childReports);
   331     }
   332     return true;
   333 }
   335 MemoryReportRequestParent::~MemoryReportRequestParent()
   336 {
   337     MOZ_COUNT_DTOR(MemoryReportRequestParent);
   338 }
   340 // A memory reporter for ContentParent objects themselves.
   341 class ContentParentsMemoryReporter MOZ_FINAL : public nsIMemoryReporter
   342 {
   343 public:
   344     NS_DECL_ISUPPORTS
   345     NS_DECL_NSIMEMORYREPORTER
   346 };
   348 NS_IMPL_ISUPPORTS(ContentParentsMemoryReporter, nsIMemoryReporter)
   350 NS_IMETHODIMP
   351 ContentParentsMemoryReporter::CollectReports(nsIMemoryReporterCallback* cb,
   352                                              nsISupports* aClosure)
   353 {
   354     nsAutoTArray<ContentParent*, 16> cps;
   355     ContentParent::GetAllEvenIfDead(cps);
   357     for (uint32_t i = 0; i < cps.Length(); i++) {
   358         ContentParent* cp = cps[i];
   359         MessageChannel* channel = cp->GetIPCChannel();
   361         nsString friendlyName;
   362         cp->FriendlyName(friendlyName);
   364         cp->AddRef();
   365         nsrefcnt refcnt = cp->Release();
   367         const char* channelStr = "no channel";
   368         uint32_t numQueuedMessages = 0;
   369         if (channel) {
   370             if (channel->Unsound_IsClosed()) {
   371                 channelStr = "closed channel";
   372             } else {
   373                 channelStr = "open channel";
   374             }
   375             numQueuedMessages = channel->Unsound_NumQueuedMessages();
   376         }
   378         nsPrintfCString path("queued-ipc-messages/content-parent"
   379                              "(%s, pid=%d, %s, 0x%p, refcnt=%d)",
   380                              NS_ConvertUTF16toUTF8(friendlyName).get(),
   381                              cp->Pid(), channelStr, cp, refcnt);
   383         NS_NAMED_LITERAL_CSTRING(desc,
   384             "The number of unset IPC messages held in this ContentParent's "
   385             "channel.  A large value here might indicate that we're leaking "
   386             "messages.  Similarly, a ContentParent object for a process that's no "
   387             "longer running could indicate that we're leaking ContentParents.");
   389         nsresult rv = cb->Callback(/* process */ EmptyCString(),
   390                                    path,
   391                                    KIND_OTHER,
   392                                    UNITS_COUNT,
   393                                    numQueuedMessages,
   394                                    desc,
   395                                    aClosure);
   397         NS_ENSURE_SUCCESS(rv, rv);
   398     }
   400     return NS_OK;
   401 }
   403 nsDataHashtable<nsStringHashKey, ContentParent*>* ContentParent::sAppContentParents;
   404 nsTArray<ContentParent*>* ContentParent::sNonAppContentParents;
   405 nsTArray<ContentParent*>* ContentParent::sPrivateContent;
   406 StaticAutoPtr<LinkedList<ContentParent> > ContentParent::sContentParents;
   408 // This is true when subprocess launching is enabled.  This is the
   409 // case between StartUp() and ShutDown() or JoinAllSubprocesses().
   410 static bool sCanLaunchSubprocesses;
   412 // The first content child has ID 1, so the chrome process can have ID 0.
   413 static uint64_t gContentChildID = 1;
   415 // We want the prelaunched process to know that it's for apps, but not
   416 // actually for any app in particular.  Use a magic manifest URL.
   417 // Can't be a static constant.
   418 #define MAGIC_PREALLOCATED_APP_MANIFEST_URL NS_LITERAL_STRING("{{template}}")
   420 static const char* sObserverTopics[] = {
   421     "xpcom-shutdown",
   422     NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC,
   423     "child-memory-reporter-request",
   424     "memory-pressure",
   425     "child-gc-request",
   426     "child-cc-request",
   427     "child-mmu-request",
   428     "last-pb-context-exited",
   429     "file-watcher-update",
   430 #ifdef MOZ_WIDGET_GONK
   431     NS_VOLUME_STATE_CHANGED,
   432     "phone-state-changed",
   433 #endif
   434 #ifdef ACCESSIBILITY
   435     "a11y-init-or-shutdown",
   436 #endif
   437 };
   439 /* static */ already_AddRefed<ContentParent>
   440 ContentParent::RunNuwaProcess()
   441 {
   442     MOZ_ASSERT(NS_IsMainThread());
   443     nsRefPtr<ContentParent> nuwaProcess =
   444         new ContentParent(/* aApp = */ nullptr,
   445                           /* aIsForBrowser = */ false,
   446                           /* aIsForPreallocated = */ true,
   447                           PROCESS_PRIORITY_BACKGROUND,
   448                           /* aIsNuwaProcess = */ true);
   449     nuwaProcess->Init();
   450     return nuwaProcess.forget();
   451 }
   453 // PreallocateAppProcess is called by the PreallocatedProcessManager.
   454 // ContentParent then takes this process back within
   455 // MaybeTakePreallocatedAppProcess.
   456 /*static*/ already_AddRefed<ContentParent>
   457 ContentParent::PreallocateAppProcess()
   458 {
   459     nsRefPtr<ContentParent> process =
   460         new ContentParent(/* app = */ nullptr,
   461                           /* isForBrowserElement = */ false,
   462                           /* isForPreallocated = */ true,
   463                           PROCESS_PRIORITY_PREALLOC);
   464     process->Init();
   465     return process.forget();
   466 }
   468 /*static*/ already_AddRefed<ContentParent>
   469 ContentParent::MaybeTakePreallocatedAppProcess(const nsAString& aAppManifestURL,
   470                                                ProcessPriority aInitialPriority)
   471 {
   472     nsRefPtr<ContentParent> process = PreallocatedProcessManager::Take();
   473     if (!process) {
   474         return nullptr;
   475     }
   477     if (!process->SetPriorityAndCheckIsAlive(aInitialPriority)) {
   478         // Kill the process just in case it's not actually dead; we don't want
   479         // to "leak" this process!
   480         process->KillHard();
   481         return nullptr;
   482     }
   483     process->TransformPreallocatedIntoApp(aAppManifestURL);
   485     return process.forget();
   486 }
   488 /*static*/ void
   489 ContentParent::StartUp()
   490 {
   491     if (XRE_GetProcessType() != GeckoProcessType_Default) {
   492         return;
   493     }
   495     // Note: This reporter measures all ContentParents.
   496     RegisterStrongMemoryReporter(new ContentParentsMemoryReporter());
   498     mozilla::dom::time::InitializeDateCacheCleaner();
   500     BackgroundChild::Startup();
   502     sCanLaunchSubprocesses = true;
   504     // Try to preallocate a process that we can transform into an app later.
   505     PreallocatedProcessManager::AllocateAfterDelay();
   507     // Test the PBackground infrastructure on ENABLE_TESTS builds when a special
   508     // testing preference is set.
   509     MaybeTestPBackground();
   510 }
   512 /*static*/ void
   513 ContentParent::ShutDown()
   514 {
   515     // No-op for now.  We rely on normal process shutdown and
   516     // ClearOnShutdown() to clean up our state.
   517     sCanLaunchSubprocesses = false;
   518 }
   520 /*static*/ void
   521 ContentParent::JoinProcessesIOThread(const nsTArray<ContentParent*>* aProcesses,
   522                                      Monitor* aMonitor, bool* aDone)
   523 {
   524     const nsTArray<ContentParent*>& processes = *aProcesses;
   525     for (uint32_t i = 0; i < processes.Length(); ++i) {
   526         if (GeckoChildProcessHost* process = processes[i]->mSubprocess) {
   527             process->Join();
   528         }
   529     }
   530     {
   531         MonitorAutoLock lock(*aMonitor);
   532         *aDone = true;
   533         lock.Notify();
   534     }
   535     // Don't touch any arguments to this function from now on.
   536 }
   538 /*static*/ void
   539 ContentParent::JoinAllSubprocesses()
   540 {
   541     MOZ_ASSERT(NS_IsMainThread());
   543     nsAutoTArray<ContentParent*, 8> processes;
   544     GetAll(processes);
   545     if (processes.IsEmpty()) {
   546         printf_stderr("There are no live subprocesses.");
   547         return;
   548     }
   550     printf_stderr("Subprocesses are still alive.  Doing emergency join.\n");
   552     bool done = false;
   553     Monitor monitor("mozilla.dom.ContentParent.JoinAllSubprocesses");
   554     XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
   555                                      NewRunnableFunction(
   556                                          &ContentParent::JoinProcessesIOThread,
   557                                          &processes, &monitor, &done));
   558     {
   559         MonitorAutoLock lock(monitor);
   560         while (!done) {
   561             lock.Wait();
   562         }
   563     }
   565     sCanLaunchSubprocesses = false;
   566 }
   568 /*static*/ already_AddRefed<ContentParent>
   569 ContentParent::GetNewOrUsed(bool aForBrowserElement)
   570 {
   571     if (!sNonAppContentParents)
   572         sNonAppContentParents = new nsTArray<ContentParent*>();
   574     int32_t maxContentProcesses = Preferences::GetInt("dom.ipc.processCount", 1);
   575     if (maxContentProcesses < 1)
   576         maxContentProcesses = 1;
   578     if (sNonAppContentParents->Length() >= uint32_t(maxContentProcesses)) {
   579         uint32_t idx = rand() % sNonAppContentParents->Length();
   580         nsRefPtr<ContentParent> p = (*sNonAppContentParents)[idx];
   581         NS_ASSERTION(p->IsAlive(), "Non-alive contentparent in sNonAppContentParents?");
   582         return p.forget();
   583     }
   585     // Try to take and transform the preallocated process into browser.
   586     nsRefPtr<ContentParent> p = PreallocatedProcessManager::Take();
   587     if (p) {
   588         p->TransformPreallocatedIntoBrowser();
   589     } else {
   590       // Failed in using the preallocated process: fork from the chrome process.
   591 #ifdef MOZ_NUWA_PROCESS
   592         if (Preferences::GetBool("dom.ipc.processPrelaunch.enabled", false)) {
   593             // Wait until the Nuwa process forks a new process.
   594             return nullptr;
   595         }
   596 #endif
   597         p = new ContentParent(/* app = */ nullptr,
   598                               aForBrowserElement,
   599                               /* isForPreallocated = */ false,
   600                               PROCESS_PRIORITY_FOREGROUND);
   601     }
   603     p->Init();
   604     sNonAppContentParents->AppendElement(p);
   605     return p.forget();
   606 }
   608 /*static*/ ProcessPriority
   609 ContentParent::GetInitialProcessPriority(Element* aFrameElement)
   610 {
   611     // Frames with mozapptype == critical which are expecting a system message
   612     // get FOREGROUND_HIGH priority.
   614     if (!aFrameElement) {
   615         return PROCESS_PRIORITY_FOREGROUND;
   616     }
   618     if (aFrameElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::mozapptype,
   619                                    NS_LITERAL_STRING("keyboard"), eCaseMatters)) {
   620         return PROCESS_PRIORITY_FOREGROUND_KEYBOARD;
   621     } else if (!aFrameElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::mozapptype,
   622                                            NS_LITERAL_STRING("critical"), eCaseMatters)) {
   623         return PROCESS_PRIORITY_FOREGROUND;
   624     }
   626     nsCOMPtr<nsIMozBrowserFrame> browserFrame =
   627         do_QueryInterface(aFrameElement);
   628     if (!browserFrame) {
   629         return PROCESS_PRIORITY_FOREGROUND;
   630     }
   632     return browserFrame->GetIsExpectingSystemMessage() ?
   633                PROCESS_PRIORITY_FOREGROUND_HIGH :
   634                PROCESS_PRIORITY_FOREGROUND;
   635 }
   637 bool
   638 ContentParent::PreallocatedProcessReady()
   639 {
   640 #ifdef MOZ_NUWA_PROCESS
   641     return PreallocatedProcessManager::PreallocatedProcessReady();
   642 #else
   643     return true;
   644 #endif
   645 }
   647 void
   648 ContentParent::RunAfterPreallocatedProcessReady(nsIRunnable* aRequest)
   649 {
   650 #ifdef MOZ_NUWA_PROCESS
   651     PreallocatedProcessManager::RunAfterPreallocatedProcessReady(aRequest);
   652 #endif
   653 }
   655 /*static*/ TabParent*
   656 ContentParent::CreateBrowserOrApp(const TabContext& aContext,
   657                                   Element* aFrameElement)
   658 {
   659     if (!sCanLaunchSubprocesses) {
   660         return nullptr;
   661     }
   663     if (aContext.IsBrowserElement() || !aContext.HasOwnApp()) {
   664         if (nsRefPtr<ContentParent> cp = GetNewOrUsed(aContext.IsBrowserElement())) {
   665             uint32_t chromeFlags = 0;
   667             // Propagate the private-browsing status of the element's parent
   668             // docshell to the remote docshell, via the chrome flags.
   669             nsCOMPtr<Element> frameElement = do_QueryInterface(aFrameElement);
   670             MOZ_ASSERT(frameElement);
   671             nsIDocShell* docShell =
   672                 frameElement->OwnerDoc()->GetWindow()->GetDocShell();
   673             MOZ_ASSERT(docShell);
   674             nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(docShell);
   675             if (loadContext && loadContext->UsePrivateBrowsing()) {
   676                 chromeFlags |= nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW;
   677             }
   678             bool affectLifetime;
   679             docShell->GetAffectPrivateSessionLifetime(&affectLifetime);
   680             if (affectLifetime) {
   681                 chromeFlags |= nsIWebBrowserChrome::CHROME_PRIVATE_LIFETIME;
   682             }
   684             nsRefPtr<TabParent> tp(new TabParent(cp, aContext, chromeFlags));
   685             tp->SetOwnerElement(aFrameElement);
   687             PBrowserParent* browser = cp->SendPBrowserConstructor(
   688                 // DeallocPBrowserParent() releases this ref.
   689                 tp.forget().take(),
   690                 aContext.AsIPCTabContext(),
   691                 chromeFlags);
   692             return static_cast<TabParent*>(browser);
   693         }
   694         return nullptr;
   695     }
   697     // If we got here, we have an app and we're not a browser element.  ownApp
   698     // shouldn't be null, because we otherwise would have gone into the
   699     // !HasOwnApp() branch above.
   700     nsCOMPtr<mozIApplication> ownApp = aContext.GetOwnApp();
   702     if (!sAppContentParents) {
   703         sAppContentParents =
   704             new nsDataHashtable<nsStringHashKey, ContentParent*>();
   705     }
   707     // Each app gets its own ContentParent instance unless it shares it with
   708     // a parent app.
   709     nsAutoString manifestURL;
   710     if (NS_FAILED(ownApp->GetManifestURL(manifestURL))) {
   711         NS_ERROR("Failed to get manifest URL");
   712         return nullptr;
   713     }
   715     ProcessPriority initialPriority = GetInitialProcessPriority(aFrameElement);
   716     nsRefPtr<ContentParent> p = sAppContentParents->Get(manifestURL);
   718     if (!p && Preferences::GetBool("dom.ipc.reuse_parent_app")) {
   719         nsAutoString parentAppURL;
   720         aFrameElement->GetAttr(kNameSpaceID_None,
   721                                nsGkAtoms::parentapp, parentAppURL);
   722         nsAdoptingString systemAppURL =
   723             Preferences::GetString("browser.homescreenURL");
   724         nsCOMPtr<nsIAppsService> appsService =
   725             do_GetService(APPS_SERVICE_CONTRACTID);
   726         if (!parentAppURL.IsEmpty() &&
   727             !parentAppURL.Equals(systemAppURL) &&
   728             appsService) {
   729             nsCOMPtr<mozIApplication> parentApp;
   730             nsCOMPtr<mozIApplication> app;
   731             appsService->GetAppByManifestURL(parentAppURL,
   732                                              getter_AddRefs(parentApp));
   733             appsService->GetAppByManifestURL(manifestURL,
   734                                              getter_AddRefs(app));
   736             // Only let certified apps re-use the same process.
   737             unsigned short parentAppStatus = 0;
   738             unsigned short appStatus = 0;
   739             if (app &&
   740                 NS_SUCCEEDED(app->GetAppStatus(&appStatus)) &&
   741                 appStatus == nsIPrincipal::APP_STATUS_CERTIFIED &&
   742                 parentApp &&
   743                 NS_SUCCEEDED(parentApp->GetAppStatus(&parentAppStatus)) &&
   744                 parentAppStatus == nsIPrincipal::APP_STATUS_CERTIFIED) {
   745                 // Check if we can re-use the process of the parent app.
   746                 p = sAppContentParents->Get(parentAppURL);
   747             }
   748         }
   749     }
   751     if (p) {
   752         // Check that the process is still alive and set its priority.
   753         // Hopefully the process won't die after this point, if this call
   754         // succeeds.
   755         if (!p->SetPriorityAndCheckIsAlive(initialPriority)) {
   756             p = nullptr;
   757         }
   758     }
   760     if (!p) {
   761         p = MaybeTakePreallocatedAppProcess(manifestURL,
   762                                             initialPriority);
   763         if (!p) {
   764 #ifdef MOZ_NUWA_PROCESS
   765             if (Preferences::GetBool("dom.ipc.processPrelaunch.enabled",
   766                                      false)) {
   767                 // Returning nullptr from here so the frame loader will retry
   768                 // later when we have a spare process.
   769                 return nullptr;
   770             }
   771 #endif
   772             NS_WARNING("Unable to use pre-allocated app process");
   773             p = new ContentParent(ownApp,
   774                                   /* isForBrowserElement = */ false,
   775                                   /* isForPreallocated = */ false,
   776                                   initialPriority);
   777             p->Init();
   778         }
   779         sAppContentParents->Put(manifestURL, p);
   780     }
   782     uint32_t chromeFlags = 0;
   784     nsRefPtr<TabParent> tp = new TabParent(p, aContext, chromeFlags);
   785     tp->SetOwnerElement(aFrameElement);
   786     PBrowserParent* browser = p->SendPBrowserConstructor(
   787         // DeallocPBrowserParent() releases this ref.
   788         nsRefPtr<TabParent>(tp).forget().take(),
   789         aContext.AsIPCTabContext(),
   790         chromeFlags);
   792     p->MaybeTakeCPUWakeLock(aFrameElement);
   794     return static_cast<TabParent*>(browser);
   795 }
   797 void
   798 ContentParent::GetAll(nsTArray<ContentParent*>& aArray)
   799 {
   800     aArray.Clear();
   802     if (!sContentParents) {
   803         return;
   804     }
   806     for (ContentParent* cp = sContentParents->getFirst(); cp;
   807          cp = cp->LinkedListElement<ContentParent>::getNext()) {
   808         if (cp->mIsAlive) {
   809             aArray.AppendElement(cp);
   810         }
   811     }
   812 }
   814 void
   815 ContentParent::GetAllEvenIfDead(nsTArray<ContentParent*>& aArray)
   816 {
   817     aArray.Clear();
   819     if (!sContentParents) {
   820         return;
   821     }
   823     for (ContentParent* cp = sContentParents->getFirst(); cp;
   824          cp = cp->LinkedListElement<ContentParent>::getNext()) {
   825         aArray.AppendElement(cp);
   826     }
   827 }
   829 void
   830 ContentParent::Init()
   831 {
   832     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   833     if (obs) {
   834         size_t length = ArrayLength(sObserverTopics);
   835         for (size_t i = 0; i < length; ++i) {
   836             obs->AddObserver(this, sObserverTopics[i], false);
   837         }
   838     }
   839     Preferences::AddStrongObserver(this, "");
   840     if (obs) {
   841         obs->NotifyObservers(static_cast<nsIObserver*>(this), "ipc:content-created", nullptr);
   842     }
   844 #ifdef ACCESSIBILITY
   845     // If accessibility is running in chrome process then start it in content
   846     // process.
   847     if (nsIPresShell::IsAccessibilityActive()) {
   848         unused << SendActivateA11y();
   849     }
   850 #endif
   852     DebugOnly<FileUpdateDispatcher*> observer = FileUpdateDispatcher::GetSingleton();
   853     NS_ASSERTION(observer, "FileUpdateDispatcher is null");
   854 }
   856 namespace {
   858 class SystemMessageHandledListener MOZ_FINAL
   859     : public nsITimerCallback
   860     , public LinkedListElement<SystemMessageHandledListener>
   861 {
   862 public:
   863     NS_DECL_ISUPPORTS
   865     SystemMessageHandledListener() {}
   867     static void OnSystemMessageHandled()
   868     {
   869         if (!sListeners) {
   870             return;
   871         }
   873         SystemMessageHandledListener* listener = sListeners->popFirst();
   874         if (!listener) {
   875             return;
   876         }
   878         // Careful: ShutDown() may delete |this|.
   879         listener->ShutDown();
   880     }
   882     void Init(WakeLock* aWakeLock)
   883     {
   884         MOZ_ASSERT(!mWakeLock);
   885         MOZ_ASSERT(!mTimer);
   887         // mTimer keeps a strong reference to |this|.  When this object's
   888         // destructor runs, it will remove itself from the LinkedList.
   890         if (!sListeners) {
   891             sListeners = new LinkedList<SystemMessageHandledListener>();
   892             ClearOnShutdown(&sListeners);
   893         }
   894         sListeners->insertBack(this);
   896         mWakeLock = aWakeLock;
   898         mTimer = do_CreateInstance("@mozilla.org/timer;1");
   900         uint32_t timeoutSec =
   901             Preferences::GetInt("dom.ipc.systemMessageCPULockTimeoutSec", 30);
   902         mTimer->InitWithCallback(this, timeoutSec * 1000,
   903                                  nsITimer::TYPE_ONE_SHOT);
   904     }
   906     NS_IMETHOD Notify(nsITimer* aTimer)
   907     {
   908         // Careful: ShutDown() may delete |this|.
   909         ShutDown();
   910         return NS_OK;
   911     }
   913 private:
   914     static StaticAutoPtr<LinkedList<SystemMessageHandledListener> > sListeners;
   916     void ShutDown()
   917     {
   918         nsRefPtr<SystemMessageHandledListener> kungFuDeathGrip = this;
   920         ErrorResult rv;
   921         mWakeLock->Unlock(rv);
   923         if (mTimer) {
   924             mTimer->Cancel();
   925             mTimer = nullptr;
   926         }
   927     }
   929     nsRefPtr<WakeLock> mWakeLock;
   930     nsCOMPtr<nsITimer> mTimer;
   931 };
   933 StaticAutoPtr<LinkedList<SystemMessageHandledListener> >
   934     SystemMessageHandledListener::sListeners;
   936 NS_IMPL_ISUPPORTS(SystemMessageHandledListener,
   937                   nsITimerCallback)
   939 } // anonymous namespace
   941 void
   942 ContentParent::MaybeTakeCPUWakeLock(Element* aFrameElement)
   943 {
   944     // Take the CPU wake lock on behalf of this processs if it's expecting a
   945     // system message.  We'll release the CPU lock once the message is
   946     // delivered, or after some period of time, which ever comes first.
   948     nsCOMPtr<nsIMozBrowserFrame> browserFrame =
   949         do_QueryInterface(aFrameElement);
   950     if (!browserFrame ||
   951         !browserFrame->GetIsExpectingSystemMessage()) {
   952         return;
   953     }
   955     nsRefPtr<PowerManagerService> pms = PowerManagerService::GetInstance();
   956     nsRefPtr<WakeLock> lock =
   957         pms->NewWakeLockOnBehalfOfProcess(NS_LITERAL_STRING("cpu"), this);
   959     // This object's Init() function keeps it alive.
   960     nsRefPtr<SystemMessageHandledListener> listener =
   961         new SystemMessageHandledListener();
   962     listener->Init(lock);
   963 }
   965 bool
   966 ContentParent::SetPriorityAndCheckIsAlive(ProcessPriority aPriority)
   967 {
   968     ProcessPriorityManager::SetProcessPriority(this, aPriority);
   970     // Now that we've set this process's priority, check whether the process is
   971     // still alive.  Hopefully we've set the priority to FOREGROUND*, so the
   972     // process won't unexpectedly crash after this point!
   973     //
   974     // Bug 943174: use waitid() with WNOWAIT so that, if the process
   975     // did exit, we won't consume its zombie and confuse the
   976     // GeckoChildProcessHost dtor.  Also, if the process isn't a
   977     // direct child because of Nuwa this will fail with ECHILD, and we
   978     // need to assume the child is alive in that case rather than
   979     // assuming it's dead (as is otherwise a reasonable fallback).
   980 #ifdef MOZ_WIDGET_GONK
   981     siginfo_t info;
   982     info.si_pid = 0;
   983     if (waitid(P_PID, Pid(), &info, WNOWAIT | WNOHANG | WEXITED) == 0
   984         && info.si_pid != 0) {
   985         return false;
   986     }
   987 #endif
   989     return true;
   990 }
   992 // Helper for ContentParent::TransformPreallocatedIntoApp.
   993 static void
   994 TryGetNameFromManifestURL(const nsAString& aManifestURL,
   995                           nsAString& aName)
   996 {
   997     aName.Truncate();
   998     if (aManifestURL.IsEmpty() ||
   999         aManifestURL == MAGIC_PREALLOCATED_APP_MANIFEST_URL) {
  1000         return;
  1003     nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
  1004     NS_ENSURE_TRUE_VOID(appsService);
  1006     nsCOMPtr<mozIApplication> app;
  1007     appsService->GetAppByManifestURL(aManifestURL, getter_AddRefs(app));
  1009     if (!app) {
  1010         return;
  1013     app->GetName(aName);
  1016 void
  1017 ContentParent::TransformPreallocatedIntoApp(const nsAString& aAppManifestURL)
  1019     MOZ_ASSERT(IsPreallocated());
  1020     mAppManifestURL = aAppManifestURL;
  1021     TryGetNameFromManifestURL(aAppManifestURL, mAppName);
  1024 void
  1025 ContentParent::TransformPreallocatedIntoBrowser()
  1027     // Reset mAppManifestURL, mIsForBrowser and mOSPrivileges for browser.
  1028     mAppManifestURL.Truncate();
  1029     mIsForBrowser = true;
  1032 void
  1033 ContentParent::ShutDownProcess(bool aCloseWithError)
  1035     const InfallibleTArray<PIndexedDBParent*>& idbParents =
  1036         ManagedPIndexedDBParent();
  1037     for (uint32_t i = 0; i < idbParents.Length(); ++i) {
  1038         static_cast<IndexedDBParent*>(idbParents[i])->Disconnect();
  1041     // If Close() fails with an error, we'll end up back in this function, but
  1042     // with aCloseWithError = true.  It's important that we call
  1043     // CloseWithError() in this case; see bug 895204.
  1045     if (!aCloseWithError && !mCalledClose) {
  1046         // Close() can only be called once: It kicks off the destruction
  1047         // sequence.
  1048         mCalledClose = true;
  1049         Close();
  1052     if (aCloseWithError && !mCalledCloseWithError) {
  1053         MessageChannel* channel = GetIPCChannel();
  1054         if (channel) {
  1055             mCalledCloseWithError = true;
  1056             channel->CloseWithError();
  1060     // NB: must MarkAsDead() here so that this isn't accidentally
  1061     // returned from Get*() while in the midst of shutdown.
  1062     MarkAsDead();
  1064     // A ContentParent object might not get freed until after XPCOM shutdown has
  1065     // shut down the cycle collector.  But by then it's too late to release any
  1066     // CC'ed objects, so we need to null them out here, while we still can.  See
  1067     // bug 899761.
  1068     if (mMessageManager) {
  1069       mMessageManager->Disconnect();
  1070       mMessageManager = nullptr;
  1074 void
  1075 ContentParent::MarkAsDead()
  1077     if (!mAppManifestURL.IsEmpty()) {
  1078         if (sAppContentParents) {
  1079             sAppContentParents->Remove(mAppManifestURL);
  1080             if (!sAppContentParents->Count()) {
  1081                 delete sAppContentParents;
  1082                 sAppContentParents = nullptr;
  1085     } else if (sNonAppContentParents) {
  1086         sNonAppContentParents->RemoveElement(this);
  1087         if (!sNonAppContentParents->Length()) {
  1088             delete sNonAppContentParents;
  1089             sNonAppContentParents = nullptr;
  1093     if (sPrivateContent) {
  1094         sPrivateContent->RemoveElement(this);
  1095         if (!sPrivateContent->Length()) {
  1096             delete sPrivateContent;
  1097             sPrivateContent = nullptr;
  1101     mIsAlive = false;
  1104 void
  1105 ContentParent::OnChannelError()
  1107     nsRefPtr<ContentParent> content(this);
  1108 #ifdef MOZ_NUWA_PROCESS
  1109     // Handle app or Nuwa process exit before normal channel error handling.
  1110     PreallocatedProcessManager::MaybeForgetSpare(this);
  1111 #endif
  1112     PContentParent::OnChannelError();
  1115 void
  1116 ContentParent::OnChannelConnected(int32_t pid)
  1118     ProcessHandle handle;
  1119     if (!base::OpenPrivilegedProcessHandle(pid, &handle)) {
  1120         NS_WARNING("Can't open handle to child process.");
  1122     else {
  1123         // we need to close the existing handle before setting a new one.
  1124         base::CloseProcessHandle(OtherProcess());
  1125         SetOtherProcess(handle);
  1127 #if defined(ANDROID) || defined(LINUX)
  1128         // Check nice preference
  1129         int32_t nice = Preferences::GetInt("dom.ipc.content.nice", 0);
  1131         // Environment variable overrides preference
  1132         char* relativeNicenessStr = getenv("MOZ_CHILD_PROCESS_RELATIVE_NICENESS");
  1133         if (relativeNicenessStr) {
  1134             nice = atoi(relativeNicenessStr);
  1137         /* make the GUI thread have higher priority on single-cpu devices */
  1138         nsCOMPtr<nsIPropertyBag2> infoService = do_GetService(NS_SYSTEMINFO_CONTRACTID);
  1139         if (infoService) {
  1140             int32_t cpus;
  1141             nsresult rv = infoService->GetPropertyAsInt32(NS_LITERAL_STRING("cpucount"), &cpus);
  1142             if (NS_FAILED(rv)) {
  1143                 cpus = 1;
  1145             if (nice != 0 && cpus == 1) {
  1146                 setpriority(PRIO_PROCESS, pid, getpriority(PRIO_PROCESS, pid) + nice);
  1149 #endif
  1152     // Set a reply timeout. The only time the parent process will actually
  1153     // timeout is through urgent messages (which are used by CPOWs).
  1154     SetReplyTimeoutMs(Preferences::GetInt("dom.ipc.cpow.timeout", 3000));
  1157 void
  1158 ContentParent::ProcessingError(Result what)
  1160     if (MsgDropped == what) {
  1161         // Messages sent after crashes etc. are not a big deal.
  1162         return;
  1164     // Other errors are big deals.
  1165     KillHard();
  1168 namespace {
  1170 void
  1171 DelayedDeleteSubprocess(GeckoChildProcessHost* aSubprocess)
  1173     XRE_GetIOMessageLoop()
  1174         ->PostTask(FROM_HERE,
  1175                    new DeleteTask<GeckoChildProcessHost>(aSubprocess));
  1178 // This runnable only exists to delegate ownership of the
  1179 // ContentParent to this runnable, until it's deleted by the event
  1180 // system.
  1181 struct DelayedDeleteContentParentTask : public nsRunnable
  1183     DelayedDeleteContentParentTask(ContentParent* aObj) : mObj(aObj) { }
  1185     // No-op
  1186     NS_IMETHODIMP Run() { return NS_OK; }
  1188     nsRefPtr<ContentParent> mObj;
  1189 };
  1193 void
  1194 ContentParent::ActorDestroy(ActorDestroyReason why)
  1196     if (mForceKillTask) {
  1197         mForceKillTask->Cancel();
  1198         mForceKillTask = nullptr;
  1201     nsRefPtr<nsFrameMessageManager> ppm = mMessageManager;
  1202     if (ppm) {
  1203       ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()),
  1204                           CHILD_PROCESS_SHUTDOWN_MESSAGE, false,
  1205                           nullptr, nullptr, nullptr, nullptr);
  1207     nsRefPtr<ContentParent> kungFuDeathGrip(this);
  1208     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
  1209     if (obs) {
  1210         size_t length = ArrayLength(sObserverTopics);
  1211         for (size_t i = 0; i < length; ++i) {
  1212             obs->RemoveObserver(static_cast<nsIObserver*>(this),
  1213                                 sObserverTopics[i]);
  1217     if (ppm) {
  1218       ppm->Disconnect();
  1221     // Tell the memory reporter manager that this ContentParent is going away.
  1222     nsRefPtr<nsMemoryReporterManager> mgr =
  1223         nsMemoryReporterManager::GetOrCreate();
  1224 #ifdef MOZ_NUWA_PROCESS
  1225     bool isMemoryChild = !IsNuwaProcess();
  1226 #else
  1227     bool isMemoryChild = true;
  1228 #endif
  1229     if (mgr && isMemoryChild) {
  1230         mgr->DecrementNumChildProcesses();
  1233     // remove the global remote preferences observers
  1234     Preferences::RemoveObserver(this, "");
  1236     RecvRemoveGeolocationListener();
  1238     mConsoleService = nullptr;
  1240     MarkAsDead();
  1242     if (obs) {
  1243         nsRefPtr<nsHashPropertyBag> props = new nsHashPropertyBag();
  1245         props->SetPropertyAsUint64(NS_LITERAL_STRING("childID"), mChildID);
  1247         if (AbnormalShutdown == why) {
  1248             props->SetPropertyAsBool(NS_LITERAL_STRING("abnormal"), true);
  1250 #ifdef MOZ_CRASHREPORTER
  1251             // There's a window in which child processes can crash
  1252             // after IPC is established, but before a crash reporter
  1253             // is created.
  1254             if (ManagedPCrashReporterParent().Length() > 0) {
  1255                 CrashReporterParent* crashReporter =
  1256                     static_cast<CrashReporterParent*>(ManagedPCrashReporterParent()[0]);
  1258                 // If we're an app process, always stomp the latest URI
  1259                 // loaded in the child process with our manifest URL.  We
  1260                 // would rather associate the crashes with apps than
  1261                 // random child windows loaded in them.
  1262                 //
  1263                 // XXX would be nice if we could get both ...
  1264                 if (!mAppManifestURL.IsEmpty()) {
  1265                     crashReporter->AnnotateCrashReport(NS_LITERAL_CSTRING("URL"),
  1266                                                        NS_ConvertUTF16toUTF8(mAppManifestURL));
  1269                 crashReporter->GenerateCrashReport(this, nullptr);
  1271                 nsAutoString dumpID(crashReporter->ChildDumpID());
  1272                 props->SetPropertyAsAString(NS_LITERAL_STRING("dumpID"), dumpID);
  1274 #endif
  1276         obs->NotifyObservers((nsIPropertyBag2*) props, "ipc:content-shutdown", nullptr);
  1279     mIdleListeners.Clear();
  1281     // If the child process was terminated due to a SIGKIL, ShutDownProcess
  1282     // might not have been called yet.  We must call it to ensure that our
  1283     // channel is closed, etc.
  1284     ShutDownProcess(/* closeWithError */ true);
  1286     MessageLoop::current()->
  1287         PostTask(FROM_HERE,
  1288                  NewRunnableFunction(DelayedDeleteSubprocess, mSubprocess));
  1289     mSubprocess = nullptr;
  1291     // IPDL rules require actors to live on past ActorDestroy, but it
  1292     // may be that the kungFuDeathGrip above is the last reference to
  1293     // |this|.  If so, when we go out of scope here, we're deleted and
  1294     // all hell breaks loose.
  1295     //
  1296     // This runnable ensures that a reference to |this| lives on at
  1297     // least until after the current task finishes running.
  1298     NS_DispatchToCurrentThread(new DelayedDeleteContentParentTask(this));
  1301 void
  1302 ContentParent::NotifyTabDestroying(PBrowserParent* aTab)
  1304     // There can be more than one PBrowser for a given app process
  1305     // because of popup windows.  PBrowsers can also destroy
  1306     // concurrently.  When all the PBrowsers are destroying, kick off
  1307     // another task to ensure the child process *really* shuts down,
  1308     // even if the PBrowsers themselves never finish destroying.
  1309     int32_t numLiveTabs = ManagedPBrowserParent().Length();
  1310     ++mNumDestroyingTabs;
  1311     if (mNumDestroyingTabs != numLiveTabs) {
  1312         return;
  1315     // We're dying now, so prevent this content process from being
  1316     // recycled during its shutdown procedure.
  1317     MarkAsDead();
  1319     MOZ_ASSERT(!mForceKillTask);
  1320     int32_t timeoutSecs =
  1321         Preferences::GetInt("dom.ipc.tabs.shutdownTimeoutSecs", 5);
  1322     if (timeoutSecs > 0) {
  1323         MessageLoop::current()->PostDelayedTask(
  1324             FROM_HERE,
  1325             mForceKillTask = NewRunnableMethod(this, &ContentParent::KillHard),
  1326             timeoutSecs * 1000);
  1330 void
  1331 ContentParent::NotifyTabDestroyed(PBrowserParent* aTab,
  1332                                   bool aNotifiedDestroying)
  1334     if (aNotifiedDestroying) {
  1335         --mNumDestroyingTabs;
  1338     // There can be more than one PBrowser for a given app process
  1339     // because of popup windows.  When the last one closes, shut
  1340     // us down.
  1341     if (ManagedPBrowserParent().Length() == 1) {
  1342         MessageLoop::current()->PostTask(
  1343             FROM_HERE,
  1344             NewRunnableMethod(this, &ContentParent::ShutDownProcess,
  1345                               /* force */ false));
  1349 jsipc::JavaScriptParent*
  1350 ContentParent::GetCPOWManager()
  1352     if (ManagedPJavaScriptParent().Length()) {
  1353         return static_cast<JavaScriptParent*>(ManagedPJavaScriptParent()[0]);
  1355     JavaScriptParent* actor = static_cast<JavaScriptParent*>(SendPJavaScriptConstructor());
  1356     return actor;
  1359 TestShellParent*
  1360 ContentParent::CreateTestShell()
  1362   return static_cast<TestShellParent*>(SendPTestShellConstructor());
  1365 bool
  1366 ContentParent::DestroyTestShell(TestShellParent* aTestShell)
  1368     return PTestShellParent::Send__delete__(aTestShell);
  1371 TestShellParent*
  1372 ContentParent::GetTestShellSingleton()
  1374     if (!ManagedPTestShellParent().Length())
  1375         return nullptr;
  1376     return static_cast<TestShellParent*>(ManagedPTestShellParent()[0]);
  1379 void
  1380 ContentParent::InitializeMembers()
  1382     mSubprocess = nullptr;
  1383     mChildID = gContentChildID++;
  1384     mGeolocationWatchID = -1;
  1385     mForceKillTask = nullptr;
  1386     mNumDestroyingTabs = 0;
  1387     mIsAlive = true;
  1388     mSendPermissionUpdates = false;
  1389     mCalledClose = false;
  1390     mCalledCloseWithError = false;
  1391     mCalledKillHard = false;
  1394 ContentParent::ContentParent(mozIApplication* aApp,
  1395                              bool aIsForBrowser,
  1396                              bool aIsForPreallocated,
  1397                              ProcessPriority aInitialPriority /* = PROCESS_PRIORITY_FOREGROUND */,
  1398                              bool aIsNuwaProcess /* = false */)
  1399     : mIsForBrowser(aIsForBrowser)
  1400     , mIsNuwaProcess(aIsNuwaProcess)
  1402     InitializeMembers();  // Perform common initialization.
  1404     // No more than one of !!aApp, aIsForBrowser, aIsForPreallocated should be
  1405     // true.
  1406     MOZ_ASSERT(!!aApp + aIsForBrowser + aIsForPreallocated <= 1);
  1408     // Only the preallocated process uses Nuwa.
  1409     MOZ_ASSERT_IF(aIsNuwaProcess, aIsForPreallocated);
  1411     // Insert ourselves into the global linked list of ContentParent objects.
  1412     if (!sContentParents) {
  1413         sContentParents = new LinkedList<ContentParent>();
  1415     if (!aIsNuwaProcess) {
  1416         sContentParents->insertBack(this);
  1419     if (aApp) {
  1420         aApp->GetManifestURL(mAppManifestURL);
  1421         aApp->GetName(mAppName);
  1422     } else if (aIsForPreallocated) {
  1423         mAppManifestURL = MAGIC_PREALLOCATED_APP_MANIFEST_URL;
  1426     // From this point on, NS_WARNING, NS_ASSERTION, etc. should print out the
  1427     // PID along with the warning.
  1428     nsDebugImpl::SetMultiprocessMode("Parent");
  1430     NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
  1431     ChildPrivileges privs = aIsNuwaProcess
  1432         ? base::PRIVILEGES_INHERIT
  1433         : base::PRIVILEGES_DEFAULT;
  1434     mSubprocess = new GeckoChildProcessHost(GeckoProcessType_Content, privs);
  1435     mSubprocess->SetSandboxEnabled(ShouldSandboxContentProcesses());
  1437     IToplevelProtocol::SetTransport(mSubprocess->GetChannel());
  1439     if (!aIsNuwaProcess) {
  1440         // Tell the memory reporter manager that this ContentParent exists.
  1441         nsRefPtr<nsMemoryReporterManager> mgr =
  1442             nsMemoryReporterManager::GetOrCreate();
  1443         if (mgr) {
  1444             mgr->IncrementNumChildProcesses();
  1448     std::vector<std::string> extraArgs;
  1449     if (aIsNuwaProcess) {
  1450         extraArgs.push_back("-nuwa");
  1452     mSubprocess->LaunchAndWaitForProcessHandle(extraArgs);
  1454     Open(mSubprocess->GetChannel(), mSubprocess->GetOwnedChildProcessHandle());
  1456     InitInternal(aInitialPriority,
  1457                  true, /* Setup off-main thread compositing */
  1458                  true  /* Send registered chrome */);
  1461 #ifdef MOZ_NUWA_PROCESS
  1462 static const mozilla::ipc::FileDescriptor*
  1463 FindFdProtocolFdMapping(const nsTArray<ProtocolFdMapping>& aFds,
  1464                         ProtocolId aProtoId)
  1466     for (unsigned int i = 0; i < aFds.Length(); i++) {
  1467         if (aFds[i].protocolId() == aProtoId) {
  1468             return &aFds[i].fd();
  1471     return nullptr;
  1474 /**
  1475  * This constructor is used for new content process cloned from a template.
  1477  * For Nuwa.
  1478  */
  1479 ContentParent::ContentParent(ContentParent* aTemplate,
  1480                              const nsAString& aAppManifestURL,
  1481                              base::ProcessHandle aPid,
  1482                              const nsTArray<ProtocolFdMapping>& aFds)
  1483     : mAppManifestURL(aAppManifestURL)
  1484     , mIsForBrowser(false)
  1485     , mIsNuwaProcess(false)
  1487     InitializeMembers();  // Perform common initialization.
  1489     sContentParents->insertBack(this);
  1491     // From this point on, NS_WARNING, NS_ASSERTION, etc. should print out the
  1492     // PID along with the warning.
  1493     nsDebugImpl::SetMultiprocessMode("Parent");
  1495     NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
  1497     const FileDescriptor* fd = FindFdProtocolFdMapping(aFds, GetProtocolId());
  1499     NS_ASSERTION(fd != nullptr, "IPC Channel for PContent is necessary!");
  1500     mSubprocess = new GeckoExistingProcessHost(GeckoProcessType_Content,
  1501                                                aPid,
  1502                                                *fd);
  1504     // Tell the memory reporter manager that this ContentParent exists.
  1505     nsRefPtr<nsMemoryReporterManager> mgr =
  1506         nsMemoryReporterManager::GetOrCreate();
  1507     if (mgr) {
  1508         mgr->IncrementNumChildProcesses();
  1511     mSubprocess->LaunchAndWaitForProcessHandle();
  1513     // Clone actors routed by aTemplate for this instance.
  1514     IToplevelProtocol::SetTransport(mSubprocess->GetChannel());
  1515     ProtocolCloneContext cloneContext;
  1516     cloneContext.SetContentParent(this);
  1517     CloneManagees(aTemplate, &cloneContext);
  1518     CloneOpenedToplevels(aTemplate, aFds, aPid, &cloneContext);
  1520     Open(mSubprocess->GetChannel(),
  1521          mSubprocess->GetChildProcessHandle());
  1523     // Set the subprocess's priority (bg if we're a preallocated process, fg
  1524     // otherwise).  We do this first because we're likely /lowering/ its CPU and
  1525     // memory priority, which it has inherited from this process.
  1526     ProcessPriority priority;
  1527     if (IsPreallocated()) {
  1528         priority = PROCESS_PRIORITY_PREALLOC;
  1529     } else {
  1530         priority = PROCESS_PRIORITY_FOREGROUND;
  1533     InitInternal(priority,
  1534                  false, /* Setup Off-main thread compositing */
  1535                  false  /* Send registered chrome */);
  1537 #endif  // MOZ_NUWA_PROCESS
  1539 ContentParent::~ContentParent()
  1541     if (mForceKillTask) {
  1542         mForceKillTask->Cancel();
  1545     if (OtherProcess())
  1546         base::CloseProcessHandle(OtherProcess());
  1548     NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
  1550     // We should be removed from all these lists in ActorDestroy.
  1551     MOZ_ASSERT(!sPrivateContent || !sPrivateContent->Contains(this));
  1552     if (mAppManifestURL.IsEmpty()) {
  1553         MOZ_ASSERT(!sNonAppContentParents ||
  1554                    !sNonAppContentParents->Contains(this));
  1555     } else {
  1556         // In general, we expect sAppContentParents->Get(mAppManifestURL) to be
  1557         // nullptr.  But it could be that we created another ContentParent for
  1558         // this app after we did this->ActorDestroy(), so the right check is
  1559         // that sAppContentParents->Get(mAppManifestURL) != this.
  1560         MOZ_ASSERT(!sAppContentParents ||
  1561                    sAppContentParents->Get(mAppManifestURL) != this);
  1565 void
  1566 ContentParent::InitInternal(ProcessPriority aInitialPriority,
  1567                             bool aSetupOffMainThreadCompositing,
  1568                             bool aSendRegisteredChrome)
  1570     // Set the subprocess's priority.  We do this early on because we're likely
  1571     // /lowering/ the process's CPU and memory priority, which it has inherited
  1572     // from this process.
  1573     //
  1574     // This call can cause us to send IPC messages to the child process, so it
  1575     // must come after the Open() call above.
  1576     ProcessPriorityManager::SetProcessPriority(this, aInitialPriority);
  1578     if (aSetupOffMainThreadCompositing) {
  1579         // NB: internally, this will send an IPC message to the child
  1580         // process to get it to create the CompositorChild.  This
  1581         // message goes through the regular IPC queue for this
  1582         // channel, so delivery will happen-before any other messages
  1583         // we send.  The CompositorChild must be created before any
  1584         // PBrowsers are created, because they rely on the Compositor
  1585         // already being around.  (Creation is async, so can't happen
  1586         // on demand.)
  1587         bool useOffMainThreadCompositing = !!CompositorParent::CompositorLoop();
  1588         if (useOffMainThreadCompositing) {
  1589             DebugOnly<bool> opened = PCompositor::Open(this);
  1590             MOZ_ASSERT(opened);
  1592             if (gfxPrefs::AsyncVideoEnabled()) {
  1593                 opened = PImageBridge::Open(this);
  1594                 MOZ_ASSERT(opened);
  1599     if (aSendRegisteredChrome) {
  1600         nsCOMPtr<nsIChromeRegistry> registrySvc = nsChromeRegistry::GetService();
  1601         nsChromeRegistryChrome* chromeRegistry =
  1602             static_cast<nsChromeRegistryChrome*>(registrySvc.get());
  1603         chromeRegistry->SendRegisteredChrome(this);
  1606     mMessageManager = nsFrameMessageManager::NewProcessMessageManager(this);
  1608     if (gAppData) {
  1609         nsCString version(gAppData->version);
  1610         nsCString buildID(gAppData->buildID);
  1611         nsCString name(gAppData->name);
  1612         nsCString UAName(gAppData->UAName);
  1614         // Sending all information to content process.
  1615         unused << SendAppInfo(version, buildID, name, UAName);
  1618     nsStyleSheetService *sheetService = nsStyleSheetService::GetInstance();
  1619     if (sheetService) {
  1620         // This looks like a lot of work, but in a normal browser session we just
  1621         // send two loads.
  1623         nsCOMArray<nsIStyleSheet>& agentSheets = *sheetService->AgentStyleSheets();
  1624         for (uint32_t i = 0; i < agentSheets.Length(); i++) {
  1625             URIParams uri;
  1626             SerializeURI(agentSheets[i]->GetSheetURI(), uri);
  1627             unused << SendLoadAndRegisterSheet(uri, nsIStyleSheetService::AGENT_SHEET);
  1630         nsCOMArray<nsIStyleSheet>& userSheets = *sheetService->UserStyleSheets();
  1631         for (uint32_t i = 0; i < userSheets.Length(); i++) {
  1632             URIParams uri;
  1633             SerializeURI(userSheets[i]->GetSheetURI(), uri);
  1634             unused << SendLoadAndRegisterSheet(uri, nsIStyleSheetService::USER_SHEET);
  1637         nsCOMArray<nsIStyleSheet>& authorSheets = *sheetService->AuthorStyleSheets();
  1638         for (uint32_t i = 0; i < authorSheets.Length(); i++) {
  1639             URIParams uri;
  1640             SerializeURI(authorSheets[i]->GetSheetURI(), uri);
  1641             unused << SendLoadAndRegisterSheet(uri, nsIStyleSheetService::AUTHOR_SHEET);
  1645 #ifdef MOZ_CONTENT_SANDBOX
  1646     bool shouldSandbox = true;
  1647 #ifdef MOZ_NUWA_PROCESS
  1648     if (IsNuwaProcess()) {
  1649         shouldSandbox = false;
  1651 #endif
  1652     if (shouldSandbox && !SendSetProcessSandbox()) {
  1653         KillHard();
  1655 #endif
  1658 bool
  1659 ContentParent::IsAlive()
  1661     return mIsAlive;
  1664 bool
  1665 ContentParent::IsForApp()
  1667     return !mAppManifestURL.IsEmpty();
  1670 #ifdef MOZ_NUWA_PROCESS
  1671 bool
  1672 ContentParent::IsNuwaProcess()
  1674     return mIsNuwaProcess;
  1676 #endif
  1678 int32_t
  1679 ContentParent::Pid()
  1681     if (!mSubprocess || !mSubprocess->GetChildProcessHandle()) {
  1682         return -1;
  1684     return base::GetProcId(mSubprocess->GetChildProcessHandle());
  1687 bool
  1688 ContentParent::RecvReadPrefsArray(InfallibleTArray<PrefSetting>* aPrefs)
  1690     Preferences::GetPreferences(aPrefs);
  1691     return true;
  1694 bool
  1695 ContentParent::RecvReadFontList(InfallibleTArray<FontListEntry>* retValue)
  1697 #ifdef ANDROID
  1698     gfxAndroidPlatform::GetPlatform()->GetFontList(retValue);
  1699 #endif
  1700     return true;
  1703 bool
  1704 ContentParent::RecvReadPermissions(InfallibleTArray<IPC::Permission>* aPermissions)
  1706 #ifdef MOZ_PERMISSIONS
  1707     nsCOMPtr<nsIPermissionManager> permissionManagerIface =
  1708         do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
  1709     nsPermissionManager* permissionManager =
  1710         static_cast<nsPermissionManager*>(permissionManagerIface.get());
  1711     NS_ABORT_IF_FALSE(permissionManager,
  1712                  "We have no permissionManager in the Chrome process !");
  1714     nsCOMPtr<nsISimpleEnumerator> enumerator;
  1715     DebugOnly<nsresult> rv = permissionManager->GetEnumerator(getter_AddRefs(enumerator));
  1716     NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv), "Could not get enumerator!");
  1717     while(1) {
  1718         bool hasMore;
  1719         enumerator->HasMoreElements(&hasMore);
  1720         if (!hasMore)
  1721             break;
  1723         nsCOMPtr<nsISupports> supp;
  1724         enumerator->GetNext(getter_AddRefs(supp));
  1725         nsCOMPtr<nsIPermission> perm = do_QueryInterface(supp);
  1727         nsCString host;
  1728         perm->GetHost(host);
  1729         uint32_t appId;
  1730         perm->GetAppId(&appId);
  1731         bool isInBrowserElement;
  1732         perm->GetIsInBrowserElement(&isInBrowserElement);
  1733         nsCString type;
  1734         perm->GetType(type);
  1735         uint32_t capability;
  1736         perm->GetCapability(&capability);
  1737         uint32_t expireType;
  1738         perm->GetExpireType(&expireType);
  1739         int64_t expireTime;
  1740         perm->GetExpireTime(&expireTime);
  1742         aPermissions->AppendElement(IPC::Permission(host, appId,
  1743                                                     isInBrowserElement, type,
  1744                                                     capability, expireType,
  1745                                                     expireTime));
  1748     // Ask for future changes
  1749     mSendPermissionUpdates = true;
  1750 #endif
  1752     return true;
  1755 bool
  1756 ContentParent::RecvSetClipboardText(const nsString& text,
  1757                                        const bool& isPrivateData,
  1758                                        const int32_t& whichClipboard)
  1760     nsresult rv;
  1761     nsCOMPtr<nsIClipboard> clipboard(do_GetService(kCClipboardCID, &rv));
  1762     NS_ENSURE_SUCCESS(rv, true);
  1764     nsCOMPtr<nsISupportsString> dataWrapper =
  1765         do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
  1766     NS_ENSURE_SUCCESS(rv, true);
  1768     rv = dataWrapper->SetData(text);
  1769     NS_ENSURE_SUCCESS(rv, true);
  1771     nsCOMPtr<nsITransferable> trans = do_CreateInstance("@mozilla.org/widget/transferable;1", &rv);
  1772     NS_ENSURE_SUCCESS(rv, true);
  1773     trans->Init(nullptr);
  1775     // If our data flavor has already been added, this will fail. But we don't care
  1776     trans->AddDataFlavor(kUnicodeMime);
  1777     trans->SetIsPrivateData(isPrivateData);
  1779     nsCOMPtr<nsISupports> nsisupportsDataWrapper =
  1780         do_QueryInterface(dataWrapper);
  1782     rv = trans->SetTransferData(kUnicodeMime, nsisupportsDataWrapper,
  1783                                 text.Length() * sizeof(char16_t));
  1784     NS_ENSURE_SUCCESS(rv, true);
  1786     clipboard->SetData(trans, nullptr, whichClipboard);
  1787     return true;
  1790 bool
  1791 ContentParent::RecvGetClipboardText(const int32_t& whichClipboard, nsString* text)
  1793     nsresult rv;
  1794     nsCOMPtr<nsIClipboard> clipboard(do_GetService(kCClipboardCID, &rv));
  1795     NS_ENSURE_SUCCESS(rv, true);
  1797     nsCOMPtr<nsITransferable> trans = do_CreateInstance("@mozilla.org/widget/transferable;1", &rv);
  1798     NS_ENSURE_SUCCESS(rv, true);
  1799     trans->Init(nullptr);
  1800     trans->AddDataFlavor(kUnicodeMime);
  1802     clipboard->GetData(trans, whichClipboard);
  1803     nsCOMPtr<nsISupports> tmp;
  1804     uint32_t len;
  1805     rv = trans->GetTransferData(kUnicodeMime, getter_AddRefs(tmp), &len);
  1806     if (NS_FAILED(rv))
  1807         return true;
  1809     nsCOMPtr<nsISupportsString> supportsString = do_QueryInterface(tmp);
  1810     // No support for non-text data
  1811     if (!supportsString)
  1812         return true;
  1813     supportsString->GetData(*text);
  1814     return true;
  1817 bool
  1818 ContentParent::RecvEmptyClipboard(const int32_t& whichClipboard)
  1820     nsresult rv;
  1821     nsCOMPtr<nsIClipboard> clipboard(do_GetService(kCClipboardCID, &rv));
  1822     NS_ENSURE_SUCCESS(rv, true);
  1824     clipboard->EmptyClipboard(whichClipboard);
  1826     return true;
  1829 bool
  1830 ContentParent::RecvClipboardHasText(const int32_t& whichClipboard, bool* hasText)
  1832     nsresult rv;
  1833     nsCOMPtr<nsIClipboard> clipboard(do_GetService(kCClipboardCID, &rv));
  1834     NS_ENSURE_SUCCESS(rv, true);
  1836     clipboard->HasDataMatchingFlavors(sClipboardTextFlavors, 1,
  1837                                       whichClipboard, hasText);
  1838     return true;
  1841 bool
  1842 ContentParent::RecvGetSystemColors(const uint32_t& colorsCount, InfallibleTArray<uint32_t>* colors)
  1844 #ifdef MOZ_WIDGET_ANDROID
  1845     NS_ASSERTION(AndroidBridge::Bridge() != nullptr, "AndroidBridge is not available");
  1846     if (AndroidBridge::Bridge() == nullptr) {
  1847         // Do not fail - the colors won't be right, but it's not critical
  1848         return true;
  1851     colors->AppendElements(colorsCount);
  1853     // The array elements correspond to the members of AndroidSystemColors structure,
  1854     // so just pass the pointer to the elements buffer
  1855     AndroidBridge::Bridge()->GetSystemColors((AndroidSystemColors*)colors->Elements());
  1856 #endif
  1857     return true;
  1860 bool
  1861 ContentParent::RecvGetIconForExtension(const nsCString& aFileExt, const uint32_t& aIconSize, InfallibleTArray<uint8_t>* bits)
  1863 #ifdef MOZ_WIDGET_ANDROID
  1864     NS_ASSERTION(AndroidBridge::Bridge() != nullptr, "AndroidBridge is not available");
  1865     if (AndroidBridge::Bridge() == nullptr) {
  1866         // Do not fail - just no icon will be shown
  1867         return true;
  1870     bits->AppendElements(aIconSize * aIconSize * 4);
  1872     AndroidBridge::Bridge()->GetIconForExtension(aFileExt, aIconSize, bits->Elements());
  1873 #endif
  1874     return true;
  1877 bool
  1878 ContentParent::RecvGetShowPasswordSetting(bool* showPassword)
  1880     // default behavior is to show the last password character
  1881     *showPassword = true;
  1882 #ifdef MOZ_WIDGET_ANDROID
  1883     NS_ASSERTION(AndroidBridge::Bridge() != nullptr, "AndroidBridge is not available");
  1885     *showPassword = mozilla::widget::android::GeckoAppShell::GetShowPasswordSetting();
  1886 #endif
  1887     return true;
  1890 bool
  1891 ContentParent::RecvFirstIdle()
  1893     // When the ContentChild goes idle, it sends us a FirstIdle message
  1894     // which we use as a good time to prelaunch another process. If we
  1895     // prelaunch any sooner than this, then we'll be competing with the
  1896     // child process and slowing it down.
  1897     PreallocatedProcessManager::AllocateAfterDelay();
  1898     return true;
  1901 bool
  1902 ContentParent::RecvAudioChannelGetState(const AudioChannel& aChannel,
  1903                                         const bool& aElementHidden,
  1904                                         const bool& aElementWasHidden,
  1905                                         AudioChannelState* aState)
  1907     nsRefPtr<AudioChannelService> service =
  1908         AudioChannelService::GetAudioChannelService();
  1909     *aState = AUDIO_CHANNEL_STATE_NORMAL;
  1910     if (service) {
  1911         *aState = service->GetStateInternal(aChannel, mChildID,
  1912                                             aElementHidden, aElementWasHidden);
  1914     return true;
  1917 bool
  1918 ContentParent::RecvAudioChannelRegisterType(const AudioChannel& aChannel,
  1919                                             const bool& aWithVideo)
  1921     nsRefPtr<AudioChannelService> service =
  1922         AudioChannelService::GetAudioChannelService();
  1923     if (service) {
  1924         service->RegisterType(aChannel, mChildID, aWithVideo);
  1926     return true;
  1929 bool
  1930 ContentParent::RecvAudioChannelUnregisterType(const AudioChannel& aChannel,
  1931                                               const bool& aElementHidden,
  1932                                               const bool& aWithVideo)
  1934     nsRefPtr<AudioChannelService> service =
  1935         AudioChannelService::GetAudioChannelService();
  1936     if (service) {
  1937         service->UnregisterType(aChannel, aElementHidden, mChildID, aWithVideo);
  1939     return true;
  1942 bool
  1943 ContentParent::RecvAudioChannelChangedNotification()
  1945     nsRefPtr<AudioChannelService> service =
  1946         AudioChannelService::GetAudioChannelService();
  1947     if (service) {
  1948        service->SendAudioChannelChangedNotification(ChildID());
  1950     return true;
  1953 bool
  1954 ContentParent::RecvAudioChannelChangeDefVolChannel(const int32_t& aChannel,
  1955                                                    const bool& aHidden)
  1957     nsRefPtr<AudioChannelService> service =
  1958         AudioChannelService::GetAudioChannelService();
  1959     if (service) {
  1960        service->SetDefaultVolumeControlChannelInternal(aChannel,
  1961                                                        aHidden, mChildID);
  1963     return true;
  1966 bool
  1967 ContentParent::RecvBroadcastVolume(const nsString& aVolumeName)
  1969 #ifdef MOZ_WIDGET_GONK
  1970     nsresult rv;
  1971     nsCOMPtr<nsIVolumeService> vs = do_GetService(NS_VOLUMESERVICE_CONTRACTID, &rv);
  1972     if (vs) {
  1973         vs->BroadcastVolume(aVolumeName);
  1975     return true;
  1976 #else
  1977     NS_WARNING("ContentParent::RecvBroadcastVolume shouldn't be called when MOZ_WIDGET_GONK is not defined");
  1978     return false;
  1979 #endif
  1982 bool
  1983 ContentParent::RecvNuwaReady()
  1985 #ifdef MOZ_NUWA_PROCESS
  1986     if (!IsNuwaProcess()) {
  1987         NS_ERROR(
  1988             nsPrintfCString(
  1989                 "Terminating child process %d for unauthorized IPC message: NuwaReady",
  1990                 Pid()).get());
  1992         KillHard();
  1993         return false;
  1995     PreallocatedProcessManager::OnNuwaReady();
  1996     return true;
  1997 #else
  1998     NS_ERROR("ContentParent::RecvNuwaReady() not implemented!");
  1999     return false;
  2000 #endif
  2003 bool
  2004 ContentParent::RecvAddNewProcess(const uint32_t& aPid,
  2005                                  const InfallibleTArray<ProtocolFdMapping>& aFds)
  2007 #ifdef MOZ_NUWA_PROCESS
  2008     if (!IsNuwaProcess()) {
  2009         NS_ERROR(
  2010             nsPrintfCString(
  2011                 "Terminating child process %d for unauthorized IPC message: "
  2012                 "AddNewProcess(%d)", Pid(), aPid).get());
  2014         KillHard();
  2015         return false;
  2017     nsRefPtr<ContentParent> content;
  2018     content = new ContentParent(this,
  2019                                 MAGIC_PREALLOCATED_APP_MANIFEST_URL,
  2020                                 aPid,
  2021                                 aFds);
  2022     content->Init();
  2023     PreallocatedProcessManager::PublishSpareProcess(content);
  2024     return true;
  2025 #else
  2026     NS_ERROR("ContentParent::RecvAddNewProcess() not implemented!");
  2027     return false;
  2028 #endif
  2031 // We want ContentParent to show up in CC logs for debugging purposes, but we
  2032 // don't actually cycle collect it.
  2033 NS_IMPL_CYCLE_COLLECTION_0(ContentParent)
  2035 NS_IMPL_CYCLE_COLLECTING_ADDREF(ContentParent)
  2036 NS_IMPL_CYCLE_COLLECTING_RELEASE(ContentParent)
  2038 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ContentParent)
  2039   NS_INTERFACE_MAP_ENTRY(nsIObserver)
  2040   NS_INTERFACE_MAP_ENTRY(nsIDOMGeoPositionCallback)
  2041   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver)
  2042 NS_INTERFACE_MAP_END
  2044 NS_IMETHODIMP
  2045 ContentParent::Observe(nsISupports* aSubject,
  2046                        const char* aTopic,
  2047                        const char16_t* aData)
  2049     if (!strcmp(aTopic, "xpcom-shutdown") && mSubprocess) {
  2050         ShutDownProcess(/* closeWithError */ false);
  2051         NS_ASSERTION(!mSubprocess, "Close should have nulled mSubprocess");
  2054     if (!mIsAlive || !mSubprocess)
  2055         return NS_OK;
  2057     // listening for memory pressure event
  2058     if (!strcmp(aTopic, "memory-pressure") &&
  2059         !StringEndsWith(nsDependentString(aData),
  2060                         NS_LITERAL_STRING("-no-forward"))) {
  2061         unused << SendFlushMemory(nsDependentString(aData));
  2063     // listening for remotePrefs...
  2064     else if (!strcmp(aTopic, "nsPref:changed")) {
  2065         // We know prefs are ASCII here.
  2066         NS_LossyConvertUTF16toASCII strData(aData);
  2068         PrefSetting pref(strData, null_t(), null_t());
  2069         Preferences::GetPreference(&pref);
  2070         if (!SendPreferenceUpdate(pref)) {
  2071             return NS_ERROR_NOT_AVAILABLE;
  2074     else if (!strcmp(aTopic, NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC)) {
  2075       NS_ConvertUTF16toUTF8 dataStr(aData);
  2076       const char *offline = dataStr.get();
  2077       if (!SendSetOffline(!strcmp(offline, "true") ? true : false))
  2078           return NS_ERROR_NOT_AVAILABLE;
  2080     // listening for alert notifications
  2081     else if (!strcmp(aTopic, "alertfinished") ||
  2082              !strcmp(aTopic, "alertclickcallback") ||
  2083              !strcmp(aTopic, "alertshow") ) {
  2084         if (!SendNotifyAlertsObserver(nsDependentCString(aTopic),
  2085                                       nsDependentString(aData)))
  2086             return NS_ERROR_NOT_AVAILABLE;
  2088     else if (!strcmp(aTopic, "child-memory-reporter-request")) {
  2089         bool isNuwa = false;
  2090 #ifdef MOZ_NUWA_PROCESS
  2091         isNuwa = IsNuwaProcess();
  2092 #endif
  2093         if (!isNuwa) {
  2094             unsigned generation;
  2095             int minimize, identOffset = -1;
  2096             nsDependentString msg(aData);
  2097             NS_ConvertUTF16toUTF8 cmsg(msg);
  2099             if (sscanf(cmsg.get(),
  2100                        "generation=%x minimize=%d DMDident=%n",
  2101                        &generation, &minimize, &identOffset) < 2
  2102                 || identOffset < 0) {
  2103                 return NS_ERROR_INVALID_ARG;
  2105             // The pre-%n part of the string should be all ASCII, so the byte
  2106             // offset in identOffset should be correct as a char offset.
  2107             MOZ_ASSERT(cmsg[identOffset - 1] == '=');
  2108             unused << SendPMemoryReportRequestConstructor(
  2109               generation, minimize, nsString(Substring(msg, identOffset)));
  2112     else if (!strcmp(aTopic, "child-gc-request")){
  2113         unused << SendGarbageCollect();
  2115     else if (!strcmp(aTopic, "child-cc-request")){
  2116         unused << SendCycleCollect();
  2118     else if (!strcmp(aTopic, "child-mmu-request")){
  2119         unused << SendMinimizeMemoryUsage();
  2121     else if (!strcmp(aTopic, "last-pb-context-exited")) {
  2122         unused << SendLastPrivateDocShellDestroyed();
  2124     else if (!strcmp(aTopic, "file-watcher-update")) {
  2125         nsCString creason;
  2126         CopyUTF16toUTF8(aData, creason);
  2127         DeviceStorageFile* file = static_cast<DeviceStorageFile*>(aSubject);
  2129         unused << SendFilePathUpdate(file->mStorageType, file->mStorageName, file->mPath, creason);
  2131 #ifdef MOZ_WIDGET_GONK
  2132     else if(!strcmp(aTopic, NS_VOLUME_STATE_CHANGED)) {
  2133         nsCOMPtr<nsIVolume> vol = do_QueryInterface(aSubject);
  2134         if (!vol) {
  2135             return NS_ERROR_NOT_AVAILABLE;
  2138         nsString volName;
  2139         nsString mountPoint;
  2140         int32_t  state;
  2141         int32_t  mountGeneration;
  2142         bool     isMediaPresent;
  2143         bool     isSharing;
  2144         bool     isFormatting;
  2146         vol->GetName(volName);
  2147         vol->GetMountPoint(mountPoint);
  2148         vol->GetState(&state);
  2149         vol->GetMountGeneration(&mountGeneration);
  2150         vol->GetIsMediaPresent(&isMediaPresent);
  2151         vol->GetIsSharing(&isSharing);
  2152         vol->GetIsFormatting(&isFormatting);
  2154         unused << SendFileSystemUpdate(volName, mountPoint, state,
  2155                                        mountGeneration, isMediaPresent,
  2156                                        isSharing, isFormatting);
  2157     } else if (!strcmp(aTopic, "phone-state-changed")) {
  2158         nsString state(aData);
  2159         unused << SendNotifyPhoneStateChange(state);
  2161 #endif
  2162 #ifdef ACCESSIBILITY
  2163     // Make sure accessibility is running in content process when accessibility
  2164     // gets initiated in chrome process.
  2165     else if (aData && (*aData == '1') &&
  2166              !strcmp(aTopic, "a11y-init-or-shutdown")) {
  2167         unused << SendActivateA11y();
  2169 #endif
  2171     return NS_OK;
  2174 PCompositorParent*
  2175 ContentParent::AllocPCompositorParent(mozilla::ipc::Transport* aTransport,
  2176                                       base::ProcessId aOtherProcess)
  2178     return CompositorParent::Create(aTransport, aOtherProcess);
  2181 PImageBridgeParent*
  2182 ContentParent::AllocPImageBridgeParent(mozilla::ipc::Transport* aTransport,
  2183                                        base::ProcessId aOtherProcess)
  2185     return ImageBridgeParent::Create(aTransport, aOtherProcess);
  2188 PBackgroundParent*
  2189 ContentParent::AllocPBackgroundParent(Transport* aTransport,
  2190                                       ProcessId aOtherProcess)
  2192     return BackgroundParent::Alloc(this, aTransport, aOtherProcess);
  2195 bool
  2196 ContentParent::RecvGetProcessAttributes(uint64_t* aId,
  2197                                         bool* aIsForApp, bool* aIsForBrowser)
  2199     *aId = mChildID;
  2200     *aIsForApp = IsForApp();
  2201     *aIsForBrowser = mIsForBrowser;
  2203     return true;
  2206 bool
  2207 ContentParent::RecvGetXPCOMProcessAttributes(bool* aIsOffline)
  2209     nsCOMPtr<nsIIOService> io(do_GetIOService());
  2210     NS_ASSERTION(io, "No IO service?");
  2211     DebugOnly<nsresult> rv = io->GetOffline(aIsOffline);
  2212     NS_ASSERTION(NS_SUCCEEDED(rv), "Failed getting offline?");
  2214     return true;
  2217 mozilla::jsipc::PJavaScriptParent *
  2218 ContentParent::AllocPJavaScriptParent()
  2220     mozilla::jsipc::JavaScriptParent *parent = new mozilla::jsipc::JavaScriptParent();
  2221     if (!parent->init()) {
  2222         delete parent;
  2223         return nullptr;
  2225     return parent;
  2228 bool
  2229 ContentParent::DeallocPJavaScriptParent(PJavaScriptParent *parent)
  2231     static_cast<mozilla::jsipc::JavaScriptParent *>(parent)->decref();
  2232     return true;
  2235 PBrowserParent*
  2236 ContentParent::AllocPBrowserParent(const IPCTabContext& aContext,
  2237                                    const uint32_t &aChromeFlags)
  2239     unused << aChromeFlags;
  2241     const IPCTabAppBrowserContext& appBrowser = aContext.appBrowserContext();
  2243     // We don't trust the IPCTabContext we receive from the child, so we'll bail
  2244     // if we receive an IPCTabContext that's not a PopupIPCTabContext.
  2245     // (PopupIPCTabContext lets the child process prove that it has access to
  2246     // the app it's trying to open.)
  2247     if (appBrowser.type() != IPCTabAppBrowserContext::TPopupIPCTabContext) {
  2248         NS_ERROR("Unexpected IPCTabContext type.  Aborting AllocPBrowserParent.");
  2249         return nullptr;
  2252     const PopupIPCTabContext& popupContext = appBrowser.get_PopupIPCTabContext();
  2253     TabParent* opener = static_cast<TabParent*>(popupContext.openerParent());
  2254     if (!opener) {
  2255         NS_ERROR("Got null opener from child; aborting AllocPBrowserParent.");
  2256         return nullptr;
  2259     // Popup windows of isBrowser frames must be isBrowser if the parent
  2260     // isBrowser.  Allocating a !isBrowser frame with same app ID would allow
  2261     // the content to access data it's not supposed to.
  2262     if (!popupContext.isBrowserElement() && opener->IsBrowserElement()) {
  2263         NS_ERROR("Child trying to escalate privileges!  Aborting AllocPBrowserParent.");
  2264         return nullptr;
  2267     MaybeInvalidTabContext tc(aContext);
  2268     if (!tc.IsValid()) {
  2269         NS_ERROR(nsPrintfCString("Child passed us an invalid TabContext.  (%s)  "
  2270                                  "Aborting AllocPBrowserParent.",
  2271                                  tc.GetInvalidReason()).get());
  2272         return nullptr;
  2275     TabParent* parent = new TabParent(this, tc.GetTabContext(), aChromeFlags);
  2277     // We release this ref in DeallocPBrowserParent()
  2278     NS_ADDREF(parent);
  2279     return parent;
  2282 bool
  2283 ContentParent::DeallocPBrowserParent(PBrowserParent* frame)
  2285     TabParent* parent = static_cast<TabParent*>(frame);
  2286     NS_RELEASE(parent);
  2287     return true;
  2290 PDeviceStorageRequestParent*
  2291 ContentParent::AllocPDeviceStorageRequestParent(const DeviceStorageParams& aParams)
  2293   nsRefPtr<DeviceStorageRequestParent> result = new DeviceStorageRequestParent(aParams);
  2294   if (!result->EnsureRequiredPermissions(this)) {
  2295       return nullptr;
  2297   result->Dispatch();
  2298   return result.forget().take();
  2301 bool
  2302 ContentParent::DeallocPDeviceStorageRequestParent(PDeviceStorageRequestParent* doomed)
  2304   DeviceStorageRequestParent *parent = static_cast<DeviceStorageRequestParent*>(doomed);
  2305   NS_RELEASE(parent);
  2306   return true;
  2309 PFileSystemRequestParent*
  2310 ContentParent::AllocPFileSystemRequestParent(const FileSystemParams& aParams)
  2312   nsRefPtr<FileSystemRequestParent> result = new FileSystemRequestParent();
  2313   if (!result->Dispatch(this, aParams)) {
  2314     return nullptr;
  2316   return result.forget().take();
  2319 bool
  2320 ContentParent::DeallocPFileSystemRequestParent(PFileSystemRequestParent* doomed)
  2322   FileSystemRequestParent* parent = static_cast<FileSystemRequestParent*>(doomed);
  2323   NS_RELEASE(parent);
  2324   return true;
  2327 PBlobParent*
  2328 ContentParent::AllocPBlobParent(const BlobConstructorParams& aParams)
  2330   return BlobParent::Create(this, aParams);
  2333 bool
  2334 ContentParent::DeallocPBlobParent(PBlobParent* aActor)
  2336   delete aActor;
  2337   return true;
  2340 BlobParent*
  2341 ContentParent::GetOrCreateActorForBlob(nsIDOMBlob* aBlob)
  2343   MOZ_ASSERT(NS_IsMainThread());
  2344   MOZ_ASSERT(aBlob);
  2346   // If the blob represents a remote blob for this ContentParent then we can
  2347   // simply pass its actor back here.
  2348   if (nsCOMPtr<nsIRemoteBlob> remoteBlob = do_QueryInterface(aBlob)) {
  2349     if (BlobParent* actor = static_cast<BlobParent*>(
  2350           static_cast<PBlobParent*>(remoteBlob->GetPBlob()))) {
  2351       if (static_cast<ContentParent*>(actor->Manager()) == this) {
  2352         return actor;
  2357   // XXX This is only safe so long as all blob implementations in our tree
  2358   //     inherit nsDOMFileBase. If that ever changes then this will need to grow
  2359   //     a real interface or something.
  2360   const nsDOMFileBase* blob = static_cast<nsDOMFileBase*>(aBlob);
  2362   // We often pass blobs that are multipart but that only contain one sub-blob
  2363   // (WebActivities does this a bunch). Unwrap to reduce the number of actors
  2364   // that we have to maintain.
  2365   const nsTArray<nsCOMPtr<nsIDOMBlob> >* subBlobs = blob->GetSubBlobs();
  2366   if (subBlobs && subBlobs->Length() == 1) {
  2367     const nsCOMPtr<nsIDOMBlob>& subBlob = subBlobs->ElementAt(0);
  2368     MOZ_ASSERT(subBlob);
  2370     // We can only take this shortcut if the multipart and the sub-blob are both
  2371     // Blob objects or both File objects.
  2372     nsCOMPtr<nsIDOMFile> multipartBlobAsFile = do_QueryInterface(aBlob);
  2373     nsCOMPtr<nsIDOMFile> subBlobAsFile = do_QueryInterface(subBlob);
  2374     if (!multipartBlobAsFile == !subBlobAsFile) {
  2375       // The wrapping might have been unnecessary, see if we can simply pass an
  2376       // existing remote blob for this ContentParent.
  2377       if (nsCOMPtr<nsIRemoteBlob> remoteSubBlob = do_QueryInterface(subBlob)) {
  2378         BlobParent* actor =
  2379           static_cast<BlobParent*>(
  2380             static_cast<PBlobParent*>(remoteSubBlob->GetPBlob()));
  2381         MOZ_ASSERT(actor);
  2383         if (static_cast<ContentParent*>(actor->Manager()) == this) {
  2384           return actor;
  2388       // No need to add a reference here since the original blob must have a
  2389       // strong reference in the caller and it must also have a strong reference
  2390       // to this sub-blob.
  2391       aBlob = subBlob;
  2392       blob = static_cast<nsDOMFileBase*>(aBlob);
  2393       subBlobs = blob->GetSubBlobs();
  2397   // All blobs shared between processes must be immutable.
  2398   nsCOMPtr<nsIMutable> mutableBlob = do_QueryInterface(aBlob);
  2399   if (!mutableBlob || NS_FAILED(mutableBlob->SetMutable(false))) {
  2400     NS_WARNING("Failed to make blob immutable!");
  2401     return nullptr;
  2404   ChildBlobConstructorParams params;
  2406   if (blob->IsSizeUnknown() || blob->IsDateUnknown()) {
  2407     // We don't want to call GetSize or GetLastModifiedDate
  2408     // yet since that may stat a file on the main thread
  2409     // here. Instead we'll learn the size lazily from the
  2410     // other process.
  2411     params = MysteryBlobConstructorParams();
  2413   else {
  2414     nsString contentType;
  2415     nsresult rv = aBlob->GetType(contentType);
  2416     NS_ENSURE_SUCCESS(rv, nullptr);
  2418     uint64_t length;
  2419     rv = aBlob->GetSize(&length);
  2420     NS_ENSURE_SUCCESS(rv, nullptr);
  2422     nsCOMPtr<nsIDOMFile> file = do_QueryInterface(aBlob);
  2423     if (file) {
  2424       FileBlobConstructorParams fileParams;
  2426       rv = file->GetMozLastModifiedDate(&fileParams.modDate());
  2427       NS_ENSURE_SUCCESS(rv, nullptr);
  2429       rv = file->GetName(fileParams.name());
  2430       NS_ENSURE_SUCCESS(rv, nullptr);
  2432       fileParams.contentType() = contentType;
  2433       fileParams.length() = length;
  2435       params = fileParams;
  2436     } else {
  2437       NormalBlobConstructorParams blobParams;
  2438       blobParams.contentType() = contentType;
  2439       blobParams.length() = length;
  2440       params = blobParams;
  2444   BlobParent* actor = BlobParent::Create(this, aBlob);
  2445   NS_ENSURE_TRUE(actor, nullptr);
  2447   return SendPBlobConstructor(actor, params) ? actor : nullptr;
  2450 void
  2451 ContentParent::KillHard()
  2453     // On Windows, calling KillHard multiple times causes problems - the
  2454     // process handle becomes invalid on the first call, causing a second call
  2455     // to crash our process - more details in bug 890840.
  2456     if (mCalledKillHard) {
  2457         return;
  2459     mCalledKillHard = true;
  2460     mForceKillTask = nullptr;
  2461     // This ensures the process is eventually killed, but doesn't
  2462     // immediately KILLITWITHFIRE because we want to get a minidump if
  2463     // possible.  After a timeout though, the process is forceably
  2464     // killed.
  2465     if (!KillProcess(OtherProcess(), 1, false)) {
  2466         NS_WARNING("failed to kill subprocess!");
  2468     mSubprocess->SetAlreadyDead();
  2469     XRE_GetIOMessageLoop()->PostTask(
  2470         FROM_HERE,
  2471         NewRunnableFunction(&ProcessWatcher::EnsureProcessTerminated,
  2472                             OtherProcess(), /*force=*/true));
  2473     //We do clean-up here 
  2474     MessageLoop::current()->PostDelayedTask(
  2475         FROM_HERE,
  2476         NewRunnableMethod(this, &ContentParent::ShutDownProcess,
  2477                           /* closeWithError */ true),
  2478         3000);
  2479     // We've now closed the OtherProcess() handle, so must set it to null to
  2480     // prevent our dtor closing it twice.
  2481     SetOtherProcess(0);
  2484 bool
  2485 ContentParent::IsPreallocated()
  2487     return mAppManifestURL == MAGIC_PREALLOCATED_APP_MANIFEST_URL;
  2490 void
  2491 ContentParent::FriendlyName(nsAString& aName)
  2493     aName.Truncate();
  2494 #ifdef MOZ_NUWA_PROCESS
  2495     if (IsNuwaProcess()) {
  2496         aName.AssignLiteral("(Nuwa)");
  2497     } else
  2498 #endif
  2499     if (IsPreallocated()) {
  2500         aName.AssignLiteral("(Preallocated)");
  2501     } else if (mIsForBrowser) {
  2502         aName.AssignLiteral("Browser");
  2503     } else if (!mAppName.IsEmpty()) {
  2504         aName = mAppName;
  2505     } else if (!mAppManifestURL.IsEmpty()) {
  2506         aName.AssignLiteral("Unknown app: ");
  2507         aName.Append(mAppManifestURL);
  2508     } else {
  2509         aName.AssignLiteral("???");
  2513 PCrashReporterParent*
  2514 ContentParent::AllocPCrashReporterParent(const NativeThreadId& tid,
  2515                                          const uint32_t& processType)
  2517 #ifdef MOZ_CRASHREPORTER
  2518   return new CrashReporterParent();
  2519 #else
  2520   return nullptr;
  2521 #endif
  2524 bool
  2525 ContentParent::RecvPCrashReporterConstructor(PCrashReporterParent* actor,
  2526                                              const NativeThreadId& tid,
  2527                                              const uint32_t& processType)
  2529   static_cast<CrashReporterParent*>(actor)->SetChildData(tid, processType);
  2530   return true;
  2533 bool
  2534 ContentParent::DeallocPCrashReporterParent(PCrashReporterParent* crashreporter)
  2536   delete crashreporter;
  2537   return true;
  2540 hal_sandbox::PHalParent*
  2541 ContentParent::AllocPHalParent()
  2543     return hal_sandbox::CreateHalParent();
  2546 bool
  2547 ContentParent::DeallocPHalParent(hal_sandbox::PHalParent* aHal)
  2549     delete aHal;
  2550     return true;
  2553 PIndexedDBParent*
  2554 ContentParent::AllocPIndexedDBParent()
  2556   return new IndexedDBParent(this);
  2559 bool
  2560 ContentParent::DeallocPIndexedDBParent(PIndexedDBParent* aActor)
  2562   delete aActor;
  2563   return true;
  2566 bool
  2567 ContentParent::RecvPIndexedDBConstructor(PIndexedDBParent* aActor)
  2569   nsRefPtr<IndexedDatabaseManager> mgr = IndexedDatabaseManager::GetOrCreate();
  2570   NS_ENSURE_TRUE(mgr, false);
  2572   if (!IndexedDatabaseManager::IsMainProcess()) {
  2573     NS_RUNTIMEABORT("Not supported yet!");
  2576   nsRefPtr<IDBFactory> factory;
  2577   nsresult rv = IDBFactory::Create(this, getter_AddRefs(factory));
  2578   NS_ENSURE_SUCCESS(rv, false);
  2580   NS_ASSERTION(factory, "This should never be null!");
  2582   IndexedDBParent* actor = static_cast<IndexedDBParent*>(aActor);
  2583   actor->mFactory = factory;
  2584   actor->mASCIIOrigin = factory->GetASCIIOrigin();
  2586   return true;
  2589 PMemoryReportRequestParent*
  2590 ContentParent::AllocPMemoryReportRequestParent(const uint32_t& generation,
  2591                                                const bool &minimizeMemoryUsage,
  2592                                                const nsString &aDMDDumpIdent)
  2594   MemoryReportRequestParent* parent = new MemoryReportRequestParent();
  2595   return parent;
  2598 bool
  2599 ContentParent::DeallocPMemoryReportRequestParent(PMemoryReportRequestParent* actor)
  2601   delete actor;
  2602   return true;
  2605 PTestShellParent*
  2606 ContentParent::AllocPTestShellParent()
  2608   return new TestShellParent();
  2611 bool
  2612 ContentParent::DeallocPTestShellParent(PTestShellParent* shell)
  2614   delete shell;
  2615   return true;
  2618 PNeckoParent*
  2619 ContentParent::AllocPNeckoParent()
  2621     return new NeckoParent();
  2624 bool
  2625 ContentParent::DeallocPNeckoParent(PNeckoParent* necko)
  2627     delete necko;
  2628     return true;
  2631 PExternalHelperAppParent*
  2632 ContentParent::AllocPExternalHelperAppParent(const OptionalURIParams& uri,
  2633                                              const nsCString& aMimeContentType,
  2634                                              const nsCString& aContentDisposition,
  2635                                              const uint32_t& aContentDispositionHint,
  2636                                              const nsString& aContentDispositionFilename,
  2637                                              const bool& aForceSave,
  2638                                              const int64_t& aContentLength,
  2639                                              const OptionalURIParams& aReferrer,
  2640                                              PBrowserParent* aBrowser)
  2642     ExternalHelperAppParent *parent = new ExternalHelperAppParent(uri, aContentLength);
  2643     parent->AddRef();
  2644     parent->Init(this, 
  2645                  aMimeContentType, 
  2646                  aContentDisposition,
  2647                  aContentDispositionHint,
  2648                  aContentDispositionFilename,
  2649                  aForceSave, 
  2650                  aReferrer, 
  2651                  aBrowser);
  2652     return parent;
  2655 bool
  2656 ContentParent::DeallocPExternalHelperAppParent(PExternalHelperAppParent* aService)
  2658     ExternalHelperAppParent *parent = static_cast<ExternalHelperAppParent *>(aService);
  2659     parent->Release();
  2660     return true;
  2663 PSmsParent*
  2664 ContentParent::AllocPSmsParent()
  2666     if (!AssertAppProcessPermission(this, "sms")) {
  2667         return nullptr;
  2670     SmsParent* parent = new SmsParent();
  2671     parent->AddRef();
  2672     return parent;
  2675 bool
  2676 ContentParent::DeallocPSmsParent(PSmsParent* aSms)
  2678     static_cast<SmsParent*>(aSms)->Release();
  2679     return true;
  2682 PTelephonyParent*
  2683 ContentParent::AllocPTelephonyParent()
  2685     if (!AssertAppProcessPermission(this, "telephony")) {
  2686         return nullptr;
  2689     TelephonyParent* actor = new TelephonyParent();
  2690     NS_ADDREF(actor);
  2691     return actor;
  2694 bool
  2695 ContentParent::DeallocPTelephonyParent(PTelephonyParent* aActor)
  2697     static_cast<TelephonyParent*>(aActor)->Release();
  2698     return true;
  2701 PStorageParent*
  2702 ContentParent::AllocPStorageParent()
  2704     return new DOMStorageDBParent();
  2707 bool
  2708 ContentParent::DeallocPStorageParent(PStorageParent* aActor)
  2710     DOMStorageDBParent* child = static_cast<DOMStorageDBParent*>(aActor);
  2711     child->ReleaseIPDLReference();
  2712     return true;
  2715 PBluetoothParent*
  2716 ContentParent::AllocPBluetoothParent()
  2718 #ifdef MOZ_B2G_BT
  2719     if (!AssertAppProcessPermission(this, "bluetooth")) {
  2720         return nullptr;
  2722     return new mozilla::dom::bluetooth::BluetoothParent();
  2723 #else
  2724     MOZ_CRASH("No support for bluetooth on this platform!");
  2725 #endif
  2728 bool
  2729 ContentParent::DeallocPBluetoothParent(PBluetoothParent* aActor)
  2731 #ifdef MOZ_B2G_BT
  2732     delete aActor;
  2733     return true;
  2734 #else
  2735     MOZ_CRASH("No support for bluetooth on this platform!");
  2736 #endif
  2739 bool
  2740 ContentParent::RecvPBluetoothConstructor(PBluetoothParent* aActor)
  2742 #ifdef MOZ_B2G_BT
  2743     nsRefPtr<BluetoothService> btService = BluetoothService::Get();
  2744     NS_ENSURE_TRUE(btService, false);
  2746     return static_cast<BluetoothParent*>(aActor)->InitWithService(btService);
  2747 #else
  2748     MOZ_CRASH("No support for bluetooth on this platform!");
  2749 #endif
  2752 PFMRadioParent*
  2753 ContentParent::AllocPFMRadioParent()
  2755 #ifdef MOZ_B2G_FM
  2756     if (!AssertAppProcessPermission(this, "fmradio")) {
  2757         return nullptr;
  2759     return new FMRadioParent();
  2760 #else
  2761     NS_WARNING("No support for FMRadio on this platform!");
  2762     return nullptr;
  2763 #endif
  2766 bool
  2767 ContentParent::DeallocPFMRadioParent(PFMRadioParent* aActor)
  2769 #ifdef MOZ_B2G_FM
  2770     delete aActor;
  2771     return true;
  2772 #else
  2773     NS_WARNING("No support for FMRadio on this platform!");
  2774     return false;
  2775 #endif
  2778 asmjscache::PAsmJSCacheEntryParent*
  2779 ContentParent::AllocPAsmJSCacheEntryParent(
  2780                                     const asmjscache::OpenMode& aOpenMode,
  2781                                     const asmjscache::WriteParams& aWriteParams,
  2782                                     const IPC::Principal& aPrincipal)
  2784   return asmjscache::AllocEntryParent(aOpenMode, aWriteParams, aPrincipal);
  2787 bool
  2788 ContentParent::DeallocPAsmJSCacheEntryParent(PAsmJSCacheEntryParent* aActor)
  2790   asmjscache::DeallocEntryParent(aActor);
  2791   return true;
  2794 PSpeechSynthesisParent*
  2795 ContentParent::AllocPSpeechSynthesisParent()
  2797 #ifdef MOZ_WEBSPEECH
  2798     return new mozilla::dom::SpeechSynthesisParent();
  2799 #else
  2800     return nullptr;
  2801 #endif
  2804 bool
  2805 ContentParent::DeallocPSpeechSynthesisParent(PSpeechSynthesisParent* aActor)
  2807 #ifdef MOZ_WEBSPEECH
  2808     delete aActor;
  2809     return true;
  2810 #else
  2811     return false;
  2812 #endif
  2815 bool
  2816 ContentParent::RecvPSpeechSynthesisConstructor(PSpeechSynthesisParent* aActor)
  2818 #ifdef MOZ_WEBSPEECH
  2819     return true;
  2820 #else
  2821     return false;
  2822 #endif
  2825 bool
  2826 ContentParent::RecvSpeakerManagerGetSpeakerStatus(bool* aValue)
  2828 #ifdef MOZ_WIDGET_GONK
  2829   *aValue = false;
  2830   nsRefPtr<SpeakerManagerService> service =
  2831     SpeakerManagerService::GetSpeakerManagerService();
  2832   if (service) {
  2833     *aValue = service->GetSpeakerStatus();
  2835   return true;
  2836 #endif
  2837   return false;
  2840 bool
  2841 ContentParent::RecvSpeakerManagerForceSpeaker(const bool& aEnable)
  2843 #ifdef MOZ_WIDGET_GONK
  2844   nsRefPtr<SpeakerManagerService> service =
  2845     SpeakerManagerService::GetSpeakerManagerService();
  2846   if (service) {
  2847     service->ForceSpeaker(aEnable, mChildID);
  2849   return true;
  2850 #endif
  2851   return false;
  2854 bool
  2855 ContentParent::RecvStartVisitedQuery(const URIParams& aURI)
  2857     nsCOMPtr<nsIURI> newURI = DeserializeURI(aURI);
  2858     if (!newURI) {
  2859         return false;
  2861     nsCOMPtr<IHistory> history = services::GetHistoryService();
  2862     if (history) {
  2863         history->RegisterVisitedCallback(newURI, nullptr);
  2865     return true;
  2869 bool
  2870 ContentParent::RecvVisitURI(const URIParams& uri,
  2871                             const OptionalURIParams& referrer,
  2872                             const uint32_t& flags)
  2874     nsCOMPtr<nsIURI> ourURI = DeserializeURI(uri);
  2875     if (!ourURI) {
  2876         return false;
  2878     nsCOMPtr<nsIURI> ourReferrer = DeserializeURI(referrer);
  2879     nsCOMPtr<IHistory> history = services::GetHistoryService();
  2880     if (history) {
  2881         history->VisitURI(ourURI, ourReferrer, flags);
  2883     return true;
  2887 bool
  2888 ContentParent::RecvSetURITitle(const URIParams& uri,
  2889                                const nsString& title)
  2891     nsCOMPtr<nsIURI> ourURI = DeserializeURI(uri);
  2892     if (!ourURI) {
  2893         return false;
  2895     nsCOMPtr<IHistory> history = services::GetHistoryService();
  2896     if (history) {
  2897         history->SetURITitle(ourURI, title);
  2899     return true;
  2902 bool
  2903 ContentParent::RecvGetRandomValues(const uint32_t& length,
  2904                                    InfallibleTArray<uint8_t>* randomValues)
  2906     uint8_t* buf = Crypto::GetRandomValues(length);
  2907     if (!buf) {
  2908         return true;
  2911     randomValues->SetCapacity(length);
  2912     randomValues->SetLength(length);
  2914     memcpy(randomValues->Elements(), buf, length);
  2916     NS_Free(buf);
  2918     return true;
  2921 bool
  2922 ContentParent::RecvLoadURIExternal(const URIParams& uri)
  2924     nsCOMPtr<nsIExternalProtocolService> extProtService(do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID));
  2925     if (!extProtService) {
  2926         return true;
  2928     nsCOMPtr<nsIURI> ourURI = DeserializeURI(uri);
  2929     if (!ourURI) {
  2930         return false;
  2932     extProtService->LoadURI(ourURI, nullptr);
  2933     return true;
  2936 bool
  2937 ContentParent::RecvShowAlertNotification(const nsString& aImageUrl, const nsString& aTitle,
  2938                                          const nsString& aText, const bool& aTextClickable,
  2939                                          const nsString& aCookie, const nsString& aName,
  2940                                          const nsString& aBidi, const nsString& aLang,
  2941                                          const IPC::Principal& aPrincipal)
  2943 #ifdef MOZ_CHILD_PERMISSIONS
  2944     uint32_t permission = mozilla::CheckPermission(this, aPrincipal,
  2945                                                    "desktop-notification");
  2946     if (permission != nsIPermissionManager::ALLOW_ACTION) {
  2947         return true;
  2949 #endif /* MOZ_CHILD_PERMISSIONS */
  2951     nsCOMPtr<nsIAlertsService> sysAlerts(do_GetService(NS_ALERTSERVICE_CONTRACTID));
  2952     if (sysAlerts) {
  2953         sysAlerts->ShowAlertNotification(aImageUrl, aTitle, aText, aTextClickable,
  2954                                          aCookie, this, aName, aBidi, aLang, aPrincipal);
  2956     return true;
  2959 bool
  2960 ContentParent::RecvCloseAlert(const nsString& aName,
  2961                               const IPC::Principal& aPrincipal)
  2963 #ifdef MOZ_CHILD_PERMISSIONS
  2964     uint32_t permission = mozilla::CheckPermission(this, aPrincipal,
  2965                                                    "desktop-notification");
  2966     if (permission != nsIPermissionManager::ALLOW_ACTION) {
  2967         return true;
  2969 #endif
  2971     nsCOMPtr<nsIAlertsService> sysAlerts(do_GetService(NS_ALERTSERVICE_CONTRACTID));
  2972     if (sysAlerts) {
  2973         sysAlerts->CloseAlert(aName, aPrincipal);
  2976     return true;
  2979 bool
  2980 ContentParent::RecvSyncMessage(const nsString& aMsg,
  2981                                const ClonedMessageData& aData,
  2982                                const InfallibleTArray<CpowEntry>& aCpows,
  2983                                const IPC::Principal& aPrincipal,
  2984                                InfallibleTArray<nsString>* aRetvals)
  2986   nsIPrincipal* principal = aPrincipal;
  2987   if (!Preferences::GetBool("dom.testing.ignore_ipc_principal", false) &&
  2988       principal && !AssertAppPrincipal(this, principal)) {
  2989     return false;
  2992   nsRefPtr<nsFrameMessageManager> ppm = mMessageManager;
  2993   if (ppm) {
  2994     StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData);
  2995     CpowIdHolder cpows(GetCPOWManager(), aCpows);
  2997     ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()),
  2998                         aMsg, true, &cloneData, &cpows, aPrincipal, aRetvals);
  3000   return true;
  3003 bool
  3004 ContentParent::AnswerRpcMessage(const nsString& aMsg,
  3005                                 const ClonedMessageData& aData,
  3006                                 const InfallibleTArray<CpowEntry>& aCpows,
  3007                                 const IPC::Principal& aPrincipal,
  3008                                 InfallibleTArray<nsString>* aRetvals)
  3010   nsIPrincipal* principal = aPrincipal;
  3011   if (!Preferences::GetBool("dom.testing.ignore_ipc_principal", false) &&
  3012       principal && !AssertAppPrincipal(this, principal)) {
  3013     return false;
  3016   nsRefPtr<nsFrameMessageManager> ppm = mMessageManager;
  3017   if (ppm) {
  3018     StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData);
  3019     CpowIdHolder cpows(GetCPOWManager(), aCpows);
  3020     ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()),
  3021                         aMsg, true, &cloneData, &cpows, aPrincipal, aRetvals);
  3023   return true;
  3026 bool
  3027 ContentParent::RecvAsyncMessage(const nsString& aMsg,
  3028                                 const ClonedMessageData& aData,
  3029                                 const InfallibleTArray<CpowEntry>& aCpows,
  3030                                 const IPC::Principal& aPrincipal)
  3032   nsIPrincipal* principal = aPrincipal;
  3033   if (!Preferences::GetBool("dom.testing.ignore_ipc_principal", false) &&
  3034       principal && !AssertAppPrincipal(this, principal)) {
  3035     return false;
  3038   nsRefPtr<nsFrameMessageManager> ppm = mMessageManager;
  3039   if (ppm) {
  3040     StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData);
  3041     CpowIdHolder cpows(GetCPOWManager(), aCpows);
  3042     ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()),
  3043                         aMsg, false, &cloneData, &cpows, aPrincipal, nullptr);
  3045   return true;
  3048 bool
  3049 ContentParent::RecvFilePathUpdateNotify(const nsString& aType,
  3050                                         const nsString& aStorageName,
  3051                                         const nsString& aFilePath,
  3052                                         const nsCString& aReason)
  3054     nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(aType,
  3055                                                             aStorageName,
  3056                                                             aFilePath);
  3058     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
  3059     if (!obs) {
  3060         return false;
  3062     obs->NotifyObservers(dsf, "file-watcher-update",
  3063                          NS_ConvertASCIItoUTF16(aReason).get());
  3064     return true;
  3067 static int32_t
  3068 AddGeolocationListener(nsIDOMGeoPositionCallback* watcher, bool highAccuracy)
  3070   nsCOMPtr<nsIDOMGeoGeolocation> geo = do_GetService("@mozilla.org/geolocation;1");
  3071   if (!geo) {
  3072     return -1;
  3075   PositionOptions* options = new PositionOptions();
  3076   options->mTimeout = 0;
  3077   options->mMaximumAge = 0;
  3078   options->mEnableHighAccuracy = highAccuracy;
  3079   int32_t retval = 1;
  3080   geo->WatchPosition(watcher, nullptr, options, &retval);
  3081   return retval;
  3084 bool
  3085 ContentParent::RecvAddGeolocationListener(const IPC::Principal& aPrincipal,
  3086                                           const bool& aHighAccuracy)
  3088 #ifdef MOZ_CHILD_PERMISSIONS
  3089   if (!Preferences::GetBool("dom.testing.ignore_ipc_principal", false)) {
  3090     uint32_t permission = mozilla::CheckPermission(this, aPrincipal,
  3091                                                    "geolocation");
  3092     if (permission != nsIPermissionManager::ALLOW_ACTION) {
  3093       return true;
  3096 #endif /* MOZ_CHILD_PERMISSIONS */
  3098   // To ensure no geolocation updates are skipped, we always force the
  3099   // creation of a new listener.
  3100   RecvRemoveGeolocationListener();
  3101   mGeolocationWatchID = AddGeolocationListener(this, aHighAccuracy);
  3102   return true;
  3105 bool
  3106 ContentParent::RecvRemoveGeolocationListener()
  3108   if (mGeolocationWatchID != -1) {
  3109     nsCOMPtr<nsIDOMGeoGeolocation> geo = do_GetService("@mozilla.org/geolocation;1");
  3110     if (!geo) {
  3111       return true;
  3113     geo->ClearWatch(mGeolocationWatchID);
  3114     mGeolocationWatchID = -1;
  3116   return true;
  3119 bool
  3120 ContentParent::RecvSetGeolocationHigherAccuracy(const bool& aEnable)
  3122   // This should never be called without a listener already present,
  3123   // so this check allows us to forgo securing privileges.
  3124   if (mGeolocationWatchID != -1) {
  3125     RecvRemoveGeolocationListener();
  3126     mGeolocationWatchID = AddGeolocationListener(this, aEnable);
  3128   return true;
  3131 NS_IMETHODIMP
  3132 ContentParent::HandleEvent(nsIDOMGeoPosition* postion)
  3134   unused << SendGeolocationUpdate(GeoPosition(postion));
  3135   return NS_OK;
  3138 nsConsoleService *
  3139 ContentParent::GetConsoleService()
  3141     if (mConsoleService) {
  3142         return mConsoleService.get();
  3145     // Get the ConsoleService by CID rather than ContractID, so that we
  3146     // can cast the returned pointer to an nsConsoleService (rather than
  3147     // just an nsIConsoleService). This allows us to call the non-idl function
  3148     // nsConsoleService::LogMessageWithMode.
  3149     NS_DEFINE_CID(consoleServiceCID, NS_CONSOLESERVICE_CID);
  3150     nsCOMPtr<nsConsoleService>  consoleService(do_GetService(consoleServiceCID));
  3151     mConsoleService = consoleService;
  3152     return mConsoleService.get();
  3155 bool
  3156 ContentParent::RecvConsoleMessage(const nsString& aMessage)
  3158   nsRefPtr<nsConsoleService> consoleService = GetConsoleService();
  3159   if (!consoleService) {
  3160     return true;
  3163   nsRefPtr<nsConsoleMessage> msg(new nsConsoleMessage(aMessage.get()));
  3164   consoleService->LogMessageWithMode(msg, nsConsoleService::SuppressLog);
  3165   return true;
  3168 bool
  3169 ContentParent::RecvScriptError(const nsString& aMessage,
  3170                                       const nsString& aSourceName,
  3171                                       const nsString& aSourceLine,
  3172                                       const uint32_t& aLineNumber,
  3173                                       const uint32_t& aColNumber,
  3174                                       const uint32_t& aFlags,
  3175                                       const nsCString& aCategory)
  3177   nsRefPtr<nsConsoleService> consoleService = GetConsoleService();
  3178   if (!consoleService) {
  3179     return true;
  3182   nsCOMPtr<nsIScriptError> msg(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
  3183   nsresult rv = msg->Init(aMessage, aSourceName, aSourceLine,
  3184                           aLineNumber, aColNumber, aFlags, aCategory.get());
  3185   if (NS_FAILED(rv))
  3186     return true;
  3188   consoleService->LogMessageWithMode(msg, nsConsoleService::SuppressLog);
  3189   return true;
  3192 bool
  3193 ContentParent::RecvPrivateDocShellsExist(const bool& aExist)
  3195   if (!sPrivateContent)
  3196     sPrivateContent = new nsTArray<ContentParent*>();
  3197   if (aExist) {
  3198     sPrivateContent->AppendElement(this);
  3199   } else {
  3200     sPrivateContent->RemoveElement(this);
  3201     if (!sPrivateContent->Length()) {
  3202       nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
  3203       obs->NotifyObservers(nullptr, "last-pb-context-exited", nullptr);
  3204       delete sPrivateContent;
  3205       sPrivateContent = nullptr;
  3208   return true;
  3211 bool
  3212 ContentParent::DoSendAsyncMessage(JSContext* aCx,
  3213                                   const nsAString& aMessage,
  3214                                   const mozilla::dom::StructuredCloneData& aData,
  3215                                   JS::Handle<JSObject *> aCpows,
  3216                                   nsIPrincipal* aPrincipal)
  3218   ClonedMessageData data;
  3219   if (!BuildClonedMessageDataForParent(this, aData, data)) {
  3220     return false;
  3222   InfallibleTArray<CpowEntry> cpows;
  3223   if (!GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) {
  3224     return false;
  3226   return SendAsyncMessage(nsString(aMessage), data, cpows, aPrincipal);
  3229 bool
  3230 ContentParent::CheckPermission(const nsAString& aPermission)
  3232   return AssertAppProcessPermission(this, NS_ConvertUTF16toUTF8(aPermission).get());
  3235 bool
  3236 ContentParent::CheckManifestURL(const nsAString& aManifestURL)
  3238   return AssertAppProcessManifestURL(this, NS_ConvertUTF16toUTF8(aManifestURL).get());
  3241 bool
  3242 ContentParent::CheckAppHasPermission(const nsAString& aPermission)
  3244   return AssertAppHasPermission(this, NS_ConvertUTF16toUTF8(aPermission).get());
  3247 bool
  3248 ContentParent::CheckAppHasStatus(unsigned short aStatus)
  3250   return AssertAppHasStatus(this, aStatus);
  3253 bool
  3254 ContentParent::RecvSystemMessageHandled()
  3256     SystemMessageHandledListener::OnSystemMessageHandled();
  3257     return true;
  3260 bool
  3261 ContentParent::RecvCreateFakeVolume(const nsString& fsName, const nsString& mountPoint)
  3263 #ifdef MOZ_WIDGET_GONK
  3264   nsresult rv;
  3265   nsCOMPtr<nsIVolumeService> vs = do_GetService(NS_VOLUMESERVICE_CONTRACTID, &rv);
  3266   if (vs) {
  3267     vs->CreateFakeVolume(fsName, mountPoint);
  3269   return true;
  3270 #else
  3271   NS_WARNING("ContentParent::RecvCreateFakeVolume shouldn't be called when MOZ_WIDGET_GONK is not defined");
  3272   return false;
  3273 #endif
  3276 bool
  3277 ContentParent::RecvSetFakeVolumeState(const nsString& fsName, const int32_t& fsState)
  3279 #ifdef MOZ_WIDGET_GONK
  3280   nsresult rv;
  3281   nsCOMPtr<nsIVolumeService> vs = do_GetService(NS_VOLUMESERVICE_CONTRACTID, &rv);
  3282   if (vs) {
  3283     vs->SetFakeVolumeState(fsName, fsState);
  3285   return true;
  3286 #else
  3287   NS_WARNING("ContentParent::RecvSetFakeVolumeState shouldn't be called when MOZ_WIDGET_GONK is not defined");
  3288   return false;
  3289 #endif
  3292 bool
  3293 ContentParent::RecvKeywordToURI(const nsCString& aKeyword, OptionalInputStreamParams* aPostData,
  3294                                 OptionalURIParams* aURI)
  3296   nsCOMPtr<nsIURIFixup> fixup = do_GetService(NS_URIFIXUP_CONTRACTID);
  3297   if (!fixup) {
  3298     return true;
  3301   nsCOMPtr<nsIInputStream> postData;
  3302   nsCOMPtr<nsIURI> uri;
  3303   if (NS_FAILED(fixup->KeywordToURI(aKeyword, getter_AddRefs(postData),
  3304                                     getter_AddRefs(uri)))) {
  3305     return true;
  3308   nsTArray<mozilla::ipc::FileDescriptor> fds;
  3309   SerializeInputStream(postData, *aPostData, fds);
  3310   MOZ_ASSERT(fds.IsEmpty());
  3312   SerializeURI(uri, *aURI);
  3313   return true;
  3316 bool
  3317 ContentParent::ShouldContinueFromReplyTimeout()
  3319   // The only time ContentParent sends blocking messages is for CPOWs, so
  3320   // timeouts should only ever occur in electrolysis-enabled sessions.
  3321   MOZ_ASSERT(BrowserTabsRemote());
  3322   return false;
  3325 bool
  3326 ContentParent::ShouldSandboxContentProcesses()
  3328 #ifdef MOZ_CONTENT_SANDBOX
  3329   return !PR_GetEnv("MOZ_DISABLE_CONTENT_SANDBOX");
  3330 #else
  3331   return true;
  3332 #endif
  3335 bool
  3336 ContentParent::RecvRecordingDeviceEvents(const nsString& aRecordingStatus,
  3337                                          const nsString& aPageURL,
  3338                                          const bool& aIsAudio,
  3339                                          const bool& aIsVideo)
  3341     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
  3342     if (obs) {
  3343         // recording-device-ipc-events needs to gather more information from content process
  3344         nsRefPtr<nsHashPropertyBag> props = new nsHashPropertyBag();
  3345         props->SetPropertyAsUint64(NS_LITERAL_STRING("childID"), ChildID());
  3346         props->SetPropertyAsBool(NS_LITERAL_STRING("isApp"), IsForApp());
  3347         props->SetPropertyAsBool(NS_LITERAL_STRING("isAudio"), aIsAudio);
  3348         props->SetPropertyAsBool(NS_LITERAL_STRING("isVideo"), aIsVideo);
  3350         nsString requestURL = IsForApp() ? AppManifestURL() : aPageURL;
  3351         props->SetPropertyAsAString(NS_LITERAL_STRING("requestURL"), requestURL);
  3353         obs->NotifyObservers((nsIPropertyBag2*) props,
  3354                              "recording-device-ipc-events",
  3355                              aRecordingStatus.get());
  3356     } else {
  3357         NS_WARNING("Could not get the Observer service for ContentParent::RecvRecordingDeviceEvents.");
  3359     return true;
  3362 bool
  3363 ContentParent::RecvGetGraphicsFeatureStatus(const int32_t& aFeature,
  3364                                             int32_t* aStatus,
  3365                                             bool* aSuccess)
  3367     nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
  3368     if (!gfxInfo) {
  3369         *aSuccess = false;
  3370         return true;
  3373     *aSuccess = NS_SUCCEEDED(gfxInfo->GetFeatureStatus(aFeature, aStatus));
  3374     return true;
  3377 bool
  3378 ContentParent::RecvAddIdleObserver(const uint64_t& aObserver, const uint32_t& aIdleTimeInS)
  3380   nsresult rv;
  3381   nsCOMPtr<nsIIdleService> idleService =
  3382     do_GetService("@mozilla.org/widget/idleservice;1", &rv);
  3383   NS_ENSURE_SUCCESS(rv, false);
  3385   nsRefPtr<ParentIdleListener> listener = new ParentIdleListener(this, aObserver);
  3386   mIdleListeners.Put(aObserver, listener);
  3387   idleService->AddIdleObserver(listener, aIdleTimeInS);
  3388   return true;
  3391 bool
  3392 ContentParent::RecvRemoveIdleObserver(const uint64_t& aObserver, const uint32_t& aIdleTimeInS)
  3394   nsresult rv;
  3395   nsCOMPtr<nsIIdleService> idleService =
  3396     do_GetService("@mozilla.org/widget/idleservice;1", &rv);
  3397   NS_ENSURE_SUCCESS(rv, false);
  3399   nsRefPtr<ParentIdleListener> listener;
  3400   bool found = mIdleListeners.Get(aObserver, &listener);
  3401   if (found) {
  3402     mIdleListeners.Remove(aObserver);
  3403     idleService->RemoveIdleObserver(listener, aIdleTimeInS);
  3406   return true;
  3409 bool
  3410 ContentParent::RecvBackUpXResources(const FileDescriptor& aXSocketFd)
  3412 #ifndef MOZ_X11
  3413     NS_RUNTIMEABORT("This message only makes sense on X11 platforms");
  3414 #else
  3415     NS_ABORT_IF_FALSE(0 > mChildXSocketFdDup.get(),
  3416                       "Already backed up X resources??");
  3417     mChildXSocketFdDup.forget();
  3418     if (aXSocketFd.IsValid()) {
  3419       mChildXSocketFdDup.reset(aXSocketFd.PlatformHandle());
  3421 #endif
  3422     return true;
  3425 PFileDescriptorSetParent*
  3426 ContentParent::AllocPFileDescriptorSetParent(const FileDescriptor& aFD)
  3428     return new FileDescriptorSetParent(aFD);
  3431 bool
  3432 ContentParent::DeallocPFileDescriptorSetParent(PFileDescriptorSetParent* aActor)
  3434     delete static_cast<FileDescriptorSetParent*>(aActor);
  3435     return true;
  3438 } // namespace dom
  3439 } // namespace mozilla
  3441 NS_IMPL_ISUPPORTS(ParentIdleListener, nsIObserver)
  3443 NS_IMETHODIMP
  3444 ParentIdleListener::Observe(nsISupports*, const char* aTopic, const char16_t* aData) {
  3445   mozilla::unused << mParent->SendNotifyIdleObserver(mObserver,
  3446                                                      nsDependentCString(aTopic),
  3447                                                      nsDependentString(aData));
  3448   return NS_OK;

mercurial