Bug 1337063 - Transfer child's initial ContentDeviceData with SendSetXPCOMProcessAttributes - r=dvander draft
authorMilan Sreckovic <milan@mozilla.com>
Tue, 30 May 2017 13:07:32 -0400
changeset 586525 3f78a6c5efc5dc375dccdf6295c47ced2135a7b7
parent 586442 286f71223256cbb3a769432fd860f563c4886e81
child 631022 e20dd3aa08778e13985e99618760b96b102ddd1f
push id61443
push userbmo:milan@mozilla.com
push dateTue, 30 May 2017 17:11:49 +0000
reviewersdvander
bugs1337063
milestone55.0a1
Bug 1337063 - Transfer child's initial ContentDeviceData with SendSetXPCOMProcessAttributes - r=dvander MozReview-Commit-ID: 23Xf9DW2Hb9
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
dom/ipc/ContentParent.cpp
dom/ipc/PContent.ipdl
gfx/ipc/D3DMessageUtils.cpp
gfx/thebes/gfxPlatform.cpp
gfx/thebes/gfxPlatform.h
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -520,17 +520,17 @@ NS_INTERFACE_MAP_END
 
 mozilla::ipc::IPCResult
 ContentChild::RecvSetXPCOMProcessAttributes(const XPCOMInitData& aXPCOMInit,
                                             const StructuredCloneData& aInitialData,
                                             nsTArray<LookAndFeelInt>&& aLookAndFeelIntCache)
 {
   mLookAndFeelCache = aLookAndFeelIntCache;
   InitXPCOM(aXPCOMInit, aInitialData);
-  InitGraphicsDeviceData();
+  InitGraphicsDeviceData(aXPCOMInit.contentDeviceData());
 
 #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.
   // Create nsPrintingProxy instance later than the SystemGroup initialization.
   RefPtr<nsPrintingProxy> printingProxy = nsPrintingProxy::GetInstance();
 #endif
 
@@ -961,21 +961,21 @@ ContentChild::AppendProcessId(nsACString
   if (!aName.IsEmpty()) {
     aName.Append(' ');
   }
   unsigned pid = getpid();
   aName.Append(nsPrintfCString("(pid %u)", pid));
 }
 
 void
-ContentChild::InitGraphicsDeviceData()
+ContentChild::InitGraphicsDeviceData(const ContentDeviceData& aData)
 {
   // Initialize the graphics platform. This may contact the parent process
   // to read device preferences.
-  gfxPlatform::GetPlatform();
+  gfxPlatform::InitChild(aData);
 }
 
 void
 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++) {
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -101,17 +101,17 @@ public:
             base::ProcessId aParentPid,
             IPC::Channel* aChannel,
             uint64_t aChildID,
             bool aIsForBrowser);
 
   void InitXPCOM(const XPCOMInitData& aXPCOMInit,
                  const mozilla::dom::ipc::StructuredCloneData& aInitialData);
 
-  void InitGraphicsDeviceData();
+  void InitGraphicsDeviceData(const ContentDeviceData& aData);
 
   static ContentChild* GetSingleton()
   {
     return sSingleton;
   }
 
   const AppInfo& GetAppInfo()
   {
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -2229,16 +2229,18 @@ ContentParent::InitInternal(ProcessPrior
   // send the file URL instead.
   StyleSheet* ucs = nsLayoutStylesheetCache::For(StyleBackendType::Gecko)->UserContentSheet();
   if (ucs) {
     SerializeURI(ucs->GetSheetURI(), xpcomInit.userContentSheetURL());
   } else {
     SerializeURI(nullptr, xpcomInit.userContentSheetURL());
   }
 
+  gfxPlatform::GetPlatform()->BuildContentDeviceData(&xpcomInit.contentDeviceData());
+
   nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
   if (gfxInfo) {
     for (int32_t i = 1; i <= nsIGfxInfo::FEATURE_MAX_VALUE; ++i) {
       int32_t status = 0;
       nsAutoCString failureId;
       gfxInfo->GetFeatureStatus(i, failureId, &status);
       dom::GfxInfoFeatureStatus gfxFeatureStatus;
       gfxFeatureStatus.feature() = i;
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -263,16 +263,17 @@ struct XPCOMInitData
     bool haveBidiKeyboards;
     nsString[] dictionaries;
     ClipboardCapabilities clipboardCaps;
     DomainPolicyClone domainPolicy;
     /* used on MacOSX only */
     FontFamilyListEntry[] fontFamilies;
     OptionalURIParams userContentSheetURL;
     PrefSetting[] prefs;
+    ContentDeviceData contentDeviceData;
     GfxInfoFeatureStatus[] gfxFeatureStatus;
     DataStorageEntry[] dataStorage;
     nsCString[] appLocales;
     nsCString[] requestedLocales;
 };
 
 /**
  * The PContent protocol is a top-level protocol between the UI process
--- a/gfx/ipc/D3DMessageUtils.cpp
+++ b/gfx/ipc/D3DMessageUtils.cpp
@@ -42,18 +42,16 @@ ParamTraits<DxgiAdapterDesc>::Write(Mess
   WriteParam(aMsg, aParam.DeviceId);
   WriteParam(aMsg, aParam.SubSysId);
   WriteParam(aMsg, aParam.Revision);
   WriteParam(aMsg, aParam.DedicatedVideoMemory);
   WriteParam(aMsg, aParam.DedicatedSystemMemory);
   WriteParam(aMsg, aParam.SharedSystemMemory);
   WriteParam(aMsg, aParam.AdapterLuid.LowPart);
   WriteParam(aMsg, aParam.AdapterLuid.HighPart);
-#else
-  MOZ_ASSERT_UNREACHABLE("DxgiAdapterDesc is Windows-only");
 #endif
 }
 
 bool
 ParamTraits<DxgiAdapterDesc>::Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
 {
 #if defined(XP_WIN)
   if (!aMsg->ReadBytesInto(aIter, aResult->Description, sizeof(aResult->Description))) {
@@ -67,15 +65,15 @@ ParamTraits<DxgiAdapterDesc>::Read(const
       ReadParam(aMsg, aIter, &aResult->DedicatedVideoMemory) &&
       ReadParam(aMsg, aIter, &aResult->DedicatedSystemMemory) &&
       ReadParam(aMsg, aIter, &aResult->SharedSystemMemory) &&
       ReadParam(aMsg, aIter, &aResult->AdapterLuid.LowPart) &&
       ReadParam(aMsg, aIter, &aResult->AdapterLuid.HighPart))
   {
     return true;
   }
+  return false;
 #else
-  MOZ_ASSERT_UNREACHABLE("DxgiAdapterDesc is Windows-only");
+  return true;
 #endif
-  return false;
 }
 
 } // namespace IPC
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -147,16 +147,18 @@ void ShutdownTileCache();
 using namespace mozilla;
 using namespace mozilla::layers;
 using namespace mozilla::gl;
 using namespace mozilla::gfx;
 
 gfxPlatform *gPlatform = nullptr;
 static bool gEverInitialized = false;
 
+const ContentDeviceData* gContentDeviceInitData = nullptr;
+
 static Mutex* gGfxPlatformPrefsLock = nullptr;
 
 // These two may point to the same profile
 static qcms_profile *gCMSOutputProfile = nullptr;
 static qcms_profile *gCMSsRGBProfile = nullptr;
 
 static qcms_transform *gCMSRGBTransform = nullptr;
 static qcms_transform *gCMSInverseRGBTransform = nullptr;
@@ -522,27 +524,42 @@ gfxPlatform::gfxPlatform()
 
     VRManager::ManagerInit();
 }
 
 gfxPlatform*
 gfxPlatform::GetPlatform()
 {
     if (!gPlatform) {
+        MOZ_RELEASE_ASSERT(!XRE_IsContentProcess(),
+                           "Content Process should have called InitChild() before first GetPlatform()");
         Init();
     }
     return gPlatform;
 }
 
 bool
 gfxPlatform::Initialized()
 {
   return !!gPlatform;
 }
 
+/* static */ void
+gfxPlatform::InitChild(const ContentDeviceData& aData)
+{
+  MOZ_ASSERT(XRE_IsContentProcess());
+  MOZ_RELEASE_ASSERT(!gPlatform,
+                     "InitChild() should be called before first GetPlatform()");
+  // Make the provided initial ContentDeviceData available to the init
+  // routines, so they don't have to do a sync request from the parent.
+  gContentDeviceInitData = &aData;
+  Init();
+  gContentDeviceInitData = nullptr;
+}
+
 void RecordingPrefChanged(const char *aPrefName, void *aClosure)
 {
   if (Preferences::GetBool("gfx.2d.recording", false)) {
     nsAutoCString fileName;
     nsAdoptingString prefFileName = Preferences::GetString("gfx.2d.recordingfile");
 
     if (prefFileName) {
       fileName.Append(NS_ConvertUTF16toUTF8(prefFileName));
@@ -2666,16 +2683,21 @@ gfxPlatform::NotifyGPUProcessDisabled()
   }
 }
 
 void
 gfxPlatform::FetchAndImportContentDeviceData()
 {
   MOZ_ASSERT(XRE_IsContentProcess());
 
+  if (gContentDeviceInitData) {
+    ImportContentDeviceData(*gContentDeviceInitData);
+    return;
+  }
+
   mozilla::dom::ContentChild* cc = mozilla::dom::ContentChild::GetSingleton();
 
   mozilla::gfx::ContentDeviceData data;
   cc->SendGetGraphicsDeviceInitData(&data);
 
   ImportContentDeviceData(data);
 }
 
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -170,16 +170,22 @@ public:
     static bool Initialized();
 
     /**
      * Shut down Thebes.
      * Init() arranges for this to be called at an appropriate time.
      */
     static void Shutdown();
 
+    /**
+     * Initialize gfxPlatform (if not already done) in a child process, with
+     * the provided ContentDeviceData.
+     */
+    static void InitChild(const mozilla::gfx::ContentDeviceData& aData);
+
     static void InitLayersIPC();
     static void ShutdownLayersIPC();
 
     /**
      * Initialize ScrollMetadata statics. Does not depend on gfxPlatform.
      */
     static void InitNullMetadata();