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