Bug 928558 - AutoMounter mark volumes as shared a bit early when open files are detected. r=qDot

This commit is contained in:
Dave Hylands 2013-10-18 20:21:52 -07:00
parent c886826721
commit 476564b49a
5 changed files with 68 additions and 8 deletions

View File

@ -316,11 +316,37 @@ AutoMounterResponseCallback::ResponseReceived(const VolumeCommand* aCommand)
}
}
class AutoBool {
public:
explicit AutoBool(bool &aBool) : mBool(aBool) {
mBool = true;
}
~AutoBool() {
mBool = false;
}
private:
bool &mBool;
};
/***************************************************************************/
void
AutoMounter::UpdateState()
{
static bool inUpdateState = false;
if (inUpdateState) {
// When UpdateState calls SetISharing, this causes a volume state
// change to occur, which would normally cause UpdateState to be called
// again. We want the volume state change to go out (so that device
// storage will see the change in sharing state), but since we're
// already in UpdateState we just want to prevent recursion from screwing
// things up.
return;
}
AutoBool inUpdateStateDetector(inUpdateState);
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
// If the following preconditions are met:
@ -379,6 +405,7 @@ AutoMounter::UpdateState()
umsAvail, umsEnabled, mMode, usbCablePluggedIn, tryToShare);
bool filesOpen = false;
static unsigned filesOpenDelayCount = 0;
VolumeArray::index_type volIndex;
VolumeArray::size_type numVolumes = VolumeManager::NumVolumes();
for (volIndex = 0; volIndex < numVolumes; volIndex++) {
@ -413,6 +440,12 @@ AutoMounter::UpdateState()
break;
}
// Mark the volume as if we've started sharing. This will cause
// apps which watch device storage notifications to see the volume
// go into the shared state, and prompt them to close any open files
// that they might have.
vol->SetIsSharing(true);
// Check to see if there are any open files on the volume and
// don't initiate the unmount while there are open files.
OpenFileFinder::Info fileInfo;
@ -431,15 +464,26 @@ AutoMounter::UpdateState()
LOGW("UpdateState: Mounted volume %s has open files, not sharing",
vol->NameStr());
// Check again in 5 seconds to see if the files are closed. Since
// we're trying to share the volume, this implies that we're
// Check again in a few seconds to see if the files are closed.
// Since we're trying to share the volume, this implies that we're
// plugged into the PC via USB and this in turn implies that the
// battery is charging, so we don't need to be too concerned about
// wasting battery here.
//
// If we just detected that there were files open, then we use
// a short timer. We will have told the apps that we're trying
// trying to share, and they'll be closing their files. This makes
// the sharing more responsive. If after a few seconds, the apps
// haven't closed their files, then we back off.
int delay = 1000;
if (filesOpenDelayCount > 10) {
delay = 5000;
}
MessageLoopForIO::current()->
PostDelayedTask(FROM_HERE,
NewRunnableMethod(this, &AutoMounter::UpdateState),
5000);
delay);
filesOpen = true;
break;
}
@ -447,7 +491,6 @@ AutoMounter::UpdateState()
// Volume is mounted, we need to unmount before
// we can share.
LOG("UpdateState: Unmounting %s", vol->NameStr());
vol->SetIsSharing(true);
vol->StartUnmount(mResponseCallback);
return; // UpdateState will be called again when the Unmount command completes
}
@ -488,8 +531,10 @@ AutoMounter::UpdateState()
int32_t status = AUTOMOUNTER_STATUS_DISABLED;
if (filesOpen) {
filesOpenDelayCount++;
status = AUTOMOUNTER_STATUS_FILES_OPEN;
} else if (enabled) {
filesOpenDelayCount = 0;
status = AUTOMOUNTER_STATUS_ENABLED;
}
SetAutoMounterStatus(status);

View File

@ -68,7 +68,15 @@ Volume::Volume(const nsCSubstring& aName)
void
Volume::SetIsSharing(bool aIsSharing)
{
if (aIsSharing == mIsSharing) {
return;
}
mIsSharing = aIsSharing;
LOG("Volume %s: IsSharing set to %d state %s",
NameStr(), (int)mIsSharing, StateStr(mState));
if (mIsSharing) {
mEventObserverList.Broadcast(this);
}
}
void

View File

@ -95,6 +95,12 @@ bool nsVolume::Equals(nsIVolume* aVolume)
return false;
}
bool isSharing;
aVolume->GetIsSharing(&isSharing);
if (mIsSharing != isSharing) {
return false;
}
return true;
}

View File

@ -71,6 +71,10 @@ public:
int32_t State() const { return mState; }
const char* StateStr() const { return NS_VolumeStateStr(mState); }
bool IsFake() const { return mIsFake; }
bool IsMediaPresent() const { return mIsMediaPresent; }
bool IsSharing() const { return mIsSharing; }
typedef nsTArray<nsRefPtr<nsVolume> > Array;
private:
@ -80,9 +84,6 @@ private:
void UpdateMountLock(const nsAString& aMountLockState);
void UpdateMountLock(bool aMountLocked);
bool IsFake() const { return mIsFake; }
bool IsMediaPresent() const { return mIsMediaPresent; }
bool IsSharing() const { return mIsSharing; }
void SetIsFake(bool aIsFake);
void SetState(int32_t aState);

View File

@ -454,7 +454,7 @@ nsVolumeService::UpdateVolumeIOThread(const Volume* aVolume)
"media %d sharing %d",
aVolume->NameStr(), aVolume->StateStr(), aVolume->MountPoint().get(),
aVolume->MountGeneration(), (int)aVolume->IsMountLocked(),
(int)aVolume->IsMediaPresent(), (int)aVolume->IsSharing());
(int)aVolume->MediaPresent(), (int)aVolume->IsSharing());
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
NS_DispatchToMainThread(new UpdateVolumeRunnable(this, aVolume));
}