Bug 841660 - Implement format interface for volume-based device storage, r=dhylands

This commit is contained in:
Alan Huang 2013-09-06 14:11:58 +08:00
parent b165a8e9e8
commit 6381088980
18 changed files with 375 additions and 22 deletions

View File

@ -95,6 +95,7 @@ public:
void GetDiskFreeSpace(int64_t* aSoFar);
void GetStatus(nsAString& aStatus);
void DoFormat(nsAString& aStatus);
static void GetRootDirectoryForType(const nsAString& aStorageType,
const nsAString& aStorageName,
nsIFile** aFile);
@ -237,6 +238,7 @@ public:
already_AddRefed<DOMRequest> FreeSpace(ErrorResult& aRv);
already_AddRefed<DOMRequest> UsedSpace(ErrorResult& aRv);
already_AddRefed<DOMRequest> Available(ErrorResult& aRv);
already_AddRefed<DOMRequest> Format(ErrorResult& aRv);
bool Default();

View File

@ -103,6 +103,16 @@ DeviceStorageRequestChild::
break;
}
case DeviceStorageResponseValue::TFormatStorageResponse:
{
FormatStorageResponse r = aValue;
AutoJSContext cx;
JS::Rooted<JS::Value> result(
cx, StringToJsval(mRequest->GetOwner(), r.mountState()));
mRequest->FireSuccess(result);
break;
}
case DeviceStorageResponseValue::TEnumerationResponse:
{
EnumerationResponse r = aValue;

View File

@ -131,6 +131,18 @@ DeviceStorageRequestParent::Dispatch()
break;
}
case DeviceStorageParams::TDeviceStorageFormatParams:
{
DeviceStorageFormatParams p = mParams;
nsRefPtr<DeviceStorageFile> dsf =
new DeviceStorageFile(p.type(), p.storageName());
nsRefPtr<PostFormatResultEvent> r
= new PostFormatResultEvent(this, dsf);
NS_DispatchToMainThread(r);
break;
}
case DeviceStorageParams::TDeviceStorageEnumerationParams:
{
DeviceStorageEnumerationParams p = mParams;
@ -215,6 +227,14 @@ DeviceStorageRequestParent::EnsureRequiredPermissions(
break;
}
case DeviceStorageParams::TDeviceStorageFormatParams:
{
DeviceStorageFormatParams p = mParams;
type = p.type();
requestType = DEVICE_STORAGE_REQUEST_FORMAT;
break;
}
case DeviceStorageParams::TDeviceStorageEnumerationParams:
{
DeviceStorageEnumerationParams p = mParams;
@ -726,6 +746,34 @@ DeviceStorageRequestParent::PostAvailableResultEvent::CancelableRun()
return NS_OK;
}
DeviceStorageRequestParent::PostFormatResultEvent::
PostFormatResultEvent(DeviceStorageRequestParent* aParent,
DeviceStorageFile* aFile)
: CancelableRunnable(aParent)
, mFile(aFile)
{
}
DeviceStorageRequestParent::PostFormatResultEvent::
~PostFormatResultEvent()
{
}
nsresult
DeviceStorageRequestParent::PostFormatResultEvent::CancelableRun()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
nsString state = NS_LITERAL_STRING("unavailable");
if (mFile) {
mFile->DoFormat(state);
}
FormatStorageResponse response(state);
unused << mParent->Send__delete__(mParent, response);
return NS_OK;
}
} // namespace devicestorage
} // namespace dom
} // namespace mozilla

View File

@ -227,6 +227,16 @@ private:
nsRefPtr<DeviceStorageFile> mFile;
};
class PostFormatResultEvent : public CancelableRunnable
{
public:
PostFormatResultEvent(DeviceStorageRequestParent* aParent, DeviceStorageFile* aFile);
virtual ~PostFormatResultEvent();
virtual nsresult CancelableRun();
private:
nsRefPtr<DeviceStorageFile> mFile;
};
protected:
bool AddRunnable(CancelableRunnable* aRunnable) {
MutexAutoLock lock(mMutex);

View File

@ -53,6 +53,11 @@ struct AvailableStorageResponse
nsString mountState;
};
struct FormatStorageResponse
{
nsString mountState;
};
union DeviceStorageResponseValue
{
ErrorResponse;
@ -62,6 +67,7 @@ union DeviceStorageResponseValue
FreeSpaceStorageResponse;
UsedSpaceStorageResponse;
AvailableStorageResponse;
FormatStorageResponse;
};
sync protocol PDeviceStorageRequest {

View File

@ -390,6 +390,7 @@ DeviceStorageTypeChecker::GetAccessForRequest(
break;
case DEVICE_STORAGE_REQUEST_WRITE:
case DEVICE_STORAGE_REQUEST_DELETE:
case DEVICE_STORAGE_REQUEST_FORMAT:
aAccessResult.AssignLiteral("write");
break;
case DEVICE_STORAGE_REQUEST_CREATE:
@ -1279,6 +1280,36 @@ DeviceStorageFile::IsAvailable()
return status.EqualsLiteral("available");
}
void
DeviceStorageFile::DoFormat(nsAString& aStatus)
{
DeviceStorageTypeChecker* typeChecker
= DeviceStorageTypeChecker::CreateOrGet();
if (!typeChecker) {
return;
}
if (!typeChecker->IsVolumeBased(mStorageType)) {
aStatus.AssignLiteral("notVolume");
return;
}
#ifdef MOZ_WIDGET_GONK
nsCOMPtr<nsIVolumeService> vs = do_GetService(NS_VOLUMESERVICE_CONTRACTID);
NS_ENSURE_TRUE_VOID(vs);
nsCOMPtr<nsIVolume> vol;
nsresult rv = vs->GetVolumeByName(mStorageName, getter_AddRefs(vol));
NS_ENSURE_SUCCESS_VOID(rv);
if (!vol) {
return;
}
vol->Format();
aStatus.AssignLiteral("formatting");
#endif
return;
}
void
DeviceStorageFile::GetStatus(nsAString& aStatus)
{
@ -1316,6 +1347,13 @@ DeviceStorageFile::GetStatus(nsAString& aStatus)
aStatus.AssignLiteral("shared");
return;
}
bool isFormatting;
rv = vol->GetIsFormatting(&isFormatting);
NS_ENSURE_SUCCESS_VOID(rv);
if (isFormatting) {
aStatus.AssignLiteral("unavailable");
return;
}
int32_t volState;
rv = vol->GetState(&volState);
NS_ENSURE_SUCCESS_VOID(rv);
@ -1848,6 +1886,39 @@ private:
nsRefPtr<DOMRequest> mRequest;
};
class PostFormatResultEvent : public nsRunnable
{
public:
PostFormatResultEvent(DeviceStorageFile *aFile, DOMRequest* aRequest)
: mFile(aFile)
, mRequest(aRequest)
{
}
~PostFormatResultEvent() {}
NS_IMETHOD Run()
{
MOZ_ASSERT(NS_IsMainThread());
nsString state = NS_LITERAL_STRING("unavailable");
if (mFile) {
mFile->DoFormat(state);
}
AutoJSContext cx;
JS::Rooted<JS::Value> result(cx,
StringToJsval(mRequest->GetOwner(), state));
mRequest->FireSuccess(result);
mRequest = nullptr;
return NS_OK;
}
private:
nsRefPtr<DeviceStorageFile> mFile;
nsRefPtr<DOMRequest> mRequest;
};
class PostResultEvent : public nsRunnable
{
public:
@ -2423,6 +2494,23 @@ public:
mDeviceStorage->mAllowedToWatchFile = true;
return NS_OK;
}
case DEVICE_STORAGE_REQUEST_FORMAT:
{
if (XRE_GetProcessType() != GeckoProcessType_Default) {
PDeviceStorageRequestChild* child
= new DeviceStorageRequestChild(mRequest, mFile);
DeviceStorageFormatParams params(mFile->mStorageType,
mFile->mStorageName);
ContentChild::GetSingleton()
->SendPDeviceStorageRequestConstructor(child, params);
return NS_OK;
}
r = new PostFormatResultEvent(mFile, mRequest);
NS_DispatchToMainThread(r);
return NS_OK;
}
}
if (r) {
@ -3083,6 +3171,26 @@ nsDOMDeviceStorage::Available(ErrorResult& aRv)
return request.forget();
}
already_AddRefed<DOMRequest>
nsDOMDeviceStorage::Format(ErrorResult& aRv)
{
nsCOMPtr<nsPIDOMWindow> win = GetOwner();
if (!win) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
nsRefPtr<DOMRequest> request = new DOMRequest(win);
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType,
mStorageName);
nsCOMPtr<nsIRunnable> r
= new DeviceStorageRequest(DEVICE_STORAGE_REQUEST_FORMAT,
win, mPrincipal, dsf, request);
NS_DispatchToMainThread(r);
return request.forget();
}
NS_IMETHODIMP
nsDOMDeviceStorage::GetRootDirectoryForFile(const nsAString& aName,
nsIFile** aRootDirectory)

View File

@ -51,7 +51,8 @@ enum DeviceStorageRequestType {
DEVICE_STORAGE_REQUEST_WATCH,
DEVICE_STORAGE_REQUEST_FREE_SPACE,
DEVICE_STORAGE_REQUEST_USED_SPACE,
DEVICE_STORAGE_REQUEST_AVAILABLE
DEVICE_STORAGE_REQUEST_AVAILABLE,
DEVICE_STORAGE_REQUEST_FORMAT
};
class DeviceStorageUsedSpaceCache MOZ_FINAL

View File

@ -79,6 +79,12 @@ struct DeviceStorageAvailableParams
nsString storageName;
};
struct DeviceStorageFormatParams
{
nsString type;
nsString storageName;
};
struct DeviceStorageAddParams
{
nsString type;
@ -119,6 +125,7 @@ union DeviceStorageParams
DeviceStorageFreeSpaceParams;
DeviceStorageUsedSpaceParams;
DeviceStorageAvailableParams;
DeviceStorageFormatParams;
};
struct FMRadioRequestEnableParams

View File

@ -263,6 +263,21 @@ public:
UpdateState();
}
void FormatVolume(const nsACString& aVolumeName)
{
RefPtr<Volume> vol = VolumeManager::FindVolumeByName(aVolumeName);
if (!vol) {
return;
}
if (vol->IsFormatRequested()) {
return;
}
vol->SetFormatRequested(true);
DBG("Calling UpdateState due to volume %s formatting set to %d",
vol->NameStr(), (int)vol->IsFormatRequested());
UpdateState();
}
private:
AutoVolumeEventObserver mVolumeEventObserver;
@ -428,14 +443,14 @@ AutoMounter::UpdateState()
continue;
}
if (tryToShare && vol->IsSharingEnabled()) {
if ((tryToShare && vol->IsSharingEnabled()) || vol->IsFormatRequested()) {
// We're going to try to unmount and share the volumes
switch (volState) {
case nsIVolume::STATE_MOUNTED: {
if (vol->IsMountLocked()) {
// The volume is currently locked, so leave it in the mounted
// state.
LOGW("UpdateState: Mounted volume %s is locked, not sharing",
LOGW("UpdateState: Mounted volume %s is locked, not sharing or formatting",
vol->NameStr());
break;
}
@ -444,7 +459,11 @@ AutoMounter::UpdateState()
// 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);
if (tryToShare && vol->IsSharingEnabled()) {
vol->SetIsSharing(true);
} else if (vol->IsFormatRequested()){
vol->SetIsFormatting(true);
}
// Check to see if there are any open files on the volume and
// don't initiate the unmount while there are open files.
@ -461,7 +480,7 @@ AutoMounter::UpdateState()
fileInfo.mComm.get(),
fileInfo.mExe.get());
} while (fileFinder.Next(&fileInfo));
LOGW("UpdateState: Mounted volume %s has open files, not sharing",
LOGW("UpdateState: Mounted volume %s has open files, not sharing or formatting",
vol->NameStr());
// Check again in a few seconds to see if the files are closed.
@ -495,10 +514,23 @@ AutoMounter::UpdateState()
return; // UpdateState will be called again when the Unmount command completes
}
case nsIVolume::STATE_IDLE: {
// Volume is unmounted. We can go ahead and share.
LOG("UpdateState: Sharing %s", vol->NameStr());
vol->StartShare(mResponseCallback);
return; // UpdateState will be called again when the Share command completes
LOG("UpdateState: Volume %s is nsIVolume::STATE_IDLE", vol->NameStr());
if (vol->IsFormatting() && !vol->IsFormatRequested()) {
vol->SetFormatRequested(false);
LOG("UpdateState: Mounting %s", vol->NameStr());
vol->StartMount(mResponseCallback);
break;
}
if (tryToShare && vol->IsSharingEnabled()) {
// Volume is unmounted. We can go ahead and share.
LOG("UpdateState: Sharing %s", vol->NameStr());
vol->StartShare(mResponseCallback);
} else if (vol->IsFormatRequested()){
// Volume is unmounted. We can go ahead and format.
LOG("UpdateState: Formatting %s", vol->NameStr());
vol->StartFormat(mResponseCallback);
}
return; // UpdateState will be called again when the Share/Format command completes
}
default: {
// Not in a state that we can do anything about.
@ -578,6 +610,15 @@ SetAutoMounterSharingModeIOThread(const nsCString& aVolumeName, const bool& aAll
sAutoMounter->SetSharingMode(aVolumeName, aAllowSharing);
}
static void
AutoMounterFormatVolumeIOThread(const nsCString& aVolumeName)
{
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
MOZ_ASSERT(sAutoMounter);
sAutoMounter->FormatVolume(aVolumeName);
}
static void
UsbCableEventIOThread()
{
@ -732,10 +773,19 @@ SetAutoMounterSharingMode(const nsCString& aVolumeName, bool aAllowSharing)
{
XRE_GetIOMessageLoop()->PostTask(
FROM_HERE,
NewRunnableFunction(SetAutoMounterSharingModeIOThread,
NewRunnableFunction(SetAutoMounterSharingModeIOThread,
aVolumeName, aAllowSharing));
}
void
AutoMounterFormatVolume(const nsCString& aVolumeName)
{
XRE_GetIOMessageLoop()->PostTask(
FROM_HERE,
NewRunnableFunction(AutoMounterFormatVolumeIOThread,
aVolumeName));
}
void
ShutdownAutoMounter()
{

View File

@ -59,6 +59,15 @@ GetAutoMounterStatus();
void
SetAutoMounterSharingMode(const nsCString& aVolumeName, bool aAllowSharing);
/**
* Formats the volume with specified volume name.
*
* If the volume is ready to format, automounter
* will unmount it, format it and then mount it again.
*/
void
AutoMounterFormatVolume(const nsCString& aVolumeName);
/**
* Shuts down the automounter.
*

View File

@ -60,7 +60,9 @@ Volume::Volume(const nsCSubstring& aName)
mMountLocked(true), // Needs to agree with nsVolume::nsVolume
mSharingEnabled(false),
mCanBeShared(true),
mIsSharing(false)
mIsSharing(false),
mFormatRequested(false),
mIsFormatting(false)
{
DBG("Volume %s: created", NameStr());
}
@ -79,6 +81,20 @@ Volume::SetIsSharing(bool aIsSharing)
}
}
void
Volume::SetIsFormatting(bool aIsFormatting)
{
if (aIsFormatting == mIsFormatting) {
return;
}
mIsFormatting = aIsFormatting;
LOG("Volume %s: IsFormatting set to %d state %s",
NameStr(), (int)mIsFormatting, StateStr(mState));
if (mIsFormatting) {
mEventObserverList.Broadcast(this);
}
}
void
Volume::SetMediaPresent(bool aMediaPresent)
{
@ -126,12 +142,20 @@ Volume::SetSharingEnabled(bool aSharingEnabled)
NameStr(), (int)mSharingEnabled, (int)mCanBeShared);
}
void
Volume::SetFormatRequested(bool aFormatRequested)
{
mFormatRequested = aFormatRequested;
LOG("SetFormatRequested for volume %s to %d CanBeFormatted = %d",
NameStr(), (int)mFormatRequested, (int)CanBeFormatted());
}
void
Volume::SetState(Volume::STATE aNewState)
{
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
if (aNewState == mState) {
return;
}
@ -156,7 +180,12 @@ Volume::SetState(Volume::STATE aNewState)
break;
case nsIVolume::STATE_MOUNTED:
mIsFormatting = false;
mIsSharing = false;
break;
case nsIVolume::STATE_FORMATTING:
mFormatRequested = false;
mIsFormatting = true;
mIsSharing = false;
break;
@ -207,6 +236,15 @@ Volume::StartUnmount(VolumeResponseCallback* aCallback)
StartCommand(new VolumeActionCommand(this, "unmount", "force", aCallback));
}
void
Volume::StartFormat(VolumeResponseCallback* aCallback)
{
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
StartCommand(new VolumeActionCommand(this, "format", "", aCallback));
}
void
Volume::StartShare(VolumeResponseCallback* aCallback)
{

View File

@ -46,10 +46,14 @@ public:
bool IsMountLocked() const { return mMountLocked; }
bool MediaPresent() const { return mMediaPresent; }
bool CanBeShared() const { return mCanBeShared; }
bool CanBeFormatted() const { return CanBeShared(); }
bool IsSharingEnabled() const { return mCanBeShared && mSharingEnabled; }
bool IsFormatRequested() const { return CanBeFormatted() && mFormatRequested; }
bool IsSharing() const { return mIsSharing; }
bool IsFormatting() const { return mIsFormatting; }
void SetSharingEnabled(bool aSharingEnabled);
void SetFormatRequested(bool aFormatRequested);
typedef mozilla::Observer<Volume *> EventObserver;
typedef mozilla::ObserverList<Volume *> EventObserverList;
@ -69,10 +73,12 @@ private:
// be called as each one completes.
void StartMount(VolumeResponseCallback* aCallback);
void StartUnmount(VolumeResponseCallback* aCallback);
void StartFormat(VolumeResponseCallback* aCallback);
void StartShare(VolumeResponseCallback* aCallback);
void StartUnshare(VolumeResponseCallback* aCallback);
void SetIsSharing(bool aIsSharing);
void SetIsFormatting(bool aIsFormatting);
void SetState(STATE aNewState);
void SetMediaPresent(bool aMediaPresent);
void SetMountPoint(const nsCSubstring& aMountPoint);
@ -91,8 +97,10 @@ private:
int32_t mMountGeneration;
bool mMountLocked;
bool mSharingEnabled;
bool mFormatRequested;
bool mCanBeShared;
bool mIsSharing;
bool mIsFormatting;
static EventObserverList mEventObserverList;
};

View File

@ -37,6 +37,7 @@ private:
void InitVolumeServiceIOThread(nsVolumeService* const & aVolumeService);
void ShutdownVolumeServiceIOThread();
void FormatVolume(const nsCString& aVolume);
} // system
} // mozilla

View File

@ -5,7 +5,7 @@
#include "nsISupports.idl"
#include "nsIVolumeStat.idl"
[scriptable, uuid(e476e7ea-5cde-4d5a-b00d-d60daad76398)]
[scriptable, uuid(8c163fe4-5577-11e3-b3d0-10bf48d707fb)]
interface nsIVolume : nsISupports
{
// These MUST match the states from android's system/vold/Volume.h header
@ -62,8 +62,17 @@ interface nsIVolume : nsISupports
// transitioning from mounted to sharing and back again.
readonly attribute boolean isSharing;
// Determines if the volume is currently formatting. This sets true once
// mFormatRequest == true and mState == STATE_MOUNTED, and sets false
// once the volume has been formatted and mounted again.
readonly attribute boolean isFormatting;
nsIVolumeStat getStats();
// Formats the volume in IO thread, if the volume is ready to be formatted.
// Automounter will unmount it, format it and then mount it again.
void format();
// Whether this is a fake volume.
readonly attribute boolean isFake;
};

View File

@ -13,6 +13,8 @@
#include "nsVolumeStat.h"
#include "nsXULAppAPI.h"
#include "Volume.h"
#include "AutoMounter.h"
#include "VolumeManager.h"
#define VOLUME_MANAGER_LOG_TAG "nsVolume"
#include "VolumeManagerLog.h"
@ -53,7 +55,8 @@ nsVolume::nsVolume(const Volume* aVolume)
mMountLocked(aVolume->IsMountLocked()),
mIsFake(false),
mIsMediaPresent(aVolume->MediaPresent()),
mIsSharing(aVolume->IsSharing())
mIsSharing(aVolume->IsSharing()),
mIsFormatting(aVolume->IsFormatting())
{
}
@ -101,6 +104,12 @@ bool nsVolume::Equals(nsIVolume* aVolume)
return false;
}
bool isFormatting;
aVolume->GetIsFormatting(&isFormatting);
if (mIsFormatting != isFormatting) {
return false;
}
return true;
}
@ -122,6 +131,12 @@ NS_IMETHODIMP nsVolume::GetIsSharing(bool *aIsSharing)
return NS_OK;
}
NS_IMETHODIMP nsVolume::GetIsFormatting(bool *aIsFormatting)
{
*aIsFormatting = mIsFormatting;
return NS_OK;
}
NS_IMETHODIMP nsVolume::GetName(nsAString& aName)
{
aName = mName;
@ -170,15 +185,36 @@ NS_IMETHODIMP nsVolume::GetIsFake(bool *aIsFake)
return NS_OK;
}
NS_IMETHODIMP nsVolume::Format()
{
XRE_GetIOMessageLoop()->PostTask(
FROM_HERE,
NewRunnableFunction(FormatVolumeIOThread, NameStr()));
return NS_OK;
}
/* static */
void nsVolume::FormatVolumeIOThread(const nsCString& aVolume)
{
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
if (VolumeManager::State() != VolumeManager::VOLUMES_READY) {
return;
}
AutoMounterFormatVolume(aVolume);
}
void
nsVolume::LogState() const
{
if (mState == nsIVolume::STATE_MOUNTED) {
LOG("nsVolume: %s state %s @ '%s' gen %d locked %d fake %d "
"media %d sharing %d",
"media %d sharing %d formatting %d",
NameStr().get(), StateStr(), MountPointStr().get(),
MountGeneration(), (int)IsMountLocked(), (int)IsFake(),
(int)IsMediaPresent(), (int)IsSharing());
(int)IsMediaPresent(), (int)IsSharing(),
(int)IsFormatting());
return;
}
@ -195,6 +231,7 @@ void nsVolume::Set(nsIVolume* aVolume)
aVolume->GetIsFake(&mIsFake);
aVolume->GetIsMediaPresent(&mIsMediaPresent);
aVolume->GetIsSharing(&mIsSharing);
aVolume->GetIsFormatting(&mIsFormatting);
int32_t volMountGeneration;
aVolume->GetMountGeneration(&volMountGeneration);

View File

@ -37,7 +37,8 @@ public:
mMountLocked(false),
mIsFake(false),
mIsMediaPresent(aIsMediaPresent),
mIsSharing(aIsSharing)
mIsSharing(aIsSharing),
mIsFormatting(false)
{
}
@ -50,7 +51,8 @@ public:
mMountLocked(true), // Needs to agree with Volume::Volume
mIsFake(false),
mIsMediaPresent(false),
mIsSharing(false)
mIsSharing(false),
mIsFormatting(false)
{
}
@ -74,6 +76,7 @@ public:
bool IsFake() const { return mIsFake; }
bool IsMediaPresent() const { return mIsMediaPresent; }
bool IsSharing() const { return mIsSharing; }
bool IsFormatting() const { return mIsFormatting; }
typedef nsTArray<nsRefPtr<nsVolume> > Array;
@ -86,6 +89,7 @@ private:
void SetIsFake(bool aIsFake);
void SetState(int32_t aState);
static void FormatVolumeIOThread(const nsCString& aVolume);
nsString mName;
nsString mMountPoint;
@ -95,6 +99,7 @@ private:
bool mIsFake;
bool mIsMediaPresent;
bool mIsSharing;
bool mIsFormatting;
};
} // system

View File

@ -431,10 +431,11 @@ public:
{
MOZ_ASSERT(NS_IsMainThread());
DBG("UpdateVolumeRunnable::Run '%s' state %s gen %d locked %d "
"media %d sharing %d",
"media %d sharing %d formatting %d",
mVolume->NameStr().get(), mVolume->StateStr(),
mVolume->MountGeneration(), (int)mVolume->IsMountLocked(),
(int)mVolume->IsMediaPresent(), mVolume->IsSharing());
(int)mVolume->IsMediaPresent(), mVolume->IsSharing(),
mVolume->IsFormatting());
mVolumeService->UpdateVolume(mVolume);
mVolumeService = nullptr;
@ -451,10 +452,11 @@ void
nsVolumeService::UpdateVolumeIOThread(const Volume* aVolume)
{
DBG("UpdateVolumeIOThread: Volume '%s' state %s mount '%s' gen %d locked %d "
"media %d sharing %d",
"media %d sharing %d formatting %d",
aVolume->NameStr(), aVolume->StateStr(), aVolume->MountPoint().get(),
aVolume->MountGeneration(), (int)aVolume->IsMountLocked(),
(int)aVolume->MediaPresent(), (int)aVolume->IsSharing());
(int)aVolume->MediaPresent(), (int)aVolume->IsSharing(),
(int)aVolume->IsFormatting());
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
NS_DispatchToMainThread(new UpdateVolumeRunnable(this, aVolume));
}

View File

@ -39,6 +39,8 @@ interface DeviceStorage : EventTarget {
DOMRequest usedSpace();
[Throws]
DOMRequest available();
[Throws]
DOMRequest format();
// Note that the storageName is just a name (like sdcard), and doesn't
// include any path information.