diff --git a/dom/system/gonk/nsVolume.cpp b/dom/system/gonk/nsVolume.cpp index 138e2236c8c..efb28facd6a 100644 --- a/dom/system/gonk/nsVolume.cpp +++ b/dom/system/gonk/nsVolume.cpp @@ -66,6 +66,22 @@ nsVolume::nsVolume(const Volume* aVolume) { } +nsVolume::nsVolume(const nsVolume* aVolume) + : mName(aVolume->mName), + mMountPoint(aVolume->mMountPoint), + mState(aVolume->mState), + mMountGeneration(aVolume->mMountGeneration), + mMountLocked(aVolume->mMountLocked), + mIsFake(aVolume->mIsFake), + mIsMediaPresent(aVolume->mIsMediaPresent), + mIsSharing(aVolume->mIsSharing), + mIsFormatting(aVolume->mIsFormatting), + mIsUnmounting(aVolume->mIsUnmounting), + mIsRemovable(aVolume->mIsRemovable), + mIsHotSwappable(aVolume->mIsHotSwappable) +{ +} + void nsVolume::Dump(const char* aLabel) const { LOG("%s: Volume: %s is %s and %s @ %s gen %d locked %d", @@ -333,40 +349,28 @@ nsVolume::LogState() const LOG("nsVolume: %s state %s", NameStr().get(), StateStr()); } -void nsVolume::Set(nsIVolume* aVolume) +void nsVolume::UpdateMountLock(nsVolume* aOldVolume) { MOZ_ASSERT(NS_IsMainThread()); - aVolume->GetName(mName); - aVolume->GetMountPoint(mMountPoint); - aVolume->GetState(&mState); - aVolume->GetIsFake(&mIsFake); - aVolume->GetIsMediaPresent(&mIsMediaPresent); - aVolume->GetIsSharing(&mIsSharing); - aVolume->GetIsFormatting(&mIsFormatting); - aVolume->GetIsUnmounting(&mIsUnmounting); - aVolume->GetIsRemovable(&mIsRemovable); - aVolume->GetIsHotSwappable(&mIsHotSwappable); - - int32_t volMountGeneration; - aVolume->GetMountGeneration(&volMountGeneration); - + bool oldMountLocked = aOldVolume ? aOldVolume->mMountLocked : false; if (mState != nsIVolume::STATE_MOUNTED) { // Since we're not in the mounted state, we need to // forgot whatever mount generation we may have had. mMountGeneration = -1; - return; - } - if (mMountGeneration == volMountGeneration) { - // No change in mount generation, nothing else to do + mMountLocked = oldMountLocked; return; } - mMountGeneration = volMountGeneration; + int32_t oldMountGeneration = aOldVolume ? aOldVolume->mMountGeneration : -1; + if (mMountGeneration == oldMountGeneration) { + // No change in mount generation, nothing else to do + mMountLocked = oldMountLocked; + return; + } if (!XRE_IsParentProcess()) { // Child processes just track the state, not maintain it. - aVolume->GetIsMountLocked(&mMountLocked); return; } diff --git a/dom/system/gonk/nsVolume.h b/dom/system/gonk/nsVolume.h index f1fb87bea14..d65f1e0071b 100644 --- a/dom/system/gonk/nsVolume.h +++ b/dom/system/gonk/nsVolume.h @@ -24,6 +24,9 @@ public: // This constructor is used by the UpdateVolumeRunnable constructor nsVolume(const Volume* aVolume); + // This constructor is used by nsVolumeService::SetFakeVolumeState + nsVolume(const nsVolume* aVolume); + // This constructor is used by ContentChild::RecvFileSystemUpdate which is // used to update the volume cache maintained in the child process. nsVolume(const nsAString& aName, const nsAString& aMountPoint, @@ -47,25 +50,8 @@ public: { } - // This constructor is used by nsVolumeService::FindAddVolumeByName, and - // will be followed shortly by a Set call. - nsVolume(const nsAString& aName) - : mName(aName), - mState(STATE_INIT), - mMountGeneration(-1), - mMountLocked(true), // Needs to agree with Volume::Volume - mIsFake(false), - mIsMediaPresent(false), - mIsSharing(false), - mIsFormatting(false), - mIsUnmounting(false), - mIsRemovable(false), - mIsHotSwappable(false) - { - } - bool Equals(nsIVolume* aVolume); - void Set(nsIVolume* aVolume); + void UpdateMountLock(nsVolume* aOldVolume); void LogState() const; diff --git a/dom/system/gonk/nsVolumeService.cpp b/dom/system/gonk/nsVolumeService.cpp index 033a97d1756..281046444b2 100644 --- a/dom/system/gonk/nsVolumeService.cpp +++ b/dom/system/gonk/nsVolumeService.cpp @@ -368,7 +368,7 @@ nsVolumeService::FindVolumeByMountLockName(const nsAString& aMountLockName) } already_AddRefed -nsVolumeService::FindVolumeByName(const nsAString& aName) +nsVolumeService::FindVolumeByName(const nsAString& aName, nsVolume::Array::index_type* aIndex) { mArrayMonitor.AssertCurrentThreadOwns(); @@ -377,52 +377,35 @@ nsVolumeService::FindVolumeByName(const nsAString& aName) for (volIndex = 0; volIndex < numVolumes; volIndex++) { nsRefPtr vol = mVolumeArray[volIndex]; if (vol->Name().Equals(aName)) { + if (aIndex) { + *aIndex = volIndex; + } return vol.forget(); } } return nullptr; } -//static -already_AddRefed -nsVolumeService::CreateOrFindVolumeByName(const nsAString& aName, bool aIsFake /*= false*/) -{ - MonitorAutoLock autoLock(mArrayMonitor); - - nsRefPtr vol; - vol = FindVolumeByName(aName); - if (vol) { - return vol.forget(); - } - // 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(nsVolume* aVolume, bool aNotifyObservers) { MOZ_ASSERT(NS_IsMainThread()); - nsString volName; - aVolume->GetName(volName); - bool aIsFake; - aVolume->GetIsFake(&aIsFake); - nsRefPtr vol = CreateOrFindVolumeByName(volName, aIsFake); - if (vol->Equals(aVolume)) { - // Nothing has really changed. Don't bother telling anybody. - return; + { + MonitorAutoLock autoLock(mArrayMonitor); + nsVolume::Array::index_type volIndex; + nsRefPtr vol = FindVolumeByName(aVolume->Name(), &volIndex); + if (!vol) { + mVolumeArray.AppendElement(aVolume); + } else if (vol->Equals(aVolume) || (!vol->IsFake() && aVolume->IsFake())) { + // Ignore if nothing changed or if a fake tries to override a real volume. + return; + } else { + mVolumeArray.ReplaceElementAt(volIndex, aVolume); + } + aVolume->UpdateMountLock(vol); } - if (!vol->IsFake() && aIsFake) { - // Prevent an incoming fake volume from overriding an existing real volume. - return; - } - - vol->Set(aVolume); - if (!aNotifyObservers) { return; } @@ -431,8 +414,8 @@ nsVolumeService::UpdateVolume(nsIVolume* aVolume, bool aNotifyObservers) if (!obs) { return; } - NS_ConvertUTF8toUTF16 stateStr(vol->StateStr()); - obs->NotifyObservers(vol, NS_VOLUME_STATE_CHANGED, stateStr.get()); + NS_ConvertUTF8toUTF16 stateStr(aVolume->StateStr()); + obs->NotifyObservers(aVolume, NS_VOLUME_STATE_CHANGED, stateStr.get()); } NS_IMETHODIMP @@ -471,11 +454,8 @@ nsVolumeService::SetFakeVolumeState(const nsAString& name, int32_t state) return NS_ERROR_NOT_AVAILABLE; } - // UpdateVolume expects the volume passed in to NOT be the - // same pointer as what CreateOrFindVolumeByName would return, - // which is why we allocate a temporary volume here. - nsRefPtr volume = new nsVolume(name); - volume->Set(vol); + // Clone the existing volume so we can replace it + nsRefPtr volume = new nsVolume(vol); volume->SetState(state); volume->LogState(); UpdateVolume(volume.get()); @@ -502,15 +482,15 @@ nsVolumeService::RemoveFakeVolume(const nsAString& name) void nsVolumeService::RemoveVolumeByName(const nsAString& aName) { - nsRefPtr vol; { MonitorAutoLock autoLock(mArrayMonitor); - vol = FindVolumeByName(aName); + nsVolume::Array::index_type volIndex; + nsRefPtr vol = FindVolumeByName(aName, &volIndex); + if (!vol) { + return; + } + mVolumeArray.RemoveElementAt(volIndex); } - if (!vol) { - return; - } - mVolumeArray.RemoveElement(vol); if (XRE_IsParentProcess()) { nsCOMPtr obs = GetObserverService(); diff --git a/dom/system/gonk/nsVolumeService.h b/dom/system/gonk/nsVolumeService.h index 9c1f11cc482..9bddc0b8fe2 100644 --- a/dom/system/gonk/nsVolumeService.h +++ b/dom/system/gonk/nsVolumeService.h @@ -47,7 +47,7 @@ public: void DumpNoLock(const char* aLabel); // To use this function, you have to create a new volume and pass it in. - void UpdateVolume(nsIVolume* aVolume, bool aNotifyObservers = true); + void UpdateVolume(nsVolume* aVolume, bool aNotifyObservers = true); void UpdateVolumeIOThread(const Volume* aVolume); void RecvVolumesFromParent(const nsTArray& aVolumes); @@ -61,8 +61,9 @@ private: void CheckMountLock(const nsAString& aMountLockName, const nsAString& aMountLockState); already_AddRefed FindVolumeByMountLockName(const nsAString& aMountLockName); - already_AddRefed FindVolumeByName(const nsAString& aName); - already_AddRefed CreateOrFindVolumeByName(const nsAString& aName, bool aIsFake = false); + + already_AddRefed FindVolumeByName(const nsAString& aName, + nsVolume::Array::index_type* aIndex = nullptr); Monitor mArrayMonitor; nsVolume::Array mVolumeArray;