diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 1f556e4dfaef..d60e132d5ebd 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -2957,30 +2957,8 @@ ContentParent::Observe(nsISupports* aSubject, const char* aTopic, if (!strcmp(aTopic, "nsPref:changed")) { // A pref changed. If it's not on the blacklist, inform child processes. -#define BLACKLIST_ENTRY(s) \ - { s, (sizeof(s) / sizeof(char16_t)) - 1 } - struct BlacklistEntry { - const char16_t* mPrefBranch; - size_t mLen; - }; - // These prefs are not useful in child processes. - static const BlacklistEntry sContentPrefBranchBlacklist[] = { - BLACKLIST_ENTRY(u"app.update.lastUpdateTime."), - BLACKLIST_ENTRY(u"datareporting.policy."), - BLACKLIST_ENTRY(u"browser.safebrowsing.provider."), - BLACKLIST_ENTRY(u"browser.shell."), - BLACKLIST_ENTRY(u"browser.slowStartup."), - BLACKLIST_ENTRY(u"extensions.getAddons.cache."), - BLACKLIST_ENTRY(u"media.gmp-manager."), - BLACKLIST_ENTRY(u"media.gmp-gmpopenh264."), - BLACKLIST_ENTRY(u"privacy.sanitize."), - }; -#undef BLACKLIST_ENTRY - - for (const auto& entry : sContentPrefBranchBlacklist) { - if (NS_strncmp(entry.mPrefBranch, aData, entry.mLen) == 0) { - return NS_OK; - } + if (!ShouldSyncPreference(aData)) { + return NS_OK; } // We know prefs are ASCII here. @@ -3128,6 +3106,37 @@ ContentParent::Observe(nsISupports* aSubject, const char* aTopic, return NS_OK; } +/* static */ +bool ContentParent::ShouldSyncPreference(const char16_t* aData) { +#define BLACKLIST_ENTRY(s) \ + { s, (sizeof(s) / sizeof(char16_t)) - 1 } + struct BlacklistEntry { + const char16_t* mPrefBranch; + size_t mLen; + }; + // These prefs are not useful in child processes. + static const BlacklistEntry sContentPrefBranchBlacklist[] = { + BLACKLIST_ENTRY(u"app.update.lastUpdateTime."), + BLACKLIST_ENTRY(u"datareporting.policy."), + BLACKLIST_ENTRY(u"browser.safebrowsing.provider."), + BLACKLIST_ENTRY(u"browser.shell."), + BLACKLIST_ENTRY(u"browser.slowStartup."), + BLACKLIST_ENTRY(u"browser.startup."), + BLACKLIST_ENTRY(u"extensions.getAddons.cache."), + BLACKLIST_ENTRY(u"media.gmp-manager."), + BLACKLIST_ENTRY(u"media.gmp-gmpopenh264."), + BLACKLIST_ENTRY(u"privacy.sanitize."), + }; +#undef BLACKLIST_ENTRY + + for (const auto& entry : sContentPrefBranchBlacklist) { + if (NS_strncmp(entry.mPrefBranch, aData, entry.mLen) == 0) { + return false; + } + } + return true; +} + void ContentParent::UpdateNetworkLinkType() { nsresult rv; nsCOMPtr nls = diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index 5afd06ddf282..e2e5a8de7d2a 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -1216,6 +1216,8 @@ class ContentParent final : public PContentParent, void UpdateNetworkLinkType(); + static bool ShouldSyncPreference(const char16_t* aData); + private: // Released in ActorDestroy; deliberately not exposed to the CC. RefPtr mSelfRef; diff --git a/gfx/ipc/GPUParent.cpp b/gfx/ipc/GPUParent.cpp index f76d3cb537e3..d01863909a1a 100644 --- a/gfx/ipc/GPUParent.cpp +++ b/gfx/ipc/GPUParent.cpp @@ -342,6 +342,11 @@ mozilla::ipc::IPCResult GPUParent::RecvUpdateVar(const GfxVarUpdate& aUpdate) { return IPC_OK(); } +mozilla::ipc::IPCResult GPUParent::RecvPreferenceUpdate(const Pref& aPref) { + Preferences::SetPreference(aPref); + return IPC_OK(); +} + static void CopyFeatureChange(Feature aFeature, Maybe* aOut) { FeatureState& feature = gfxConfig::GetFeature(aFeature); if (feature.DisabledByDefault() || feature.IsEnabled()) { diff --git a/gfx/ipc/GPUParent.h b/gfx/ipc/GPUParent.h index ed47be459b23..6ed9d9c236a2 100644 --- a/gfx/ipc/GPUParent.h +++ b/gfx/ipc/GPUParent.h @@ -57,6 +57,7 @@ class GPUParent final : public PGPUParent { Endpoint&& aEndpoint); mozilla::ipc::IPCResult RecvUpdatePref(const GfxPrefSetting& pref); mozilla::ipc::IPCResult RecvUpdateVar(const GfxVarUpdate& pref); + mozilla::ipc::IPCResult RecvPreferenceUpdate(const Pref& pref); mozilla::ipc::IPCResult RecvNewContentCompositorManager( Endpoint&& aEndpoint); mozilla::ipc::IPCResult RecvNewContentImageBridge( diff --git a/gfx/ipc/GPUProcessManager.cpp b/gfx/ipc/GPUProcessManager.cpp index 0f52cc97a07c..7a306facd0b8 100644 --- a/gfx/ipc/GPUProcessManager.cpp +++ b/gfx/ipc/GPUProcessManager.cpp @@ -10,6 +10,7 @@ #include "GPUProcessHost.h" #include "GPUProcessListener.h" #include "mozilla/MemoryReportingProcess.h" +#include "mozilla/Preferences.h" #include "mozilla/Sprintf.h" #include "mozilla/StaticPtr.h" #include "mozilla/StaticPrefs.h" @@ -84,6 +85,7 @@ GPUProcessManager::GPUProcessManager() mIdNamespace = AllocateNamespace(); mObserver = new Observer(this); nsContentUtils::RegisterShutdownObserver(mObserver); + Preferences::AddStrongObserver(mObserver, ""); mDeviceResetLastTime = TimeStamp::Now(); @@ -112,6 +114,8 @@ GPUProcessManager::Observer::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData) { if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) { mManager->OnXPCOMShutdown(); + } else if (!strcmp(aTopic, "nsPref:changed")) { + mManager->OnPreferenceChange(aData); } return NS_OK; } @@ -119,12 +123,32 @@ GPUProcessManager::Observer::Observe(nsISupports* aSubject, const char* aTopic, void GPUProcessManager::OnXPCOMShutdown() { if (mObserver) { nsContentUtils::UnregisterShutdownObserver(mObserver); + Preferences::RemoveObserver(mObserver, ""); mObserver = nullptr; } CleanShutdown(); } +void GPUProcessManager::OnPreferenceChange(const char16_t* aData) { + // A pref changed. If it's not on the blacklist, inform child processes. + if (!dom::ContentParent::ShouldSyncPreference(aData)) { + return; + } + + // We know prefs are ASCII here. + NS_LossyConvertUTF16toASCII strData(aData); + + mozilla::dom::Pref pref(strData, /* isLocked */ false, Nothing(), Nothing()); + Preferences::GetPreference(&pref); + if (!!mGPUChild) { + MOZ_ASSERT(mQueuedPrefs.IsEmpty()); + mGPUChild->SendPreferenceUpdate(pref); + } else { + mQueuedPrefs.AppendElement(pref); + } +} + void GPUProcessManager::LaunchGPUProcess() { if (mProcess) { return; @@ -342,6 +366,13 @@ void GPUProcessManager::OnProcessLaunchComplete(GPUProcessHost* aHost) { std::move(vsyncChild)); mGPUChild->SendInitVsyncBridge(std::move(vsyncParent)); + // Flush any pref updates that happened during launch and weren't + // included in the blobs set up in LaunchGPUProcess. + for (const mozilla::dom::Pref& pref : mQueuedPrefs) { + Unused << NS_WARN_IF(!mGPUChild->SendPreferenceUpdate(pref)); + } + mQueuedPrefs.Clear(); + CrashReporter::AnnotateCrashReport( CrashReporter::Annotation::GPUProcessStatus, NS_LITERAL_CSTRING("Running")); diff --git a/gfx/ipc/GPUProcessManager.h b/gfx/ipc/GPUProcessManager.h index 34ad84052a45..3fb47284e9c1 100644 --- a/gfx/ipc/GPUProcessManager.h +++ b/gfx/ipc/GPUProcessManager.h @@ -179,6 +179,7 @@ class GPUProcessManager final : public GPUProcessHost::Listener { private: // Called from our xpcom-shutdown observer. void OnXPCOMShutdown(); + void OnPreferenceChange(const char16_t* aData); bool CreateContentCompositorManager( base::ProcessId aOtherProcess, @@ -277,6 +278,10 @@ class GPUProcessManager final : public GPUProcessHost::Listener { uint64_t mProcessToken; GPUChild* mGPUChild; RefPtr mVsyncBridge; + // Collects any pref changes that occur during process launch (after + // the initial map is passed in command-line arguments) to be sent + // when the process can receive IPC messages. + nsTArray mQueuedPrefs; }; } // namespace gfx diff --git a/gfx/ipc/PGPU.ipdl b/gfx/ipc/PGPU.ipdl index 4c06f5a1fe4d..11ae817132ef 100644 --- a/gfx/ipc/PGPU.ipdl +++ b/gfx/ipc/PGPU.ipdl @@ -6,6 +6,7 @@ include GraphicsMessages; include MemoryReportTypes; include HangTypes; +include PrefsTypes; include protocol PAPZInputBridge; include protocol PCompositorManager; include protocol PImageBridge; @@ -66,6 +67,8 @@ parent: async UpdatePref(GfxPrefSetting pref); async UpdateVar(GfxVarUpdate var); + async PreferenceUpdate(Pref pref); + // Create a new content-process compositor bridge. async NewContentCompositorManager(Endpoint endpoint); async NewContentImageBridge(Endpoint endpoint);