bug 1303096 - Stop sending sync messages soon after content process start-up r=billm
authorBrad Lassey <blassey@mozilla.com>
Sun, 05 Feb 2017 00:52:38 -0500
changeset 387742 5a43dbcb95cab9ff9728383f05780faa72e1ad5e
parent 387741 c5d678ebcbcd24dce64426492e3f20ca5a1bd261
child 387743 4dc3eb7f7b1284459eafc16d1fa0aecc9b2ff385
push id7198
push userjlorenzo@mozilla.com
push dateTue, 18 Apr 2017 12:07:49 +0000
treeherdermozilla-beta@d57aa49c3948 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbillm
bugs1303096
milestone54.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
bug 1303096 - Stop sending sync messages soon after content process start-up r=billm
caps/DomainPolicy.cpp
caps/nsIDomainPolicy.idl
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/ContentPrefs.cpp
dom/ipc/ContentPrefs.h
dom/ipc/ContentProcess.cpp
dom/ipc/ContentProcess.h
dom/ipc/PContent.ipdl
dom/ipc/TabChild.cpp
dom/ipc/moz.build
dom/media/gmp/GMPProcessChild.cpp
dom/media/gmp/GMPProcessChild.h
dom/plugins/ipc/PluginProcessChild.cpp
dom/plugins/ipc/PluginProcessChild.h
gfx/ipc/GPUProcessImpl.cpp
gfx/ipc/GPUProcessImpl.h
ipc/glue/ProcessChild.h
modules/libpref/Preferences.cpp
modules/libpref/Preferences.h
modules/libpref/prefapi.cpp
modules/libpref/prefapi_private_data.h
toolkit/xre/nsEmbedFunctions.cpp
--- a/caps/DomainPolicy.cpp
+++ b/caps/DomainPolicy.cpp
@@ -134,17 +134,17 @@ CopyURIs(const InfallibleTArray<URIParam
 {
     for (uint32_t i = 0; i < aDomains.Length(); i++) {
         nsCOMPtr<nsIURI> uri = DeserializeURI(aDomains[i]);
         aSet->Add(uri);
     }
 }
 
 void
-DomainPolicy::ApplyClone(DomainPolicyClone* aClone)
+DomainPolicy::ApplyClone(const DomainPolicyClone* aClone)
 {
     CopyURIs(aClone->blacklist(), mBlacklist);
     CopyURIs(aClone->whitelist(), mWhitelist);
     CopyURIs(aClone->superBlacklist(), mSuperBlacklist);
     CopyURIs(aClone->superWhitelist(), mSuperWhitelist);
 }
 
 static already_AddRefed<nsIURI>
--- a/caps/nsIDomainPolicy.idl
+++ b/caps/nsIDomainPolicy.idl
@@ -12,16 +12,17 @@ interface nsIDomainSet;
 namespace mozilla {
 namespace dom {
 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
  * nsIScriptSecurityManager, these domain sets are consulted when each new
  * global is created (they have no effect on already-created globals).
  * If javascript is globally enabled with |javascript.enabled|, the blacklists
  * are consulted. If globally disabled, the whitelists are consulted. Lookups
  * on blacklist and whitelist happen with contains(), and lookups on
@@ -36,17 +37,17 @@ interface nsIDomainPolicy : nsISupports
     readonly attribute nsIDomainSet blacklist;
     readonly attribute nsIDomainSet superBlacklist;
     readonly attribute nsIDomainSet whitelist;
     readonly attribute nsIDomainSet superWhitelist;
 
     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)]
 interface nsIDomainSet : nsISupports
 {
     /*
      * The type of the set. See: DomainSetType
      */
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -497,20 +497,34 @@ ContentChild::~ContentChild()
 #endif
 
 NS_INTERFACE_MAP_BEGIN(ContentChild)
   NS_INTERFACE_MAP_ENTRY(nsIContentChild)
   NS_INTERFACE_MAP_ENTRY(nsIWindowProvider)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContentChild)
 NS_INTERFACE_MAP_END
 
+
+mozilla::ipc::IPCResult
+ContentChild::RecvSetXPCOMProcessAttributes(const XPCOMInitData& aXPCOMInit,
+                                            const StructuredCloneData& aInitialData,
+                                            nsTArray<LookAndFeelInt>&& 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
   // use the one from the environment on its own when deciding which backend
   // to use, and when starting under XWayland, it may choose to start with
   // the wayland backend instead of the x11 backend.
   // The DISPLAY environment variable is normally set by the parent process.
   char* display_name = PR_GetEnv("DISPLAY");
@@ -566,17 +580,18 @@ ContentChild::Init(MessageLoop* aIOLoop,
   SendBackUpXResources(FileDescriptor(xSocketFd));
 #endif
 
 #ifdef MOZ_CRASHREPORTER
   SendPCrashReporterConstructor(CrashReporter::CurrentThreadId(),
                                 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,
   // PrintingParent, is always available for printing initiated from the parent.
   RefPtr<nsPrintingProxy> printingProxy = nsPrintingProxy::GetInstance();
 #endif
 
   SetProcessName(NS_LITERAL_STRING("Web Content"), true);
@@ -928,18 +943,24 @@ void
 ContentChild::InitGraphicsDeviceData()
 {
   // Initialize the graphics platform. This may contact the parent process
   // to read device preferences.
   gfxPlatform::GetPlatform();
 }
 
 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();
 
   nsCOMPtr<nsIIPCBackgroundChildCreateCallback> callback =
     new BackgroundChildPrimer();
   if (!BackgroundChild::GetOrCreateForCurrentThread(callback)) {
     MOZ_CRASH("Failed to create PBackgroundChild!");
@@ -952,71 +973,60 @@ ContentChild::InitXPCOM()
     NS_WARNING("Couldn't acquire console service");
     return;
   }
 
   mConsoleListener = new ConsoleListener(this);
   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<nsIClipboard> clipboard(do_GetService("@mozilla.org/widget/clipboard;1"));
   if (nsCOMPtr<nsIClipboardProxy> clipboardProxy = do_QueryInterface(clipboard)) {
-    clipboardProxy->SetCapabilities(clipboardCaps);
+    clipboardProxy->SetCapabilities(aXPCOMInit.clipboardCaps());
   }
 
   {
     AutoJSAPI jsapi;
     if (NS_WARN_IF(!jsapi.Init(xpc::PrivilegedJunkScope()))) {
       MOZ_CRASH();
     }
     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();
     }
     ProcessGlobal* global = ProcessGlobal::Get();
     global->SetInitialProcessData(data);
   }
 
   // The stylesheet cache is not ready yet. Store this URL for future use.
-  nsCOMPtr<nsIURI> ucsURL = DeserializeURI(userContentSheetURL);
+  nsCOMPtr<nsIURI> ucsURL = DeserializeURI(aXPCOMInit.userContentSheetURL());
   nsLayoutStylesheetCache::SetUserContentCSSURL(ucsURL);
 
   // This will register cross-process observer.
   mozilla::dom::time::InitializeDateCacheCleaner();
 }
 
 mozilla::ipc::IPCResult
 ContentChild::RecvRequestMemoryReport(const uint32_t& aGeneration,
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -91,19 +91,22 @@ public:
                       const nsAString& aName,
                       const nsACString& aFeatures,
                       bool aForceNoOpener,
                       bool* aWindowIsNew,
                       mozIDOMWindowProxy** aReturn);
 
   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();
 
   static ContentChild* GetSingleton()
   {
     return sSingleton;
   }
 
@@ -568,16 +571,21 @@ public:
 
   mozilla::ipc::IPCResult
   RecvRequestMemoryReport(
           const uint32_t& generation,
           const bool& anonymize,
           const bool& minimizeMemoryUsage,
           const MaybeFileDesc& DMDFile) override;
 
+  virtual mozilla::ipc::IPCResult
+  RecvSetXPCOMProcessAttributes(const XPCOMInitData& aXPCOMInit,
+                                const StructuredCloneData& aInitialData,
+                                nsTArray<LookAndFeelInt>&& aLookAndFeelIntCache) override;
+
 #if defined(XP_WIN) && defined(ACCESSIBILITY)
   bool
   SendGetA11yContentId();
 #endif // defined(XP_WIN) && defined(ACCESSIBILITY)
 
   // Get a reference to the font family list passed from the chrome process,
   // for use during gfx initialization.
   InfallibleTArray<mozilla::dom::FontFamilyListEntry>&
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -181,16 +181,18 @@
 #include "mozilla/StyleSheetInlines.h"
 #include "nsHostObjectProtocolHandler.h"
 #include "nsICaptivePortalService.h"
 
 #include "nsIBidiKeyboard.h"
 
 #include "nsLayoutStylesheetCache.h"
 
+#include "ContentPrefs.h"
+
 #ifdef MOZ_WEBRTC
 #include "signaling/src/peerconnection/WebrtcGlobalParent.h"
 #endif
 
 #if defined(ANDROID) || defined(LINUX)
 #include "nsSystemInfo.h"
 #endif
 
@@ -1819,16 +1821,58 @@ ContentParent::InitializeMembers()
 }
 
 bool
 ContentParent::LaunchSubprocess(ProcessPriority aInitialPriority /* = PROCESS_PRIORITY_FOREGROUND */)
 {
   PROFILER_LABEL_FUNC(js::ProfileEntry::Category::OTHER);
 
   std::vector<std::string> extraArgs;
+  extraArgs.push_back("-childID");
+  char idStr[21];
+  SprintfLiteral(idStr, "%" PRId64, static_cast<uint64_t>(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;
   }
 
   Open(mSubprocess->GetChannel(),
      base::GetProcId(mSubprocess->GetChildProcessHandle()));
 
@@ -1838,16 +1882,27 @@ ContentParent::LaunchSubprocess(ProcessP
 
   ContentProcessManager::GetSingleton()->AddContentProcess(this);
 
   mHangMonitorActor = ProcessHangMonitor::AddProcess(this);
 
   // Set a reply timeout for CPOWs.
   SetReplyTimeoutMs(Preferences::GetInt("dom.ipc.cpow.timeout", 0));
 
+  Telemetry::Accumulate(Telemetry::CONTENT_PROCESS_LAUNCH_TIME_MS,
+                        static_cast<uint32_t>((TimeStamp::Now() - mLaunchTS)
+                                              .ToMilliseconds()));
+
+  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+  if (obs) {
+    nsAutoString cpId;
+    cpId.AppendInt(static_cast<uint64_t>(this->ChildID()));
+    obs->NotifyObservers(static_cast<nsIObserver*>(this), "ipc:content-initializing", cpId.get());
+  }
+
   return true;
 }
 
 ContentParent::ContentParent(ContentParent* aOpener,
                              const nsAString& aRemoteType)
   : nsIContentParent()
   , mLaunchTS(TimeStamp::Now())
   , mOpener(aOpener)
@@ -1895,16 +1950,100 @@ ContentParent::~ContentParent()
              !sBrowserContentParents->Get(mRemoteType)->Contains(this));
 }
 
 void
 ContentParent::InitInternal(ProcessPriority aInitialPriority,
                             bool aSetupOffMainThreadCompositing,
                             bool aSendRegisteredChrome)
 {
+  Telemetry::Accumulate(Telemetry::CONTENT_PROCESS_LAUNCH_TIME_MS,
+                        static_cast<uint32_t>((TimeStamp::Now() - mLaunchTS)
+                                              .ToMilliseconds()));
+
+  XPCOMInitData xpcomInit;
+
+  Preferences::GetPreferences(&xpcomInit.prefs());
+  nsCOMPtr<nsIIOService> io(do_GetIOService());
+  MOZ_ASSERT(io, "No IO service?");
+  DebugOnly<nsresult> 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<nsICaptivePortalService> 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<nsISpellChecker> spellChecker(do_GetService(NS_SPELLCHECKER_CONTRACTID));
+  MOZ_ASSERT(spellChecker, "No spell checker?");
+
+  spellChecker->GetDictionaryList(&xpcomInit.dictionaries());
+
+  nsCOMPtr<nsIClipboard> 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<LookAndFeelInt> 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<nsIChromeRegistry> registrySvc = nsChromeRegistry::GetService();
     nsChromeRegistryChrome* chromeRegistry =
       static_cast<nsChromeRegistryChrome*>(registrySvc.get());
     chromeRegistry->SendRegisteredChrome(this);
   }
 
   if (gAppData) {
@@ -2067,23 +2206,16 @@ ContentParent::Pid() const
 {
   if (!mSubprocess || !mSubprocess->GetChildProcessHandle()) {
     return -1;
   }
   return base::GetProcId(mSubprocess->GetChildProcessHandle());
 }
 
 mozilla::ipc::IPCResult
-ContentParent::RecvReadPrefsArray(InfallibleTArray<PrefSetting>* aPrefs)
-{
-  Preferences::GetPreferences(aPrefs);
-  return IPC_OK();
-}
-
-mozilla::ipc::IPCResult
 ContentParent::RecvGetGfxVars(InfallibleTArray<GfxVarUpdate>* aVars)
 {
   // Ensure gfxVars is initialized (for xpcshell tests).
   gfxVars::Initialize();
 
   *aVars = gfxVars::FetchNonDefaultVars();
 
   // Now that content has initialized gfxVars, we can start listening for
@@ -2543,128 +2675,16 @@ ContentParent::RecvInitBackground(Endpoi
 {
   if (!BackgroundParent::Alloc(this, Move(aEndpoint))) {
     return IPC_FAIL(this, "BackgroundParent::Alloc failed");
   }
 
   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<nsString>* dictionaries,
-                                             ClipboardCapabilities* clipboardCaps,
-                                             DomainPolicyClone* domainPolicy,
-                                             StructuredCloneData* aInitialData,
-                                             InfallibleTArray<FontFamilyListEntry>* fontFamilies,
-                                             OptionalURIParams* aUserContentCSSURL,
-                                             nsTArray<LookAndFeelInt>* aLookAndFeelIntCache)
-{
-  Telemetry::Accumulate(Telemetry::CONTENT_PROCESS_LAUNCH_TIME_MS,
-                        static_cast<uint32_t>((TimeStamp::Now() - mLaunchTS)
-                                              .ToMilliseconds()));
-
-  nsCOMPtr<nsIIOService> io(do_GetIOService());
-  MOZ_ASSERT(io, "No IO service?");
-  DebugOnly<nsresult> 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<nsICaptivePortalService> 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<nsISpellChecker> spellChecker(do_GetService(NS_SPELLCHECKER_CONTRACTID));
-  MOZ_ASSERT(spellChecker, "No spell checker?");
-
-  spellChecker->GetDictionaryList(dictionaries);
-
-  nsCOMPtr<nsIClipboard> 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<nsIObserverService> obs = mozilla::services::GetObserverService();
-  if (obs) {
-    nsAutoString cpId;
-    cpId.AppendInt(static_cast<uint64_t>(this->ChildID()));
-    obs->NotifyObservers(static_cast<nsIObserver*>(this), "ipc:content-initializing", cpId.get());
-  }
-
-  return IPC_OK();
-}
-
 mozilla::jsipc::PJavaScriptParent *
 ContentParent::AllocPJavaScriptParent()
 {
   MOZ_ASSERT(ManagedPJavaScriptParent().IsEmpty());
   return nsIContentParent::AllocPJavaScriptParent();
 }
 
 bool
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -741,34 +741,16 @@ private:
 
   /**
    * Get or create the corresponding content parent array to |aContentProcessType|.
    */
   static nsTArray<ContentParent*>& GetOrCreatePool(const nsAString& aContentProcessType);
 
   virtual mozilla::ipc::IPCResult RecvInitBackground(Endpoint<mozilla::ipc::PBackgroundParent>&& 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<nsString>* dictionaries,
-                                ClipboardCapabilities* clipboardCaps,
-                                DomainPolicyClone* domainPolicy,
-                                StructuredCloneData* initialData,
-                                InfallibleTArray<FontFamilyListEntry>* fontFamilies,
-                                OptionalURIParams* aUserContentSheetURL,
-                                nsTArray<LookAndFeelInt>* aLookAndFeelIntCache) override;
-
-
   mozilla::ipc::IPCResult RecvAddMemoryReport(const MemoryReport& aReport) override;
   mozilla::ipc::IPCResult RecvFinishMemoryReport(const uint32_t& aGeneration) override;
 
   virtual bool
   DeallocPJavaScriptParent(mozilla::jsipc::PJavaScriptParent*) override;
 
   virtual bool
   DeallocPRemoteSpellcheckEngineParent(PRemoteSpellcheckEngineParent*) override;
@@ -893,17 +875,16 @@ private:
 
   virtual PWebBrowserPersistDocumentParent*
   AllocPWebBrowserPersistDocumentParent(PBrowserParent* aBrowser,
                                         const uint64_t& aOuterWindowID) override;
 
   virtual bool
   DeallocPWebBrowserPersistDocumentParent(PWebBrowserPersistDocumentParent* aActor) override;
 
-  virtual mozilla::ipc::IPCResult RecvReadPrefsArray(InfallibleTArray<PrefSetting>* aPrefs) override;
   virtual mozilla::ipc::IPCResult RecvGetGfxVars(InfallibleTArray<GfxVarUpdate>* aVars) override;
 
   virtual mozilla::ipc::IPCResult RecvReadFontList(InfallibleTArray<FontListEntry>* retValue) override;
 
   virtual mozilla::ipc::IPCResult RecvReadDataStorageArray(const nsString& aFilename,
                                                            InfallibleTArray<DataStorageItem>* aValues) override;
 
   virtual mozilla::ipc::IPCResult RecvReadPermissions(InfallibleTArray<IPC::Permission>* aPermissions) override;
new file mode 100644
--- /dev/null
+++ b/dom/ipc/ContentPrefs.cpp
@@ -0,0 +1,276 @@
+/* -*- 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.event.touch.coalescing.enabled",
+  "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];
+}
+
new file mode 100644
--- /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
--- a/dom/ipc/ContentProcess.cpp
+++ b/dom/ipc/ContentProcess.cpp
@@ -2,16 +2,17 @@
 /* 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 "mozilla/ipc/IOThreadChild.h"
 
 #include "ContentProcess.h"
+#include "ContentPrefs.h"
 
 #if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
 #include <stdlib.h>
 #endif
 
 #if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
 #include "mozilla/Preferences.h"
 #include "nsAppDirectoryServiceDefs.h"
@@ -98,60 +99,157 @@ SetUpSandboxEnvironment()
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return;
   }
 
   SetTmpEnvironmentVariable(sandboxedContentTemp);
 }
 #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<nsIFile> profileDir;
 #endif
 
-bool
-ContentProcess::Init()
-{
-    mContent.Init(IOThreadChild::message_loop(),
-                  ParentPid(),
-                  IOThreadChild::channel());
-    mXREEmbed.Start();
-    mContent.InitXPCOM();
-    mContent.InitGraphicsDeviceData();
+  InfallibleTArray<PrefSetting> 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<int32_t>(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
 // in ContentChild::ActorDestroy().
 void
 ContentProcess::CleanUp()
 {
-    mXREEmbed.Stop();
+  mXREEmbed.Stop();
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/ipc/ContentProcess.h
+++ b/dom/ipc/ContentProcess.h
@@ -29,33 +29,23 @@ class ContentProcess : public mozilla::i
 public:
   explicit ContentProcess(ProcessId aParentPid)
     : ProcessChild(aParentPid)
   { }
 
   ~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<nsIFile> mProfileDir;
-#endif
-
 #if defined(XP_WIN)
   // This object initializes and configures COM.
   mozilla::mscom::MainThreadRuntime mCOMRuntime;
 #endif
 
   DISALLOW_EVIL_CONSTRUCTORS(ContentProcess);
 };
 
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -329,16 +329,32 @@ struct GMPAPITags
 
 struct GMPCapabilityData
 {
     nsCString name;
     nsCString version;
     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;
     int32_t status;
     nsCString failureId;
 };
 
 /**
@@ -522,16 +538,18 @@ child:
      */
     async InitServiceWorkers(ServiceWorkerConfiguration aConfig);
 
     /**
      * Send BlobURLRegistrationData to child process.
      */
     async InitBlobURLs(BlobURLRegistrationData[] registrations);
 
+    async SetXPCOMProcessAttributes(XPCOMInitData xpcomInit, StructuredCloneData initialData, LookAndFeelInt[] lookAndFeelIntCache);
+
     // Notify child that last-pb-context-exited notification was observed
     async LastPrivateDocShellDestroyed();
 
     async FilePathUpdate(nsString storageType, nsString storageName, nsString filepath,
                          nsCString reasons);
 
     async NotifyProcessPriorityChanged(ProcessPriority priority);
     async MinimizeMemoryUsage();
@@ -645,40 +663,16 @@ child:
     async BlobURLUnregistration(nsCString aURI);
 
 
     async GMPsChanged(GMPCapabilityData[] capabilities);
 
 parent:
     async InitBackground(Endpoint<PBackgroundParent> 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 <browser> or <xul:browser remote>.
-     *
-     * 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)
         returns (ContentParentId cpId, bool isForBrowser, TabId tabId);
     sync BridgeToChildProcess(ContentParentId cpId)
         returns (Endpoint<PContentBridgeParent> endpoint);
 
     async CreateGMPService();
@@ -812,17 +806,16 @@ parent:
     async StartVisitedQuery(URIParams uri);
     async VisitURI(URIParams uri, OptionalURIParams referrer, uint32_t flags);
     async SetURITitle(URIParams uri, nsString title);
 
     async LoadURIExternal(URIParams uri, PBrowser windowContext);
     async ExtProtocolChannelConnectParent(uint32_t registrarId);
 
     // PrefService message
-    sync ReadPrefsArray() returns (PrefSetting[] prefs) verify;
     sync GetGfxVars() returns (GfxVarUpdate[] vars);
 
     sync ReadFontList() returns (FontListEntry[] retValue);
 
     sync ReadDataStorageArray(nsString aFilename)
       returns (DataStorageItem[] retValue);
 
     sync SyncMessage(nsString aMessage, ClonedMessageData aData,
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -114,16 +114,18 @@
 #include "FrameLayerBuilder.h"
 #include "VRManagerChild.h"
 #include "nsICommandParams.h"
 #include "nsISHistory.h"
 #include "nsQueryObject.h"
 #include "GroupedSHistory.h"
 #include "nsIHttpChannel.h"
 #include "mozilla/dom/DocGroup.h"
+#include "nsISupportsPrimitives.h"
+#include "mozilla/Telemetry.h"
 
 #ifdef NS_PRINTING
 #include "nsIPrintSession.h"
 #include "nsIPrintSettings.h"
 #include "nsIPrintSettingsService.h"
 #include "nsIWebBrowserPrint.h"
 #endif
 
--- a/dom/ipc/moz.build
+++ b/dom/ipc/moz.build
@@ -15,16 +15,17 @@ EXPORTS.mozilla.dom.ipc += [
     'StructuredCloneData.h',
 ]
 
 EXPORTS.mozilla.dom += [
     'ContentBridgeChild.h',
     'ContentBridgeParent.h',
     'ContentChild.h',
     'ContentParent.h',
+    'ContentPrefs.h',
     'ContentProcess.h',
     'ContentProcessManager.h',
     'CPOWManagerGetter.h',
     'CrashReporterChild.h',
     'CrashReporterParent.h',
     'FilePickerParent.h',
     'MemoryReportRequest.h',
     'nsIContentChild.h',
@@ -45,16 +46,17 @@ EXPORTS.mozilla += [
     'ProcessPriorityManager.h',
 ]
 
 UNIFIED_SOURCES += [
     'ColorPickerParent.cpp',
     'ContentBridgeChild.cpp',
     'ContentBridgeParent.cpp',
     'ContentParent.cpp',
+    'ContentPrefs.cpp',
     'ContentProcess.cpp',
     'ContentProcessManager.cpp',
     'CrashReporterParent.cpp',
     'DatePickerParent.cpp',
     'FilePickerParent.cpp',
     'MemoryReportRequest.cpp',
     'nsIContentChild.cpp',
     'nsIContentParent.cpp',
--- a/dom/media/gmp/GMPProcessChild.cpp
+++ b/dom/media/gmp/GMPProcessChild.cpp
@@ -20,17 +20,17 @@ GMPProcessChild::GMPProcessChild(Process
 {
 }
 
 GMPProcessChild::~GMPProcessChild()
 {
 }
 
 bool
-GMPProcessChild::Init()
+GMPProcessChild::Init(int aArgc, char* aArgv[])
 {
   nsAutoString pluginFilename;
 
 #if defined(OS_POSIX)
   // NB: need to be very careful in ensuring that the first arg
   // (after the binary name) here is indeed the plugin module path.
   // Keep in sync with dom/plugins/PluginModuleParent.
   std::vector<std::string> values = CommandLine::ForCurrentProcess()->argv();
--- a/dom/media/gmp/GMPProcessChild.h
+++ b/dom/media/gmp/GMPProcessChild.h
@@ -17,17 +17,17 @@ class GMPLoader;
 class GMPProcessChild final : public mozilla::ipc::ProcessChild {
 protected:
   typedef mozilla::ipc::ProcessChild ProcessChild;
 
 public:
   explicit GMPProcessChild(ProcessId aParentPid);
   ~GMPProcessChild();
 
-  bool Init() override;
+  bool Init(int aArgc, char* aArgv[]) override;
   void CleanUp() override;
 
 private:
   GMPChild mPlugin;
   DISALLOW_COPY_AND_ASSIGN(GMPProcessChild);
 };
 
 } // namespace gmp
--- a/dom/plugins/ipc/PluginProcessChild.cpp
+++ b/dom/plugins/ipc/PluginProcessChild.cpp
@@ -35,17 +35,17 @@ using mozilla::ipc::IOThreadChild;
 #include <algorithm>
 #endif
 
 namespace mozilla {
 namespace plugins {
 
 
 bool
-PluginProcessChild::Init()
+PluginProcessChild::Init(int aArgc, char* aArgv[])
 {
     nsDebugImpl::SetMultiprocessMode("NPAPI");
 
 #if defined(XP_MACOSX)
     // Remove the trigger for "dyld interposing" that we added in
     // GeckoChildProcessHost::PerformAsyncLaunchInternal(), in the host
     // process just before we were launched.  Dyld interposing will still
     // happen in our process (the plugin child process).  But we don't want
--- a/dom/plugins/ipc/PluginProcessChild.h
+++ b/dom/plugins/ipc/PluginProcessChild.h
@@ -25,17 +25,17 @@ protected:
 public:
     explicit PluginProcessChild(ProcessId aParentPid)
       : ProcessChild(aParentPid), mPlugin(true)
     { }
 
     virtual ~PluginProcessChild()
     { }
 
-    virtual bool Init() override;
+    virtual bool Init(int aArgc, char* aArgv[]) override;
     virtual void CleanUp() override;
 
 protected:
     static PluginProcessChild* current() {
         return static_cast<PluginProcessChild*>(ProcessChild::current());
     }
 
 private:
--- a/gfx/ipc/GPUProcessImpl.cpp
+++ b/gfx/ipc/GPUProcessImpl.cpp
@@ -17,17 +17,17 @@ GPUProcessImpl::GPUProcessImpl(ProcessId
 {
 }
 
 GPUProcessImpl::~GPUProcessImpl()
 {
 }
 
 bool
-GPUProcessImpl::Init()
+GPUProcessImpl::Init(int aArgc, char* aArgv[])
 {
   return mGPU.Init(ParentPid(),
                    IOThreadChild::message_loop(),
                    IOThreadChild::channel());
 }
 
 void
 GPUProcessImpl::CleanUp()
--- a/gfx/ipc/GPUProcessImpl.h
+++ b/gfx/ipc/GPUProcessImpl.h
@@ -19,17 +19,17 @@ namespace gfx {
 // This class owns the subprocess instance of a PGPU - which in this case,
 // is a GPUParent. It is instantiated as a singleton in XRE_InitChildProcess.
 class GPUProcessImpl final : public ipc::ProcessChild
 {
 public:
   explicit GPUProcessImpl(ProcessId aParentPid);
   ~GPUProcessImpl();
 
-  bool Init() override;
+  bool Init(int aArgc, char* aArgv[]) override;
   void CleanUp() override;
 
 private:
   DISALLOW_COPY_AND_ASSIGN(GPUProcessImpl);
 
   GPUParent mGPU;
 
 #if defined(XP_WIN)
--- a/ipc/glue/ProcessChild.h
+++ b/ipc/glue/ProcessChild.h
@@ -22,17 +22,17 @@ namespace ipc {
 class ProcessChild : public ChildProcess {
 protected:
   typedef base::ProcessId ProcessId;
 
 public:
   explicit ProcessChild(ProcessId aParentPid);
   virtual ~ProcessChild();
 
-  virtual bool Init() = 0;
+  virtual bool Init(int aArgc, char* aArgv[]) = 0;
   virtual void CleanUp()
   { }
 
   static MessageLoop* message_loop() {
     return gProcessChild->mUILoop;
   }
 
     /**
--- a/modules/libpref/Preferences.cpp
+++ b/modules/libpref/Preferences.cpp
@@ -1,16 +1,16 @@
 /* -*- 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 "mozilla/MemoryReporting.h"
-#include "mozilla/dom/ContentChild.h"
+#include "mozilla/dom/PContent.h"
 
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/HashFunctions.h"
 #include "mozilla/UniquePtrExtensions.h"
 
 #include "nsXULAppAPI.h"
 
@@ -541,36 +541,42 @@ NS_INTERFACE_MAP_BEGIN(Preferences)
     NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
 NS_INTERFACE_MAP_END
 
 
 /*
  * nsIPrefService Implementation
  */
 
+InfallibleTArray<Preferences::PrefSetting>* gInitPrefs;
+
+/*static*/
+void
+Preferences::SetInitPreferences(nsTArray<PrefSetting>* aPrefs) {
+  gInitPrefs = new InfallibleTArray<PrefSetting>(mozilla::Move(*aPrefs));
+}
+
 nsresult
 Preferences::Init()
 {
   nsresult rv;
 
   PREF_SetDirtyCallback(&DirtyCallback);
   PREF_Init();
 
   rv = pref_InitInitialObjects();
   NS_ENSURE_SUCCESS(rv, rv);
 
-  using mozilla::dom::ContentChild;
   if (XRE_IsContentProcess()) {
-    InfallibleTArray<PrefSetting> 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;
   }
 
   nsXPIDLCString lockFileName;
   /*
    * The following is a small hack which will allow us to only load the library
    * which supports the netscape.cfg file if the preference is defined. We
    * test for the existence of the pref, set in the all.js (mozilla) or
@@ -775,16 +781,24 @@ Preferences::GetPreferences(InfallibleTA
       continue;
     }
 
     dom::PrefSetting *pref = aPrefs->AppendElement();
     pref_GetPrefFromEntry(entry, pref);
   }
 }
 
+#ifdef DEBUG
+void
+Preferences::SetInitPhase(pref_initPhase phase)
+{
+  pref_SetInitPhase(phase);
+}
+#endif
+
 NS_IMETHODIMP
 Preferences::GetBranch(const char *aPrefRoot, nsIPrefBranch **_retval)
 {
   nsresult rv;
 
   if ((nullptr != aPrefRoot) && (*aPrefRoot != '\0')) {
     // TODO: - cache this stuff and allow consumers to share branches (hold weak references I think)
     RefPtr<nsPrefBranch> prefBranch = new nsPrefBranch(aPrefRoot, false);
--- a/modules/libpref/Preferences.h
+++ b/modules/libpref/Preferences.h
@@ -23,16 +23,30 @@ class nsIFile;
 class nsAdoptingString;
 class nsAdoptingCString;
 
 #ifndef have_PrefChangedFunc_typedef
 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 {
 class PrefSetting;
 } // namespace dom
 
 class Preferences final : public nsIPrefService,
                           public nsIObserver,
@@ -361,16 +375,22 @@ public:
    */
   static int32_t GetDefaultType(const char* aPref);
 
   // Used to synchronise preferences between chrome and content processes.
   static void GetPreferences(InfallibleTArray<PrefSetting>* aPrefs);
   static void GetPreference(PrefSetting* aPref);
   static void SetPreference(const PrefSetting& aPref);
 
+  static void SetInitPreferences(nsTArray<PrefSetting>* aPrefs);
+
+#ifdef DEBUG
+  static void SetInitPhase(pref_initPhase phase);
+#endif
+
   static int64_t SizeOfIncludingThisAndOtherStuff(mozilla::MallocSizeOf aMallocSizeOf);
 
   static void DirtyCallback();
 
 protected:
   virtual ~Preferences();
 
   nsresult NotifyServiceObservers(const char *aSubject);
--- a/modules/libpref/prefapi.cpp
+++ b/modules/libpref/prefapi.cpp
@@ -24,16 +24,17 @@
 
 #include "plstr.h"
 #include "PLDHashTable.h"
 #include "plbase64.h"
 #include "mozilla/Logging.h"
 #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"
 #include "prlink.h"
 
 using namespace mozilla;
 
 static void
@@ -731,23 +732,58 @@ static PrefTypeFlags pref_SetValue(PrefV
         MOZ_ASSERT(newValue.stringVal);
         existingValue->stringVal = newValue.stringVal ? PL_strdup(newValue.stringVal) : nullptr;
     }
     else {
         *existingValue = newValue;
     }
     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<PrefHashEntry*>(gHashTable->Search(key));
 }
 
 nsresult pref_HashPref(const char *key, PrefValue value, PrefType type, uint32_t flags)
 {
 #ifndef MOZ_B2G
     MOZ_ASSERT(NS_IsMainThread());
 #endif
--- a/modules/libpref/prefapi_private_data.h
+++ b/modules/libpref/prefapi_private_data.h
@@ -5,31 +5,37 @@
 
 /* Data shared between prefapi.c and nsPref.cpp */
 
 #ifndef prefapi_private_data_h
 #define prefapi_private_data_h
 
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/UniquePtr.h"
+#include "Preferences.h"
 
 extern PLDHashTable* gHashTable;
 
 namespace mozilla {
 namespace dom {
 class PrefSetting;
 } // namespace dom
 } // namespace mozilla
 
 mozilla::UniquePtr<char*[]>
 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);
 
 bool
 pref_EntryHasAdvisablySizedValues(PrefHashEntry* aHashEntry);
 
 void pref_GetPrefFromEntry(PrefHashEntry *aHashEntry,
                            mozilla::dom::PrefSetting* aPref);
--- a/toolkit/xre/nsEmbedFunctions.cpp
+++ b/toolkit/xre/nsEmbedFunctions.cpp
@@ -620,59 +620,18 @@ XRE_InitChildProcess(int aArgc,
       case GeckoProcessType_Default:
         MOZ_CRASH("This makes no sense");
         break;
 
       case GeckoProcessType_Plugin:
         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<ContentProcess*>(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<ContentProcess*>(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:
 #ifdef MOZ_IPDL_TESTS
         process = new IPDLUnitTestProcessChild(parentPID);
 #else
         MOZ_CRASH("rebuild with --enable-ipdl-tests");
 #endif
@@ -685,17 +644,17 @@ XRE_InitChildProcess(int aArgc,
       case GeckoProcessType_GPU:
         process = new gfx::GPUProcessImpl(parentPID);
         break;
 
       default:
         MOZ_CRASH("Unknown main thread class");
       }
 
-      if (!process->Init()) {
+      if (!process->Init(aArgc, aArgv)) {
         return NS_ERROR_FAILURE;
       }
 
 #ifdef MOZ_CRASHREPORTER
 #if defined(XP_WIN) || defined(XP_MACOSX)
       CrashReporter::InitChildProcessTmpDir();
 #endif
 #endif