From 600308cb7f2c5717b083d6fe173bc9f093761774 Mon Sep 17 00:00:00 2001 From: Brad Lassey Date: Sun, 5 Feb 2017 00:52:38 -0500 Subject: [PATCH] bug 1303096 - Stop sending sync messages soon after content process start-up r=billm --- caps/DomainPolicy.cpp | 2 +- caps/nsIDomainPolicy.idl | 3 +- dom/ipc/ContentChild.cpp | 64 +++--- dom/ipc/ContentChild.h | 12 +- dom/ipc/ContentParent.cpp | 258 ++++++++++++----------- dom/ipc/ContentParent.h | 19 -- dom/ipc/ContentPrefs.cpp | 275 +++++++++++++++++++++++++ dom/ipc/ContentPrefs.h | 25 +++ dom/ipc/ContentProcess.cpp | 156 +++++++++++--- dom/ipc/ContentProcess.h | 12 +- dom/ipc/PContent.ipdl | 43 ++-- dom/ipc/TabChild.cpp | 2 + dom/ipc/moz.build | 2 + dom/media/gmp/GMPProcessChild.cpp | 2 +- dom/media/gmp/GMPProcessChild.h | 2 +- dom/plugins/ipc/PluginProcessChild.cpp | 2 +- dom/plugins/ipc/PluginProcessChild.h | 2 +- gfx/ipc/GPUProcessImpl.cpp | 2 +- gfx/ipc/GPUProcessImpl.h | 2 +- ipc/glue/ProcessChild.h | 2 +- modules/libpref/Preferences.cpp | 30 ++- modules/libpref/Preferences.h | 20 ++ modules/libpref/prefapi.cpp | 38 +++- modules/libpref/prefapi_private_data.h | 6 + toolkit/xre/nsEmbedFunctions.cpp | 47 +---- 25 files changed, 734 insertions(+), 294 deletions(-) create mode 100644 dom/ipc/ContentPrefs.cpp create mode 100644 dom/ipc/ContentPrefs.h diff --git a/caps/DomainPolicy.cpp b/caps/DomainPolicy.cpp index 16029a2bdfdc7..2dcec2abe4b3b 100644 --- a/caps/DomainPolicy.cpp +++ b/caps/DomainPolicy.cpp @@ -139,7 +139,7 @@ CopyURIs(const InfallibleTArray& aDomains, nsIDomainSet* aSet) } void -DomainPolicy::ApplyClone(DomainPolicyClone* aClone) +DomainPolicy::ApplyClone(const DomainPolicyClone* aClone) { CopyURIs(aClone->blacklist(), mBlacklist); CopyURIs(aClone->whitelist(), mWhitelist); diff --git a/caps/nsIDomainPolicy.idl b/caps/nsIDomainPolicy.idl index 54b0de4dbf981..3fd4020a60d05 100644 --- a/caps/nsIDomainPolicy.idl +++ b/caps/nsIDomainPolicy.idl @@ -17,6 +17,7 @@ class DomainPolicyClone; %} [ptr] native DomainPolicyClonePtr(mozilla::dom::DomainPolicyClone); +[ptr] native DomainPolicyCloneConstPtr(const mozilla::dom::DomainPolicyClone); /* * When a domain policy is instantiated by invoking activateDomainPolicy() on @@ -41,7 +42,7 @@ interface nsIDomainPolicy : nsISupports void deactivate(); [noscript, notxpcom] void cloneDomainPolicy(in DomainPolicyClonePtr aClone); - [noscript, notxpcom] void applyClone(in DomainPolicyClonePtr aClone); + [noscript, notxpcom] void applyClone(in DomainPolicyCloneConstPtr aClone); }; [scriptable, builtinclass, uuid(665c981b-0a0f-4229-ac06-a826e02d4f69)] diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index aee51eeee77a8..e271e10bb2cce 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -502,10 +502,24 @@ NS_INTERFACE_MAP_BEGIN(ContentChild) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContentChild) NS_INTERFACE_MAP_END + +mozilla::ipc::IPCResult +ContentChild::RecvSetXPCOMProcessAttributes(const XPCOMInitData& aXPCOMInit, + const StructuredCloneData& aInitialData, + nsTArray&& aLookAndFeelIntCache) +{ + mLookAndFeelCache = aLookAndFeelIntCache; + InitXPCOM(aXPCOMInit, aInitialData); + InitGraphicsDeviceData(); + return IPC_OK(); +} + bool ContentChild::Init(MessageLoop* aIOLoop, base::ProcessId aParentPid, - IPC::Channel* aChannel) + IPC::Channel* aChannel, + uint64_t aChildID, + bool aIsForBrowser) { #ifdef MOZ_WIDGET_GTK // We need to pass a display down to gtk_init because it's not going to @@ -571,7 +585,8 @@ ContentChild::Init(MessageLoop* aIOLoop, XRE_GetProcessType()); #endif - SendGetProcessAttributes(&mID, &mIsForBrowser); + mID = aChildID; + mIsForBrowser = aIsForBrowser; #ifdef NS_PRINTING // Force the creation of the nsPrintingProxy so that it's IPC counterpart, @@ -933,8 +948,14 @@ ContentChild::InitGraphicsDeviceData() } void -ContentChild::InitXPCOM() +ContentChild::InitXPCOM(const XPCOMInitData& aXPCOMInit, + const mozilla::dom::ipc::StructuredCloneData& aInitialData) { + SET_PREF_PHASE(pref_initPhase::BEGIN_ALL_PREFS); + for (unsigned int i = 0; i < aXPCOMInit.prefs().Length(); i++) { + Preferences::SetPreference(aXPCOMInit.prefs().ElementAt(i)); + } + SET_PREF_PHASE(pref_initPhase::END_ALL_PREFS); // Do this as early as possible to get the parent process to initialize the // background thread since we'll likely need database information very soon. BackgroundChild::Startup(); @@ -957,42 +978,29 @@ ContentChild::InitXPCOM() if (NS_FAILED(svc->RegisterListener(mConsoleListener))) NS_WARNING("Couldn't register console listener for child process"); - bool isOffline, isLangRTL, haveBidiKeyboards; - bool isConnected; - int32_t captivePortalState; - ClipboardCapabilities clipboardCaps; - DomainPolicyClone domainPolicy; - StructuredCloneData initialData; - OptionalURIParams userContentSheetURL; - - SendGetXPCOMProcessAttributes(&isOffline, &isConnected, &captivePortalState, - &isLangRTL, &haveBidiKeyboards, - &mAvailableDictionaries, - &clipboardCaps, &domainPolicy, &initialData, - &mFontFamilies, &userContentSheetURL, - &mLookAndFeelCache); - - RecvSetOffline(isOffline); - RecvSetConnectivity(isConnected); - RecvSetCaptivePortalState(captivePortalState); - RecvBidiKeyboardNotify(isLangRTL, haveBidiKeyboards); + mAvailableDictionaries = aXPCOMInit.dictionaries(); + + RecvSetOffline(aXPCOMInit.isOffline()); + RecvSetConnectivity(aXPCOMInit.isConnected()); + RecvSetCaptivePortalState(aXPCOMInit.captivePortalState()); + RecvBidiKeyboardNotify(aXPCOMInit.isLangRTL(), aXPCOMInit.haveBidiKeyboards()); // Create the CPOW manager as soon as possible. SendPJavaScriptConstructor(); - if (domainPolicy.active()) { + if (aXPCOMInit.domainPolicy().active()) { nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager(); MOZ_ASSERT(ssm); ssm->ActivateDomainPolicyInternal(getter_AddRefs(mPolicy)); if (!mPolicy) { MOZ_CRASH("Failed to activate domain policy."); } - mPolicy->ApplyClone(&domainPolicy); + mPolicy->ApplyClone(&aXPCOMInit.domainPolicy()); } nsCOMPtr clipboard(do_GetService("@mozilla.org/widget/clipboard;1")); if (nsCOMPtr clipboardProxy = do_QueryInterface(clipboard)) { - clipboardProxy->SetCapabilities(clipboardCaps); + clipboardProxy->SetCapabilities(aXPCOMInit.clipboardCaps()); } { @@ -1002,7 +1010,9 @@ ContentChild::InitXPCOM() } ErrorResult rv; JS::RootedValue data(jsapi.cx()); - initialData.Read(jsapi.cx(), &data, rv); + mozilla::dom::ipc::StructuredCloneData id; + id.Copy(aInitialData); + id.Read(jsapi.cx(), &data, rv); if (NS_WARN_IF(rv.Failed())) { MOZ_CRASH(); } @@ -1011,7 +1021,7 @@ ContentChild::InitXPCOM() } // The stylesheet cache is not ready yet. Store this URL for future use. - nsCOMPtr ucsURL = DeserializeURI(userContentSheetURL); + nsCOMPtr ucsURL = DeserializeURI(aXPCOMInit.userContentSheetURL()); nsLayoutStylesheetCache::SetUserContentCSSURL(ucsURL); // This will register cross-process observer. diff --git a/dom/ipc/ContentChild.h b/dom/ipc/ContentChild.h index c9e4153c24999..d712f5c8c1653 100644 --- a/dom/ipc/ContentChild.h +++ b/dom/ipc/ContentChild.h @@ -96,9 +96,12 @@ class ContentChild final : public PContentChild bool Init(MessageLoop* aIOLoop, base::ProcessId aParentPid, - IPC::Channel* aChannel); + IPC::Channel* aChannel, + uint64_t aChildID, + bool aIsForBrowser); - void InitXPCOM(); + void InitXPCOM(const XPCOMInitData& aXPCOMInit, + const mozilla::dom::ipc::StructuredCloneData& aInitialData); void InitGraphicsDeviceData(); @@ -573,6 +576,11 @@ class ContentChild final : public PContentChild const bool& minimizeMemoryUsage, const MaybeFileDesc& DMDFile) override; + virtual mozilla::ipc::IPCResult + RecvSetXPCOMProcessAttributes(const XPCOMInitData& aXPCOMInit, + const StructuredCloneData& aInitialData, + nsTArray&& aLookAndFeelIntCache) override; + #if defined(XP_WIN) && defined(ACCESSIBILITY) bool SendGetA11yContentId(); diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 030d413fd0031..7db9e85399f77 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -186,6 +186,8 @@ #include "nsLayoutStylesheetCache.h" +#include "ContentPrefs.h" + #ifdef MOZ_WEBRTC #include "signaling/src/peerconnection/WebrtcGlobalParent.h" #endif @@ -1824,6 +1826,48 @@ ContentParent::LaunchSubprocess(ProcessPriority aInitialPriority /* = PROCESS_PR PROFILER_LABEL_FUNC(js::ProfileEntry::Category::OTHER); std::vector extraArgs; + extraArgs.push_back("-childID"); + char idStr[21]; + SprintfLiteral(idStr, "%" PRId64, static_cast(mChildID)); + extraArgs.push_back(idStr); + extraArgs.push_back(IsForBrowser() ? "-isForBrowser" : "-notForBrowser"); + + std::stringstream boolPrefs; + std::stringstream intPrefs; + std::stringstream stringPrefs; + + size_t prefsLen; + ContentPrefs::GetContentPrefs(&prefsLen); + + for (unsigned int i = 0; i < prefsLen; i++) { + MOZ_ASSERT(i == 0 || strcmp(ContentPrefs::GetContentPref(i), ContentPrefs::GetContentPref(i - 1)) > 0); + switch (Preferences::GetType(ContentPrefs::GetContentPref(i))) { + case nsIPrefBranch::PREF_INT: + intPrefs << i << ':' << Preferences::GetInt(ContentPrefs::GetContentPref(i)) << '|'; + break; + case nsIPrefBranch::PREF_BOOL: + boolPrefs << i << ':' << Preferences::GetBool(ContentPrefs::GetContentPref(i)) << '|'; + break; + case nsIPrefBranch::PREF_STRING: { + std::string value(Preferences::GetCString(ContentPrefs::GetContentPref(i)).get()); + stringPrefs << i << ':' << value.length() << ':' << value << '|'; + } + break; + case nsIPrefBranch::PREF_INVALID: + break; + default: + printf("preference type: %x\n", Preferences::GetType(ContentPrefs::GetContentPref(i))); + MOZ_CRASH(); + } + } + + extraArgs.push_back("-intPrefs"); + extraArgs.push_back(intPrefs.str()); + extraArgs.push_back("-boolPrefs"); + extraArgs.push_back(boolPrefs.str()); + extraArgs.push_back("-stringPrefs"); + extraArgs.push_back(stringPrefs.str()); + if (!mSubprocess->LaunchAndWaitForProcessHandle(extraArgs)) { MarkAsDead(); return false; @@ -1843,6 +1887,17 @@ ContentParent::LaunchSubprocess(ProcessPriority aInitialPriority /* = PROCESS_PR // Set a reply timeout for CPOWs. SetReplyTimeoutMs(Preferences::GetInt("dom.ipc.cpow.timeout", 0)); + Telemetry::Accumulate(Telemetry::CONTENT_PROCESS_LAUNCH_TIME_MS, + static_cast((TimeStamp::Now() - mLaunchTS) + .ToMilliseconds())); + + nsCOMPtr obs = mozilla::services::GetObserverService(); + if (obs) { + nsAutoString cpId; + cpId.AppendInt(static_cast(this->ChildID())); + obs->NotifyObservers(static_cast(this), "ipc:content-initializing", cpId.get()); + } + return true; } @@ -1900,6 +1955,90 @@ ContentParent::InitInternal(ProcessPriority aInitialPriority, bool aSetupOffMainThreadCompositing, bool aSendRegisteredChrome) { + Telemetry::Accumulate(Telemetry::CONTENT_PROCESS_LAUNCH_TIME_MS, + static_cast((TimeStamp::Now() - mLaunchTS) + .ToMilliseconds())); + + XPCOMInitData xpcomInit; + + Preferences::GetPreferences(&xpcomInit.prefs()); + nsCOMPtr io(do_GetIOService()); + MOZ_ASSERT(io, "No IO service?"); + DebugOnly rv = io->GetOffline(&xpcomInit.isOffline()); + MOZ_ASSERT(NS_SUCCEEDED(rv), "Failed getting offline?"); + + rv = io->GetConnectivity(&xpcomInit.isConnected()); + MOZ_ASSERT(NS_SUCCEEDED(rv), "Failed getting connectivity?"); + + xpcomInit.captivePortalState() = nsICaptivePortalService::UNKNOWN; + nsCOMPtr cps = do_GetService(NS_CAPTIVEPORTAL_CONTRACTID); + if (cps) { + cps->GetState(&xpcomInit.captivePortalState()); + } + + nsIBidiKeyboard* bidi = nsContentUtils::GetBidiKeyboard(); + + xpcomInit.isLangRTL() = false; + xpcomInit.haveBidiKeyboards() = false; + if (bidi) { + bidi->IsLangRTL(&xpcomInit.isLangRTL()); + bidi->GetHaveBidiKeyboards(&xpcomInit.haveBidiKeyboards()); + } + + nsCOMPtr spellChecker(do_GetService(NS_SPELLCHECKER_CONTRACTID)); + MOZ_ASSERT(spellChecker, "No spell checker?"); + + spellChecker->GetDictionaryList(&xpcomInit.dictionaries()); + + nsCOMPtr clipboard(do_GetService("@mozilla.org/widget/clipboard;1")); + MOZ_ASSERT(clipboard, "No clipboard?"); + + rv = clipboard->SupportsSelectionClipboard(&xpcomInit.clipboardCaps().supportsSelectionClipboard()); + MOZ_ASSERT(NS_SUCCEEDED(rv)); + + rv = clipboard->SupportsFindClipboard(&xpcomInit.clipboardCaps().supportsFindClipboard()); + MOZ_ASSERT(NS_SUCCEEDED(rv)); + + // Let's copy the domain policy from the parent to the child (if it's active). + StructuredCloneData initialData; + nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager(); + if (ssm) { + ssm->CloneDomainPolicy(&xpcomInit.domainPolicy()); + + if (nsFrameMessageManager* mm = nsFrameMessageManager::sParentProcessManager) { + AutoJSAPI jsapi; + if (NS_WARN_IF(!jsapi.Init(xpc::PrivilegedJunkScope()))) { + MOZ_CRASH(); + } + JS::RootedValue init(jsapi.cx()); + nsresult result = mm->GetInitialProcessData(jsapi.cx(), &init); + if (NS_FAILED(result)) { + MOZ_CRASH(); + } + + ErrorResult rv; + initialData.Write(jsapi.cx(), init, rv); + if (NS_WARN_IF(rv.Failed())) { + rv.SuppressException(); + MOZ_CRASH(); + } + } + } + // This is only implemented (returns a non-empty list) by MacOSX at present. + gfxPlatform::GetPlatform()->GetSystemFontFamilyList(&xpcomInit.fontFamilies()); + nsTArray lnfCache = LookAndFeel::GetIntCache(); + + // Content processes have no permission to access profile directory, so we + // send the file URL instead. + StyleSheet* ucs = nsLayoutStylesheetCache::For(StyleBackendType::Gecko)->UserContentSheet(); + if (ucs) { + SerializeURI(ucs->GetSheetURI(), xpcomInit.userContentSheetURL()); + } else { + SerializeURI(nullptr, xpcomInit.userContentSheetURL()); + } + + Unused << SendSetXPCOMProcessAttributes(xpcomInit, initialData, lnfCache); + if (aSendRegisteredChrome) { nsCOMPtr registrySvc = nsChromeRegistry::GetService(); nsChromeRegistryChrome* chromeRegistry = @@ -2071,13 +2210,6 @@ ContentParent::Pid() const return base::GetProcId(mSubprocess->GetChildProcessHandle()); } -mozilla::ipc::IPCResult -ContentParent::RecvReadPrefsArray(InfallibleTArray* aPrefs) -{ - Preferences::GetPreferences(aPrefs); - return IPC_OK(); -} - mozilla::ipc::IPCResult ContentParent::RecvGetGfxVars(InfallibleTArray* aVars) { @@ -2548,118 +2680,6 @@ ContentParent::RecvInitBackground(Endpoint&& aEndpoint) return IPC_OK(); } -mozilla::ipc::IPCResult -ContentParent::RecvGetProcessAttributes(ContentParentId* aCpId, - bool* aIsForBrowser) -{ - *aCpId = mChildID; - *aIsForBrowser = mIsForBrowser; - - return IPC_OK(); -} - -mozilla::ipc::IPCResult -ContentParent::RecvGetXPCOMProcessAttributes(bool* aIsOffline, - bool* aIsConnected, - int32_t* aCaptivePortalState, - bool* aIsLangRTL, - bool* aHaveBidiKeyboards, - InfallibleTArray* dictionaries, - ClipboardCapabilities* clipboardCaps, - DomainPolicyClone* domainPolicy, - StructuredCloneData* aInitialData, - InfallibleTArray* fontFamilies, - OptionalURIParams* aUserContentCSSURL, - nsTArray* aLookAndFeelIntCache) -{ - Telemetry::Accumulate(Telemetry::CONTENT_PROCESS_LAUNCH_TIME_MS, - static_cast((TimeStamp::Now() - mLaunchTS) - .ToMilliseconds())); - - nsCOMPtr io(do_GetIOService()); - MOZ_ASSERT(io, "No IO service?"); - DebugOnly rv = io->GetOffline(aIsOffline); - MOZ_ASSERT(NS_SUCCEEDED(rv), "Failed getting offline?"); - - rv = io->GetConnectivity(aIsConnected); - MOZ_ASSERT(NS_SUCCEEDED(rv), "Failed getting connectivity?"); - - *aCaptivePortalState = nsICaptivePortalService::UNKNOWN; - nsCOMPtr cps = do_GetService(NS_CAPTIVEPORTAL_CONTRACTID); - if (cps) { - cps->GetState(aCaptivePortalState); - } - - nsIBidiKeyboard* bidi = nsContentUtils::GetBidiKeyboard(); - - *aIsLangRTL = false; - *aHaveBidiKeyboards = false; - if (bidi) { - bidi->IsLangRTL(aIsLangRTL); - bidi->GetHaveBidiKeyboards(aHaveBidiKeyboards); - } - - nsCOMPtr spellChecker(do_GetService(NS_SPELLCHECKER_CONTRACTID)); - MOZ_ASSERT(spellChecker, "No spell checker?"); - - spellChecker->GetDictionaryList(dictionaries); - - nsCOMPtr clipboard(do_GetService("@mozilla.org/widget/clipboard;1")); - MOZ_ASSERT(clipboard, "No clipboard?"); - - rv = clipboard->SupportsSelectionClipboard(&clipboardCaps->supportsSelectionClipboard()); - MOZ_ASSERT(NS_SUCCEEDED(rv)); - - rv = clipboard->SupportsFindClipboard(&clipboardCaps->supportsFindClipboard()); - MOZ_ASSERT(NS_SUCCEEDED(rv)); - - // Let's copy the domain policy from the parent to the child (if it's active). - nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager(); - NS_ENSURE_TRUE(ssm, IPC_OK()); - ssm->CloneDomainPolicy(domainPolicy); - - if (nsFrameMessageManager* mm = nsFrameMessageManager::sParentProcessManager) { - AutoJSAPI jsapi; - if (NS_WARN_IF(!jsapi.Init(xpc::PrivilegedJunkScope()))) { - return IPC_FAIL_NO_REASON(this); - } - JS::RootedValue init(jsapi.cx()); - nsresult result = mm->GetInitialProcessData(jsapi.cx(), &init); - if (NS_FAILED(result)) { - return IPC_FAIL_NO_REASON(this); - } - - ErrorResult rv; - aInitialData->Write(jsapi.cx(), init, rv); - if (NS_WARN_IF(rv.Failed())) { - rv.SuppressException(); - return IPC_FAIL_NO_REASON(this); - } - } - - // This is only implemented (returns a non-empty list) by MacOSX at present. - gfxPlatform::GetPlatform()->GetSystemFontFamilyList(fontFamilies); - *aLookAndFeelIntCache = LookAndFeel::GetIntCache(); - - // Content processes have no permission to access profile directory, so we - // send the file URL instead. - StyleSheet* ucs = nsLayoutStylesheetCache::For(StyleBackendType::Gecko)->UserContentSheet(); - if (ucs) { - SerializeURI(ucs->GetSheetURI(), *aUserContentCSSURL); - } else { - SerializeURI(nullptr, *aUserContentCSSURL); - } - - nsCOMPtr obs = mozilla::services::GetObserverService(); - if (obs) { - nsAutoString cpId; - cpId.AppendInt(static_cast(this->ChildID())); - obs->NotifyObservers(static_cast(this), "ipc:content-initializing", cpId.get()); - } - - return IPC_OK(); -} - mozilla::jsipc::PJavaScriptParent * ContentParent::AllocPJavaScriptParent() { diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index f0650a00c601b..3c79fb5598616 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -746,24 +746,6 @@ class ContentParent final : public PContentParent virtual mozilla::ipc::IPCResult RecvInitBackground(Endpoint&& aEndpoint) override; - virtual mozilla::ipc::IPCResult RecvGetProcessAttributes(ContentParentId* aCpId, - bool* aIsForBrowser) override; - - virtual mozilla::ipc::IPCResult - RecvGetXPCOMProcessAttributes(bool* aIsOffline, - bool* aIsConnected, - int32_t* aCaptivePortalState, - bool* aIsLangRTL, - bool* aHaveBidiKeyboards, - InfallibleTArray* dictionaries, - ClipboardCapabilities* clipboardCaps, - DomainPolicyClone* domainPolicy, - StructuredCloneData* initialData, - InfallibleTArray* fontFamilies, - OptionalURIParams* aUserContentSheetURL, - nsTArray* aLookAndFeelIntCache) override; - - mozilla::ipc::IPCResult RecvAddMemoryReport(const MemoryReport& aReport) override; mozilla::ipc::IPCResult RecvFinishMemoryReport(const uint32_t& aGeneration) override; @@ -898,7 +880,6 @@ class ContentParent final : public PContentParent virtual bool DeallocPWebBrowserPersistDocumentParent(PWebBrowserPersistDocumentParent* aActor) override; - virtual mozilla::ipc::IPCResult RecvReadPrefsArray(InfallibleTArray* aPrefs) override; virtual mozilla::ipc::IPCResult RecvGetGfxVars(InfallibleTArray* aVars) override; virtual mozilla::ipc::IPCResult RecvReadFontList(InfallibleTArray* retValue) override; diff --git a/dom/ipc/ContentPrefs.cpp b/dom/ipc/ContentPrefs.cpp new file mode 100644 index 0000000000000..343fe98d03f52 --- /dev/null +++ b/dom/ipc/ContentPrefs.cpp @@ -0,0 +1,275 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "ContentPrefs.h" + +const char* mozilla::dom::ContentPrefs::gInitPrefs[] = { + "accessibility.monoaudio.enable", + "accessibility.mouse_focuses_formcontrol", + "accessibility.tabfocus_applies_to_xul", + "app.update.channel", + "browser.dom.window.dump.enabled", + "browser.sessionhistory.max_entries", + "browser.sessionhistory.max_total_viewers", + "content.cors.disable", + "content.cors.no_private_data", + "content.notify.backoffcount", + "content.notify.interval", + "content.notify.ontimer", + "content.sink.enable_perf_mode", + "content.sink.event_probe_rate", + "content.sink.initial_perf_time", + "content.sink.interactive_deflect_count", + "content.sink.interactive_parse_time", + "content.sink.interactive_time", + "content.sink.pending_event_mode", + "content.sink.perf_deflect_count", + "content.sink.perf_parse_time", + "device.storage.prompt.testing", + "device.storage.writable.name", + "dom.allow_XUL_XBL_for_file", + "dom.allow_cut_copy", + "dom.enable_frame_timing", + "dom.enable_performance", + "dom.enable_resource_timing", + "dom.event.handling-user-input-time-limit", + "dom.forms.autocomplete.experimental", + "dom.ipc.processPriorityManager.backgroundGracePeriodMS", + "dom.ipc.processPriorityManager.backgroundPerceivableGracePeriodMS", + "dom.max_chrome_script_run_time", + "dom.max_script_run_time", + "dom.performance.enable_notify_performance_timing", + "dom.performance.enable_user_timing_logging", + "dom.storage.testing", + "dom.url.encode_decode_hash", + "dom.url.getters_decode_hash", + "dom.use_watchdog", + "dom.vibrator.enabled", + "dom.vibrator.max_vibrate_list_len", + "dom.vibrator.max_vibrate_ms", + "focusmanager.testmode", + "font.size.inflation.disabledInMasterProcess", + "font.size.inflation.emPerLine", + "font.size.inflation.forceEnabled", + "font.size.inflation.lineThreshold", + "font.size.inflation.mappingIntercept", + "font.size.inflation.maxRatio", + "font.size.inflation.minTwips", + "full-screen-api.allow-trusted-requests-only", + "full-screen-api.enabled", + "full-screen-api.unprefix.enabled", + "gfx.font_rendering.opentype_svg.enabled", + "hangmonitor.timeout", + "html5.flushtimer.initialdelay", + "html5.flushtimer.subsequentdelay", + "html5.offmainthread", + "intl.charset.fallback.tld", + "intl.ime.hack.on_ime_unaware_apps.fire_key_events_for_composition", + "javascript.enabled", + "javascript.options.asmjs", + "javascript.options.asyncstack", + "javascript.options.baselinejit", + "javascript.options.baselinejit.threshold", + "javascript.options.baselinejit.unsafe_eager_compilation", + "javascript.options.discardSystemSource", + "javascript.options.dump_stack_on_debuggee_would_run", + "javascript.options.gczeal", + "javascript.options.gczeal.frequency", + "javascript.options.ion", + "javascript.options.ion.offthread_compilation", + "javascript.options.ion.threshold", + "javascript.options.ion.unsafe_eager_compilation", + "javascript.options.jit.full_debug_checks", + "javascript.options.native_regexp", + "javascript.options.parallel_parsing", + "javascript.options.shared_memory", + "javascript.options.strict", + "javascript.options.strict.debug", + "javascript.options.throw_on_asmjs_validation_failure", + "javascript.options.throw_on_debuggee_would_run", + "javascript.options.wasm", + "javascript.options.wasm_baselinejit", + "javascript.options.werror", + "javascript.use_us_english_locale", + "jsloader.reuseGlobal", + "layout.css.all-shorthand.enabled", + "layout.css.background-blend-mode.enabled", + "layout.css.background-clip-text.enabled", + "layout.css.box-decoration-break.enabled", + "layout.css.color-adjust.enabled", + "layout.css.contain.enabled", + "layout.css.control-characters.visible", + "layout.css.display-flow-root.enabled", + "layout.css.expensive-style-struct-assertions.enabled", + "layout.css.float-logical-values.enabled", + "layout.css.font-variations.enabled", + "layout.css.grid.enabled", + "layout.css.image-orientation.enabled", + "layout.css.initial-letter.enabled", + "layout.css.isolation.enabled", + "layout.css.mix-blend-mode.enabled", + "layout.css.object-fit-and-position.enabled", + "layout.css.osx-font-smoothing.enabled", + "layout.css.overflow-clip-box.enabled", + "layout.css.prefixes.animations", + "layout.css.prefixes.border-image", + "layout.css.prefixes.box-sizing", + "layout.css.prefixes.device-pixel-ratio-webkit", + "layout.css.prefixes.font-features", + "layout.css.prefixes.gradients", + "layout.css.prefixes.transforms", + "layout.css.prefixes.transitions", + "layout.css.prefixes.webkit", + "layout.css.scope-pseudo.enabled", + "layout.css.scroll-behavior.property-enabled", + "layout.css.scroll-snap.enabled", + "layout.css.shape-outside.enabled", + "layout.css.text-align-unsafe-value.enabled", + "layout.css.text-combine-upright-digits.enabled", + "layout.css.text-combine-upright.enabled", + "layout.css.touch_action.enabled", + "layout.css.unprefixing-service.enabled", + "layout.css.unprefixing-service.globally-whitelisted", + "layout.css.unprefixing-service.include-test-domains", + "layout.css.variables.enabled", + "layout.css.visited_links_enabled", + "layout.idle_period.required_quiescent_frames", + "layout.idle_period.time_limit", + "layout.interruptible-reflow.enabled", + "mathml.disabled", + "media.apple.forcevda", + "media.clearkey.persistent-license.enabled", + "media.cubeb_latency_msg_frames", + "media.cubeb_latency_playback_ms", + "media.decoder-doctor.wmf-disabled-is-failure", + "media.decoder.fuzzing.dont-delay-inputexhausted", + "media.decoder.fuzzing.enabled", + "media.decoder.fuzzing.video-output-minimum-interval-ms", + "media.decoder.limit", + "media.decoder.recycle.enabled", + "media.dormant-on-pause-timeout-ms", + "media.eme.audio.blank", + "media.eme.enabled", + "media.eme.video.blank", + "media.ffmpeg.enabled", + "media.ffvpx.enabled", + "media.flac.enabled", + "media.forcestereo.enabled", + "media.gmp.async-shutdown-timeout", + "media.gmp.decoder.aac", + "media.gmp.decoder.enabled", + "media.gmp.decoder.h264", + "media.gmp.insecure.allow", + "media.gpu-process-decoder", + "media.libavcodec.allow-obsolete", + "media.num-decode-threads", + "media.ogg.enabled", + "media.ogg.flac.enabled", + "media.resampling.enabled", + "media.resampling.rate", + "media.ruin-av-sync.enabled", + "media.rust.test_mode", + "media.suspend-bkgnd-video.delay-ms", + "media.suspend-bkgnd-video.enabled", + "media.use-blank-decoder", + "media.video_stats.enabled", + "media.volume_scale", + "media.webspeech.recognition.enable", + "media.webspeech.recognition.force_enable", + "media.webspeech.synth.force_global_queue", + "media.webspeech.test.enable", + "media.webspeech.test.fake_fsm_events", + "media.webspeech.test.fake_recognition_service", + "media.wmf.allow-unsupported-resolutions", + "media.wmf.decoder.thread-count", + "media.wmf.enabled", + "media.wmf.skip-blacklist", + "media.wmf.vp9.enabled", + "memory.free_dirty_pages", + "memory.low_commit_space_threshold_mb", + "memory.low_memory_notification_interval_ms", + "memory.low_physical_memory_threshold_mb", + "memory.low_virtual_mem_threshold_mb", + "network.IDN.blacklist_chars", + "network.IDN.restriction_profile", + "network.IDN.use_whitelist", + "network.IDN_show_punycode", + "network.buffer.cache.count", + "network.buffer.cache.size", + "network.captive-portal-service.enabled", + "network.cookie.cookieBehavior", + "network.cookie.lifetimePolicy", + "network.dns.disablePrefetch", + "network.dns.disablePrefetchFromHTTPS", + "network.jar.block-remote-files", + "network.loadinfo.skip_type_assertion", + "network.notify.changed", + "network.offline-mirrors-connectivity", + "network.protocol-handler.external.jar", + "network.proxy.type", + "network.security.ports.banned", + "network.security.ports.banned.override", + "network.standard-url.enable-rust", + "network.standard-url.max-length", + "network.sts.max_time_for_events_between_two_polls", + "network.sts.max_time_for_pr_close_during_shutdown", + "network.tcp.keepalive.enabled", + "network.tcp.keepalive.idle_time", + "network.tcp.keepalive.probe_count", + "network.tcp.keepalive.retry_interval", + "network.tcp.sendbuffer", + "nglayout.debug.invalidation", + "privacy.donottrackheader.enabled", + "privacy.firstparty.isolate", + "privacy.firstparty.isolate.restrict_opener_access", + "privacy.resistFingerprinting", + "security.data_uri.inherit_security_context", + "security.fileuri.strict_origin_policy", + "security.sandbox.content.level", + "security.sandbox.content.tempDirSuffix", + "security.sandbox.logging.enabled", + "security.sandbox.mac.track.violations", + "security.sandbox.windows.log", + "security.sandbox.windows.log.stackTraceDepth", + "shutdown.watchdog.timeoutSecs", + "signed.applets.codebase_principal_support", + "svg.disabled", + "svg.display-lists.hit-testing.enabled", + "svg.display-lists.painting.enabled", + "svg.new-getBBox.enabled", + "svg.paint-order.enabled", + "svg.path-caching.enabled", + "svg.transform-box.enabled", + "toolkit.asyncshutdown.crash_timeout", + "toolkit.asyncshutdown.log", + "toolkit.osfile.log", + "toolkit.osfile.log.redirect", + "toolkit.telemetry.enabled", + "toolkit.telemetry.idleTimeout", + "toolkit.telemetry.initDelay", + "toolkit.telemetry.log.dump", + "toolkit.telemetry.log.level", + "toolkit.telemetry.minSubsessionLength", + "toolkit.telemetry.scheduler.idleTickInterval", + "toolkit.telemetry.scheduler.tickInterval", + "toolkit.telemetry.unified", + "ui.key.menuAccessKeyFocuses", + "ui.popup.disable_autohide", + "ui.use_activity_cursor", + "view_source.editor.external"}; + +const char** mozilla::dom::ContentPrefs::GetContentPrefs(size_t* aCount) +{ + *aCount = ArrayLength(ContentPrefs::gInitPrefs); + return gInitPrefs; +} + +const char* mozilla::dom::ContentPrefs::GetContentPref(size_t aIndex) +{ + MOZ_ASSERT(aIndex < ArrayLength(ContentPrefs::gInitPrefs)); + return gInitPrefs[aIndex]; +} + diff --git a/dom/ipc/ContentPrefs.h b/dom/ipc/ContentPrefs.h new file mode 100644 index 0000000000000..f85d4b5cbad5b --- /dev/null +++ b/dom/ipc/ContentPrefs.h @@ -0,0 +1,25 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_ContentPrefs_h +#define mozilla_dom_ContentPrefs_h + +namespace mozilla { +namespace dom { + +class ContentPrefs { +public: + static const char** GetContentPrefs(size_t* aCount); + static const char* GetContentPref(size_t aIndex); + +private: + static const char* gInitPrefs[]; +}; + +} +} + +#endif diff --git a/dom/ipc/ContentProcess.cpp b/dom/ipc/ContentProcess.cpp index 2413d88087e5f..394e7f1deff81 100644 --- a/dom/ipc/ContentProcess.cpp +++ b/dom/ipc/ContentProcess.cpp @@ -7,6 +7,7 @@ #include "mozilla/ipc/IOThreadChild.h" #include "ContentProcess.h" +#include "ContentPrefs.h" #if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX) #include @@ -103,46 +104,143 @@ SetUpSandboxEnvironment() } #endif -void -ContentProcess::SetAppDir(const nsACString& aPath) +bool +ContentProcess::Init(int aArgc, char* aArgv[]) { - mXREEmbed.SetAppDir(aPath); -} + // If passed in grab the application path for xpcom init + bool foundAppdir = false; + bool foundChildID = false; + bool foundIsForBrowser = false; + bool foundIntPrefs = false; + bool foundBoolPrefs = false; + bool foundStringPrefs = false; + + uint64_t childID; + bool isForBrowser; #if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX) -void -ContentProcess::SetProfile(const nsACString& aProfile) -{ - bool flag; - nsresult rv = - XRE_GetFileFromPath(aProfile.BeginReading(), getter_AddRefs(mProfileDir)); - if (NS_FAILED(rv) || - NS_FAILED(mProfileDir->Exists(&flag)) || !flag) { - NS_WARNING("Invalid profile directory passed to content process."); - mProfileDir = nullptr; - } -} + // If passed in grab the profile path for sandboxing + bool foundProfile = false; + nsCOMPtr profileDir; #endif -bool -ContentProcess::Init() -{ - mContent.Init(IOThreadChild::message_loop(), - ParentPid(), - IOThreadChild::channel()); - mXREEmbed.Start(); - mContent.InitXPCOM(); - mContent.InitGraphicsDeviceData(); + InfallibleTArray prefsArray; + for (int idx = aArgc; idx > 0; idx--) { + if (!aArgv[idx]) { + continue; + } + + if (!strcmp(aArgv[idx], "-appdir")) { + MOZ_ASSERT(!foundAppdir); + if (foundAppdir) { + continue; + } + nsCString appDir; + appDir.Assign(nsDependentCString(aArgv[idx+1])); + mXREEmbed.SetAppDir(appDir); + foundAppdir = true; + } else if (!strcmp(aArgv[idx], "-childID")) { + MOZ_ASSERT(!foundChildID); + if (foundChildID) { + continue; + } + if (idx + 1 < aArgc) { + childID = strtoull(aArgv[idx + 1], nullptr, 10); + foundChildID = true; + } + } else if (!strcmp(aArgv[idx], "-isForBrowser") || !strcmp(aArgv[idx], "-notForBrowser")) { + MOZ_ASSERT(!foundIsForBrowser); + if (foundIsForBrowser) { + continue; + } + isForBrowser = strcmp(aArgv[idx], "-notForBrowser"); + foundIsForBrowser = true; + } else if (!strcmp(aArgv[idx], "-intPrefs")) { + SET_PREF_PHASE(BEGIN_INIT_PREFS); + char* str = aArgv[idx + 1]; + while (*str) { + int32_t index = strtol(str, &str, 10); + str++; + MaybePrefValue value(PrefValue(static_cast(strtol(str, &str, 10)))); + str++; + PrefSetting pref(nsCString(ContentPrefs::GetContentPref(index)), value, MaybePrefValue()); + prefsArray.AppendElement(pref); + } + SET_PREF_PHASE(END_INIT_PREFS); + foundIntPrefs = true; + } else if (!strcmp(aArgv[idx], "-boolPrefs")) { + SET_PREF_PHASE(BEGIN_INIT_PREFS); + char* str = aArgv[idx + 1]; + while (*str) { + int32_t index = strtol(str, &str, 10); + str++; + MaybePrefValue value(PrefValue(!!strtol(str, &str, 10))); + str++; + PrefSetting pref(nsCString(ContentPrefs::GetContentPref(index)), value, MaybePrefValue()); + prefsArray.AppendElement(pref); + } + SET_PREF_PHASE(END_INIT_PREFS); + foundBoolPrefs = true; + } else if (!strcmp(aArgv[idx], "-stringPrefs")) { + SET_PREF_PHASE(BEGIN_INIT_PREFS); + char* str = aArgv[idx + 1]; + while (*str) { + int32_t index = strtol(str, &str, 10); + str++; + int32_t length = strtol(str, &str, 10); + str++; + MaybePrefValue value(PrefValue(nsCString(str, length))); + PrefSetting pref(nsCString(ContentPrefs::GetContentPref(index)), value, MaybePrefValue()); + prefsArray.AppendElement(pref); + str += length + 1; + } + SET_PREF_PHASE(END_INIT_PREFS); + foundStringPrefs = true; + } + +#if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX) + else if (!strcmp(aArgv[idx], "-profile")) { + MOZ_ASSERT(!foundProfile); + if (foundProfile) { + continue; + } + bool flag; + nsresult rv = XRE_GetFileFromPath(aArgv[idx+1], getter_AddRefs(profileDir)); + if (NS_FAILED(rv) || + NS_FAILED(profileDir->Exists(&flag)) || !flag) { + NS_WARNING("Invalid profile directory passed to content process."); + profileDir = nullptr; + } + foundProfile = true; + } +#endif /* XP_MACOSX && MOZ_CONTENT_SANDBOX */ + + bool allFound = foundAppdir && foundChildID && foundIsForBrowser && foundIntPrefs && foundBoolPrefs && foundStringPrefs; +#if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX) + allFound &= foundProfile; +#endif + + if (allFound) { + break; + } + } + Preferences::SetInitPreferences(&prefsArray); + mContent.Init(IOThreadChild::message_loop(), + ParentPid(), + IOThreadChild::channel(), + childID, + isForBrowser); + mXREEmbed.Start(); #if (defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX) - mContent.SetProfileDir(mProfileDir); + mContent.SetProfileDir(profileDir); #endif #if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX) - SetUpSandboxEnvironment(); + SetUpSandboxEnvironment(); #endif - return true; + return true; } // Note: CleanUp() never gets called in non-debug builds because we exit early @@ -150,7 +248,7 @@ ContentProcess::Init() void ContentProcess::CleanUp() { - mXREEmbed.Stop(); + mXREEmbed.Stop(); } } // namespace dom diff --git a/dom/ipc/ContentProcess.h b/dom/ipc/ContentProcess.h index bf9968f8cad9c..a3854c761e109 100644 --- a/dom/ipc/ContentProcess.h +++ b/dom/ipc/ContentProcess.h @@ -34,23 +34,13 @@ class ContentProcess : public mozilla::ipc::ProcessChild ~ContentProcess() { } - virtual bool Init() override; + virtual bool Init(int aArgc, char* aArgv[]) override; virtual void CleanUp() override; - void SetAppDir(const nsACString& aPath); - -#if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX) - void SetProfile(const nsACString& aProfile); -#endif - private: ContentChild mContent; mozilla::ipc::ScopedXREEmbed mXREEmbed; -#if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX) - nsCOMPtr mProfileDir; -#endif - #if defined(XP_WIN) // This object initializes and configures COM. mozilla::mscom::MainThreadRuntime mCOMRuntime; diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl index eead95c2fa642..71f382b4fb7b6 100644 --- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -334,6 +334,22 @@ struct GMPCapabilityData GMPAPITags[] capabilities; }; +struct XPCOMInitData +{ + bool isOffline; + bool isConnected; + int32_t captivePortalState; + bool isLangRTL; + bool haveBidiKeyboards; + nsString[] dictionaries; + ClipboardCapabilities clipboardCaps; + DomainPolicyClone domainPolicy; + /* used on MacOSX only */ + FontFamilyListEntry[] fontFamilies; + OptionalURIParams userContentSheetURL; + PrefSetting[] prefs; +}; + struct GfxInfoFeatureStatus { int32_t feature; @@ -527,6 +543,8 @@ child: */ async InitBlobURLs(BlobURLRegistrationData[] registrations); + async SetXPCOMProcessAttributes(XPCOMInitData xpcomInit, StructuredCloneData initialData, LookAndFeelInt[] lookAndFeelIntCache); + // Notify child that last-pb-context-exited notification was observed async LastPrivateDocShellDestroyed(); @@ -650,30 +668,6 @@ child: parent: async InitBackground(Endpoint aEndpoint); - /** - * Tell the content process some attributes of itself. This is - * among the first information queried by content processes after - * startup. (The message is sync to allow the content process to - * control when it receives the information.) - * - * |id| is a unique ID among all subprocesses. When - * |isForBrowser|, we're loading or . - * - * Keep the return values in sync with PBrowser()! - */ - sync GetProcessAttributes() - returns (ContentParentId cpId, bool isForBrowser); - sync GetXPCOMProcessAttributes() - returns (bool isOffline, bool isConnected, int32_t captivePortalState, - bool isLangRTL, - bool haveBidiKeyboards, nsString[] dictionaries, - ClipboardCapabilities clipboardCaps, - DomainPolicyClone domainPolicy, - StructuredCloneData initialData, - FontFamilyListEntry[] fontFamilies /* used on MacOSX only */, - OptionalURIParams userContentSheetURL, - LookAndFeelInt[] lookAndFeelIntCache); - sync CreateChildProcess(IPCTabContext context, ProcessPriority priority, TabId openerTabId) @@ -817,7 +811,6 @@ parent: async ExtProtocolChannelConnectParent(uint32_t registrarId); // PrefService message - sync ReadPrefsArray() returns (PrefSetting[] prefs) verify; sync GetGfxVars() returns (GfxVarUpdate[] vars); sync ReadFontList() returns (FontListEntry[] retValue); diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index debd5cd2e25fc..a72655e9dd109 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -119,6 +119,8 @@ #include "GroupedSHistory.h" #include "nsIHttpChannel.h" #include "mozilla/dom/DocGroup.h" +#include "nsISupportsPrimitives.h" +#include "mozilla/Telemetry.h" #ifdef NS_PRINTING #include "nsIPrintSession.h" diff --git a/dom/ipc/moz.build b/dom/ipc/moz.build index 452e1fe451662..e84887ea40a89 100644 --- a/dom/ipc/moz.build +++ b/dom/ipc/moz.build @@ -20,6 +20,7 @@ EXPORTS.mozilla.dom += [ 'ContentBridgeParent.h', 'ContentChild.h', 'ContentParent.h', + 'ContentPrefs.h', 'ContentProcess.h', 'ContentProcessManager.h', 'CPOWManagerGetter.h', @@ -50,6 +51,7 @@ UNIFIED_SOURCES += [ 'ContentBridgeChild.cpp', 'ContentBridgeParent.cpp', 'ContentParent.cpp', + 'ContentPrefs.cpp', 'ContentProcess.cpp', 'ContentProcessManager.cpp', 'CrashReporterParent.cpp', diff --git a/dom/media/gmp/GMPProcessChild.cpp b/dom/media/gmp/GMPProcessChild.cpp index d1ada706a7ddc..d56339bc1018a 100644 --- a/dom/media/gmp/GMPProcessChild.cpp +++ b/dom/media/gmp/GMPProcessChild.cpp @@ -25,7 +25,7 @@ GMPProcessChild::~GMPProcessChild() } bool -GMPProcessChild::Init() +GMPProcessChild::Init(int aArgc, char* aArgv[]) { nsAutoString pluginFilename; diff --git a/dom/media/gmp/GMPProcessChild.h b/dom/media/gmp/GMPProcessChild.h index c2c8be9e2ebc5..382882e18a31a 100644 --- a/dom/media/gmp/GMPProcessChild.h +++ b/dom/media/gmp/GMPProcessChild.h @@ -22,7 +22,7 @@ class GMPProcessChild final : public mozilla::ipc::ProcessChild { explicit GMPProcessChild(ProcessId aParentPid); ~GMPProcessChild(); - bool Init() override; + bool Init(int aArgc, char* aArgv[]) override; void CleanUp() override; private: diff --git a/dom/plugins/ipc/PluginProcessChild.cpp b/dom/plugins/ipc/PluginProcessChild.cpp index eb698e8af5cfb..5b0a2beecdea0 100644 --- a/dom/plugins/ipc/PluginProcessChild.cpp +++ b/dom/plugins/ipc/PluginProcessChild.cpp @@ -40,7 +40,7 @@ namespace plugins { bool -PluginProcessChild::Init() +PluginProcessChild::Init(int aArgc, char* aArgv[]) { nsDebugImpl::SetMultiprocessMode("NPAPI"); diff --git a/dom/plugins/ipc/PluginProcessChild.h b/dom/plugins/ipc/PluginProcessChild.h index 75c842a1bfda4..fd0a328bc7037 100644 --- a/dom/plugins/ipc/PluginProcessChild.h +++ b/dom/plugins/ipc/PluginProcessChild.h @@ -30,7 +30,7 @@ class PluginProcessChild : public mozilla::ipc::ProcessChild { virtual ~PluginProcessChild() { } - virtual bool Init() override; + virtual bool Init(int aArgc, char* aArgv[]) override; virtual void CleanUp() override; protected: diff --git a/gfx/ipc/GPUProcessImpl.cpp b/gfx/ipc/GPUProcessImpl.cpp index 38d13484b3e7f..f7c4c80daafeb 100644 --- a/gfx/ipc/GPUProcessImpl.cpp +++ b/gfx/ipc/GPUProcessImpl.cpp @@ -22,7 +22,7 @@ GPUProcessImpl::~GPUProcessImpl() } bool -GPUProcessImpl::Init() +GPUProcessImpl::Init(int aArgc, char* aArgv[]) { return mGPU.Init(ParentPid(), IOThreadChild::message_loop(), diff --git a/gfx/ipc/GPUProcessImpl.h b/gfx/ipc/GPUProcessImpl.h index 5e8b6694a6c6c..fc7ff8ca3a6ef 100644 --- a/gfx/ipc/GPUProcessImpl.h +++ b/gfx/ipc/GPUProcessImpl.h @@ -24,7 +24,7 @@ class GPUProcessImpl final : public ipc::ProcessChild explicit GPUProcessImpl(ProcessId aParentPid); ~GPUProcessImpl(); - bool Init() override; + bool Init(int aArgc, char* aArgv[]) override; void CleanUp() override; private: diff --git a/ipc/glue/ProcessChild.h b/ipc/glue/ProcessChild.h index 4d1d3865902aa..65d62bae8fbaa 100644 --- a/ipc/glue/ProcessChild.h +++ b/ipc/glue/ProcessChild.h @@ -27,7 +27,7 @@ class ProcessChild : public ChildProcess { explicit ProcessChild(ProcessId aParentPid); virtual ~ProcessChild(); - virtual bool Init() = 0; + virtual bool Init(int aArgc, char* aArgv[]) = 0; virtual void CleanUp() { } diff --git a/modules/libpref/Preferences.cpp b/modules/libpref/Preferences.cpp index f36819236f475..b1f86b9e0f626 100644 --- a/modules/libpref/Preferences.cpp +++ b/modules/libpref/Preferences.cpp @@ -5,7 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "mozilla/MemoryReporting.h" -#include "mozilla/dom/ContentChild.h" +#include "mozilla/dom/PContent.h" #include "mozilla/ArrayUtils.h" #include "mozilla/Attributes.h" @@ -546,6 +546,14 @@ NS_INTERFACE_MAP_END * nsIPrefService Implementation */ +InfallibleTArray* gInitPrefs; + +/*static*/ +void +Preferences::SetInitPreferences(nsTArray* aPrefs) { + gInitPrefs = new InfallibleTArray(mozilla::Move(*aPrefs)); +} + nsresult Preferences::Init() { @@ -557,15 +565,13 @@ Preferences::Init() rv = pref_InitInitialObjects(); NS_ENSURE_SUCCESS(rv, rv); - using mozilla::dom::ContentChild; if (XRE_IsContentProcess()) { - InfallibleTArray prefs; - ContentChild::GetSingleton()->SendReadPrefsArray(&prefs); - - // Store the array - for (uint32_t i = 0; i < prefs.Length(); ++i) { - pref_SetPref(prefs[i]); + MOZ_ASSERT(gInitPrefs); + for (unsigned int i = 0; i < gInitPrefs->Length(); i++) { + Preferences::SetPreference(gInitPrefs->ElementAt(i)); } + delete gInitPrefs; + gInitPrefs = nullptr; return NS_OK; } @@ -780,6 +786,14 @@ Preferences::GetPreferences(InfallibleTArray* aPrefs) } } +#ifdef DEBUG +void +Preferences::SetInitPhase(pref_initPhase phase) +{ + pref_SetInitPhase(phase); +} +#endif + NS_IMETHODIMP Preferences::GetBranch(const char *aPrefRoot, nsIPrefBranch **_retval) { diff --git a/modules/libpref/Preferences.h b/modules/libpref/Preferences.h index 255d2a8d2f29d..8b0daef13b463 100644 --- a/modules/libpref/Preferences.h +++ b/modules/libpref/Preferences.h @@ -28,6 +28,20 @@ typedef void (*PrefChangedFunc)(const char *, void *); #define have_PrefChangedFunc_typedef #endif +#ifdef DEBUG +enum pref_initPhase { + START, + BEGIN_INIT_PREFS, + END_INIT_PREFS, + BEGIN_ALL_PREFS, + END_ALL_PREFS +}; + +#define SET_PREF_PHASE(p) Preferences::SetInitPhase(p) +#else +#define SET_PREF_PHASE(p) do { } while (0) +#endif + namespace mozilla { namespace dom { @@ -366,6 +380,12 @@ class Preferences final : public nsIPrefService, static void GetPreference(PrefSetting* aPref); static void SetPreference(const PrefSetting& aPref); + static void SetInitPreferences(nsTArray* aPrefs); + +#ifdef DEBUG + static void SetInitPhase(pref_initPhase phase); +#endif + static int64_t SizeOfIncludingThisAndOtherStuff(mozilla::MallocSizeOf aMallocSizeOf); static void DirtyCallback(); diff --git a/modules/libpref/prefapi.cpp b/modules/libpref/prefapi.cpp index 046a6941903d9..a42c83d343bf1 100644 --- a/modules/libpref/prefapi.cpp +++ b/modules/libpref/prefapi.cpp @@ -29,6 +29,7 @@ #include "prprf.h" #include "mozilla/MemoryReporting.h" #include "mozilla/dom/PContent.h" +#include "mozilla/dom/ContentPrefs.h" #include "nsQuickSort.h" #include "nsString.h" #include "nsPrintfCString.h" @@ -736,13 +737,48 @@ static PrefTypeFlags pref_SetValue(PrefValue* existingValue, PrefTypeFlags flags } return flags; } +#ifdef DEBUG +static pref_initPhase gPhase = START; + +void +pref_SetInitPhase(pref_initPhase phase) +{ + gPhase = phase; +} + +struct StringComparator +{ + const char* mKey; + explicit StringComparator(const char* aKey) : mKey(aKey) {} + int operator()(const char* string) const { + return strcmp(mKey, string); + } +}; + +bool +inInitArray(const char* key) +{ + size_t prefsLen; + size_t found; + const char** list = mozilla::dom::ContentPrefs::GetContentPrefs(&prefsLen); + return BinarySearchIf(list, 0, prefsLen, + StringComparator(key), &found); +} +#endif PrefHashEntry* pref_HashTableLookup(const char *key) { #ifndef MOZ_B2G MOZ_ASSERT(NS_IsMainThread()); #endif - + MOZ_ASSERT((!XRE_IsContentProcess() || gPhase != START), + "pref access before commandline prefs set"); + /* If you're hitting this assertion, you've added a pref access to start up. + * Consider moving it later or add it to the whitelist in ContentPrefs.cpp + * and get review from a DOM peer + */ + MOZ_ASSERT((!XRE_IsContentProcess() || gPhase > END_INIT_PREFS || inInitArray(key)), + "accessing non-init pref before the rest of the prefs are sent"); return static_cast(gHashTable->Search(key)); } diff --git a/modules/libpref/prefapi_private_data.h b/modules/libpref/prefapi_private_data.h index f1fa68fdc45eb..4cf58f6a9f856 100644 --- a/modules/libpref/prefapi_private_data.h +++ b/modules/libpref/prefapi_private_data.h @@ -10,6 +10,7 @@ #include "mozilla/MemoryReporting.h" #include "mozilla/UniquePtr.h" +#include "Preferences.h" extern PLDHashTable* gHashTable; @@ -25,6 +26,11 @@ pref_savePrefs(PLDHashTable* aTable, uint32_t* aPrefCount); nsresult pref_SetPref(const mozilla::dom::PrefSetting& aPref); +#ifdef DEBUG +void +pref_SetInitPhase(pref_initPhase phase); +#endif + int pref_CompareStrings(const void *v1, const void *v2, void* unused); PrefHashEntry* pref_HashTableLookup(const char *key); diff --git a/toolkit/xre/nsEmbedFunctions.cpp b/toolkit/xre/nsEmbedFunctions.cpp index 89584b5621ad5..4649a41525f87 100644 --- a/toolkit/xre/nsEmbedFunctions.cpp +++ b/toolkit/xre/nsEmbedFunctions.cpp @@ -625,49 +625,8 @@ XRE_InitChildProcess(int aArgc, process = new PluginProcessChild(parentPID); break; - case GeckoProcessType_Content: { - process = new ContentProcess(parentPID); - // If passed in grab the application path for xpcom init - bool foundAppdir = false; - -#if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX) - // If passed in grab the profile path for sandboxing - bool foundProfile = false; -#endif - - for (int idx = aArgc; idx > 0; idx--) { - if (aArgv[idx] && !strcmp(aArgv[idx], "-appdir")) { - MOZ_ASSERT(!foundAppdir); - if (foundAppdir) { - continue; - } - nsCString appDir; - appDir.Assign(nsDependentCString(aArgv[idx+1])); - static_cast(process.get())->SetAppDir(appDir); - foundAppdir = true; - } - -#if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX) - if (aArgv[idx] && !strcmp(aArgv[idx], "-profile")) { - MOZ_ASSERT(!foundProfile); - if (foundProfile) { - continue; - } - nsCString profile; - profile.Assign(nsDependentCString(aArgv[idx+1])); - static_cast(process.get())->SetProfile(profile); - foundProfile = true; - } - if (foundProfile && foundAppdir) { - break; - } -#else - if (foundAppdir) { - break; - } -#endif /* XP_MACOSX && MOZ_CONTENT_SANDBOX */ - } - } + case GeckoProcessType_Content: + process = new ContentProcess(parentPID); break; case GeckoProcessType_IPDLUnitTest: @@ -690,7 +649,7 @@ XRE_InitChildProcess(int aArgc, MOZ_CRASH("Unknown main thread class"); } - if (!process->Init()) { + if (!process->Init(aArgc, aArgv)) { return NS_ERROR_FAILURE; }