Merge with mozilla-central

This commit is contained in:
Ed Morley 2013-04-23 12:17:57 +01:00
commit 69699beaa1
15 changed files with 390 additions and 277 deletions

View File

@ -91,7 +91,7 @@ DirectoryProvider.prototype = {
if (!Services.volumeService) { if (!Services.volumeService) {
return false; return false;
} }
let volume = Services.volumeService.getVolumeByPath(volumePath); let volume = Services.volumeService.createOrGetVolumeByPath(volumePath);
if (!volume || volume.state !== Ci.nsIVolume.STATE_MOUNTED) { if (!volume || volume.state !== Ci.nsIVolume.STATE_MOUNTED) {
return false; return false;
} }
@ -201,7 +201,7 @@ DirectoryProvider.prototype = {
} }
if (Services.volumeService) { if (Services.volumeService) {
let extVolume = Services.volumeService.getVolumeByPath(path); let extVolume = Services.volumeService.createOrGetVolumeByPath(path);
if (!extVolume) { if (!extVolume) {
path = LOCAL_DIR; path = LOCAL_DIR;
} }

View File

@ -29,7 +29,9 @@
#include "nsIOutputStream.h" #include "nsIOutputStream.h"
#include "nsNetUtil.h" #include "nsNetUtil.h"
#define TARGET_FOLDER "/sdcard/downloads/bluetooth/" #define TARGET_ROOT "/sdcard/"
#define TARGET_SUBDIR "downloads/bluetooth/"
#define TARGET_FOLDER TARGET_ROOT TARGET_SUBDIR
USING_BLUETOOTH_NAMESPACE USING_BLUETOOTH_NAMESPACE
using namespace mozilla; using namespace mozilla;
@ -561,6 +563,11 @@ BluetoothOppManager::CreateFile()
*/ */
f->GetLeafName(sFileName); f->GetLeafName(sFileName);
nsString fullFileName;
f->GetPath(fullFileName);
MOZ_ASSERT(StringBeginsWith(fullFileName, NS_LITERAL_STRING(TARGET_ROOT)));
nsDependentSubstring storagePath = Substring(fullFileName, strlen(TARGET_ROOT));
mDsFile = nullptr; mDsFile = nullptr;
nsCOMPtr<nsIMIMEService> mimeSvc = do_GetService(NS_MIMESERVICE_CONTRACTID); nsCOMPtr<nsIMIMEService> mimeSvc = do_GetService(NS_MIMESERVICE_CONTRACTID);
@ -570,11 +577,11 @@ BluetoothOppManager::CreateFile()
if (NS_SUCCEEDED(rv)) { if (NS_SUCCEEDED(rv)) {
if (StringBeginsWith(mimeType, NS_LITERAL_CSTRING("image/"))) { if (StringBeginsWith(mimeType, NS_LITERAL_CSTRING("image/"))) {
mDsFile = new DeviceStorageFile(NS_LITERAL_STRING("pictures"), f); mDsFile = new DeviceStorageFile(NS_LITERAL_STRING("pictures"), storagePath);
} else if (StringBeginsWith(mimeType, NS_LITERAL_CSTRING("video/"))) { } else if (StringBeginsWith(mimeType, NS_LITERAL_CSTRING("video/"))) {
mDsFile = new DeviceStorageFile(NS_LITERAL_STRING("movies"), f); mDsFile = new DeviceStorageFile(NS_LITERAL_STRING("movies"), storagePath);
} else if (StringBeginsWith(mimeType, NS_LITERAL_CSTRING("audio/"))) { } else if (StringBeginsWith(mimeType, NS_LITERAL_CSTRING("audio/"))) {
mDsFile = new DeviceStorageFile(NS_LITERAL_STRING("music"), f); mDsFile = new DeviceStorageFile(NS_LITERAL_STRING("music"), storagePath);
} else { } else {
NS_WARNING("Couldn't recognize the mimetype of received file."); NS_WARNING("Couldn't recognize the mimetype of received file.");
} }

View File

@ -905,7 +905,8 @@ nsGonkCameraControl::StartRecordingImpl(StartRecordingTask* aStartRecording)
*/ */
nsCOMPtr<nsIFile> filename = aStartRecording->mFolder; nsCOMPtr<nsIFile> filename = aStartRecording->mFolder;
filename->AppendRelativePath(aStartRecording->mFilename); filename->AppendRelativePath(aStartRecording->mFilename);
mVideoFile = new DeviceStorageFile(NS_LITERAL_STRING("videos"), filename); mVideoFile = new DeviceStorageFile(NS_LITERAL_STRING("videos"),
aStartRecording->mFilename);
nsAutoCString nativeFilename; nsAutoCString nativeFilename;
filename->GetNativePath(nativeFilename); filename->GetNativePath(nativeFilename);

View File

@ -20,10 +20,18 @@ public:
nsCOMPtr<nsIFile> mFile; nsCOMPtr<nsIFile> mFile;
nsString mPath; nsString mPath;
nsString mStorageType; nsString mStorageType;
nsString mRootDir;
bool mEditable; bool mEditable;
DeviceStorageFile(const nsAString& aStorageType, nsIFile* aFile, const nsAString& aPath); // Used when the path will be set later via SetPath.
DeviceStorageFile(const nsAString& aStorageType, nsIFile* aFile); DeviceStorageFile(const nsAString& aStorageType);
// Used for non-enumeration purposes.
DeviceStorageFile(const nsAString& aStorageType, const nsAString& aPath);
// Used for enumerations. When you call Enumerate, you can pass in a directory to enumerate
// and the results that are returned are relative to that directory, files related to an
// enumeration need to know the "root of the enumeration" directory.
DeviceStorageFile(const nsAString& aStorageType, const nsAString& aRootDir, const nsAString& aPath);
void SetPath(const nsAString& aPath); void SetPath(const nsAString& aPath);
void SetEditable(bool aEditable); void SetEditable(bool aEditable);
@ -32,6 +40,7 @@ public:
// we want to make sure that the names of file can't reach // we want to make sure that the names of file can't reach
// outside of the type of storage the user asked for. // outside of the type of storage the user asked for.
bool IsSafePath(); bool IsSafePath();
bool IsSafePath(const nsAString& aPath);
nsresult Remove(); nsresult Remove();
nsresult Write(nsIInputStream* aInputStream); nsresult Write(nsIInputStream* aInputStream);
@ -40,10 +49,13 @@ public:
void collectFilesInternal(nsTArray<nsRefPtr<DeviceStorageFile> > &aFiles, PRTime aSince, nsAString& aRootPath); void collectFilesInternal(nsTArray<nsRefPtr<DeviceStorageFile> > &aFiles, PRTime aSince, nsAString& aRootPath);
static void DirectoryDiskUsage(nsIFile* aFile, uint64_t* aSoFar, const nsAString& aStorageType); static void DirectoryDiskUsage(nsIFile* aFile, uint64_t* aSoFar, const nsAString& aStorageType);
static void GetRootDirectoryForType(const nsAString& aType,
const nsAString& aVolName,
nsIFile** aFile);
private: private:
void Init(const nsAString& aStorageType);
void NormalizeFilePath(); void NormalizeFilePath();
void AppendRelativePath(); void AppendRelativePath(const nsAString& aPath);
}; };
/* /*

View File

@ -100,14 +100,9 @@ DeviceStorageRequestChild::Recv__delete__(const DeviceStorageResponseValue& aVal
uint32_t count = r.paths().Length(); uint32_t count = r.paths().Length();
for (uint32_t i = 0; i < count; i++) { for (uint32_t i = 0; i < count; i++) {
nsCOMPtr<nsIFile> f; nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(r.type(),
nsresult rv = NS_NewLocalFile(r.paths()[i].fullpath(), false, getter_AddRefs(f)); r.relpath(),
if (NS_FAILED(rv)) { r.paths()[i].name());
continue;
}
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(r.paths()[i].type(), f);
dsf->SetPath(r.paths()[i].name());
cursor->mFiles.AppendElement(dsf); cursor->mFiles.AppendElement(dsf);
} }

View File

@ -34,10 +34,7 @@ DeviceStorageRequestParent::Dispatch()
{ {
DeviceStorageAddParams p = mParams; DeviceStorageAddParams p = mParams;
nsCOMPtr<nsIFile> f; nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(p.type(), p.relpath());
NS_NewLocalFile(p.fullpath(), false, getter_AddRefs(f));
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(p.type(), f);
BlobParent* bp = static_cast<BlobParent*>(p.blobParent()); BlobParent* bp = static_cast<BlobParent*>(p.blobParent());
nsCOMPtr<nsIDOMBlob> blob = bp->GetBlob(); nsCOMPtr<nsIDOMBlob> blob = bp->GetBlob();
@ -56,12 +53,7 @@ DeviceStorageRequestParent::Dispatch()
case DeviceStorageParams::TDeviceStorageGetParams: case DeviceStorageParams::TDeviceStorageGetParams:
{ {
DeviceStorageGetParams p = mParams; DeviceStorageGetParams p = mParams;
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(p.type(), p.rootDir(), p.relpath());
nsCOMPtr<nsIFile> f;
NS_NewLocalFile(p.fullpath(), false, getter_AddRefs(f));
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(p.type(), f);
dsf->SetPath(p.name());
nsRefPtr<CancelableRunnable> r = new ReadFileEvent(this, dsf); nsRefPtr<CancelableRunnable> r = new ReadFileEvent(this, dsf);
nsCOMPtr<nsIEventTarget> target = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID); nsCOMPtr<nsIEventTarget> target = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
@ -74,10 +66,7 @@ DeviceStorageRequestParent::Dispatch()
{ {
DeviceStorageDeleteParams p = mParams; DeviceStorageDeleteParams p = mParams;
nsCOMPtr<nsIFile> f; nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(p.type(), p.relpath());
NS_NewLocalFile(p.fullpath(), false, getter_AddRefs(f));
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(p.type(), f);
nsRefPtr<CancelableRunnable> r = new DeleteFileEvent(this, dsf); nsRefPtr<CancelableRunnable> r = new DeleteFileEvent(this, dsf);
nsCOMPtr<nsIEventTarget> target = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID); nsCOMPtr<nsIEventTarget> target = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
@ -90,10 +79,7 @@ DeviceStorageRequestParent::Dispatch()
{ {
DeviceStorageFreeSpaceParams p = mParams; DeviceStorageFreeSpaceParams p = mParams;
nsCOMPtr<nsIFile> f; nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(p.type(), p.relpath());
NS_NewLocalFile(p.fullpath(), false, getter_AddRefs(f));
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(p.type(), f);
nsRefPtr<FreeSpaceFileEvent> r = new FreeSpaceFileEvent(this, dsf); nsRefPtr<FreeSpaceFileEvent> r = new FreeSpaceFileEvent(this, dsf);
nsCOMPtr<nsIEventTarget> target = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID); nsCOMPtr<nsIEventTarget> target = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
@ -106,10 +92,7 @@ DeviceStorageRequestParent::Dispatch()
{ {
DeviceStorageUsedSpaceParams p = mParams; DeviceStorageUsedSpaceParams p = mParams;
nsCOMPtr<nsIFile> f; nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(p.type(), p.relpath());
NS_NewLocalFile(p.fullpath(), false, getter_AddRefs(f));
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(p.type(), f);
nsRefPtr<UsedSpaceFileEvent> r = new UsedSpaceFileEvent(this, dsf); nsRefPtr<UsedSpaceFileEvent> r = new UsedSpaceFileEvent(this, dsf);
nsCOMPtr<nsIEventTarget> target = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID); nsCOMPtr<nsIEventTarget> target = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
@ -121,7 +104,9 @@ DeviceStorageRequestParent::Dispatch()
case DeviceStorageParams::TDeviceStorageAvailableParams: case DeviceStorageParams::TDeviceStorageAvailableParams:
{ {
DeviceStorageAvailableParams p = mParams; DeviceStorageAvailableParams p = mParams;
nsRefPtr<PostAvailableResultEvent> r = new PostAvailableResultEvent(this, p.fullpath());
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(p.type(), p.relpath());
nsRefPtr<PostAvailableResultEvent> r = new PostAvailableResultEvent(this, dsf);
NS_DispatchToMainThread(r); NS_DispatchToMainThread(r);
break; break;
} }
@ -129,11 +114,7 @@ DeviceStorageRequestParent::Dispatch()
case DeviceStorageParams::TDeviceStorageEnumerationParams: case DeviceStorageParams::TDeviceStorageEnumerationParams:
{ {
DeviceStorageEnumerationParams p = mParams; DeviceStorageEnumerationParams p = mParams;
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(p.type(), p.relpath(), NS_LITERAL_STRING(""));
nsCOMPtr<nsIFile> f;
NS_NewLocalFile(p.fullpath(), false, getter_AddRefs(f));
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(p.type(), f);
nsRefPtr<CancelableRunnable> r = new EnumerateFileEvent(this, dsf, p.since()); nsRefPtr<CancelableRunnable> r = new EnumerateFileEvent(this, dsf, p.since());
nsCOMPtr<nsIEventTarget> target = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID); nsCOMPtr<nsIEventTarget> target = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
@ -382,8 +363,12 @@ DeviceStorageRequestParent::PostBlobSuccessEvent::CancelableRun() {
} }
DeviceStorageRequestParent::PostEnumerationSuccessEvent::PostEnumerationSuccessEvent(DeviceStorageRequestParent* aParent, DeviceStorageRequestParent::PostEnumerationSuccessEvent::PostEnumerationSuccessEvent(DeviceStorageRequestParent* aParent,
const nsAString& aStorageType,
const nsAString& aRelPath,
InfallibleTArray<DeviceStorageFileValue>& aPaths) InfallibleTArray<DeviceStorageFileValue>& aPaths)
: CancelableRunnable(aParent) : CancelableRunnable(aParent)
, mStorageType(aStorageType)
, mRelPath(aRelPath)
, mPaths(aPaths) , mPaths(aPaths)
{ {
} }
@ -394,7 +379,7 @@ nsresult
DeviceStorageRequestParent::PostEnumerationSuccessEvent::CancelableRun() { DeviceStorageRequestParent::PostEnumerationSuccessEvent::CancelableRun() {
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
EnumerationResponse response(mPaths); EnumerationResponse response(mStorageType, mRelPath, mPaths);
unused << mParent->Send__delete__(mParent, response); unused << mParent->Send__delete__(mParent, response);
return NS_OK; return NS_OK;
} }
@ -621,13 +606,11 @@ DeviceStorageRequestParent::EnumerateFileEvent::CancelableRun()
uint32_t count = files.Length(); uint32_t count = files.Length();
for (uint32_t i = 0; i < count; i++) { for (uint32_t i = 0; i < count; i++) {
nsString fullpath; DeviceStorageFileValue dsvf(files[i]->mPath);
files[i]->mFile->GetPath(fullpath);
DeviceStorageFileValue dsvf(mFile->mStorageType, files[i]->mPath, fullpath);
values.AppendElement(dsvf); values.AppendElement(dsvf);
} }
r = new PostEnumerationSuccessEvent(mParent, values); r = new PostEnumerationSuccessEvent(mParent, mFile->mStorageType, mFile->mRootDir, values);
NS_DispatchToMainThread(r); NS_DispatchToMainThread(r);
return NS_OK; return NS_OK;
} }
@ -655,9 +638,9 @@ DeviceStorageRequestParent::PostPathResultEvent::CancelableRun()
} }
DeviceStorageRequestParent::PostAvailableResultEvent::PostAvailableResultEvent(DeviceStorageRequestParent* aParent, DeviceStorageRequestParent::PostAvailableResultEvent::PostAvailableResultEvent(DeviceStorageRequestParent* aParent,
const nsAString &aPath) DeviceStorageFile* aFile)
: CancelableRunnable(aParent) : CancelableRunnable(aParent)
, mPath(aPath) , mFile(aFile)
{ {
} }
@ -673,7 +656,7 @@ DeviceStorageRequestParent::PostAvailableResultEvent::CancelableRun()
nsString state; nsString state;
state.Assign(NS_LITERAL_STRING("available")); state.Assign(NS_LITERAL_STRING("available"));
#ifdef MOZ_WIDGET_GONK #ifdef MOZ_WIDGET_GONK
nsresult rv = GetSDCardStatus(mPath, state); nsresult rv = GetSDCardStatus(mFile->mPath, state);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
state.Assign(NS_LITERAL_STRING("unavailable")); state.Assign(NS_LITERAL_STRING("unavailable"));
} }

View File

@ -105,10 +105,15 @@ private:
class PostEnumerationSuccessEvent : public CancelableRunnable class PostEnumerationSuccessEvent : public CancelableRunnable
{ {
public: public:
PostEnumerationSuccessEvent(DeviceStorageRequestParent* aParent, InfallibleTArray<DeviceStorageFileValue>& aPaths); PostEnumerationSuccessEvent(DeviceStorageRequestParent* aParent,
const nsAString& aStorageType,
const nsAString& aRelPath,
InfallibleTArray<DeviceStorageFileValue>& aPaths);
virtual ~PostEnumerationSuccessEvent(); virtual ~PostEnumerationSuccessEvent();
virtual nsresult CancelableRun(); virtual nsresult CancelableRun();
private: private:
const nsString mStorageType;
const nsString mRelPath;
InfallibleTArray<DeviceStorageFileValue> mPaths; InfallibleTArray<DeviceStorageFileValue> mPaths;
}; };
@ -211,11 +216,11 @@ private:
class PostAvailableResultEvent : public CancelableRunnable class PostAvailableResultEvent : public CancelableRunnable
{ {
public: public:
PostAvailableResultEvent(DeviceStorageRequestParent* aParent, const nsAString& aPath); PostAvailableResultEvent(DeviceStorageRequestParent* aParent, DeviceStorageFile* aFile);
virtual ~PostAvailableResultEvent(); virtual ~PostAvailableResultEvent();
virtual nsresult CancelableRun(); virtual nsresult CancelableRun();
private: private:
nsString mPath; nsRefPtr<DeviceStorageFile> mFile;
}; };
protected: protected:

View File

@ -27,13 +27,13 @@ struct BlobResponse
struct DeviceStorageFileValue struct DeviceStorageFileValue
{ {
nsString type;
nsString name; nsString name;
nsString fullpath;
}; };
struct EnumerationResponse struct EnumerationResponse
{ {
nsString type;
nsString relpath;
DeviceStorageFileValue[] paths; DeviceStorageFileValue[] paths;
}; };

View File

@ -67,6 +67,21 @@ using namespace mozilla::dom::devicestorage;
#include "nsDirectoryServiceDefs.h" #include "nsDirectoryServiceDefs.h"
class GlobalDirs : public RefCounted<GlobalDirs>
{
public:
#if !defined(MOZ_WIDGET_GONK)
nsCOMPtr<nsIFile> pictures;
nsCOMPtr<nsIFile> videos;
nsCOMPtr<nsIFile> music;
nsCOMPtr<nsIFile> apps;
nsCOMPtr<nsIFile> sdcard;
#endif
nsCOMPtr<nsIFile> temp;
};
static StaticRefPtr<GlobalDirs> sDirs;
nsAutoPtr<DeviceStorageTypeChecker> DeviceStorageTypeChecker::sDeviceStorageTypeChecker; nsAutoPtr<DeviceStorageTypeChecker> DeviceStorageTypeChecker::sDeviceStorageTypeChecker;
DeviceStorageTypeChecker::DeviceStorageTypeChecker() DeviceStorageTypeChecker::DeviceStorageTypeChecker()
@ -311,35 +326,182 @@ private:
}; };
DeviceStorageFile::DeviceStorageFile(const nsAString& aStorageType, DeviceStorageFile::DeviceStorageFile(const nsAString& aStorageType,
nsIFile* aFile, const nsAString& aRootDir,
const nsAString& aPath)
: mPath(aPath)
, mStorageType(aStorageType)
, mRootDir(aRootDir)
, mEditable(false)
{
Init(aStorageType);
AppendRelativePath(mRootDir);
if (!mPath.EqualsLiteral("")) {
AppendRelativePath(mPath);
}
NormalizeFilePath();
}
DeviceStorageFile::DeviceStorageFile(const nsAString& aStorageType,
const nsAString& aPath) const nsAString& aPath)
: mPath(aPath) : mPath(aPath)
, mStorageType(aStorageType) , mStorageType(aStorageType)
, mEditable(false) , mEditable(false)
{ {
NS_ASSERTION(aFile, "Must not create a DeviceStorageFile with a null nsIFile"); Init(aStorageType);
// always take a clone AppendRelativePath(aPath);
nsCOMPtr<nsIFile> file;
aFile->Clone(getter_AddRefs(mFile));
AppendRelativePath();
NormalizeFilePath(); NormalizeFilePath();
}
DeviceStorageFile::DeviceStorageFile(const nsAString& aStorageType)
: mStorageType(aStorageType)
, mEditable(false)
{
Init(aStorageType);
}
void
DeviceStorageFile::Init(const nsAString& aStorageType)
{
// The hard-coded sdcard below will change as part of bug 858416
DeviceStorageFile::GetRootDirectoryForType(aStorageType,
NS_LITERAL_STRING("sdcard"),
getter_AddRefs(mFile));
DebugOnly<DeviceStorageTypeChecker*> typeChecker = DeviceStorageTypeChecker::CreateOrGet(); DebugOnly<DeviceStorageTypeChecker*> typeChecker = DeviceStorageTypeChecker::CreateOrGet();
NS_ASSERTION(typeChecker, "DeviceStorageTypeChecker is null"); NS_ASSERTION(typeChecker, "DeviceStorageTypeChecker is null");
} }
DeviceStorageFile::DeviceStorageFile(const nsAString& aStorageType, nsIFile* aFile) static void
: mStorageType(aStorageType) InitDirs()
, mEditable(false)
{ {
NS_ASSERTION(aFile, "Must not create a DeviceStorageFile with a null nsIFile"); if (sDirs) {
// always take a clone return;
nsCOMPtr<nsIFile> file; }
aFile->Clone(getter_AddRefs(mFile)); NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
sDirs = new GlobalDirs;
ClearOnShutdown(&sDirs);
DebugOnly<DeviceStorageTypeChecker*> typeChecker = DeviceStorageTypeChecker::CreateOrGet(); nsCOMPtr<nsIProperties> dirService = do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID);
NS_ASSERTION(typeChecker, "DeviceStorageTypeChecker is null"); NS_ASSERTION(dirService, "Must have directory service");
#if !defined(MOZ_WIDGET_GONK)
#if defined (MOZ_WIDGET_COCOA)
dirService->Get(NS_OSX_PICTURE_DOCUMENTS_DIR, NS_GET_IID(nsIFile), getter_AddRefs(sDirs->pictures));
dirService->Get(NS_OSX_MOVIE_DOCUMENTS_DIR, NS_GET_IID(nsIFile), getter_AddRefs(sDirs->videos));
dirService->Get(NS_OSX_MUSIC_DOCUMENTS_DIR, NS_GET_IID(nsIFile), getter_AddRefs(sDirs->music));
#elif defined (XP_UNIX)
dirService->Get(NS_UNIX_XDG_PICTURES_DIR, NS_GET_IID(nsIFile), getter_AddRefs(sDirs->pictures));
dirService->Get(NS_UNIX_XDG_VIDEOS_DIR, NS_GET_IID(nsIFile), getter_AddRefs(sDirs->videos));
dirService->Get(NS_UNIX_XDG_MUSIC_DIR, NS_GET_IID(nsIFile), getter_AddRefs(sDirs->music));
#elif defined (XP_WIN)
dirService->Get(NS_WIN_PICTURES_DIR, NS_GET_IID(nsIFile), getter_AddRefs(sDirs->pictures));
dirService->Get(NS_WIN_VIDEOS_DIR, NS_GET_IID(nsIFile), getter_AddRefs(sDirs->videos));
dirService->Get(NS_WIN_MUSIC_DIR, NS_GET_IID(nsIFile), getter_AddRefs(sDirs->music));
#endif
dirService->Get(NS_APP_USER_PROFILE_50_DIR, NS_GET_IID(nsIFile), getter_AddRefs(sDirs->apps));
if (sDirs->apps) {
sDirs->apps->AppendRelativeNativePath(NS_LITERAL_CSTRING("webapps"));
}
// Eventually, on desktop, we want to do something smarter -- for example,
// detect when an sdcard is inserted, and use that instead of this.
dirService->Get(NS_APP_USER_PROFILE_50_DIR, NS_GET_IID(nsIFile), getter_AddRefs(sDirs->sdcard));
if (sDirs->sdcard) {
sDirs->sdcard->AppendRelativeNativePath(NS_LITERAL_CSTRING("fake-sdcard"));
}
#endif // !MOZ_WIDGET_GONK
if (mozilla::Preferences::GetBool("device.storage.testing", false)) {
dirService->Get(NS_OS_TEMP_DIR, NS_GET_IID(nsIFile), getter_AddRefs(sDirs->temp));
if (sDirs->temp) {
sDirs->temp->AppendRelativeNativePath(NS_LITERAL_CSTRING("device-storage-testing"));
sDirs->temp->Create(nsIFile::DIRECTORY_TYPE, 0777);
sDirs->temp->Normalize();
}
}
}
void
DeviceStorageFile::GetRootDirectoryForType(const nsAString &aType, const
nsAString &aVolName,
nsIFile** aFile)
{
nsCOMPtr<nsIFile> f;
InitDirs();
#ifdef MOZ_WIDGET_GONK
nsString volMountPoint(NS_LITERAL_STRING("/sdcard"));
if (!aVolName.EqualsLiteral("")) {
nsCOMPtr<nsIVolumeService> vs = do_GetService(NS_VOLUMESERVICE_CONTRACTID);
if (vs) {
nsresult rv;
nsCOMPtr<nsIVolume> vol;
rv = vs->GetVolumeByName(aVolName, getter_AddRefs(vol));
if (NS_SUCCEEDED(rv)) {
vol->GetMountPoint(volMountPoint);
}
}
}
#endif
// Picture directory
if (aType.EqualsLiteral(DEVICESTORAGE_PICTURES)) {
#ifdef MOZ_WIDGET_GONK
NS_NewLocalFile(volMountPoint, false, getter_AddRefs(f));
#else
f = sDirs->pictures;
#endif
}
// Video directory
else if (aType.EqualsLiteral(DEVICESTORAGE_VIDEOS)) {
#ifdef MOZ_WIDGET_GONK
NS_NewLocalFile(volMountPoint, false, getter_AddRefs(f));
#else
f = sDirs->videos;
#endif
}
// Music directory
else if (aType.EqualsLiteral(DEVICESTORAGE_MUSIC)) {
#ifdef MOZ_WIDGET_GONK
NS_NewLocalFile(volMountPoint, false, getter_AddRefs(f));
#else
f = sDirs->music;
#endif
}
// Apps directory
else if (aType.EqualsLiteral(DEVICESTORAGE_APPS)) {
#ifdef MOZ_WIDGET_GONK
NS_NewLocalFile(NS_LITERAL_STRING("/data"), false, getter_AddRefs(f));
#else
f = sDirs->apps;
#endif
}
// default SDCard
else if (aType.EqualsLiteral(DEVICESTORAGE_SDCARD)) {
#ifdef MOZ_WIDGET_GONK
NS_NewLocalFile(volMountPoint, false, getter_AddRefs(f));
#else
f = sDirs->sdcard;
#endif
}
// in testing, we default all device storage types to a temp directory
if (f && mozilla::Preferences::GetBool("device.storage.testing", false)) {
f = sDirs->temp;
}
if (f) {
f->Clone(aFile);
} else {
*aFile = nullptr;
}
} }
void void
@ -357,21 +519,27 @@ DeviceStorageFile::SetEditable(bool aEditable) {
// outside of the type of storage the user asked for. // outside of the type of storage the user asked for.
bool bool
DeviceStorageFile::IsSafePath() DeviceStorageFile::IsSafePath()
{
return IsSafePath(mRootDir) && IsSafePath(mPath);
}
bool
DeviceStorageFile::IsSafePath(const nsAString& aPath)
{ {
nsAString::const_iterator start, end; nsAString::const_iterator start, end;
mPath.BeginReading(start); aPath.BeginReading(start);
mPath.EndReading(end); aPath.EndReading(end);
// if the path is a '~' or starts with '~/', return false. // if the path is a '~' or starts with '~/', return false.
NS_NAMED_LITERAL_STRING(tilde, "~"); NS_NAMED_LITERAL_STRING(tilde, "~");
NS_NAMED_LITERAL_STRING(tildeSlash, "~/"); NS_NAMED_LITERAL_STRING(tildeSlash, "~/");
if (mPath.Equals(tilde) || if (aPath.Equals(tilde) ||
StringBeginsWith(mPath, tildeSlash)) { StringBeginsWith(aPath, tildeSlash)) {
NS_WARNING("Path name starts with tilde!"); NS_WARNING("Path name starts with tilde!");
return false; return false;
} }
// split on /. if any token is "", ., or .., return false. // split on /. if any token is "", ., or .., return false.
NS_ConvertUTF16toUTF8 cname(mPath); NS_ConvertUTF16toUTF8 cname(aPath);
char* buffer = cname.BeginWriting(); char* buffer = cname.BeginWriting();
const char* token; const char* token;
@ -398,12 +566,12 @@ DeviceStorageFile::NormalizeFilePath() {
} }
void void
DeviceStorageFile::AppendRelativePath() { DeviceStorageFile::AppendRelativePath(const nsAString& aPath) {
#if defined(XP_WIN) #if defined(XP_WIN)
// replace forward slashes with backslashes, // replace forward slashes with backslashes,
// since nsLocalFileWin chokes on them // since nsLocalFileWin chokes on them
nsString temp; nsString temp;
temp.Assign(mPath); temp.Assign(aPath);
PRUnichar* cur = temp.BeginWriting(); PRUnichar* cur = temp.BeginWriting();
PRUnichar* end = temp.EndWriting(); PRUnichar* end = temp.EndWriting();
@ -414,7 +582,7 @@ DeviceStorageFile::AppendRelativePath() {
} }
mFile->AppendRelativePath(temp); mFile->AppendRelativePath(temp);
#else #else
mFile->AppendRelativePath(mPath); mFile->AppendRelativePath(aPath);
#endif #endif
} }
@ -536,7 +704,6 @@ DeviceStorageFile::CollectFiles(nsTArray<nsRefPtr<DeviceStorageFile> > &aFiles,
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
return; return;
} }
return collectFilesInternal(aFiles, aSince, rootPath); return collectFilesInternal(aFiles, aSince, rootPath);
} }
@ -585,12 +752,10 @@ DeviceStorageFile::collectFilesInternal(nsTArray<nsRefPtr<DeviceStorageFile> > &
nsDependentSubstring newPath = Substring(fullpath, len); nsDependentSubstring newPath = Substring(fullpath, len);
if (isDir) { if (isDir) {
DeviceStorageFile dsf(mStorageType, f); DeviceStorageFile dsf(mStorageType, mRootDir, newPath);
dsf.SetPath(newPath);
dsf.collectFilesInternal(aFiles, aSince, aRootPath); dsf.collectFilesInternal(aFiles, aSince, aRootPath);
} else if (isFile) { } else if (isFile) {
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType, f); nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType, mRootDir, newPath);
dsf->SetPath(newPath);
aFiles.AppendElement(dsf); aFiles.AppendElement(dsf);
} }
} }
@ -706,11 +871,13 @@ UnregisterForSDCardChanges(nsIObserver* aObserver)
#endif #endif
void void
nsDOMDeviceStorage::SetRootDirectoryForType(const nsAString& aType, const nsAString& aVolName) nsDOMDeviceStorage::SetRootDirectoryForType(const nsAString& aType,
const nsAString& aVolName)
{ {
nsCOMPtr<nsIFile> f; nsCOMPtr<nsIFile> f;
nsCOMPtr<nsIProperties> dirService = do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID); DeviceStorageFile::GetRootDirectoryForType(aType,
NS_ASSERTION(dirService, "Must have directory service"); aVolName,
getter_AddRefs(f));
mVolumeName = NS_LITERAL_STRING(""); mVolumeName = NS_LITERAL_STRING("");
#ifdef MOZ_WIDGET_GONK #ifdef MOZ_WIDGET_GONK
@ -727,84 +894,7 @@ nsDOMDeviceStorage::SetRootDirectoryForType(const nsAString& aType, const nsAStr
} }
} }
} }
#endif
// Picture directory
if (aType.EqualsLiteral(DEVICESTORAGE_PICTURES)) {
#ifdef MOZ_WIDGET_GONK
NS_NewLocalFile(volMountPoint, false, getter_AddRefs(f));
#elif defined (MOZ_WIDGET_COCOA)
dirService->Get(NS_OSX_PICTURE_DOCUMENTS_DIR, NS_GET_IID(nsIFile), getter_AddRefs(f));
#elif defined (XP_UNIX)
dirService->Get(NS_UNIX_XDG_PICTURES_DIR, NS_GET_IID(nsIFile), getter_AddRefs(f));
#elif defined (XP_WIN)
dirService->Get(NS_WIN_PICTURES_DIR, NS_GET_IID(nsIFile), getter_AddRefs(f));
#endif
}
// Video directory
else if (aType.EqualsLiteral(DEVICESTORAGE_VIDEOS)) {
#ifdef MOZ_WIDGET_GONK
NS_NewLocalFile(volMountPoint, false, getter_AddRefs(f));
#elif defined (MOZ_WIDGET_COCOA)
dirService->Get(NS_OSX_MOVIE_DOCUMENTS_DIR, NS_GET_IID(nsIFile), getter_AddRefs(f));
#elif defined (XP_UNIX)
dirService->Get(NS_UNIX_XDG_VIDEOS_DIR, NS_GET_IID(nsIFile), getter_AddRefs(f));
#elif defined (XP_WIN)
dirService->Get(NS_WIN_VIDEOS_DIR, NS_GET_IID(nsIFile), getter_AddRefs(f));
#endif
}
// Music directory
else if (aType.EqualsLiteral(DEVICESTORAGE_MUSIC)) {
#ifdef MOZ_WIDGET_GONK
NS_NewLocalFile(volMountPoint, false, getter_AddRefs(f));
#elif defined (MOZ_WIDGET_COCOA)
dirService->Get(NS_OSX_MUSIC_DOCUMENTS_DIR, NS_GET_IID(nsIFile), getter_AddRefs(f));
#elif defined (XP_UNIX)
dirService->Get(NS_UNIX_XDG_MUSIC_DIR, NS_GET_IID(nsIFile), getter_AddRefs(f));
#elif defined (XP_WIN)
dirService->Get(NS_WIN_MUSIC_DIR, NS_GET_IID(nsIFile), getter_AddRefs(f));
#endif
}
// Apps directory
else if (aType.EqualsLiteral(DEVICESTORAGE_APPS)) {
#ifdef MOZ_WIDGET_GONK
NS_NewLocalFile(NS_LITERAL_STRING("/data"), false, getter_AddRefs(f));
#else
dirService->Get(NS_APP_USER_PROFILE_50_DIR, NS_GET_IID(nsIFile), getter_AddRefs(f));
if (f) {
f->AppendRelativeNativePath(NS_LITERAL_CSTRING("webapps"));
}
#endif
}
// default SDCard
else if (aType.EqualsLiteral(DEVICESTORAGE_SDCARD)) {
#ifdef MOZ_WIDGET_GONK
NS_NewLocalFile(volMountPoint, false, getter_AddRefs(f));
#else
// Eventually, on desktop, we want to do something smarter -- for example,
// detect when an sdcard is inserted, and use that instead of this.
dirService->Get(NS_APP_USER_PROFILE_50_DIR, NS_GET_IID(nsIFile), getter_AddRefs(f));
if (f) {
f->AppendRelativeNativePath(NS_LITERAL_CSTRING("fake-sdcard"));
}
#endif
}
// in testing, we default all device storage types to a temp directory
if (f && mozilla::Preferences::GetBool("device.storage.testing", false)) {
dirService->Get(NS_OS_TEMP_DIR, NS_GET_IID(nsIFile), getter_AddRefs(f));
if (f) {
f->AppendRelativeNativePath(NS_LITERAL_CSTRING("device-storage-testing"));
f->Create(nsIFile::DIRECTORY_TYPE, 0777);
f->Normalize();
}
}
#ifdef MOZ_WIDGET_GONK
RegisterForSDCardChanges(this); RegisterForSDCardChanges(this);
#endif #endif
@ -1026,20 +1116,13 @@ ContinueCursorEvent::Continue()
return; return;
} }
nsString fullpath;
nsresult rv = file->mFile->GetPath(fullpath);
if (NS_FAILED(rv)) {
NS_ASSERTION(false, "GetPath failed to return a valid path");
return;
}
nsDOMDeviceStorageCursor* cursor = static_cast<nsDOMDeviceStorageCursor*>(mRequest.get()); nsDOMDeviceStorageCursor* cursor = static_cast<nsDOMDeviceStorageCursor*>(mRequest.get());
nsString cursorStorageType; nsString cursorStorageType;
cursor->GetStorageType(cursorStorageType); cursor->GetStorageType(cursorStorageType);
DeviceStorageRequestChild* child = new DeviceStorageRequestChild(mRequest, file); DeviceStorageRequestChild* child = new DeviceStorageRequestChild(mRequest, file);
child->SetCallback(cursor); child->SetCallback(cursor);
DeviceStorageGetParams params(cursorStorageType, file->mPath, fullpath); DeviceStorageGetParams params(cursorStorageType, file->mRootDir, file->mPath);
ContentChild::GetSingleton()->SendPDeviceStorageRequestConstructor(child, params); ContentChild::GetSingleton()->SendPDeviceStorageRequestConstructor(child, params);
mRequest = nullptr; mRequest = nullptr;
} }
@ -1180,17 +1263,8 @@ nsDOMDeviceStorageCursor::Allow()
} }
if (XRE_GetProcessType() != GeckoProcessType_Default) { if (XRE_GetProcessType() != GeckoProcessType_Default) {
nsString fullpath;
nsresult rv = mFile->mFile->GetPath(fullpath);
if (NS_FAILED(rv)) {
// just do nothing
return NS_OK;
}
PDeviceStorageRequestChild* child = new DeviceStorageRequestChild(this, mFile); PDeviceStorageRequestChild* child = new DeviceStorageRequestChild(this, mFile);
DeviceStorageEnumerationParams params(mFile->mStorageType, fullpath, mSince); DeviceStorageEnumerationParams params(mFile->mStorageType, mFile->mRootDir, mSince);
ContentChild::GetSingleton()->SendPDeviceStorageRequestConstructor(child, params); ContentChild::GetSingleton()->SendPDeviceStorageRequestConstructor(child, params);
return NS_OK; return NS_OK;
} }
@ -1650,14 +1724,6 @@ public:
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
nsString fullpath;
nsresult rv = mFile->mFile->GetPath(fullpath);
if (NS_FAILED(rv)) {
// just do nothing
return NS_OK;
}
switch(mRequestType) { switch(mRequestType) {
case DEVICE_STORAGE_REQUEST_CREATE: case DEVICE_STORAGE_REQUEST_CREATE:
{ {
@ -1687,8 +1753,7 @@ public:
DeviceStorageAddParams params; DeviceStorageAddParams params;
params.blobChild() = actor; params.blobChild() = actor;
params.type() = mFile->mStorageType; params.type() = mFile->mStorageType;
params.name() = mFile->mPath; params.relpath() = mFile->mPath;
params.fullpath() = fullpath;
PDeviceStorageRequestChild* child = new DeviceStorageRequestChild(mRequest, mFile); PDeviceStorageRequestChild* child = new DeviceStorageRequestChild(mRequest, mFile);
ContentChild::GetSingleton()->SendPDeviceStorageRequestConstructor(child, params); ContentChild::GetSingleton()->SendPDeviceStorageRequestConstructor(child, params);
@ -1714,7 +1779,7 @@ public:
if (XRE_GetProcessType() != GeckoProcessType_Default) { if (XRE_GetProcessType() != GeckoProcessType_Default) {
PDeviceStorageRequestChild* child = new DeviceStorageRequestChild(mRequest, mFile); PDeviceStorageRequestChild* child = new DeviceStorageRequestChild(mRequest, mFile);
DeviceStorageGetParams params(mFile->mStorageType, mFile->mPath, fullpath); DeviceStorageGetParams params(mFile->mStorageType, mFile->mRootDir, mFile->mPath);
ContentChild::GetSingleton()->SendPDeviceStorageRequestConstructor(child, params); ContentChild::GetSingleton()->SendPDeviceStorageRequestConstructor(child, params);
return NS_OK; return NS_OK;
} }
@ -1738,7 +1803,7 @@ public:
if (XRE_GetProcessType() != GeckoProcessType_Default) { if (XRE_GetProcessType() != GeckoProcessType_Default) {
PDeviceStorageRequestChild* child = new DeviceStorageRequestChild(mRequest, mFile); PDeviceStorageRequestChild* child = new DeviceStorageRequestChild(mRequest, mFile);
DeviceStorageDeleteParams params(mFile->mStorageType, fullpath); DeviceStorageDeleteParams params(mFile->mStorageType, mFile->mPath);
ContentChild::GetSingleton()->SendPDeviceStorageRequestConstructor(child, params); ContentChild::GetSingleton()->SendPDeviceStorageRequestConstructor(child, params);
return NS_OK; return NS_OK;
} }
@ -1750,7 +1815,7 @@ public:
{ {
if (XRE_GetProcessType() != GeckoProcessType_Default) { if (XRE_GetProcessType() != GeckoProcessType_Default) {
PDeviceStorageRequestChild* child = new DeviceStorageRequestChild(mRequest, mFile); PDeviceStorageRequestChild* child = new DeviceStorageRequestChild(mRequest, mFile);
DeviceStorageFreeSpaceParams params(mFile->mStorageType, fullpath); DeviceStorageFreeSpaceParams params(mFile->mStorageType, mFile->mPath);
ContentChild::GetSingleton()->SendPDeviceStorageRequestConstructor(child, params); ContentChild::GetSingleton()->SendPDeviceStorageRequestConstructor(child, params);
return NS_OK; return NS_OK;
} }
@ -1762,7 +1827,7 @@ public:
{ {
if (XRE_GetProcessType() != GeckoProcessType_Default) { if (XRE_GetProcessType() != GeckoProcessType_Default) {
PDeviceStorageRequestChild* child = new DeviceStorageRequestChild(mRequest, mFile); PDeviceStorageRequestChild* child = new DeviceStorageRequestChild(mRequest, mFile);
DeviceStorageUsedSpaceParams params(mFile->mStorageType, fullpath); DeviceStorageUsedSpaceParams params(mFile->mStorageType, mFile->mPath);
ContentChild::GetSingleton()->SendPDeviceStorageRequestConstructor(child, params); ContentChild::GetSingleton()->SendPDeviceStorageRequestConstructor(child, params);
return NS_OK; return NS_OK;
} }
@ -1774,7 +1839,7 @@ public:
{ {
if (XRE_GetProcessType() != GeckoProcessType_Default) { if (XRE_GetProcessType() != GeckoProcessType_Default) {
PDeviceStorageRequestChild* child = new DeviceStorageRequestChild(mRequest, mFile); PDeviceStorageRequestChild* child = new DeviceStorageRequestChild(mRequest, mFile);
DeviceStorageAvailableParams params(mFile->mStorageType, fullpath); DeviceStorageAvailableParams params(mFile->mStorageType, mFile->mPath);
ContentChild::GetSingleton()->SendPDeviceStorageRequestConstructor(child, params); ContentChild::GetSingleton()->SendPDeviceStorageRequestConstructor(child, params);
return NS_OK; return NS_OK;
} }
@ -2024,7 +2089,7 @@ nsDOMDeviceStorage::AddNamed(nsIDOMBlob *aBlob,
nsCOMPtr<nsIRunnable> r; nsCOMPtr<nsIRunnable> r;
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType, mRootDirectory, aPath); nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType, aPath);
if (!dsf->IsSafePath()) { if (!dsf->IsSafePath()) {
r = new PostErrorEvent(request, POST_ERROR_EVENT_PERMISSION_DENIED); r = new PostErrorEvent(request, POST_ERROR_EVENT_PERMISSION_DENIED);
} else if (!typeChecker->Check(mStorageType, dsf->mFile) || } else if (!typeChecker->Check(mStorageType, dsf->mFile) ||
@ -2080,7 +2145,7 @@ nsDOMDeviceStorage::GetInternal(const JS::Value & aPath,
return NS_OK; return NS_OK;
} }
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType, mRootDirectory, path); nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType, path);
dsf->SetEditable(aEditable); dsf->SetEditable(aEditable);
if (!dsf->IsSafePath()) { if (!dsf->IsSafePath()) {
r = new PostErrorEvent(request, POST_ERROR_EVENT_PERMISSION_DENIED); r = new PostErrorEvent(request, POST_ERROR_EVENT_PERMISSION_DENIED);
@ -2113,7 +2178,7 @@ nsDOMDeviceStorage::Delete(const JS::Value & aPath, JSContext* aCx, nsIDOMDOMReq
return NS_OK; return NS_OK;
} }
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType, mRootDirectory, path); nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType, path);
if (!dsf->IsSafePath()) { if (!dsf->IsSafePath()) {
r = new PostErrorEvent(request, POST_ERROR_EVENT_PERMISSION_DENIED); r = new PostErrorEvent(request, POST_ERROR_EVENT_PERMISSION_DENIED);
@ -2137,7 +2202,7 @@ nsDOMDeviceStorage::FreeSpace(nsIDOMDOMRequest** aRetval)
nsRefPtr<DOMRequest> request = new DOMRequest(win); nsRefPtr<DOMRequest> request = new DOMRequest(win);
NS_ADDREF(*aRetval = request); NS_ADDREF(*aRetval = request);
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType, mRootDirectory); nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType);
nsCOMPtr<nsIRunnable> r = new DeviceStorageRequest(DEVICE_STORAGE_REQUEST_FREE_SPACE, nsCOMPtr<nsIRunnable> r = new DeviceStorageRequest(DEVICE_STORAGE_REQUEST_FREE_SPACE,
win, win,
mPrincipal, mPrincipal,
@ -2158,7 +2223,7 @@ nsDOMDeviceStorage::UsedSpace(nsIDOMDOMRequest** aRetval)
nsRefPtr<DOMRequest> request = new DOMRequest(win); nsRefPtr<DOMRequest> request = new DOMRequest(win);
NS_ADDREF(*aRetval = request); NS_ADDREF(*aRetval = request);
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType, mRootDirectory); nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType);
nsCOMPtr<nsIRunnable> r = new DeviceStorageRequest(DEVICE_STORAGE_REQUEST_USED_SPACE, nsCOMPtr<nsIRunnable> r = new DeviceStorageRequest(DEVICE_STORAGE_REQUEST_USED_SPACE,
win, win,
mPrincipal, mPrincipal,
@ -2179,7 +2244,7 @@ nsDOMDeviceStorage::Available(nsIDOMDOMRequest** aRetval)
nsRefPtr<DOMRequest> request = new DOMRequest(win); nsRefPtr<DOMRequest> request = new DOMRequest(win);
NS_ADDREF(*aRetval = request); NS_ADDREF(*aRetval = request);
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType, mRootDirectory); nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType);
nsCOMPtr<nsIRunnable> r = new DeviceStorageRequest(DEVICE_STORAGE_REQUEST_AVAILABLE, nsCOMPtr<nsIRunnable> r = new DeviceStorageRequest(DEVICE_STORAGE_REQUEST_AVAILABLE,
win, win,
mPrincipal, mPrincipal,
@ -2279,7 +2344,7 @@ nsDOMDeviceStorage::EnumerateInternal(const JS::Value & aName,
since = ExtractDateFromOptions(aCx, aOptions); since = ExtractDateFromOptions(aCx, aOptions);
} }
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType, mRootDirectory, path); nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType, path, NS_LITERAL_STRING(""));
dsf->SetEditable(aEditable); dsf->SetEditable(aEditable);
nsRefPtr<nsDOMDeviceStorageCursor> cursor = new nsDOMDeviceStorageCursor(win, mPrincipal, nsRefPtr<nsDOMDeviceStorageCursor> cursor = new nsDOMDeviceStorageCursor(win, mPrincipal,
@ -2453,7 +2518,7 @@ nsDOMDeviceStorage::AddEventListener(const nsAString & aType,
} }
nsRefPtr<DOMRequest> request = new DOMRequest(win); nsRefPtr<DOMRequest> request = new DOMRequest(win);
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType, mRootDirectory); nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType);
nsCOMPtr<nsIRunnable> r = new DeviceStorageRequest(DEVICE_STORAGE_REQUEST_WATCH, nsCOMPtr<nsIRunnable> r = new DeviceStorageRequest(DEVICE_STORAGE_REQUEST_WATCH,
win, mPrincipal, dsf, request, this); win, mPrincipal, dsf, request, this);
NS_DispatchToMainThread(r); NS_DispatchToMainThread(r);
@ -2474,7 +2539,7 @@ nsDOMDeviceStorage::AddEventListener(const nsAString & aType,
} }
nsRefPtr<DOMRequest> request = new DOMRequest(win); nsRefPtr<DOMRequest> request = new DOMRequest(win);
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType, mRootDirectory); nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType);
nsCOMPtr<nsIRunnable> r = new DeviceStorageRequest(DEVICE_STORAGE_REQUEST_WATCH, nsCOMPtr<nsIRunnable> r = new DeviceStorageRequest(DEVICE_STORAGE_REQUEST_WATCH,
win, mPrincipal, dsf, request, this); win, mPrincipal, dsf, request, this);
NS_DispatchToMainThread(r); NS_DispatchToMainThread(r);

View File

@ -1176,10 +1176,7 @@ ContentChild::RecvLastPrivateDocShellDestroyed()
bool bool
ContentChild::RecvFilePathUpdate(const nsString& type, const nsString& path, const nsCString& aReason) ContentChild::RecvFilePathUpdate(const nsString& type, const nsString& path, const nsCString& aReason)
{ {
nsCOMPtr<nsIFile> file; nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(type, path);
NS_NewLocalFile(path, false, getter_AddRefs(file));
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(type, file);
nsString reason; nsString reason;
CopyASCIItoUTF16(aReason, reason); CopyASCIItoUTF16(aReason, reason);

View File

@ -1531,10 +1531,7 @@ ContentParent::Observe(nsISupports* aSubject,
CopyUTF16toUTF8(aData, creason); CopyUTF16toUTF8(aData, creason);
DeviceStorageFile* file = static_cast<DeviceStorageFile*>(aSubject); DeviceStorageFile* file = static_cast<DeviceStorageFile*>(aSubject);
nsString path; unused << SendFilePathUpdate(file->mStorageType, file->mPath, creason);
file->mFile->GetPath(path);
unused << SendFilePathUpdate(file->mStorageType, path, creason);
} }
#ifdef MOZ_WIDGET_GONK #ifdef MOZ_WIDGET_GONK
else if(!strcmp(aTopic, NS_VOLUME_STATE_CHANGED)) { else if(!strcmp(aTopic, NS_VOLUME_STATE_CHANGED)) {
@ -2349,15 +2346,11 @@ ContentParent::RecvAsyncMessage(const nsString& aMsg,
} }
bool bool
ContentParent::RecvFilePathUpdateNotify(const nsString& aType, const nsString& aFilePath, const nsCString& aReason) ContentParent::RecvFilePathUpdateNotify(const nsString& aType,
const nsString& aFilePath,
const nsCString& aReason)
{ {
nsCOMPtr<nsIFile> file; nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(aType, aFilePath);
nsresult rv = NS_NewLocalFile(aFilePath, false, getter_AddRefs(file));
if (NS_FAILED(rv)) {
// ignore
return true;
}
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(aType, file);
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (!obs) { if (!obs) {

View File

@ -63,46 +63,45 @@ struct FontListEntry {
struct DeviceStorageFreeSpaceParams struct DeviceStorageFreeSpaceParams
{ {
nsString type; nsString type;
nsString fullpath; nsString relpath;
}; };
struct DeviceStorageUsedSpaceParams struct DeviceStorageUsedSpaceParams
{ {
nsString type; nsString type;
nsString fullpath; nsString relpath;
}; };
struct DeviceStorageAvailableParams struct DeviceStorageAvailableParams
{ {
nsString type; nsString type;
nsString fullpath; nsString relpath;
}; };
struct DeviceStorageAddParams struct DeviceStorageAddParams
{ {
nsString type; nsString type;
nsString relpath;
PBlob blob; PBlob blob;
nsString name;
nsString fullpath;
}; };
struct DeviceStorageGetParams struct DeviceStorageGetParams
{ {
nsString type; nsString type;
nsString name; nsString rootDir;
nsString fullpath; nsString relpath;
}; };
struct DeviceStorageDeleteParams struct DeviceStorageDeleteParams
{ {
nsString type; nsString type;
nsString fullpath; nsString relpath;
}; };
struct DeviceStorageEnumerationParams struct DeviceStorageEnumerationParams
{ {
nsString type; nsString type;
nsString fullpath; nsString relpath;
uint64_t since; uint64_t since;
}; };

View File

@ -12,11 +12,12 @@
%} %}
[ref] native nsStringTArrayRef(nsTArray<nsString>); [ref] native nsStringTArrayRef(nsTArray<nsString>);
[scriptable, uuid(fc4e6449-922e-463d-880b-bfbab4909114)] [scriptable, uuid(7c179fb7-67a0-43a3-9337-294e0360b858)]
interface nsIVolumeService : nsISupports interface nsIVolumeService : nsISupports
{ {
nsIVolume getVolumeByName(in DOMString volName); nsIVolume getVolumeByName(in DOMString volName);
nsIVolume getVolumeByPath(in DOMString path); nsIVolume getVolumeByPath(in DOMString path);
nsIVolume createOrGetVolumeByPath(in DOMString path);
void BroadcastVolume(in DOMString volName); void BroadcastVolume(in DOMString volName);
@ -27,6 +28,6 @@ interface nsIVolumeService : nsISupports
%{C++ %{C++
#define NS_VOLUMESERVICE_CID \ #define NS_VOLUMESERVICE_CID \
{0x597403c6, 0x5ba4, 0x4e7b, {0xb3, 0xf4, 0xed, 0x3f, 0x05, 0xf7, 0x75, 0xd8}} {0x7c179fb7, 0x67a0, 0x43a3, {0x93, 0x37, 0x29, 0x4e, 0x03, 0x60, 0xb8, 0x58}}
#define NS_VOLUMESERVICE_CONTRACTID "@mozilla.org/telephony/volume-service;1" #define NS_VOLUMESERVICE_CONTRACTID "@mozilla.org/telephony/volume-service;1"
%} %}

View File

@ -54,8 +54,8 @@ nsVolumeService::GetSingleton()
if (!sSingleton) { if (!sSingleton) {
sSingleton = new nsVolumeService(); sSingleton = new nsVolumeService();
} }
NS_ADDREF(sSingleton.get()); nsRefPtr<nsVolumeService> volumeService = sSingleton.get();
return sSingleton.get(); return volumeService.forget();
} }
// static // static
@ -86,6 +86,7 @@ nsVolumeService::Shutdown()
} }
nsVolumeService::nsVolumeService() nsVolumeService::nsVolumeService()
: mArrayMonitor("nsVolumeServiceArray")
{ {
sSingleton = this; sSingleton = this;
@ -118,22 +119,32 @@ nsVolumeService::~nsVolumeService()
} }
// Callback for nsIDOMMozWakeLockListener // Callback for nsIDOMMozWakeLockListener
NS_IMETHODIMP nsVolumeService::Callback(const nsAString& aTopic, const nsAString& aState) NS_IMETHODIMP
nsVolumeService::Callback(const nsAString& aTopic, const nsAString& aState)
{ {
CheckMountLock(aTopic, aState); CheckMountLock(aTopic, aState);
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP nsVolumeService::BroadcastVolume(const nsAString& aVolName) NS_IMETHODIMP
nsVolumeService::BroadcastVolume(const nsAString& aVolName)
{ {
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default); MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
if (aVolName.EqualsLiteral("")) { if (aVolName.EqualsLiteral("")) {
nsVolume::Array volumeArray;
{
// Copy the array since we don't want to call BroadcastVolume
// while we're holding the lock.
MonitorAutoLock autoLock(mArrayMonitor);
volumeArray = mVolumeArray;
}
// We treat being passed the empty string as "broadcast all volumes" // We treat being passed the empty string as "broadcast all volumes"
nsVolume::Array::size_type numVolumes = mVolumeArray.Length(); nsVolume::Array::size_type numVolumes = volumeArray.Length();
nsVolume::Array::index_type volIndex; nsVolume::Array::index_type volIndex;
for (volIndex = 0; volIndex < numVolumes; volIndex++) { for (volIndex = 0; volIndex < numVolumes; volIndex++) {
const nsString &volName(mVolumeArray[volIndex]->Name()); const nsString& volName(volumeArray[volIndex]->Name());
if (!volName.EqualsLiteral("")) { if (!volName.EqualsLiteral("")) {
// Note: The volume service is the only entity that should be able to // Note: The volume service is the only entity that should be able to
// modify the array of volumes. So we shouldn't have any issues with // modify the array of volumes. So we shouldn't have any issues with
@ -146,7 +157,11 @@ NS_IMETHODIMP nsVolumeService::BroadcastVolume(const nsAString& aVolName)
} }
return NS_OK; return NS_OK;
} }
nsRefPtr<nsVolume> vol = FindVolumeByName(aVolName); nsRefPtr<nsVolume> vol;
{
MonitorAutoLock autoLock(mArrayMonitor);
vol = FindVolumeByName(aVolName);
}
if (!vol) { if (!vol) {
ERR("BroadcastVolume: Unable to locate volume '%s'", ERR("BroadcastVolume: Unable to locate volume '%s'",
NS_LossyConvertUTF16toASCII(aVolName).get()); NS_LossyConvertUTF16toASCII(aVolName).get());
@ -164,16 +179,19 @@ NS_IMETHODIMP nsVolumeService::BroadcastVolume(const nsAString& aVolName)
NS_IMETHODIMP nsVolumeService::GetVolumeByName(const nsAString& aVolName, nsIVolume **aResult) NS_IMETHODIMP nsVolumeService::GetVolumeByName(const nsAString& aVolName, nsIVolume **aResult)
{ {
MonitorAutoLock autoLock(mArrayMonitor);
nsRefPtr<nsVolume> vol = FindVolumeByName(aVolName); nsRefPtr<nsVolume> vol = FindVolumeByName(aVolName);
if (!vol) { if (!vol) {
return NS_ERROR_NOT_AVAILABLE; return NS_ERROR_NOT_AVAILABLE;
} }
NS_ADDREF(*aResult = vol); vol.forget(aResult);
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP nsVolumeService::GetVolumeByPath(const nsAString& aPath, nsIVolume **aResult) NS_IMETHODIMP
nsVolumeService::GetVolumeByPath(const nsAString& aPath, nsIVolume **aResult)
{ {
nsCString utf8Path = NS_ConvertUTF16toUTF8(aPath); nsCString utf8Path = NS_ConvertUTF16toUTF8(aPath);
char realPathBuf[PATH_MAX]; char realPathBuf[PATH_MAX];
@ -193,6 +211,8 @@ NS_IMETHODIMP nsVolumeService::GetVolumeByPath(const nsAString& aPath, nsIVolume
strlcat(realPathBuf, "/", sizeof(realPathBuf)); strlcat(realPathBuf, "/", sizeof(realPathBuf));
MonitorAutoLock autoLock(mArrayMonitor);
nsVolume::Array::size_type numVolumes = mVolumeArray.Length(); nsVolume::Array::size_type numVolumes = mVolumeArray.Length();
nsVolume::Array::index_type volIndex; nsVolume::Array::index_type volIndex;
for (volIndex = 0; volIndex < numVolumes; volIndex++) { for (volIndex = 0; volIndex < numVolumes; volIndex++) {
@ -201,22 +221,35 @@ NS_IMETHODIMP nsVolumeService::GetVolumeByPath(const nsAString& aPath, nsIVolume
volMountPointSlash.Append(NS_LITERAL_CSTRING("/")); volMountPointSlash.Append(NS_LITERAL_CSTRING("/"));
nsDependentCSubstring testStr(realPathBuf, volMountPointSlash.Length()); nsDependentCSubstring testStr(realPathBuf, volMountPointSlash.Length());
if (volMountPointSlash.Equals(testStr)) { if (volMountPointSlash.Equals(testStr)) {
NS_ADDREF(*aResult = vol); vol.forget(aResult);
return NS_OK; return NS_OK;
} }
} }
return NS_ERROR_FILE_NOT_FOUND;
}
// In order to support queries by DeviceStorage and the updater, we will fabricate NS_IMETHODIMP
// a volume from the pathname, so that the caller can determine the volume size nsVolumeService::CreateOrGetVolumeByPath(const nsAString& aPath, nsIVolume** aResult)
nsRefPtr<nsVolume> vol = new nsVolume(NS_LITERAL_STRING("fake"), {
nsresult rv = GetVolumeByPath(aPath, aResult);
if (rv == NS_OK) {
return NS_OK;
}
// In order to support queries by the updater, we will fabricate a volume
// from the pathname, so that the caller can determine the volume size.
nsCOMPtr<nsIVolume> vol = new nsVolume(NS_LITERAL_STRING("fake"),
aPath, nsIVolume::STATE_MOUNTED, aPath, nsIVolume::STATE_MOUNTED,
-1 /*generation*/); -1 /*generation*/);
NS_ADDREF(*aResult = vol); vol.forget(aResult);
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP nsVolumeService::GetVolumeNames(nsTArray<nsString>& aVolNames) NS_IMETHODIMP
nsVolumeService::GetVolumeNames(nsTArray<nsString>& aVolNames)
{ {
MonitorAutoLock autoLock(mArrayMonitor);
nsVolume::Array::size_type numVolumes = mVolumeArray.Length(); nsVolume::Array::size_type numVolumes = mVolumeArray.Length();
nsVolume::Array::index_type volIndex; nsVolume::Array::index_type volIndex;
for (volIndex = 0; volIndex < numVolumes; volIndex++) { for (volIndex = 0; volIndex < numVolumes; volIndex++) {
@ -227,22 +260,35 @@ NS_IMETHODIMP nsVolumeService::GetVolumeNames(nsTArray<nsString>& aVolNames)
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP nsVolumeService::CreateMountLock(const nsAString& aVolumeName, nsIVolumeMountLock **aResult) NS_IMETHODIMP
nsVolumeService::CreateMountLock(const nsAString& aVolumeName, nsIVolumeMountLock **aResult)
{ {
nsRefPtr<nsVolumeMountLock> mountLock = nsVolumeMountLock::Create(aVolumeName); nsCOMPtr<nsIVolumeMountLock> mountLock = nsVolumeMountLock::Create(aVolumeName);
if (!mountLock) { if (!mountLock) {
return NS_ERROR_NOT_AVAILABLE; return NS_ERROR_NOT_AVAILABLE;
} }
NS_ADDREF(*aResult = mountLock); mountLock.forget(aResult);
return NS_OK; return NS_OK;
} }
void nsVolumeService::CheckMountLock(const nsAString& aMountLockName, void
nsVolumeService::CheckMountLock(const nsAString& aMountLockName,
const nsAString& aMountLockState) const nsAString& aMountLockState)
{ {
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default); MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
nsRefPtr<nsVolume> vol = FindVolumeByMountLockName(aMountLockName);
if (vol) {
vol->UpdateMountLock(aMountLockState);
}
}
already_AddRefed<nsVolume>
nsVolumeService::FindVolumeByMountLockName(const nsAString& aMountLockName)
{
MonitorAutoLock autoLock(mArrayMonitor);
nsVolume::Array::size_type numVolumes = mVolumeArray.Length(); nsVolume::Array::size_type numVolumes = mVolumeArray.Length();
nsVolume::Array::index_type volIndex; nsVolume::Array::index_type volIndex;
for (volIndex = 0; volIndex < numVolumes; volIndex++) { for (volIndex = 0; volIndex < numVolumes; volIndex++) {
@ -250,15 +296,16 @@ void nsVolumeService::CheckMountLock(const nsAString& aMountLockName,
nsString mountLockName; nsString mountLockName;
vol->GetMountLockName(mountLockName); vol->GetMountLockName(mountLockName);
if (mountLockName.Equals(aMountLockName)) { if (mountLockName.Equals(aMountLockName)) {
vol->UpdateMountLock(aMountLockState); return vol.forget();
return;
} }
} }
return nullptr;
} }
already_AddRefed<nsVolume> nsVolumeService::FindVolumeByName(const nsAString& aName) already_AddRefed<nsVolume>
nsVolumeService::FindVolumeByName(const nsAString& aName)
{ {
MOZ_ASSERT(NS_IsMainThread()); mArrayMonitor.AssertCurrentThreadOwns();
nsVolume::Array::size_type numVolumes = mVolumeArray.Length(); nsVolume::Array::size_type numVolumes = mVolumeArray.Length();
nsVolume::Array::index_type volIndex; nsVolume::Array::index_type volIndex;
@ -268,13 +315,14 @@ already_AddRefed<nsVolume> nsVolumeService::FindVolumeByName(const nsAString& aN
return vol.forget(); return vol.forget();
} }
} }
return NULL; return nullptr;
} }
//static //static
already_AddRefed<nsVolume> nsVolumeService::FindAddVolumeByName(const nsAString& aName) already_AddRefed<nsVolume>
nsVolumeService::CreateOrFindVolumeByName(const nsAString& aName)
{ {
MOZ_ASSERT(NS_IsMainThread()); MonitorAutoLock autoLock(mArrayMonitor);
nsRefPtr<nsVolume> vol; nsRefPtr<nsVolume> vol;
vol = FindVolumeByName(aName); vol = FindVolumeByName(aName);
@ -287,7 +335,8 @@ already_AddRefed<nsVolume> nsVolumeService::FindAddVolumeByName(const nsAString&
return vol.forget(); return vol.forget();
} }
NS_IMETHODIMP nsVolumeService::Observe(nsISupports* aSubject, const char* aTopic, const PRUnichar* aData) NS_IMETHODIMP
nsVolumeService::Observe(nsISupports* aSubject, const char* aTopic, const PRUnichar* aData)
{ {
if (strcmp(aTopic, NS_VOLUME_STATE_CHANGED) != 0) { if (strcmp(aTopic, NS_VOLUME_STATE_CHANGED) != 0) {
return NS_OK; return NS_OK;
@ -301,13 +350,14 @@ NS_IMETHODIMP nsVolumeService::Observe(nsISupports* aSubject, const char* aTopic
return NS_OK; return NS_OK;
} }
void nsVolumeService::UpdateVolume(nsIVolume* aVolume) void
nsVolumeService::UpdateVolume(nsIVolume* aVolume)
{ {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
nsString volName; nsString volName;
aVolume->GetName(volName); aVolume->GetName(volName);
nsRefPtr<nsVolume> vol = FindAddVolumeByName(volName); nsRefPtr<nsVolume> vol = CreateOrFindVolumeByName(volName);
if (vol->Equals(aVolume)) { if (vol->Equals(aVolume)) {
// Nothing has really changed. Don't bother telling anybody. // Nothing has really changed. Don't bother telling anybody.
return; return;
@ -347,8 +397,8 @@ public:
mVolume->MountGeneration(), (int)mVolume->IsMountLocked()); mVolume->MountGeneration(), (int)mVolume->IsMountLocked());
mVolumeService->UpdateVolume(mVolume); mVolumeService->UpdateVolume(mVolume);
mVolumeService = NULL; mVolumeService = nullptr;
mVolume = NULL; mVolume = nullptr;
return NS_OK; return NS_OK;
} }
@ -357,7 +407,8 @@ private:
nsRefPtr<nsVolume> mVolume; nsRefPtr<nsVolume> mVolume;
}; };
void nsVolumeService::UpdateVolumeIOThread(const Volume* aVolume) void
nsVolumeService::UpdateVolumeIOThread(const Volume* aVolume)
{ {
DBG("UpdateVolumeIOThread: Volume '%s' state %s mount '%s' gen %d locked %d", DBG("UpdateVolumeIOThread: Volume '%s' state %s mount '%s' gen %d locked %d",
aVolume->NameStr(), aVolume->StateStr(), aVolume->MountPoint().get(), aVolume->NameStr(), aVolume->StateStr(), aVolume->MountPoint().get(),

View File

@ -5,6 +5,7 @@
#ifndef mozilla_system_nsvolumeservice_h__ #ifndef mozilla_system_nsvolumeservice_h__
#define mozilla_system_nsvolumeservice_h__ #define mozilla_system_nsvolumeservice_h__
#include "mozilla/Monitor.h"
#include "mozilla/RefPtr.h" #include "mozilla/RefPtr.h"
#include "mozilla/StaticPtr.h" #include "mozilla/StaticPtr.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
@ -42,16 +43,19 @@ public:
//static nsVolumeService* GetSingleton(); //static nsVolumeService* GetSingleton();
static void Shutdown(); static void Shutdown();
void CheckMountLock(const nsAString& aMountLockName,
const nsAString& aMountLockState);
already_AddRefed<nsVolume> FindVolumeByName(const nsAString& aName);
already_AddRefed<nsVolume> FindAddVolumeByName(const nsAString& aName);
void UpdateVolume(nsIVolume* aVolume); void UpdateVolume(nsIVolume* aVolume);
void UpdateVolumeIOThread(const Volume* aVolume); void UpdateVolumeIOThread(const Volume* aVolume);
private: private:
~nsVolumeService(); ~nsVolumeService();
void CheckMountLock(const nsAString& aMountLockName,
const nsAString& aMountLockState);
already_AddRefed<nsVolume> FindVolumeByMountLockName(const nsAString& aMountLockName);
already_AddRefed<nsVolume> FindVolumeByName(const nsAString& aName);
already_AddRefed<nsVolume> CreateOrFindVolumeByName(const nsAString& aName);
Monitor mArrayMonitor;
nsVolume::Array mVolumeArray; nsVolume::Array mVolumeArray;
static StaticRefPtr<nsVolumeService> sSingleton; static StaticRefPtr<nsVolumeService> sSingleton;