|
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
|
2 /* vim: set sw=4 ts=8 et tw=80 : */ |
|
3 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
4 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 #ifdef MOZ_WIDGET_GTK |
|
8 #include <gtk/gtk.h> |
|
9 #endif |
|
10 |
|
11 #ifdef MOZ_WIDGET_QT |
|
12 #include "nsQAppInstance.h" |
|
13 #endif |
|
14 |
|
15 #include "ContentChild.h" |
|
16 #include "CrashReporterChild.h" |
|
17 #include "FileDescriptorSetChild.h" |
|
18 #include "TabChild.h" |
|
19 |
|
20 #include "mozilla/Attributes.h" |
|
21 #include "mozilla/dom/asmjscache/AsmJSCache.h" |
|
22 #include "mozilla/dom/asmjscache/PAsmJSCacheEntryChild.h" |
|
23 #include "mozilla/dom/ExternalHelperAppChild.h" |
|
24 #include "mozilla/dom/PCrashReporterChild.h" |
|
25 #include "mozilla/dom/DOMStorageIPC.h" |
|
26 #include "mozilla/hal_sandbox/PHalChild.h" |
|
27 #include "mozilla/ipc/BackgroundChild.h" |
|
28 #include "mozilla/ipc/GeckoChildProcessHost.h" |
|
29 #include "mozilla/ipc/TestShellChild.h" |
|
30 #include "mozilla/layers/CompositorChild.h" |
|
31 #include "mozilla/layers/ImageBridgeChild.h" |
|
32 #include "mozilla/layers/PCompositorChild.h" |
|
33 #include "mozilla/net/NeckoChild.h" |
|
34 #include "mozilla/Preferences.h" |
|
35 |
|
36 #if defined(MOZ_CONTENT_SANDBOX) |
|
37 #if defined(XP_WIN) |
|
38 #define TARGET_SANDBOX_EXPORTS |
|
39 #include "mozilla/sandboxTarget.h" |
|
40 #elif defined(XP_LINUX) |
|
41 #include "mozilla/Sandbox.h" |
|
42 #endif |
|
43 #endif |
|
44 |
|
45 #include "mozilla/unused.h" |
|
46 |
|
47 #include "nsIConsoleListener.h" |
|
48 #include "nsIIPCBackgroundChildCreateCallback.h" |
|
49 #include "nsIInterfaceRequestorUtils.h" |
|
50 #include "nsIMemoryReporter.h" |
|
51 #include "nsIMemoryInfoDumper.h" |
|
52 #include "nsIMutable.h" |
|
53 #include "nsIObserverService.h" |
|
54 #include "nsIScriptSecurityManager.h" |
|
55 #include "nsServiceManagerUtils.h" |
|
56 #include "nsStyleSheetService.h" |
|
57 #include "nsXULAppAPI.h" |
|
58 #include "nsIScriptError.h" |
|
59 #include "nsIConsoleService.h" |
|
60 #include "nsJSEnvironment.h" |
|
61 #include "SandboxHal.h" |
|
62 #include "nsDebugImpl.h" |
|
63 #include "nsHashPropertyBag.h" |
|
64 #include "nsLayoutStylesheetCache.h" |
|
65 #include "nsIJSRuntimeService.h" |
|
66 #include "nsThreadManager.h" |
|
67 |
|
68 #include "IHistory.h" |
|
69 #include "nsNetUtil.h" |
|
70 |
|
71 #include "base/message_loop.h" |
|
72 #include "base/process_util.h" |
|
73 #include "base/task.h" |
|
74 |
|
75 #include "nsChromeRegistryContent.h" |
|
76 #include "nsFrameMessageManager.h" |
|
77 |
|
78 #include "nsIGeolocationProvider.h" |
|
79 #include "mozilla/dom/PMemoryReportRequestChild.h" |
|
80 |
|
81 #ifdef MOZ_PERMISSIONS |
|
82 #include "nsIScriptSecurityManager.h" |
|
83 #include "nsPermission.h" |
|
84 #include "nsPermissionManager.h" |
|
85 #endif |
|
86 |
|
87 #include "PermissionMessageUtils.h" |
|
88 |
|
89 #if defined(MOZ_WIDGET_ANDROID) |
|
90 #include "APKOpen.h" |
|
91 #endif |
|
92 |
|
93 #if defined(MOZ_WIDGET_GONK) |
|
94 #include "nsVolume.h" |
|
95 #include "nsVolumeService.h" |
|
96 #include "SpeakerManagerService.h" |
|
97 #endif |
|
98 |
|
99 #ifdef XP_WIN |
|
100 #include <process.h> |
|
101 #define getpid _getpid |
|
102 #endif |
|
103 |
|
104 #ifdef MOZ_X11 |
|
105 #include "mozilla/X11Util.h" |
|
106 #endif |
|
107 |
|
108 #ifdef ACCESSIBILITY |
|
109 #include "nsIAccessibilityService.h" |
|
110 #endif |
|
111 |
|
112 #ifdef MOZ_NUWA_PROCESS |
|
113 #include <setjmp.h> |
|
114 #include "ipc/Nuwa.h" |
|
115 #endif |
|
116 |
|
117 #include "mozilla/dom/indexedDB/PIndexedDBChild.h" |
|
118 #include "mozilla/dom/mobilemessage/SmsChild.h" |
|
119 #include "mozilla/dom/devicestorage/DeviceStorageRequestChild.h" |
|
120 #include "mozilla/dom/PFileSystemRequestChild.h" |
|
121 #include "mozilla/dom/FileSystemTaskBase.h" |
|
122 #include "mozilla/dom/bluetooth/PBluetoothChild.h" |
|
123 #include "mozilla/dom/PFMRadioChild.h" |
|
124 #include "mozilla/ipc/InputStreamUtils.h" |
|
125 |
|
126 #ifdef MOZ_WEBSPEECH |
|
127 #include "mozilla/dom/PSpeechSynthesisChild.h" |
|
128 #endif |
|
129 |
|
130 #include "nsDOMFile.h" |
|
131 #include "nsIRemoteBlob.h" |
|
132 #include "ProcessUtils.h" |
|
133 #include "StructuredCloneUtils.h" |
|
134 #include "URIUtils.h" |
|
135 #include "nsContentUtils.h" |
|
136 #include "nsIPrincipal.h" |
|
137 #include "nsDeviceStorage.h" |
|
138 #include "AudioChannelService.h" |
|
139 #include "JavaScriptChild.h" |
|
140 #include "mozilla/dom/telephony/PTelephonyChild.h" |
|
141 #include "mozilla/dom/time/DateCacheCleaner.h" |
|
142 #include "mozilla/net/NeckoMessageUtils.h" |
|
143 |
|
144 using namespace base; |
|
145 using namespace mozilla; |
|
146 using namespace mozilla::docshell; |
|
147 using namespace mozilla::dom::bluetooth; |
|
148 using namespace mozilla::dom::devicestorage; |
|
149 using namespace mozilla::dom::ipc; |
|
150 using namespace mozilla::dom::mobilemessage; |
|
151 using namespace mozilla::dom::indexedDB; |
|
152 using namespace mozilla::dom::telephony; |
|
153 using namespace mozilla::hal_sandbox; |
|
154 using namespace mozilla::ipc; |
|
155 using namespace mozilla::layers; |
|
156 using namespace mozilla::net; |
|
157 using namespace mozilla::jsipc; |
|
158 #if defined(MOZ_WIDGET_GONK) |
|
159 using namespace mozilla::system; |
|
160 #endif |
|
161 |
|
162 #ifdef MOZ_NUWA_PROCESS |
|
163 static bool sNuwaForking = false; |
|
164 |
|
165 // The size of the reserved stack (in unsigned ints). It's used to reserve space |
|
166 // to push sigsetjmp() in NuwaCheckpointCurrentThread() to higher in the stack |
|
167 // so that after it returns and do other work we don't garble the stack we want |
|
168 // to preserve in NuwaCheckpointCurrentThread(). |
|
169 #define RESERVED_INT_STACK 128 |
|
170 |
|
171 // A sentinel value for checking whether RESERVED_INT_STACK is large enough. |
|
172 #define STACK_SENTINEL_VALUE 0xdeadbeef |
|
173 #endif |
|
174 |
|
175 namespace mozilla { |
|
176 namespace dom { |
|
177 |
|
178 class MemoryReportRequestChild : public PMemoryReportRequestChild, |
|
179 public nsIRunnable |
|
180 { |
|
181 public: |
|
182 NS_DECL_ISUPPORTS |
|
183 |
|
184 MemoryReportRequestChild(uint32_t aGeneration, const nsAString& aDMDDumpIdent); |
|
185 virtual ~MemoryReportRequestChild(); |
|
186 NS_IMETHOD Run(); |
|
187 private: |
|
188 uint32_t mGeneration; |
|
189 nsString mDMDDumpIdent; |
|
190 }; |
|
191 |
|
192 NS_IMPL_ISUPPORTS(MemoryReportRequestChild, nsIRunnable) |
|
193 |
|
194 MemoryReportRequestChild::MemoryReportRequestChild(uint32_t aGeneration, const nsAString& aDMDDumpIdent) |
|
195 : mGeneration(aGeneration), mDMDDumpIdent(aDMDDumpIdent) |
|
196 { |
|
197 MOZ_COUNT_CTOR(MemoryReportRequestChild); |
|
198 } |
|
199 |
|
200 MemoryReportRequestChild::~MemoryReportRequestChild() |
|
201 { |
|
202 MOZ_COUNT_DTOR(MemoryReportRequestChild); |
|
203 } |
|
204 |
|
205 class AlertObserver |
|
206 { |
|
207 public: |
|
208 |
|
209 AlertObserver(nsIObserver *aObserver, const nsString& aData) |
|
210 : mObserver(aObserver) |
|
211 , mData(aData) |
|
212 { |
|
213 } |
|
214 |
|
215 ~AlertObserver() {} |
|
216 |
|
217 bool ShouldRemoveFrom(nsIObserver* aObserver, |
|
218 const nsString& aData) const |
|
219 { |
|
220 return (mObserver == aObserver && |
|
221 mData == aData); |
|
222 } |
|
223 |
|
224 bool Observes(const nsString& aData) const |
|
225 { |
|
226 return mData.Equals(aData); |
|
227 } |
|
228 |
|
229 bool Notify(const nsCString& aType) const |
|
230 { |
|
231 mObserver->Observe(nullptr, aType.get(), mData.get()); |
|
232 return true; |
|
233 } |
|
234 |
|
235 private: |
|
236 nsCOMPtr<nsIObserver> mObserver; |
|
237 nsString mData; |
|
238 }; |
|
239 |
|
240 class ConsoleListener MOZ_FINAL : public nsIConsoleListener |
|
241 { |
|
242 public: |
|
243 ConsoleListener(ContentChild* aChild) |
|
244 : mChild(aChild) {} |
|
245 |
|
246 NS_DECL_ISUPPORTS |
|
247 NS_DECL_NSICONSOLELISTENER |
|
248 |
|
249 private: |
|
250 ContentChild* mChild; |
|
251 friend class ContentChild; |
|
252 }; |
|
253 |
|
254 NS_IMPL_ISUPPORTS(ConsoleListener, nsIConsoleListener) |
|
255 |
|
256 NS_IMETHODIMP |
|
257 ConsoleListener::Observe(nsIConsoleMessage* aMessage) |
|
258 { |
|
259 if (!mChild) |
|
260 return NS_OK; |
|
261 |
|
262 nsCOMPtr<nsIScriptError> scriptError = do_QueryInterface(aMessage); |
|
263 if (scriptError) { |
|
264 nsString msg, sourceName, sourceLine; |
|
265 nsXPIDLCString category; |
|
266 uint32_t lineNum, colNum, flags; |
|
267 |
|
268 nsresult rv = scriptError->GetErrorMessage(msg); |
|
269 NS_ENSURE_SUCCESS(rv, rv); |
|
270 rv = scriptError->GetSourceName(sourceName); |
|
271 NS_ENSURE_SUCCESS(rv, rv); |
|
272 rv = scriptError->GetSourceLine(sourceLine); |
|
273 NS_ENSURE_SUCCESS(rv, rv); |
|
274 |
|
275 // Before we send the error to the parent process (which |
|
276 // involves copying the memory), truncate any long lines. CSS |
|
277 // errors in particular share the memory for long lines with |
|
278 // repeated errors, but the IPC communication we're about to do |
|
279 // will break that sharing, so we better truncate now. |
|
280 if (sourceLine.Length() > 1000) { |
|
281 sourceLine.Truncate(1000); |
|
282 } |
|
283 |
|
284 rv = scriptError->GetCategory(getter_Copies(category)); |
|
285 NS_ENSURE_SUCCESS(rv, rv); |
|
286 rv = scriptError->GetLineNumber(&lineNum); |
|
287 NS_ENSURE_SUCCESS(rv, rv); |
|
288 rv = scriptError->GetColumnNumber(&colNum); |
|
289 NS_ENSURE_SUCCESS(rv, rv); |
|
290 rv = scriptError->GetFlags(&flags); |
|
291 NS_ENSURE_SUCCESS(rv, rv); |
|
292 mChild->SendScriptError(msg, sourceName, sourceLine, |
|
293 lineNum, colNum, flags, category); |
|
294 return NS_OK; |
|
295 } |
|
296 |
|
297 nsXPIDLString msg; |
|
298 nsresult rv = aMessage->GetMessageMoz(getter_Copies(msg)); |
|
299 NS_ENSURE_SUCCESS(rv, rv); |
|
300 mChild->SendConsoleMessage(msg); |
|
301 return NS_OK; |
|
302 } |
|
303 |
|
304 class SystemMessageHandledObserver MOZ_FINAL : public nsIObserver |
|
305 { |
|
306 public: |
|
307 NS_DECL_ISUPPORTS |
|
308 NS_DECL_NSIOBSERVER |
|
309 |
|
310 void Init(); |
|
311 }; |
|
312 |
|
313 void SystemMessageHandledObserver::Init() |
|
314 { |
|
315 nsCOMPtr<nsIObserverService> os = |
|
316 mozilla::services::GetObserverService(); |
|
317 |
|
318 if (os) { |
|
319 os->AddObserver(this, "handle-system-messages-done", |
|
320 /* ownsWeak */ false); |
|
321 } |
|
322 } |
|
323 |
|
324 NS_IMETHODIMP |
|
325 SystemMessageHandledObserver::Observe(nsISupports* aSubject, |
|
326 const char* aTopic, |
|
327 const char16_t* aData) |
|
328 { |
|
329 if (ContentChild::GetSingleton()) { |
|
330 ContentChild::GetSingleton()->SendSystemMessageHandled(); |
|
331 } |
|
332 return NS_OK; |
|
333 } |
|
334 |
|
335 NS_IMPL_ISUPPORTS(SystemMessageHandledObserver, nsIObserver) |
|
336 |
|
337 class BackgroundChildPrimer MOZ_FINAL : |
|
338 public nsIIPCBackgroundChildCreateCallback |
|
339 { |
|
340 public: |
|
341 BackgroundChildPrimer() |
|
342 { } |
|
343 |
|
344 NS_DECL_ISUPPORTS |
|
345 |
|
346 private: |
|
347 ~BackgroundChildPrimer() |
|
348 { } |
|
349 |
|
350 virtual void |
|
351 ActorCreated(PBackgroundChild* aActor) MOZ_OVERRIDE |
|
352 { |
|
353 MOZ_ASSERT(aActor, "Failed to create a PBackgroundChild actor!"); |
|
354 } |
|
355 |
|
356 virtual void |
|
357 ActorFailed() MOZ_OVERRIDE |
|
358 { |
|
359 MOZ_CRASH("Failed to create a PBackgroundChild actor!"); |
|
360 } |
|
361 }; |
|
362 |
|
363 NS_IMPL_ISUPPORTS(BackgroundChildPrimer, nsIIPCBackgroundChildCreateCallback) |
|
364 |
|
365 ContentChild* ContentChild::sSingleton; |
|
366 |
|
367 // Performs initialization that is not fork-safe, i.e. that must be done after |
|
368 // forking from the Nuwa process. |
|
369 static void |
|
370 InitOnContentProcessCreated() |
|
371 { |
|
372 // This will register cross-process observer. |
|
373 mozilla::dom::time::InitializeDateCacheCleaner(); |
|
374 } |
|
375 |
|
376 ContentChild::ContentChild() |
|
377 : mID(uint64_t(-1)) |
|
378 #ifdef ANDROID |
|
379 ,mScreenSize(0, 0) |
|
380 #endif |
|
381 , mCanOverrideProcessName(true) |
|
382 { |
|
383 // This process is a content process, so it's clearly running in |
|
384 // multiprocess mode! |
|
385 nsDebugImpl::SetMultiprocessMode("Child"); |
|
386 } |
|
387 |
|
388 ContentChild::~ContentChild() |
|
389 { |
|
390 } |
|
391 |
|
392 bool |
|
393 ContentChild::Init(MessageLoop* aIOLoop, |
|
394 base::ProcessHandle aParentHandle, |
|
395 IPC::Channel* aChannel) |
|
396 { |
|
397 #ifdef MOZ_WIDGET_GTK |
|
398 // sigh |
|
399 gtk_init(nullptr, nullptr); |
|
400 #endif |
|
401 |
|
402 #ifdef MOZ_WIDGET_QT |
|
403 // sigh, seriously |
|
404 nsQAppInstance::AddRef(); |
|
405 #endif |
|
406 |
|
407 #ifdef MOZ_X11 |
|
408 // Do this after initializing GDK, or GDK will install its own handler. |
|
409 XRE_InstallX11ErrorHandler(); |
|
410 #endif |
|
411 |
|
412 #ifdef MOZ_NUWA_PROCESS |
|
413 SetTransport(aChannel); |
|
414 #endif |
|
415 |
|
416 NS_ASSERTION(!sSingleton, "only one ContentChild per child"); |
|
417 |
|
418 // Once we start sending IPC messages, we need the thread manager to be |
|
419 // initialized so we can deal with the responses. Do that here before we |
|
420 // try to construct the crash reporter. |
|
421 nsresult rv = nsThreadManager::get()->Init(); |
|
422 if (NS_WARN_IF(NS_FAILED(rv))) { |
|
423 return false; |
|
424 } |
|
425 |
|
426 Open(aChannel, aParentHandle, aIOLoop); |
|
427 sSingleton = this; |
|
428 |
|
429 #ifdef MOZ_X11 |
|
430 // Send the parent our X socket to act as a proxy reference for our X |
|
431 // resources. |
|
432 int xSocketFd = ConnectionNumber(DefaultXDisplay()); |
|
433 SendBackUpXResources(FileDescriptor(xSocketFd)); |
|
434 #endif |
|
435 |
|
436 #ifdef MOZ_CRASHREPORTER |
|
437 SendPCrashReporterConstructor(CrashReporter::CurrentThreadId(), |
|
438 XRE_GetProcessType()); |
|
439 #endif |
|
440 |
|
441 GetCPOWManager(); |
|
442 |
|
443 InitProcessAttributes(); |
|
444 |
|
445 return true; |
|
446 } |
|
447 |
|
448 void |
|
449 ContentChild::InitProcessAttributes() |
|
450 { |
|
451 SendGetProcessAttributes(&mID, &mIsForApp, &mIsForBrowser); |
|
452 |
|
453 #ifdef MOZ_NUWA_PROCESS |
|
454 if (IsNuwaProcess()) { |
|
455 SetProcessName(NS_LITERAL_STRING("(Nuwa)"), false); |
|
456 return; |
|
457 } |
|
458 #endif |
|
459 if (mIsForApp && !mIsForBrowser) { |
|
460 SetProcessName(NS_LITERAL_STRING("(Preallocated app)"), false); |
|
461 } else { |
|
462 SetProcessName(NS_LITERAL_STRING("Browser"), false); |
|
463 } |
|
464 |
|
465 } |
|
466 |
|
467 void |
|
468 ContentChild::SetProcessName(const nsAString& aName, bool aDontOverride) |
|
469 { |
|
470 if (!mCanOverrideProcessName) { |
|
471 return; |
|
472 } |
|
473 |
|
474 char* name; |
|
475 if ((name = PR_GetEnv("MOZ_DEBUG_APP_PROCESS")) && |
|
476 aName.EqualsASCII(name)) { |
|
477 #ifdef OS_POSIX |
|
478 printf_stderr("\n\nCHILDCHILDCHILDCHILD\n [%s] debug me @%d\n\n", name, getpid()); |
|
479 sleep(30); |
|
480 #elif defined(OS_WIN) |
|
481 // Windows has a decent JIT debugging story, so NS_DebugBreak does the |
|
482 // right thing. |
|
483 NS_DebugBreak(NS_DEBUG_BREAK, |
|
484 "Invoking NS_DebugBreak() to debug child process", |
|
485 nullptr, __FILE__, __LINE__); |
|
486 #endif |
|
487 } |
|
488 |
|
489 mProcessName = aName; |
|
490 mozilla::ipc::SetThisProcessName(NS_LossyConvertUTF16toASCII(aName).get()); |
|
491 |
|
492 if (aDontOverride) { |
|
493 mCanOverrideProcessName = false; |
|
494 } |
|
495 } |
|
496 |
|
497 void |
|
498 ContentChild::GetProcessName(nsAString& aName) |
|
499 { |
|
500 aName.Assign(mProcessName); |
|
501 } |
|
502 |
|
503 void |
|
504 ContentChild::GetProcessName(nsACString& aName) |
|
505 { |
|
506 aName.Assign(NS_ConvertUTF16toUTF8(mProcessName)); |
|
507 } |
|
508 |
|
509 /* static */ void |
|
510 ContentChild::AppendProcessId(nsACString& aName) |
|
511 { |
|
512 if (!aName.IsEmpty()) { |
|
513 aName.AppendLiteral(" "); |
|
514 } |
|
515 unsigned pid = getpid(); |
|
516 aName.Append(nsPrintfCString("(pid %u)", pid)); |
|
517 } |
|
518 |
|
519 void |
|
520 ContentChild::InitXPCOM() |
|
521 { |
|
522 // Do this as early as possible to get the parent process to initialize the |
|
523 // background thread since we'll likely need database information very soon. |
|
524 BackgroundChild::Startup(); |
|
525 |
|
526 nsCOMPtr<nsIIPCBackgroundChildCreateCallback> callback = |
|
527 new BackgroundChildPrimer(); |
|
528 if (!BackgroundChild::GetOrCreateForCurrentThread(callback)) { |
|
529 MOZ_CRASH("Failed to create PBackgroundChild!"); |
|
530 } |
|
531 |
|
532 nsCOMPtr<nsIConsoleService> svc(do_GetService(NS_CONSOLESERVICE_CONTRACTID)); |
|
533 if (!svc) { |
|
534 NS_WARNING("Couldn't acquire console service"); |
|
535 return; |
|
536 } |
|
537 |
|
538 mConsoleListener = new ConsoleListener(this); |
|
539 if (NS_FAILED(svc->RegisterListener(mConsoleListener))) |
|
540 NS_WARNING("Couldn't register console listener for child process"); |
|
541 |
|
542 bool isOffline; |
|
543 SendGetXPCOMProcessAttributes(&isOffline); |
|
544 RecvSetOffline(isOffline); |
|
545 |
|
546 DebugOnly<FileUpdateDispatcher*> observer = FileUpdateDispatcher::GetSingleton(); |
|
547 NS_ASSERTION(observer, "FileUpdateDispatcher is null"); |
|
548 |
|
549 // This object is held alive by the observer service. |
|
550 nsRefPtr<SystemMessageHandledObserver> sysMsgObserver = |
|
551 new SystemMessageHandledObserver(); |
|
552 sysMsgObserver->Init(); |
|
553 |
|
554 #ifndef MOZ_NUWA_PROCESS |
|
555 InitOnContentProcessCreated(); |
|
556 #endif |
|
557 } |
|
558 |
|
559 PMemoryReportRequestChild* |
|
560 ContentChild::AllocPMemoryReportRequestChild(const uint32_t& generation, |
|
561 const bool &minimizeMemoryUsage, |
|
562 const nsString& aDMDDumpIdent) |
|
563 { |
|
564 MemoryReportRequestChild *actor = new MemoryReportRequestChild(generation, aDMDDumpIdent); |
|
565 actor->AddRef(); |
|
566 return actor; |
|
567 } |
|
568 |
|
569 // This is just a wrapper for InfallibleTArray<MemoryReport> that implements |
|
570 // nsISupports, so it can be passed to nsIMemoryReporter::CollectReports. |
|
571 class MemoryReportsWrapper MOZ_FINAL : public nsISupports { |
|
572 public: |
|
573 NS_DECL_ISUPPORTS |
|
574 MemoryReportsWrapper(InfallibleTArray<MemoryReport> *r) : mReports(r) { } |
|
575 InfallibleTArray<MemoryReport> *mReports; |
|
576 }; |
|
577 NS_IMPL_ISUPPORTS0(MemoryReportsWrapper) |
|
578 |
|
579 class MemoryReportCallback MOZ_FINAL : public nsIMemoryReporterCallback |
|
580 { |
|
581 public: |
|
582 NS_DECL_ISUPPORTS |
|
583 |
|
584 MemoryReportCallback(const nsACString &aProcess) |
|
585 : mProcess(aProcess) |
|
586 { |
|
587 } |
|
588 |
|
589 NS_IMETHOD Callback(const nsACString &aProcess, const nsACString &aPath, |
|
590 int32_t aKind, int32_t aUnits, int64_t aAmount, |
|
591 const nsACString &aDescription, |
|
592 nsISupports *aiWrappedReports) |
|
593 { |
|
594 MemoryReportsWrapper *wrappedReports = |
|
595 static_cast<MemoryReportsWrapper *>(aiWrappedReports); |
|
596 |
|
597 MemoryReport memreport(mProcess, nsCString(aPath), aKind, aUnits, |
|
598 aAmount, nsCString(aDescription)); |
|
599 wrappedReports->mReports->AppendElement(memreport); |
|
600 return NS_OK; |
|
601 } |
|
602 private: |
|
603 const nsCString mProcess; |
|
604 }; |
|
605 NS_IMPL_ISUPPORTS( |
|
606 MemoryReportCallback |
|
607 , nsIMemoryReporterCallback |
|
608 ) |
|
609 |
|
610 bool |
|
611 ContentChild::RecvPMemoryReportRequestConstructor( |
|
612 PMemoryReportRequestChild* child, |
|
613 const uint32_t& generation, |
|
614 const bool& minimizeMemoryUsage, |
|
615 const nsString& aDMDDumpIdent) |
|
616 { |
|
617 MemoryReportRequestChild *actor = static_cast<MemoryReportRequestChild*>(child); |
|
618 nsresult rv; |
|
619 |
|
620 if (minimizeMemoryUsage) { |
|
621 nsCOMPtr<nsIMemoryReporterManager> mgr = do_GetService("@mozilla.org/memory-reporter-manager;1"); |
|
622 rv = mgr->MinimizeMemoryUsage(actor); |
|
623 // mgr will eventually call actor->Run() |
|
624 } else { |
|
625 rv = actor->Run(); |
|
626 } |
|
627 |
|
628 return !NS_WARN_IF(NS_FAILED(rv)); |
|
629 } |
|
630 |
|
631 NS_IMETHODIMP MemoryReportRequestChild::Run() |
|
632 { |
|
633 ContentChild *child = static_cast<ContentChild*>(Manager()); |
|
634 nsCOMPtr<nsIMemoryReporterManager> mgr = do_GetService("@mozilla.org/memory-reporter-manager;1"); |
|
635 |
|
636 InfallibleTArray<MemoryReport> reports; |
|
637 |
|
638 nsCString process; |
|
639 child->GetProcessName(process); |
|
640 child->AppendProcessId(process); |
|
641 |
|
642 // Run the reporters. The callback will turn each measurement into a |
|
643 // MemoryReport. |
|
644 nsRefPtr<MemoryReportsWrapper> wrappedReports = |
|
645 new MemoryReportsWrapper(&reports); |
|
646 nsRefPtr<MemoryReportCallback> cb = new MemoryReportCallback(process); |
|
647 mgr->GetReportsForThisProcessExtended(cb, wrappedReports, mDMDDumpIdent); |
|
648 |
|
649 bool sent = Send__delete__(this, mGeneration, reports); |
|
650 return sent ? NS_OK : NS_ERROR_FAILURE; |
|
651 } |
|
652 |
|
653 bool |
|
654 ContentChild::RecvAudioChannelNotify() |
|
655 { |
|
656 nsRefPtr<AudioChannelService> service = |
|
657 AudioChannelService::GetAudioChannelService(); |
|
658 if (service) { |
|
659 service->Notify(); |
|
660 } |
|
661 return true; |
|
662 } |
|
663 |
|
664 bool |
|
665 ContentChild::DeallocPMemoryReportRequestChild(PMemoryReportRequestChild* actor) |
|
666 { |
|
667 static_cast<MemoryReportRequestChild*>(actor)->Release(); |
|
668 return true; |
|
669 } |
|
670 |
|
671 bool |
|
672 ContentChild::RecvDumpGCAndCCLogsToFile(const nsString& aIdentifier, |
|
673 const bool& aDumpAllTraces, |
|
674 const bool& aDumpChildProcesses) |
|
675 { |
|
676 nsCOMPtr<nsIMemoryInfoDumper> dumper = do_GetService("@mozilla.org/memory-info-dumper;1"); |
|
677 |
|
678 nsString gcLogPath, ccLogPath; |
|
679 dumper->DumpGCAndCCLogsToFile(aIdentifier, aDumpAllTraces, |
|
680 aDumpChildProcesses, gcLogPath, ccLogPath); |
|
681 return true; |
|
682 } |
|
683 |
|
684 PCompositorChild* |
|
685 ContentChild::AllocPCompositorChild(mozilla::ipc::Transport* aTransport, |
|
686 base::ProcessId aOtherProcess) |
|
687 { |
|
688 return CompositorChild::Create(aTransport, aOtherProcess); |
|
689 } |
|
690 |
|
691 PImageBridgeChild* |
|
692 ContentChild::AllocPImageBridgeChild(mozilla::ipc::Transport* aTransport, |
|
693 base::ProcessId aOtherProcess) |
|
694 { |
|
695 return ImageBridgeChild::StartUpInChildProcess(aTransport, aOtherProcess); |
|
696 } |
|
697 |
|
698 PBackgroundChild* |
|
699 ContentChild::AllocPBackgroundChild(Transport* aTransport, |
|
700 ProcessId aOtherProcess) |
|
701 { |
|
702 return BackgroundChild::Alloc(aTransport, aOtherProcess); |
|
703 } |
|
704 |
|
705 bool |
|
706 ContentChild::RecvSetProcessSandbox() |
|
707 { |
|
708 // We may want to move the sandbox initialization somewhere else |
|
709 // at some point; see bug 880808. |
|
710 #if defined(MOZ_CONTENT_SANDBOX) |
|
711 #if defined(XP_LINUX) |
|
712 SetCurrentProcessSandbox(); |
|
713 #elif defined(XP_WIN) |
|
714 mozilla::SandboxTarget::Instance()->StartSandbox(); |
|
715 #endif |
|
716 #endif |
|
717 return true; |
|
718 } |
|
719 |
|
720 bool |
|
721 ContentChild::RecvSpeakerManagerNotify() |
|
722 { |
|
723 #ifdef MOZ_WIDGET_GONK |
|
724 nsRefPtr<SpeakerManagerService> service = |
|
725 SpeakerManagerService::GetSpeakerManagerService(); |
|
726 if (service) { |
|
727 service->Notify(); |
|
728 } |
|
729 return true; |
|
730 #endif |
|
731 return false; |
|
732 } |
|
733 |
|
734 static CancelableTask* sFirstIdleTask; |
|
735 |
|
736 static void FirstIdle(void) |
|
737 { |
|
738 MOZ_ASSERT(sFirstIdleTask); |
|
739 sFirstIdleTask = nullptr; |
|
740 ContentChild::GetSingleton()->SendFirstIdle(); |
|
741 } |
|
742 |
|
743 mozilla::jsipc::PJavaScriptChild * |
|
744 ContentChild::AllocPJavaScriptChild() |
|
745 { |
|
746 nsCOMPtr<nsIJSRuntimeService> svc = do_GetService("@mozilla.org/js/xpc/RuntimeService;1"); |
|
747 NS_ENSURE_TRUE(svc, nullptr); |
|
748 |
|
749 JSRuntime *rt; |
|
750 svc->GetRuntime(&rt); |
|
751 NS_ENSURE_TRUE(svc, nullptr); |
|
752 |
|
753 mozilla::jsipc::JavaScriptChild *child = new mozilla::jsipc::JavaScriptChild(rt); |
|
754 if (!child->init()) { |
|
755 delete child; |
|
756 return nullptr; |
|
757 } |
|
758 return child; |
|
759 } |
|
760 |
|
761 bool |
|
762 ContentChild::DeallocPJavaScriptChild(PJavaScriptChild *child) |
|
763 { |
|
764 delete child; |
|
765 return true; |
|
766 } |
|
767 |
|
768 PBrowserChild* |
|
769 ContentChild::AllocPBrowserChild(const IPCTabContext& aContext, |
|
770 const uint32_t& aChromeFlags) |
|
771 { |
|
772 // We'll happily accept any kind of IPCTabContext here; we don't need to |
|
773 // check that it's of a certain type for security purposes, because we |
|
774 // believe whatever the parent process tells us. |
|
775 |
|
776 MaybeInvalidTabContext tc(aContext); |
|
777 if (!tc.IsValid()) { |
|
778 NS_ERROR(nsPrintfCString("Received an invalid TabContext from " |
|
779 "the parent process. (%s) Crashing...", |
|
780 tc.GetInvalidReason()).get()); |
|
781 MOZ_CRASH("Invalid TabContext received from the parent process."); |
|
782 } |
|
783 |
|
784 nsRefPtr<TabChild> child = TabChild::Create(this, tc.GetTabContext(), aChromeFlags); |
|
785 |
|
786 // The ref here is released in DeallocPBrowserChild. |
|
787 return child.forget().take(); |
|
788 } |
|
789 |
|
790 bool |
|
791 ContentChild::RecvPBrowserConstructor(PBrowserChild* actor, |
|
792 const IPCTabContext& context, |
|
793 const uint32_t& chromeFlags) |
|
794 { |
|
795 // This runs after AllocPBrowserChild() returns and the IPC machinery for this |
|
796 // PBrowserChild has been set up. |
|
797 |
|
798 nsCOMPtr<nsIObserverService> os = services::GetObserverService(); |
|
799 if (os) { |
|
800 nsITabChild* tc = |
|
801 static_cast<nsITabChild*>(static_cast<TabChild*>(actor)); |
|
802 os->NotifyObservers(tc, "tab-child-created", nullptr); |
|
803 } |
|
804 |
|
805 static bool hasRunOnce = false; |
|
806 if (!hasRunOnce) { |
|
807 hasRunOnce = true; |
|
808 |
|
809 MOZ_ASSERT(!sFirstIdleTask); |
|
810 sFirstIdleTask = NewRunnableFunction(FirstIdle); |
|
811 MessageLoop::current()->PostIdleTask(FROM_HERE, sFirstIdleTask); |
|
812 |
|
813 // Redo InitProcessAttributes() when the app or browser is really |
|
814 // launching so the attributes will be correct. |
|
815 InitProcessAttributes(); |
|
816 } |
|
817 |
|
818 return true; |
|
819 } |
|
820 |
|
821 PFileDescriptorSetChild* |
|
822 ContentChild::AllocPFileDescriptorSetChild(const FileDescriptor& aFD) |
|
823 { |
|
824 return new FileDescriptorSetChild(aFD); |
|
825 } |
|
826 |
|
827 bool |
|
828 ContentChild::DeallocPFileDescriptorSetChild(PFileDescriptorSetChild* aActor) |
|
829 { |
|
830 delete static_cast<FileDescriptorSetChild*>(aActor); |
|
831 return true; |
|
832 } |
|
833 |
|
834 bool |
|
835 ContentChild::DeallocPBrowserChild(PBrowserChild* iframe) |
|
836 { |
|
837 TabChild* child = static_cast<TabChild*>(iframe); |
|
838 NS_RELEASE(child); |
|
839 return true; |
|
840 } |
|
841 |
|
842 PBlobChild* |
|
843 ContentChild::AllocPBlobChild(const BlobConstructorParams& aParams) |
|
844 { |
|
845 return BlobChild::Create(this, aParams); |
|
846 } |
|
847 |
|
848 bool |
|
849 ContentChild::DeallocPBlobChild(PBlobChild* aActor) |
|
850 { |
|
851 delete aActor; |
|
852 return true; |
|
853 } |
|
854 |
|
855 BlobChild* |
|
856 ContentChild::GetOrCreateActorForBlob(nsIDOMBlob* aBlob) |
|
857 { |
|
858 MOZ_ASSERT(NS_IsMainThread()); |
|
859 MOZ_ASSERT(aBlob); |
|
860 |
|
861 // If the blob represents a remote blob then we can simply pass its actor back |
|
862 // here. |
|
863 if (nsCOMPtr<nsIRemoteBlob> remoteBlob = do_QueryInterface(aBlob)) { |
|
864 BlobChild* actor = |
|
865 static_cast<BlobChild*>( |
|
866 static_cast<PBlobChild*>(remoteBlob->GetPBlob())); |
|
867 MOZ_ASSERT(actor); |
|
868 return actor; |
|
869 } |
|
870 |
|
871 // XXX This is only safe so long as all blob implementations in our tree |
|
872 // inherit nsDOMFileBase. If that ever changes then this will need to grow |
|
873 // a real interface or something. |
|
874 const nsDOMFileBase* blob = static_cast<nsDOMFileBase*>(aBlob); |
|
875 |
|
876 // We often pass blobs that are multipart but that only contain one sub-blob |
|
877 // (WebActivities does this a bunch). Unwrap to reduce the number of actors |
|
878 // that we have to maintain. |
|
879 const nsTArray<nsCOMPtr<nsIDOMBlob> >* subBlobs = blob->GetSubBlobs(); |
|
880 if (subBlobs && subBlobs->Length() == 1) { |
|
881 const nsCOMPtr<nsIDOMBlob>& subBlob = subBlobs->ElementAt(0); |
|
882 MOZ_ASSERT(subBlob); |
|
883 |
|
884 // We can only take this shortcut if the multipart and the sub-blob are both |
|
885 // Blob objects or both File objects. |
|
886 nsCOMPtr<nsIDOMFile> multipartBlobAsFile = do_QueryInterface(aBlob); |
|
887 nsCOMPtr<nsIDOMFile> subBlobAsFile = do_QueryInterface(subBlob); |
|
888 if (!multipartBlobAsFile == !subBlobAsFile) { |
|
889 // The wrapping was unnecessary, see if we can simply pass an existing |
|
890 // remote blob. |
|
891 if (nsCOMPtr<nsIRemoteBlob> remoteBlob = do_QueryInterface(subBlob)) { |
|
892 BlobChild* actor = |
|
893 static_cast<BlobChild*>( |
|
894 static_cast<PBlobChild*>(remoteBlob->GetPBlob())); |
|
895 MOZ_ASSERT(actor); |
|
896 return actor; |
|
897 } |
|
898 |
|
899 // No need to add a reference here since the original blob must have a |
|
900 // strong reference in the caller and it must also have a strong reference |
|
901 // to this sub-blob. |
|
902 aBlob = subBlob; |
|
903 blob = static_cast<nsDOMFileBase*>(aBlob); |
|
904 subBlobs = blob->GetSubBlobs(); |
|
905 } |
|
906 } |
|
907 |
|
908 // All blobs shared between processes must be immutable. |
|
909 nsCOMPtr<nsIMutable> mutableBlob = do_QueryInterface(aBlob); |
|
910 if (!mutableBlob || NS_FAILED(mutableBlob->SetMutable(false))) { |
|
911 NS_WARNING("Failed to make blob immutable!"); |
|
912 return nullptr; |
|
913 } |
|
914 |
|
915 ParentBlobConstructorParams params; |
|
916 |
|
917 if (blob->IsSizeUnknown() || blob->IsDateUnknown()) { |
|
918 // We don't want to call GetSize or GetLastModifiedDate |
|
919 // yet since that may stat a file on the main thread |
|
920 // here. Instead we'll learn the size lazily from the |
|
921 // other process. |
|
922 params.blobParams() = MysteryBlobConstructorParams(); |
|
923 params.optionalInputStreamParams() = void_t(); |
|
924 } |
|
925 else { |
|
926 nsString contentType; |
|
927 nsresult rv = aBlob->GetType(contentType); |
|
928 NS_ENSURE_SUCCESS(rv, nullptr); |
|
929 |
|
930 uint64_t length; |
|
931 rv = aBlob->GetSize(&length); |
|
932 NS_ENSURE_SUCCESS(rv, nullptr); |
|
933 |
|
934 nsCOMPtr<nsIInputStream> stream; |
|
935 rv = aBlob->GetInternalStream(getter_AddRefs(stream)); |
|
936 NS_ENSURE_SUCCESS(rv, nullptr); |
|
937 |
|
938 InputStreamParams inputStreamParams; |
|
939 nsTArray<mozilla::ipc::FileDescriptor> fds; |
|
940 SerializeInputStream(stream, inputStreamParams, fds); |
|
941 MOZ_ASSERT(fds.IsEmpty()); |
|
942 |
|
943 params.optionalInputStreamParams() = inputStreamParams; |
|
944 |
|
945 nsCOMPtr<nsIDOMFile> file = do_QueryInterface(aBlob); |
|
946 if (file) { |
|
947 FileBlobConstructorParams fileParams; |
|
948 |
|
949 rv = file->GetName(fileParams.name()); |
|
950 NS_ENSURE_SUCCESS(rv, nullptr); |
|
951 |
|
952 rv = file->GetMozLastModifiedDate(&fileParams.modDate()); |
|
953 NS_ENSURE_SUCCESS(rv, nullptr); |
|
954 |
|
955 fileParams.contentType() = contentType; |
|
956 fileParams.length() = length; |
|
957 |
|
958 params.blobParams() = fileParams; |
|
959 } else { |
|
960 NormalBlobConstructorParams blobParams; |
|
961 blobParams.contentType() = contentType; |
|
962 blobParams.length() = length; |
|
963 params.blobParams() = blobParams; |
|
964 } |
|
965 } |
|
966 |
|
967 BlobChild* actor = BlobChild::Create(this, aBlob); |
|
968 NS_ENSURE_TRUE(actor, nullptr); |
|
969 |
|
970 return SendPBlobConstructor(actor, params) ? actor : nullptr; |
|
971 } |
|
972 |
|
973 PCrashReporterChild* |
|
974 ContentChild::AllocPCrashReporterChild(const mozilla::dom::NativeThreadId& id, |
|
975 const uint32_t& processType) |
|
976 { |
|
977 #ifdef MOZ_CRASHREPORTER |
|
978 return new CrashReporterChild(); |
|
979 #else |
|
980 return nullptr; |
|
981 #endif |
|
982 } |
|
983 |
|
984 bool |
|
985 ContentChild::DeallocPCrashReporterChild(PCrashReporterChild* crashreporter) |
|
986 { |
|
987 delete crashreporter; |
|
988 return true; |
|
989 } |
|
990 |
|
991 PHalChild* |
|
992 ContentChild::AllocPHalChild() |
|
993 { |
|
994 return CreateHalChild(); |
|
995 } |
|
996 |
|
997 bool |
|
998 ContentChild::DeallocPHalChild(PHalChild* aHal) |
|
999 { |
|
1000 delete aHal; |
|
1001 return true; |
|
1002 } |
|
1003 |
|
1004 PIndexedDBChild* |
|
1005 ContentChild::AllocPIndexedDBChild() |
|
1006 { |
|
1007 NS_NOTREACHED("Should never get here!"); |
|
1008 return nullptr; |
|
1009 } |
|
1010 |
|
1011 bool |
|
1012 ContentChild::DeallocPIndexedDBChild(PIndexedDBChild* aActor) |
|
1013 { |
|
1014 delete aActor; |
|
1015 return true; |
|
1016 } |
|
1017 |
|
1018 asmjscache::PAsmJSCacheEntryChild* |
|
1019 ContentChild::AllocPAsmJSCacheEntryChild( |
|
1020 const asmjscache::OpenMode& aOpenMode, |
|
1021 const asmjscache::WriteParams& aWriteParams, |
|
1022 const IPC::Principal& aPrincipal) |
|
1023 { |
|
1024 NS_NOTREACHED("Should never get here!"); |
|
1025 return nullptr; |
|
1026 } |
|
1027 |
|
1028 bool |
|
1029 ContentChild::DeallocPAsmJSCacheEntryChild(PAsmJSCacheEntryChild* aActor) |
|
1030 { |
|
1031 asmjscache::DeallocEntryChild(aActor); |
|
1032 return true; |
|
1033 } |
|
1034 |
|
1035 PTestShellChild* |
|
1036 ContentChild::AllocPTestShellChild() |
|
1037 { |
|
1038 return new TestShellChild(); |
|
1039 } |
|
1040 |
|
1041 bool |
|
1042 ContentChild::DeallocPTestShellChild(PTestShellChild* shell) |
|
1043 { |
|
1044 delete shell; |
|
1045 return true; |
|
1046 } |
|
1047 |
|
1048 jsipc::JavaScriptChild * |
|
1049 ContentChild::GetCPOWManager() |
|
1050 { |
|
1051 if (ManagedPJavaScriptChild().Length()) { |
|
1052 return static_cast<JavaScriptChild*>(ManagedPJavaScriptChild()[0]); |
|
1053 } |
|
1054 JavaScriptChild* actor = static_cast<JavaScriptChild*>(SendPJavaScriptConstructor()); |
|
1055 return actor; |
|
1056 } |
|
1057 |
|
1058 bool |
|
1059 ContentChild::RecvPTestShellConstructor(PTestShellChild* actor) |
|
1060 { |
|
1061 return true; |
|
1062 } |
|
1063 |
|
1064 PDeviceStorageRequestChild* |
|
1065 ContentChild::AllocPDeviceStorageRequestChild(const DeviceStorageParams& aParams) |
|
1066 { |
|
1067 return new DeviceStorageRequestChild(); |
|
1068 } |
|
1069 |
|
1070 bool |
|
1071 ContentChild::DeallocPDeviceStorageRequestChild(PDeviceStorageRequestChild* aDeviceStorage) |
|
1072 { |
|
1073 delete aDeviceStorage; |
|
1074 return true; |
|
1075 } |
|
1076 |
|
1077 PFileSystemRequestChild* |
|
1078 ContentChild::AllocPFileSystemRequestChild(const FileSystemParams& aParams) |
|
1079 { |
|
1080 NS_NOTREACHED("Should never get here!"); |
|
1081 return nullptr; |
|
1082 } |
|
1083 |
|
1084 bool |
|
1085 ContentChild::DeallocPFileSystemRequestChild(PFileSystemRequestChild* aFileSystem) |
|
1086 { |
|
1087 mozilla::dom::FileSystemTaskBase* child = |
|
1088 static_cast<mozilla::dom::FileSystemTaskBase*>(aFileSystem); |
|
1089 // The reference is increased in FileSystemTaskBase::Start of |
|
1090 // FileSystemTaskBase.cpp. We should decrease it after IPC. |
|
1091 NS_RELEASE(child); |
|
1092 return true; |
|
1093 } |
|
1094 |
|
1095 PNeckoChild* |
|
1096 ContentChild::AllocPNeckoChild() |
|
1097 { |
|
1098 return new NeckoChild(); |
|
1099 } |
|
1100 |
|
1101 bool |
|
1102 ContentChild::DeallocPNeckoChild(PNeckoChild* necko) |
|
1103 { |
|
1104 delete necko; |
|
1105 return true; |
|
1106 } |
|
1107 |
|
1108 PExternalHelperAppChild* |
|
1109 ContentChild::AllocPExternalHelperAppChild(const OptionalURIParams& uri, |
|
1110 const nsCString& aMimeContentType, |
|
1111 const nsCString& aContentDisposition, |
|
1112 const uint32_t& aContentDispositionHint, |
|
1113 const nsString& aContentDispositionFilename, |
|
1114 const bool& aForceSave, |
|
1115 const int64_t& aContentLength, |
|
1116 const OptionalURIParams& aReferrer, |
|
1117 PBrowserChild* aBrowser) |
|
1118 { |
|
1119 ExternalHelperAppChild *child = new ExternalHelperAppChild(); |
|
1120 child->AddRef(); |
|
1121 return child; |
|
1122 } |
|
1123 |
|
1124 bool |
|
1125 ContentChild::DeallocPExternalHelperAppChild(PExternalHelperAppChild* aService) |
|
1126 { |
|
1127 ExternalHelperAppChild *child = static_cast<ExternalHelperAppChild*>(aService); |
|
1128 child->Release(); |
|
1129 return true; |
|
1130 } |
|
1131 |
|
1132 PSmsChild* |
|
1133 ContentChild::AllocPSmsChild() |
|
1134 { |
|
1135 return new SmsChild(); |
|
1136 } |
|
1137 |
|
1138 bool |
|
1139 ContentChild::DeallocPSmsChild(PSmsChild* aSms) |
|
1140 { |
|
1141 delete aSms; |
|
1142 return true; |
|
1143 } |
|
1144 |
|
1145 PTelephonyChild* |
|
1146 ContentChild::AllocPTelephonyChild() |
|
1147 { |
|
1148 MOZ_CRASH("No one should be allocating PTelephonyChild actors"); |
|
1149 } |
|
1150 |
|
1151 bool |
|
1152 ContentChild::DeallocPTelephonyChild(PTelephonyChild* aActor) |
|
1153 { |
|
1154 delete aActor; |
|
1155 return true; |
|
1156 } |
|
1157 |
|
1158 PStorageChild* |
|
1159 ContentChild::AllocPStorageChild() |
|
1160 { |
|
1161 NS_NOTREACHED("We should never be manually allocating PStorageChild actors"); |
|
1162 return nullptr; |
|
1163 } |
|
1164 |
|
1165 bool |
|
1166 ContentChild::DeallocPStorageChild(PStorageChild* aActor) |
|
1167 { |
|
1168 DOMStorageDBChild* child = static_cast<DOMStorageDBChild*>(aActor); |
|
1169 child->ReleaseIPDLReference(); |
|
1170 return true; |
|
1171 } |
|
1172 |
|
1173 PBluetoothChild* |
|
1174 ContentChild::AllocPBluetoothChild() |
|
1175 { |
|
1176 #ifdef MOZ_B2G_BT |
|
1177 MOZ_CRASH("No one should be allocating PBluetoothChild actors"); |
|
1178 #else |
|
1179 MOZ_CRASH("No support for bluetooth on this platform!"); |
|
1180 #endif |
|
1181 } |
|
1182 |
|
1183 bool |
|
1184 ContentChild::DeallocPBluetoothChild(PBluetoothChild* aActor) |
|
1185 { |
|
1186 #ifdef MOZ_B2G_BT |
|
1187 delete aActor; |
|
1188 return true; |
|
1189 #else |
|
1190 MOZ_CRASH("No support for bluetooth on this platform!"); |
|
1191 #endif |
|
1192 } |
|
1193 |
|
1194 PFMRadioChild* |
|
1195 ContentChild::AllocPFMRadioChild() |
|
1196 { |
|
1197 #ifdef MOZ_B2G_FM |
|
1198 NS_RUNTIMEABORT("No one should be allocating PFMRadioChild actors"); |
|
1199 return nullptr; |
|
1200 #else |
|
1201 NS_RUNTIMEABORT("No support for FMRadio on this platform!"); |
|
1202 return nullptr; |
|
1203 #endif |
|
1204 } |
|
1205 |
|
1206 bool |
|
1207 ContentChild::DeallocPFMRadioChild(PFMRadioChild* aActor) |
|
1208 { |
|
1209 #ifdef MOZ_B2G_FM |
|
1210 delete aActor; |
|
1211 return true; |
|
1212 #else |
|
1213 NS_RUNTIMEABORT("No support for FMRadio on this platform!"); |
|
1214 return false; |
|
1215 #endif |
|
1216 } |
|
1217 |
|
1218 PSpeechSynthesisChild* |
|
1219 ContentChild::AllocPSpeechSynthesisChild() |
|
1220 { |
|
1221 #ifdef MOZ_WEBSPEECH |
|
1222 MOZ_CRASH("No one should be allocating PSpeechSynthesisChild actors"); |
|
1223 #else |
|
1224 return nullptr; |
|
1225 #endif |
|
1226 } |
|
1227 |
|
1228 bool |
|
1229 ContentChild::DeallocPSpeechSynthesisChild(PSpeechSynthesisChild* aActor) |
|
1230 { |
|
1231 #ifdef MOZ_WEBSPEECH |
|
1232 delete aActor; |
|
1233 return true; |
|
1234 #else |
|
1235 return false; |
|
1236 #endif |
|
1237 } |
|
1238 |
|
1239 bool |
|
1240 ContentChild::RecvRegisterChrome(const InfallibleTArray<ChromePackage>& packages, |
|
1241 const InfallibleTArray<ResourceMapping>& resources, |
|
1242 const InfallibleTArray<OverrideMapping>& overrides, |
|
1243 const nsCString& locale) |
|
1244 { |
|
1245 nsCOMPtr<nsIChromeRegistry> registrySvc = nsChromeRegistry::GetService(); |
|
1246 nsChromeRegistryContent* chromeRegistry = |
|
1247 static_cast<nsChromeRegistryContent*>(registrySvc.get()); |
|
1248 chromeRegistry->RegisterRemoteChrome(packages, resources, overrides, locale); |
|
1249 return true; |
|
1250 } |
|
1251 |
|
1252 bool |
|
1253 ContentChild::RecvSetOffline(const bool& offline) |
|
1254 { |
|
1255 nsCOMPtr<nsIIOService> io (do_GetIOService()); |
|
1256 NS_ASSERTION(io, "IO Service can not be null"); |
|
1257 |
|
1258 io->SetOffline(offline); |
|
1259 |
|
1260 return true; |
|
1261 } |
|
1262 |
|
1263 void |
|
1264 ContentChild::ActorDestroy(ActorDestroyReason why) |
|
1265 { |
|
1266 if (AbnormalShutdown == why) { |
|
1267 NS_WARNING("shutting down early because of crash!"); |
|
1268 QuickExit(); |
|
1269 } |
|
1270 |
|
1271 #ifndef DEBUG |
|
1272 // In release builds, there's no point in the content process |
|
1273 // going through the full XPCOM shutdown path, because it doesn't |
|
1274 // keep persistent state. |
|
1275 QuickExit(); |
|
1276 #endif |
|
1277 |
|
1278 if (sFirstIdleTask) { |
|
1279 sFirstIdleTask->Cancel(); |
|
1280 } |
|
1281 |
|
1282 mAlertObservers.Clear(); |
|
1283 |
|
1284 mIdleObservers.Clear(); |
|
1285 |
|
1286 nsCOMPtr<nsIConsoleService> svc(do_GetService(NS_CONSOLESERVICE_CONTRACTID)); |
|
1287 if (svc) { |
|
1288 svc->UnregisterListener(mConsoleListener); |
|
1289 mConsoleListener->mChild = nullptr; |
|
1290 } |
|
1291 |
|
1292 XRE_ShutdownChildProcess(); |
|
1293 } |
|
1294 |
|
1295 void |
|
1296 ContentChild::ProcessingError(Result what) |
|
1297 { |
|
1298 switch (what) { |
|
1299 case MsgDropped: |
|
1300 QuickExit(); |
|
1301 |
|
1302 case MsgNotKnown: |
|
1303 NS_RUNTIMEABORT("aborting because of MsgNotKnown"); |
|
1304 case MsgNotAllowed: |
|
1305 NS_RUNTIMEABORT("aborting because of MsgNotAllowed"); |
|
1306 case MsgPayloadError: |
|
1307 NS_RUNTIMEABORT("aborting because of MsgPayloadError"); |
|
1308 case MsgProcessingError: |
|
1309 NS_RUNTIMEABORT("aborting because of MsgProcessingError"); |
|
1310 case MsgRouteError: |
|
1311 NS_RUNTIMEABORT("aborting because of MsgRouteError"); |
|
1312 case MsgValueError: |
|
1313 NS_RUNTIMEABORT("aborting because of MsgValueError"); |
|
1314 |
|
1315 default: |
|
1316 NS_RUNTIMEABORT("not reached"); |
|
1317 } |
|
1318 } |
|
1319 |
|
1320 void |
|
1321 ContentChild::QuickExit() |
|
1322 { |
|
1323 NS_WARNING("content process _exit()ing"); |
|
1324 _exit(0); |
|
1325 } |
|
1326 |
|
1327 nsresult |
|
1328 ContentChild::AddRemoteAlertObserver(const nsString& aData, |
|
1329 nsIObserver* aObserver) |
|
1330 { |
|
1331 NS_ASSERTION(aObserver, "Adding a null observer?"); |
|
1332 mAlertObservers.AppendElement(new AlertObserver(aObserver, aData)); |
|
1333 return NS_OK; |
|
1334 } |
|
1335 |
|
1336 bool |
|
1337 ContentChild::RecvPreferenceUpdate(const PrefSetting& aPref) |
|
1338 { |
|
1339 Preferences::SetPreference(aPref); |
|
1340 return true; |
|
1341 } |
|
1342 |
|
1343 bool |
|
1344 ContentChild::RecvNotifyAlertsObserver(const nsCString& aType, const nsString& aData) |
|
1345 { |
|
1346 for (uint32_t i = 0; i < mAlertObservers.Length(); |
|
1347 /*we mutate the array during the loop; ++i iff no mutation*/) { |
|
1348 AlertObserver* observer = mAlertObservers[i]; |
|
1349 if (observer->Observes(aData) && observer->Notify(aType)) { |
|
1350 // if aType == alertfinished, this alert is done. we can |
|
1351 // remove the observer. |
|
1352 if (aType.Equals(nsDependentCString("alertfinished"))) { |
|
1353 mAlertObservers.RemoveElementAt(i); |
|
1354 continue; |
|
1355 } |
|
1356 } |
|
1357 ++i; |
|
1358 } |
|
1359 return true; |
|
1360 } |
|
1361 |
|
1362 bool |
|
1363 ContentChild::RecvNotifyVisited(const URIParams& aURI) |
|
1364 { |
|
1365 nsCOMPtr<nsIURI> newURI = DeserializeURI(aURI); |
|
1366 if (!newURI) { |
|
1367 return false; |
|
1368 } |
|
1369 nsCOMPtr<IHistory> history = services::GetHistoryService(); |
|
1370 if (history) { |
|
1371 history->NotifyVisited(newURI); |
|
1372 } |
|
1373 return true; |
|
1374 } |
|
1375 |
|
1376 bool |
|
1377 ContentChild::RecvAsyncMessage(const nsString& aMsg, |
|
1378 const ClonedMessageData& aData, |
|
1379 const InfallibleTArray<CpowEntry>& aCpows, |
|
1380 const IPC::Principal& aPrincipal) |
|
1381 { |
|
1382 nsRefPtr<nsFrameMessageManager> cpm = nsFrameMessageManager::sChildProcessManager; |
|
1383 if (cpm) { |
|
1384 StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForChild(aData); |
|
1385 CpowIdHolder cpows(GetCPOWManager(), aCpows); |
|
1386 cpm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(cpm.get()), |
|
1387 aMsg, false, &cloneData, &cpows, aPrincipal, nullptr); |
|
1388 } |
|
1389 return true; |
|
1390 } |
|
1391 |
|
1392 bool |
|
1393 ContentChild::RecvGeolocationUpdate(const GeoPosition& somewhere) |
|
1394 { |
|
1395 nsCOMPtr<nsIGeolocationUpdate> gs = do_GetService("@mozilla.org/geolocation/service;1"); |
|
1396 if (!gs) { |
|
1397 return true; |
|
1398 } |
|
1399 nsCOMPtr<nsIDOMGeoPosition> position = somewhere; |
|
1400 gs->Update(position); |
|
1401 return true; |
|
1402 } |
|
1403 |
|
1404 bool |
|
1405 ContentChild::RecvAddPermission(const IPC::Permission& permission) |
|
1406 { |
|
1407 #if MOZ_PERMISSIONS |
|
1408 nsCOMPtr<nsIPermissionManager> permissionManagerIface = |
|
1409 do_GetService(NS_PERMISSIONMANAGER_CONTRACTID); |
|
1410 nsPermissionManager* permissionManager = |
|
1411 static_cast<nsPermissionManager*>(permissionManagerIface.get()); |
|
1412 NS_ABORT_IF_FALSE(permissionManager, |
|
1413 "We have no permissionManager in the Content process !"); |
|
1414 |
|
1415 nsCOMPtr<nsIURI> uri; |
|
1416 NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("http://") + nsCString(permission.host)); |
|
1417 NS_ENSURE_TRUE(uri, true); |
|
1418 |
|
1419 nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager(); |
|
1420 MOZ_ASSERT(secMan); |
|
1421 |
|
1422 nsCOMPtr<nsIPrincipal> principal; |
|
1423 nsresult rv = secMan->GetAppCodebasePrincipal(uri, permission.appId, |
|
1424 permission.isInBrowserElement, |
|
1425 getter_AddRefs(principal)); |
|
1426 NS_ENSURE_SUCCESS(rv, true); |
|
1427 |
|
1428 permissionManager->AddInternal(principal, |
|
1429 nsCString(permission.type), |
|
1430 permission.capability, |
|
1431 0, |
|
1432 permission.expireType, |
|
1433 permission.expireTime, |
|
1434 nsPermissionManager::eNotify, |
|
1435 nsPermissionManager::eNoDBOperation); |
|
1436 #endif |
|
1437 |
|
1438 return true; |
|
1439 } |
|
1440 |
|
1441 bool |
|
1442 ContentChild::RecvScreenSizeChanged(const gfxIntSize& size) |
|
1443 { |
|
1444 #ifdef ANDROID |
|
1445 mScreenSize = size; |
|
1446 #else |
|
1447 NS_RUNTIMEABORT("Message currently only expected on android"); |
|
1448 #endif |
|
1449 return true; |
|
1450 } |
|
1451 |
|
1452 bool |
|
1453 ContentChild::RecvFlushMemory(const nsString& reason) |
|
1454 { |
|
1455 #ifdef MOZ_NUWA_PROCESS |
|
1456 if (IsNuwaProcess()) { |
|
1457 // Don't flush memory in the nuwa process: the GC thread could be frozen. |
|
1458 return true; |
|
1459 } |
|
1460 #endif |
|
1461 nsCOMPtr<nsIObserverService> os = |
|
1462 mozilla::services::GetObserverService(); |
|
1463 if (os) |
|
1464 os->NotifyObservers(nullptr, "memory-pressure", reason.get()); |
|
1465 return true; |
|
1466 } |
|
1467 |
|
1468 bool |
|
1469 ContentChild::RecvActivateA11y() |
|
1470 { |
|
1471 #ifdef ACCESSIBILITY |
|
1472 // Start accessibility in content process if it's running in chrome |
|
1473 // process. |
|
1474 nsCOMPtr<nsIAccessibilityService> accService = |
|
1475 do_GetService("@mozilla.org/accessibilityService;1"); |
|
1476 #endif |
|
1477 return true; |
|
1478 } |
|
1479 |
|
1480 bool |
|
1481 ContentChild::RecvGarbageCollect() |
|
1482 { |
|
1483 // Rebroadcast the "child-gc-request" so that workers will GC. |
|
1484 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); |
|
1485 if (obs) { |
|
1486 obs->NotifyObservers(nullptr, "child-gc-request", nullptr); |
|
1487 } |
|
1488 nsJSContext::GarbageCollectNow(JS::gcreason::DOM_IPC); |
|
1489 return true; |
|
1490 } |
|
1491 |
|
1492 bool |
|
1493 ContentChild::RecvCycleCollect() |
|
1494 { |
|
1495 // Rebroadcast the "child-cc-request" so that workers will CC. |
|
1496 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); |
|
1497 if (obs) { |
|
1498 obs->NotifyObservers(nullptr, "child-cc-request", nullptr); |
|
1499 } |
|
1500 nsJSContext::CycleCollectNow(); |
|
1501 return true; |
|
1502 } |
|
1503 |
|
1504 #ifdef MOZ_NUWA_PROCESS |
|
1505 static void |
|
1506 OnFinishNuwaPreparation () |
|
1507 { |
|
1508 MakeNuwaProcess(); |
|
1509 } |
|
1510 #endif |
|
1511 |
|
1512 static void |
|
1513 PreloadSlowThings() |
|
1514 { |
|
1515 // This fetches and creates all the built-in stylesheets. |
|
1516 nsLayoutStylesheetCache::UserContentSheet(); |
|
1517 |
|
1518 TabChild::PreloadSlowThings(); |
|
1519 |
|
1520 } |
|
1521 |
|
1522 bool |
|
1523 ContentChild::RecvAppInfo(const nsCString& version, const nsCString& buildID, |
|
1524 const nsCString& name, const nsCString& UAName) |
|
1525 { |
|
1526 mAppInfo.version.Assign(version); |
|
1527 mAppInfo.buildID.Assign(buildID); |
|
1528 mAppInfo.name.Assign(name); |
|
1529 mAppInfo.UAName.Assign(UAName); |
|
1530 |
|
1531 if (!Preferences::GetBool("dom.ipc.processPrelaunch.enabled", false)) { |
|
1532 return true; |
|
1533 } |
|
1534 |
|
1535 // If we're part of the mozbrowser machinery, go ahead and start |
|
1536 // preloading things. We can only do this for mozbrowser because |
|
1537 // PreloadSlowThings() may set the docshell of the first TabChild |
|
1538 // inactive, and we can only safely restore it to active from |
|
1539 // BrowserElementChild.js. |
|
1540 if ((mIsForApp || mIsForBrowser) |
|
1541 #ifdef MOZ_NUWA_PROCESS |
|
1542 && !IsNuwaProcess() |
|
1543 #endif |
|
1544 ) { |
|
1545 PreloadSlowThings(); |
|
1546 } |
|
1547 |
|
1548 #ifdef MOZ_NUWA_PROCESS |
|
1549 if (IsNuwaProcess()) { |
|
1550 ContentChild::GetSingleton()->RecvGarbageCollect(); |
|
1551 MessageLoop::current()->PostTask( |
|
1552 FROM_HERE, NewRunnableFunction(OnFinishNuwaPreparation)); |
|
1553 } |
|
1554 #endif |
|
1555 |
|
1556 return true; |
|
1557 } |
|
1558 |
|
1559 bool |
|
1560 ContentChild::RecvLastPrivateDocShellDestroyed() |
|
1561 { |
|
1562 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); |
|
1563 obs->NotifyObservers(nullptr, "last-pb-context-exited", nullptr); |
|
1564 return true; |
|
1565 } |
|
1566 |
|
1567 bool |
|
1568 ContentChild::RecvFilePathUpdate(const nsString& aStorageType, |
|
1569 const nsString& aStorageName, |
|
1570 const nsString& aPath, |
|
1571 const nsCString& aReason) |
|
1572 { |
|
1573 nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(aStorageType, aStorageName, aPath); |
|
1574 |
|
1575 nsString reason; |
|
1576 CopyASCIItoUTF16(aReason, reason); |
|
1577 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); |
|
1578 obs->NotifyObservers(dsf, "file-watcher-update", reason.get()); |
|
1579 return true; |
|
1580 } |
|
1581 |
|
1582 bool |
|
1583 ContentChild::RecvFileSystemUpdate(const nsString& aFsName, |
|
1584 const nsString& aVolumeName, |
|
1585 const int32_t& aState, |
|
1586 const int32_t& aMountGeneration, |
|
1587 const bool& aIsMediaPresent, |
|
1588 const bool& aIsSharing, |
|
1589 const bool& aIsFormatting) |
|
1590 { |
|
1591 #ifdef MOZ_WIDGET_GONK |
|
1592 nsRefPtr<nsVolume> volume = new nsVolume(aFsName, aVolumeName, aState, |
|
1593 aMountGeneration, aIsMediaPresent, |
|
1594 aIsSharing, aIsFormatting); |
|
1595 |
|
1596 nsRefPtr<nsVolumeService> vs = nsVolumeService::GetSingleton(); |
|
1597 if (vs) { |
|
1598 vs->UpdateVolume(volume); |
|
1599 } |
|
1600 #else |
|
1601 // Remove warnings about unused arguments |
|
1602 unused << aFsName; |
|
1603 unused << aVolumeName; |
|
1604 unused << aState; |
|
1605 unused << aMountGeneration; |
|
1606 unused << aIsMediaPresent; |
|
1607 unused << aIsSharing; |
|
1608 unused << aIsFormatting; |
|
1609 #endif |
|
1610 return true; |
|
1611 } |
|
1612 |
|
1613 bool |
|
1614 ContentChild::RecvNotifyProcessPriorityChanged( |
|
1615 const hal::ProcessPriority& aPriority) |
|
1616 { |
|
1617 nsCOMPtr<nsIObserverService> os = services::GetObserverService(); |
|
1618 NS_ENSURE_TRUE(os, true); |
|
1619 |
|
1620 nsRefPtr<nsHashPropertyBag> props = new nsHashPropertyBag(); |
|
1621 props->SetPropertyAsInt32(NS_LITERAL_STRING("priority"), |
|
1622 static_cast<int32_t>(aPriority)); |
|
1623 |
|
1624 os->NotifyObservers(static_cast<nsIPropertyBag2*>(props), |
|
1625 "ipc:process-priority-changed", nullptr); |
|
1626 return true; |
|
1627 } |
|
1628 |
|
1629 bool |
|
1630 ContentChild::RecvMinimizeMemoryUsage() |
|
1631 { |
|
1632 #ifdef MOZ_NUWA_PROCESS |
|
1633 if (IsNuwaProcess()) { |
|
1634 // Don't minimize memory in the nuwa process: it will perform GC, but the |
|
1635 // GC thread could be frozen. |
|
1636 return true; |
|
1637 } |
|
1638 #endif |
|
1639 nsCOMPtr<nsIMemoryReporterManager> mgr = |
|
1640 do_GetService("@mozilla.org/memory-reporter-manager;1"); |
|
1641 NS_ENSURE_TRUE(mgr, true); |
|
1642 |
|
1643 mgr->MinimizeMemoryUsage(/* callback = */ nullptr); |
|
1644 return true; |
|
1645 } |
|
1646 |
|
1647 bool |
|
1648 ContentChild::RecvNotifyPhoneStateChange(const nsString& aState) |
|
1649 { |
|
1650 nsCOMPtr<nsIObserverService> os = services::GetObserverService(); |
|
1651 if (os) { |
|
1652 os->NotifyObservers(nullptr, "phone-state-changed", aState.get()); |
|
1653 } |
|
1654 return true; |
|
1655 } |
|
1656 |
|
1657 void |
|
1658 ContentChild::AddIdleObserver(nsIObserver* aObserver, uint32_t aIdleTimeInS) |
|
1659 { |
|
1660 MOZ_ASSERT(aObserver, "null idle observer"); |
|
1661 // Make sure aObserver isn't released while we wait for the parent |
|
1662 aObserver->AddRef(); |
|
1663 SendAddIdleObserver(reinterpret_cast<uint64_t>(aObserver), aIdleTimeInS); |
|
1664 mIdleObservers.PutEntry(aObserver); |
|
1665 } |
|
1666 |
|
1667 void |
|
1668 ContentChild::RemoveIdleObserver(nsIObserver* aObserver, uint32_t aIdleTimeInS) |
|
1669 { |
|
1670 MOZ_ASSERT(aObserver, "null idle observer"); |
|
1671 SendRemoveIdleObserver(reinterpret_cast<uint64_t>(aObserver), aIdleTimeInS); |
|
1672 aObserver->Release(); |
|
1673 mIdleObservers.RemoveEntry(aObserver); |
|
1674 } |
|
1675 |
|
1676 bool |
|
1677 ContentChild::RecvNotifyIdleObserver(const uint64_t& aObserver, |
|
1678 const nsCString& aTopic, |
|
1679 const nsString& aTimeStr) |
|
1680 { |
|
1681 nsIObserver* observer = reinterpret_cast<nsIObserver*>(aObserver); |
|
1682 if (mIdleObservers.Contains(observer)) { |
|
1683 observer->Observe(nullptr, aTopic.get(), aTimeStr.get()); |
|
1684 } else { |
|
1685 NS_WARNING("Received notification for an idle observer that was removed."); |
|
1686 } |
|
1687 return true; |
|
1688 } |
|
1689 |
|
1690 bool |
|
1691 ContentChild::RecvLoadAndRegisterSheet(const URIParams& aURI, const uint32_t& aType) |
|
1692 { |
|
1693 nsCOMPtr<nsIURI> uri = DeserializeURI(aURI); |
|
1694 if (!uri) { |
|
1695 return true; |
|
1696 } |
|
1697 |
|
1698 nsStyleSheetService *sheetService = nsStyleSheetService::GetInstance(); |
|
1699 if (sheetService) { |
|
1700 sheetService->LoadAndRegisterSheet(uri, aType); |
|
1701 } |
|
1702 |
|
1703 return true; |
|
1704 } |
|
1705 |
|
1706 bool |
|
1707 ContentChild::RecvUnregisterSheet(const URIParams& aURI, const uint32_t& aType) |
|
1708 { |
|
1709 nsCOMPtr<nsIURI> uri = DeserializeURI(aURI); |
|
1710 if (!uri) { |
|
1711 return true; |
|
1712 } |
|
1713 |
|
1714 nsStyleSheetService *sheetService = nsStyleSheetService::GetInstance(); |
|
1715 if (sheetService) { |
|
1716 sheetService->UnregisterSheet(uri, aType); |
|
1717 } |
|
1718 |
|
1719 return true; |
|
1720 } |
|
1721 |
|
1722 #ifdef MOZ_NUWA_PROCESS |
|
1723 class CallNuwaSpawn : public nsRunnable |
|
1724 { |
|
1725 public: |
|
1726 NS_IMETHOD Run() |
|
1727 { |
|
1728 NuwaSpawn(); |
|
1729 if (IsNuwaProcess()) { |
|
1730 return NS_OK; |
|
1731 } |
|
1732 |
|
1733 // In the new process. |
|
1734 ContentChild* child = ContentChild::GetSingleton(); |
|
1735 child->SetProcessName(NS_LITERAL_STRING("(Preallocated app)"), false); |
|
1736 mozilla::ipc::Transport* transport = child->GetTransport(); |
|
1737 int fd = transport->GetFileDescriptor(); |
|
1738 transport->ResetFileDescriptor(fd); |
|
1739 |
|
1740 IToplevelProtocol* toplevel = child->GetFirstOpenedActors(); |
|
1741 while (toplevel != nullptr) { |
|
1742 transport = toplevel->GetTransport(); |
|
1743 fd = transport->GetFileDescriptor(); |
|
1744 transport->ResetFileDescriptor(fd); |
|
1745 |
|
1746 toplevel = toplevel->getNext(); |
|
1747 } |
|
1748 |
|
1749 // Perform other after-fork initializations. |
|
1750 InitOnContentProcessCreated(); |
|
1751 |
|
1752 return NS_OK; |
|
1753 } |
|
1754 }; |
|
1755 |
|
1756 static void |
|
1757 DoNuwaFork() |
|
1758 { |
|
1759 NS_ASSERTION(NuwaSpawnPrepare != nullptr, |
|
1760 "NuwaSpawnPrepare() is not available!"); |
|
1761 NuwaSpawnPrepare(); // NuwaSpawn will be blocked. |
|
1762 |
|
1763 { |
|
1764 nsCOMPtr<nsIRunnable> callSpawn(new CallNuwaSpawn()); |
|
1765 NS_DispatchToMainThread(callSpawn); |
|
1766 } |
|
1767 |
|
1768 // IOThread should be blocked here for waiting NuwaSpawn(). |
|
1769 NS_ASSERTION(NuwaSpawnWait != nullptr, |
|
1770 "NuwaSpawnWait() is not available!"); |
|
1771 NuwaSpawnWait(); // Now! NuwaSpawn can go. |
|
1772 // Here, we can make sure the spawning was finished. |
|
1773 } |
|
1774 |
|
1775 /** |
|
1776 * This function should keep IO thread in a stable state and freeze it |
|
1777 * until the spawning is finished. |
|
1778 */ |
|
1779 static void |
|
1780 RunNuwaFork() |
|
1781 { |
|
1782 if (NuwaCheckpointCurrentThread()) { |
|
1783 DoNuwaFork(); |
|
1784 } |
|
1785 } |
|
1786 #endif |
|
1787 |
|
1788 bool |
|
1789 ContentChild::RecvNuwaFork() |
|
1790 { |
|
1791 #ifdef MOZ_NUWA_PROCESS |
|
1792 if (sNuwaForking) { // No reentry. |
|
1793 return true; |
|
1794 } |
|
1795 sNuwaForking = true; |
|
1796 |
|
1797 // We want to ensure that the PBackground actor gets cloned in the Nuwa |
|
1798 // process before we freeze. Also, we have to do this to avoid deadlock. |
|
1799 // Protocols that are "opened" (e.g. PBackground, PCompositor) block the |
|
1800 // main thread to wait for the IPC thread during the open operation. |
|
1801 // NuwaSpawnWait() blocks the IPC thread to wait for the main thread when |
|
1802 // the Nuwa process is forked. Unless we ensure that the two cannot happen |
|
1803 // at the same time then we risk deadlock. Spinning the event loop here |
|
1804 // guarantees the ordering is safe for PBackground. |
|
1805 while (!BackgroundChild::GetForCurrentThread()) { |
|
1806 if (NS_WARN_IF(!NS_ProcessNextEvent())) { |
|
1807 return false; |
|
1808 } |
|
1809 } |
|
1810 |
|
1811 MessageLoop* ioloop = XRE_GetIOMessageLoop(); |
|
1812 ioloop->PostTask(FROM_HERE, NewRunnableFunction(RunNuwaFork)); |
|
1813 return true; |
|
1814 #else |
|
1815 return false; // Makes the underlying IPC channel abort. |
|
1816 #endif |
|
1817 } |
|
1818 |
|
1819 } // namespace dom |
|
1820 } // namespace mozilla |
|
1821 |
|
1822 extern "C" { |
|
1823 |
|
1824 #if defined(MOZ_NUWA_PROCESS) |
|
1825 NS_EXPORT void |
|
1826 GetProtoFdInfos(NuwaProtoFdInfo* aInfoList, |
|
1827 size_t aInfoListSize, |
|
1828 size_t* aInfoSize) |
|
1829 { |
|
1830 size_t i = 0; |
|
1831 |
|
1832 mozilla::dom::ContentChild* content = |
|
1833 mozilla::dom::ContentChild::GetSingleton(); |
|
1834 aInfoList[i].protoId = content->GetProtocolId(); |
|
1835 aInfoList[i].originFd = |
|
1836 content->GetTransport()->GetFileDescriptor(); |
|
1837 i++; |
|
1838 |
|
1839 for (IToplevelProtocol* actor = content->GetFirstOpenedActors(); |
|
1840 actor != nullptr; |
|
1841 actor = actor->getNext()) { |
|
1842 if (i >= aInfoListSize) { |
|
1843 NS_RUNTIMEABORT("Too many top level protocols!"); |
|
1844 } |
|
1845 |
|
1846 aInfoList[i].protoId = actor->GetProtocolId(); |
|
1847 aInfoList[i].originFd = |
|
1848 actor->GetTransport()->GetFileDescriptor(); |
|
1849 i++; |
|
1850 } |
|
1851 |
|
1852 if (i > NUWA_TOPLEVEL_MAX) { |
|
1853 NS_RUNTIMEABORT("Too many top level protocols!"); |
|
1854 } |
|
1855 *aInfoSize = i; |
|
1856 } |
|
1857 |
|
1858 class RunAddNewIPCProcess : public nsRunnable |
|
1859 { |
|
1860 public: |
|
1861 RunAddNewIPCProcess(pid_t aPid, |
|
1862 nsTArray<mozilla::ipc::ProtocolFdMapping>& aMaps) |
|
1863 : mPid(aPid) |
|
1864 { |
|
1865 mMaps.SwapElements(aMaps); |
|
1866 } |
|
1867 |
|
1868 NS_IMETHOD Run() |
|
1869 { |
|
1870 mozilla::dom::ContentChild::GetSingleton()-> |
|
1871 SendAddNewProcess(mPid, mMaps); |
|
1872 |
|
1873 MOZ_ASSERT(sNuwaForking); |
|
1874 sNuwaForking = false; |
|
1875 |
|
1876 return NS_OK; |
|
1877 } |
|
1878 |
|
1879 private: |
|
1880 pid_t mPid; |
|
1881 nsTArray<mozilla::ipc::ProtocolFdMapping> mMaps; |
|
1882 }; |
|
1883 |
|
1884 /** |
|
1885 * AddNewIPCProcess() is called by Nuwa process to tell the parent |
|
1886 * process that a new process is created. |
|
1887 * |
|
1888 * In the newly created process, ResetContentChildTransport() is called to |
|
1889 * reset fd for the IPC Channel and the session. |
|
1890 */ |
|
1891 NS_EXPORT void |
|
1892 AddNewIPCProcess(pid_t aPid, NuwaProtoFdInfo* aInfoList, size_t aInfoListSize) |
|
1893 { |
|
1894 nsTArray<mozilla::ipc::ProtocolFdMapping> maps; |
|
1895 |
|
1896 for (size_t i = 0; i < aInfoListSize; i++) { |
|
1897 int _fd = aInfoList[i].newFds[NUWA_NEWFD_PARENT]; |
|
1898 mozilla::ipc::FileDescriptor fd(_fd); |
|
1899 mozilla::ipc::ProtocolFdMapping map(aInfoList[i].protoId, fd); |
|
1900 maps.AppendElement(map); |
|
1901 } |
|
1902 |
|
1903 nsRefPtr<RunAddNewIPCProcess> runner = new RunAddNewIPCProcess(aPid, maps); |
|
1904 NS_DispatchToMainThread(runner); |
|
1905 } |
|
1906 |
|
1907 NS_EXPORT void |
|
1908 OnNuwaProcessReady() |
|
1909 { |
|
1910 mozilla::dom::ContentChild* content = |
|
1911 mozilla::dom::ContentChild::GetSingleton(); |
|
1912 content->SendNuwaReady(); |
|
1913 } |
|
1914 |
|
1915 NS_EXPORT void |
|
1916 AfterNuwaFork() |
|
1917 { |
|
1918 SetCurrentProcessPrivileges(base::PRIVILEGES_DEFAULT); |
|
1919 } |
|
1920 |
|
1921 #endif // MOZ_NUWA_PROCESS |
|
1922 |
|
1923 } |