mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 06:11:37 +00:00
Bug 1033952 - Implement "Removable" and "HotSwappable" APIs for device storage. r=dhylands, r=bzbarsky
This commit is contained in:
parent
2c080f980c
commit
0aa1eafc0c
@ -272,6 +272,7 @@ public:
|
||||
bool CanBeMounted();
|
||||
bool CanBeFormatted();
|
||||
bool CanBeShared();
|
||||
bool IsRemovable();
|
||||
bool Default();
|
||||
|
||||
// Uses XPCOM GetStorageName
|
||||
@ -322,6 +323,7 @@ private:
|
||||
nsCOMPtr<nsIFile> mRootDirectory;
|
||||
nsString mStorageName;
|
||||
bool mIsShareable;
|
||||
bool mIsRemovable;
|
||||
|
||||
already_AddRefed<nsDOMDeviceStorage> GetStorage(const nsAString& aFullPath,
|
||||
nsAString& aOutStoragePath);
|
||||
|
@ -3337,6 +3337,7 @@ NS_IMPL_RELEASE_INHERITED(nsDOMDeviceStorage, DOMEventTargetHelper)
|
||||
nsDOMDeviceStorage::nsDOMDeviceStorage(nsPIDOMWindow* aWindow)
|
||||
: DOMEventTargetHelper(aWindow)
|
||||
, mIsShareable(false)
|
||||
, mIsRemovable(false)
|
||||
, mIsWatchingFile(false)
|
||||
, mAllowedToWatchFile(false)
|
||||
{
|
||||
@ -3383,6 +3384,12 @@ nsDOMDeviceStorage::Init(nsPIDOMWindow* aWindow, const nsAString &aType,
|
||||
return rv;
|
||||
}
|
||||
mIsShareable = !isFake;
|
||||
bool isRemovable;
|
||||
rv = vol->GetIsHotSwappable(&isRemovable);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
mIsRemovable = isRemovable;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -4226,6 +4233,12 @@ nsDOMDeviceStorage::CanBeShared()
|
||||
return mIsShareable;
|
||||
}
|
||||
|
||||
bool
|
||||
nsDOMDeviceStorage::IsRemovable()
|
||||
{
|
||||
return mIsRemovable;
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
nsDOMDeviceStorage::GetRoot(ErrorResult& aRv)
|
||||
{
|
||||
|
@ -2153,13 +2153,15 @@ ContentChild::RecvFileSystemUpdate(const nsString& aFsName,
|
||||
const bool& aIsSharing,
|
||||
const bool& aIsFormatting,
|
||||
const bool& aIsFake,
|
||||
const bool& aIsUnmounting)
|
||||
const bool& aIsUnmounting,
|
||||
const bool& aIsRemovable,
|
||||
const bool& aIsHotSwappable)
|
||||
{
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
nsRefPtr<nsVolume> volume = new nsVolume(aFsName, aVolumeName, aState,
|
||||
aMountGeneration, aIsMediaPresent,
|
||||
aIsSharing, aIsFormatting, aIsFake,
|
||||
aIsUnmounting);
|
||||
aIsUnmounting, aIsRemovable, aIsHotSwappable);
|
||||
|
||||
nsRefPtr<nsVolumeService> vs = nsVolumeService::GetSingleton();
|
||||
if (vs) {
|
||||
@ -2176,6 +2178,8 @@ ContentChild::RecvFileSystemUpdate(const nsString& aFsName,
|
||||
unused << aIsFormatting;
|
||||
unused << aIsFake;
|
||||
unused << aIsUnmounting;
|
||||
unused << aIsRemovable;
|
||||
unused << aIsHotSwappable;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
@ -336,7 +336,9 @@ public:
|
||||
const bool& aIsSharing,
|
||||
const bool& aIsFormatting,
|
||||
const bool& aIsFake,
|
||||
const bool& aIsUnmounting) MOZ_OVERRIDE;
|
||||
const bool& aIsUnmounting,
|
||||
const bool& aIsRemovable,
|
||||
const bool& aIsHotSwappable) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool RecvNuwaFork() MOZ_OVERRIDE;
|
||||
|
||||
|
@ -2829,6 +2829,8 @@ ContentParent::Observe(nsISupports* aSubject,
|
||||
bool isFormatting;
|
||||
bool isFake;
|
||||
bool isUnmounting;
|
||||
bool isRemovable;
|
||||
bool isHotSwappable;
|
||||
|
||||
vol->GetName(volName);
|
||||
vol->GetMountPoint(mountPoint);
|
||||
@ -2839,6 +2841,8 @@ ContentParent::Observe(nsISupports* aSubject,
|
||||
vol->GetIsFormatting(&isFormatting);
|
||||
vol->GetIsFake(&isFake);
|
||||
vol->GetIsUnmounting(&isUnmounting);
|
||||
vol->GetIsRemovable(&isRemovable);
|
||||
vol->GetIsHotSwappable(&isHotSwappable);
|
||||
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
if (!(IsNuwaReady() && IsNuwaProcess()))
|
||||
@ -2847,7 +2851,7 @@ ContentParent::Observe(nsISupports* aSubject,
|
||||
unused << SendFileSystemUpdate(volName, mountPoint, state,
|
||||
mountGeneration, isMediaPresent,
|
||||
isSharing, isFormatting, isFake,
|
||||
isUnmounting);
|
||||
isUnmounting, isRemovable, isHotSwappable);
|
||||
}
|
||||
} else if (!strcmp(aTopic, "phone-state-changed")) {
|
||||
nsString state(aData);
|
||||
|
@ -319,6 +319,8 @@ struct VolumeInfo {
|
||||
bool isFormatting;
|
||||
bool isFake;
|
||||
bool isUnmounting;
|
||||
bool isRemovable;
|
||||
bool isHotSwappable;
|
||||
};
|
||||
|
||||
struct ClipboardCapabilities {
|
||||
@ -489,7 +491,8 @@ child:
|
||||
// VolumeInfo above.
|
||||
FileSystemUpdate(nsString fsName, nsString mountPoint, int32_t fsState,
|
||||
int32_t mountGeneration, bool isMediaPresent,
|
||||
bool isSharing, bool isFormatting, bool isFake, bool isUnmounting);
|
||||
bool isSharing, bool isFormatting, bool isFake,
|
||||
bool isUnmounting, bool isRemovable, bool isHotSwappable);
|
||||
|
||||
// Ask the Nuwa process to create a new child process.
|
||||
NuwaFork();
|
||||
|
@ -81,6 +81,8 @@ Volume::Volume(const nsCSubstring& aName)
|
||||
mIsSharing(false),
|
||||
mIsFormatting(false),
|
||||
mIsUnmounting(false),
|
||||
mIsRemovable(false),
|
||||
mIsHotSwappable(false),
|
||||
mId(sNextId++)
|
||||
{
|
||||
DBG("Volume %s: created", NameStr());
|
||||
@ -156,6 +158,78 @@ Volume::SetIsUnmounting(bool aIsUnmounting)
|
||||
sEventObserverList.Broadcast(this);
|
||||
}
|
||||
|
||||
void
|
||||
Volume::SetIsRemovable(bool aIsRemovable)
|
||||
{
|
||||
if (aIsRemovable == mIsRemovable) {
|
||||
return;
|
||||
}
|
||||
mIsRemovable = aIsRemovable;
|
||||
if (!mIsRemovable) {
|
||||
mIsHotSwappable = false;
|
||||
}
|
||||
LOG("Volume %s: IsRemovable set to %d state %s",
|
||||
NameStr(), (int)mIsRemovable, StateStr(mState));
|
||||
sEventObserverList.Broadcast(this);
|
||||
}
|
||||
|
||||
void
|
||||
Volume::SetIsHotSwappable(bool aIsHotSwappable)
|
||||
{
|
||||
if (aIsHotSwappable == mIsHotSwappable) {
|
||||
return;
|
||||
}
|
||||
mIsHotSwappable = aIsHotSwappable;
|
||||
if (mIsHotSwappable) {
|
||||
mIsRemovable = true;
|
||||
}
|
||||
LOG("Volume %s: IsHotSwappable set to %d state %s",
|
||||
NameStr(), (int)mIsHotSwappable, StateStr(mState));
|
||||
sEventObserverList.Broadcast(this);
|
||||
}
|
||||
|
||||
bool
|
||||
Volume::BoolConfigValue(const nsCString& aConfigValue, bool& aBoolValue)
|
||||
{
|
||||
if (aConfigValue.EqualsLiteral("1") ||
|
||||
aConfigValue.LowerCaseEqualsLiteral("true")) {
|
||||
aBoolValue = true;
|
||||
return true;
|
||||
}
|
||||
if (aConfigValue.EqualsLiteral("0") ||
|
||||
aConfigValue.LowerCaseEqualsLiteral("false")) {
|
||||
aBoolValue = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
Volume::SetConfig(const nsCString& aConfigName, const nsCString& aConfigValue)
|
||||
{
|
||||
if (aConfigName.LowerCaseEqualsLiteral("removable")) {
|
||||
bool value = false;
|
||||
if (BoolConfigValue(aConfigValue, value)) {
|
||||
SetIsRemovable(value);
|
||||
} else {
|
||||
ERR("Volume %s: invalid value '%s' for configuration '%s'",
|
||||
NameStr(), aConfigValue.get(), aConfigName.get());
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (aConfigName.LowerCaseEqualsLiteral("hotswappable")) {
|
||||
bool value = false;
|
||||
if (BoolConfigValue(aConfigValue, value)) {
|
||||
SetIsHotSwappable(value);
|
||||
} else {
|
||||
ERR("Volume %s: invalid value '%s' for configuration '%s'",
|
||||
NameStr(), aConfigValue.get(), aConfigName.get());
|
||||
}
|
||||
return;
|
||||
}
|
||||
ERR("Volume %s: invalid config '%s'", NameStr(), aConfigName.get());
|
||||
}
|
||||
|
||||
void
|
||||
Volume::SetMediaPresent(bool aMediaPresent)
|
||||
{
|
||||
|
@ -75,6 +75,8 @@ public:
|
||||
bool IsSharing() const { return mIsSharing; }
|
||||
bool IsFormatting() const { return mIsFormatting; }
|
||||
bool IsUnmounting() const { return mIsUnmounting; }
|
||||
bool IsRemovable() const { return mIsRemovable; }
|
||||
bool IsHotSwappable() const { return mIsHotSwappable; }
|
||||
|
||||
void SetFakeVolume(const nsACString& aMountPoint);
|
||||
|
||||
@ -107,11 +109,16 @@ private:
|
||||
void SetIsSharing(bool aIsSharing);
|
||||
void SetIsFormatting(bool aIsFormatting);
|
||||
void SetIsUnmounting(bool aIsUnmounting);
|
||||
void SetIsRemovable(bool aIsRemovable);
|
||||
void SetIsHotSwappable(bool aIsHotSwappable);
|
||||
void SetState(STATE aNewState);
|
||||
void SetMediaPresent(bool aMediaPresent);
|
||||
void SetMountPoint(const nsCSubstring& aMountPoint);
|
||||
void StartCommand(VolumeCommand* aCommand);
|
||||
|
||||
bool BoolConfigValue(const nsCString& aConfigValue, bool& aBoolValue);
|
||||
void SetConfig(const nsCString& aConfigName, const nsCString& aConfigValue);
|
||||
|
||||
void HandleVoldResponse(int aResponseCode, nsCWhitespaceTokenizer& aTokenizer);
|
||||
|
||||
static void UpdateMountLock(const nsACString& aVolumeName,
|
||||
@ -132,6 +139,8 @@ private:
|
||||
bool mIsSharing;
|
||||
bool mIsFormatting;
|
||||
bool mIsUnmounting;
|
||||
bool mIsRemovable;
|
||||
bool mIsHotSwappable;
|
||||
uint32_t mId; // Unique ID (used by MTP)
|
||||
|
||||
static VolumeObserverList sEventObserverList;
|
||||
|
@ -168,12 +168,12 @@ void VolumeManager::InitConfig()
|
||||
//
|
||||
// The format of the volume.cfg file is as follows:
|
||||
// create volume-name mount-point
|
||||
// configure volume-name preference preference-value
|
||||
// Blank lines and lines starting with the hash character "#" will be ignored.
|
||||
|
||||
ScopedCloseFile fp;
|
||||
int n = 0;
|
||||
char line[255];
|
||||
char *command, *volNamePtr, *mountPointPtr, *save_ptr;
|
||||
const char *filename = "/system/etc/volume.cfg";
|
||||
if (!(fp = fopen(filename, "r"))) {
|
||||
LOG("Unable to open volume configuration file '%s' - ignoring", filename);
|
||||
@ -185,27 +185,87 @@ void VolumeManager::InitConfig()
|
||||
|
||||
if (line[0] == '#')
|
||||
continue;
|
||||
if (!(command = strtok_r(line, delim, &save_ptr))) {
|
||||
|
||||
nsCString commandline(line);
|
||||
nsCWhitespaceTokenizer tokenizer(commandline);
|
||||
if (!tokenizer.hasMoreTokens()) {
|
||||
// Blank line - ignore
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(command, "create")) {
|
||||
if (!(volNamePtr = strtok_r(nullptr, delim, &save_ptr))) {
|
||||
|
||||
nsCString command(tokenizer.nextToken());
|
||||
if (command.EqualsLiteral("create")) {
|
||||
if (!tokenizer.hasMoreTokens()) {
|
||||
ERR("No vol_name in %s line %d", filename, n);
|
||||
continue;
|
||||
}
|
||||
if (!(mountPointPtr = strtok_r(nullptr, delim, &save_ptr))) {
|
||||
ERR("No mount point for volume '%s'. %s line %d", volNamePtr, filename, n);
|
||||
nsCString volName(tokenizer.nextToken());
|
||||
if (!tokenizer.hasMoreTokens()) {
|
||||
ERR("No mount point for volume '%s'. %s line %d",
|
||||
volName.get(), filename, n);
|
||||
continue;
|
||||
}
|
||||
nsCString mountPoint(mountPointPtr);
|
||||
nsCString volName(volNamePtr);
|
||||
|
||||
nsCString mountPoint(tokenizer.nextToken());
|
||||
RefPtr<Volume> vol = FindAddVolumeByName(volName);
|
||||
vol->SetFakeVolume(mountPoint);
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
ERR("Unrecognized command: '%s'", command);
|
||||
if (command.EqualsLiteral("configure")) {
|
||||
if (!tokenizer.hasMoreTokens()) {
|
||||
ERR("No vol_name in %s line %d", filename, n);
|
||||
continue;
|
||||
}
|
||||
nsCString volName(tokenizer.nextToken());
|
||||
if (!tokenizer.hasMoreTokens()) {
|
||||
ERR("No configuration name specified for volume '%s'. %s line %d",
|
||||
volName.get(), filename, n);
|
||||
continue;
|
||||
}
|
||||
nsCString configName(tokenizer.nextToken());
|
||||
if (!tokenizer.hasMoreTokens()) {
|
||||
ERR("No value for configuration name '%s'. %s line %d",
|
||||
configName.get(), filename, n);
|
||||
continue;
|
||||
}
|
||||
nsCString configValue(tokenizer.nextToken());
|
||||
RefPtr<Volume> vol = FindVolumeByName(volName);
|
||||
if (vol) {
|
||||
vol->SetConfig(configName, configValue);
|
||||
} else {
|
||||
ERR("Invalid volume name '%s'.", volName.get());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
ERR("Unrecognized command: '%s'", command.get());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
VolumeManager::DefaultConfig()
|
||||
{
|
||||
|
||||
VolumeManager::VolumeArray::size_type numVolumes = VolumeManager::NumVolumes();
|
||||
if (numVolumes == 0) {
|
||||
return;
|
||||
}
|
||||
if (numVolumes == 1) {
|
||||
// This is to cover early shipping phones like the Buri,
|
||||
// which had no internal storage, and only external sdcard.
|
||||
//
|
||||
// Phones line the nexus-4 which only have an internal
|
||||
// storage area will need to have a volume.cfg file with
|
||||
// removable set to false.
|
||||
RefPtr<Volume> vol = VolumeManager::GetVolume(0);
|
||||
vol->SetIsRemovable(true);
|
||||
vol->SetIsHotSwappable(true);
|
||||
return;
|
||||
}
|
||||
VolumeManager::VolumeArray::index_type volIndex;
|
||||
for (volIndex = 0; volIndex < numVolumes; volIndex++) {
|
||||
RefPtr<Volume> vol = VolumeManager::GetVolume(volIndex);
|
||||
if (!vol->Name().EqualsLiteral("sdcard")) {
|
||||
vol->SetIsRemovable(true);
|
||||
vol->SetIsHotSwappable(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -233,6 +293,7 @@ class VolumeListCallback : public VolumeResponseCallback
|
||||
// We've received the list of volumes. Now read the Volume.cfg
|
||||
// file to perform customizations, and then tell everybody
|
||||
// that we're ready for business.
|
||||
VolumeManager::DefaultConfig();
|
||||
VolumeManager::InitConfig();
|
||||
VolumeManager::Dump("READY");
|
||||
VolumeManager::SetState(VolumeManager::VOLUMES_READY);
|
||||
|
@ -138,6 +138,8 @@ protected:
|
||||
virtual void OnFileCanWriteWithoutBlocking(int aFd);
|
||||
virtual void OnError();
|
||||
|
||||
static void DefaultConfig();
|
||||
|
||||
private:
|
||||
bool OpenSocket();
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include "nsISupports.idl"
|
||||
#include "nsIVolumeStat.idl"
|
||||
|
||||
[scriptable, uuid(9B5E27F4-601C-11E4-B541-3E2D1D5D46B0)]
|
||||
[scriptable, uuid(946B5334-6EC9-11E4-8689-F3061E5D46B0)]
|
||||
interface nsIVolume : nsISupports
|
||||
{
|
||||
// These MUST match the states from android's system/vold/Volume.h header
|
||||
@ -86,6 +86,13 @@ interface nsIVolume : nsISupports
|
||||
|
||||
// Whether this is a fake volume.
|
||||
readonly attribute boolean isFake;
|
||||
|
||||
// Whether this is a removable volume
|
||||
readonly attribute boolean isRemovable;
|
||||
|
||||
// Whether this is a hot-swappable volume
|
||||
readonly attribute boolean isHotSwappable;
|
||||
|
||||
};
|
||||
|
||||
%{C++
|
||||
|
@ -59,7 +59,9 @@ nsVolume::nsVolume(const Volume* aVolume)
|
||||
mIsMediaPresent(aVolume->MediaPresent()),
|
||||
mIsSharing(aVolume->IsSharing()),
|
||||
mIsFormatting(aVolume->IsFormatting()),
|
||||
mIsUnmounting(aVolume->IsUnmounting())
|
||||
mIsUnmounting(aVolume->IsUnmounting()),
|
||||
mIsRemovable(aVolume->IsRemovable()),
|
||||
mIsHotSwappable(aVolume->IsHotSwappable())
|
||||
{
|
||||
}
|
||||
|
||||
@ -119,6 +121,18 @@ bool nsVolume::Equals(nsIVolume* aVolume)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isRemovable;
|
||||
aVolume->GetIsRemovable(&isRemovable);
|
||||
if (mIsRemovable != isRemovable) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isHotSwappable;
|
||||
aVolume->GetIsHotSwappable(&isHotSwappable);
|
||||
if (mIsHotSwappable != isHotSwappable) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -200,6 +214,18 @@ NS_IMETHODIMP nsVolume::GetIsFake(bool *aIsFake)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsVolume::GetIsRemovable(bool *aIsRemovable)
|
||||
{
|
||||
*aIsRemovable = mIsRemovable;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsVolume::GetIsHotSwappable(bool *aIsHotSwappable)
|
||||
{
|
||||
*aIsHotSwappable = mIsHotSwappable;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsVolume::Format()
|
||||
{
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
|
||||
@ -277,11 +303,12 @@ nsVolume::LogState() const
|
||||
{
|
||||
if (mState == nsIVolume::STATE_MOUNTED) {
|
||||
LOG("nsVolume: %s state %s @ '%s' gen %d locked %d fake %d "
|
||||
"media %d sharing %d formatting %d unmounting %d",
|
||||
"media %d sharing %d formatting %d unmounting %d removable %d hotswappable %d",
|
||||
NameStr().get(), StateStr(), MountPointStr().get(),
|
||||
MountGeneration(), (int)IsMountLocked(), (int)IsFake(),
|
||||
(int)IsMediaPresent(), (int)IsSharing(),
|
||||
(int)IsFormatting(), (int)IsUnmounting());
|
||||
(int)IsFormatting(), (int)IsUnmounting(),
|
||||
(int)IsRemovable(), (int)IsHotSwappable());
|
||||
return;
|
||||
}
|
||||
|
||||
@ -300,6 +327,8 @@ void nsVolume::Set(nsIVolume* aVolume)
|
||||
aVolume->GetIsSharing(&mIsSharing);
|
||||
aVolume->GetIsFormatting(&mIsFormatting);
|
||||
aVolume->GetIsUnmounting(&mIsUnmounting);
|
||||
aVolume->GetIsRemovable(&mIsRemovable);
|
||||
aVolume->GetIsHotSwappable(&mIsHotSwappable);
|
||||
|
||||
int32_t volMountGeneration;
|
||||
aVolume->GetMountGeneration(&volMountGeneration);
|
||||
@ -377,6 +406,24 @@ nsVolume::SetIsFake(bool aIsFake)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsVolume::SetIsRemovable(bool aIsRemovable)
|
||||
{
|
||||
mIsRemovable = aIsRemovable;
|
||||
if (!mIsRemovable) {
|
||||
mIsHotSwappable = false;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsVolume::SetIsHotSwappable(bool aIsHotSwappable)
|
||||
{
|
||||
mIsHotSwappable = aIsHotSwappable;
|
||||
if (mIsHotSwappable) {
|
||||
mIsRemovable = true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsVolume::SetState(int32_t aState)
|
||||
{
|
||||
|
@ -31,7 +31,8 @@ public:
|
||||
const int32_t& aState, const int32_t& aMountGeneration,
|
||||
const bool& aIsMediaPresent, const bool& aIsSharing,
|
||||
const bool& aIsFormatting, const bool& aIsFake,
|
||||
const bool& aIsUnmounting)
|
||||
const bool& aIsUnmounting, const bool& aIsRemovable,
|
||||
const bool& aIsHotSwappable)
|
||||
: mName(aName),
|
||||
mMountPoint(aMountPoint),
|
||||
mState(aState),
|
||||
@ -41,7 +42,9 @@ public:
|
||||
mIsMediaPresent(aIsMediaPresent),
|
||||
mIsSharing(aIsSharing),
|
||||
mIsFormatting(aIsFormatting),
|
||||
mIsUnmounting(aIsUnmounting)
|
||||
mIsUnmounting(aIsUnmounting),
|
||||
mIsRemovable(aIsRemovable),
|
||||
mIsHotSwappable(aIsHotSwappable)
|
||||
{
|
||||
}
|
||||
|
||||
@ -56,7 +59,9 @@ public:
|
||||
mIsMediaPresent(false),
|
||||
mIsSharing(false),
|
||||
mIsFormatting(false),
|
||||
mIsUnmounting(false)
|
||||
mIsUnmounting(false),
|
||||
mIsRemovable(false),
|
||||
mIsHotSwappable(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -82,6 +87,8 @@ public:
|
||||
bool IsSharing() const { return mIsSharing; }
|
||||
bool IsFormatting() const { return mIsFormatting; }
|
||||
bool IsUnmounting() const { return mIsUnmounting; }
|
||||
bool IsRemovable() const { return mIsRemovable; }
|
||||
bool IsHotSwappable() const { return mIsHotSwappable; }
|
||||
|
||||
typedef nsTArray<nsRefPtr<nsVolume> > Array;
|
||||
|
||||
@ -93,6 +100,8 @@ private:
|
||||
void UpdateMountLock(bool aMountLocked);
|
||||
|
||||
void SetIsFake(bool aIsFake);
|
||||
void SetIsRemovable(bool aIsRemovable);
|
||||
void SetIsHotSwappable(bool aIsHotSwappble);
|
||||
void SetState(int32_t aState);
|
||||
static void FormatVolumeIOThread(const nsCString& aVolume);
|
||||
static void MountVolumeIOThread(const nsCString& aVolume);
|
||||
@ -108,6 +117,8 @@ private:
|
||||
bool mIsSharing;
|
||||
bool mIsFormatting;
|
||||
bool mIsUnmounting;
|
||||
bool mIsRemovable;
|
||||
bool mIsHotSwappable;
|
||||
};
|
||||
|
||||
} // system
|
||||
|
@ -210,7 +210,9 @@ nsVolumeService::CreateOrGetVolumeByPath(const nsAString& aPath, nsIVolume** aRe
|
||||
false /* isSharing */,
|
||||
false /* isFormatting */,
|
||||
true /* isFake */,
|
||||
false /* isUnmounting*/);
|
||||
false /* isUnmounting */,
|
||||
false /* isRemovable */,
|
||||
false /* isHotSwappable*/);
|
||||
vol.forget(aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
@ -272,6 +274,8 @@ nsVolumeService::GetVolumesForIPC(nsTArray<VolumeInfo>* aResult)
|
||||
volInfo->isFormatting() = vol->mIsFormatting;
|
||||
volInfo->isFake() = vol->mIsFake;
|
||||
volInfo->isUnmounting() = vol->mIsUnmounting;
|
||||
volInfo->isRemovable() = vol->mIsRemovable;
|
||||
volInfo->isHotSwappable() = vol->mIsHotSwappable;
|
||||
}
|
||||
}
|
||||
|
||||
@ -300,7 +304,9 @@ nsVolumeService::GetVolumesFromParent()
|
||||
volInfo.isSharing(),
|
||||
volInfo.isFormatting(),
|
||||
volInfo.isFake(),
|
||||
volInfo.isUnmounting());
|
||||
volInfo.isUnmounting(),
|
||||
volInfo.isRemovable(),
|
||||
volInfo.isHotSwappable());
|
||||
UpdateVolume(vol, false);
|
||||
}
|
||||
}
|
||||
@ -425,7 +431,9 @@ nsVolumeService::CreateFakeVolume(const nsAString& name, const nsAString& path)
|
||||
false /* isSharing */,
|
||||
false /* isFormatting */,
|
||||
true /* isFake */,
|
||||
false /* isUnmounting */);
|
||||
false /* isUnmounting */,
|
||||
false /* isRemovable */,
|
||||
false /* isHotSwappable */);
|
||||
vol->LogState();
|
||||
UpdateVolume(vol.get());
|
||||
return NS_OK;
|
||||
@ -475,11 +483,12 @@ public:
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
DBG("UpdateVolumeRunnable::Run '%s' state %s gen %d locked %d "
|
||||
"media %d sharing %d formatting %d unmounting %d",
|
||||
"media %d sharing %d formatting %d unmounting %d removable %d hotswappable %d",
|
||||
mVolume->NameStr().get(), mVolume->StateStr(),
|
||||
mVolume->MountGeneration(), (int)mVolume->IsMountLocked(),
|
||||
(int)mVolume->IsMediaPresent(), mVolume->IsSharing(),
|
||||
mVolume->IsFormatting(), mVolume->IsUnmounting());
|
||||
mVolume->IsFormatting(), mVolume->IsUnmounting(),
|
||||
(int)mVolume->IsRemovable(), (int)mVolume->IsHotSwappable());
|
||||
|
||||
mVolumeService->UpdateVolume(mVolume);
|
||||
mVolumeService = nullptr;
|
||||
@ -496,11 +505,12 @@ void
|
||||
nsVolumeService::UpdateVolumeIOThread(const Volume* aVolume)
|
||||
{
|
||||
DBG("UpdateVolumeIOThread: Volume '%s' state %s mount '%s' gen %d locked %d "
|
||||
"media %d sharing %d formatting %d unmounting %d",
|
||||
"media %d sharing %d formatting %d unmounting %d removable %d hotswappable %d",
|
||||
aVolume->NameStr(), aVolume->StateStr(), aVolume->MountPoint().get(),
|
||||
aVolume->MountGeneration(), (int)aVolume->IsMountLocked(),
|
||||
(int)aVolume->MediaPresent(), (int)aVolume->IsSharing(),
|
||||
(int)aVolume->IsFormatting(), (int)mVolume->IsUnmounting());
|
||||
(int)aVolume->IsFormatting(), (int)mVolume->IsUnmounting(),
|
||||
(int)aVolume->IsRemovable(), (int)mVolume->IsHotSwappable());
|
||||
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
|
||||
NS_DispatchToMainThread(new UpdateVolumeRunnable(this, aVolume));
|
||||
}
|
||||
|
@ -82,6 +82,9 @@ interface DeviceStorage : EventTarget {
|
||||
// for storing new files.
|
||||
readonly attribute boolean default;
|
||||
|
||||
// Indicates if the storage area denoted by storageName is removable
|
||||
readonly attribute boolean isRemovable;
|
||||
|
||||
[NewObject, Throws]
|
||||
// XXXbz what type does this really return?
|
||||
Promise<any> getRoot();
|
||||
|
Loading…
Reference in New Issue
Block a user