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