author | Cervantes Yu <cyu@mozilla.com> |
Fri, 14 Aug 2015 15:41:54 +0800 | |
changeset 260718 | c46f4154cceac710d34729778b2528f1422962e0 |
parent 260717 | 7b1ba1e20dd9c55cfc80cc1c553cafa90ce0b8f9 |
child 260719 | 86347848ca3b600c0601e77f244be42040ecc227 |
push id | 29322 |
push user | kwierso@gmail.com |
push date | Thu, 03 Sep 2015 20:41:12 +0000 |
treeherder | mozilla-central@cf073093dc61 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | khuey |
bugs | 1192255 |
milestone | 43.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -2169,20 +2169,17 @@ ContentChild::RecvScreenSizeChanged(cons #endif return true; } bool ContentChild::RecvFlushMemory(const nsString& reason) { #ifdef MOZ_NUWA_PROCESS - if (IsNuwaProcess()) { - // Don't flush memory in the nuwa process: the GC thread could be frozen. - return true; - } + MOZ_ASSERT(!IsNuwaProcess() || !IsNuwaReady()); #endif nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService(); if (os) os->NotifyObservers(nullptr, "memory-pressure", reason.get()); return true; } @@ -2411,21 +2408,17 @@ ContentChild::RecvNotifyProcessPriorityC "ipc:process-priority-changed", nullptr); return true; } bool ContentChild::RecvMinimizeMemoryUsage() { #ifdef MOZ_NUWA_PROCESS - if (IsNuwaProcess()) { - // Don't minimize memory in the nuwa process: it will perform GC, but the - // GC thread could be frozen. - return true; - } + MOZ_ASSERT(!IsNuwaProcess() || !IsNuwaReady()); #endif nsCOMPtr<nsIMemoryReporterManager> mgr = do_GetService("@mozilla.org/memory-reporter-manager;1"); NS_ENSURE_TRUE(mgr, true); mgr->MinimizeMemoryUsage(/* callback = */ nullptr); return true; }
--- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -677,16 +677,32 @@ static const char* sObserverTopics[] = { "profiler-stopped", "profiler-paused", "profiler-resumed", "profiler-subprocess-gather", "profiler-subprocess", #endif }; +#ifdef MOZ_NUWA_PROCESS +// Contains the observer topics that can be sent to the Nuwa process after it +// becomes ready. The ContentParent instance will unregister sObserverTopics +// if not listed in sNuwaSafeObserverTopics. +static const char* sNuwaSafeObserverTopics[] = { + "xpcom-shutdown", + "profile-before-change", +#ifdef MOZ_WIDGET_GONK + "phone-state-changed", +#endif +#ifdef ACCESSIBILITY + "a11y-init-or-shutdown", +#endif + "nsPref:Changed" +}; +#endif /* static */ already_AddRefed<ContentParent> ContentParent::RunNuwaProcess() { MOZ_ASSERT(NS_IsMainThread()); nsRefPtr<ContentParent> nuwaProcess = new ContentParent(/* aApp = */ nullptr, /* aOpener = */ nullptr, /* aIsForBrowser = */ false, @@ -2918,25 +2934,62 @@ ContentParent::ForkNewProcess(bool aBloc if (mNuwaParent->ForkNewProcess(pid, mozilla::Move(fds), aBlocking)) { OnNewProcessCreated(pid, mozilla::Move(fds)); } #else NS_ERROR("ContentParent::ForkNewProcess() not implemented!"); #endif } +#ifdef MOZ_NUWA_PROCESS +// Keep only observer topics listed in sNuwaSafeObserverTopics and unregister +// all the other registered topics. +static void +KeepNuwaSafeObserverTopics(ContentParent* aNuwaContentParent) +{ + MOZ_ASSERT(aNuwaContentParent && aNuwaContentParent->IsNuwaProcess()); + + nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); + if (!obs) { + return; + } + + size_t topicLength = ArrayLength(sObserverTopics); + for (size_t i = 0; i < topicLength; ++i) { + bool nuwaSafe = false; + size_t safeTopicLength = ArrayLength(sNuwaSafeObserverTopics); + + for (size_t j = 0; j < safeTopicLength; j++) { + if (!nsCRT::strcmp(sObserverTopics[i], + sNuwaSafeObserverTopics[j])) { + // In the whitelist: don't need to unregister. + nuwaSafe = true; + break; + } + } + + if (!nuwaSafe) { + obs->RemoveObserver(aNuwaContentParent, sObserverTopics[i]); + } + } + +} +#endif + void ContentParent::OnNuwaReady() { #ifdef MOZ_NUWA_PROCESS // Protection from unauthorized IPC message is done in PNuwa protocol. // Just assert that this actor is really for the Nuwa process. MOZ_ASSERT(IsNuwaProcess()); sNuwaReady = true; + KeepNuwaSafeObserverTopics(this); + PreallocatedProcessManager::OnNuwaReady(); return; #else NS_ERROR("ContentParent::OnNuwaReady() not implemented!"); return; #endif } @@ -3020,69 +3073,67 @@ ContentParent::Observe(nsISupports* aSub NS_ProcessNextEvent(nullptr, true); } NS_ASSERTION(!mSubprocess, "Close should have nulled mSubprocess"); } if (!mIsAlive || !mSubprocess) return NS_OK; + // The Nuwa process unregisters the topics after it becomes ready except for + // the ones listed in sNuwaSafeObserverTopics. If the topic needs to be + // observed by the Nuwa process, either for: + // 1. The topic is safe for the Nuwa process, either: + // 1.1 The state can safely happen (only run on the main thread) in the Nuwa + // process (e.g. "a11y-init-or-shutdown"), or + // 1.2 The topic doesn't send an IPC message (e.g. "xpcom-shutdown"). + // 2. The topic needs special handling (e.g. nsPref:Changed), + // add the topic to sNuwaSafeObserverTopics and then handle it if necessary. + // listening for memory pressure event if (!strcmp(aTopic, "memory-pressure") && !StringEndsWith(nsDependentString(aData), NS_LITERAL_STRING("-no-forward"))) { unused << SendFlushMemory(nsDependentString(aData)); } // listening for remotePrefs... else if (!strcmp(aTopic, "nsPref:changed")) { // We know prefs are ASCII here. NS_LossyConvertUTF16toASCII strData(aData); PrefSetting pref(strData, null_t(), null_t()); Preferences::GetPreference(&pref); #ifdef MOZ_NUWA_PROCESS - if (IsNuwaProcess() && PreallocatedProcessManager::IsNuwaReady()) { + if (IsReadyNuwaProcess()) { // Don't send the pref update to the Nuwa process. Save the update // to send to the forked child. if (!sNuwaPrefUpdates) { sNuwaPrefUpdates = new nsTArray<PrefSetting>(); } sNuwaPrefUpdates->AppendElement(pref); } else if (!SendPreferenceUpdate(pref)) { return NS_ERROR_NOT_AVAILABLE; } #else if (!SendPreferenceUpdate(pref)) { return NS_ERROR_NOT_AVAILABLE; } #endif } else if (!strcmp(aTopic, NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC)) { - NS_ConvertUTF16toUTF8 dataStr(aData); - const char *offline = dataStr.get(); -#ifdef MOZ_NUWA_PROCESS - if (!(IsNuwaReady() && IsNuwaProcess())) { -#endif - if (!SendSetOffline(!strcmp(offline, "true") ? true : false)) { - return NS_ERROR_NOT_AVAILABLE; - } -#ifdef MOZ_NUWA_PROCESS - } -#endif + NS_ConvertUTF16toUTF8 dataStr(aData); + const char *offline = dataStr.get(); + if (!SendSetOffline(!strcmp(offline, "true") ? true : false)) { + return NS_ERROR_NOT_AVAILABLE; + } } else if (!strcmp(aTopic, NS_IPC_IOSERVICE_SET_CONNECTIVITY_TOPIC)) { -#ifdef MOZ_NUWA_PROCESS - if (!(IsNuwaReady() && IsNuwaProcess())) { -#endif - if (!SendSetConnectivity(NS_LITERAL_STRING("true").Equals(aData))) { - return NS_ERROR_NOT_AVAILABLE; - } -#ifdef MOZ_NUWA_PROCESS + if (!SendSetConnectivity(NS_LITERAL_STRING("true").Equals(aData))) { + return NS_ERROR_NOT_AVAILABLE; } -#endif } // listening for alert notifications else if (!strcmp(aTopic, "alertfinished") || !strcmp(aTopic, "alertclickcallback") || !strcmp(aTopic, "alertshow") ) { if (!SendNotifyAlertsObserver(nsDependentCString(aTopic), nsDependentString(aData))) return NS_ERROR_NOT_AVAILABLE; @@ -3098,23 +3149,17 @@ ContentParent::Observe(nsISupports* aSub } else if (!strcmp(aTopic, "last-pb-context-exited")) { unused << SendLastPrivateDocShellDestroyed(); } else if (!strcmp(aTopic, "file-watcher-update")) { nsCString creason; CopyUTF16toUTF8(aData, creason); DeviceStorageFile* file = static_cast<DeviceStorageFile*>(aSubject); - -#ifdef MOZ_NUWA_PROCESS - if (!(IsNuwaReady() && IsNuwaProcess())) -#endif - { - unused << SendFilePathUpdate(file->mStorageType, file->mStorageName, file->mPath, creason); - } + unused << SendFilePathUpdate(file->mStorageType, file->mStorageName, file->mPath, creason); } #ifdef MOZ_WIDGET_GONK else if(!strcmp(aTopic, NS_VOLUME_STATE_CHANGED)) { nsCOMPtr<nsIVolume> vol = do_QueryInterface(aSubject); if (!vol) { return NS_ERROR_NOT_AVAILABLE; } @@ -3137,37 +3182,27 @@ ContentParent::Observe(nsISupports* aSub vol->GetIsMediaPresent(&isMediaPresent); vol->GetIsSharing(&isSharing); vol->GetIsFormatting(&isFormatting); vol->GetIsFake(&isFake); vol->GetIsUnmounting(&isUnmounting); vol->GetIsRemovable(&isRemovable); vol->GetIsHotSwappable(&isHotSwappable); -#ifdef MOZ_NUWA_PROCESS - if (!(IsNuwaReady() && IsNuwaProcess())) -#endif - { - unused << SendFileSystemUpdate(volName, mountPoint, state, - mountGeneration, isMediaPresent, - isSharing, isFormatting, isFake, - isUnmounting, isRemovable, isHotSwappable); - } + unused << SendFileSystemUpdate(volName, mountPoint, state, + mountGeneration, isMediaPresent, + isSharing, isFormatting, isFake, + isUnmounting, isRemovable, isHotSwappable); } else if (!strcmp(aTopic, "phone-state-changed")) { nsString state(aData); unused << SendNotifyPhoneStateChange(state); } else if(!strcmp(aTopic, NS_VOLUME_REMOVED)) { -#ifdef MOZ_NUWA_PROCESS - if (!(IsNuwaReady() && IsNuwaProcess())) -#endif - { - nsString volName(aData); - unused << SendVolumeRemoved(volName); - } + nsString volName(aData); + unused << SendVolumeRemoved(volName); } #endif #ifdef ACCESSIBILITY // Make sure accessibility is running in content process when accessibility // gets initiated in chrome process. else if (aData && (*aData == '1') && !strcmp(aTopic, "a11y-init-or-shutdown")) { unused << SendActivateA11y(); @@ -4463,22 +4498,20 @@ ContentParent::DoSendAsyncMessage(JSCont if (!BuildClonedMessageDataForParent(this, aData, data)) { return false; } InfallibleTArray<CpowEntry> cpows; jsipc::CPOWManager* mgr = GetCPOWManager(); if (aCpows && (!mgr || !mgr->Wrap(aCx, aCpows, &cpows))) { return false; } -#ifdef MOZ_NUWA_PROCESS - if (IsNuwaProcess() && IsNuwaReady()) { + if (IsReadyNuwaProcess()) { // Nuwa won't receive frame messages after it is frozen. return true; } -#endif return SendAsyncMessage(nsString(aMessage), data, cpows, Principal(aPrincipal)); } bool ContentParent::CheckPermission(const nsAString& aPermission) { return AssertAppProcessPermission(this, NS_ConvertUTF16toUTF8(aPermission).get()); }
--- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -255,16 +255,25 @@ public: virtual bool IsForBrowser() override { return mIsForBrowser; } #ifdef MOZ_NUWA_PROCESS bool IsNuwaProcess(); #endif + // A shorthand for checking if the Nuwa process is ready. + bool IsReadyNuwaProcess() { +#ifdef MOZ_NUWA_PROCESS + return IsNuwaProcess() && IsNuwaReady(); +#else + return false; +#endif + } + GeckoChildProcessHost* Process() { return mSubprocess; } int32_t Pid(); ContentParent* Opener() { return mOpener;
--- a/ipc/glue/MessageLink.cpp +++ b/ipc/glue/MessageLink.cpp @@ -182,16 +182,17 @@ ProcessLink::SendMessage(Message *msg) #ifdef MOZ_NUWA_PROCESS // Parent to child: check whether we are sending some unexpected message to // the Nuwa process. if (mIsToNuwaProcess && mozilla::dom::ContentParent::IsNuwaReady()) { switch (msg->type()) { case mozilla::dom::PNuwa::Msg_Fork__ID: case mozilla::dom::PNuwa::Reply_AddNewProcess__ID: case mozilla::dom::PContent::Msg_NotifyPhoneStateChange__ID: + case mozilla::dom::PContent::Msg_ActivateA11y__ID: case mozilla::hal_sandbox::PHal::Msg_NotifyNetworkChange__ID: case GOODBYE_MESSAGE_TYPE: break; default: #ifdef DEBUG MOZ_CRASH(); #else // In optimized build, message will be dropped.