Bug 1140597 - Don't try and process device storage notifications if the process isn't using device storage.
☠☠ backed out by 7b56591efd68 ☠ ☠
authorDave Hylands <dhylands@mozilla.com>
Fri, 27 Mar 2015 14:22:20 -0700
changeset 236154 d93c07e6bcd20caeff5c74ca5990d841b4a969d3
parent 236153 09c7fb510916cc1214a2d51afdec9919054234bc
child 236155 3c2915d73a210435d5aa5e3d783dfd36f0937509
push id14789
push userdhylands@mozilla.com
push dateFri, 27 Mar 2015 21:22:46 +0000
treeherderb2g-inbound@d93c07e6bcd2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1140597
milestone39.0a1
Bug 1140597 - Don't try and process device storage notifications if the process isn't using device storage.
dom/devicestorage/DeviceStorage.h
dom/devicestorage/nsDeviceStorage.cpp
dom/ipc/ContentChild.cpp
dom/system/gonk/nsIVolumeService.idl
dom/system/gonk/nsVolume.cpp
dom/system/gonk/nsVolume.h
dom/system/gonk/nsVolumeService.cpp
dom/system/gonk/nsVolumeService.h
--- a/dom/devicestorage/DeviceStorage.h
+++ b/dom/devicestorage/DeviceStorage.h
@@ -191,16 +191,18 @@ public:
 
   virtual void RemoveEventListener(const nsAString& aType,
                                    mozilla::dom::EventListener* aListener,
                                    bool aUseCapture,
                                    ErrorResult& aRv) override;
 
   explicit nsDOMDeviceStorage(nsPIDOMWindow* aWindow);
 
+  static int InstanceCount() { return sInstanceCount; }
+
   nsresult Init(nsPIDOMWindow* aWindow, const nsAString& aType,
                 const nsAString& aVolName);
 
   bool IsAvailable();
   bool IsFullPath(const nsAString& aPath)
   {
     return aPath.Length() > 0 && aPath.CharAt(0) == '/';
   }
@@ -314,16 +316,18 @@ private:
   DeleteInternal(nsPIDOMWindow* aWin, const nsAString& aPath,
                  DOMRequest* aRequest);
 
   already_AddRefed<DOMCursor>
   EnumerateInternal(const nsAString& aName,
                     const EnumerationParameters& aOptions, bool aEditable,
                     ErrorResult& aRv);
 
+  static int sInstanceCount;
+
   nsString mStorageType;
   nsCOMPtr<nsIFile> mRootDirectory;
   nsString mStorageName;
   bool mIsShareable;
   bool mIsRemovable;
 
   already_AddRefed<nsDOMDeviceStorage> GetStorage(const nsAString& aFullPath,
                                                   nsAString& aOutStoragePath);
--- a/dom/devicestorage/nsDeviceStorage.cpp
+++ b/dom/devicestorage/nsDeviceStorage.cpp
@@ -567,16 +567,24 @@ FileUpdateDispatcher::Observe(nsISupport
     ContentChild::GetSingleton()
       ->SendFilePathUpdateNotify(dsf->mStorageType,
                                  dsf->mStorageName,
                                  dsf->mPath,
                                  NS_ConvertUTF16toUTF8(aData));
     return NS_OK;
   }
 
+  if (nsDOMDeviceStorage::InstanceCount() == 0) {
+    // This process doesn't have any nsDOMDeviceStorage instances, so no
+    // need to send out notifications (since there are no nsDOMDeviceStorage
+    // instances, we can't create a DeviceStorageFile object).
+
+    return NS_OK;
+  }
+
   // Multiple storage types may match the same files. So walk through each of
   // the storage types, and if the extension matches, tell them about it.
   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   if (DeviceStorageTypeChecker::IsSharedMediaRoot(dsf->mStorageType)) {
     DeviceStorageTypeChecker* typeChecker
       = DeviceStorageTypeChecker::CreateOrGet();
     MOZ_ASSERT(typeChecker);
 
@@ -3331,23 +3339,27 @@ NS_IMPL_CYCLE_COLLECTION(DeviceStorageRe
 NS_INTERFACE_MAP_BEGIN(nsDOMDeviceStorage)
   NS_INTERFACE_MAP_ENTRY(nsIDOMDeviceStorage)
   NS_INTERFACE_MAP_ENTRY(nsIObserver)
 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
 
 NS_IMPL_ADDREF_INHERITED(nsDOMDeviceStorage, DOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(nsDOMDeviceStorage, DOMEventTargetHelper)
 
+int nsDOMDeviceStorage::sInstanceCount = 0;
+
 nsDOMDeviceStorage::nsDOMDeviceStorage(nsPIDOMWindow* aWindow)
   : DOMEventTargetHelper(aWindow)
   , mIsShareable(false)
   , mIsRemovable(false)
   , mIsWatchingFile(false)
   , mAllowedToWatchFile(false)
 {
+  MOZ_ASSERT(NS_IsMainThread());
+  sInstanceCount++;
 }
 
 /* virtual */ JSObject*
 nsDOMDeviceStorage::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return DeviceStorageBinding::Wrap(aCx, this, aGivenProto);
 }
 
@@ -3421,16 +3433,18 @@ nsDOMDeviceStorage::Init(nsPIDOMWindow* 
     }
   }
 
   return NS_OK;
 }
 
 nsDOMDeviceStorage::~nsDOMDeviceStorage()
 {
+  MOZ_ASSERT(NS_IsMainThread());
+  sInstanceCount--;
 }
 
 void
 nsDOMDeviceStorage::Shutdown()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (mFileSystem) {
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -2285,16 +2285,23 @@ ContentChild::RecvVolumes(nsTArray<Volum
 }
 
 bool
 ContentChild::RecvFilePathUpdate(const nsString& aStorageType,
                                  const nsString& aStorageName,
                                  const nsString& aPath,
                                  const nsCString& aReason)
 {
+    if (nsDOMDeviceStorage::InstanceCount() == 0) {
+        // No device storage instances in this process. Don't try and
+        // and create a DeviceStorageFile since it will fail.
+
+        return true;
+    }
+
     nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(aStorageType, aStorageName, aPath);
 
     nsString reason;
     CopyASCIItoUTF16(aReason, reason);
     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
     obs->NotifyObservers(dsf, "file-watcher-update", reason.get());
     return true;
 }
--- a/dom/system/gonk/nsIVolumeService.idl
+++ b/dom/system/gonk/nsIVolumeService.idl
@@ -3,27 +3,29 @@
  * 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(879874c6-5532-437a-bf76-703d0c2e7e77)]
 interface nsIVolumeService : nsISupports
 {
     nsIVolume getVolumeByName(in DOMString volName);
     nsIVolume getVolumeByPath(in DOMString path);
     nsIVolume createOrGetVolumeByPath(in DOMString path);
 
     nsIVolumeMountLock createMountLock(in DOMString volName);
 
     nsIArray getVolumeNames();
 
+    void Dump(in DOMString label);
+
     /* 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);
 };
 
 %{C++
 #define NS_VOLUMESERVICE_CID \
   {0x7c179fb7, 0x67a0, 0x43a3, {0x93, 0x37, 0x29, 0x4e, 0x03, 0x60, 0xb8, 0x58}}
--- a/dom/system/gonk/nsVolume.cpp
+++ b/dom/system/gonk/nsVolume.cpp
@@ -61,16 +61,33 @@ nsVolume::nsVolume(const Volume* aVolume
     mIsSharing(aVolume->IsSharing()),
     mIsFormatting(aVolume->IsFormatting()),
     mIsUnmounting(aVolume->IsUnmounting()),
     mIsRemovable(aVolume->IsRemovable()),
     mIsHotSwappable(aVolume->IsHotSwappable())
 {
 }
 
+void nsVolume::Dump(const char* aLabel) const
+{
+  LOG("%s: Volume: %s is %s and %s @ %s gen %d locked %d",
+      aLabel,
+      NameStr().get(),
+      StateStr(),
+      IsMediaPresent() ? "inserted" : "missing",
+      MountPointStr().get(),
+      MountGeneration(),
+      (int)IsMountLocked());
+  LOG("%s:   IsSharing %s IsFormating %s IsUnmounting %s",
+      aLabel,
+      (IsSharing() ? "y" : "n"),
+      (IsFormatting() ? "y" : "n"),
+      (IsUnmounting() ? "y" : "n"));
+}
+
 bool nsVolume::Equals(nsIVolume* aVolume)
 {
   nsString volName;
   aVolume->GetName(volName);
   if (!mName.Equals(volName)) {
     return false;
   }
 
--- a/dom/system/gonk/nsVolume.h
+++ b/dom/system/gonk/nsVolume.h
@@ -68,16 +68,18 @@ public:
   bool Equals(nsIVolume* aVolume);
   void Set(nsIVolume* aVolume);
 
   void LogState() const;
 
   const nsString& Name() const        { return mName; }
   nsCString NameStr() const           { return NS_LossyConvertUTF16toASCII(mName); }
 
+  void Dump(const char* aLabel) const;
+
   int32_t MountGeneration() const     { return mMountGeneration; }
   bool IsMountLocked() const          { return mMountLocked; }
 
   const nsString& MountPoint() const  { return mMountPoint; }
   nsCString MountPointStr() const     { return NS_LossyConvertUTF16toASCII(mMountPoint); }
 
   int32_t State() const               { return mState; }
   const char* StateStr() const        { return NS_VolumeStateStr(mState); }
--- a/dom/system/gonk/nsVolumeService.cpp
+++ b/dom/system/gonk/nsVolumeService.cpp
@@ -119,16 +119,41 @@ nsVolumeService::~nsVolumeService()
 // Callback for nsIDOMMozWakeLockListener
 NS_IMETHODIMP
 nsVolumeService::Callback(const nsAString& aTopic, const nsAString& aState)
 {
   CheckMountLock(aTopic, aState);
   return NS_OK;
 }
 
+void nsVolumeService::DumpNoLock(const char* aLabel)
+{
+  mArrayMonitor.AssertCurrentThreadOwns();
+
+  nsVolume::Array::size_type numVolumes = mVolumeArray.Length();
+
+  if (numVolumes == 0) {
+    LOG("%s: No Volumes!", aLabel);
+    return;
+  }
+  nsVolume::Array::index_type volIndex;
+  for (volIndex = 0; volIndex < numVolumes; volIndex++) {
+    nsRefPtr<nsVolume> vol = mVolumeArray[volIndex];
+    vol->Dump(aLabel);
+  }
+}
+
+NS_IMETHODIMP
+nsVolumeService::Dump(const nsAString& aLabel)
+{
+  MonitorAutoLock autoLock(mArrayMonitor);
+  DumpNoLock(NS_LossyConvertUTF16toASCII(aLabel).get());
+  return NS_OK;
+}
+
 NS_IMETHODIMP nsVolumeService::GetVolumeByName(const nsAString& aVolName, nsIVolume **aResult)
 {
   MonitorAutoLock autoLock(mArrayMonitor);
 
   nsRefPtr<nsVolume> vol = FindVolumeByName(aVolName);
   if (!vol) {
     return NS_ERROR_NOT_AVAILABLE;
   }
@@ -277,16 +302,17 @@ nsVolumeService::RecvVolumesFromParent(c
   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;
   }
+
   for (uint32_t i = 0; i < aVolumes.Length(); i++) {
     const VolumeInfo& volInfo(aVolumes[i]);
     nsRefPtr<nsVolume> vol = new nsVolume(volInfo.name(),
                                           volInfo.mountPoint(),
                                           volInfo.volState(),
                                           volInfo.mountGeneration(),
                                           volInfo.isMediaPresent(),
                                           volInfo.isSharing(),
--- a/dom/system/gonk/nsVolumeService.h
+++ b/dom/system/gonk/nsVolumeService.h
@@ -40,16 +40,18 @@ public:
   NS_DECL_NSIDOMMOZWAKELOCKLISTENER
 
   nsVolumeService();
 
   static already_AddRefed<nsVolumeService> GetSingleton();
   //static nsVolumeService* GetSingleton();
   static void Shutdown();
 
+  void DumpNoLock(const char* aLabel);
+
   void UpdateVolume(nsIVolume* aVolume, bool aNotifyObservers = true);
   void UpdateVolumeIOThread(const Volume* aVolume);
 
   void RecvVolumesFromParent(const nsTArray<dom::VolumeInfo>& aVolumes);
   void GetVolumesForIPC(nsTArray<dom::VolumeInfo>* aResult);
 
 private:
   ~nsVolumeService();