Bug 1040017: Prevent SetOffLineStatus from being sent to Nuwa after loading. r=khuey
☠☠ backed out by 548e9d7175ec ☠ ☠
authorPatrick Wang (Chih-Kai Wang) <kk1fff@patrickz.net>
Thu, 21 Aug 2014 13:32:57 +0800
changeset 200753 7a6008e82204cb0221305eb0bb38215c34e72a32
parent 200752 a4200559a648a1e2a6d67dd6a18cfa80e12a035b
child 200754 ff9ac3b549cc6f6415c6ff9b66b4d9059c767698
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewerskhuey
bugs1040017
milestone34.0a1
Bug 1040017: Prevent SetOffLineStatus from being sent to Nuwa after loading. r=khuey
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -178,16 +178,43 @@ using namespace mozilla::system;
 #endif
 
 #if defined(MOZ_CONTENT_SANDBOX) && defined(XP_LINUX)
 #include "mozilla/Sandbox.h"
 #endif
 
 static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID);
 static const char* sClipboardTextFlavors[] = { kUnicodeMime };
+#ifdef MOZ_NUWA_PROCESS
+bool ContentParent::sNuwaReady = false;
+
+// Contains data that is observed by Nuwa and is going to be sent to
+// the new process when it is forked.
+struct ContentParent::NuwaReinitializeData {
+    NuwaReinitializeData()
+        : mReceivedFilePathUpdate(false)
+        , mReceivedFileSystemUpdate(false) { }
+
+    bool mReceivedFilePathUpdate;
+    nsString mFilePathUpdateStoageType;
+    nsString mFilePathUpdateStorageName;
+    nsString mFilePathUpdatePath;
+    nsCString mFilePathUpdateReason;
+
+    bool mReceivedFileSystemUpdate;
+    nsString mFileSystemUpdateFsName;
+    nsString mFileSystemUpdateMountPount;
+    int32_t mFileSystemUpdateState;
+    int32_t mFileSystemUpdateMountGeneration;
+    bool mFileSystemUpdateIsMediaPresent;
+    bool mFileSystemUpdateIsSharing;
+    bool mFileSystemUpdateIsFormatting;
+    bool mFileSystemUpdateIsFake;
+};
+#endif
 
 using base::ChildPrivileges;
 using base::KillProcess;
 using namespace mozilla::dom::bluetooth;
 using namespace mozilla::dom::devicestorage;
 using namespace mozilla::dom::indexedDB;
 using namespace mozilla::dom::power;
 using namespace mozilla::dom::mobilemessage;
@@ -569,16 +596,19 @@ ContentParent::RunNuwaProcess()
     nsRefPtr<ContentParent> nuwaProcess =
         new ContentParent(/* aApp = */ nullptr,
                           /* aOpener = */ nullptr,
                           /* aIsForBrowser = */ false,
                           /* aIsForPreallocated = */ true,
                           PROCESS_PRIORITY_BACKGROUND,
                           /* aIsNuwaProcess = */ true);
     nuwaProcess->Init();
+#ifdef MOZ_NUWA_PROCESS
+    sNuwaReady = false;
+#endif
     return nuwaProcess.forget();
 }
 
 // PreallocateAppProcess is called by the PreallocatedProcessManager.
 // ContentParent then takes this process back within
 // GetNewOrPreallocatedAppProcess.
 /*static*/ already_AddRefed<ContentParent>
 ContentParent::PreallocateAppProcess()
@@ -1966,16 +1996,22 @@ ContentParent::~ContentParent()
     } else {
         // In general, we expect sAppContentParents->Get(mAppManifestURL) to be
         // nullptr.  But it could be that we created another ContentParent for
         // this app after we did this->ActorDestroy(), so the right check is
         // that sAppContentParents->Get(mAppManifestURL) != this.
         MOZ_ASSERT(!sAppContentParents ||
                    sAppContentParents->Get(mAppManifestURL) != this);
     }
+
+#ifdef MOZ_NUWA_PROCESS
+    if (IsNuwaProcess()) {
+        sNuwaReady = false;
+    }
+#endif
 }
 
 void
 ContentParent::InitInternal(ProcessPriority aInitialPriority,
                             bool aSetupOffMainThreadCompositing,
                             bool aSendRegisteredChrome)
 {
     // Set the subprocess's priority.  We do this early on because we're likely
@@ -2426,16 +2462,17 @@ ContentParent::RecvNuwaReady()
         NS_ERROR(
             nsPrintfCString(
                 "Terminating child process %d for unauthorized IPC message: NuwaReady",
                 Pid()).get());
 
         KillHard();
         return false;
     }
+    sNuwaReady = true;
     PreallocatedProcessManager::OnNuwaReady();
     return true;
 #else
     NS_ERROR("ContentParent::RecvNuwaReady() not implemented!");
     return false;
 #endif
 }
 
@@ -2461,16 +2498,42 @@ ContentParent::RecvAddNewProcess(const u
     content->Init();
 
     size_t numNuwaPrefUpdates = sNuwaPrefUpdates ?
                                 sNuwaPrefUpdates->Length() : 0;
     // Resend pref updates to the forked child.
     for (int i = 0; i < numNuwaPrefUpdates; i++) {
         content->SendPreferenceUpdate(sNuwaPrefUpdates->ElementAt(i));
     }
+
+    // Update offline settings.
+    bool isOffline;
+    RecvGetXPCOMProcessAttributes(&isOffline);
+    content->SendSetOffline(isOffline);
+
+    // Send observed updates to new content.
+    if (mReinitializeData) {
+        if (mReinitializeData->mReceivedFilePathUpdate) {
+            unused << content->SendFilePathUpdate(mReinitializeData->mFilePathUpdateStoageType,
+                                                  mReinitializeData->mFilePathUpdateStorageName,
+                                                  mReinitializeData->mFilePathUpdatePath,
+                                                  mReinitializeData->mFilePathUpdateReason);
+        }
+        if (mReinitializeData->mReceivedFilePathUpdate) {
+            unused << content->SendFileSystemUpdate(mReinitializeData->mFileSystemUpdateFsName,
+                                                    mReinitializeData->mFileSystemUpdateMountPount,
+                                                    mReinitializeData->mFileSystemUpdateState,
+                                                    mReinitializeData->mFileSystemUpdateMountGeneration,
+                                                    mReinitializeData->mFileSystemUpdateIsMediaPresent,
+                                                    mReinitializeData->mFileSystemUpdateIsSharing,
+                                                    mReinitializeData->mFileSystemUpdateIsFormatting,
+                                                    mReinitializeData->mFileSystemUpdateIsFake);
+        }
+    }
+
     PreallocatedProcessManager::PublishSpareProcess(content);
     return true;
 #else
     NS_ERROR("ContentParent::RecvAddNewProcess() not implemented!");
     return false;
 #endif
 }
 
@@ -2529,18 +2592,25 @@ ContentParent::Observe(nsISupports* aSub
         if (!SendPreferenceUpdate(pref)) {
             return NS_ERROR_NOT_AVAILABLE;
         }
 #endif
     }
     else if (!strcmp(aTopic, NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC)) {
       NS_ConvertUTF16toUTF8 dataStr(aData);
       const char *offline = dataStr.get();
-      if (!SendSetOffline(!strcmp(offline, "true") ? true : false))
-          return NS_ERROR_NOT_AVAILABLE;
+#ifdef MOZ_NUWA_PROCESS
+      if (!(IsNuwaReady() && IsNuwaProcess())) {
+#endif
+          if (!SendSetOffline(!strcmp(offline, "true") ? true : false)) {
+              return NS_ERROR_NOT_AVAILABLE;
+          }
+#ifdef MOZ_NUWA_PROCESS
+      }
+#endif
     }
     // listening for alert notifications
     else if (!strcmp(aTopic, "alertfinished") ||
              !strcmp(aTopic, "alertclickcallback") ||
              !strcmp(aTopic, "alertshow") ) {
         if (!SendNotifyAlertsObserver(nsDependentCString(aTopic),
                                       nsDependentString(aData)))
             return NS_ERROR_NOT_AVAILABLE;
@@ -2595,17 +2665,34 @@ ContentParent::Observe(nsISupports* aSub
     else if (!strcmp(aTopic, "last-pb-context-exited")) {
         unused << SendLastPrivateDocShellDestroyed();
     }
     else if (!strcmp(aTopic, "file-watcher-update")) {
         nsCString creason;
         CopyUTF16toUTF8(aData, creason);
         DeviceStorageFile* file = static_cast<DeviceStorageFile*>(aSubject);
 
-        unused << SendFilePathUpdate(file->mStorageType, file->mStorageName, file->mPath, creason);
+#ifdef MOZ_NUWA_PROCESS
+        if (!(IsNuwaReady() && IsNuwaProcess())) {
+#endif
+
+            unused << SendFilePathUpdate(file->mStorageType, file->mStorageName, file->mPath, creason);
+
+#ifdef MOZ_NUWA_PROCESS
+        } else {
+            if (!mReinitializeData) {
+                mReinitializeData = new NuwaReinitializeData();
+            }
+            mReinitializeData->mReceivedFilePathUpdate = true;
+            mReinitializeData->mFilePathUpdateStoageType = file->mStorageType;
+            mReinitializeData->mFilePathUpdateStorageName = file->mStorageName;
+            mReinitializeData->mFilePathUpdatePath = file->mPath;
+            mReinitializeData->mFilePathUpdateReason = creason;
+        }
+#endif
     }
 #ifdef MOZ_WIDGET_GONK
     else if(!strcmp(aTopic, NS_VOLUME_STATE_CHANGED)) {
         nsCOMPtr<nsIVolume> vol = do_QueryInterface(aSubject);
         if (!vol) {
             return NS_ERROR_NOT_AVAILABLE;
         }
 
@@ -2622,19 +2709,40 @@ ContentParent::Observe(nsISupports* aSub
         vol->GetMountPoint(mountPoint);
         vol->GetState(&state);
         vol->GetMountGeneration(&mountGeneration);
         vol->GetIsMediaPresent(&isMediaPresent);
         vol->GetIsSharing(&isSharing);
         vol->GetIsFormatting(&isFormatting);
         vol->GetIsFake(&isFake);
 
-        unused << SendFileSystemUpdate(volName, mountPoint, state,
-                                       mountGeneration, isMediaPresent,
-                                       isSharing, isFormatting, isFake);
+#ifdef MOZ_NUWA_PROCESS
+        if (!(IsNuwaReady() && IsNuwaProcess())) {
+#endif
+
+            unused << SendFileSystemUpdate(volName, mountPoint, state,
+                                           mountGeneration, isMediaPresent,
+                                           isSharing, isFormatting, isFake);
+
+#ifdef MOZ_NUWA_PROCESS
+        } else {
+            if (!mReinitializeData) {
+                mReinitializeData = new NuwaReinitializeData();
+            }
+            mReinitializeData->mReceivedFileSystemUpdate = true;
+            mReinitializeData->mFileSystemUpdateFsName = volName;
+            mReinitializeData->mFileSystemUpdateMountPount = mountPoint;
+            mReinitializeData->mFileSystemUpdateState = state;
+            mReinitializeData->mFileSystemUpdateMountPount = mountGeneration;
+            mReinitializeData->mFileSystemUpdateIsMediaPresent = isMediaPresent;
+            mReinitializeData->mFileSystemUpdateIsSharing = isSharing;
+            mReinitializeData->mFileSystemUpdateIsFormatting = isFormatting;
+            mReinitializeData->mFileSystemUpdateIsFake = isFake;
+        }
+#endif
     } else if (!strcmp(aTopic, "phone-state-changed")) {
         nsString state(aData);
         unused << SendNotifyPhoneStateChange(state);
     }
 #endif
 #ifdef ACCESSIBILITY
     // Make sure accessibility is running in content process when accessibility
     // gets initiated in chrome process.
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -73,16 +73,21 @@ class ContentParent : public PContentPar
 {
     typedef mozilla::ipc::GeckoChildProcessHost GeckoChildProcessHost;
     typedef mozilla::ipc::OptionalURIParams OptionalURIParams;
     typedef mozilla::ipc::TestShellParent TestShellParent;
     typedef mozilla::ipc::URIParams URIParams;
     typedef mozilla::dom::ClonedMessageData ClonedMessageData;
 
 public:
+#ifdef MOZ_NUWA_PROCESS
+    static bool IsNuwaReady() {
+        return sNuwaReady;
+    }
+#endif
     virtual bool IsContentParent() MOZ_OVERRIDE { return true; }
     /**
      * Start up the content-process machinery.  This might include
      * scheduling pre-launch tasks.
      */
     static void StartUp();
     /** Shut down the content-process machinery. */
     static void ShutDown();
@@ -696,16 +701,22 @@ private:
 
     nsDataHashtable<nsUint64HashKey, nsRefPtr<ParentIdleListener> > mIdleListeners;
 
 #ifdef MOZ_X11
     // Dup of child's X socket, used to scope its resources to this
     // object instead of the child process's lifetime.
     ScopedClose mChildXSocketFdDup;
 #endif
+
+#ifdef MOZ_NUWA_PROCESS
+    static bool sNuwaReady;
+    struct NuwaReinitializeData;
+    nsAutoPtr<NuwaReinitializeData> mReinitializeData;
+#endif
 };
 
 } // namespace dom
 } // namespace mozilla
 
 class ParentIdleListener : public nsIObserver {
 public:
   NS_DECL_ISUPPORTS