Back out 01fe5d23d233 (Bug 1063877) due to broken emulator mochitests
authorDave Hylands <dhylands@mozilla.com>
Mon, 15 Sep 2014 14:08:35 -0700
changeset 228697 ee4e51c71b03391073b396a53261e69a0db8849d
parent 228696 1e0f892f3046057461b0b02b2ade18159ab673e0
child 228698 224e8fb07a62d588a754a10841a82b72a34290b4
push id4187
push userbhearsum@mozilla.com
push dateFri, 28 Nov 2014 15:29:12 +0000
treeherdermozilla-beta@f23cc6a30c11 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1063877
milestone35.0a1
backs out01fe5d23d233f3215998d188e089d1f30a52294c
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
Back out 01fe5d23d233 (Bug 1063877) due to broken emulator mochitests
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/PContent.ipdl
dom/system/gonk/nsIVolumeService.idl
dom/system/gonk/nsVolumeMountLock.cpp
dom/system/gonk/nsVolumeMountLock.h
dom/system/gonk/nsVolumeService.cpp
dom/system/gonk/nsVolumeService.h
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -141,17 +141,16 @@
 #endif
 
 #ifdef MOZ_WIDGET_ANDROID
 # include "AndroidBridge.h"
 #endif
 
 #ifdef MOZ_WIDGET_GONK
 #include "nsIVolume.h"
-#include "nsVolumeService.h"
 #include "nsIVolumeService.h"
 #include "SpeakerManagerService.h"
 using namespace mozilla::system;
 #endif
 
 #ifdef MOZ_B2G_BT
 #include "BluetoothParent.h"
 #include "BluetoothService.h"
@@ -2438,24 +2437,27 @@ ContentParent::RecvDataStoreGetStores(
     return false;
   }
 
   mSendDataStoreInfos = true;
   return true;
 }
 
 bool
-ContentParent::RecvGetVolumes(InfallibleTArray<VolumeInfo>* aResult)
+ContentParent::RecvBroadcastVolume(const nsString& aVolumeName)
 {
 #ifdef MOZ_WIDGET_GONK
-    nsRefPtr<nsVolumeService> vs = nsVolumeService::GetSingleton();
-    vs->GetVolumesForIPC(aResult);
+    nsresult rv;
+    nsCOMPtr<nsIVolumeService> vs = do_GetService(NS_VOLUMESERVICE_CONTRACTID, &rv);
+    if (vs) {
+        vs->BroadcastVolume(aVolumeName);
+    }
     return true;
 #else
-    NS_WARNING("ContentParent::RecvGetVolumes shouldn't be called when MOZ_WIDGET_GONK is not defined");
+    NS_WARNING("ContentParent::RecvBroadcastVolume shouldn't be called when MOZ_WIDGET_GONK is not defined");
     return false;
 #endif
 }
 
 bool
 ContentParent::RecvNuwaReady()
 {
 #ifdef MOZ_NUWA_PROCESS
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -591,17 +591,17 @@ private:
                                                 const bool& aElementHidden,
                                                 const bool& aWithVideo) MOZ_OVERRIDE;
 
     virtual bool RecvAudioChannelChangedNotification() MOZ_OVERRIDE;
 
     virtual bool RecvAudioChannelChangeDefVolChannel(const int32_t& aChannel,
                                                      const bool& aHidden) MOZ_OVERRIDE;
     virtual bool RecvGetSystemMemory(const uint64_t& getterId) MOZ_OVERRIDE;
-    virtual bool RecvGetVolumes(InfallibleTArray<VolumeInfo>* aResult) MOZ_OVERRIDE;
+    virtual bool RecvBroadcastVolume(const nsString& aVolumeName) MOZ_OVERRIDE;
 
     virtual bool RecvDataStoreGetStores(
                        const nsString& aName,
                        const nsString& aOwner,
                        const IPC::Principal& aPrincipal,
                        InfallibleTArray<DataStoreSetting>* aValue) MOZ_OVERRIDE;
 
     virtual bool RecvSpeakerManagerGetSpeakerStatus(bool* aValue) MOZ_OVERRIDE;
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -287,29 +287,16 @@ struct PrefSetting {
 struct DataStoreSetting {
   nsString name;
   nsString originURL;
   nsString manifestURL;
   bool readOnly;
   bool enabled;
 };
 
-// Note: Any changes to this structure should also be changed in
-// FileSystemUpdate below.
-struct VolumeInfo {
-  nsString name;
-  nsString mountPoint;
-  int32_t volState;
-  int32_t mountGeneration;
-  bool isMediaPresent;
-  bool isSharing;
-  bool isFormatting;
-  bool isFake;
-};
-
 intr protocol PContent
 {
     parent opens PCompositor;
     parent opens PSharedBufferManager;
     parent opens PImageBridge;
     child opens PBackground;
 
     manages PAsmJSCacheEntry;
@@ -436,18 +423,16 @@ child:
     AppInfo(nsCString version, nsCString buildID, nsCString name, nsCString UAName);
 
     // Notify child that last-pb-context-exited notification was observed
     LastPrivateDocShellDestroyed();
 
     FilePathUpdate(nsString storageType, nsString storageName, nsString filepath,
                    nsCString reasons);
 
-    // Note: Any changes to this structure should also be changed in
-    // VolumeInfo above.
     FileSystemUpdate(nsString fsName, nsString mountPoint, int32_t fsState,
                      int32_t mountGeneration, bool isMediaPresent,
                      bool isSharing, bool isFormatting, bool isFake);
 
     // Ask the Nuwa process to create a new child process.
     NuwaFork();
 
     NotifyProcessPriorityChanged(ProcessPriority priority);
@@ -630,18 +615,18 @@ parent:
 
     sync DataStoreGetStores(nsString aName, nsString aOwner, Principal aPrincipal)
         returns (DataStoreSetting[] dataStores);
 
     async FilePathUpdateNotify(nsString aType,
                                nsString aStorageName,
                                nsString aFilepath,
                                nsCString aReason);
-
-    sync GetVolumes() returns (VolumeInfo[] volumes);
+    // get nsIVolumeService to broadcast volume information
+    async BroadcastVolume(nsString volumeName);
 
     // Notify the parent that the child has finished handling a system message.
     async SystemMessageHandled();
 
     NuwaReady();
 
     sync AddNewProcess(uint32_t pid, ProtocolFdMapping[] aFds);
 
--- a/dom/system/gonk/nsIVolumeService.idl
+++ b/dom/system/gonk/nsIVolumeService.idl
@@ -3,23 +3,25 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 #include "nsIVolume.idl"
 #include "nsIVolumeMountLock.idl"
 
 interface nsIArray;
 
-[scriptable, uuid(c31b182c-61a3-449c-bba8-fd45044499c2)]
+[scriptable, uuid(cab99ab4-542e-4387-bd40-db6ef30e4f5f)]
 interface nsIVolumeService : nsISupports
 {
     nsIVolume getVolumeByName(in DOMString volName);
     nsIVolume getVolumeByPath(in DOMString path);
     nsIVolume createOrGetVolumeByPath(in DOMString path);
 
+    void BroadcastVolume(in DOMString volName);
+
     nsIVolumeMountLock createMountLock(in DOMString volName);
 
     nsIArray getVolumeNames();
 
     /* for test case only to simulate sdcard insertion/removal */
     void createFakeVolume(in DOMString name, in DOMString path);
     void SetFakeVolumeState(in DOMString name, in long state);
 };
--- a/dom/system/gonk/nsVolumeMountLock.cpp
+++ b/dom/system/gonk/nsVolumeMountLock.cpp
@@ -60,29 +60,28 @@ nsresult nsVolumeMountLock::Init()
       NS_LossyConvertUTF16toASCII(mVolumeName).get());
 
   // Add ourselves as an Observer. It's important that we use a weak
   // reference here. If we used a strong reference, then that reference
   // would prevent this object from being destructed.
   nsCOMPtr<nsIObserverService> obs = GetObserverService();
   obs->AddObserver(this, NS_VOLUME_STATE_CHANGED, true /*weak*/);
 
-  // Get the initial mountGeneration and grab a lock.
+  // Request the sdcard info, so we know the state/generation without having
+  // to wait for a state change.
+  if (XRE_GetProcessType() == GeckoProcessType_Content) {
+    ContentChild::GetSingleton()->SendBroadcastVolume(mVolumeName);
+    return NS_OK;
+  }
   nsCOMPtr<nsIVolumeService> vs = do_GetService(NS_VOLUMESERVICE_CONTRACTID);
   NS_ENSURE_TRUE(vs, NS_ERROR_FAILURE);
 
-  nsCOMPtr<nsIVolume> vol;
-  nsresult rv = vs->GetVolumeByName(mVolumeName, getter_AddRefs(vol));
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-  rv = vol->GetMountGeneration(&mVolumeGeneration);
-  NS_ENSURE_SUCCESS(rv, rv);
+  vs->BroadcastVolume(mVolumeName);
 
-  return Lock(vol);
+  return NS_OK;
 }
 
 /* void unlock (); */
 NS_IMETHODIMP nsVolumeMountLock::Unlock()
 {
   LOG("nsVolumeMountLock released for '%s'",
       NS_LossyConvertUTF16toASCII(mVolumeName).get());
 
@@ -138,28 +137,22 @@ NS_IMETHODIMP nsVolumeMountLock::Observe
 
   // The generation changed, which means that any wakelock we may have
   // been holding is now invalid. Grab a new wakelock for the new generation
   // number.
 
   mWakeLock = nullptr;
   mVolumeGeneration = mountGeneration;
 
-  return Lock(vol);
-}
-
-nsresult
-nsVolumeMountLock::Lock(nsIVolume* aVolume)
-{
   nsRefPtr<power::PowerManagerService> pmService =
     power::PowerManagerService::GetInstance();
   NS_ENSURE_TRUE(pmService, NS_ERROR_FAILURE);
 
   nsString mountLockName;
-  aVolume->GetMountLockName(mountLockName);
+  vol->GetMountLockName(mountLockName);
 
   ErrorResult err;
   mWakeLock = pmService->NewWakeLock(mountLockName, nullptr, err);
   if (err.Failed()) {
     return err.ErrorCode();
   }
 
   LOG("nsVolumeMountLock acquired for '%s' gen %d",
--- a/dom/system/gonk/nsVolumeMountLock.h
+++ b/dom/system/gonk/nsVolumeMountLock.h
@@ -9,18 +9,16 @@
 
 #include "mozilla/dom/WakeLock.h"
 #include "nsIObserver.h"
 #include "nsString.h"
 #include "nsTArray.h"
 #include "nsAutoPtr.h"
 #include "nsWeakReference.h"
 
-class nsIVolume;
-
 namespace mozilla {
 namespace system {
 
 /* The VolumeMountLock is designed so that it can be used in the Child or
  * Parent process. While the VolumeMountLock object exists, then the
  * VolumeManager/AutoMounter will prevent a mounted volume from being
  * shared with the PC.
  */
@@ -38,17 +36,16 @@ public:
 
   const nsString& VolumeName() const  { return mVolumeName; }
 
 private:
   nsVolumeMountLock(const nsAString& aVolumeName);
   ~nsVolumeMountLock();
 
   nsresult Init();
-  nsresult Lock(nsIVolume* aVolume);
 
   nsRefPtr<dom::WakeLock>  mWakeLock;
   nsString                 mVolumeName;
   int32_t                  mVolumeGeneration;
   bool                     mUnlocked;
 };
 
 } // namespace system
--- a/dom/system/gonk/nsVolumeService.cpp
+++ b/dom/system/gonk/nsVolumeService.cpp
@@ -81,21 +81,26 @@ nsVolumeService::Shutdown()
   XRE_GetIOMessageLoop()->PostTask(
       FROM_HERE,
       NewRunnableFunction(ShutdownVolumeServiceIOThread));
 
   sSingleton = nullptr;
 }
 
 nsVolumeService::nsVolumeService()
-  : mArrayMonitor("nsVolumeServiceArray"),
-    mGotVolumesFromParent(false)
+  : mArrayMonitor("nsVolumeServiceArray")
 {
   sSingleton = this;
 
+  if (XRE_GetProcessType() != GeckoProcessType_Default) {
+    // Request the initial state for all volumes.
+    ContentChild::GetSingleton()->SendBroadcastVolume(NS_LITERAL_STRING(""));
+    return;
+  }
+
   // Startup the IOThread side of things. The actual volume changes
   // are captured by the IOThread and forwarded to main thread.
   XRE_GetIOMessageLoop()->PostTask(
       FROM_HERE,
       NewRunnableFunction(InitVolumeServiceIOThread, this));
 
   nsCOMPtr<nsIPowerManagerService> pmService =
     do_GetService(POWERMANAGERSERVICE_CONTRACTID);
@@ -112,36 +117,83 @@ nsVolumeService::~nsVolumeService()
 // Callback for nsIDOMMozWakeLockListener
 NS_IMETHODIMP
 nsVolumeService::Callback(const nsAString& aTopic, const nsAString& aState)
 {
   CheckMountLock(aTopic, aState);
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsVolumeService::BroadcastVolume(const nsAString& aVolName)
+{
+  MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
+
+  if (aVolName.EqualsLiteral("")) {
+    nsVolume::Array volumeArray;
+    {
+      // Copy the array since we don't want to call BroadcastVolume
+      // while we're holding the lock.
+      MonitorAutoLock autoLock(mArrayMonitor);
+      volumeArray = mVolumeArray;
+    }
+
+    // We treat being passed the empty string as "broadcast all volumes"
+    nsVolume::Array::size_type numVolumes = volumeArray.Length();
+    nsVolume::Array::index_type volIndex;
+    for (volIndex = 0; volIndex < numVolumes; volIndex++) {
+      const nsString& volName(volumeArray[volIndex]->Name());
+      if (!volName.EqualsLiteral("")) {
+        // Note: The volume service is the only entity that should be able to
+        // modify the array of volumes. So we shouldn't have any issues with
+        // the array being modified under our feet (Since we're the volume
+        // service the array can't change until after we finish iterating the
+        // the loop).
+        nsresult rv = BroadcastVolume(volName);
+        NS_ENSURE_SUCCESS(rv, rv);
+      }
+    }
+    return NS_OK;
+  }
+  nsRefPtr<nsVolume> vol;
+  {
+    MonitorAutoLock autoLock(mArrayMonitor);
+    vol = FindVolumeByName(aVolName);
+  }
+  if (!vol) {
+    ERR("BroadcastVolume: Unable to locate volume '%s'",
+        NS_LossyConvertUTF16toASCII(aVolName).get());
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
+  nsCOMPtr<nsIObserverService> obs = GetObserverService();
+  NS_ENSURE_TRUE(obs, NS_NOINTERFACE);
+
+  DBG("nsVolumeService::BroadcastVolume for '%s'", vol->NameStr().get());
+  NS_ConvertUTF8toUTF16 stateStr(vol->StateStr());
+  obs->NotifyObservers(vol, NS_VOLUME_STATE_CHANGED, stateStr.get());
+  return NS_OK;
+}
+
 NS_IMETHODIMP nsVolumeService::GetVolumeByName(const nsAString& aVolName, nsIVolume **aResult)
 {
-  GetVolumesFromParent();
-
   MonitorAutoLock autoLock(mArrayMonitor);
 
   nsRefPtr<nsVolume> vol = FindVolumeByName(aVolName);
   if (!vol) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   vol.forget(aResult);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsVolumeService::GetVolumeByPath(const nsAString& aPath, nsIVolume **aResult)
 {
-  GetVolumesFromParent();
-
   NS_ConvertUTF16toUTF8 utf8Path(aPath);
   char realPathBuf[PATH_MAX];
 
   while (realpath(utf8Path.get(), realPathBuf) < 0) {
     if (errno != ENOENT) {
       ERR("GetVolumeByPath: realpath on '%s' failed: %d", utf8Path.get(), errno);
       return NSRESULT_FOR_ERRNO();
     }
@@ -182,18 +234,16 @@ nsVolumeService::GetVolumeByPath(const n
     }
   }
   return NS_ERROR_FILE_NOT_FOUND;
 }
 
 NS_IMETHODIMP
 nsVolumeService::CreateOrGetVolumeByPath(const nsAString& aPath, nsIVolume** aResult)
 {
-  GetVolumesFromParent();
-
   nsresult rv = GetVolumeByPath(aPath, aResult);
   if (rv == NS_OK) {
     return NS_OK;
   }
 
   // In order to support queries by the updater, we will fabricate a volume
   // from the pathname, so that the caller can determine the volume size.
   nsCOMPtr<nsIVolume> vol = new nsVolume(NS_LITERAL_STRING("fake"),
@@ -205,18 +255,16 @@ nsVolumeService::CreateOrGetVolumeByPath
                                          true  /* isFake */);
   vol.forget(aResult);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsVolumeService::GetVolumeNames(nsIArray** aVolNames)
 {
-  GetVolumesFromParent();
-
   NS_ENSURE_ARG_POINTER(aVolNames);
   MonitorAutoLock autoLock(mArrayMonitor);
 
   *aVolNames = nullptr;
 
   nsresult rv;
   nsCOMPtr<nsIMutableArray> volNames =
     do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
@@ -236,70 +284,16 @@ nsVolumeService::GetVolumeNames(nsIArray
     rv = volNames->AppendElement(isupportsString, false);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   NS_ADDREF(*aVolNames = volNames);
   return NS_OK;
 }
 
-void
-nsVolumeService::GetVolumesForIPC(nsTArray<VolumeInfo>* aResult)
-{
-  MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
-  MOZ_ASSERT(NS_IsMainThread());
-
-  MonitorAutoLock autoLock(mArrayMonitor);
-
-  nsVolume::Array::size_type numVolumes = mVolumeArray.Length();
-  nsVolume::Array::index_type volIndex;
-  for (volIndex = 0; volIndex < numVolumes; volIndex++) {
-    nsRefPtr<nsVolume> vol = mVolumeArray[volIndex];
-    VolumeInfo* volInfo = aResult->AppendElement();
-
-    volInfo->name()             = vol->mName;
-    volInfo->mountPoint()       = vol->mMountPoint;
-    volInfo->volState()         = vol->mState;
-    volInfo->mountGeneration()  = vol->mMountGeneration;
-    volInfo->isMediaPresent()   = vol->mIsMediaPresent;
-    volInfo->isSharing()        = vol->mIsSharing;
-    volInfo->isFormatting()     = vol->mIsFormatting;
-    volInfo->isFake()           = vol->mIsFake;
-  }
-}
-
-void
-nsVolumeService::GetVolumesFromParent()
-{
-  if (XRE_GetProcessType() == GeckoProcessType_Default) {
-    // We are the parent. Therefore our volumes are already correct.
-    return;
-  }
-  if (mGotVolumesFromParent) {
-    // We've already done this, no need to do it again.
-    return;
-  }
-  mGotVolumesFromParent = true;
-
-  nsTArray<VolumeInfo> result;
-  ContentChild::GetSingleton()->SendGetVolumes(&result);
-  for (uint32_t i = 0; i < result.Length(); i++) {
-    const VolumeInfo& volInfo(result[i]);
-    nsRefPtr<nsVolume> vol = new nsVolume(volInfo.name(),
-                                          volInfo.mountPoint(),
-                                          volInfo.volState(),
-                                          volInfo.mountGeneration(),
-                                          volInfo.isMediaPresent(),
-                                          volInfo.isSharing(),
-                                          volInfo.isFormatting(),
-                                          volInfo.isFake());
-    UpdateVolume(vol, false);
-  }
-}
-
 NS_IMETHODIMP
 nsVolumeService::CreateMountLock(const nsAString& aVolumeName, nsIVolumeMountLock **aResult)
 {
   nsCOMPtr<nsIVolumeMountLock> mountLock = nsVolumeMountLock::Create(aVolumeName);
   if (!mountLock) {
     return NS_ERROR_NOT_AVAILABLE;
   }
   mountLock.forget(aResult);
@@ -367,17 +361,17 @@ nsVolumeService::CreateOrFindVolumeByNam
   // Volume not found - add a new one
   vol = new nsVolume(aName);
   vol->SetIsFake(aIsFake);
   mVolumeArray.AppendElement(vol);
   return vol.forget();
 }
 
 void
-nsVolumeService::UpdateVolume(nsIVolume* aVolume, bool aNotifyObservers)
+nsVolumeService::UpdateVolume(nsIVolume* aVolume)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   nsString volName;
   aVolume->GetName(volName);
   bool aIsFake;
   aVolume->GetIsFake(&aIsFake);
   nsRefPtr<nsVolume> vol = CreateOrFindVolumeByName(volName, aIsFake);
@@ -387,21 +381,16 @@ nsVolumeService::UpdateVolume(nsIVolume*
   }
 
   if (!vol->IsFake() && aIsFake) {
     // Prevent an incoming fake volume from overriding an existing real volume.
     return;
   }
 
   vol->Set(aVolume);
-
-  if (!aNotifyObservers) {
-    return;
-  }
-
   nsCOMPtr<nsIObserverService> obs = GetObserverService();
   if (!obs) {
     return;
   }
   NS_ConvertUTF8toUTF16 stateStr(vol->StateStr());
   obs->NotifyObservers(vol, NS_VOLUME_STATE_CHANGED, stateStr.get());
 }
 
--- a/dom/system/gonk/nsVolumeService.h
+++ b/dom/system/gonk/nsVolumeService.h
@@ -10,21 +10,16 @@
 #include "mozilla/StaticPtr.h"
 #include "nsCOMPtr.h"
 #include "nsIDOMWakeLockListener.h"
 #include "nsIVolume.h"
 #include "nsIVolumeService.h"
 #include "nsVolume.h"
 
 namespace mozilla {
-
-namespace dom {
-class VolumeInfo;
-} // dom
-
 namespace system {
 
 class WakeLockCallback;
 class Volume;
 
 /***************************************************************************
 * The nsVolumeData class encapsulates the data that is updated/maintained
 * on the main thread in order to support the nsIVolume and nsIVolumeService
@@ -40,34 +35,30 @@ public:
   NS_DECL_NSIDOMMOZWAKELOCKLISTENER
 
   nsVolumeService();
 
   static already_AddRefed<nsVolumeService> GetSingleton();
   //static nsVolumeService* GetSingleton();
   static void Shutdown();
 
-  void UpdateVolume(nsIVolume* aVolume, bool aNotifyObservers = true);
+  void UpdateVolume(nsIVolume* aVolume);
   void UpdateVolumeIOThread(const Volume* aVolume);
 
-  void GetVolumesForIPC(nsTArray<dom::VolumeInfo>* aResult);
-
 private:
   ~nsVolumeService();
 
   void CheckMountLock(const nsAString& aMountLockName,
                       const nsAString& aMountLockState);
   already_AddRefed<nsVolume> FindVolumeByMountLockName(const nsAString& aMountLockName);
   already_AddRefed<nsVolume> FindVolumeByName(const nsAString& aName);
   already_AddRefed<nsVolume> CreateOrFindVolumeByName(const nsAString& aName, bool aIsFake = false);
-  void GetVolumesFromParent();
 
   Monitor mArrayMonitor;
   nsVolume::Array mVolumeArray;
 
   static StaticRefPtr<nsVolumeService> sSingleton;
-  bool mGotVolumesFromParent;
 };
 
 } // system
 } // mozilla
 
 #endif  // mozilla_system_nsvolumeservice_h__