Bug 858416 - Create a composite device storage interface. r=dougt

This commit is contained in:
Dave Hylands 2013-05-11 02:10:18 -07:00
parent 7082133dd8
commit af61fd0d1c
21 changed files with 1126 additions and 504 deletions

View File

@ -261,6 +261,11 @@ SettingsListener.observe('debug.log-animations.enabled', false, function(value)
Services.prefs.setBoolPref('layers.offmainthreadcomposition.log-animations', value);
});
// =================== Device Storage ====================
SettingsListener.observe('device.storage.writable.name', false, function(value) {
Services.prefs.setBoolPref('device.storage.writable.name', value);
});
// =================== Privacy ====================
SettingsListener.observe('privacy.donottrackheader.enabled', false, function(value) {
Services.prefs.setBoolPref('privacy.donottrackheader.enabled', value);

View File

@ -953,38 +953,21 @@ NS_IMETHODIMP Navigator::GetDeviceStorage(const nsAString &aType, nsIDOMDeviceSt
return NS_OK;
}
// We're going to obsolete getDeviceStorage, but want to leave it in for
// compatability right now. So we do essentially the same thing as GetDeviceStorages
// but only take the first element of the array.
nsCOMPtr<nsPIDOMWindow> win(do_QueryReferent(mWindow));
NS_WARNING("navigator.getDeviceStorage is deprecated. Returning navigator.getDeviceStorages[0]");
if (!win || !win->GetOuterWindow() || !win->GetDocShell()) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIVariant> variantArray;
nsRefPtr<nsDOMDeviceStorage> storage;
nsDOMDeviceStorage::CreateDeviceStorageFor(win, aType, getter_AddRefs(storage));
nsresult rv = GetDeviceStorages(aType, getter_AddRefs(variantArray));
NS_ENSURE_SUCCESS(rv, rv);
uint16_t dataType;
variantArray->GetDataType(&dataType);
if (dataType != nsIDataType::VTYPE_ARRAY) {
NS_ASSERTION(dataType == nsIDataType::VTYPE_EMPTY_ARRAY,
"Expecting an empty array");
if (!storage) {
return NS_OK;
}
uint16_t valueType;
nsIID iid;
uint32_t valueCount;
void* rawArray;
variantArray->GetAsArray(&valueType, &iid, &valueCount, &rawArray);
NS_ASSERTION(valueCount > 0, "Expecting non-zero array size");
nsIDOMDeviceStorage** values = static_cast<nsIDOMDeviceStorage**>(rawArray);
*_retval = values[0];
for (uint32_t i = 1; i < valueCount; i++) {
values[i]->Release();
}
nsMemory::Free(rawArray);
NS_ADDREF(*_retval = storage.get());
mDeviceStorageStores.AppendElement(storage);
return NS_OK;
}

View File

@ -29,9 +29,7 @@
#include "nsIOutputStream.h"
#include "nsNetUtil.h"
#define TARGET_ROOT "/sdcard/"
#define TARGET_SUBDIR "downloads/bluetooth/"
#define TARGET_FOLDER TARGET_ROOT TARGET_SUBDIR
USING_BLUETOOTH_NAMESPACE
using namespace mozilla;
@ -485,53 +483,13 @@ BluetoothOppManager::AfterOppDisconnected()
void
BluetoothOppManager::DeleteReceivedFile()
{
nsString path;
path.AssignLiteral(TARGET_FOLDER);
nsCOMPtr<nsIFile> f;
nsresult rv = NS_NewLocalFile(path + sFileName, false, getter_AddRefs(f));
if (NS_FAILED(rv)) {
NS_WARNING("Couldn't find received file, nothing to delete.");
return;
}
if (mOutputStream) {
mOutputStream->Close();
mOutputStream = nullptr;
}
f->Remove(false);
}
DeviceStorageFile*
BluetoothOppManager::CreateDeviceStorageFile(nsIFile* aFile)
{
nsString fullFilePath;
aFile->GetPath(fullFilePath);
MOZ_ASSERT(StringBeginsWith(fullFilePath, NS_LITERAL_STRING(TARGET_ROOT)));
nsDependentSubstring storagePath =
Substring(fullFilePath, strlen(TARGET_ROOT));
nsCOMPtr<nsIMIMEService> mimeSvc = do_GetService(NS_MIMESERVICE_CONTRACTID);
NS_ENSURE_TRUE(mimeSvc, nullptr);
nsCString mimeType;
nsresult rv = mimeSvc->GetTypeFromFile(aFile, mimeType);
if (NS_FAILED(rv)) {
return nullptr;
}
if (StringBeginsWith(mimeType, NS_LITERAL_CSTRING("image/"))) {
return new DeviceStorageFile(NS_LITERAL_STRING("pictures"), storagePath);
} else if (StringBeginsWith(mimeType, NS_LITERAL_CSTRING("video/"))) {
return new DeviceStorageFile(NS_LITERAL_STRING("videos"), storagePath);
} else if (StringBeginsWith(mimeType, NS_LITERAL_CSTRING("audio/"))) {
return new DeviceStorageFile(NS_LITERAL_STRING("music"), storagePath);
} else {
NS_WARNING("Couldn't recognize the mimetype of received file.");
return nullptr;
if (mDsFile && mDsFile->mFile) {
mDsFile->mFile->Remove(false);
}
}
@ -541,22 +499,18 @@ BluetoothOppManager::CreateFile()
MOZ_ASSERT(mPacketLeftLength == 0);
nsString path;
path.AssignLiteral(TARGET_FOLDER);
path.AssignLiteral(TARGET_SUBDIR);
path.Append(sFileName);
nsCOMPtr<nsIFile> f;
nsresult rv;
rv = NS_NewLocalFile(path + sFileName, false, getter_AddRefs(f));
if (NS_FAILED(rv)) {
NS_WARNING("Couldn't new a local file");
return false;
}
rv = f->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 00644);
if (NS_FAILED(rv)) {
mDsFile = DeviceStorageFile::CreateUnique(path, nsIFile::NORMAL_FILE_TYPE, 0644);
if (!mDsFile) {
NS_WARNING("Couldn't create the file");
return false;
}
nsCOMPtr<nsIFile> f;
mDsFile->mFile->Clone(getter_AddRefs(f));
/*
* The function CreateUnique() may create a file with a different file
* name from the original sFileName. Therefore we have to retrieve
@ -564,8 +518,6 @@ BluetoothOppManager::CreateFile()
*/
f->GetLeafName(sFileName);
mDsFile = CreateDeviceStorageFile(f);
NS_NewLocalFileOutputStream(getter_AddRefs(mOutputStream), f);
NS_ENSURE_TRUE(mOutputStream, false);

View File

@ -109,7 +109,6 @@ private:
bool IsReservedChar(PRUnichar c);
void ClearQueue();
void RetrieveSentFileName();
DeviceStorageFile* CreateDeviceStorageFile(nsIFile* aFile);
void NotifyAboutFileChange();
/**

View File

@ -34,6 +34,8 @@
#include <media/mediaplayer.h>
#include "nsPrintfCString.h"
#include "nsIObserverService.h"
#include "nsIVolume.h"
#include "nsIVolumeService.h"
#include "DOMCameraManager.h"
#include "GonkCameraHwMgr.h"
#include "DOMCameraCapabilities.h"
@ -905,7 +907,22 @@ nsGonkCameraControl::StartRecordingImpl(StartRecordingTask* aStartRecording)
*/
nsCOMPtr<nsIFile> filename = aStartRecording->mFolder;
filename->AppendRelativePath(aStartRecording->mFilename);
nsString fullpath;
filename->GetPath(fullpath);
nsCOMPtr<nsIVolumeService> vs = do_GetService(NS_VOLUMESERVICE_CONTRACTID);
NS_ENSURE_TRUE(vs, NS_ERROR_FAILURE);
nsCOMPtr<nsIVolume> vol;
nsresult rv = vs->GetVolumeByPath(fullpath, getter_AddRefs(vol));
NS_ENSURE_SUCCESS(rv, NS_ERROR_INVALID_ARG);
nsString volName;
vol->GetName(volName);
mVideoFile = new DeviceStorageFile(NS_LITERAL_STRING("videos"),
volName,
aStartRecording->mFilename);
nsAutoCString nativeFilename;
@ -923,7 +940,7 @@ nsGonkCameraControl::StartRecordingImpl(StartRecordingTask* aStartRecording)
return NS_ERROR_FAILURE;
}
nsresult rv = SetupRecording(fd, aStartRecording->mOptions.rotation, aStartRecording->mOptions.maxFileSizeBytes, aStartRecording->mOptions.maxVideoLengthMs);
rv = SetupRecording(fd, aStartRecording->mOptions.rotation, aStartRecording->mOptions.maxFileSizeBytes, aStartRecording->mOptions.maxVideoLengthMs);
NS_ENSURE_SUCCESS(rv, rv);
if (mRecorder->start() != OK) {

View File

@ -12,7 +12,9 @@
#include "nsIPrincipal.h"
#include "nsIObserver.h"
#include "nsDOMEventTargetHelper.h"
#include "mozilla/RefPtr.h"
#include "mozilla/StaticPtr.h"
#include "DOMRequest.h"
#define DEVICESTORAGE_PICTURES "pictures"
#define DEVICESTORAGE_VIDEOS "videos"
@ -24,49 +26,73 @@ class DeviceStorageFile MOZ_FINAL
: public nsISupports {
public:
nsCOMPtr<nsIFile> mFile;
nsString mPath;
nsString mStorageType;
nsString mStorageName;
nsString mRootDir;
nsString mPath;
bool mEditable;
// Used when the path will be set later via SetPath.
DeviceStorageFile(const nsAString& aStorageType);
DeviceStorageFile(const nsAString& aStorageType,
const nsAString& aStorageName);
// Used for non-enumeration purposes.
DeviceStorageFile(const nsAString& aStorageType, const nsAString& aPath);
DeviceStorageFile(const nsAString& aStorageType,
const nsAString& aStorageName,
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);
DeviceStorageFile(const nsAString& aStorageType,
const nsAString& aStorageName,
const nsAString& aRootDir,
const nsAString& aPath);
void SetPath(const nsAString& aPath);
void SetEditable(bool aEditable);
static already_AddRefed<DeviceStorageFile> CreateUnique(nsAString& aFileName,
uint32_t aFileType,
uint32_t aFileAttributes);
NS_DECL_ISUPPORTS
bool IsAvailable();
bool IsComposite();
void GetCompositePath(nsAString& aCompositePath);
// we want to make sure that the names of file can't reach
// outside of the type of storage the user asked for.
bool IsSafePath();
bool IsSafePath(const nsAString& aPath);
void Dump(const char* label);
nsresult Remove();
nsresult Write(nsIInputStream* aInputStream);
nsresult Write(InfallibleTArray<uint8_t>& bits);
void CollectFiles(nsTArray<nsRefPtr<DeviceStorageFile> > &aFiles, PRTime aSince = 0);
void collectFilesInternal(nsTArray<nsRefPtr<DeviceStorageFile> > &aFiles, PRTime aSince, nsAString& aRootPath);
void CollectFiles(nsTArray<nsRefPtr<DeviceStorageFile> >& aFiles,
PRTime aSince = 0);
void collectFilesInternal(nsTArray<nsRefPtr<DeviceStorageFile> >& aFiles,
PRTime aSince, nsAString& aRootPath);
static void DirectoryDiskUsage(nsIFile* aFile,
uint64_t* aPicturesSoFar,
uint64_t* aVideosSoFar,
uint64_t* aMusicSoFar,
uint64_t* aTotalSoFar);
void AccumDiskUsage(uint64_t* aPicturesSoFar, uint64_t* aVideosSoFar,
uint64_t* aMusicSoFar, uint64_t* aTotalSoFar);
static void GetRootDirectoryForType(const nsAString& aType,
const nsAString& aVolName,
void GetDiskFreeSpace(int64_t* aSoFar);
void GetStatus(nsAString& aStatus);
static void GetRootDirectoryForType(const nsAString& aStorageType,
const nsAString& aStorageName,
nsIFile** aFile);
private:
void Init(const nsAString& aStorageType);
void Init();
void NormalizeFilePath();
void AppendRelativePath(const nsAString& aPath);
void GetStatusInternal(nsAString& aStorageName, nsAString& aStatus);
void AccumDirectoryUsage(nsIFile* aFile,
uint64_t* aPicturesSoFar,
uint64_t* aVideosSoFar,
uint64_t* aMusicSoFar,
uint64_t* aTotalSoFar);
};
/*
@ -100,6 +126,8 @@ class nsDOMDeviceStorage MOZ_FINAL
, public nsIObserver
{
public:
typedef nsTArray<nsString> VolumeNameArray;
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIDOMDEVICESTORAGE
@ -117,18 +145,32 @@ public:
nsDOMDeviceStorage();
nsresult Init(nsPIDOMWindow* aWindow, const nsAString &aType, const nsAString &aVolName);
nsresult Init(nsPIDOMWindow* aWindow, const nsAString& aType,
nsTArray<nsRefPtr<nsDOMDeviceStorage> >& aStores);
nsresult Init(nsPIDOMWindow* aWindow, const nsAString& aType,
const nsAString& aVolName);
void SetRootDirectoryForType(const nsAString& aType, const nsAString &aVolName);
bool IsAvailable();
static void GetOrderedVolumeNames(const nsAString &aType,
nsTArray<nsString> &aVolumeNames);
void SetRootDirectoryForType(const nsAString& aType, const nsAString& aVolName);
static void CreateDeviceStorageFor(nsPIDOMWindow* aWin,
const nsAString& aType,
nsDOMDeviceStorage** aStore);
static void CreateDeviceStoragesFor(nsPIDOMWindow* aWin,
const nsAString &aType,
nsTArray<nsRefPtr<nsDOMDeviceStorage> > &aStores);
const nsAString& aType,
nsTArray<nsRefPtr<nsDOMDeviceStorage> >& aStores);
void Shutdown();
static void GetOrderedVolumeNames(nsTArray<nsString>& aVolumeNames);
static void GetWritableStorageName(const nsAString& aStorageType,
nsAString &aStorageName);
static bool ParseCompositePath(const nsAString& aCompositePath,
nsAString& aOutStorageName,
nsAString& aOutStoragePath);
private:
~nsDOMDeviceStorage();
@ -137,8 +179,17 @@ private:
nsIDOMDOMRequest** aRetval,
bool aEditable);
nsresult EnumerateInternal(const JS::Value & aName,
const JS::Value & aOptions,
nsresult GetInternal(nsPIDOMWindow* aWin,
const nsAString& aPath,
mozilla::dom::DOMRequest* aRequest,
bool aEditable);
nsresult DeleteInternal(nsPIDOMWindow* aWin,
const nsAString& aPath,
mozilla::dom::DOMRequest* aRequest);
nsresult EnumerateInternal(const JS::Value& aName,
const JS::Value& aOptions,
JSContext* aCx,
uint8_t aArgc,
bool aEditable,
@ -146,7 +197,13 @@ private:
nsString mStorageType;
nsCOMPtr<nsIFile> mRootDirectory;
nsString mVolumeName;
nsString mStorageName;
bool IsComposite() { return mStores.Length() > 0; }
nsTArray<nsRefPtr<nsDOMDeviceStorage> > mStores;
already_AddRefed<nsDOMDeviceStorage> GetStorage(const nsAString& aCompositePath,
nsAString& aOutStoragePath);
already_AddRefed<nsDOMDeviceStorage> GetStorageByName(const nsAString &aStorageName);
nsCOMPtr<nsIPrincipal> mPrincipal;
@ -158,8 +215,16 @@ private:
friend class WatchFileEvent;
friend class DeviceStorageRequest;
class VolumeNameCache : public mozilla::RefCounted<VolumeNameCache>
{
public:
nsTArray<nsString> mVolumeNames;
};
static mozilla::StaticRefPtr<VolumeNameCache> sVolumeNameCache;
#ifdef MOZ_WIDGET_GONK
void DispatchMountChangeEvent(nsAString& aType);
void DispatchMountChangeEvent(nsAString& aVolumeName,
nsAString& aVolumeStatus);
#endif
// nsIDOMDeviceStorage.type

View File

@ -51,7 +51,9 @@ DeviceStorageRequestChild::Recv__delete__(const DeviceStorageResponseValue& aVal
case DeviceStorageResponseValue::TSuccessResponse:
{
JS::Value result = StringToJsval(mRequest->GetOwner(), mFile->mPath);
nsString compositePath;
mFile->GetCompositePath(compositePath);
JS::Value result = StringToJsval(mRequest->GetOwner(), compositePath);
mRequest->FireSuccess(result);
break;
}
@ -101,7 +103,8 @@ DeviceStorageRequestChild::Recv__delete__(const DeviceStorageResponseValue& aVal
uint32_t count = r.paths().Length();
for (uint32_t i = 0; i < count; i++) {
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(r.type(),
r.relpath(),
r.paths()[i].storageName(),
r.rootdir(),
r.paths()[i].name());
cursor->mFiles.AppendElement(dsf);
}

View File

@ -37,7 +37,8 @@ DeviceStorageRequestParent::Dispatch()
{
DeviceStorageAddParams p = mParams;
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(p.type(), p.relpath());
nsRefPtr<DeviceStorageFile> dsf =
new DeviceStorageFile(p.type(), p.storageName(), p.relpath());
BlobParent* bp = static_cast<BlobParent*>(p.blobParent());
nsCOMPtr<nsIDOMBlob> blob = bp->GetBlob();
@ -56,7 +57,8 @@ DeviceStorageRequestParent::Dispatch()
case DeviceStorageParams::TDeviceStorageGetParams:
{
DeviceStorageGetParams p = mParams;
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(p.type(), p.rootDir(), p.relpath());
nsRefPtr<DeviceStorageFile> dsf =
new DeviceStorageFile(p.type(), p.storageName(), p.rootDir(), p.relpath());
nsRefPtr<CancelableRunnable> r = new ReadFileEvent(this, dsf);
nsCOMPtr<nsIEventTarget> target = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
@ -69,7 +71,8 @@ DeviceStorageRequestParent::Dispatch()
{
DeviceStorageDeleteParams p = mParams;
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(p.type(), p.relpath());
nsRefPtr<DeviceStorageFile> dsf =
new DeviceStorageFile(p.type(), p.storageName(), p.relpath());
nsRefPtr<CancelableRunnable> r = new DeleteFileEvent(this, dsf);
nsCOMPtr<nsIEventTarget> target = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
@ -82,7 +85,8 @@ DeviceStorageRequestParent::Dispatch()
{
DeviceStorageFreeSpaceParams p = mParams;
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(p.type(), p.relpath());
nsRefPtr<DeviceStorageFile> dsf =
new DeviceStorageFile(p.type(), p.storageName());
nsRefPtr<FreeSpaceFileEvent> r = new FreeSpaceFileEvent(this, dsf);
nsCOMPtr<nsIEventTarget> target = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
@ -98,7 +102,8 @@ DeviceStorageRequestParent::Dispatch()
DeviceStorageUsedSpaceParams p = mParams;
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(p.type(), p.relpath());
nsRefPtr<DeviceStorageFile> dsf =
new DeviceStorageFile(p.type(), p.storageName());
nsRefPtr<UsedSpaceFileEvent> r = new UsedSpaceFileEvent(this, dsf);
usedSpaceCache->Dispatch(r);
@ -109,7 +114,8 @@ DeviceStorageRequestParent::Dispatch()
{
DeviceStorageAvailableParams p = mParams;
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(p.type(), p.relpath());
nsRefPtr<DeviceStorageFile> dsf =
new DeviceStorageFile(p.type(), p.storageName());
nsRefPtr<PostAvailableResultEvent> r = new PostAvailableResultEvent(this, dsf);
NS_DispatchToMainThread(r);
break;
@ -118,7 +124,8 @@ DeviceStorageRequestParent::Dispatch()
case DeviceStorageParams::TDeviceStorageEnumerationParams:
{
DeviceStorageEnumerationParams p = mParams;
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(p.type(), p.relpath(), NS_LITERAL_STRING(""));
nsRefPtr<DeviceStorageFile> dsf
= new DeviceStorageFile(p.type(), p.storageName(), p.rootdir(), NS_LITERAL_STRING(""));
nsRefPtr<CancelableRunnable> r = new EnumerateFileEvent(this, dsf, p.since());
nsCOMPtr<nsIEventTarget> target = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
@ -351,7 +358,9 @@ DeviceStorageRequestParent::PostBlobSuccessEvent::CancelableRun() {
nsString mime;
CopyASCIItoUTF16(mMimeType, mime);
nsCOMPtr<nsIDOMBlob> blob = new nsDOMFileFile(mFile->mPath, mime, mLength, mFile->mFile, mLastModificationDate);
nsString compositePath;
mFile->GetCompositePath(compositePath);
nsCOMPtr<nsIDOMBlob> blob = new nsDOMFileFile(compositePath, mime, mLength, mFile->mFile, mLastModificationDate);
ContentParent* cp = static_cast<ContentParent*>(mParent->Manager());
BlobParent* actor = cp->GetOrCreateActorForBlob(blob);
@ -487,13 +496,12 @@ DeviceStorageRequestParent::FreeSpaceFileEvent::CancelableRun()
{
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
nsCOMPtr<nsIRunnable> r;
int64_t freeSpace = 0;
nsresult rv = mFile->mFile->GetDiskSpaceAvailable(&freeSpace);
if (NS_FAILED(rv)) {
freeSpace = 0;
if (mFile) {
mFile->GetDiskFreeSpace(&freeSpace);
}
nsCOMPtr<nsIRunnable> r;
r = new PostFreeSpaceResultEvent(mParent, static_cast<uint64_t>(freeSpace));
NS_DispatchToMainThread(r);
return NS_OK;
@ -515,40 +523,20 @@ DeviceStorageRequestParent::UsedSpaceFileEvent::CancelableRun()
{
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
DeviceStorageUsedSpaceCache* usedSpaceCache = DeviceStorageUsedSpaceCache::CreateOrGet();
NS_ASSERTION(usedSpaceCache, "DeviceStorageUsedSpaceCache is null");
nsCOMPtr<nsIRunnable> r;
uint64_t usedSize;
nsresult rv = usedSpaceCache->GetUsedSizeForType(mFile->mStorageType, &usedSize);
if (NS_SUCCEEDED(rv)) {
r = new PostUsedSpaceResultEvent(mParent, mFile->mStorageType, usedSize);
NS_DispatchToMainThread(r);
return NS_OK;
}
uint64_t picturesUsage = 0, videosUsage = 0, musicUsage = 0, totalUsage = 0;
DeviceStorageFile::DirectoryDiskUsage(mFile->mFile, &picturesUsage,
&videosUsage, &musicUsage,
&totalUsage);
if (mFile->mStorageType.EqualsLiteral(DEVICESTORAGE_APPS)) {
// Don't cache this since it's for a different volume from the media.
r = new PostUsedSpaceResultEvent(mParent, mFile->mStorageType, totalUsage);
mFile->AccumDiskUsage(&picturesUsage, &videosUsage,
&musicUsage, &totalUsage);
nsCOMPtr<nsIRunnable> r;
if (mFile->mStorageType.EqualsLiteral(DEVICESTORAGE_PICTURES)) {
r = new PostUsedSpaceResultEvent(mParent, mFile->mStorageType, picturesUsage);
}
else if (mFile->mStorageType.EqualsLiteral(DEVICESTORAGE_VIDEOS)) {
r = new PostUsedSpaceResultEvent(mParent, mFile->mStorageType, videosUsage);
}
else if (mFile->mStorageType.EqualsLiteral(DEVICESTORAGE_MUSIC)) {
r = new PostUsedSpaceResultEvent(mParent, mFile->mStorageType, musicUsage);
} else {
usedSpaceCache->SetUsedSizes(picturesUsage, videosUsage, musicUsage, totalUsage);
if (mFile->mStorageType.EqualsLiteral(DEVICESTORAGE_PICTURES)) {
r = new PostUsedSpaceResultEvent(mParent, mFile->mStorageType, picturesUsage);
}
else if (mFile->mStorageType.EqualsLiteral(DEVICESTORAGE_VIDEOS)) {
r = new PostUsedSpaceResultEvent(mParent, mFile->mStorageType, videosUsage);
}
else if (mFile->mStorageType.EqualsLiteral(DEVICESTORAGE_MUSIC)) {
r = new PostUsedSpaceResultEvent(mParent, mFile->mStorageType, musicUsage);
} else {
r = new PostUsedSpaceResultEvent(mParent, mFile->mStorageType, totalUsage);
}
r = new PostUsedSpaceResultEvent(mParent, mFile->mStorageType, totalUsage);
}
NS_DispatchToMainThread(r);
return NS_OK;
@ -627,12 +615,14 @@ DeviceStorageRequestParent::EnumerateFileEvent::CancelableRun()
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
nsCOMPtr<nsIRunnable> r;
bool check = false;
mFile->mFile->Exists(&check);
if (!check) {
r = new PostErrorEvent(mParent, POST_ERROR_EVENT_FILE_DOES_NOT_EXIST);
NS_DispatchToMainThread(r);
return NS_OK;
if (mFile->mFile) {
bool check = false;
mFile->mFile->Exists(&check);
if (!check) {
r = new PostErrorEvent(mParent, POST_ERROR_EVENT_FILE_DOES_NOT_EXIST);
NS_DispatchToMainThread(r);
return NS_OK;
}
}
nsTArray<nsRefPtr<DeviceStorageFile> > files;
@ -642,7 +632,7 @@ DeviceStorageRequestParent::EnumerateFileEvent::CancelableRun()
uint32_t count = files.Length();
for (uint32_t i = 0; i < count; i++) {
DeviceStorageFileValue dsvf(files[i]->mPath);
DeviceStorageFileValue dsvf(files[i]->mStorageName, files[i]->mPath);
values.AppendElement(dsvf);
}
@ -689,18 +679,10 @@ DeviceStorageRequestParent::PostAvailableResultEvent::CancelableRun()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
nsString state;
state.Assign(NS_LITERAL_STRING("available"));
#ifdef MOZ_WIDGET_GONK
nsString path;
nsresult rv = mFile->mFile->GetPath(path);
if (NS_SUCCEEDED(rv)) {
rv = GetSDCardStatus(path, state);
nsString state = NS_LITERAL_STRING("unavailable");
if (mFile) {
mFile->GetStatus(state);
}
if (NS_FAILED(rv)) {
state.Assign(NS_LITERAL_STRING("unavailable"));
}
#endif
AvailableStorageResponse response(state);
unused << mParent->Send__delete__(mParent, response);

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -28,6 +28,7 @@ class nsPIDOMWindow;
#include "prtime.h"
#include "DeviceStorage.h"
#include "mozilla/dom/devicestorage/DeviceStorageRequestChild.h"
#include "mozilla/RefPtr.h"
#include "mozilla/StaticPtr.h"
namespace mozilla {
@ -64,52 +65,71 @@ public:
class InvalidateRunnable MOZ_FINAL : public nsRunnable
{
public:
InvalidateRunnable(DeviceStorageUsedSpaceCache* aCache) {
mOwner = aCache;
}
InvalidateRunnable(DeviceStorageUsedSpaceCache* aCache,
const nsAString& aStorageName)
: mCache(aCache)
, mStorageName(aStorageName) {}
~InvalidateRunnable() {}
NS_IMETHOD Run() {
mOwner->mDirty = true;
NS_IMETHOD Run()
{
mozilla::RefPtr<DeviceStorageUsedSpaceCache::CacheEntry> cacheEntry;
cacheEntry = mCache->GetCacheEntry(mStorageName);
if (cacheEntry) {
cacheEntry->mDirty = true;
}
return NS_OK;
}
private:
DeviceStorageUsedSpaceCache* mOwner;
DeviceStorageUsedSpaceCache* mCache;
nsString mStorageName;
};
void Invalidate() {
void Invalidate(const nsAString& aStorageName)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(mIOThread, "Null mIOThread!");
nsRefPtr<InvalidateRunnable> r = new InvalidateRunnable(this);
nsRefPtr<InvalidateRunnable> r = new InvalidateRunnable(this, aStorageName);
mIOThread->Dispatch(r, NS_DISPATCH_NORMAL);
}
void Dispatch(nsIRunnable* aRunnable) {
void Dispatch(nsIRunnable* aRunnable)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(mIOThread, "Null mIOThread!");
mIOThread->Dispatch(aRunnable, NS_DISPATCH_NORMAL);
}
nsresult GetUsedSizeForType(const nsAString& aStorageType, uint64_t* usedSize);
void SetUsedSizes(uint64_t aPictureSize, uint64_t aVideosSize,
nsresult GetUsedSizeForType(const nsAString& aStorageType,
const nsAString& aStorageName,
uint64_t* usedSize);
nsresult AccumUsedSizes(const nsAString& aStorageName,
uint64_t* aPictureSize, uint64_t* aVideosSize,
uint64_t* aMusicSize, uint64_t* aTotalSize);
void SetUsedSizes(const nsAString& aStorageName,
uint64_t aPictureSize, uint64_t aVideosSize,
uint64_t aMusicSize, uint64_t aTotalSize);
private:
friend class InvalidateRunnable;
nsresult GetPicturesUsedSize(uint64_t* usedSize);
nsresult GetMusicUsedSize(uint64_t* usedSize);
nsresult GetVideosUsedSize(uint64_t* usedSize);
nsresult GetTotalUsedSize(uint64_t* usedSize);
class CacheEntry : public mozilla::RefCounted<CacheEntry>
{
public:
bool mDirty;
nsString mStorageName;
uint64_t mPicturesUsedSize;
uint64_t mVideosUsedSize;
uint64_t mMusicUsedSize;
uint64_t mTotalUsedSize;
};
mozilla::TemporaryRef<CacheEntry> GetCacheEntry(const nsAString& aStorageName);
bool mDirty;
uint64_t mPicturesUsedSize;
uint64_t mVideosUsedSize;
uint64_t mMusicUsedSize;
uint64_t mTotalUsedSize;
nsTArray<mozilla::RefPtr<CacheEntry> > mCacheEntries;
nsCOMPtr<nsIThread> mIOThread;
@ -129,6 +149,7 @@ public:
bool Check(const nsAString& aType, nsIDOMBlob* aBlob);
bool Check(const nsAString& aType, nsIFile* aFile);
void GetTypeFromFile(nsIFile* aFile, nsAString& aType);
void GetTypeFromFileName(const nsAString& aFileName, nsAString& aType);
static nsresult GetPermissionForType(const nsAString& aType, nsACString& aPermissionResult);
static nsresult GetAccessForRequest(const DeviceStorageRequestType aRequestType, nsACString& aAccessResult);
@ -204,8 +225,4 @@ nsIFileToJsval(nsPIDOMWindow* aWindow, DeviceStorageFile* aFile);
JS::Value
InterfaceToJsval(nsPIDOMWindow* aWindow, nsISupports* aObject, const nsIID* aIID);
#ifdef MOZ_WIDGET_GONK
nsresult GetSDCardStatus(nsAString& aPath, nsAString& aState);
#endif
#endif

View File

@ -34,6 +34,18 @@ function enumerateSuccess(e) {
}
var filename = e.target.result.name;
if (filename[0] == "/") {
// We got /storgaeName/prefix/filename
// Remove the storageName (this shows up on FirefoxOS)
filename = filename.substring(1); // Remove leading slash
var slashIndex = filename.indexOf("/");
if (slashIndex >= 0) {
filename = filename.substring(slashIndex + 1); // Remove storageName
}
}
if (filename.startsWith(prefix)) {
filename = filename.substring(prefix.length + 1); // Remove prefix
}
var index = files.indexOf(filename);
files.remove(index);
@ -41,7 +53,7 @@ function enumerateSuccess(e) {
ok(index > -1, "filename should be in the enumeration : " + e.target.result.name);
// clean up
var cleanup = storage.delete(prefix + "/" + filename);
var cleanup = storage.delete(e.target.result.name);
cleanup.onsuccess = function(e) {} // todo - can i remove this?
e.target.continue();

View File

@ -36,16 +36,30 @@ function enumerateSuccess(e) {
if (e.target.result == null) {
ok(files.length == 0, "when the enumeration is done, we shouldn't have any files in this array")
devicestorage_cleanup();
return;
}
var filename = e.target.result.name;
var index = files.indexOf(filename);
if (filename[0] == "/") {
// We got /storgaeName/prefix/filename
// Remove the storageName (this shows up on FirefoxOS)
filename = filename.substring(1); // Remove leading slash
var slashIndex = filename.indexOf("/");
if (slashIndex >= 0) {
filename = filename.substring(slashIndex + 1); // Remove storageName
}
}
if (filename.startsWith(prefix)) {
filename = filename.substring(prefix.length + 1); // Remove prefix
}
var index = files.indexOf(enumFilename);
files.remove(index);
ok(index > -1, "filename should be in the enumeration : " + e.target.result.name);
// clean up
var cleanup = storage.delete(prefix + "/" + filename);
var cleanup = storage.delete(e.target.result.name);
cleanup.onsuccess = function(e) {} // todo - can i remove this?
e.target.continue();

View File

@ -35,6 +35,18 @@ function verifyAndDelete(prefix, files, e) {
}
var filename = e.target.result.name;
if (filename[0] == "/") {
// We got /storgaeName/prefix/filename
// Remove the storageName (this shows up on FirefoxOS)
filename = filename.substring(1); // Remove leading slash
var slashIndex = filename.indexOf("/");
if (slashIndex >= 0) {
filename = filename.substring(slashIndex + 1); // Remove storageName
}
}
if (filename.startsWith(prefix)) {
filename = filename.substring(prefix.length + 1); // Remove prefix
}
var index = files.indexOf(filename);
ok(index > -1, "filename should be in the enumeration : " + e.target.result.name);

View File

@ -16,7 +16,7 @@ dictionary DeviceStorageEnumerationParameters
jsval since;
};
[scriptable, uuid(b6274c63-daa2-4c7a-aa45-b72e45b5f2d2), builtinclass]
[scriptable, uuid(3d336180-b130-4b54-b205-ce74e36e733f), builtinclass]
interface nsIDOMDeviceStorage : nsIDOMEventTarget
{
[implicit_jscontext] attribute jsval onchange;
@ -44,9 +44,9 @@ interface nsIDOMDeviceStorage : nsIDOMEventTarget
nsIDOMDOMRequest available();
// Note that the volumeName is just a name (like sdcard), and doesn't
// Note that the storageName is just a name (like sdcard), and doesn't
// include any path information.
readonly attribute DOMString volumeName;
readonly attribute DOMString storageName;
[noscript] readonly attribute nsIFile rootDirectory;
};

View File

@ -1162,9 +1162,12 @@ ContentChild::RecvLastPrivateDocShellDestroyed()
}
bool
ContentChild::RecvFilePathUpdate(const nsString& type, const nsString& path, const nsCString& aReason)
ContentChild::RecvFilePathUpdate(const nsString& aStorageType,
const nsString& aStorageName,
const nsString& aPath,
const nsCString& aReason)
{
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(type, path);
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(aStorageType, aStorageName, aPath);
nsString reason;
CopyASCIItoUTF16(aReason, reason);
@ -1175,12 +1178,12 @@ ContentChild::RecvFilePathUpdate(const nsString& type, const nsString& path, con
bool
ContentChild::RecvFileSystemUpdate(const nsString& aFsName,
const nsString& aName,
const nsString& aVolumeName,
const int32_t& aState,
const int32_t& aMountGeneration)
{
#ifdef MOZ_WIDGET_GONK
nsRefPtr<nsVolume> volume = new nsVolume(aFsName, aName, aState,
nsRefPtr<nsVolume> volume = new nsVolume(aFsName, aVolumeName, aState,
aMountGeneration);
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
@ -1189,7 +1192,7 @@ ContentChild::RecvFileSystemUpdate(const nsString& aFsName,
#else
// Remove warnings about unused arguments
unused << aFsName;
unused << aName;
unused << aVolumeName;
unused << aState;
unused << aMountGeneration;
#endif

View File

@ -186,9 +186,12 @@ public:
virtual bool RecvLastPrivateDocShellDestroyed();
virtual bool RecvFilePathUpdate(const nsString& type, const nsString& path, const nsCString& reason);
virtual bool RecvFilePathUpdate(const nsString& aStorageType,
const nsString& aStorageName,
const nsString& aPath,
const nsCString& aReason);
virtual bool RecvFileSystemUpdate(const nsString& aFsName,
const nsString& aName,
const nsString& aVolumeName,
const int32_t& aState,
const int32_t& aMountGeneration);

View File

@ -1510,7 +1510,7 @@ ContentParent::Observe(nsISupports* aSubject,
CopyUTF16toUTF8(aData, creason);
DeviceStorageFile* file = static_cast<DeviceStorageFile*>(aSubject);
unused << SendFilePathUpdate(file->mStorageType, file->mPath, creason);
unused << SendFilePathUpdate(file->mStorageType, file->mStorageName, file->mPath, creason);
}
#ifdef MOZ_WIDGET_GONK
else if(!strcmp(aTopic, NS_VOLUME_STATE_CHANGED)) {
@ -2350,16 +2350,20 @@ ContentParent::RecvAsyncMessage(const nsString& aMsg,
bool
ContentParent::RecvFilePathUpdateNotify(const nsString& aType,
const nsString& aStorageName,
const nsString& aFilePath,
const nsCString& aReason)
{
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(aType, aFilePath);
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(aType,
aStorageName,
aFilePath);
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (!obs) {
return false;
}
obs->NotifyObservers(dsf, "file-watcher-update", NS_ConvertASCIItoUTF16(aReason).get());
obs->NotifyObservers(dsf, "file-watcher-update",
NS_ConvertASCIItoUTF16(aReason).get());
return true;
}

View File

@ -367,6 +367,7 @@ private:
const ClonedMessageData& aData);
virtual bool RecvFilePathUpdateNotify(const nsString& aType,
const nsString& aStorageName,
const nsString& aFilePath,
const nsCString& aReason);

View File

@ -65,24 +65,25 @@ struct FontListEntry {
struct DeviceStorageFreeSpaceParams
{
nsString type;
nsString relpath;
nsString storageName;
};
struct DeviceStorageUsedSpaceParams
{
nsString type;
nsString relpath;
nsString storageName;
};
struct DeviceStorageAvailableParams
{
nsString type;
nsString relpath;
nsString storageName;
};
struct DeviceStorageAddParams
{
nsString type;
nsString storageName;
nsString relpath;
PBlob blob;
};
@ -90,6 +91,7 @@ struct DeviceStorageAddParams
struct DeviceStorageGetParams
{
nsString type;
nsString storageName;
nsString rootDir;
nsString relpath;
};
@ -97,13 +99,15 @@ struct DeviceStorageGetParams
struct DeviceStorageDeleteParams
{
nsString type;
nsString storageName;
nsString relpath;
};
struct DeviceStorageEnumerationParams
{
nsString type;
nsString relpath;
nsString storageName;
nsString rootdir;
uint64_t since;
};
@ -346,7 +350,8 @@ child:
// Notify child that last-pb-context-exited notification was observed
LastPrivateDocShellDestroyed();
FilePathUpdate(nsString type, nsString filepath, nsCString reasons);
FilePathUpdate(nsString storageType, nsString storageName, nsString filepath,
nsCString reasons);
FileSystemUpdate(nsString fsName, nsString mountPoint, int32_t fsState,
int32_t mountGeneration);
@ -494,6 +499,7 @@ parent:
async AudioChannelChangedNotification();
async FilePathUpdateNotify(nsString aType,
nsString aStorageName,
nsString aFilepath,
nsCString aReason);
// get nsIVolumeService to broadcast volume information

View File

@ -196,9 +196,21 @@ nsVolumeService::GetVolumeByPath(const nsAString& aPath, nsIVolume **aResult)
nsCString utf8Path = NS_ConvertUTF16toUTF8(aPath);
char realPathBuf[PATH_MAX];
if (!realpath(utf8Path.get(), realPathBuf)) {
ERR("GetVolumeByPath: realpath on '%s' failed: %d", utf8Path.get(), errno);
return NSRESULT_FOR_ERRNO();
while (realpath(utf8Path.get(), realPathBuf) < 0) {
if (errno != ENOENT) {
ERR("GetVolumeByPath: realpath on '%s' failed: %d", utf8Path.get(), errno);
return NSRESULT_FOR_ERRNO();
}
// The pathname we were passed doesn't exist, so we try stripping off trailing
// components until we get a successful call to realpath, or until we run out
// of components (if we finally get to /something then we also stop).
int32_t slashIndex = utf8Path.RFindChar('/');
if ((slashIndex == kNotFound) || (slashIndex == 0)) {
errno = ENOENT;
ERR("GetVolumeByPath: realpath on '%s' failed.", utf8Path.get());
return NSRESULT_FOR_ERRNO();
}
utf8Path = Substring(utf8Path, 0, slashIndex);
}
// The volume mount point is always a directory. Something like /mnt/sdcard