forked from mirrors/gecko-dev
Bug 1299500 - Get rid of DeviceStorage API - part 10 - DeviceStorage, r=ehsan, r=billm
This commit is contained in:
parent
fb4c8780f3
commit
12b54aa0f5
75 changed files with 1 additions and 11992 deletions
|
|
@ -89,38 +89,6 @@ var AdbController = {
|
|||
|
||||
updateState: function() {
|
||||
this.umsActive = false;
|
||||
this.storages = navigator.getDeviceStorages('sdcard');
|
||||
this.updateStorageState(0);
|
||||
},
|
||||
|
||||
updateStorageState: function(storageIndex) {
|
||||
if (storageIndex >= this.storages.length) {
|
||||
// We've iterated through all of the storage objects, now we can
|
||||
// really do updateStateInternal.
|
||||
this.updateStateInternal();
|
||||
return;
|
||||
}
|
||||
let storage = this.storages[storageIndex];
|
||||
DEBUG && debug("Checking availability of storage: '" + storage.storageName + "'");
|
||||
|
||||
let req = storage.available();
|
||||
req.onsuccess = function(e) {
|
||||
DEBUG && debug("Storage: '" + storage.storageName + "' is '" + e.target.result + "'");
|
||||
if (e.target.result == 'shared') {
|
||||
// We've found a storage area that's being shared with the PC.
|
||||
// We can stop looking now.
|
||||
this.umsActive = true;
|
||||
this.updateStateInternal();
|
||||
return;
|
||||
}
|
||||
this.updateStorageState(storageIndex + 1);
|
||||
}.bind(this);
|
||||
req.onerror = function(e) {
|
||||
|
||||
Cu.reportError("AdbController: error querying storage availability for '" +
|
||||
this.storages[storageIndex].storageName + "' (ignoring)\n");
|
||||
this.updateStorageState(storageIndex + 1);
|
||||
}.bind(this);
|
||||
},
|
||||
|
||||
updateStateInternal: function() {
|
||||
|
|
|
|||
|
|
@ -307,11 +307,6 @@ DOMInterfaces = {
|
|||
'headerFile': 'mozilla/dom/DeviceMotionEvent.h',
|
||||
},
|
||||
|
||||
'DeviceStorage': {
|
||||
'nativeType': 'nsDOMDeviceStorage',
|
||||
'headerFile': 'DeviceStorage.h',
|
||||
},
|
||||
|
||||
'Document': {
|
||||
'nativeType': 'nsIDocument',
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,382 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef DeviceStorage_h
|
||||
#define DeviceStorage_h
|
||||
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "mozilla/dom/DOMRequest.h"
|
||||
#include "nsWeakReference.h"
|
||||
|
||||
#define DEVICESTORAGE_PICTURES "pictures"
|
||||
#define DEVICESTORAGE_VIDEOS "videos"
|
||||
#define DEVICESTORAGE_MUSIC "music"
|
||||
#define DEVICESTORAGE_APPS "apps"
|
||||
#define DEVICESTORAGE_SDCARD "sdcard"
|
||||
#define DEVICESTORAGE_CRASHES "crashes"
|
||||
|
||||
class nsIInputStream;
|
||||
class nsIOutputStream;
|
||||
struct DeviceStorageFileDescriptor;
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
class nsIVolume;
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
class EventListenerManager;
|
||||
namespace dom {
|
||||
class Blob;
|
||||
struct DeviceStorageEnumerationParameters;
|
||||
class DOMCursor;
|
||||
class DOMRequest;
|
||||
class Promise;
|
||||
class DeviceStorageFileSystem;
|
||||
} // namespace dom
|
||||
namespace ipc {
|
||||
class FileDescriptor;
|
||||
class PrincipalInfo;
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
||||
|
||||
class DeviceStorageRequest;
|
||||
class DeviceStorageCursorRequest;
|
||||
class DeviceStorageRequestManager;
|
||||
class nsDOMDeviceStorageCursor;
|
||||
|
||||
class DeviceStorageFile final
|
||||
: public nsISupports {
|
||||
public:
|
||||
nsCOMPtr<nsIFile> mFile;
|
||||
nsString mStorageType;
|
||||
nsString mStorageName;
|
||||
nsString mRootDir;
|
||||
nsString mPath;
|
||||
bool mEditable;
|
||||
nsString mMimeType;
|
||||
uint64_t mLength;
|
||||
uint64_t mLastModifiedDate;
|
||||
|
||||
// Used when the path will be set later via SetPath.
|
||||
DeviceStorageFile(const nsAString& aStorageType,
|
||||
const nsAString& aStorageName);
|
||||
// Used for non-enumeration purposes.
|
||||
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& 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);
|
||||
|
||||
static already_AddRefed<DeviceStorageFile>
|
||||
CreateUnique(const nsAString& aStorageType,
|
||||
const nsAString& aStorageName,
|
||||
nsAString& aFileName,
|
||||
uint32_t aFileType,
|
||||
uint32_t aFileAttributes);
|
||||
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
||||
bool IsAvailable();
|
||||
void GetFullPath(nsAString& aFullPath);
|
||||
|
||||
// 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() const;
|
||||
bool ValidateAndSplitPath(const nsAString& aPath,
|
||||
nsTArray<nsString>* aParts = nullptr) const;
|
||||
|
||||
void Dump(const char* label);
|
||||
|
||||
nsresult Remove();
|
||||
nsresult Write(nsIInputStream* aInputStream);
|
||||
nsresult Write(InfallibleTArray<uint8_t>& bits);
|
||||
nsresult Append(nsIInputStream* aInputStream);
|
||||
nsresult Append(nsIInputStream* aInputStream,
|
||||
nsIOutputStream* aOutputStream);
|
||||
void CollectFiles(nsTArray<RefPtr<DeviceStorageFile> >& aFiles,
|
||||
PRTime aSince = 0);
|
||||
void collectFilesInternal(nsTArray<RefPtr<DeviceStorageFile> >& aFiles,
|
||||
PRTime aSince, nsAString& aRootPath);
|
||||
|
||||
void AccumDiskUsage(uint64_t* aPicturesSoFar, uint64_t* aVideosSoFar,
|
||||
uint64_t* aMusicSoFar, uint64_t* aTotalSoFar);
|
||||
|
||||
void GetStorageFreeSpace(int64_t* aSoFar);
|
||||
void GetStatus(nsAString& aStatus);
|
||||
void GetStorageStatus(nsAString& aStatus);
|
||||
void DoFormat(nsAString& aStatus);
|
||||
void DoMount(nsAString& aStatus);
|
||||
void DoUnmount(nsAString& aStatus);
|
||||
static void GetRootDirectoryForType(const nsAString& aStorageType,
|
||||
const nsAString& aStorageName,
|
||||
nsIFile** aFile);
|
||||
|
||||
nsresult CalculateSizeAndModifiedDate();
|
||||
nsresult CalculateMimeType();
|
||||
nsresult CreateFileDescriptor(mozilla::ipc::FileDescriptor& aFileDescriptor);
|
||||
|
||||
private:
|
||||
~DeviceStorageFile() {}
|
||||
void Init();
|
||||
void AppendRelativePath(const nsAString& aPath);
|
||||
void AccumDirectoryUsage(nsIFile* aFile,
|
||||
uint64_t* aPicturesSoFar,
|
||||
uint64_t* aVideosSoFar,
|
||||
uint64_t* aMusicSoFar,
|
||||
uint64_t* aTotalSoFar);
|
||||
};
|
||||
|
||||
#define NS_DOM_DEVICE_STORAGE_CID \
|
||||
{ 0xe4a9b969, 0x81fe, 0x44f1, \
|
||||
{ 0xaa, 0x0c, 0x9e, 0x16, 0x64, 0x86, 0x2a, 0xd5 } }
|
||||
|
||||
class nsDOMDeviceStorage final
|
||||
: public mozilla::DOMEventTargetHelper
|
||||
, public nsSupportsWeakReference
|
||||
{
|
||||
typedef mozilla::ErrorResult ErrorResult;
|
||||
typedef mozilla::dom::DeviceStorageEnumerationParameters
|
||||
EnumerationParameters;
|
||||
typedef mozilla::dom::DOMCursor DOMCursor;
|
||||
typedef mozilla::dom::DOMRequest DOMRequest;
|
||||
typedef mozilla::dom::Promise Promise;
|
||||
typedef mozilla::dom::DeviceStorageFileSystem DeviceStorageFileSystem;
|
||||
public:
|
||||
typedef nsTArray<nsString> VolumeNameArray;
|
||||
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_DOM_DEVICE_STORAGE_CID)
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_REALLY_FORWARD_NSIDOMEVENTTARGET(DOMEventTargetHelper)
|
||||
|
||||
void EventListenerWasAdded(const nsAString& aType,
|
||||
ErrorResult& aRv,
|
||||
JSCompartment* aCompartment) override;
|
||||
|
||||
explicit nsDOMDeviceStorage(nsPIDOMWindowInner* aWindow);
|
||||
|
||||
static int InstanceCount() { return sInstanceCount; }
|
||||
|
||||
static void InvalidateVolumeCaches();
|
||||
|
||||
nsresult Init(nsPIDOMWindowInner* aWindow, const nsAString& aType,
|
||||
const nsAString& aVolName);
|
||||
|
||||
bool IsAvailable();
|
||||
bool IsFullPath(const nsAString& aPath)
|
||||
{
|
||||
return aPath.Length() > 0 && aPath.CharAt(0) == '/';
|
||||
}
|
||||
|
||||
void SetRootDirectoryForType(const nsAString& aType,
|
||||
const nsAString& aVolName);
|
||||
|
||||
// WebIDL
|
||||
nsPIDOMWindowInner*
|
||||
GetParentObject() const
|
||||
{
|
||||
return GetOwner();
|
||||
}
|
||||
virtual JSObject*
|
||||
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
IMPL_EVENT_HANDLER(change)
|
||||
|
||||
already_AddRefed<DOMRequest>
|
||||
Add(mozilla::dom::Blob* aBlob, ErrorResult& aRv);
|
||||
already_AddRefed<DOMRequest>
|
||||
AddNamed(mozilla::dom::Blob* aBlob, const nsAString& aPath, ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<DOMRequest>
|
||||
AppendNamed(mozilla::dom::Blob* aBlob, const nsAString& aPath,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<DOMRequest>
|
||||
Get(const nsAString& aPath, ErrorResult& aRv)
|
||||
{
|
||||
return GetInternal(aPath, false, aRv);
|
||||
}
|
||||
already_AddRefed<DOMRequest>
|
||||
GetEditable(const nsAString& aPath, ErrorResult& aRv)
|
||||
{
|
||||
return GetInternal(aPath, true, aRv);
|
||||
}
|
||||
already_AddRefed<DOMRequest>
|
||||
Delete(const nsAString& aPath, ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<DOMCursor>
|
||||
Enumerate(const EnumerationParameters& aOptions, ErrorResult& aRv)
|
||||
{
|
||||
return Enumerate(NullString(), aOptions, aRv);
|
||||
}
|
||||
already_AddRefed<DOMCursor>
|
||||
Enumerate(const nsAString& aPath, const EnumerationParameters& aOptions,
|
||||
ErrorResult& aRv);
|
||||
already_AddRefed<DOMCursor>
|
||||
EnumerateEditable(const EnumerationParameters& aOptions, ErrorResult& aRv)
|
||||
{
|
||||
return EnumerateEditable(NullString(), aOptions, aRv);
|
||||
}
|
||||
already_AddRefed<DOMCursor>
|
||||
EnumerateEditable(const nsAString& aPath,
|
||||
const EnumerationParameters& aOptions, ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<DOMRequest> FreeSpace(ErrorResult& aRv);
|
||||
already_AddRefed<DOMRequest> UsedSpace(ErrorResult& aRv);
|
||||
already_AddRefed<DOMRequest> Available(ErrorResult& aRv);
|
||||
already_AddRefed<DOMRequest> Format(ErrorResult& aRv);
|
||||
already_AddRefed<DOMRequest> StorageStatus(ErrorResult& aRv);
|
||||
already_AddRefed<DOMRequest> Mount(ErrorResult& aRv);
|
||||
already_AddRefed<DOMRequest> Unmount(ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<DOMRequest> CreateFileDescriptor(const nsAString& aPath,
|
||||
DeviceStorageFileDescriptor* aDSFD,
|
||||
ErrorResult& aRv);
|
||||
|
||||
bool CanBeMounted();
|
||||
bool CanBeFormatted();
|
||||
bool CanBeShared();
|
||||
bool IsRemovable();
|
||||
bool LowDiskSpace();
|
||||
bool Default();
|
||||
void GetStorageName(nsAString& aStorageName);
|
||||
|
||||
already_AddRefed<Promise>
|
||||
GetRoot(ErrorResult& aRv);
|
||||
|
||||
static void
|
||||
CreateDeviceStorageFor(nsPIDOMWindowInner* aWin,
|
||||
const nsAString& aType,
|
||||
nsDOMDeviceStorage** aStore);
|
||||
|
||||
static void
|
||||
CreateDeviceStorageByNameAndType(nsPIDOMWindowInner* aWin,
|
||||
const nsAString& aName,
|
||||
const nsAString& aType,
|
||||
nsDOMDeviceStorage** aStore);
|
||||
|
||||
bool Equals(nsPIDOMWindowInner* aWin,
|
||||
const nsAString& aName,
|
||||
const nsAString& aType);
|
||||
|
||||
void Shutdown();
|
||||
|
||||
static void GetOrderedVolumeNames(const nsAString& aType,
|
||||
nsTArray<nsString>& aVolumeNames);
|
||||
|
||||
static void GetOrderedVolumeNames(nsTArray<nsString>& aVolumeNames);
|
||||
|
||||
static void GetDefaultStorageName(const nsAString& aStorageType,
|
||||
nsAString& aStorageName);
|
||||
|
||||
static bool ParseFullPath(const nsAString& aFullPath,
|
||||
nsAString& aOutStorageName,
|
||||
nsAString& aOutStoragePath);
|
||||
|
||||
// DeviceStorageStatics callbacks
|
||||
void OnFileWatcherUpdate(const nsCString& aData, DeviceStorageFile* aFile);
|
||||
void OnDiskSpaceWatcher(bool aLowDiskSpace);
|
||||
void OnWritableNameChanged();
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
void OnVolumeStateChanged(nsIVolume* aVolume);
|
||||
#endif
|
||||
|
||||
uint32_t CreateDOMRequest(DOMRequest** aRequest, ErrorResult& aRv);
|
||||
uint32_t CreateDOMCursor(DeviceStorageCursorRequest* aRequest,
|
||||
nsDOMDeviceStorageCursor** aCursor,
|
||||
ErrorResult& aRv);
|
||||
already_AddRefed<DOMRequest> CreateAndRejectDOMRequest(const char *aReason,
|
||||
ErrorResult& aRv);
|
||||
|
||||
nsresult CheckPermission(already_AddRefed<DeviceStorageRequest>&& aRequest);
|
||||
|
||||
bool IsOwningThread();
|
||||
nsresult DispatchToOwningThread(already_AddRefed<nsIRunnable>&& aRunnable);
|
||||
|
||||
private:
|
||||
~nsDOMDeviceStorage();
|
||||
|
||||
static nsresult CheckPrincipal(nsPIDOMWindowInner* aWindow,
|
||||
bool aIsAppsStorage,
|
||||
nsIPrincipal** aPrincipal);
|
||||
|
||||
already_AddRefed<DOMRequest>
|
||||
AddOrAppendNamed(mozilla::dom::Blob* aBlob, const nsAString& aPath,
|
||||
bool aCreate, ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<DOMRequest>
|
||||
GetInternal(const nsAString& aPath, bool aEditable, ErrorResult& aRv);
|
||||
|
||||
void
|
||||
DeleteInternal(nsPIDOMWindowInner* aWin, const nsAString& aPath,
|
||||
DOMRequest* aRequest);
|
||||
|
||||
already_AddRefed<DOMCursor>
|
||||
EnumerateInternal(const nsAString& aName,
|
||||
const EnumerationParameters& aOptions, bool aEditable,
|
||||
ErrorResult& aRv);
|
||||
|
||||
static int sInstanceCount;
|
||||
|
||||
nsString mStorageType;
|
||||
nsCOMPtr<nsIFile> mRootDirectory;
|
||||
nsString mStorageName;
|
||||
bool mIsShareable;
|
||||
bool mIsRemovable;
|
||||
|
||||
already_AddRefed<nsDOMDeviceStorage> GetStorage(const nsAString& aFullPath,
|
||||
nsAString& aOutStoragePath);
|
||||
already_AddRefed<nsDOMDeviceStorage>
|
||||
GetStorageByName(const nsAString &aStorageName);
|
||||
|
||||
static already_AddRefed<nsDOMDeviceStorage>
|
||||
GetStorageByNameAndType(nsPIDOMWindowInner* aWin,
|
||||
const nsAString& aStorageName,
|
||||
const nsAString& aType);
|
||||
|
||||
bool mIsDefaultLocation;
|
||||
|
||||
nsresult Notify(const char* aReason, class DeviceStorageFile* aFile);
|
||||
|
||||
friend class WatchFileEvent;
|
||||
friend class DeviceStorageRequest;
|
||||
|
||||
static mozilla::StaticAutoPtr<nsTArray<nsString>> sVolumeNameCache;
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
nsString mLastStatus;
|
||||
nsString mLastStorageStatus;
|
||||
void DispatchStatusChangeEvent(nsAString& aStatus);
|
||||
void DispatchStorageStatusChangeEvent(nsAString& aStorageStatus);
|
||||
#endif
|
||||
|
||||
uint64_t mInnerWindowID;
|
||||
RefPtr<DeviceStorageFileSystem> mFileSystem;
|
||||
RefPtr<DeviceStorageRequestManager> mManager;
|
||||
nsAutoPtr<mozilla::ipc::PrincipalInfo> mPrincipalInfo;
|
||||
nsCOMPtr<nsIThread> mOwningThread;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsDOMDeviceStorage, NS_DOM_DEVICE_STORAGE_CID)
|
||||
|
||||
#endif
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef DeviceStorageFileDescriptor_h
|
||||
#define DeviceStorageFileDescriptor_h
|
||||
|
||||
#include "mozilla/ipc/FileDescriptor.h"
|
||||
|
||||
struct DeviceStorageFileDescriptor final
|
||||
{
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DeviceStorageFileDescriptor)
|
||||
RefPtr<DeviceStorageFile> mDSFile;
|
||||
mozilla::ipc::FileDescriptor mFileDescriptor;
|
||||
private:
|
||||
~DeviceStorageFileDescriptor() {}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,151 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
#include "DeviceStorageRequestChild.h"
|
||||
#include "DeviceStorageFileDescriptor.h"
|
||||
#include "nsDeviceStorage.h"
|
||||
#include "mozilla/dom/File.h"
|
||||
#include "mozilla/dom/ipc/BlobChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace devicestorage {
|
||||
|
||||
DeviceStorageRequestChild::DeviceStorageRequestChild()
|
||||
{
|
||||
MOZ_COUNT_CTOR(DeviceStorageRequestChild);
|
||||
}
|
||||
|
||||
DeviceStorageRequestChild::DeviceStorageRequestChild(DeviceStorageRequest* aRequest)
|
||||
: mRequest(aRequest)
|
||||
{
|
||||
MOZ_ASSERT(aRequest);
|
||||
MOZ_COUNT_CTOR(DeviceStorageRequestChild);
|
||||
}
|
||||
|
||||
DeviceStorageRequestChild::~DeviceStorageRequestChild() {
|
||||
MOZ_COUNT_DTOR(DeviceStorageRequestChild);
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
DeviceStorageRequestChild::
|
||||
Recv__delete__(const DeviceStorageResponseValue& aValue)
|
||||
{
|
||||
switch (aValue.type()) {
|
||||
|
||||
case DeviceStorageResponseValue::TErrorResponse:
|
||||
{
|
||||
DS_LOG_INFO("error %u", mRequest->GetId());
|
||||
ErrorResponse r = aValue;
|
||||
mRequest->Reject(r.error());
|
||||
break;
|
||||
}
|
||||
|
||||
case DeviceStorageResponseValue::TSuccessResponse:
|
||||
{
|
||||
DS_LOG_INFO("success %u", mRequest->GetId());
|
||||
nsString fullPath;
|
||||
mRequest->GetFile()->GetFullPath(fullPath);
|
||||
mRequest->Resolve(fullPath);
|
||||
break;
|
||||
}
|
||||
|
||||
case DeviceStorageResponseValue::TFileDescriptorResponse:
|
||||
{
|
||||
DS_LOG_INFO("fd %u", mRequest->GetId());
|
||||
FileDescriptorResponse r = aValue;
|
||||
|
||||
DeviceStorageFile* file = mRequest->GetFile();
|
||||
DeviceStorageFileDescriptor* descriptor = mRequest->GetFileDescriptor();
|
||||
nsString fullPath;
|
||||
file->GetFullPath(fullPath);
|
||||
descriptor->mDSFile = file;
|
||||
descriptor->mFileDescriptor = r.fileDescriptor();
|
||||
mRequest->Resolve(fullPath);
|
||||
break;
|
||||
}
|
||||
|
||||
case DeviceStorageResponseValue::TBlobResponse:
|
||||
{
|
||||
DS_LOG_INFO("blob %u", mRequest->GetId());
|
||||
BlobResponse r = aValue;
|
||||
BlobChild* actor = static_cast<BlobChild*>(r.blobChild());
|
||||
RefPtr<BlobImpl> blobImpl = actor->GetBlobImpl();
|
||||
mRequest->Resolve(blobImpl.get());
|
||||
break;
|
||||
}
|
||||
|
||||
case DeviceStorageResponseValue::TFreeSpaceStorageResponse:
|
||||
{
|
||||
DS_LOG_INFO("free %u", mRequest->GetId());
|
||||
FreeSpaceStorageResponse r = aValue;
|
||||
mRequest->Resolve(r.freeBytes());
|
||||
break;
|
||||
}
|
||||
|
||||
case DeviceStorageResponseValue::TUsedSpaceStorageResponse:
|
||||
{
|
||||
DS_LOG_INFO("used %u", mRequest->GetId());
|
||||
UsedSpaceStorageResponse r = aValue;
|
||||
mRequest->Resolve(r.usedBytes());
|
||||
break;
|
||||
}
|
||||
|
||||
case DeviceStorageResponseValue::TFormatStorageResponse:
|
||||
{
|
||||
DS_LOG_INFO("format %u", mRequest->GetId());
|
||||
FormatStorageResponse r = aValue;
|
||||
mRequest->Resolve(r.mountState());
|
||||
break;
|
||||
}
|
||||
|
||||
case DeviceStorageResponseValue::TMountStorageResponse:
|
||||
{
|
||||
DS_LOG_INFO("mount %u", mRequest->GetId());
|
||||
MountStorageResponse r = aValue;
|
||||
mRequest->Resolve(r.storageStatus());
|
||||
break;
|
||||
}
|
||||
|
||||
case DeviceStorageResponseValue::TUnmountStorageResponse:
|
||||
{
|
||||
DS_LOG_INFO("unmount %u", mRequest->GetId());
|
||||
UnmountStorageResponse r = aValue;
|
||||
mRequest->Resolve(r.storageStatus());
|
||||
break;
|
||||
}
|
||||
|
||||
case DeviceStorageResponseValue::TEnumerationResponse:
|
||||
{
|
||||
DS_LOG_INFO("enumerate %u", mRequest->GetId());
|
||||
EnumerationResponse r = aValue;
|
||||
auto request = static_cast<DeviceStorageCursorRequest*>(mRequest.get());
|
||||
uint32_t count = r.paths().Length();
|
||||
request->AddFiles(count);
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
RefPtr<DeviceStorageFile> dsf
|
||||
= new DeviceStorageFile(r.type(), r.paths()[i].storageName(),
|
||||
r.rootdir(), r.paths()[i].name());
|
||||
request->AddFile(dsf.forget());
|
||||
}
|
||||
request->Continue();
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
DS_LOG_ERROR("unknown %u", mRequest->GetId());
|
||||
MOZ_CRASH("not reached");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
} // namespace devicestorage
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_devicestorage_DeviceStorageRequestChild_h
|
||||
#define mozilla_dom_devicestorage_DeviceStorageRequestChild_h
|
||||
|
||||
#include "mozilla/dom/devicestorage/PDeviceStorageRequestChild.h"
|
||||
|
||||
class DeviceStorageFile;
|
||||
class DeviceStorageRequest;
|
||||
struct DeviceStorageFileDescriptor;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
namespace devicestorage {
|
||||
|
||||
class DeviceStorageRequestChildCallback
|
||||
{
|
||||
public:
|
||||
virtual void RequestComplete() = 0;
|
||||
};
|
||||
|
||||
class DeviceStorageRequestChild : public PDeviceStorageRequestChild
|
||||
{
|
||||
public:
|
||||
DeviceStorageRequestChild();
|
||||
explicit DeviceStorageRequestChild(DeviceStorageRequest* aRequest);
|
||||
~DeviceStorageRequestChild();
|
||||
|
||||
virtual mozilla::ipc::IPCResult Recv__delete__(const DeviceStorageResponseValue& value);
|
||||
|
||||
private:
|
||||
RefPtr<DeviceStorageRequest> mRequest;
|
||||
};
|
||||
|
||||
} // namespace devicestorage
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
|
|
@ -1,595 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "DeviceStorageRequestParent.h"
|
||||
#include "nsIMIMEService.h"
|
||||
#include "nsCExternalHandlerService.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "mozilla/dom/FileBlobImpl.h"
|
||||
#include "mozilla/dom/ipc/BlobParent.h"
|
||||
#include "ContentParent.h"
|
||||
#include "nsProxyRelease.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsNetCID.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace devicestorage {
|
||||
|
||||
DeviceStorageRequestParent::DeviceStorageRequestParent(
|
||||
const DeviceStorageParams& aParams)
|
||||
: mParams(aParams)
|
||||
, mMutex("DeviceStorageRequestParent::mMutex")
|
||||
, mActorDestroyed(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(DeviceStorageRequestParent);
|
||||
|
||||
DebugOnly<DeviceStorageUsedSpaceCache*> usedSpaceCache
|
||||
= DeviceStorageUsedSpaceCache::CreateOrGet();
|
||||
MOZ_ASSERT(usedSpaceCache);
|
||||
}
|
||||
|
||||
void
|
||||
DeviceStorageRequestParent::Dispatch()
|
||||
{
|
||||
RefPtr<CancelableRunnable> r;
|
||||
switch (mParams.type()) {
|
||||
case DeviceStorageParams::TDeviceStorageAddParams:
|
||||
{
|
||||
DeviceStorageAddParams p = mParams;
|
||||
|
||||
RefPtr<DeviceStorageFile> dsf =
|
||||
new DeviceStorageFile(p.type(), p.storageName(), p.relpath());
|
||||
|
||||
BlobParent* bp = static_cast<BlobParent*>(p.blobParent());
|
||||
RefPtr<BlobImpl> blobImpl = bp->GetBlobImpl();
|
||||
|
||||
ErrorResult rv;
|
||||
nsCOMPtr<nsIInputStream> stream;
|
||||
blobImpl->GetInternalStream(getter_AddRefs(stream), rv);
|
||||
MOZ_ASSERT(!rv.Failed());
|
||||
|
||||
r = new WriteFileEvent(this, dsf.forget(), stream,
|
||||
DEVICE_STORAGE_REQUEST_CREATE);
|
||||
break;
|
||||
}
|
||||
|
||||
case DeviceStorageParams::TDeviceStorageAppendParams:
|
||||
{
|
||||
DeviceStorageAppendParams p = mParams;
|
||||
|
||||
RefPtr<DeviceStorageFile> dsf =
|
||||
new DeviceStorageFile(p.type(), p.storageName(), p.relpath());
|
||||
|
||||
BlobParent* bp = static_cast<BlobParent*>(p.blobParent());
|
||||
RefPtr<BlobImpl> blobImpl = bp->GetBlobImpl();
|
||||
|
||||
ErrorResult rv;
|
||||
nsCOMPtr<nsIInputStream> stream;
|
||||
blobImpl->GetInternalStream(getter_AddRefs(stream), rv);
|
||||
MOZ_ASSERT(!rv.Failed());
|
||||
|
||||
r = new WriteFileEvent(this, dsf.forget(), stream,
|
||||
DEVICE_STORAGE_REQUEST_APPEND);
|
||||
break;
|
||||
}
|
||||
|
||||
case DeviceStorageParams::TDeviceStorageCreateFdParams:
|
||||
{
|
||||
DeviceStorageCreateFdParams p = mParams;
|
||||
|
||||
RefPtr<DeviceStorageFile> dsf =
|
||||
new DeviceStorageFile(p.type(), p.storageName(), p.relpath());
|
||||
|
||||
r = new CreateFdEvent(this, dsf.forget());
|
||||
break;
|
||||
}
|
||||
|
||||
case DeviceStorageParams::TDeviceStorageGetParams:
|
||||
{
|
||||
DeviceStorageGetParams p = mParams;
|
||||
RefPtr<DeviceStorageFile> dsf =
|
||||
new DeviceStorageFile(p.type(), p.storageName(),
|
||||
p.rootDir(), p.relpath());
|
||||
r = new ReadFileEvent(this, dsf.forget());
|
||||
break;
|
||||
}
|
||||
|
||||
case DeviceStorageParams::TDeviceStorageDeleteParams:
|
||||
{
|
||||
DeviceStorageDeleteParams p = mParams;
|
||||
|
||||
RefPtr<DeviceStorageFile> dsf =
|
||||
new DeviceStorageFile(p.type(), p.storageName(), p.relpath());
|
||||
r = new DeleteFileEvent(this, dsf.forget());
|
||||
break;
|
||||
}
|
||||
|
||||
case DeviceStorageParams::TDeviceStorageFreeSpaceParams:
|
||||
{
|
||||
DeviceStorageFreeSpaceParams p = mParams;
|
||||
|
||||
RefPtr<DeviceStorageFile> dsf =
|
||||
new DeviceStorageFile(p.type(), p.storageName());
|
||||
r = new FreeSpaceFileEvent(this, dsf.forget());
|
||||
break;
|
||||
}
|
||||
|
||||
case DeviceStorageParams::TDeviceStorageUsedSpaceParams:
|
||||
{
|
||||
DeviceStorageUsedSpaceCache* usedSpaceCache
|
||||
= DeviceStorageUsedSpaceCache::CreateOrGet();
|
||||
MOZ_ASSERT(usedSpaceCache);
|
||||
|
||||
DeviceStorageUsedSpaceParams p = mParams;
|
||||
|
||||
RefPtr<DeviceStorageFile> dsf =
|
||||
new DeviceStorageFile(p.type(), p.storageName());
|
||||
usedSpaceCache->Dispatch(
|
||||
MakeAndAddRef<UsedSpaceFileEvent>(this, dsf.forget()));
|
||||
return;
|
||||
}
|
||||
|
||||
case DeviceStorageParams::TDeviceStorageFormatParams:
|
||||
{
|
||||
DeviceStorageFormatParams p = mParams;
|
||||
|
||||
RefPtr<DeviceStorageFile> dsf =
|
||||
new DeviceStorageFile(p.type(), p.storageName());
|
||||
DebugOnly<nsresult> rv = NS_DispatchToMainThread(
|
||||
new PostFormatResultEvent(this, dsf.forget()));
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
return;
|
||||
}
|
||||
|
||||
case DeviceStorageParams::TDeviceStorageMountParams:
|
||||
{
|
||||
DeviceStorageMountParams p = mParams;
|
||||
|
||||
RefPtr<DeviceStorageFile> dsf =
|
||||
new DeviceStorageFile(p.type(), p.storageName());
|
||||
DebugOnly<nsresult> rv = NS_DispatchToMainThread(
|
||||
new PostMountResultEvent(this, dsf.forget()));
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
return;
|
||||
}
|
||||
|
||||
case DeviceStorageParams::TDeviceStorageUnmountParams:
|
||||
{
|
||||
DeviceStorageUnmountParams p = mParams;
|
||||
|
||||
RefPtr<DeviceStorageFile> dsf =
|
||||
new DeviceStorageFile(p.type(), p.storageName());
|
||||
DebugOnly<nsresult> rv = NS_DispatchToMainThread(
|
||||
new PostUnmountResultEvent(this, dsf.forget()));
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
return;
|
||||
}
|
||||
|
||||
case DeviceStorageParams::TDeviceStorageEnumerationParams:
|
||||
{
|
||||
DeviceStorageEnumerationParams p = mParams;
|
||||
RefPtr<DeviceStorageFile> dsf
|
||||
= new DeviceStorageFile(p.type(), p.storageName(),
|
||||
p.rootdir(), NS_LITERAL_STRING(""));
|
||||
r = new EnumerateFileEvent(this, dsf.forget(), p.since());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
MOZ_CRASH("not reached");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (r) {
|
||||
nsCOMPtr<nsIEventTarget> target =
|
||||
do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
|
||||
MOZ_ASSERT(target);
|
||||
target->Dispatch(r.forget(), NS_DISPATCH_NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
DeviceStorageRequestParent::~DeviceStorageRequestParent()
|
||||
{
|
||||
MOZ_COUNT_DTOR(DeviceStorageRequestParent);
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF(DeviceStorageRequestParent)
|
||||
NS_IMPL_RELEASE(DeviceStorageRequestParent)
|
||||
|
||||
void
|
||||
DeviceStorageRequestParent::ActorDestroy(ActorDestroyReason)
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
mActorDestroyed = true;
|
||||
for (auto& runnable : mRunnables) {
|
||||
runnable->Cancel();
|
||||
}
|
||||
// Ensure we clear all references to the runnables so that there won't
|
||||
// be leak due to cyclic reference. Note that it is safe to release
|
||||
// the references here, since if a runnable is not cancelled yet, the
|
||||
// corresponding thread should still hold a reference to it, and thus
|
||||
// the runnable will end up being released in that thread, not here.
|
||||
mRunnables.Clear();
|
||||
}
|
||||
|
||||
DeviceStorageRequestParent::PostFreeSpaceResultEvent::PostFreeSpaceResultEvent(
|
||||
DeviceStorageRequestParent* aParent,
|
||||
uint64_t aFreeSpace)
|
||||
: CancelableRunnable(aParent)
|
||||
, mFreeSpace(aFreeSpace)
|
||||
{
|
||||
}
|
||||
|
||||
DeviceStorageRequestParent::PostFreeSpaceResultEvent::
|
||||
~PostFreeSpaceResultEvent() {}
|
||||
|
||||
nsresult
|
||||
DeviceStorageRequestParent::PostFreeSpaceResultEvent::CancelableRun() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
FreeSpaceStorageResponse response(mFreeSpace);
|
||||
Unused << mParent->Send__delete__(mParent, response);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
DeviceStorageRequestParent::PostUsedSpaceResultEvent::CancelableRun() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
UsedSpaceStorageResponse response(mUsedSpace);
|
||||
Unused << mParent->Send__delete__(mParent, response);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
DeviceStorageRequestParent::PostErrorEvent::
|
||||
PostErrorEvent(DeviceStorageRequestParent* aParent, const char* aError)
|
||||
: CancelableRunnable(aParent)
|
||||
{
|
||||
CopyASCIItoUTF16(aError, mError);
|
||||
}
|
||||
|
||||
nsresult
|
||||
DeviceStorageRequestParent::PostErrorEvent::CancelableRun() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
ErrorResponse response(mError);
|
||||
Unused << mParent->Send__delete__(mParent, response);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
DeviceStorageRequestParent::PostSuccessEvent::CancelableRun() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
SuccessResponse response;
|
||||
Unused << mParent->Send__delete__(mParent, response);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
DeviceStorageRequestParent::PostBlobSuccessEvent::CancelableRun() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsString mime;
|
||||
CopyASCIItoUTF16(mMimeType, mime);
|
||||
|
||||
nsString fullPath;
|
||||
mFile->GetFullPath(fullPath);
|
||||
RefPtr<BlobImpl> blob =
|
||||
new FileBlobImpl(fullPath, mime, mLength, mFile->mFile,
|
||||
mLastModificationDate);
|
||||
|
||||
ContentParent* cp = static_cast<ContentParent*>(mParent->Manager());
|
||||
BlobParent* actor = cp->GetOrCreateActorForBlobImpl(blob);
|
||||
if (!actor) {
|
||||
ErrorResponse response(NS_LITERAL_STRING(POST_ERROR_EVENT_UNKNOWN));
|
||||
Unused << mParent->Send__delete__(mParent, response);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
BlobResponse response;
|
||||
response.blobParent() = actor;
|
||||
|
||||
Unused << mParent->Send__delete__(mParent, response);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
DeviceStorageRequestParent::PostEnumerationSuccessEvent::CancelableRun() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
EnumerationResponse response(mStorageType, mRelPath, mPaths);
|
||||
Unused << mParent->Send__delete__(mParent, response);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
DeviceStorageRequestParent::CreateFdEvent::CancelableRun()
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
if (!mFile->mFile) {
|
||||
return NS_DispatchToMainThread(
|
||||
new PostErrorEvent(mParent, POST_ERROR_EVENT_UNKNOWN));
|
||||
}
|
||||
bool check = false;
|
||||
mFile->mFile->Exists(&check);
|
||||
if (check) {
|
||||
return NS_DispatchToMainThread(
|
||||
new PostErrorEvent(mParent, POST_ERROR_EVENT_FILE_EXISTS));
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRunnable> r;
|
||||
FileDescriptor fileDescriptor;
|
||||
nsresult rv = mFile->CreateFileDescriptor(fileDescriptor);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("CreateFileDescriptor failed");
|
||||
mFile->Dump("CreateFileDescriptor failed");
|
||||
r = new PostErrorEvent(mParent, POST_ERROR_EVENT_UNKNOWN);
|
||||
}
|
||||
else {
|
||||
r = new PostFileDescriptorResultEvent(mParent, fileDescriptor);
|
||||
}
|
||||
|
||||
return NS_DispatchToMainThread(r.forget());
|
||||
}
|
||||
|
||||
nsresult
|
||||
DeviceStorageRequestParent::WriteFileEvent::CancelableRun()
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
if (!mInputStream || !mFile->mFile) {
|
||||
return NS_DispatchToMainThread(
|
||||
new PostErrorEvent(mParent, POST_ERROR_EVENT_UNKNOWN));
|
||||
}
|
||||
|
||||
bool check = false;
|
||||
nsresult rv;
|
||||
mFile->mFile->Exists(&check);
|
||||
|
||||
if (mRequestType == DEVICE_STORAGE_REQUEST_CREATE) {
|
||||
if (check) {
|
||||
return NS_DispatchToMainThread(
|
||||
new PostErrorEvent(mParent, POST_ERROR_EVENT_FILE_EXISTS));
|
||||
}
|
||||
rv = mFile->Write(mInputStream);
|
||||
} else if (mRequestType == DEVICE_STORAGE_REQUEST_APPEND) {
|
||||
if (!check) {
|
||||
return NS_DispatchToMainThread(
|
||||
new PostErrorEvent(mParent, POST_ERROR_EVENT_FILE_DOES_NOT_EXIST));
|
||||
}
|
||||
rv = mFile->Append(mInputStream);
|
||||
} else {
|
||||
return NS_DispatchToMainThread(
|
||||
new PostErrorEvent(mParent, POST_ERROR_EVENT_UNKNOWN));
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRunnable> r;
|
||||
if (NS_FAILED(rv)) {
|
||||
r = new PostErrorEvent(mParent, POST_ERROR_EVENT_UNKNOWN);
|
||||
}
|
||||
else {
|
||||
r = new PostPathResultEvent(mParent, mFile->mPath);
|
||||
}
|
||||
|
||||
return NS_DispatchToMainThread(r.forget());
|
||||
}
|
||||
|
||||
nsresult
|
||||
DeviceStorageRequestParent::DeleteFileEvent::CancelableRun()
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
mFile->Remove();
|
||||
|
||||
if (!mFile->mFile) {
|
||||
return NS_DispatchToMainThread(
|
||||
new PostErrorEvent(mParent, POST_ERROR_EVENT_UNKNOWN));
|
||||
}
|
||||
nsCOMPtr<nsIRunnable> r;
|
||||
bool check = false;
|
||||
mFile->mFile->Exists(&check);
|
||||
if (check) {
|
||||
r = new PostErrorEvent(mParent, POST_ERROR_EVENT_UNKNOWN);
|
||||
}
|
||||
else {
|
||||
r = new PostPathResultEvent(mParent, mFile->mPath);
|
||||
}
|
||||
|
||||
return NS_DispatchToMainThread(r.forget());
|
||||
}
|
||||
|
||||
nsresult
|
||||
DeviceStorageRequestParent::FreeSpaceFileEvent::CancelableRun()
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
int64_t freeSpace = 0;
|
||||
if (mFile) {
|
||||
mFile->GetStorageFreeSpace(&freeSpace);
|
||||
}
|
||||
|
||||
return NS_DispatchToMainThread(
|
||||
new PostFreeSpaceResultEvent(mParent, static_cast<uint64_t>(freeSpace)));
|
||||
}
|
||||
|
||||
nsresult
|
||||
DeviceStorageRequestParent::UsedSpaceFileEvent::CancelableRun()
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
uint64_t picturesUsage = 0, videosUsage = 0, musicUsage = 0, totalUsage = 0;
|
||||
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 {
|
||||
r = new PostUsedSpaceResultEvent(mParent, mFile->mStorageType, totalUsage);
|
||||
}
|
||||
return NS_DispatchToMainThread(r.forget());
|
||||
}
|
||||
|
||||
DeviceStorageRequestParent::ReadFileEvent::
|
||||
ReadFileEvent(DeviceStorageRequestParent* aParent,
|
||||
already_AddRefed<DeviceStorageFile>&& aFile)
|
||||
: CancelableFileEvent(aParent, Move(aFile))
|
||||
{
|
||||
nsCOMPtr<nsIMIMEService> mimeService
|
||||
= do_GetService(NS_MIMESERVICE_CONTRACTID);
|
||||
if (mimeService) {
|
||||
nsresult rv = mimeService->GetTypeFromFile(mFile->mFile, mMimeType);
|
||||
if (NS_FAILED(rv)) {
|
||||
mMimeType.Truncate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
DeviceStorageRequestParent::ReadFileEvent::CancelableRun()
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
if (!mFile->mFile) {
|
||||
return NS_DispatchToMainThread(
|
||||
new PostErrorEvent(mParent, POST_ERROR_EVENT_UNKNOWN));
|
||||
}
|
||||
bool check = false;
|
||||
mFile->mFile->Exists(&check);
|
||||
|
||||
if (!check) {
|
||||
return NS_DispatchToMainThread(
|
||||
new PostErrorEvent(mParent, POST_ERROR_EVENT_FILE_DOES_NOT_EXIST));
|
||||
}
|
||||
|
||||
int64_t fileSize;
|
||||
nsresult rv = mFile->mFile->GetFileSize(&fileSize);
|
||||
if (NS_FAILED(rv)) {
|
||||
return NS_DispatchToMainThread(
|
||||
new PostErrorEvent(mParent, POST_ERROR_EVENT_UNKNOWN));
|
||||
}
|
||||
|
||||
PRTime modDate;
|
||||
rv = mFile->mFile->GetLastModifiedTime(&modDate);
|
||||
if (NS_FAILED(rv)) {
|
||||
return NS_DispatchToMainThread(
|
||||
new PostErrorEvent(mParent, POST_ERROR_EVENT_UNKNOWN));
|
||||
}
|
||||
|
||||
return NS_DispatchToMainThread(
|
||||
new PostBlobSuccessEvent(mParent, mFile.forget(),
|
||||
static_cast<uint64_t>(fileSize),
|
||||
mMimeType, modDate));
|
||||
}
|
||||
|
||||
nsresult
|
||||
DeviceStorageRequestParent::EnumerateFileEvent::CancelableRun()
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
if (mFile->mFile) {
|
||||
bool check = false;
|
||||
mFile->mFile->Exists(&check);
|
||||
if (!check) {
|
||||
return NS_DispatchToMainThread(
|
||||
new PostErrorEvent(mParent, POST_ERROR_EVENT_FILE_DOES_NOT_EXIST));
|
||||
}
|
||||
}
|
||||
|
||||
nsTArray<RefPtr<DeviceStorageFile> > files;
|
||||
mFile->CollectFiles(files, mSince);
|
||||
|
||||
InfallibleTArray<DeviceStorageFileValue> values;
|
||||
|
||||
uint32_t count = files.Length();
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
DeviceStorageFileValue dsvf(files[i]->mStorageName, files[i]->mPath);
|
||||
values.AppendElement(dsvf);
|
||||
}
|
||||
|
||||
return NS_DispatchToMainThread(
|
||||
new PostEnumerationSuccessEvent(mParent, mFile->mStorageType,
|
||||
mFile->mRootDir, values));
|
||||
}
|
||||
|
||||
nsresult
|
||||
DeviceStorageRequestParent::PostPathResultEvent::CancelableRun()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
SuccessResponse response;
|
||||
Unused << mParent->Send__delete__(mParent, response);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
DeviceStorageRequestParent::PostFileDescriptorResultEvent::CancelableRun()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
FileDescriptorResponse response(mFileDescriptor);
|
||||
Unused << mParent->Send__delete__(mParent, response);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
DeviceStorageRequestParent::PostFormatResultEvent::CancelableRun()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsString state = NS_LITERAL_STRING("unavailable");
|
||||
if (mFile) {
|
||||
mFile->DoFormat(state);
|
||||
}
|
||||
|
||||
FormatStorageResponse response(state);
|
||||
Unused << mParent->Send__delete__(mParent, response);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
DeviceStorageRequestParent::PostMountResultEvent::CancelableRun()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsString state = NS_LITERAL_STRING("unavailable");
|
||||
if (mFile) {
|
||||
mFile->DoMount(state);
|
||||
}
|
||||
|
||||
MountStorageResponse response(state);
|
||||
Unused << mParent->Send__delete__(mParent, response);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
DeviceStorageRequestParent::PostUnmountResultEvent::CancelableRun()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsString state = NS_LITERAL_STRING("unavailable");
|
||||
if (mFile) {
|
||||
mFile->DoUnmount(state);
|
||||
}
|
||||
|
||||
UnmountStorageResponse response(state);
|
||||
Unused << mParent->Send__delete__(mParent, response);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace devicestorage
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
@ -1,333 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_devicestorage_DeviceStorageRequestParent_h
|
||||
#define mozilla_dom_devicestorage_DeviceStorageRequestParent_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/devicestorage/PDeviceStorageRequestParent.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsDeviceStorage.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace devicestorage {
|
||||
|
||||
class DeviceStorageRequestParent : public PDeviceStorageRequestParent
|
||||
{
|
||||
public:
|
||||
explicit DeviceStorageRequestParent(const DeviceStorageParams& aParams);
|
||||
|
||||
NS_IMETHOD_(MozExternalRefCountType) AddRef();
|
||||
NS_IMETHOD_(MozExternalRefCountType) Release();
|
||||
|
||||
void Dispatch();
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason);
|
||||
|
||||
protected:
|
||||
~DeviceStorageRequestParent();
|
||||
|
||||
private:
|
||||
ThreadSafeAutoRefCnt mRefCnt;
|
||||
NS_DECL_OWNINGTHREAD
|
||||
DeviceStorageParams mParams;
|
||||
|
||||
// XXXkhuey name collision :(
|
||||
class CancelableRunnable : public Runnable
|
||||
{
|
||||
public:
|
||||
explicit CancelableRunnable(DeviceStorageRequestParent* aParent)
|
||||
: mParent(aParent)
|
||||
{
|
||||
mCanceled = !(mParent->AddRunnable(this));
|
||||
}
|
||||
|
||||
virtual ~CancelableRunnable() {
|
||||
}
|
||||
|
||||
NS_IMETHOD Run() override {
|
||||
nsresult rv = NS_OK;
|
||||
if (!mCanceled) {
|
||||
rv = CancelableRun();
|
||||
mParent->RemoveRunnable(this);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
void Cancel() {
|
||||
mCanceled = true;
|
||||
}
|
||||
|
||||
virtual nsresult CancelableRun() = 0;
|
||||
|
||||
protected:
|
||||
RefPtr<DeviceStorageRequestParent> mParent;
|
||||
private:
|
||||
bool mCanceled;
|
||||
};
|
||||
|
||||
class CancelableFileEvent : public CancelableRunnable
|
||||
{
|
||||
protected:
|
||||
CancelableFileEvent(DeviceStorageRequestParent* aParent,
|
||||
already_AddRefed<DeviceStorageFile>&& aFile)
|
||||
: CancelableRunnable(aParent)
|
||||
, mFile(Move(aFile)) {}
|
||||
|
||||
RefPtr<DeviceStorageFile> mFile;
|
||||
};
|
||||
|
||||
class PostErrorEvent : public CancelableRunnable
|
||||
{
|
||||
public:
|
||||
PostErrorEvent(DeviceStorageRequestParent* aParent, const char* aError);
|
||||
virtual ~PostErrorEvent() {}
|
||||
virtual nsresult CancelableRun();
|
||||
private:
|
||||
nsString mError;
|
||||
};
|
||||
|
||||
class PostSuccessEvent : public CancelableRunnable
|
||||
{
|
||||
public:
|
||||
explicit PostSuccessEvent(DeviceStorageRequestParent* aParent)
|
||||
: CancelableRunnable(aParent) {}
|
||||
virtual ~PostSuccessEvent() {}
|
||||
virtual nsresult CancelableRun();
|
||||
};
|
||||
|
||||
class PostBlobSuccessEvent : public CancelableFileEvent
|
||||
{
|
||||
public:
|
||||
PostBlobSuccessEvent(DeviceStorageRequestParent* aParent,
|
||||
already_AddRefed<DeviceStorageFile>&& aFile,
|
||||
uint32_t aLength, nsACString& aMimeType,
|
||||
uint64_t aLastModifiedDate)
|
||||
: CancelableFileEvent(aParent, Move(aFile))
|
||||
, mLength(aLength)
|
||||
, mLastModificationDate(aLastModifiedDate)
|
||||
, mMimeType(aMimeType) {}
|
||||
virtual ~PostBlobSuccessEvent() {}
|
||||
virtual nsresult CancelableRun();
|
||||
private:
|
||||
uint32_t mLength;
|
||||
uint64_t mLastModificationDate;
|
||||
nsCString mMimeType;
|
||||
};
|
||||
|
||||
class PostEnumerationSuccessEvent : public CancelableRunnable
|
||||
{
|
||||
public:
|
||||
PostEnumerationSuccessEvent(DeviceStorageRequestParent* aParent,
|
||||
const nsAString& aStorageType,
|
||||
const nsAString& aRelPath,
|
||||
InfallibleTArray<DeviceStorageFileValue>& aPaths)
|
||||
: CancelableRunnable(aParent)
|
||||
, mStorageType(aStorageType)
|
||||
, mRelPath(aRelPath)
|
||||
, mPaths(aPaths) {}
|
||||
virtual ~PostEnumerationSuccessEvent() {}
|
||||
virtual nsresult CancelableRun();
|
||||
private:
|
||||
const nsString mStorageType;
|
||||
const nsString mRelPath;
|
||||
InfallibleTArray<DeviceStorageFileValue> mPaths;
|
||||
};
|
||||
|
||||
class CreateFdEvent : public CancelableFileEvent
|
||||
{
|
||||
public:
|
||||
CreateFdEvent(DeviceStorageRequestParent* aParent,
|
||||
already_AddRefed<DeviceStorageFile>&& aFile)
|
||||
: CancelableFileEvent(aParent, Move(aFile)) {}
|
||||
virtual ~CreateFdEvent() {}
|
||||
virtual nsresult CancelableRun();
|
||||
};
|
||||
|
||||
class WriteFileEvent : public CancelableFileEvent
|
||||
{
|
||||
public:
|
||||
WriteFileEvent(DeviceStorageRequestParent* aParent,
|
||||
already_AddRefed<DeviceStorageFile>&& aFile,
|
||||
nsIInputStream* aInputStream, int32_t aRequestType)
|
||||
: CancelableFileEvent(aParent, Move(aFile))
|
||||
, mInputStream(aInputStream)
|
||||
, mRequestType(aRequestType) {}
|
||||
virtual ~WriteFileEvent() {}
|
||||
virtual nsresult CancelableRun();
|
||||
private:
|
||||
nsCOMPtr<nsIInputStream> mInputStream;
|
||||
int32_t mRequestType;
|
||||
};
|
||||
|
||||
class DeleteFileEvent : public CancelableFileEvent
|
||||
{
|
||||
public:
|
||||
DeleteFileEvent(DeviceStorageRequestParent* aParent,
|
||||
already_AddRefed<DeviceStorageFile>&& aFile)
|
||||
: CancelableFileEvent(aParent, Move(aFile)) {}
|
||||
virtual ~DeleteFileEvent() {}
|
||||
virtual nsresult CancelableRun();
|
||||
};
|
||||
|
||||
class FreeSpaceFileEvent : public CancelableFileEvent
|
||||
{
|
||||
public:
|
||||
FreeSpaceFileEvent(DeviceStorageRequestParent* aParent,
|
||||
already_AddRefed<DeviceStorageFile>&& aFile)
|
||||
: CancelableFileEvent(aParent, Move(aFile)) {}
|
||||
virtual ~FreeSpaceFileEvent() {}
|
||||
virtual nsresult CancelableRun();
|
||||
};
|
||||
|
||||
class UsedSpaceFileEvent : public CancelableFileEvent
|
||||
{
|
||||
public:
|
||||
UsedSpaceFileEvent(DeviceStorageRequestParent* aParent,
|
||||
already_AddRefed<DeviceStorageFile>&& aFile)
|
||||
: CancelableFileEvent(aParent, Move(aFile)) {}
|
||||
virtual ~UsedSpaceFileEvent() {}
|
||||
virtual nsresult CancelableRun();
|
||||
};
|
||||
|
||||
class ReadFileEvent : public CancelableFileEvent
|
||||
{
|
||||
public:
|
||||
ReadFileEvent(DeviceStorageRequestParent* aParent,
|
||||
already_AddRefed<DeviceStorageFile>&& aFile);
|
||||
virtual ~ReadFileEvent() {}
|
||||
virtual nsresult CancelableRun();
|
||||
private:
|
||||
nsCString mMimeType;
|
||||
};
|
||||
|
||||
class EnumerateFileEvent : public CancelableFileEvent
|
||||
{
|
||||
public:
|
||||
EnumerateFileEvent(DeviceStorageRequestParent* aParent,
|
||||
already_AddRefed<DeviceStorageFile>&& aFile,
|
||||
uint64_t aSince)
|
||||
: CancelableFileEvent(aParent, Move(aFile))
|
||||
, mSince(aSince) {}
|
||||
virtual ~EnumerateFileEvent() {}
|
||||
virtual nsresult CancelableRun();
|
||||
private:
|
||||
uint64_t mSince;
|
||||
};
|
||||
|
||||
class PostPathResultEvent : public CancelableRunnable
|
||||
{
|
||||
public:
|
||||
PostPathResultEvent(DeviceStorageRequestParent* aParent,
|
||||
const nsAString& aPath)
|
||||
: CancelableRunnable(aParent)
|
||||
, mPath(aPath) {}
|
||||
virtual ~PostPathResultEvent() {}
|
||||
virtual nsresult CancelableRun();
|
||||
private:
|
||||
nsString mPath;
|
||||
};
|
||||
|
||||
class PostFileDescriptorResultEvent : public CancelableRunnable
|
||||
{
|
||||
public:
|
||||
PostFileDescriptorResultEvent(DeviceStorageRequestParent* aParent,
|
||||
const FileDescriptor& aFileDescriptor)
|
||||
: CancelableRunnable(aParent)
|
||||
, mFileDescriptor(aFileDescriptor) {}
|
||||
virtual ~PostFileDescriptorResultEvent() {}
|
||||
virtual nsresult CancelableRun();
|
||||
private:
|
||||
FileDescriptor mFileDescriptor;
|
||||
};
|
||||
|
||||
class PostFreeSpaceResultEvent : public CancelableRunnable
|
||||
{
|
||||
public:
|
||||
PostFreeSpaceResultEvent(DeviceStorageRequestParent* aParent,
|
||||
uint64_t aFreeSpace);
|
||||
virtual ~PostFreeSpaceResultEvent();
|
||||
virtual nsresult CancelableRun();
|
||||
private:
|
||||
uint64_t mFreeSpace;
|
||||
};
|
||||
|
||||
class PostUsedSpaceResultEvent : public CancelableRunnable
|
||||
{
|
||||
public:
|
||||
PostUsedSpaceResultEvent(DeviceStorageRequestParent* aParent,
|
||||
const nsAString& aType,
|
||||
uint64_t aUsedSpace)
|
||||
: CancelableRunnable(aParent)
|
||||
, mType(aType)
|
||||
, mUsedSpace(aUsedSpace) {}
|
||||
virtual ~PostUsedSpaceResultEvent() {}
|
||||
virtual nsresult CancelableRun();
|
||||
private:
|
||||
nsString mType;
|
||||
uint64_t mUsedSpace;
|
||||
};
|
||||
|
||||
class PostFormatResultEvent : public CancelableFileEvent
|
||||
{
|
||||
public:
|
||||
PostFormatResultEvent(DeviceStorageRequestParent* aParent,
|
||||
already_AddRefed<DeviceStorageFile>&& aFile)
|
||||
: CancelableFileEvent(aParent, Move(aFile)) {}
|
||||
virtual ~PostFormatResultEvent() {}
|
||||
virtual nsresult CancelableRun();
|
||||
};
|
||||
|
||||
class PostMountResultEvent : public CancelableFileEvent
|
||||
{
|
||||
public:
|
||||
PostMountResultEvent(DeviceStorageRequestParent* aParent,
|
||||
already_AddRefed<DeviceStorageFile>&& aFile)
|
||||
: CancelableFileEvent(aParent, Move(aFile)) {}
|
||||
virtual ~PostMountResultEvent() {}
|
||||
virtual nsresult CancelableRun();
|
||||
};
|
||||
|
||||
class PostUnmountResultEvent : public CancelableFileEvent
|
||||
{
|
||||
public:
|
||||
PostUnmountResultEvent(DeviceStorageRequestParent* aParent,
|
||||
already_AddRefed<DeviceStorageFile>&& aFile)
|
||||
: CancelableFileEvent(aParent, Move(aFile)) {}
|
||||
virtual ~PostUnmountResultEvent() {}
|
||||
virtual nsresult CancelableRun();
|
||||
};
|
||||
|
||||
protected:
|
||||
bool AddRunnable(CancelableRunnable* aRunnable) {
|
||||
MutexAutoLock lock(mMutex);
|
||||
if (mActorDestroyed)
|
||||
return false;
|
||||
|
||||
mRunnables.AppendElement(aRunnable);
|
||||
return true;
|
||||
}
|
||||
|
||||
void RemoveRunnable(CancelableRunnable* aRunnable) {
|
||||
MutexAutoLock lock(mMutex);
|
||||
mRunnables.RemoveElement(aRunnable);
|
||||
}
|
||||
|
||||
Mutex mMutex;
|
||||
bool mActorDestroyed;
|
||||
nsTArray<RefPtr<CancelableRunnable> > mRunnables;
|
||||
};
|
||||
|
||||
} // namespace devicestorage
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
|
|
@ -1,930 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "DeviceStorageStatics.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsDeviceStorage.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsAppDirectoryServiceDefs.h"
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "nsPrintfCString.h"
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
#include "nsIVolume.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
#include "AndroidBridge.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace devicestorage {
|
||||
|
||||
static const char* kPrefOverrideRootDir = "device.storage.overrideRootDir";
|
||||
static const char* kPrefTesting = "device.storage.testing";
|
||||
static const char* kPrefPromptTesting = "device.storage.prompt.testing";
|
||||
static const char* kPrefWritableName = "device.storage.writable.name";
|
||||
|
||||
// file-watcher-notify comes from some process (but not the MTP Server)
|
||||
// to indicate that a file has changed. It eventually winds up in the
|
||||
// parent process, and then gets broadcast out to all child listeners
|
||||
// as a file-watcher-update and mtp-watcher-update.
|
||||
//
|
||||
// mtp-watcher-notify comes from the MTP Server whenever it detects a change
|
||||
// and this gets rebroadcast as file-watcher-update to the device storage
|
||||
// listeners.
|
||||
//
|
||||
// download-watcher-notify is treated similarly to file-watcher-notify,
|
||||
// and gets converted into file-watcher-update and mtp-watcher-update.
|
||||
//
|
||||
// We need to make sure that the MTP server doesn't get notified about
|
||||
// files which it told us it added, otherwise it confuses some clients
|
||||
// (like the Android-File-Transfer program which runs under OS X).
|
||||
|
||||
static const char* kFileWatcherUpdate = "file-watcher-update";
|
||||
static const char* kMtpWatcherUpdate = "mtp-watcher-update";
|
||||
static const char* kDiskSpaceWatcher = "disk-space-watcher";
|
||||
static const char* kFileWatcherNotify = "file-watcher-notify";
|
||||
static const char* kMtpWatcherNotify = "mtp-watcher-notify";
|
||||
static const char* kDownloadWatcherNotify = "download-watcher-notify";
|
||||
|
||||
StaticRefPtr<DeviceStorageStatics> DeviceStorageStatics::sInstance;
|
||||
StaticMutex DeviceStorageStatics::sMutex;
|
||||
|
||||
NS_IMPL_ISUPPORTS(DeviceStorageStatics,
|
||||
nsIObserver)
|
||||
|
||||
/* static */ void
|
||||
DeviceStorageStatics::Initialize()
|
||||
{
|
||||
MOZ_ASSERT(!sInstance);
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
sInstance = new DeviceStorageStatics();
|
||||
sInstance->Init();
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
DeviceStorageStatics::InitializeDirs()
|
||||
{
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
if (NS_WARN_IF(!sInstance)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* The actual initialization can only happen on the main thread. This will
|
||||
either happen when device storage is first used on the main thread, or
|
||||
(in the future) when a worker is created. */
|
||||
if (!sInstance->mInitialized && NS_IsMainThread()) {
|
||||
sInstance->InitDirs();
|
||||
sInstance->mInitialized = true;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(sInstance->mInitialized);
|
||||
}
|
||||
|
||||
DeviceStorageStatics::DeviceStorageStatics()
|
||||
: mInitialized(false)
|
||||
, mPromptTesting(false)
|
||||
, mLowDiskSpace(false)
|
||||
{
|
||||
DS_LOG_INFO("");
|
||||
}
|
||||
|
||||
DeviceStorageStatics::~DeviceStorageStatics()
|
||||
{
|
||||
DS_LOG_INFO("");
|
||||
}
|
||||
|
||||
void
|
||||
DeviceStorageStatics::Init()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
sMutex.AssertCurrentThreadOwns();
|
||||
DS_LOG_INFO("");
|
||||
|
||||
Preferences::AddStrongObserver(this, kPrefTesting);
|
||||
Preferences::AddStrongObserver(this, kPrefPromptTesting);
|
||||
Preferences::AddStrongObserver(this, kPrefWritableName);
|
||||
|
||||
mWritableName = Preferences::GetString(kPrefWritableName);
|
||||
mPromptTesting = Preferences::GetBool(kPrefPromptTesting, false);
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (obs) {
|
||||
obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
|
||||
obs->AddObserver(this, kFileWatcherNotify, false);
|
||||
obs->AddObserver(this, kMtpWatcherNotify, false);
|
||||
obs->AddObserver(this, kDownloadWatcherNotify, false);
|
||||
}
|
||||
DS_LOG_INFO("");
|
||||
}
|
||||
|
||||
void
|
||||
DeviceStorageStatics::InitDirs()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
sMutex.AssertCurrentThreadOwns();
|
||||
DS_LOG_INFO("");
|
||||
|
||||
#if !defined(MOZ_WIDGET_GONK)
|
||||
if (!XRE_IsParentProcess()) {
|
||||
// For gonk, we have the parent process forward the directory information
|
||||
// to the child using ContentParent::ForwardKnownInfo. On desktop, this
|
||||
// winds up slowing down the startup (in particular ts_paint), so rather
|
||||
// than penalize all e10s processes, we do a synchronous IPC call here,
|
||||
// which only penalizes child processes which actually use DeviceStorage.
|
||||
|
||||
dom::ContentChild* child = dom::ContentChild::GetSingleton();
|
||||
DeviceStorageLocationInfo locationInfo;
|
||||
child->SendGetDeviceStorageLocations(&locationInfo);
|
||||
|
||||
NS_NewLocalFile(locationInfo.apps(), true, getter_AddRefs(sInstance->mDirs[TYPE_APPS]));
|
||||
NS_NewLocalFile(locationInfo.crashes(), true, getter_AddRefs(sInstance->mDirs[TYPE_CRASHES]));
|
||||
NS_NewLocalFile(locationInfo.pictures(), true, getter_AddRefs(sInstance->mDirs[TYPE_PICTURES]));
|
||||
NS_NewLocalFile(locationInfo.videos(), true, getter_AddRefs(sInstance->mDirs[TYPE_VIDEOS]));
|
||||
NS_NewLocalFile(locationInfo.music(), true, getter_AddRefs(sInstance->mDirs[TYPE_MUSIC]));
|
||||
NS_NewLocalFile(locationInfo.sdcard(), true, getter_AddRefs(sInstance->mDirs[TYPE_SDCARD]));
|
||||
|
||||
sInstance->mInitialized = true;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsIProperties> dirService
|
||||
= do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID);
|
||||
MOZ_ASSERT(dirService);
|
||||
|
||||
#if !defined(MOZ_WIDGET_GONK)
|
||||
|
||||
// Keep MOZ_WIDGET_COCOA above XP_UNIX,
|
||||
// because both are defined in Darwin builds.
|
||||
#if defined (MOZ_WIDGET_COCOA)
|
||||
dirService->Get(NS_OSX_PICTURE_DOCUMENTS_DIR,
|
||||
NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(mDirs[TYPE_PICTURES]));
|
||||
dirService->Get(NS_OSX_MOVIE_DOCUMENTS_DIR,
|
||||
NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(mDirs[TYPE_VIDEOS]));
|
||||
dirService->Get(NS_OSX_MUSIC_DOCUMENTS_DIR,
|
||||
NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(mDirs[TYPE_MUSIC]));
|
||||
|
||||
// Keep MOZ_WIDGET_ANDROID above XP_UNIX,
|
||||
// because both are defined in Android builds.
|
||||
#elif defined (MOZ_WIDGET_ANDROID)
|
||||
nsAutoString path;
|
||||
if (NS_SUCCEEDED(mozilla::AndroidBridge::GetExternalPublicDirectory(
|
||||
NS_LITERAL_STRING(DEVICESTORAGE_PICTURES), path))) {
|
||||
NS_NewLocalFile(path, /* aFollowLinks */ true,
|
||||
getter_AddRefs(mDirs[TYPE_PICTURES]));
|
||||
}
|
||||
if (NS_SUCCEEDED(mozilla::AndroidBridge::GetExternalPublicDirectory(
|
||||
NS_LITERAL_STRING(DEVICESTORAGE_VIDEOS), path))) {
|
||||
NS_NewLocalFile(path, /* aFollowLinks */ true,
|
||||
getter_AddRefs(mDirs[TYPE_VIDEOS]));
|
||||
}
|
||||
if (NS_SUCCEEDED(mozilla::AndroidBridge::GetExternalPublicDirectory(
|
||||
NS_LITERAL_STRING(DEVICESTORAGE_MUSIC), path))) {
|
||||
NS_NewLocalFile(path, /* aFollowLinks */ true,
|
||||
getter_AddRefs(mDirs[TYPE_MUSIC]));
|
||||
}
|
||||
if (NS_SUCCEEDED(mozilla::AndroidBridge::GetExternalPublicDirectory(
|
||||
NS_LITERAL_STRING(DEVICESTORAGE_SDCARD), path))) {
|
||||
NS_NewLocalFile(path, /* aFollowLinks */ true,
|
||||
getter_AddRefs(mDirs[TYPE_SDCARD]));
|
||||
}
|
||||
|
||||
#elif defined (XP_UNIX)
|
||||
dirService->Get(NS_UNIX_XDG_PICTURES_DIR,
|
||||
NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(mDirs[TYPE_PICTURES]));
|
||||
dirService->Get(NS_UNIX_XDG_VIDEOS_DIR,
|
||||
NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(mDirs[TYPE_VIDEOS]));
|
||||
dirService->Get(NS_UNIX_XDG_MUSIC_DIR,
|
||||
NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(mDirs[TYPE_MUSIC]));
|
||||
|
||||
#elif defined (XP_WIN)
|
||||
dirService->Get(NS_WIN_PICTURES_DIR,
|
||||
NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(mDirs[TYPE_PICTURES]));
|
||||
dirService->Get(NS_WIN_VIDEOS_DIR,
|
||||
NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(mDirs[TYPE_VIDEOS]));
|
||||
dirService->Get(NS_WIN_MUSIC_DIR,
|
||||
NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(mDirs[TYPE_MUSIC]));
|
||||
#endif
|
||||
|
||||
#ifndef MOZ_WIDGET_ANDROID
|
||||
// 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(mDirs[TYPE_SDCARD]));
|
||||
if (mDirs[TYPE_SDCARD]) {
|
||||
mDirs[TYPE_SDCARD]->AppendRelativeNativePath(NS_LITERAL_CSTRING("fake-sdcard"));
|
||||
}
|
||||
#endif // !MOZ_WIDGET_ANDROID
|
||||
|
||||
dirService->Get(NS_APP_USER_PROFILE_50_DIR, NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(mDirs[TYPE_APPS]));
|
||||
|
||||
if (mDirs[TYPE_APPS]) {
|
||||
mDirs[TYPE_APPS]->AppendRelativeNativePath(NS_LITERAL_CSTRING("webapps"));
|
||||
}
|
||||
#endif // !MOZ_WIDGET_GONK
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
NS_NewLocalFile(NS_LITERAL_STRING("/data"),
|
||||
false,
|
||||
getter_AddRefs(mDirs[TYPE_APPS]));
|
||||
#endif
|
||||
|
||||
if (XRE_IsParentProcess()) {
|
||||
NS_GetSpecialDirectory("UAppData", getter_AddRefs(mDirs[TYPE_CRASHES]));
|
||||
if (mDirs[TYPE_CRASHES]) {
|
||||
mDirs[TYPE_CRASHES]->Append(NS_LITERAL_STRING("Crash Reports"));
|
||||
}
|
||||
}
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
// NS_GetSpecialDirectory("UAppData") fails in content processes because
|
||||
// gAppData from toolkit/xre/nsAppRunner.cpp is not initialized.
|
||||
else {
|
||||
NS_NewLocalFile(NS_LITERAL_STRING("/data/b2g/mozilla/Crash Reports"),
|
||||
false,
|
||||
getter_AddRefs(mDirs[TYPE_CRASHES]));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Directories which don't depend on a volume should be calculated once
|
||||
// here. Directories which depend on the root directory of a volume
|
||||
// should be calculated in DeviceStorageFile::GetRootDirectoryForType.
|
||||
Preferences::AddStrongObserver(this, kPrefOverrideRootDir);
|
||||
ResetOverrideRootDir();
|
||||
}
|
||||
|
||||
void
|
||||
DeviceStorageStatics::DumpDirs()
|
||||
{
|
||||
#ifdef DS_LOGGING
|
||||
sMutex.AssertCurrentThreadOwns();
|
||||
|
||||
static const char* storageTypes[] = {
|
||||
"app",
|
||||
"crashes",
|
||||
"pictures",
|
||||
"videos",
|
||||
"music",
|
||||
"sdcard",
|
||||
"override",
|
||||
nullptr
|
||||
};
|
||||
|
||||
const char* ptStr;
|
||||
if (XRE_IsParentProcess()) {
|
||||
ptStr = "parent";
|
||||
} else {
|
||||
ptStr = "child";
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < TYPE_COUNT; ++i) {
|
||||
MOZ_ASSERT(storageTypes[i]);
|
||||
|
||||
nsString path;
|
||||
if (mDirs[i]) {
|
||||
mDirs[i]->GetPath(path);
|
||||
}
|
||||
DS_LOG_INFO("(%s) %s: '%s'",
|
||||
ptStr, storageTypes[i], NS_LossyConvertUTF16toASCII(path).get());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
DeviceStorageStatics::Shutdown()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
sMutex.AssertCurrentThreadOwns();
|
||||
DS_LOG_INFO("");
|
||||
|
||||
Preferences::RemoveObserver(this, kPrefOverrideRootDir);
|
||||
Preferences::RemoveObserver(this, kPrefTesting);
|
||||
Preferences::RemoveObserver(this, kPrefPromptTesting);
|
||||
Preferences::RemoveObserver(this, kPrefWritableName);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
DeviceStorageStatics::GetDeviceStorageLocationsForIPC(
|
||||
DeviceStorageLocationInfo* aLocationInfo)
|
||||
{
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
InitializeDirs();
|
||||
|
||||
GetDirPath(TYPE_APPS, aLocationInfo->apps());
|
||||
GetDirPath(TYPE_CRASHES, aLocationInfo->crashes());
|
||||
GetDirPath(TYPE_PICTURES, aLocationInfo->pictures());
|
||||
GetDirPath(TYPE_VIDEOS, aLocationInfo->videos());
|
||||
GetDirPath(TYPE_MUSIC, aLocationInfo->music());
|
||||
GetDirPath(TYPE_SDCARD, aLocationInfo->sdcard());
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<nsIFile>
|
||||
DeviceStorageStatics::GetDir(DeviceStorageType aType)
|
||||
{
|
||||
MOZ_ASSERT(aType < TYPE_COUNT);
|
||||
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
if (NS_WARN_IF(!sInstance)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFile> file;
|
||||
switch (aType) {
|
||||
case TYPE_APPS:
|
||||
case TYPE_CRASHES:
|
||||
case TYPE_OVERRIDE:
|
||||
file = sInstance->mDirs[aType];
|
||||
return file.forget();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// In testing, we default all device storage types to a temp directory.
|
||||
// This is only initialized if the preference device.storage.testing
|
||||
// was set to true, or if device.storage.overrideRootDir is set.
|
||||
file = sInstance->mDirs[TYPE_OVERRIDE];
|
||||
if (!file) {
|
||||
file = sInstance->mDirs[aType];
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
/* We should use volume mount points on B2G. */
|
||||
MOZ_ASSERT(!file);
|
||||
#endif
|
||||
}
|
||||
return file.forget();
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
DeviceStorageStatics::GetDirPath(DeviceStorageType aType, nsString& aDirPath)
|
||||
{
|
||||
aDirPath.Truncate();
|
||||
nsCOMPtr<nsIFile> file = GetDir(aType);
|
||||
if (file) {
|
||||
file->GetPath(aDirPath);
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
DeviceStorageStatics::HasOverrideRootDir()
|
||||
{
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
if (NS_WARN_IF(!sInstance)) {
|
||||
return false;
|
||||
}
|
||||
return sInstance->mDirs[TYPE_OVERRIDE];
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<nsIFile>
|
||||
DeviceStorageStatics::GetAppsDir()
|
||||
{
|
||||
return GetDir(TYPE_APPS);
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<nsIFile>
|
||||
DeviceStorageStatics::GetCrashesDir()
|
||||
{
|
||||
return GetDir(TYPE_CRASHES);
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<nsIFile>
|
||||
DeviceStorageStatics::GetPicturesDir()
|
||||
{
|
||||
return GetDir(TYPE_PICTURES);
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<nsIFile>
|
||||
DeviceStorageStatics::GetVideosDir()
|
||||
{
|
||||
return GetDir(TYPE_VIDEOS);
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<nsIFile>
|
||||
DeviceStorageStatics::GetMusicDir()
|
||||
{
|
||||
return GetDir(TYPE_MUSIC);
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<nsIFile>
|
||||
DeviceStorageStatics::GetSdcardDir()
|
||||
{
|
||||
return GetDir(TYPE_SDCARD);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
DeviceStorageStatics::IsPromptTesting()
|
||||
{
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
if (NS_WARN_IF(!sInstance)) {
|
||||
return false;
|
||||
}
|
||||
return sInstance->mPromptTesting;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
DeviceStorageStatics::LowDiskSpace()
|
||||
{
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
if (NS_WARN_IF(!sInstance)) {
|
||||
return false;
|
||||
}
|
||||
return sInstance->mLowDiskSpace;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
DeviceStorageStatics::GetWritableName(nsString& aName)
|
||||
{
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
if (NS_WARN_IF(!sInstance)) {
|
||||
aName.Truncate();
|
||||
return;
|
||||
}
|
||||
aName = sInstance->mWritableName;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
DeviceStorageStatics::SetWritableName(const nsAString& aName)
|
||||
{
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
if (!NS_WARN_IF(!sInstance)) {
|
||||
// Update inline although it will be updated again in case
|
||||
// another thread comes in checking it before the update takes
|
||||
sInstance->mWritableName = aName;
|
||||
}
|
||||
|
||||
nsString name;
|
||||
name.Assign(aName);
|
||||
NS_DispatchToMainThread(NS_NewRunnableFunction([name] () -> void {
|
||||
Preferences::SetString(kPrefWritableName, name);
|
||||
}));
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
DeviceStorageStatics::AddListener(nsDOMDeviceStorage* aListener)
|
||||
{
|
||||
DS_LOG_DEBUG("%p", aListener);
|
||||
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
if (NS_WARN_IF(!sInstance)) {
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(sInstance->mInitialized);
|
||||
if (sInstance->mListeners.IsEmpty()) {
|
||||
NS_DispatchToMainThread(
|
||||
NewRunnableMethod(sInstance.get(), &DeviceStorageStatics::Register));
|
||||
}
|
||||
|
||||
RefPtr<ListenerWrapper> wrapper =
|
||||
new ListenerWrapper(aListener);
|
||||
sInstance->mListeners.AppendElement(wrapper.forget());
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
DeviceStorageStatics::RemoveListener(nsDOMDeviceStorage* aListener)
|
||||
{
|
||||
DS_LOG_DEBUG("%p", aListener);
|
||||
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
if (!sInstance) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool removed = false;
|
||||
uint32_t i = sInstance->mListeners.Length();
|
||||
while (i > 0) {
|
||||
--i;
|
||||
if (sInstance->mListeners[i]->Equals(aListener)) {
|
||||
sInstance->mListeners.RemoveElementAt(i);
|
||||
removed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (removed && sInstance->mListeners.IsEmpty()) {
|
||||
NS_DispatchToMainThread(
|
||||
NewRunnableMethod(sInstance.get(), &DeviceStorageStatics::Deregister));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DeviceStorageStatics::Register()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
DS_LOG_INFO("");
|
||||
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
if (NS_WARN_IF(!sInstance)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (obs) {
|
||||
obs->AddObserver(this, kFileWatcherUpdate, false);
|
||||
obs->AddObserver(this, kDiskSpaceWatcher, false);
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
obs->AddObserver(this, NS_VOLUME_STATE_CHANGED, false);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DeviceStorageStatics::Deregister()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
DS_LOG_INFO("");
|
||||
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
if (!sInstance) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (obs) {
|
||||
obs->RemoveObserver(this, kFileWatcherUpdate);
|
||||
obs->RemoveObserver(this, kDiskSpaceWatcher);
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
obs->RemoveObserver(this, NS_VOLUME_STATE_CHANGED);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DeviceStorageStatics::ResetOverrideRootDir()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
sMutex.AssertCurrentThreadOwns();
|
||||
nsCOMPtr<nsIFile> f;
|
||||
DS_LOG_INFO("");
|
||||
|
||||
// For users running on desktop, it's convenient to be able to override
|
||||
// all of the directories to point to a single tree, much like what happens
|
||||
// on a real device.
|
||||
const nsAdoptingString& overrideRootDir =
|
||||
mozilla::Preferences::GetString(kPrefOverrideRootDir);
|
||||
if (overrideRootDir && !overrideRootDir.IsEmpty()) {
|
||||
NS_NewLocalFile(overrideRootDir, false, getter_AddRefs(f));
|
||||
}
|
||||
|
||||
if (!f && Preferences::GetBool(kPrefTesting, false)) {
|
||||
DS_LOG_INFO("temp");
|
||||
nsCOMPtr<nsIProperties> dirService
|
||||
= do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID);
|
||||
MOZ_ASSERT(dirService);
|
||||
dirService->Get(NS_OS_TEMP_DIR, NS_GET_IID(nsIFile), getter_AddRefs(f));
|
||||
if (f) {
|
||||
f->AppendRelativeNativePath(
|
||||
NS_LITERAL_CSTRING("device-storage-testing"));
|
||||
}
|
||||
}
|
||||
|
||||
if (f) {
|
||||
if (XRE_IsParentProcess()) {
|
||||
// Only the parent process can create directories. In testing, because
|
||||
// the preference is updated after startup, its entirely possible that
|
||||
// the preference updated notification will be received by a child
|
||||
// prior to the parent.
|
||||
nsresult rv = f->Create(nsIFile::DIRECTORY_TYPE, 0777);
|
||||
if (NS_FAILED(rv) && rv != NS_ERROR_FILE_ALREADY_EXISTS) {
|
||||
nsString path;
|
||||
f->GetPath(path);
|
||||
nsPrintfCString msg("DeviceStorage: Unable to create directory '%s'",
|
||||
NS_LossyConvertUTF16toASCII(path).get());
|
||||
NS_WARNING(msg.get());
|
||||
}
|
||||
}
|
||||
f->Normalize();
|
||||
}
|
||||
|
||||
mDirs[TYPE_OVERRIDE] = f.forget();
|
||||
DumpDirs();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DeviceStorageStatics::Observe(nsISupports* aSubject,
|
||||
const char* aTopic,
|
||||
const char16_t* aData)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) {
|
||||
MOZ_ASSERT(aData);
|
||||
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
if (NS_WARN_IF(!sInstance)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsDependentString name(aData);
|
||||
if (name.EqualsASCII(kPrefTesting) ||
|
||||
name.EqualsASCII(kPrefOverrideRootDir)) {
|
||||
ResetOverrideRootDir();
|
||||
} else if(name.EqualsASCII(kPrefPromptTesting)) {
|
||||
mPromptTesting = Preferences::GetBool(kPrefPromptTesting, false);
|
||||
DS_LOG_INFO("prompt testing %d", mPromptTesting);
|
||||
} else if(name.EqualsASCII(kPrefWritableName)) {
|
||||
mWritableName = Preferences::GetString(kPrefWritableName);
|
||||
uint32_t i = mListeners.Length();
|
||||
DS_LOG_INFO("writable name '%s' (%u)",
|
||||
NS_LossyConvertUTF16toASCII(mWritableName).get(), i);
|
||||
while (i > 0) {
|
||||
--i;
|
||||
mListeners[i]->OnWritableNameChanged();
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
if (!strcmp(aTopic, NS_VOLUME_STATE_CHANGED)) {
|
||||
nsCOMPtr<nsIVolume> volume = do_QueryInterface(aSubject);
|
||||
if (NS_WARN_IF(!volume)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
if (NS_WARN_IF(!sInstance)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
uint32_t i = mListeners.Length();
|
||||
DS_LOG_INFO("volume updated (%u)", i);
|
||||
while (i > 0) {
|
||||
--i;
|
||||
mListeners[i]->OnVolumeStateChanged(volume);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!strcmp(aTopic, kFileWatcherUpdate)) {
|
||||
DeviceStorageFile* file = static_cast<DeviceStorageFile*>(aSubject);
|
||||
if (NS_WARN_IF(!file)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
if (NS_WARN_IF(!sInstance)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
auto data = NS_ConvertUTF16toUTF8(aData);
|
||||
uint32_t i = mListeners.Length();
|
||||
DS_LOG_INFO("file updated (%u)", i);
|
||||
while (i > 0) {
|
||||
--i;
|
||||
mListeners[i]->OnFileWatcherUpdate(data, file);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!strcmp(aTopic, kDiskSpaceWatcher)) {
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
if (NS_WARN_IF(!sInstance)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// 'disk-space-watcher' notifications are sent when there is a modification
|
||||
// of a file in a specific location while a low device storage situation
|
||||
// exists or after recovery of a low storage situation. For Firefox OS,
|
||||
// these notifications are specific for apps storage.
|
||||
if (!NS_strcmp(aData, u"full")) {
|
||||
sInstance->mLowDiskSpace = true;
|
||||
} else if (!NS_strcmp(aData, u"free")) {
|
||||
sInstance->mLowDiskSpace = false;
|
||||
} else {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
uint32_t i = mListeners.Length();
|
||||
DS_LOG_INFO("disk space %d (%u)", sInstance->mLowDiskSpace, i);
|
||||
while (i > 0) {
|
||||
--i;
|
||||
mListeners[i]->OnDiskSpaceWatcher(sInstance->mLowDiskSpace);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
if (NS_WARN_IF(!sInstance)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
Shutdown();
|
||||
sInstance = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* Here we convert file-watcher-notify and download-watcher-notify observer
|
||||
events to file-watcher-update events. This is used to be able to
|
||||
broadcast events from one child to another child in B2G. (f.e., if one
|
||||
child decides to add a file, we want to be able to able to send a onchange
|
||||
notifications to every other child watching that device storage object).*/
|
||||
RefPtr<DeviceStorageFile> dsf;
|
||||
if (!strcmp(aTopic, kDownloadWatcherNotify)) {
|
||||
// aSubject will be an nsISupportsString with the native path to the file
|
||||
// in question.
|
||||
|
||||
nsCOMPtr<nsISupportsString> supportsString = do_QueryInterface(aSubject);
|
||||
if (!supportsString) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsString path;
|
||||
nsresult rv = supportsString->GetData(path);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// The downloader uses the sdcard storage type.
|
||||
nsString volName;
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
if (DeviceStorageTypeChecker::IsVolumeBased(NS_LITERAL_STRING(DEVICESTORAGE_SDCARD))) {
|
||||
nsCOMPtr<nsIVolumeService> vs = do_GetService(NS_VOLUMESERVICE_CONTRACTID);
|
||||
if (NS_WARN_IF(!vs)) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsCOMPtr<nsIVolume> vol;
|
||||
rv = vs->GetVolumeByPath(path, getter_AddRefs(vol));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return NS_OK;
|
||||
}
|
||||
rv = vol->GetName(volName);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsString mountPoint;
|
||||
rv = vol->GetMountPoint(mountPoint);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return NS_OK;
|
||||
}
|
||||
if (!Substring(path, 0, mountPoint.Length()).Equals(mountPoint)) {
|
||||
return NS_OK;
|
||||
}
|
||||
path = Substring(path, mountPoint.Length() + 1);
|
||||
}
|
||||
#endif
|
||||
dsf = new DeviceStorageFile(NS_LITERAL_STRING(DEVICESTORAGE_SDCARD), volName, path);
|
||||
|
||||
} else if (!strcmp(aTopic, kFileWatcherNotify) ||
|
||||
!strcmp(aTopic, kMtpWatcherNotify)) {
|
||||
dsf = static_cast<DeviceStorageFile*>(aSubject);
|
||||
} else {
|
||||
DS_LOG_WARN("unhandled topic '%s'", aTopic);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!dsf || !dsf->mFile)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!XRE_IsParentProcess()) {
|
||||
// Child process. Forward the notification to the parent.
|
||||
ContentChild::GetSingleton()
|
||||
->SendFilePathUpdateNotify(dsf->mStorageType,
|
||||
dsf->mStorageName,
|
||||
dsf->mPath,
|
||||
NS_ConvertUTF16toUTF8(aData));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Multiple storage types may match the same files. So walk through each of
|
||||
// the storage types, and if the extension matches, tell them about it.
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (DeviceStorageTypeChecker::IsSharedMediaRoot(dsf->mStorageType)) {
|
||||
DeviceStorageTypeChecker* typeChecker
|
||||
= DeviceStorageTypeChecker::CreateOrGet();
|
||||
MOZ_ASSERT(typeChecker);
|
||||
|
||||
static const nsLiteralString kMediaTypes[] = {
|
||||
NS_LITERAL_STRING(DEVICESTORAGE_SDCARD),
|
||||
NS_LITERAL_STRING(DEVICESTORAGE_PICTURES),
|
||||
NS_LITERAL_STRING(DEVICESTORAGE_VIDEOS),
|
||||
NS_LITERAL_STRING(DEVICESTORAGE_MUSIC),
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < MOZ_ARRAY_LENGTH(kMediaTypes); i++) {
|
||||
RefPtr<DeviceStorageFile> dsf2;
|
||||
if (typeChecker->Check(kMediaTypes[i], dsf->mPath)) {
|
||||
if (dsf->mStorageType.Equals(kMediaTypes[i])) {
|
||||
dsf2 = dsf;
|
||||
} else {
|
||||
dsf2 = new DeviceStorageFile(kMediaTypes[i],
|
||||
dsf->mStorageName, dsf->mPath);
|
||||
}
|
||||
obs->NotifyObservers(dsf2, kFileWatcherUpdate, aData);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
obs->NotifyObservers(dsf, kFileWatcherUpdate, aData);
|
||||
}
|
||||
if (strcmp(aTopic, kMtpWatcherNotify)) {
|
||||
// Only send mtp-watcher-updates out if the MTP Server wasn't the one
|
||||
// telling us about the change.
|
||||
obs->NotifyObservers(dsf, kMtpWatcherUpdate, aData);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
DeviceStorageStatics::ListenerWrapper::ListenerWrapper(nsDOMDeviceStorage* aListener)
|
||||
: mListener(do_GetWeakReference(static_cast<DOMEventTargetHelper*>(aListener)))
|
||||
, mOwningThread(NS_GetCurrentThread())
|
||||
{
|
||||
}
|
||||
|
||||
DeviceStorageStatics::ListenerWrapper::~ListenerWrapper()
|
||||
{
|
||||
// Even weak pointers are not thread safe
|
||||
NS_ProxyRelease(mOwningThread, mListener.forget());
|
||||
}
|
||||
|
||||
bool
|
||||
DeviceStorageStatics::ListenerWrapper::Equals(nsDOMDeviceStorage* aListener)
|
||||
{
|
||||
bool current = false;
|
||||
mOwningThread->IsOnCurrentThread(¤t);
|
||||
if (current) {
|
||||
// It is only safe to acquire the reference on the owning thread
|
||||
RefPtr<nsDOMDeviceStorage> listener = do_QueryReferent(mListener);
|
||||
return listener.get() == aListener;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
DeviceStorageStatics::ListenerWrapper::OnFileWatcherUpdate(const nsCString& aData,
|
||||
DeviceStorageFile* aFile)
|
||||
{
|
||||
RefPtr<ListenerWrapper> self = this;
|
||||
nsCString data = aData;
|
||||
RefPtr<DeviceStorageFile> file = aFile;
|
||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([self, data, file] () -> void {
|
||||
RefPtr<nsDOMDeviceStorage> listener = do_QueryReferent(self->mListener);
|
||||
if (listener) {
|
||||
listener->OnFileWatcherUpdate(data, file);
|
||||
}
|
||||
});
|
||||
mOwningThread->Dispatch(r.forget(), NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
void
|
||||
DeviceStorageStatics::ListenerWrapper::OnDiskSpaceWatcher(bool aLowDiskSpace)
|
||||
{
|
||||
RefPtr<ListenerWrapper> self = this;
|
||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([self, aLowDiskSpace] () -> void {
|
||||
RefPtr<nsDOMDeviceStorage> listener = do_QueryReferent(self->mListener);
|
||||
if (listener) {
|
||||
listener->OnDiskSpaceWatcher(aLowDiskSpace);
|
||||
}
|
||||
});
|
||||
mOwningThread->Dispatch(r.forget(), NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
void
|
||||
DeviceStorageStatics::ListenerWrapper::OnWritableNameChanged()
|
||||
{
|
||||
RefPtr<ListenerWrapper> self = this;
|
||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([self] () -> void {
|
||||
RefPtr<nsDOMDeviceStorage> listener = do_QueryReferent(self->mListener);
|
||||
if (listener) {
|
||||
listener->OnWritableNameChanged();
|
||||
}
|
||||
});
|
||||
mOwningThread->Dispatch(r.forget(), NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
void
|
||||
DeviceStorageStatics::ListenerWrapper::OnVolumeStateChanged(nsIVolume* aVolume)
|
||||
{
|
||||
RefPtr<ListenerWrapper> self = this;
|
||||
nsCOMPtr<nsIVolume> volume = aVolume;
|
||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([self, volume] () -> void {
|
||||
RefPtr<nsDOMDeviceStorage> listener = do_QueryReferent(self->mListener);
|
||||
if (listener) {
|
||||
listener->OnVolumeStateChanged(volume);
|
||||
}
|
||||
});
|
||||
mOwningThread->Dispatch(r.forget(), NS_DISPATCH_NORMAL);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace devicestorage
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_devicestorage_DeviceStorageStatics_h
|
||||
#define mozilla_dom_devicestorage_DeviceStorageStatics_h
|
||||
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/StaticMutex.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "nsArrayUtils.h"
|
||||
|
||||
class nsString;
|
||||
class nsDOMDeviceStorage;
|
||||
class DeviceStorageFile;
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
class nsIVolume;
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace devicestorage {
|
||||
|
||||
class DeviceStorageStatics final : public nsIObserver
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
static void Initialize();
|
||||
static void InitializeDirs();
|
||||
static void AddListener(nsDOMDeviceStorage* aListener);
|
||||
static void RemoveListener(nsDOMDeviceStorage* aListener);
|
||||
|
||||
static bool LowDiskSpace();
|
||||
static bool IsPromptTesting();
|
||||
static void GetWritableName(nsString& aName);
|
||||
static void SetWritableName(const nsAString& aName);
|
||||
|
||||
static void GetDeviceStorageLocationsForIPC(DeviceStorageLocationInfo* aLocationInfo);
|
||||
|
||||
static bool HasOverrideRootDir();
|
||||
static already_AddRefed<nsIFile> GetAppsDir();
|
||||
static already_AddRefed<nsIFile> GetCrashesDir();
|
||||
static already_AddRefed<nsIFile> GetPicturesDir();
|
||||
static already_AddRefed<nsIFile> GetVideosDir();
|
||||
static already_AddRefed<nsIFile> GetMusicDir();
|
||||
static already_AddRefed<nsIFile> GetSdcardDir();
|
||||
|
||||
private:
|
||||
enum DeviceStorageType {
|
||||
TYPE_APPS,
|
||||
TYPE_CRASHES,
|
||||
TYPE_PICTURES,
|
||||
TYPE_VIDEOS,
|
||||
TYPE_MUSIC,
|
||||
TYPE_SDCARD,
|
||||
TYPE_OVERRIDE,
|
||||
TYPE_COUNT
|
||||
};
|
||||
|
||||
static already_AddRefed<nsIFile> GetDir(DeviceStorageType aType);
|
||||
static void GetDirPath(DeviceStorageType aType, nsString& aString);
|
||||
|
||||
DeviceStorageStatics();
|
||||
virtual ~DeviceStorageStatics();
|
||||
|
||||
void Init();
|
||||
void InitDirs();
|
||||
void DumpDirs();
|
||||
void Shutdown();
|
||||
void Register();
|
||||
void Deregister();
|
||||
void ResetOverrideRootDir();
|
||||
|
||||
class ListenerWrapper final {
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ListenerWrapper)
|
||||
|
||||
explicit ListenerWrapper(nsDOMDeviceStorage* aListener);
|
||||
bool Equals(nsDOMDeviceStorage* aListener);
|
||||
void OnFileWatcherUpdate(const nsCString& aData, DeviceStorageFile* aFile);
|
||||
void OnDiskSpaceWatcher(bool aLowDiskSpace);
|
||||
void OnWritableNameChanged();
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
void OnVolumeStateChanged(nsIVolume* aVolume);
|
||||
#endif
|
||||
|
||||
private:
|
||||
virtual ~ListenerWrapper();
|
||||
|
||||
nsWeakPtr mListener;
|
||||
nsCOMPtr<nsIThread> mOwningThread;
|
||||
};
|
||||
|
||||
nsTArray<RefPtr<ListenerWrapper> > mListeners;
|
||||
nsCOMPtr<nsIFile> mDirs[TYPE_COUNT];
|
||||
|
||||
bool mInitialized;
|
||||
bool mPromptTesting;
|
||||
bool mLowDiskSpace;
|
||||
nsString mWritableName;
|
||||
|
||||
static StaticRefPtr<DeviceStorageStatics> sInstance;
|
||||
static StaticMutex sMutex;
|
||||
};
|
||||
|
||||
} // namespace devicestorage
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
include protocol PBlob;
|
||||
include protocol PContent;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace devicestorage {
|
||||
|
||||
|
||||
struct ErrorResponse
|
||||
{
|
||||
nsString error;
|
||||
};
|
||||
|
||||
struct SuccessResponse
|
||||
{
|
||||
};
|
||||
|
||||
struct FileDescriptorResponse
|
||||
{
|
||||
FileDescriptor fileDescriptor;
|
||||
};
|
||||
|
||||
struct BlobResponse
|
||||
{
|
||||
PBlob blob;
|
||||
};
|
||||
|
||||
struct DeviceStorageFileValue
|
||||
{
|
||||
nsString storageName;
|
||||
nsString name;
|
||||
};
|
||||
|
||||
struct EnumerationResponse
|
||||
{
|
||||
nsString type;
|
||||
nsString rootdir;
|
||||
DeviceStorageFileValue[] paths;
|
||||
};
|
||||
|
||||
struct FreeSpaceStorageResponse
|
||||
{
|
||||
uint64_t freeBytes;
|
||||
};
|
||||
|
||||
struct UsedSpaceStorageResponse
|
||||
{
|
||||
uint64_t usedBytes;
|
||||
};
|
||||
|
||||
struct FormatStorageResponse
|
||||
{
|
||||
nsString mountState;
|
||||
};
|
||||
|
||||
struct MountStorageResponse
|
||||
{
|
||||
nsString storageStatus;
|
||||
};
|
||||
|
||||
struct UnmountStorageResponse
|
||||
{
|
||||
nsString storageStatus;
|
||||
};
|
||||
|
||||
union DeviceStorageResponseValue
|
||||
{
|
||||
ErrorResponse;
|
||||
SuccessResponse;
|
||||
FileDescriptorResponse;
|
||||
BlobResponse;
|
||||
EnumerationResponse;
|
||||
FreeSpaceStorageResponse;
|
||||
UsedSpaceStorageResponse;
|
||||
FormatStorageResponse;
|
||||
MountStorageResponse;
|
||||
UnmountStorageResponse;
|
||||
};
|
||||
|
||||
sync protocol PDeviceStorageRequest {
|
||||
manager PContent;
|
||||
child:
|
||||
async __delete__(DeviceStorageResponseValue response);
|
||||
};
|
||||
|
||||
} // namespace devicestorage
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
with Files("**"):
|
||||
BUG_COMPONENT = ("Core", "DOM: Device Interfaces")
|
||||
|
||||
|
||||
EXPORTS += [
|
||||
'DeviceStorage.h',
|
||||
'DeviceStorageFileDescriptor.h',
|
||||
'nsDeviceStorage.h',
|
||||
]
|
||||
|
||||
EXPORTS.mozilla.dom.devicestorage += [
|
||||
'DeviceStorageRequestChild.h',
|
||||
'DeviceStorageRequestParent.h',
|
||||
'DeviceStorageStatics.h',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'DeviceStorageRequestChild.cpp',
|
||||
'DeviceStorageRequestParent.cpp',
|
||||
'DeviceStorageStatics.cpp',
|
||||
'nsDeviceStorage.cpp',
|
||||
]
|
||||
|
||||
IPDL_SOURCES += [
|
||||
'PDeviceStorageRequest.ipdl',
|
||||
]
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
LOCAL_INCLUDES += [
|
||||
'/dom/base',
|
||||
'/dom/ipc',
|
||||
]
|
||||
|
||||
MOCHITEST_MANIFESTS += [
|
||||
'test/mochitest.ini',
|
||||
]
|
||||
MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,434 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsDeviceStorage_h
|
||||
#define nsDeviceStorage_h
|
||||
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/devicestorage/DeviceStorageRequestChild.h"
|
||||
|
||||
#include "DOMRequest.h"
|
||||
#include "DOMCursor.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsDOMClassInfoID.h"
|
||||
#include "nsIClassInfo.h"
|
||||
#include "nsIDOMWindow.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsString.h"
|
||||
#include "nsWeakPtr.h"
|
||||
#include "nsIDOMEventListener.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsIStringBundle.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "prtime.h"
|
||||
#include "DeviceStorage.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
class ErrorResult;
|
||||
|
||||
namespace dom {
|
||||
class BlobImpl;
|
||||
class DeviceStorageParams;
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
class nsDOMDeviceStorage;
|
||||
class DeviceStorageCursorRequest;
|
||||
|
||||
//#define DS_LOGGING 1
|
||||
|
||||
#ifdef DS_LOGGING
|
||||
// FIXME -- use MOZ_LOG and set to warn by default
|
||||
#define DS_LOG_DEBUG(msg, ...) printf_stderr("[%s:%d] " msg "\n", __func__, __LINE__, ##__VA_ARGS__)
|
||||
#define DS_LOG_INFO DS_LOG_DEBUG
|
||||
#define DS_LOG_WARN DS_LOG_DEBUG
|
||||
#define DS_LOG_ERROR DS_LOG_DEBUG
|
||||
#else
|
||||
#define DS_LOG_DEBUG(msg, ...)
|
||||
#define DS_LOG_INFO(msg, ...)
|
||||
#define DS_LOG_WARN(msg, ...)
|
||||
#define DS_LOG_ERROR(msg, ...)
|
||||
#endif
|
||||
|
||||
#define POST_ERROR_EVENT_FILE_EXISTS "NoModificationAllowedError"
|
||||
#define POST_ERROR_EVENT_FILE_DOES_NOT_EXIST "NotFoundError"
|
||||
#define POST_ERROR_EVENT_FILE_NOT_ENUMERABLE "TypeMismatchError"
|
||||
#define POST_ERROR_EVENT_PERMISSION_DENIED "SecurityError"
|
||||
#define POST_ERROR_EVENT_ILLEGAL_TYPE "TypeMismatchError"
|
||||
#define POST_ERROR_EVENT_UNKNOWN "Unknown"
|
||||
|
||||
enum DeviceStorageRequestType {
|
||||
DEVICE_STORAGE_REQUEST_READ,
|
||||
DEVICE_STORAGE_REQUEST_WRITE,
|
||||
DEVICE_STORAGE_REQUEST_APPEND,
|
||||
DEVICE_STORAGE_REQUEST_CREATE,
|
||||
DEVICE_STORAGE_REQUEST_DELETE,
|
||||
DEVICE_STORAGE_REQUEST_WATCH,
|
||||
DEVICE_STORAGE_REQUEST_FREE_SPACE,
|
||||
DEVICE_STORAGE_REQUEST_USED_SPACE,
|
||||
DEVICE_STORAGE_REQUEST_AVAILABLE,
|
||||
DEVICE_STORAGE_REQUEST_STATUS,
|
||||
DEVICE_STORAGE_REQUEST_FORMAT,
|
||||
DEVICE_STORAGE_REQUEST_MOUNT,
|
||||
DEVICE_STORAGE_REQUEST_UNMOUNT,
|
||||
DEVICE_STORAGE_REQUEST_CREATEFD,
|
||||
DEVICE_STORAGE_REQUEST_CURSOR
|
||||
};
|
||||
|
||||
enum DeviceStorageAccessType {
|
||||
DEVICE_STORAGE_ACCESS_READ,
|
||||
DEVICE_STORAGE_ACCESS_WRITE,
|
||||
DEVICE_STORAGE_ACCESS_CREATE,
|
||||
DEVICE_STORAGE_ACCESS_UNDEFINED,
|
||||
DEVICE_STORAGE_ACCESS_COUNT
|
||||
};
|
||||
|
||||
class DeviceStorageUsedSpaceCache final
|
||||
{
|
||||
public:
|
||||
static DeviceStorageUsedSpaceCache* CreateOrGet();
|
||||
|
||||
DeviceStorageUsedSpaceCache();
|
||||
~DeviceStorageUsedSpaceCache();
|
||||
|
||||
|
||||
class InvalidateRunnable final : public mozilla::Runnable
|
||||
{
|
||||
public:
|
||||
InvalidateRunnable(DeviceStorageUsedSpaceCache* aCache,
|
||||
const nsAString& aStorageName)
|
||||
: mCache(aCache)
|
||||
, mStorageName(aStorageName) {}
|
||||
|
||||
~InvalidateRunnable() {}
|
||||
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
RefPtr<DeviceStorageUsedSpaceCache::CacheEntry> cacheEntry;
|
||||
cacheEntry = mCache->GetCacheEntry(mStorageName);
|
||||
if (cacheEntry) {
|
||||
cacheEntry->mDirty = true;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
private:
|
||||
DeviceStorageUsedSpaceCache* mCache;
|
||||
nsString mStorageName;
|
||||
};
|
||||
|
||||
void Invalidate(const nsAString& aStorageName)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mIOThread);
|
||||
|
||||
mIOThread->Dispatch(new InvalidateRunnable(this, aStorageName),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
void Dispatch(already_AddRefed<nsIRunnable>&& aRunnable)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mIOThread);
|
||||
|
||||
mIOThread->Dispatch(mozilla::Move(aRunnable), NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
struct CacheEntry
|
||||
{
|
||||
// Technically, this doesn't need to be threadsafe, but the implementation
|
||||
// of the non-thread safe one causes ASSERTS due to the underlying thread
|
||||
// associated with a LazyIdleThread changing from time to time.
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CacheEntry)
|
||||
|
||||
bool mDirty;
|
||||
nsString mStorageName;
|
||||
int64_t mFreeBytes;
|
||||
uint64_t mPicturesUsedSize;
|
||||
uint64_t mVideosUsedSize;
|
||||
uint64_t mMusicUsedSize;
|
||||
uint64_t mTotalUsedSize;
|
||||
|
||||
private:
|
||||
~CacheEntry() {}
|
||||
};
|
||||
already_AddRefed<CacheEntry> GetCacheEntry(const nsAString& aStorageName);
|
||||
|
||||
nsTArray<RefPtr<CacheEntry>> mCacheEntries;
|
||||
|
||||
nsCOMPtr<nsIThread> mIOThread;
|
||||
|
||||
static mozilla::StaticAutoPtr<DeviceStorageUsedSpaceCache> sDeviceStorageUsedSpaceCache;
|
||||
};
|
||||
|
||||
class DeviceStorageTypeChecker final
|
||||
{
|
||||
public:
|
||||
static DeviceStorageTypeChecker* CreateOrGet();
|
||||
|
||||
DeviceStorageTypeChecker();
|
||||
~DeviceStorageTypeChecker();
|
||||
|
||||
void InitFromBundle(nsIStringBundle* aBundle);
|
||||
|
||||
bool Check(const nsAString& aType, mozilla::dom::BlobImpl* aBlob);
|
||||
bool Check(const nsAString& aType, nsIFile* aFile);
|
||||
bool Check(const nsAString& aType, const nsString& aPath);
|
||||
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);
|
||||
static nsresult GetAccessForIndex(size_t aAccessIndex, nsACString& aAccessResult);
|
||||
static size_t GetAccessIndexForRequest(const DeviceStorageRequestType aRequestType);
|
||||
static bool IsVolumeBased(const nsAString& aType);
|
||||
static bool IsSharedMediaRoot(const nsAString& aType);
|
||||
|
||||
private:
|
||||
nsString mPicturesExtensions;
|
||||
nsString mVideosExtensions;
|
||||
nsString mMusicExtensions;
|
||||
|
||||
static mozilla::StaticAutoPtr<DeviceStorageTypeChecker> sDeviceStorageTypeChecker;
|
||||
};
|
||||
|
||||
class nsDOMDeviceStorageCursor final
|
||||
: public mozilla::dom::DOMCursor
|
||||
{
|
||||
public:
|
||||
NS_FORWARD_NSIDOMDOMCURSOR(mozilla::dom::DOMCursor::)
|
||||
|
||||
// DOMCursor
|
||||
virtual void Continue(mozilla::ErrorResult& aRv) override;
|
||||
|
||||
nsDOMDeviceStorageCursor(nsIGlobalObject* aGlobal,
|
||||
DeviceStorageCursorRequest* aRequest);
|
||||
|
||||
void FireSuccess(JS::Handle<JS::Value> aResult);
|
||||
void FireError(const nsString& aReason);
|
||||
void FireDone();
|
||||
|
||||
private:
|
||||
virtual ~nsDOMDeviceStorageCursor();
|
||||
|
||||
bool mOkToCallContinue;
|
||||
RefPtr<DeviceStorageCursorRequest> mRequest;
|
||||
};
|
||||
|
||||
class DeviceStorageRequestManager final
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DeviceStorageRequestManager)
|
||||
|
||||
static const uint32_t INVALID_ID = 0;
|
||||
|
||||
DeviceStorageRequestManager();
|
||||
|
||||
bool IsOwningThread();
|
||||
nsresult DispatchToOwningThread(already_AddRefed<nsIRunnable>&& aRunnable);
|
||||
|
||||
void StorePermission(size_t aAccess, bool aAllow);
|
||||
uint32_t CheckPermission(size_t aAccess);
|
||||
|
||||
/* These must be called on the owning thread context of the device
|
||||
storage object. It will hold onto a device storage reference until
|
||||
all of the pending requests are completed or shutdown is called. */
|
||||
uint32_t Create(nsDOMDeviceStorage* aDeviceStorage,
|
||||
mozilla::dom::DOMRequest** aRequest);
|
||||
uint32_t Create(nsDOMDeviceStorage* aDeviceStorage,
|
||||
DeviceStorageCursorRequest* aRequest,
|
||||
nsDOMDeviceStorageCursor** aCursor);
|
||||
|
||||
/* These may be called from any thread context and post a request
|
||||
to the owning thread to resolve the underlying DOMRequest or
|
||||
DOMCursor. In order to trigger FireDone for a DOMCursor, one
|
||||
should call Resolve with only the request ID. */
|
||||
nsresult Resolve(uint32_t aId, bool aForceDispatch);
|
||||
nsresult Resolve(uint32_t aId, const nsString& aValue, bool aForceDispatch);
|
||||
nsresult Resolve(uint32_t aId, uint64_t aValue, bool aForceDispatch);
|
||||
nsresult Resolve(uint32_t aId, DeviceStorageFile* aValue, bool aForceDispatch);
|
||||
nsresult Resolve(uint32_t aId, mozilla::dom::BlobImpl* aValue, bool aForceDispatch);
|
||||
nsresult Reject(uint32_t aId, const nsString& aReason);
|
||||
nsresult Reject(uint32_t aId, const char* aReason);
|
||||
|
||||
void Shutdown();
|
||||
|
||||
private:
|
||||
DeviceStorageRequestManager(const DeviceStorageRequestManager&) = delete;
|
||||
DeviceStorageRequestManager& operator=(const DeviceStorageRequestManager&) = delete;
|
||||
|
||||
struct ListEntry {
|
||||
RefPtr<mozilla::dom::DOMRequest> mRequest;
|
||||
uint32_t mId;
|
||||
bool mCursor;
|
||||
};
|
||||
|
||||
typedef nsTArray<ListEntry> ListType;
|
||||
typedef ListType::index_type ListIndex;
|
||||
|
||||
virtual ~DeviceStorageRequestManager();
|
||||
uint32_t CreateInternal(mozilla::dom::DOMRequest* aRequest, bool aCursor);
|
||||
nsresult ResolveInternal(ListIndex aIndex, JS::HandleValue aResult);
|
||||
nsresult RejectInternal(ListIndex aIndex, const nsString& aReason);
|
||||
nsresult DispatchOrAbandon(uint32_t aId,
|
||||
already_AddRefed<nsIRunnable>&& aRunnable);
|
||||
ListType::index_type Find(uint32_t aId);
|
||||
|
||||
nsCOMPtr<nsIThread> mOwningThread;
|
||||
ListType mPending; // owning thread or destructor only
|
||||
|
||||
mozilla::Mutex mMutex;
|
||||
uint32_t mPermissionCache[DEVICE_STORAGE_ACCESS_COUNT];
|
||||
bool mShutdown;
|
||||
|
||||
static mozilla::Atomic<uint32_t> sLastRequestId;
|
||||
};
|
||||
|
||||
class DeviceStorageRequest
|
||||
: public mozilla::Runnable
|
||||
{
|
||||
protected:
|
||||
DeviceStorageRequest();
|
||||
|
||||
public:
|
||||
virtual void Initialize(DeviceStorageRequestManager* aManager,
|
||||
already_AddRefed<DeviceStorageFile>&& aFile,
|
||||
uint32_t aRequest);
|
||||
|
||||
virtual void Initialize(DeviceStorageRequestManager* aManager,
|
||||
already_AddRefed<DeviceStorageFile>&& aFile,
|
||||
uint32_t aRequest,
|
||||
mozilla::dom::BlobImpl* aBlob);
|
||||
|
||||
virtual void Initialize(DeviceStorageRequestManager* aManager,
|
||||
already_AddRefed<DeviceStorageFile>&& aFile,
|
||||
uint32_t aRequest,
|
||||
DeviceStorageFileDescriptor* aDSFileDescriptor);
|
||||
|
||||
DeviceStorageAccessType GetAccess() const;
|
||||
void GetStorageType(nsAString& aType) const;
|
||||
DeviceStorageFile* GetFile() const;
|
||||
DeviceStorageFileDescriptor* GetFileDescriptor() const;
|
||||
DeviceStorageRequestManager* GetManager() const;
|
||||
|
||||
uint32_t GetId() const
|
||||
{
|
||||
return mId;
|
||||
}
|
||||
|
||||
void PermissionCacheMissed()
|
||||
{
|
||||
mPermissionCached = false;
|
||||
}
|
||||
|
||||
nsresult Cancel();
|
||||
nsresult Allow();
|
||||
|
||||
nsresult Resolve()
|
||||
{
|
||||
/* Always dispatch an empty resolve because that signals a cursor end
|
||||
and should not be executed directly from the caller's context due
|
||||
to the object potentially getting freed before we return. */
|
||||
uint32_t id = mId;
|
||||
mId = DeviceStorageRequestManager::INVALID_ID;
|
||||
return mManager->Resolve(id, true);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
nsresult Resolve(T aValue)
|
||||
{
|
||||
uint32_t id = mId;
|
||||
if (!mMultipleResolve) {
|
||||
mId = DeviceStorageRequestManager::INVALID_ID;
|
||||
}
|
||||
return mManager->Resolve(id, aValue, ForceDispatch());
|
||||
}
|
||||
|
||||
template<class T>
|
||||
nsresult Reject(T aReason)
|
||||
{
|
||||
uint32_t id = mId;
|
||||
mId = DeviceStorageRequestManager::INVALID_ID;
|
||||
return mManager->Reject(id, aReason);
|
||||
}
|
||||
|
||||
protected:
|
||||
bool ForceDispatch() const
|
||||
{
|
||||
return !mSendToParent && mPermissionCached;
|
||||
}
|
||||
|
||||
virtual ~DeviceStorageRequest();
|
||||
virtual nsresult Prepare();
|
||||
virtual nsresult CreateSendParams(mozilla::dom::DeviceStorageParams& aParams);
|
||||
nsresult AllowInternal();
|
||||
nsresult SendToParentProcess();
|
||||
|
||||
RefPtr<DeviceStorageRequestManager> mManager;
|
||||
RefPtr<DeviceStorageFile> mFile;
|
||||
uint32_t mId;
|
||||
RefPtr<mozilla::dom::BlobImpl> mBlob;
|
||||
RefPtr<DeviceStorageFileDescriptor> mDSFileDescriptor;
|
||||
DeviceStorageAccessType mAccess;
|
||||
bool mSendToParent;
|
||||
bool mUseMainThread;
|
||||
bool mUseStreamTransport;
|
||||
bool mCheckFile;
|
||||
bool mCheckBlob;
|
||||
bool mMultipleResolve;
|
||||
bool mPermissionCached;
|
||||
|
||||
private:
|
||||
DeviceStorageRequest(const DeviceStorageRequest&) = delete;
|
||||
DeviceStorageRequest& operator=(const DeviceStorageRequest&) = delete;
|
||||
};
|
||||
|
||||
class DeviceStorageCursorRequest final
|
||||
: public DeviceStorageRequest
|
||||
{
|
||||
public:
|
||||
DeviceStorageCursorRequest();
|
||||
|
||||
using DeviceStorageRequest::Initialize;
|
||||
|
||||
virtual void Initialize(DeviceStorageRequestManager* aManager,
|
||||
already_AddRefed<DeviceStorageFile>&& aFile,
|
||||
uint32_t aRequest,
|
||||
PRTime aSince);
|
||||
|
||||
void AddFiles(size_t aSize);
|
||||
void AddFile(already_AddRefed<DeviceStorageFile> aFile);
|
||||
nsresult Continue();
|
||||
NS_IMETHOD Run() override;
|
||||
|
||||
protected:
|
||||
virtual ~DeviceStorageCursorRequest()
|
||||
{ };
|
||||
|
||||
nsresult SendContinueToParentProcess();
|
||||
nsresult CreateSendParams(mozilla::dom::DeviceStorageParams& aParams) override;
|
||||
|
||||
size_t mIndex;
|
||||
PRTime mSince;
|
||||
nsString mStorageType;
|
||||
nsTArray<RefPtr<DeviceStorageFile> > mFiles;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
[DEFAULT]
|
||||
skip-if = os == 'android'
|
||||
|
||||
[test_app_permissions.html]
|
||||
[test_fs_app_permissions.html]
|
||||
|
|
@ -1,110 +0,0 @@
|
|||
/**
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
var oldVal = false;
|
||||
|
||||
Object.defineProperty(Array.prototype, "remove", {
|
||||
enumerable: false,
|
||||
configurable: false,
|
||||
writable: false,
|
||||
value: function(from, to) {
|
||||
// Array Remove - By John Resig (MIT Licensed)
|
||||
var rest = this.slice((to || from) + 1 || this.length);
|
||||
this.length = from < 0 ? this.length + from : from;
|
||||
return this.push.apply(this, rest);
|
||||
}
|
||||
});
|
||||
|
||||
function devicestorage_setup(callback) {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
const Cc = SpecialPowers.Cc;
|
||||
const Ci = SpecialPowers.Ci;
|
||||
var directoryService = Cc["@mozilla.org/file/directory_service;1"]
|
||||
.getService(Ci.nsIProperties);
|
||||
var f = directoryService.get("TmpD", Ci.nsIFile);
|
||||
f.appendRelativePath("device-storage-testing");
|
||||
|
||||
let script = SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL('remove_testing_directory.js'));
|
||||
|
||||
script.addMessageListener('directory-removed', function listener () {
|
||||
script.removeMessageListener('directory-removed', listener);
|
||||
var prefs = [["device.storage.enabled", true],
|
||||
["device.storage.testing", true],
|
||||
["device.storage.overrideRootDir", f.path],
|
||||
["device.storage.prompt.testing", true]];
|
||||
SpecialPowers.pushPrefEnv({"set": prefs}, callback);
|
||||
});
|
||||
}
|
||||
|
||||
function getRandomBuffer() {
|
||||
var size = 1024;
|
||||
var buffer = new ArrayBuffer(size);
|
||||
var view = new Uint8Array(buffer);
|
||||
for (var i = 0; i < size; i++) {
|
||||
view[i] = parseInt(Math.random() * 255);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
function createRandomBlob(mime) {
|
||||
return blob = new Blob([getRandomBuffer()], {type: mime});
|
||||
}
|
||||
|
||||
function randomFilename(l) {
|
||||
var set = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZ";
|
||||
var result = "";
|
||||
for (var i=0; i<l; i++) {
|
||||
var r = Math.floor(set.length * Math.random());
|
||||
result += set.substring(r, r + 1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function reportErrorAndQuit(e) {
|
||||
ok(false, "handleError was called : " + e.target.error.name);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function createTestFiles(storage, paths) {
|
||||
function createTestFile(path) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
function addNamed() {
|
||||
var req = storage.addNamed(createRandomBlob("image/png"), path);
|
||||
|
||||
req.onsuccess = function() {
|
||||
ok(true, path + " was created.");
|
||||
resolve();
|
||||
};
|
||||
|
||||
req.onerror = function(e) {
|
||||
ok(false, "Failed to create " + path + ': ' + e.target.error.name);
|
||||
reject();
|
||||
};
|
||||
}
|
||||
|
||||
// Bug 980136. Check if the file exists before we create.
|
||||
var req = storage.get(path);
|
||||
|
||||
req.onsuccess = function() {
|
||||
ok(true, path + " exists. Do not need to create.");
|
||||
resolve();
|
||||
};
|
||||
|
||||
req.onerror = function(e) {
|
||||
ok(true, path + " does not exists: " + e.target.error.name);
|
||||
addNamed();
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
var arr = [];
|
||||
|
||||
paths.forEach(function(path) {
|
||||
arr.push(createTestFile(path));
|
||||
});
|
||||
|
||||
return Promise.all(arr);
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
[DEFAULT]
|
||||
support-files = devicestorage_common.js
|
||||
remove_testing_directory.js
|
||||
|
||||
[test_823965.html]
|
||||
# [test_add.html]
|
||||
# man, our mime database sucks hard. followup bug # 788273
|
||||
[test_addCorrectType.html]
|
||||
[test_available.html]
|
||||
[test_basic.html]
|
||||
[test_dirs.html]
|
||||
# [test_diskSpace.html]
|
||||
# Possible race between the time we write a file, and the
|
||||
# time it takes to be reflected by statfs(). Bug # 791287
|
||||
[test_dotdot.html]
|
||||
[test_enumerate.html]
|
||||
[test_enumerateMultipleContinue.html]
|
||||
[test_enumerateOptions.html]
|
||||
[test_freeSpace.html]
|
||||
# FileSystem API tests start
|
||||
[test_fs_basic.html]
|
||||
[test_fs_createDirectory.html]
|
||||
[test_fs_get.html]
|
||||
[test_fs_getFilesAndDirectories.html]
|
||||
[test_fs_remove.html]
|
||||
[test_fs_createFile.html]
|
||||
[test_fs_appendFile.html]
|
||||
# FileSystem API tests end
|
||||
[test_lastModificationFilter.html]
|
||||
[test_overrideDir.html]
|
||||
[test_overwrite.html]
|
||||
[test_sanity.html]
|
||||
[test_usedSpace.html]
|
||||
[test_watch.html]
|
||||
[test_watchOther.html]
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
// ensure that the directory we are writing into is empty
|
||||
try {
|
||||
var Cc = Components.classes;
|
||||
var Ci = Components.interfaces;
|
||||
var directoryService = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
|
||||
var f = directoryService.get("TmpD", Ci.nsIFile);
|
||||
f.appendRelativePath("device-storage-testing");
|
||||
f.remove(true);
|
||||
} catch(e) {}
|
||||
|
||||
sendAsyncMessage('directory-removed', {});
|
||||
|
|
@ -1,107 +0,0 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html> <!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=823965
|
||||
-->
|
||||
<head>
|
||||
<title>Test for the device storage API </title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="devicestorage_common.js"></script>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=823965">Mozilla Bug 823965</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
devicestorage_setup(function () {
|
||||
|
||||
var gFileName = "devicestorage/" + randomFilename(12) + "/hi.png";
|
||||
var gData = "My name is Doug Turner (?!?). My IRC nick is DougT. I like Maple cookies."
|
||||
var gDataBlob = new Blob([gData], {type: 'image/png'});
|
||||
|
||||
function getSuccess(e) {
|
||||
var storage = navigator.getDeviceStorage("pictures");
|
||||
ok(navigator.getDeviceStorage, "Should have getDeviceStorage");
|
||||
|
||||
ok(e.target.result.name == gFileName, "File name should match");
|
||||
ok(e.target.result.size > 0, "File size be greater than zero");
|
||||
ok(e.target.result.type, "File should have a mime type");
|
||||
ok(e.target.result.lastModifiedDate, "File should have a last modified date");
|
||||
|
||||
var mreq = storage.enumerate();
|
||||
mreq.onsuccess = function() {
|
||||
var storage2 = navigator.getDeviceStorage('music');
|
||||
var dreq = storage2.delete(mreq.result.name);
|
||||
dreq.onerror = function () {
|
||||
ok(true, "The bug has been fixed");
|
||||
SimpleTest.finish();
|
||||
};
|
||||
dreq.onsuccess = function () {
|
||||
ok(false, "The bug has been fixed");
|
||||
SimpleTest.finish();
|
||||
};
|
||||
};
|
||||
|
||||
mreq.onerror = getError;
|
||||
}
|
||||
|
||||
function getError(e) {
|
||||
ok(false, "getError was called : " + e.target.error.name);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function addSuccess(e) {
|
||||
|
||||
var filename = e.target.result;
|
||||
if (filename[0] == "/") {
|
||||
// We got /storageName/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
|
||||
}
|
||||
}
|
||||
ok(filename == gFileName, "File name should match");
|
||||
// Since we now have the fully qualified name, change gFileName to that.
|
||||
gFileName = e.target.result;
|
||||
|
||||
var storage = navigator.getDeviceStorage("pictures");
|
||||
request = storage.get(gFileName);
|
||||
request.onsuccess = getSuccess;
|
||||
request.onerror = getError;
|
||||
|
||||
ok(true, "addSuccess was called");
|
||||
}
|
||||
|
||||
function addError(e) {
|
||||
ok(false, "addError was called : " + e.target.error.name);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
ok(navigator.getDeviceStorage, "Should have getDeviceStorage");
|
||||
|
||||
var storage = navigator.getDeviceStorage("pictures");
|
||||
ok(storage, "Should have gotten a storage");
|
||||
|
||||
request = storage.addNamed(gDataBlob, gFileName);
|
||||
ok(request, "Should have a non-null request");
|
||||
|
||||
request.onsuccess = addSuccess;
|
||||
request.onerror = addError;
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=786922
|
||||
-->
|
||||
<head>
|
||||
<title>Test for basic sanity of the device storage API </title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="devicestorage_common.js"></script>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=786922">Mozilla Bug 786922</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
|
||||
devicestorage_setup(function () {
|
||||
|
||||
function add(storage, mime) {
|
||||
dump("adding: " + mime + "\n");
|
||||
return navigator.getDeviceStorage(storage).add(createRandomBlob(mime));
|
||||
}
|
||||
|
||||
var tests = [
|
||||
function () { return add("pictures", "image/png")},
|
||||
function () { return add("videos", "video/webm")},
|
||||
function () { return add("music", "audio/wav")},
|
||||
function () { return add("sdcard", "maple/cookies")},
|
||||
];
|
||||
|
||||
function fail(e) {
|
||||
ok(false, "onerror was called");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function next(e) {
|
||||
|
||||
if (e != undefined)
|
||||
ok(true, "addError was called");
|
||||
|
||||
var f = tests.pop();
|
||||
|
||||
if (f == undefined) {
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
request = f();
|
||||
request.onsuccess = next;
|
||||
request.onerror = fail;
|
||||
}
|
||||
|
||||
next();
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=786922
|
||||
-->
|
||||
<head>
|
||||
<title>Test for basic sanity of the device storage API </title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="devicestorage_common.js"></script>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=786922">Mozilla Bug 786922</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
|
||||
devicestorage_setup(function () {
|
||||
|
||||
function addNamed(storage, mime, fileExtension) {
|
||||
dump("adding: " + mime + " " + fileExtension + "\n");
|
||||
return navigator.getDeviceStorage(storage).addNamed(createRandomBlob(mime), randomFilename(40) + "." + fileExtension);
|
||||
}
|
||||
|
||||
// These tests must all fail
|
||||
var tests = [
|
||||
function () { return addNamed("pictures", "kyle/smash", ".png")},
|
||||
function () { return addNamed("pictures", "image/png", ".poo")},
|
||||
function () { return addNamed("music", "kyle/smash", ".mp3")},
|
||||
function () { return addNamed("music", "music/mp3", ".poo")},
|
||||
function () { return addNamed("videos", "kyle/smash", ".ogv")},
|
||||
function () { return addNamed("videos", "video/ogv", ".poo")},
|
||||
];
|
||||
|
||||
function fail(e) {
|
||||
ok(false, "addSuccess was called");
|
||||
ok(e.target.error.name == "TypeMismatchError", "Error must be TypeMismatchError");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function next(e) {
|
||||
|
||||
if (e != undefined)
|
||||
ok(true, "addError was called");
|
||||
|
||||
var f = tests.pop();
|
||||
|
||||
if (f == undefined) {
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
request = f();
|
||||
request.onsuccess = fail;
|
||||
request.onerror = next;
|
||||
}
|
||||
|
||||
next();
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,481 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=805322
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Permission test for Device Storage</title>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=805322">Mozilla Bug 805322</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
function randomFilename(l) {
|
||||
var set = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZ";
|
||||
var result = "";
|
||||
for (var i=0; i<l; i++) {
|
||||
var r = Math.floor(set.length * Math.random());
|
||||
result += set.substring(r, r + 1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
var MockPermissionPrompt = SpecialPowers.MockPermissionPrompt;
|
||||
MockPermissionPrompt.init();
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function TestAdd(iframe, data) {
|
||||
|
||||
var storage = iframe.contentDocument.defaultView.navigator.getDeviceStorage(data.type);
|
||||
isnot(storage, null, "Should be able to get storage object for " + data.type);
|
||||
|
||||
var blob = new Blob(["Kyle Huey is not a helicopter."], {type: data.mimeType});
|
||||
|
||||
request = storage.addNamed(blob, randomFilename(100) + "hi" + data.fileExtension);
|
||||
isnot(request, null, "Should be able to get request");
|
||||
|
||||
request.onsuccess = function() {
|
||||
is(data.shouldPass, true, "onsuccess was called for type " + data.type);
|
||||
testComplete(iframe, data);
|
||||
};
|
||||
|
||||
request.onerror = function(e) {
|
||||
isnot(data.shouldPass, true, "onfailure was called for type " + data.type + " Error: " + e.target.error.name);
|
||||
is(e.target.error.name, "SecurityError", "onerror should fire a SecurityError");
|
||||
testComplete(iframe, data);
|
||||
};
|
||||
}
|
||||
|
||||
function TestGet(iframe, data) {
|
||||
|
||||
createTestFile(data.fileExtension);
|
||||
|
||||
var storage = iframe.contentDocument.defaultView.navigator.getDeviceStorage(data.type);
|
||||
isnot(storage, null, "Should be able to get storage object for " + data.type);
|
||||
|
||||
request = storage.get("testfile" + data.fileExtension);
|
||||
isnot(request, null, "Should be able to get request");
|
||||
|
||||
request.onsuccess = function() {
|
||||
is(data.shouldPass, true, "onsuccess was called for type " + data.type);
|
||||
testComplete(iframe, data);
|
||||
};
|
||||
|
||||
request.onerror = function(e) {
|
||||
isnot(data.shouldPass, true, "onfailure was called for type " + data.type + " Error: " + e.target.error.name);
|
||||
testComplete(iframe, data);
|
||||
};
|
||||
}
|
||||
|
||||
function TestDelete(iframe, data) {
|
||||
|
||||
createTestFile(data.fileExtension);
|
||||
|
||||
var storage = iframe.contentDocument.defaultView.navigator.getDeviceStorage(data.type);
|
||||
isnot(storage, null, "Should be able to get storage object for " + data.type);
|
||||
|
||||
request = storage.delete("testfile" + data.fileExtension);
|
||||
isnot(request, null, "Should be able to get request");
|
||||
|
||||
request.onsuccess = function() {
|
||||
is(data.shouldPass, true, "onsuccess was called for type " + data.type);
|
||||
testComplete(iframe, data);
|
||||
};
|
||||
|
||||
request.onerror = function(e) {
|
||||
isnot(data.shouldPass, true, "onfailure was called for type " + data.type + " Error: " + e.target.error.name);
|
||||
is(e.target.error.name, "SecurityError", "onerror should fire a SecurityError");
|
||||
testComplete(iframe, data);
|
||||
};
|
||||
}
|
||||
|
||||
function TestEnumerate(iframe, data) {
|
||||
|
||||
createTestFile(data.fileExtension);
|
||||
|
||||
var storage = iframe.contentDocument.defaultView.navigator.getDeviceStorage(data.type);
|
||||
isnot(storage, null, "Should be able to get storage object for " + data.type);
|
||||
|
||||
request = storage.enumerate();
|
||||
isnot(request, null, "Should be able to get request");
|
||||
|
||||
request.onsuccess = function(e) {
|
||||
is(data.shouldPass, true, "onsuccess was called for type " + data.type);
|
||||
|
||||
if (e.target.result == null) {
|
||||
testComplete(iframe, data);
|
||||
return;
|
||||
}
|
||||
e.target.continue();
|
||||
};
|
||||
|
||||
request.onerror = function(e) {
|
||||
isnot(data.shouldPass, true, "onfailure was called for type " + data.type + " Error: " + e.target.error.name);
|
||||
is(e.target.error.name, "SecurityError", "onerror should fire a SecurityError");
|
||||
testComplete(iframe, data);
|
||||
};
|
||||
}
|
||||
|
||||
var gTestUri = "https://example.com/chrome/dom/devicestorage/test/test_app_permissions.html"
|
||||
|
||||
var gData = [
|
||||
|
||||
// Get
|
||||
// Web applications with no permissions
|
||||
{
|
||||
type: 'pictures',
|
||||
shouldPass: false,
|
||||
fileExtension: '.png',
|
||||
test: TestGet
|
||||
},
|
||||
{
|
||||
type: 'videos',
|
||||
shouldPass: false,
|
||||
fileExtension: '.ogv',
|
||||
test: TestGet
|
||||
},
|
||||
{
|
||||
type: 'music',
|
||||
shouldPass: false,
|
||||
fileExtension: '.ogg',
|
||||
test: TestGet
|
||||
},
|
||||
{
|
||||
type: 'sdcard',
|
||||
shouldPass: false,
|
||||
fileExtension: '.txt',
|
||||
test: TestGet
|
||||
},
|
||||
|
||||
// Web applications with permission granted
|
||||
{
|
||||
type: 'pictures',
|
||||
shouldPass: true,
|
||||
fileExtension: '.png',
|
||||
|
||||
permissions: ["device-storage:pictures"],
|
||||
|
||||
test: TestGet
|
||||
},
|
||||
{
|
||||
type: 'videos',
|
||||
shouldPass: true,
|
||||
fileExtension: '.ogv',
|
||||
|
||||
permissions: ["device-storage:videos"],
|
||||
|
||||
test: TestGet
|
||||
},
|
||||
{
|
||||
type: 'music',
|
||||
shouldPass: true,
|
||||
fileExtension: '.ogg',
|
||||
|
||||
permissions: ["device-storage:music"],
|
||||
|
||||
test: TestGet
|
||||
},
|
||||
{
|
||||
type: 'sdcard',
|
||||
shouldPass: true,
|
||||
fileExtension: '.txt',
|
||||
|
||||
permissions: ["device-storage:sdcard"],
|
||||
|
||||
test: TestGet
|
||||
},
|
||||
|
||||
|
||||
// Add
|
||||
|
||||
|
||||
// Web applications with no permissions
|
||||
{
|
||||
type: 'pictures',
|
||||
mimeType: 'image/png',
|
||||
fileExtension: '.png',
|
||||
shouldPass: false,
|
||||
test: TestAdd
|
||||
},
|
||||
{
|
||||
type: 'videos',
|
||||
mimeType: 'video/ogv',
|
||||
fileExtension: '.ogv',
|
||||
shouldPass: false,
|
||||
test: TestAdd
|
||||
},
|
||||
{
|
||||
type: 'music',
|
||||
mimeType: 'audio/ogg',
|
||||
fileExtension: '.ogg',
|
||||
shouldPass: false,
|
||||
test: TestAdd
|
||||
},
|
||||
{
|
||||
type: 'sdcard',
|
||||
mimeType: 'text/plain',
|
||||
fileExtension: '.txt',
|
||||
shouldPass: false,
|
||||
test: TestAdd
|
||||
},
|
||||
|
||||
// Web applications with permission granted
|
||||
{
|
||||
type: 'pictures',
|
||||
mimeType: 'image/png',
|
||||
fileExtension: '.png',
|
||||
shouldPass: true,
|
||||
|
||||
permissions: ["device-storage:pictures"],
|
||||
|
||||
test: TestAdd
|
||||
},
|
||||
{
|
||||
type: 'videos',
|
||||
mimeType: 'video/ogv',
|
||||
fileExtension: '.ogv',
|
||||
shouldPass: true,
|
||||
|
||||
permissions: ["device-storage:videos"],
|
||||
|
||||
test: TestAdd
|
||||
},
|
||||
{
|
||||
type: 'music',
|
||||
mimeType: 'audio/ogg',
|
||||
fileExtension: '.ogg',
|
||||
shouldPass: true,
|
||||
|
||||
permissions: ["device-storage:music"],
|
||||
|
||||
test: TestAdd
|
||||
},
|
||||
{
|
||||
type: 'sdcard',
|
||||
mimeType: 'text/plain',
|
||||
fileExtension: '.txt',
|
||||
shouldPass: true,
|
||||
|
||||
permissions: ["device-storage:sdcard"],
|
||||
|
||||
test: TestAdd
|
||||
},
|
||||
|
||||
|
||||
// Delete
|
||||
|
||||
// Web applications with no permissions
|
||||
{
|
||||
type: 'pictures',
|
||||
shouldPass: false,
|
||||
fileExtension: '.png',
|
||||
test: TestDelete
|
||||
},
|
||||
{
|
||||
type: 'videos',
|
||||
shouldPass: false,
|
||||
fileExtension: '.ogv',
|
||||
test: TestDelete
|
||||
},
|
||||
{
|
||||
type: 'music',
|
||||
shouldPass: false,
|
||||
fileExtension: '.ogg',
|
||||
test: TestDelete
|
||||
},
|
||||
{
|
||||
type: 'sdcard',
|
||||
shouldPass: false,
|
||||
fileExtension: '.txt',
|
||||
test: TestDelete
|
||||
},
|
||||
|
||||
// Web applications with permission granted
|
||||
{
|
||||
type: 'pictures',
|
||||
shouldPass: true,
|
||||
fileExtension: '.png',
|
||||
|
||||
permissions: ["device-storage:pictures"],
|
||||
|
||||
test: TestDelete
|
||||
},
|
||||
{
|
||||
type: 'videos',
|
||||
shouldPass: true,
|
||||
fileExtension: '.ogv',
|
||||
|
||||
permissions: ["device-storage:videos"],
|
||||
|
||||
test: TestDelete
|
||||
},
|
||||
{
|
||||
type: 'music',
|
||||
shouldPass: true,
|
||||
fileExtension: '.ogg',
|
||||
|
||||
permissions: ["device-storage:music"],
|
||||
|
||||
test: TestDelete
|
||||
},
|
||||
{
|
||||
type: 'sdcard',
|
||||
shouldPass: true,
|
||||
fileExtension: '.txt',
|
||||
|
||||
permissions: ["device-storage:sdcard"],
|
||||
|
||||
test: TestDelete
|
||||
},
|
||||
|
||||
// Enumeration
|
||||
|
||||
// Web applications with no permissions
|
||||
{
|
||||
type: 'pictures',
|
||||
shouldPass: false,
|
||||
fileExtension: '.png',
|
||||
test: TestEnumerate
|
||||
},
|
||||
{
|
||||
type: 'videos',
|
||||
shouldPass: false,
|
||||
fileExtension: '.ogv',
|
||||
test: TestEnumerate
|
||||
},
|
||||
{
|
||||
type: 'music',
|
||||
shouldPass: false,
|
||||
fileExtension: '.ogg',
|
||||
test: TestEnumerate
|
||||
},
|
||||
{
|
||||
type: 'sdcard',
|
||||
shouldPass: false,
|
||||
fileExtension: '.txt',
|
||||
test: TestEnumerate
|
||||
},
|
||||
|
||||
// Web applications with permission granted
|
||||
{
|
||||
type: 'pictures',
|
||||
shouldPass: true,
|
||||
fileExtension: '.png',
|
||||
|
||||
permissions: ["device-storage:pictures"],
|
||||
|
||||
test: TestEnumerate
|
||||
},
|
||||
{
|
||||
type: 'videos',
|
||||
shouldPass: true,
|
||||
fileExtension: '.ogv',
|
||||
|
||||
permissions: ["device-storage:videos"],
|
||||
|
||||
test: TestEnumerate
|
||||
},
|
||||
{
|
||||
type: 'music',
|
||||
shouldPass: true,
|
||||
fileExtension: '.ogg',
|
||||
|
||||
permissions: ["device-storage:music"],
|
||||
|
||||
test: TestEnumerate
|
||||
},
|
||||
{
|
||||
type: 'sdcard',
|
||||
shouldPass: true,
|
||||
fileExtension: '.txt',
|
||||
|
||||
permissions: ["device-storage:sdcard"],
|
||||
|
||||
test: TestEnumerate
|
||||
},
|
||||
|
||||
];
|
||||
|
||||
function setupTest(iframe,data) {
|
||||
if (data.permissions) {
|
||||
for (var j in data.permissions) {
|
||||
SpecialPowers.addPermission(data.permissions[j], true, iframe.contentDocument);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function testComplete(iframe, data) {
|
||||
if (data.permissions) {
|
||||
for (var j in data.permissions) {
|
||||
SpecialPowers.removePermission(data.permissions[j], iframe.contentDocument);
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById('content').removeChild(iframe);
|
||||
|
||||
if (gData.length == 0) {
|
||||
SimpleTest.finish();
|
||||
} else {
|
||||
gTestRunner.next();
|
||||
}
|
||||
}
|
||||
|
||||
function* runTest() {
|
||||
while (gData.length > 0) {
|
||||
var iframe = document.createElement('iframe');
|
||||
var data = gData.pop();
|
||||
|
||||
iframe.setAttribute('mozbrowser', '');
|
||||
|
||||
iframe.src = gTestUri;
|
||||
|
||||
iframe.addEventListener('load', function(e) {
|
||||
setupTest(iframe, data)
|
||||
data.test(iframe, data);
|
||||
});
|
||||
|
||||
document.getElementById('content').appendChild(iframe);
|
||||
yield undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function createTestFile(extension) {
|
||||
try {
|
||||
const Cc = SpecialPowers.Cc;
|
||||
const Ci = SpecialPowers.Ci;
|
||||
var directoryService = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
|
||||
var f = directoryService.get("TmpD", Ci.nsIFile);
|
||||
f.appendRelativePath("device-storage-testing");
|
||||
f.remove(true);
|
||||
f.appendRelativePath("testfile" + extension);
|
||||
f.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
|
||||
} catch(e) {}
|
||||
}
|
||||
|
||||
createTestFile('.txt');
|
||||
var gTestRunner = runTest();
|
||||
SpecialPowers.addPermission("browser", true, gTestUri);
|
||||
|
||||
SpecialPowers.pushPrefEnv({'set': [["dom.mozBrowserFramesEnabled", true],
|
||||
["network.disable.ipc.security", true],
|
||||
["device.storage.enabled", true],
|
||||
["device.storage.testing", true],
|
||||
["device.storage.prompt.testing", false]]},
|
||||
function() { gTestRunner.next(); });
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html> <!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=834595
|
||||
-->
|
||||
<head>
|
||||
<title>Test for the device storage API </title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="devicestorage_common.js"></script>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=834595">Mozilla Bug 834595</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
devicestorage_setup(function () {
|
||||
|
||||
function availableSuccess(e) {
|
||||
isnot(e.target.result, null, "result should not be null");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function availableError(e) {
|
||||
ok(false, "availableError was called");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
var storage = navigator.getDeviceStorage("pictures");
|
||||
|
||||
request = storage.available();
|
||||
ok(request, "Should have a non-null request");
|
||||
|
||||
request.onsuccess = availableSuccess;
|
||||
request.onerror = availableError;
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,141 +0,0 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html> <!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=717103
|
||||
-->
|
||||
<head>
|
||||
<title>Test for the device storage API </title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="devicestorage_common.js"></script>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=717103">Mozilla Bug 717103</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
devicestorage_setup(function() {
|
||||
|
||||
var gFileName = "devicestorage/" + randomFilename(12) + "/hi.png";
|
||||
var gData = "My name is Doug Turner. My IRC nick is DougT. I like Maple cookies."
|
||||
var gDataBlob = new Blob([gData], {type: 'image/png'});
|
||||
var gFileReader = new FileReader();
|
||||
|
||||
function getAfterDeleteSuccess(e) {
|
||||
ok(false, "file was deleted not successfully");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function getAfterDeleteError(e) {
|
||||
ok(true, "file was deleted successfully");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function deleteSuccess(e) {
|
||||
|
||||
ok(e.target.result == gFileName, "File name should match");
|
||||
dump(e.target.result + "\n")
|
||||
|
||||
var storage = navigator.getDeviceStorage("pictures");
|
||||
request = storage.get(e.target.result);
|
||||
request.onsuccess = getAfterDeleteSuccess;
|
||||
request.onerror = getAfterDeleteError;
|
||||
|
||||
}
|
||||
|
||||
function deleteError(e) {
|
||||
ok(false, "deleteError was called : " + e.target.error.name);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function getSuccess(e) {
|
||||
var storage = navigator.getDeviceStorage("pictures");
|
||||
ok(navigator.getDeviceStorage, "Should have getDeviceStorage");
|
||||
|
||||
ok(e.target.result.name == gFileName, "File name should match");
|
||||
ok(e.target.result.size > 0, "File size be greater than zero");
|
||||
ok(e.target.result.type, "File should have a mime type");
|
||||
ok(e.target.result.lastModifiedDate, "File should have a last modified date");
|
||||
|
||||
var name = e.target.result.name;
|
||||
|
||||
gFileReader.readAsArrayBuffer(gDataBlob);
|
||||
gFileReader.onload = function(e) {
|
||||
readerCallback(e);
|
||||
|
||||
request = storage.delete(name)
|
||||
request.onsuccess = deleteSuccess;
|
||||
request.onerror = deleteError;
|
||||
}
|
||||
}
|
||||
|
||||
function readerCallback(e) {
|
||||
|
||||
ab = e.target.result;
|
||||
|
||||
is(ab.byteLength, gData.length, "wrong arraybuffer byteLength");
|
||||
var u8v = new Uint8Array(ab);
|
||||
is(String.fromCharCode.apply(String, u8v), gData, "wrong values");
|
||||
}
|
||||
|
||||
function getError(e) {
|
||||
ok(false, "getError was called : " + e.target.error.name);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function addSuccess(e) {
|
||||
|
||||
var filename = e.target.result;
|
||||
if (filename[0] == "/") {
|
||||
// We got /storageName/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
|
||||
}
|
||||
}
|
||||
ok(filename == gFileName, "File name should match");
|
||||
|
||||
// Update gFileName to be the fully qualified name so that
|
||||
// further checks will pass.
|
||||
gFileName = e.target.result;
|
||||
|
||||
var storage = navigator.getDeviceStorage("pictures");
|
||||
request = storage.get(gFileName);
|
||||
request.onsuccess = getSuccess;
|
||||
request.onerror = getError;
|
||||
|
||||
ok(true, "addSuccess was called");
|
||||
}
|
||||
|
||||
function addError(e) {
|
||||
ok(false, "addError was called : " + e.target.error.name);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
ok(navigator.getDeviceStorage, "Should have getDeviceStorage");
|
||||
|
||||
var storage = navigator.getDeviceStorage("pictures");
|
||||
ok(storage, "Should have gotten a storage");
|
||||
|
||||
request = storage.addNamed(gDataBlob, gFileName);
|
||||
ok(request, "Should have a non-null request");
|
||||
|
||||
request.onsuccess = addSuccess;
|
||||
request.onerror = addError;
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=886627
|
||||
-->
|
||||
<head>
|
||||
<title>Test for the device storage API</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="devicestorage_common.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=886627">
|
||||
Mozilla Bug 886627
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/**
|
||||
* Test that common device storage directories are available.
|
||||
*
|
||||
* This test differs from other device storage tests in that other tests use a
|
||||
* "testing mode", which relocates the device storage directories to a testing
|
||||
* directory. On the other hand, this test turns off testing mode to makes sure
|
||||
* that the normal, non-testing directories also work properly.
|
||||
*/
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
SpecialPowers.pushPrefEnv({
|
||||
'set': [
|
||||
["device.storage.enabled", true],
|
||||
["device.storage.testing", false],
|
||||
["device.storage.prompt.testing", true],
|
||||
]
|
||||
}, function() {
|
||||
ok(navigator.getDeviceStorage, "Should have getDeviceStorage");
|
||||
ok(!navigator.getDeviceStorage("nonexistent-type"), "Should not have nonexistent storage");
|
||||
|
||||
ok(navigator.getDeviceStorage("pictures"), "Should have pictures storage");
|
||||
ok(navigator.getDeviceStorage("videos"), "Should have videos storage");
|
||||
ok(navigator.getDeviceStorage("music"), "Should have music storage");
|
||||
|
||||
// Need special permission to access "apps". We always have the permission in B2G
|
||||
// mochitests, but on other platforms, we need to manually add the permission.
|
||||
var needAppsPermission = false;;
|
||||
if (!SpecialPowers.testPermission(
|
||||
"webapps-manage", SpecialPowers.Ci.nsIPermissionManager.ALLOW_ACTION, document)) {
|
||||
ok(!navigator.getDeviceStorage("apps"), "Should not have apps storage without permission");
|
||||
needAppsPermission = true;
|
||||
}
|
||||
|
||||
var testFunction = function() {
|
||||
ok(navigator.getDeviceStorage("apps"), "Should have apps storage with permission");
|
||||
ok(navigator.getDeviceStorage("sdcard"), "Should have sdcard storage");
|
||||
ok(navigator.getDeviceStorage("crashes"), "Should have crashes storage");
|
||||
// The test harness reverts our pref changes automatically.
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
if (needAppsPermission) {
|
||||
SpecialPowers.pushPermissions(
|
||||
[{ "type":"webapps-manage", "allow": true, "context": document }],
|
||||
testFunction);
|
||||
} else {
|
||||
testFunction();
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
|
@ -1,101 +0,0 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html> <!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=717103
|
||||
-->
|
||||
<head>
|
||||
<title>Test for the device storage API </title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="devicestorage_common.js"></script>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=717103">Mozilla Bug 717103</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
devicestorage_setup(function () {
|
||||
|
||||
var freeBytes = -1;
|
||||
var stats = 0;
|
||||
|
||||
function stat(s, file_list_length) {
|
||||
if (freeBytes == -1) {
|
||||
freeBytes = s.target.result.freeBytes;
|
||||
}
|
||||
|
||||
ok(freeBytes == s.target.result.freeBytes, "Free bytes should be the same");
|
||||
ok(file_list_length * 1024 == s.target.result.totalBytes, "space taken up by files should match")
|
||||
|
||||
stats = stats + 1;
|
||||
|
||||
if (stats == 2) {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
function addSuccess(e) {
|
||||
added = added - 1;
|
||||
|
||||
if (added == 0) {
|
||||
request = pictures.stat();
|
||||
request.onsuccess = function(s) {stat(s, picture_files.length)};
|
||||
|
||||
request = videos.stat();
|
||||
request.onsuccess = function(s) {stat(s, video_files.length)};
|
||||
|
||||
request = music.stat();
|
||||
request.onsuccess = function(s) {stat(s, music_files.length)};
|
||||
}
|
||||
}
|
||||
|
||||
function addError(e) {
|
||||
ok(false, "addError was called : " + e.target.error.name);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
ok(true, "hi");
|
||||
|
||||
var pictures = navigator.getDeviceStorage("pictures");
|
||||
var picture_files = [ "a.png", "b.png", "c.png", "d.png", "e.png" ];
|
||||
|
||||
var videos = navigator.getDeviceStorage("videos");
|
||||
var video_files = [ "a.ogv", "b.ogv" ];
|
||||
|
||||
var music = navigator.getDeviceStorage("music");
|
||||
var music_files = [ "a.mp3", "b.mp3", "c.mp3" ];
|
||||
|
||||
var added = picture_files.length + video_files.length + music_files.length;
|
||||
|
||||
for (var i=0; i < picture_files.length; i++) {
|
||||
request = pictures.addNamed(createRandomBlob('image/png'), picture_files[i]);
|
||||
request.onsuccess = addSuccess;
|
||||
request.onerror = addError;
|
||||
}
|
||||
|
||||
for (var i=0; i < video_files.length; i++) {
|
||||
request = videos.addNamed(createRandomBlob('video/ogv'), video_files[i]);
|
||||
request.onsuccess = addSuccess;
|
||||
request.onerror = addError;
|
||||
}
|
||||
|
||||
for (var i=0; i < music_files.length; i++) {
|
||||
request = music.addNamed(createRandomBlob('audio/mp3'), music_files[i]);
|
||||
request.onsuccess = addSuccess;
|
||||
request.onerror = addError;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html> <!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=717103
|
||||
-->
|
||||
<head>
|
||||
<title>Test for the device storage API </title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="devicestorage_common.js"></script>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=717103">Mozilla Bug 717103</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
devicestorage_setup(function () {
|
||||
|
||||
function testingStorage() {
|
||||
return navigator.getDeviceStorage("pictures");
|
||||
}
|
||||
|
||||
var tests = [
|
||||
function () { return testingStorage().addNamed(createRandomBlob('image/png'), gFileName); },
|
||||
function () { return testingStorage().delete(gFileName); },
|
||||
function () { return testingStorage().get(gFileName); },
|
||||
function () { var r = testingStorage().enumerate("../"); return r; }
|
||||
];
|
||||
|
||||
var gFileName = "../owned.png";
|
||||
|
||||
function fail(e) {
|
||||
ok(false, "addSuccess was called");
|
||||
dump(request);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function next(e) {
|
||||
|
||||
if (e != undefined) {
|
||||
ok(true, "addError was called");
|
||||
ok(e.target.error.name == "SecurityError", "Error must be SecurityError");
|
||||
}
|
||||
|
||||
var f = tests.pop();
|
||||
|
||||
if (f == undefined) {
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
request = f();
|
||||
request.onsuccess = fail;
|
||||
request.onerror = next;
|
||||
}
|
||||
|
||||
next();
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,104 +0,0 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html> <!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=717103
|
||||
-->
|
||||
<head>
|
||||
<title>Test for the device storage API </title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="devicestorage_common.js"></script>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=717103">Mozilla Bug 717103</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
devicestorage_setup(function () {
|
||||
|
||||
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")
|
||||
dump("We still have length = " + files.length + "\n");
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
var filename = e.target.result.name;
|
||||
if (filename[0] == "/") {
|
||||
// We got /storageName/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);
|
||||
|
||||
ok(index > -1, "filename should be in the enumeration : " + e.target.result.name);
|
||||
|
||||
// clean up
|
||||
var cleanup = storage.delete(e.target.result.name);
|
||||
cleanup.onsuccess = function(e) {} // todo - can i remove this?
|
||||
|
||||
e.target.continue();
|
||||
}
|
||||
|
||||
function handleError(e) {
|
||||
ok(false, "handleError was called : " + e.target.error.name);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function addSuccess(e) {
|
||||
addedSoFar = addedSoFar + 1;
|
||||
if (addedSoFar == files.length) {
|
||||
|
||||
var cursor = storage.enumerate(prefix);
|
||||
cursor.onsuccess = enumerateSuccess;
|
||||
cursor.onerror = handleError;
|
||||
}
|
||||
}
|
||||
|
||||
function addError(e) {
|
||||
ok(false, "addError was called : " + e.target.error.name);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
var storage = navigator.getDeviceStorage("pictures");
|
||||
ok(navigator.getDeviceStorage, "Should have getDeviceStorage");
|
||||
var prefix = "devicestorage/" + randomFilename(12) + ".png"
|
||||
|
||||
var files = [ "a.PNG", "b.pnG", "c.png", "d/a.png", "d/b.png", "d/c.png", "d/d.png", "The/quick/brown/fox/jumps/over/the/lazy/dog.png"]
|
||||
var addedSoFar = 0;
|
||||
|
||||
|
||||
for (var i=0; i<files.length; i++) {
|
||||
|
||||
request = storage.addNamed(createRandomBlob('image/png'), prefix + '/' + files[i]);
|
||||
|
||||
ok(request, "Should have a non-null request");
|
||||
request.onsuccess = addSuccess;
|
||||
request.onerror = addError;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html> <!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=717103
|
||||
-->
|
||||
<head>
|
||||
<title>Test for the device storage API </title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="devicestorage_common.js"></script>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=717103">Mozilla Bug 717103</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
devicestorage_setup(function () {
|
||||
|
||||
function enumerateSuccess(e) {
|
||||
}
|
||||
|
||||
function enumerateFailure(e) {
|
||||
}
|
||||
|
||||
var cursor = navigator.getDeviceStorage("pictures").enumerate();
|
||||
cursor.onsuccess = enumerateSuccess;
|
||||
cursor.onerror = enumerateFailure;
|
||||
|
||||
try {
|
||||
cursor.continue();
|
||||
}
|
||||
catch (e) {
|
||||
ok(true, "Calling continue before enumerateSuccess fires should throw");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,109 +0,0 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html> <!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=717103
|
||||
-->
|
||||
<head>
|
||||
<title>Test for the device storage API </title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="devicestorage_common.js"></script>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=717103">Mozilla Bug 717103</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
// Array Remove - By John Resig (MIT Licensed)
|
||||
Array.prototype.remove = function(from, to) {
|
||||
var rest = this.slice((to || from) + 1 || this.length);
|
||||
this.length = from < 0 ? this.length + from : from;
|
||||
return this.push.apply(this, rest);
|
||||
};
|
||||
|
||||
devicestorage_setup();
|
||||
|
||||
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")
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
var filename = e.target.result.name;
|
||||
if (filename[0] == "/") {
|
||||
// We got /storageName/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(e.target.result.name);
|
||||
cleanup.onsuccess = function(e) {} // todo - can i remove this?
|
||||
|
||||
e.target.continue();
|
||||
}
|
||||
|
||||
function handleError(e) {
|
||||
ok(false, "handleError was called : " + e.target.error.name);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function addSuccess(e) {
|
||||
addedSoFar = addedSoFar + 1;
|
||||
if (addedSoFar == files.length) {
|
||||
|
||||
var cursor = storage.enumerate();
|
||||
cursor.onsuccess = enumerateSuccess;
|
||||
cursor.onerror = handleError;
|
||||
}
|
||||
}
|
||||
|
||||
function addError(e) {
|
||||
ok(false, "addError was called : " + e.target.error.name);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
var storage = navigator.getDeviceStorage("pictures");
|
||||
ok(navigator.getDeviceStorage, "Should have getDeviceStorage");
|
||||
var prefix = "devicestorage/" + randomFilename(12)
|
||||
|
||||
var files = [ "a.png", "b.png", "c.png" ]
|
||||
var addedSoFar = 0;
|
||||
|
||||
|
||||
for (var i=0; i<files.length; i++) {
|
||||
|
||||
request = storage.addNamed(createRandomBlob('image/png'), prefix + '/' + files[i]);
|
||||
|
||||
ok(request, "Should have a non-null request");
|
||||
request.onsuccess = addSuccess;
|
||||
request.onerror = addError;
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=717103
|
||||
-->
|
||||
<head>
|
||||
<title>Test for basic sanity of the device storage API </title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="devicestorage_common.js"></script>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=717103">Mozilla Bug 717103</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
devicestorage_setup(function () {
|
||||
|
||||
storage = navigator.getDeviceStorage("pictures");
|
||||
|
||||
|
||||
throws = false;
|
||||
try {
|
||||
var cursor = storage.enumerate();
|
||||
} catch(e) {throws = true}
|
||||
ok(!throws, "enumerate no parameter");
|
||||
|
||||
throws = false;
|
||||
try {
|
||||
var cursor = storage.enumerate("string");
|
||||
} catch(e) {throws = true}
|
||||
ok(!throws, "enumerate one string parameter");
|
||||
|
||||
throws = false;
|
||||
try {
|
||||
var cursor = storage.enumerate("string", "string2");
|
||||
} catch(e) {throws = true}
|
||||
ok(throws, "enumerate two string parameter");
|
||||
|
||||
throws = false;
|
||||
try {
|
||||
var cursor = storage.enumerate("string", {"since": new Date(1)});
|
||||
} catch(e) {throws = true}
|
||||
ok(!throws, "enumerate a string and object parameter");
|
||||
|
||||
throws = false;
|
||||
try {
|
||||
var cursor = storage.enumerate({"path": "a"});
|
||||
} catch(e) {throws = true}
|
||||
ok(!throws, "enumerate object parameter with path");
|
||||
|
||||
throws = false;
|
||||
try {
|
||||
var cursor = storage.enumerate({}, "string");
|
||||
} catch(e) {throws = true}
|
||||
ok(throws, "enumerate object then a string");
|
||||
|
||||
throws = false;
|
||||
try {
|
||||
var cursor = storage.enumerate({"path": "a", "since": new Date(0) });
|
||||
} catch(e) {throws = true}
|
||||
ok(!throws, "enumerate object parameter with path");
|
||||
|
||||
SimpleTest.finish()
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html> <!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=717103
|
||||
-->
|
||||
<head>
|
||||
<title>Test for the device storage API </title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="devicestorage_common.js"></script>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=717103">Mozilla Bug 717103</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
devicestorage_setup(function () {
|
||||
|
||||
function freeSpaceSuccess(e) {
|
||||
ok(e.target.result > 0, "free bytes should exist and be greater than zero");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function freeSpaceError(e) {
|
||||
ok(false, "freeSpaceError was called");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
var storage = navigator.getDeviceStorage("pictures");
|
||||
|
||||
function addError(e) {
|
||||
ok(false, "addError was called : " + e.target.error.name);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function addSuccess(e) {
|
||||
request = storage.freeSpace();
|
||||
ok(request, "Should have a non-null request");
|
||||
|
||||
request.onsuccess = freeSpaceSuccess;
|
||||
request.onerror = freeSpaceError;
|
||||
}
|
||||
|
||||
var prefix = "devicestorage/" + randomFilename(12);
|
||||
request = storage.addNamed(createRandomBlob('image/png'), prefix + "/a/b.png");
|
||||
request.onsuccess = addSuccess;
|
||||
request.onerror = addError;
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,598 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=910412
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Permission test of FileSystem API for Device Storage</title>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=910412">Mozilla Bug 910412</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
function randomFilename(l) {
|
||||
let set = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZ";
|
||||
let result = "";
|
||||
for (let i=0; i<l; i++) {
|
||||
let r = Math.floor(set.length * Math.random());
|
||||
result += set.substring(r, r + 1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function getRandomBuffer() {
|
||||
var size = 1024;
|
||||
var buffer = new ArrayBuffer(size);
|
||||
var view = new Uint8Array(buffer);
|
||||
for (var i = 0; i < size; i++) {
|
||||
view[i] = parseInt(Math.random() * 255);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
function createRandomBlob(mime) {
|
||||
let size = 1024;
|
||||
let buffer = new ArrayBuffer(size);
|
||||
let view = new Uint8Array(buffer);
|
||||
for (let i = 0; i < size; i++) {
|
||||
view[i] = parseInt(Math.random() * 255);
|
||||
}
|
||||
return blob = new Blob([buffer], {type: mime});
|
||||
}
|
||||
|
||||
let MockPermissionPrompt = SpecialPowers.MockPermissionPrompt;
|
||||
MockPermissionPrompt.init();
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function TestCreateDirectory(iframe, data) {
|
||||
function cbError(e) {
|
||||
is(e.name, "SecurityError", "[TestCreateDirectory] Should fire a SecurityError for type " + data.type);
|
||||
is(data.shouldPass, false, "[TestCreateDirectory] Error callback was called for type " + data.type + '. Error: ' + e.name);
|
||||
testComplete(iframe, data);
|
||||
}
|
||||
|
||||
let storage = iframe.contentDocument.defaultView.navigator.getDeviceStorage(data.type);
|
||||
isnot(storage, null, "[TestCreateDirectory] Should be able to get storage object for " + data.type);
|
||||
|
||||
if (!storage) {
|
||||
testComplete(iframe, data);
|
||||
return;
|
||||
}
|
||||
|
||||
storage.getRoot().then(function(root) {
|
||||
is(data.shouldPass, true, "[TestCreateDirectory] Success callback was called for type " + data.type);
|
||||
let filename = randomFilename(100);
|
||||
root.createDirectory(filename).then(function(d) {
|
||||
let passed = d && (d.name === filename);
|
||||
is(data.shouldPass, passed, "[TestCreateDirectory] Success callback was called for type " + data.type);
|
||||
testComplete(iframe, data);
|
||||
}, cbError);
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function TestGet(iframe, data) {
|
||||
function cbError(e) {
|
||||
is(e.name, "SecurityError", "[TestGet] Should fire a SecurityError for type " + data.type);
|
||||
is(data.shouldPass, false, "[TestGet] Error callback was called for type " + data.type + '. Error: ' + e.name);
|
||||
testComplete(iframe, data);
|
||||
}
|
||||
|
||||
createTestFile(data.fileExtension);
|
||||
|
||||
let storage = iframe.contentDocument.defaultView.navigator.getDeviceStorage(data.type);
|
||||
isnot(storage, null, "[TestGet] Should be able to get storage object for " + data.type);
|
||||
|
||||
if (!storage) {
|
||||
testComplete(iframe, data);
|
||||
return;
|
||||
}
|
||||
|
||||
storage.getRoot().then(function(root) {
|
||||
ok(true, "[TestGet] Success callback of getRoot was called for type " + data.type);
|
||||
root.get("testfile" + data.fileExtension).then(function() {
|
||||
is(data.shouldPass, true, "[TestGet] Success callback was called for type " + data.type);
|
||||
testComplete(iframe, data);
|
||||
}, cbError);
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function TestCreateFile(iframe, data) {
|
||||
function cbError(e) {
|
||||
is(e.name, "SecurityError", "[TestCreateFile] Should fire a SecurityError for type " + data.type);
|
||||
is(data.shouldPass, false, "[TestCreateFile] Error callback was called for type " + data.type + '. Error: ' + e.name);
|
||||
testComplete(iframe, data);
|
||||
}
|
||||
|
||||
let storage = iframe.contentDocument.defaultView.navigator.getDeviceStorage(data.type);
|
||||
isnot(storage, null, "[TestCreateFile] Should be able to get storage object for " + data.type);
|
||||
|
||||
if (!storage) {
|
||||
testComplete(iframe, data);
|
||||
return;
|
||||
}
|
||||
|
||||
storage.getRoot().then(function(root) {
|
||||
ok(true, "[TestCreateFile] Success callback of getRoot was called for type " + data.type);
|
||||
let filename = randomFilename(100) + data.fileExtension;
|
||||
root.createFile(filename, {
|
||||
data: createRandomBlob(data.mimeType),
|
||||
ifExists: "replace"
|
||||
}).then(function() {
|
||||
is(data.shouldPass, true, "[TestCreateFile] Success callback was called for type " + data.type);
|
||||
testComplete(iframe, data);
|
||||
}, cbError);
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function TestRemove(iframe, data) {
|
||||
function cbError(e) {
|
||||
is(e.name, "SecurityError", "[TestRemove] Should fire a SecurityError for type " + data.type);
|
||||
is(data.shouldPass, false, "[TestRemove] Error callback was called for type " + data.type + '. Error: ' + e.name);
|
||||
testComplete(iframe, data);
|
||||
}
|
||||
|
||||
createTestFile(data.fileExtension);
|
||||
|
||||
let storage = iframe.contentDocument.defaultView.navigator.getDeviceStorage(data.type);
|
||||
isnot(storage, null, "[TestRemove] Should be able to get storage object for " + data.type);
|
||||
|
||||
if (!storage) {
|
||||
testComplete(iframe, data);
|
||||
return;
|
||||
}
|
||||
|
||||
storage.getRoot().then(function(root) {
|
||||
ok(true, "[TestRemove] Success callback of getRoot was called for type " + data.type);
|
||||
root.remove("testfile" + data.fileExtension).then(function() {
|
||||
is(data.shouldPass, true, "[TestRemove] Success callback was called for type " + data.type);
|
||||
testComplete(iframe, data);
|
||||
}, cbError);
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
let gTestUri = "https://example.com/tests/dom/devicestorage/test/test_fs_app_permissions.html"
|
||||
|
||||
let gData = [
|
||||
|
||||
// Directory#get
|
||||
|
||||
// Web applications with no permissions
|
||||
{
|
||||
type: 'pictures',
|
||||
shouldPass: false,
|
||||
fileExtension: '.png',
|
||||
test: TestGet
|
||||
},
|
||||
{
|
||||
type: 'videos',
|
||||
shouldPass: false,
|
||||
fileExtension: '.ogv',
|
||||
test: TestGet
|
||||
},
|
||||
{
|
||||
type: 'videos',
|
||||
shouldPass: false,
|
||||
fileExtension: '.ogg',
|
||||
test: TestGet
|
||||
},
|
||||
{
|
||||
type: 'music',
|
||||
shouldPass: false,
|
||||
fileExtension: '.ogg',
|
||||
test: TestGet
|
||||
},
|
||||
{
|
||||
type: 'music',
|
||||
shouldPass: false,
|
||||
fileExtension: '.txt',
|
||||
test: TestGet
|
||||
},
|
||||
{
|
||||
type: 'sdcard',
|
||||
shouldPass: false,
|
||||
fileExtension: '.txt',
|
||||
test: TestGet
|
||||
},
|
||||
|
||||
// Web applications with permission granted
|
||||
{
|
||||
type: 'pictures',
|
||||
shouldPass: true,
|
||||
fileExtension: '.png',
|
||||
|
||||
permissions: ["device-storage:pictures"],
|
||||
|
||||
test: TestGet
|
||||
},
|
||||
{
|
||||
type: 'videos',
|
||||
shouldPass: true,
|
||||
fileExtension: '.ogv',
|
||||
|
||||
permissions: ["device-storage:videos"],
|
||||
|
||||
test: TestGet
|
||||
},
|
||||
{
|
||||
type: 'videos',
|
||||
shouldPass: true,
|
||||
fileExtension: '.ogg',
|
||||
|
||||
permissions: ["device-storage:videos"],
|
||||
|
||||
test: TestGet
|
||||
},
|
||||
{
|
||||
type: 'music',
|
||||
shouldPass: true,
|
||||
fileExtension: '.ogg',
|
||||
|
||||
permissions: ["device-storage:music"],
|
||||
|
||||
test: TestGet
|
||||
},
|
||||
{
|
||||
type: 'music',
|
||||
shouldPass: false,
|
||||
fileExtension: '.txt',
|
||||
|
||||
permissions: ["device-storage:music"],
|
||||
|
||||
test: TestGet
|
||||
},
|
||||
{
|
||||
type: 'sdcard',
|
||||
shouldPass: true,
|
||||
fileExtension: '.txt',
|
||||
|
||||
permissions: ["device-storage:sdcard"],
|
||||
|
||||
test: TestGet
|
||||
},
|
||||
|
||||
// Directory#createDirectory
|
||||
|
||||
// Web applications with no permissions
|
||||
{
|
||||
type: 'pictures',
|
||||
shouldPass: false,
|
||||
test: TestCreateDirectory
|
||||
},
|
||||
{
|
||||
type: 'videos',
|
||||
shouldPass: false,
|
||||
test: TestCreateDirectory
|
||||
},
|
||||
{
|
||||
type: 'music',
|
||||
shouldPass: false,
|
||||
test: TestCreateDirectory
|
||||
},
|
||||
{
|
||||
type: 'sdcard',
|
||||
shouldPass: false,
|
||||
test: TestCreateDirectory
|
||||
},
|
||||
|
||||
// Web applications with permission granted
|
||||
{
|
||||
type: 'pictures',
|
||||
shouldPass: true,
|
||||
|
||||
permissions: ["device-storage:pictures"],
|
||||
|
||||
test: TestCreateDirectory
|
||||
},
|
||||
{
|
||||
type: 'videos',
|
||||
shouldPass: true,
|
||||
|
||||
permissions: ["device-storage:videos"],
|
||||
|
||||
test: TestCreateDirectory
|
||||
},
|
||||
{
|
||||
type: 'music',
|
||||
shouldPass: true,
|
||||
|
||||
permissions: ["device-storage:music"],
|
||||
|
||||
test: TestCreateDirectory
|
||||
},
|
||||
{
|
||||
type: 'sdcard',
|
||||
shouldPass: true,
|
||||
|
||||
permissions: ["device-storage:sdcard"],
|
||||
|
||||
test: TestCreateDirectory
|
||||
},
|
||||
|
||||
// Directory#createFile
|
||||
|
||||
// Web applications with no permissions
|
||||
{
|
||||
type: 'pictures',
|
||||
mimeType: 'image/png',
|
||||
shouldPass: false,
|
||||
fileExtension: '.png',
|
||||
test: TestCreateFile
|
||||
},
|
||||
{
|
||||
type: 'videos',
|
||||
mimeType: 'video/ogv',
|
||||
shouldPass: false,
|
||||
fileExtension: '.ogv',
|
||||
test: TestCreateFile
|
||||
},
|
||||
{
|
||||
type: 'videos',
|
||||
mimeType: 'video/ogg',
|
||||
shouldPass: false,
|
||||
fileExtension: '.ogg',
|
||||
test: TestCreateFile
|
||||
},
|
||||
{
|
||||
type: 'music',
|
||||
mimeType: 'audio/ogg',
|
||||
shouldPass: false,
|
||||
fileExtension: '.ogg',
|
||||
test: TestCreateFile
|
||||
},
|
||||
{
|
||||
type: 'music',
|
||||
mimeType: 'audio/ogg',
|
||||
shouldPass: false,
|
||||
fileExtension: '.txt',
|
||||
test: TestCreateFile
|
||||
},
|
||||
{
|
||||
type: 'sdcard',
|
||||
mimeType: 'text/plain',
|
||||
shouldPass: false,
|
||||
fileExtension: '.txt',
|
||||
test: TestCreateFile
|
||||
},
|
||||
|
||||
// Web applications with permission granted
|
||||
{
|
||||
type: 'pictures',
|
||||
mimeType: 'image/png',
|
||||
shouldPass: true,
|
||||
fileExtension: '.png',
|
||||
|
||||
permissions: ["device-storage:pictures"],
|
||||
|
||||
test: TestCreateFile
|
||||
},
|
||||
{
|
||||
type: 'videos',
|
||||
mimeType: 'video/ogv',
|
||||
shouldPass: true,
|
||||
fileExtension: '.ogv',
|
||||
|
||||
permissions: ["device-storage:videos"],
|
||||
|
||||
test: TestCreateFile
|
||||
},
|
||||
{
|
||||
type: 'videos',
|
||||
mimeType: 'video/ogg',
|
||||
shouldPass: true,
|
||||
fileExtension: '.ogg',
|
||||
|
||||
permissions: ["device-storage:videos"],
|
||||
|
||||
test: TestCreateFile
|
||||
},
|
||||
{
|
||||
type: 'music',
|
||||
mimeType: 'audio/ogg',
|
||||
shouldPass: true,
|
||||
fileExtension: '.ogg',
|
||||
|
||||
permissions: ["device-storage:music"],
|
||||
|
||||
test: TestCreateFile
|
||||
},
|
||||
{
|
||||
type: 'music',
|
||||
mimeType: 'audio/ogg',
|
||||
shouldPass: false,
|
||||
fileExtension: '.txt',
|
||||
|
||||
permissions: ["device-storage:music"],
|
||||
|
||||
test: TestCreateFile
|
||||
},
|
||||
{
|
||||
type: 'sdcard',
|
||||
mimeType: 'text/plain',
|
||||
shouldPass: true,
|
||||
fileExtension: '.txt',
|
||||
|
||||
permissions: ["device-storage:sdcard"],
|
||||
|
||||
test: TestCreateFile
|
||||
},
|
||||
|
||||
// Directory#remove
|
||||
|
||||
// Web applications with no permissions
|
||||
{
|
||||
type: 'pictures',
|
||||
shouldPass: false,
|
||||
fileExtension: '.png',
|
||||
test: TestRemove
|
||||
},
|
||||
{
|
||||
type: 'videos',
|
||||
shouldPass: false,
|
||||
fileExtension: '.ogv',
|
||||
test: TestRemove
|
||||
},
|
||||
{
|
||||
type: 'videos',
|
||||
shouldPass: false,
|
||||
fileExtension: '.ogg',
|
||||
test: TestRemove
|
||||
},
|
||||
{
|
||||
type: 'music',
|
||||
shouldPass: false,
|
||||
fileExtension: '.ogg',
|
||||
test: TestRemove
|
||||
},
|
||||
{
|
||||
type: 'music',
|
||||
shouldPass: false,
|
||||
fileExtension: '.txt',
|
||||
test: TestRemove
|
||||
},
|
||||
{
|
||||
type: 'sdcard',
|
||||
shouldPass: false,
|
||||
fileExtension: '.txt',
|
||||
test: TestRemove
|
||||
},
|
||||
|
||||
// Web applications with permission granted
|
||||
{
|
||||
type: 'pictures',
|
||||
shouldPass: true,
|
||||
fileExtension: '.png',
|
||||
|
||||
permissions: ["device-storage:pictures"],
|
||||
|
||||
test: TestRemove
|
||||
},
|
||||
{
|
||||
type: 'videos',
|
||||
shouldPass: true,
|
||||
fileExtension: '.ogv',
|
||||
|
||||
permissions: ["device-storage:videos"],
|
||||
|
||||
test: TestRemove
|
||||
},
|
||||
{
|
||||
type: 'videos',
|
||||
shouldPass: true,
|
||||
fileExtension: '.ogg',
|
||||
|
||||
permissions: ["device-storage:videos"],
|
||||
|
||||
test: TestRemove
|
||||
},
|
||||
{
|
||||
type: 'music',
|
||||
shouldPass: true,
|
||||
fileExtension: '.ogg',
|
||||
|
||||
permissions: ["device-storage:music"],
|
||||
|
||||
test: TestRemove
|
||||
},
|
||||
{
|
||||
type: 'music',
|
||||
shouldPass: false,
|
||||
fileExtension: '.txt',
|
||||
|
||||
permissions: ["device-storage:music"],
|
||||
|
||||
test: TestRemove
|
||||
},
|
||||
{
|
||||
type: 'sdcard',
|
||||
shouldPass: true,
|
||||
fileExtension: '.txt',
|
||||
|
||||
permissions: ["device-storage:sdcard"],
|
||||
|
||||
test: TestRemove
|
||||
},
|
||||
|
||||
];
|
||||
|
||||
function setupTest(iframe,data) {
|
||||
if (data.permissions) {
|
||||
for (let j in data.permissions) {
|
||||
SpecialPowers.addPermission(data.permissions[j], true, iframe.contentDocument);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function testComplete(iframe, data) {
|
||||
if (data.permissions) {
|
||||
for (let j in data.permissions) {
|
||||
SpecialPowers.removePermission(data.permissions[j], iframe.contentDocument);
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById('content').removeChild(iframe);
|
||||
|
||||
if (gData.length == 0) {
|
||||
SimpleTest.finish();
|
||||
} else {
|
||||
gTestRunner.next();
|
||||
}
|
||||
}
|
||||
|
||||
function* runTest() {
|
||||
while (gData.length > 0) {
|
||||
let iframe = document.createElement('iframe');
|
||||
let data = gData.shift();
|
||||
|
||||
iframe.setAttribute('mozbrowser', '');
|
||||
|
||||
iframe.src = gTestUri;
|
||||
|
||||
iframe.addEventListener('load', function(e) {
|
||||
setupTest(iframe, data)
|
||||
data.test(iframe, data);
|
||||
});
|
||||
|
||||
document.getElementById('content').appendChild(iframe);
|
||||
yield undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function createTestFile(extension) {
|
||||
try {
|
||||
const Cc = SpecialPowers.Cc;
|
||||
const Ci = SpecialPowers.Ci;
|
||||
let directoryService = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
|
||||
let f = directoryService.get("TmpD", Ci.nsIFile);
|
||||
f.appendRelativePath("device-storage-testing");
|
||||
f.remove(true);
|
||||
f.appendRelativePath("testfile" + extension);
|
||||
f.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
|
||||
} catch(e) {}
|
||||
}
|
||||
|
||||
let gTestRunner = runTest();
|
||||
SpecialPowers.addPermission("browser", true, gTestUri);
|
||||
|
||||
SpecialPowers.pushPrefEnv({'set': [["dom.mozBrowserFramesEnabled", true],
|
||||
["network.disable.ipc.security", true],
|
||||
["device.storage.enabled", true],
|
||||
["device.storage.testing", true],
|
||||
["device.storage.prompt.testing", false]]},
|
||||
function() { gTestRunner.next(); });
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=855952
|
||||
-->
|
||||
<head>
|
||||
<title>Test for basic sanity of the device storage API </title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="devicestorage_common.js"></script>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=855952">Mozilla Bug 855952</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
var file = new Blob(["This is a text file."], {type: "text/plain"});
|
||||
var appendFile = new Blob([" Another text file."], {type: "text/plain"});
|
||||
|
||||
devicestorage_setup(function () {
|
||||
|
||||
function deleteSuccess(e) {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function deleteError(e) {
|
||||
ok(false, "deleteError was called : " + e.target.error.name);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function appendSuccess(e) {
|
||||
ok(true, "appendSuccess was called.");
|
||||
|
||||
request = gStorage.delete(e.target.result)
|
||||
request.onsuccess = deleteSuccess;
|
||||
request.onerror = deleteError;
|
||||
}
|
||||
|
||||
function appendError(e) {
|
||||
ok(false, "appendError was called.");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function addSuccess(e) {
|
||||
ok(true, "addSuccess was called");
|
||||
|
||||
request = gStorage.appendNamed(appendFile, e.target.result);
|
||||
ok(request, "Should have a non-null request");
|
||||
|
||||
request.onsuccess = appendSuccess;
|
||||
request.onerror = appendError;
|
||||
}
|
||||
|
||||
function addError(e) {
|
||||
// test file is already exists. clean it up and try again..
|
||||
request = gStorage.delete(e.target.result)
|
||||
request.onsuccess = addFile;
|
||||
}
|
||||
|
||||
function addFile() {
|
||||
// Add a file first
|
||||
request = gStorage.addNamed(file, "devicestorage/append.asc");
|
||||
ok(request, "Should have a non-null request");
|
||||
request.onsuccess = addSuccess;
|
||||
request.onerror = addError;
|
||||
}
|
||||
|
||||
function runtest() {
|
||||
addFile();
|
||||
}
|
||||
|
||||
var gStorage = navigator.getDeviceStorage("sdcard");
|
||||
ok(navigator.getDeviceStorage, "Should have getDeviceStorage");
|
||||
ok(gStorage, "Should get storage from sdcard");
|
||||
runtest();
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html> <!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=910412
|
||||
-->
|
||||
<head>
|
||||
<title>Test for the FileSystem API for device storage</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="devicestorage_common.js"></script>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=910412">Mozilla Bug 910412</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
devicestorage_setup(function () {
|
||||
|
||||
var gFileName = randomFilename(12);
|
||||
|
||||
// The root directory object.
|
||||
var gRoot;
|
||||
|
||||
function getRootSuccess(r) {
|
||||
ok(r && r.name === storage.storageName, "Failed to get the root directory.");
|
||||
|
||||
gRoot = r;
|
||||
|
||||
// Create a new directory under the root.
|
||||
gRoot.createDirectory(gFileName).then(createDirectorySuccess, cbError);
|
||||
}
|
||||
|
||||
function createDirectorySuccess(d) {
|
||||
ok(d.name === gFileName, "Failed to create directory: name mismatch.");
|
||||
|
||||
// Get the new created directory from the root.
|
||||
gRoot.get(gFileName).then(getSuccess, cbError);
|
||||
}
|
||||
|
||||
function getSuccess(d) {
|
||||
ok(d.name === gFileName, "Should get directory - " + gFileName + ".");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function cbError(e) {
|
||||
ok(false, "Should not arrive here! Error: " + e.name);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
ok(navigator.getDeviceStorage, "Should have getDeviceStorage");
|
||||
|
||||
var storage = navigator.getDeviceStorage("pictures");
|
||||
ok(storage, "Should have gotten a storage");
|
||||
|
||||
var promise = storage.getRoot();
|
||||
ok(promise, "Should have a non-null promise");
|
||||
|
||||
promise.then(getRootSuccess, cbError);
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,107 +0,0 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html> <!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=910412
|
||||
-->
|
||||
<head>
|
||||
<title>Test createDirectory of the FileSystem API for device storage</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="devicestorage_common.js"></script>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=910412">Mozilla Bug 910412</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
devicestorage_setup(function () {
|
||||
|
||||
// The root directory object.
|
||||
var gRoot;
|
||||
var gTestCount = 0;
|
||||
var gPath = '';
|
||||
var gName = '';
|
||||
|
||||
function testCreateDirectory(rootDir, path) {
|
||||
rootDir.createDirectory(path).then(createDirectorySuccess, cbError);
|
||||
}
|
||||
|
||||
function createDirectorySuccess(d) {
|
||||
is(d.name, gName, "Failed to create directory: name mismatch.");
|
||||
|
||||
// Get the new created directory from the root.
|
||||
gRoot.get(gPath).then(getSuccess, cbError);
|
||||
}
|
||||
|
||||
function getSuccess(d) {
|
||||
is(d.name, gName, "Should get directory - " + (gPath || "[root]") + ".");
|
||||
switch (gTestCount) {
|
||||
case 0:
|
||||
gRoot = d;
|
||||
// Create a new directory under the root.
|
||||
gName = gPath = randomFilename(12);
|
||||
testCreateDirectory(gRoot, gName);
|
||||
break;
|
||||
case 1:
|
||||
// Create a sub-directory under current directory.
|
||||
gName = randomFilename(12);
|
||||
gPath = gPath + '/' + gName;
|
||||
testCreateDirectory(d, gName);
|
||||
break;
|
||||
case 2:
|
||||
// Create directory with an existing path.
|
||||
gRoot.createDirectory(gPath).then(function(what) {
|
||||
ok(false, "Should not overwrite an existing directory.");
|
||||
SimpleTest.finish();
|
||||
}, function(e) {
|
||||
ok(true, "Creating directory should fail if it already exists.");
|
||||
|
||||
// Create a directory whose intermediate directory doesn't exit.
|
||||
gName = randomFilename(12);
|
||||
gPath = 'sub1/sub2/' + gName;
|
||||
testCreateDirectory(gRoot, gPath);
|
||||
});
|
||||
break;
|
||||
default:
|
||||
// Create the parent directory.
|
||||
d.createDirectory('..').then(function(what) {
|
||||
ok(false, "Should not overwrite an existing directory.");
|
||||
SimpleTest.finish();
|
||||
}, function(e) {
|
||||
ok(true, "Accessing parent directory with '..' is not allowed.");
|
||||
SimpleTest.finish();
|
||||
});
|
||||
break;
|
||||
}
|
||||
gTestCount++;
|
||||
}
|
||||
|
||||
function cbError(e) {
|
||||
ok(false, e.name + " error should not arrive here!");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
ok(navigator.getDeviceStorage, "Should have getDeviceStorage.");
|
||||
|
||||
var storage = navigator.getDeviceStorage("pictures");
|
||||
ok(storage, "Should have gotten a storage.");
|
||||
|
||||
var promise = storage.getRoot();
|
||||
ok(promise, "Should have a non-null promise for getRoot.");
|
||||
|
||||
gName = storage.storageName;
|
||||
promise.then(getSuccess, cbError);
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,133 +0,0 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html> <!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=910412
|
||||
-->
|
||||
<head>
|
||||
<title>Test createDirectory of the FileSystem API for device storage</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="devicestorage_common.js"></script>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=910412">Mozilla Bug 910412</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="application/javascript">
|
||||
|
||||
devicestorage_setup(function () {
|
||||
|
||||
let gTestCount = 0;
|
||||
let gFileReader = new FileReader();
|
||||
let gRoot;
|
||||
|
||||
function str2array(str) {
|
||||
let strlen = str.length;
|
||||
let buf = new ArrayBuffer(strlen);
|
||||
let bufView = new Uint8Array(buf);
|
||||
for (let i=0; i < strlen; i++) {
|
||||
bufView[i] = str.charCodeAt(i);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
function array2str(data) {
|
||||
return String.fromCharCode.apply(String, new Uint8Array(data));
|
||||
}
|
||||
|
||||
let gTestCases = [
|
||||
// Create with string data.
|
||||
{
|
||||
text: "My name is Yuan.",
|
||||
get data() { return this.text; },
|
||||
shouldPass: true,
|
||||
mode: "replace"
|
||||
},
|
||||
|
||||
// Create with array buffer data.
|
||||
{
|
||||
text: "I'm from Kunming.",
|
||||
get data() { return str2array(this.text); },
|
||||
shouldPass: true,
|
||||
mode: "replace"
|
||||
},
|
||||
|
||||
// Create with array buffer view data.
|
||||
{
|
||||
text: "Kunming is in Yunnan province of China.",
|
||||
get data() { return new Uint8Array(str2array(this.text)); },
|
||||
shouldPass: true,
|
||||
mode: "replace"
|
||||
},
|
||||
|
||||
// Create with blob data.
|
||||
{
|
||||
text: "Kunming is in Yunnan province of China.",
|
||||
get data() { return new Blob([this.text], {type: 'image/png'}); },
|
||||
shouldPass: true,
|
||||
mode: "replace"
|
||||
},
|
||||
|
||||
// Don't overwrite existing file.
|
||||
{
|
||||
data: null,
|
||||
shouldPass: false,
|
||||
mode: "fail"
|
||||
}
|
||||
];
|
||||
|
||||
function next() {
|
||||
if (gTestCount >= gTestCases.length) {
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
let c = gTestCases[gTestCount++];
|
||||
gRoot.createFile("text.png", {
|
||||
data: c.data,
|
||||
ifExists: c.mode
|
||||
}).then(function(file) {
|
||||
is(c.shouldPass, true, "[" + gTestCount + "] Success callback was called for createFile.");
|
||||
if (!c.shouldPass) {
|
||||
SimpleTest.executeSoon(next);
|
||||
return;
|
||||
}
|
||||
// Check the file content.
|
||||
gFileReader.readAsArrayBuffer(file);
|
||||
gFileReader.onload = function(e) {
|
||||
ab = e.target.result;
|
||||
is(array2str(e.target.result), c.text, "[" + gTestCount + "] Wrong values.");
|
||||
SimpleTest.executeSoon(next);
|
||||
};
|
||||
}, function(e) {
|
||||
is(c.shouldPass, false, "[" + gTestCount + "] Error callback was called for createFile.");
|
||||
SimpleTest.executeSoon(next);
|
||||
});
|
||||
}
|
||||
|
||||
ok(navigator.getDeviceStorage, "Should have getDeviceStorage.");
|
||||
|
||||
let storage = navigator.getDeviceStorage("pictures");
|
||||
ok(storage, "Should have gotten a storage.");
|
||||
|
||||
// Get the root directory
|
||||
storage.getRoot().then(function(dir) {
|
||||
ok(dir, "Should have gotten the root directory.");
|
||||
gRoot = dir;
|
||||
next();
|
||||
}, function(e) {
|
||||
ok(false, e.name + " error should not arrive here!");
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,206 +0,0 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html> <!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=910412
|
||||
-->
|
||||
<head>
|
||||
<title>Test Directory#get of the FileSystem API for device storage</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="devicestorage_common.js"></script>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=910412">Mozilla Bug 910412</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
devicestorage_setup(function () {
|
||||
|
||||
SimpleTest.requestCompleteLog();
|
||||
|
||||
// The root directory object.
|
||||
var gRoot = null;
|
||||
var gSub1 = null;
|
||||
var gSub2 = null;
|
||||
var gTestCount = 0;
|
||||
var gPath = "/";
|
||||
|
||||
function testGetSuccess(dir, path) {
|
||||
dir.get(path).then(getSuccess, cbError);
|
||||
}
|
||||
|
||||
function testGetFailure(dir, path) {
|
||||
dir.get(path).then(cbSuccess, getFailure);
|
||||
}
|
||||
|
||||
function getSuccess(r) {
|
||||
ok(r, "[" + gTestCount +"] Should get the file - " + gPath + ".");
|
||||
switch (gTestCount) {
|
||||
case 0:
|
||||
gRoot = r;
|
||||
// Get sub1/sub2/text.png from root.
|
||||
gPath = "sub1/sub2/test.png";
|
||||
testGetSuccess(gRoot, "sub1/sub2/test.png");
|
||||
break;
|
||||
case 1:
|
||||
// Get sub1 from root.
|
||||
gPath = "sub1";
|
||||
testGetSuccess(gRoot, "sub1");
|
||||
break;
|
||||
case 2:
|
||||
// Get sub1/sub2 from root.
|
||||
gSub1 = r;
|
||||
gPath = "sub1/sub2";
|
||||
testGetSuccess(gRoot, "sub1/sub2");
|
||||
break;
|
||||
case 3:
|
||||
// Get sub1/sub2 from sub2.
|
||||
gSub2 = r;
|
||||
gPath = "sub1/sub2";
|
||||
testGetSuccess(gSub1, "sub2");
|
||||
break;
|
||||
case 4:
|
||||
// Test path with leading and trailing white spaces.
|
||||
gPath = "sub1/sub2";
|
||||
testGetSuccess(gSub1, "\t sub2 ");
|
||||
break;
|
||||
case 5:
|
||||
// Get sub1 from sub1/sub2 with "..".
|
||||
gPath = "sub1/sub2/..";
|
||||
testGetFailure(gSub2, "..");
|
||||
break;
|
||||
default:
|
||||
ok(false, "Should not arrive at getSuccess!");
|
||||
SimpleTest.finish();
|
||||
break;
|
||||
}
|
||||
gTestCount++;
|
||||
}
|
||||
|
||||
function getFailure(e) {
|
||||
ok(true, "[" + gTestCount +"] Should not get the file - " + gPath + ". Error: " + e.name);
|
||||
switch (gTestCount) {
|
||||
case 6:
|
||||
// Test special path "..".
|
||||
gPath = "sub1/sub2/../sub2";
|
||||
testGetFailure(gSub2, "../sub2");
|
||||
break;
|
||||
case 7:
|
||||
gPath = "sub1/sub2/../sub2";
|
||||
testGetFailure(gRoot, "sub1/sub2/../sub2");
|
||||
break;
|
||||
case 8:
|
||||
// Test special path ".".
|
||||
gPath = "sub1/./sub2";
|
||||
testGetFailure(gRoot, "sub1/./sub2");
|
||||
break;
|
||||
case 9:
|
||||
gPath = "./sub1/sub2";
|
||||
testGetFailure(gRoot, "./sub1/sub2");
|
||||
break;
|
||||
case 10:
|
||||
gPath = "././sub1/sub2";
|
||||
testGetFailure(gRoot, "././sub1/sub2");
|
||||
break;
|
||||
case 11:
|
||||
gPath = "sub1/sub2/.";
|
||||
testGetFailure(gRoot, "sub1/sub2/.");
|
||||
break;
|
||||
case 12:
|
||||
gPath = "sub1/.";
|
||||
testGetFailure(gSub1, "./");
|
||||
break;
|
||||
case 13:
|
||||
// Test path starting with "/".
|
||||
gPath = "sub1/";
|
||||
testGetFailure(gSub1, "/");
|
||||
break;
|
||||
case 14:
|
||||
// Test path ending with "/".
|
||||
gPath = "sub1/";
|
||||
testGetFailure(gSub1, "sub2/");
|
||||
break;
|
||||
case 15:
|
||||
// Test empty path.
|
||||
gPath = "sub2";
|
||||
testGetFailure(gSub2, "");
|
||||
break;
|
||||
case 16:
|
||||
// Test special path "//".
|
||||
gPath = "sub1//sub2";
|
||||
testGetFailure(gRoot, "sub1//sub2");
|
||||
break;
|
||||
case 17:
|
||||
SimpleTest.finish();
|
||||
break;
|
||||
default:
|
||||
ok(false, "Should not arrive here!");
|
||||
SimpleTest.finish();
|
||||
break;
|
||||
}
|
||||
gTestCount++;
|
||||
}
|
||||
|
||||
function cbError(e) {
|
||||
ok(false, "Should not arrive at cbError! Error: " + e.name);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function cbSuccess(e) {
|
||||
ok(false, "Should not arrive at cbSuccess!");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
ok(navigator.getDeviceStorage, "Should have getDeviceStorage.");
|
||||
|
||||
var gStorage = navigator.getDeviceStorage("pictures");
|
||||
ok(gStorage, "Should have gotten a storage.");
|
||||
|
||||
function createTestFile(path, callback) {
|
||||
function addNamed() {
|
||||
var req = gStorage.addNamed(createRandomBlob("image/png"), path);
|
||||
|
||||
req.onsuccess = function() {
|
||||
ok(true, path + " was created.");
|
||||
callback();
|
||||
};
|
||||
|
||||
req.onerror = function(e) {
|
||||
ok(false, "Failed to create " + path + ": " + e.target.error.name);
|
||||
SimpleTest.finish();
|
||||
};
|
||||
}
|
||||
|
||||
// Bug 980136. Check if the file exists before we create.
|
||||
var req = gStorage.get(path);
|
||||
|
||||
req.onsuccess = function() {
|
||||
ok(true, path + " exists. Do not need to create.");
|
||||
callback();
|
||||
};
|
||||
|
||||
req.onerror = function(e) {
|
||||
ok(true, path + " does not exists: " + e.target.error.name);
|
||||
addNamed();
|
||||
};
|
||||
}
|
||||
|
||||
createTestFile("sub1/sub2/test.png", function() {
|
||||
var promise = gStorage.getRoot();
|
||||
ok(promise, "Should have a non-null promise for getRoot.");
|
||||
promise.then(getSuccess, cbError);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,98 +0,0 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html> <!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=XXX
|
||||
-->
|
||||
<head>
|
||||
<title>Test Directory#getFilesAndDirectories of the FileSystem API for device storage</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="devicestorage_common.js"></script>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=XXX">Mozilla Bug XXX</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
devicestorage_setup(function () {
|
||||
SimpleTest.requestCompleteLog();
|
||||
|
||||
// The root directory object.
|
||||
var gRoot = null;
|
||||
|
||||
function checkContents1(contents) {
|
||||
var expected = {
|
||||
"sub2": "/sub",
|
||||
"sub3": "/sub",
|
||||
"a.png": "/sub",
|
||||
"b.png": "/sub",
|
||||
};
|
||||
|
||||
is(contents.length, Object.keys(expected).length,
|
||||
"The sub-directory should contain four children");
|
||||
|
||||
var sub2;
|
||||
|
||||
for (var child of contents) {
|
||||
if (child.name in expected) {
|
||||
ok(true, "Found '" + child.name + "' in /sub");
|
||||
if (child.name == "sub2") {
|
||||
sub2 = child;
|
||||
}
|
||||
} else {
|
||||
ok(false, "Did not expect '" + child.name + "' in /sub");
|
||||
}
|
||||
delete expected[child.name];
|
||||
}
|
||||
|
||||
// 'expected' should now be "empty"
|
||||
for (var missing in Object.keys(expected)) {
|
||||
ok(false, "Expected '" + missing.name + "' in /sub");
|
||||
}
|
||||
|
||||
sub2.getFilesAndDirectories().then(checkContents2, handleError);
|
||||
}
|
||||
|
||||
function checkContents2(contents) {
|
||||
is(contents[0].name, "c.png", "'sub2' should contain 'c.png'");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function handleError(e) {
|
||||
ok(false, "Should not arrive at handleError! Error: " + e.name);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
var gStorage = navigator.getDeviceStorage("pictures");
|
||||
|
||||
ok(gStorage, "Should have gotten a storage.");
|
||||
|
||||
function runTests() {
|
||||
gStorage.getRoot().then(function(rootDir) {
|
||||
gRoot = rootDir;
|
||||
return rootDir.get("sub");
|
||||
}).then(function(subDir) {
|
||||
return subDir.getFilesAndDirectories();
|
||||
}).then(checkContents1).catch(handleError);
|
||||
}
|
||||
|
||||
createTestFiles(gStorage, ["sub/a.png", "sub/b.png", "sub/sub2/c.png", "sub/sub3/d.png"]).then(function() {
|
||||
runTests();
|
||||
}, function() {
|
||||
ok(false, "Failed to created test files.");
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,176 +0,0 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html> <!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=934368
|
||||
-->
|
||||
<head>
|
||||
<title>Test Directory#remove and #removeDeep of the FileSystem API for device storage</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="devicestorage_common.js"></script>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=934368">Mozilla Bug 934368</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="application/javascript">
|
||||
|
||||
devicestorage_setup(function () {
|
||||
|
||||
let gStorage = null;
|
||||
let gTestCount = 0;
|
||||
let gFileMap = {};
|
||||
let gRemoveDeep = true;
|
||||
|
||||
let gTestCases = [
|
||||
// Remove a non-existent file should return false.
|
||||
{
|
||||
dir: "/",
|
||||
path: "non-existent.png",
|
||||
ret: false,
|
||||
shouldPass: true
|
||||
},
|
||||
|
||||
// Remove parent directory should fail.
|
||||
{
|
||||
dir: "sub1/sub2",
|
||||
target: "sub1",
|
||||
ret: true,
|
||||
shouldPass: false
|
||||
},
|
||||
|
||||
// Remove root directory should fail.
|
||||
{
|
||||
dir: "/",
|
||||
target: "/",
|
||||
ret: true,
|
||||
shouldPass: false
|
||||
},
|
||||
|
||||
// Remove non-descendant file should fail.
|
||||
{
|
||||
dir: "sub1",
|
||||
target: "sub/b.png",
|
||||
ret: true,
|
||||
shouldPass: false
|
||||
},
|
||||
|
||||
// Remove descendant file should return true.
|
||||
{
|
||||
dir: "sub1",
|
||||
target: "sub1/sub2/a.png",
|
||||
ret: true,
|
||||
shouldPass: true
|
||||
},
|
||||
|
||||
// Remove empty directory should return true.
|
||||
{
|
||||
dir: "sub1",
|
||||
path: "sub2",
|
||||
ret: true,
|
||||
shouldPass: true
|
||||
},
|
||||
|
||||
|
||||
// Remove non-empty directory should return true for "removeDeep" and fail
|
||||
// for "remove".
|
||||
{
|
||||
dir: "/",
|
||||
path: "sub",
|
||||
ret: true,
|
||||
get shouldPass() { return gRemoveDeep; }
|
||||
}
|
||||
];
|
||||
|
||||
function runNextTests() {
|
||||
gTestCount = 0;
|
||||
function runTests() {
|
||||
function cbError(e) {
|
||||
ok(false, "Should not arrive at cbError! Error: " + e.name);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function cbSuccess(r) {
|
||||
ok(r, "Should get the file - " + this);
|
||||
gFileMap[this] = r;
|
||||
}
|
||||
|
||||
// Get directory and file objects.
|
||||
gStorage.getRoot().then(function(root) {
|
||||
ok(root, "Should get root directory.");
|
||||
gFileMap["/"] = root;
|
||||
|
||||
let arr = [];
|
||||
|
||||
["sub1", "sub1/sub2", "sub1/sub2/a.png", "sub/b.png"].forEach(function(path) {
|
||||
arr.push(root.get(path).then(cbSuccess.bind(path), cbError));
|
||||
});
|
||||
|
||||
Promise.all(arr).then(function() {
|
||||
testNextRemove();
|
||||
}, function() {
|
||||
ok(false, "Failed to get test files.");
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}, cbError);
|
||||
};
|
||||
createTestFiles(gStorage, ["sub1/sub2/a.png", "sub/b.png"]).then(function() {
|
||||
runTests();
|
||||
}, function() {
|
||||
ok(false, "Failed to created test files.");
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
|
||||
function testNextRemove() {
|
||||
if (gTestCount < gTestCases.length) {
|
||||
let data = gTestCases[gTestCount++];
|
||||
let dir = gFileMap[data.dir];
|
||||
let path = data.path || gFileMap[data.target];
|
||||
let targetPath = data.path || data.target;
|
||||
let promise = gRemoveDeep ? dir.removeDeep(path) : dir.remove(path);
|
||||
promise.then(function(result) {
|
||||
ok(data.shouldPass, "Success callback was called to remove " +
|
||||
targetPath + " from " + data.dir);
|
||||
is(result, data.ret, "Return value should match to remove " +
|
||||
targetPath + " from " + data.dir);
|
||||
SimpleTest.executeSoon(testNextRemove);
|
||||
}, function(err) {
|
||||
ok(!data.shouldPass, "Error callback was called to remove " +
|
||||
targetPath + " from " + data.dir + '. Error: ' + err.name);
|
||||
SimpleTest.executeSoon(testNextRemove);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (gRemoveDeep) {
|
||||
// Test "remove" after "removeDeep".
|
||||
gRemoveDeep = false;
|
||||
runNextTests();
|
||||
return;
|
||||
}
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
ok(navigator.getDeviceStorage, "Should have getDeviceStorage.");
|
||||
|
||||
gStorage = navigator.getDeviceStorage("pictures");
|
||||
ok(gStorage, "Should have gotten a storage.");
|
||||
|
||||
// Test "removeDeep" first.
|
||||
gRemoveDeep = true;
|
||||
runNextTests();
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,176 +0,0 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html> <!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=717103
|
||||
-->
|
||||
<head>
|
||||
<title>Test for the device storage API </title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="devicestorage_common.js"></script>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=717103">Mozilla Bug 717103</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
SimpleTest.requestFlakyTimeout("untriaged");
|
||||
devicestorage_setup(function () {
|
||||
|
||||
// We put the old files in 2 levels deep. When you add a file to a directory
|
||||
// it will modify the parents last modification time, but not the parents
|
||||
// parents. So we want to make sure that even though x's timestamp is earlier
|
||||
// than the since parameter, we still pick up the later files.
|
||||
var oldFiles = ["x/y/aa.png", "x/y/ab.png", "x/y/ac.png"];
|
||||
var timeFile = "t.png";
|
||||
var newFiles = ["x/y/ad.png", "x/y/ae.png", "x/y/af.png", // new files in old dir
|
||||
"z/bd.png", "z/be.png", "z/bf.png"]; // new files in new dir
|
||||
|
||||
var storage = navigator.getDeviceStorage('pictures');
|
||||
var prefix = "devicestorage/" + randomFilename(12);
|
||||
var i;
|
||||
var timestamp;
|
||||
var lastFileAddedTimestamp;
|
||||
|
||||
function verifyAndDelete(prefix, files, e) {
|
||||
if (e.target.result == null) {
|
||||
ok(files.length == 0, "when the enumeration is done, we shouldn't have any files in this array")
|
||||
dump("We still have length = " + files.length + "\n");
|
||||
dump(files + "\n");
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
var filename = e.target.result.name;
|
||||
if (filename[0] == "/") {
|
||||
// We got /storageName/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);
|
||||
if (index == -1)
|
||||
return;
|
||||
|
||||
files.splice(index, 1);
|
||||
|
||||
// clean up
|
||||
var cleanup = storage.delete(e.target.result.name);
|
||||
cleanup.onsuccess = function(e) {}
|
||||
}
|
||||
|
||||
function addFile(filename, callback) {
|
||||
var addReq = storage.addNamed(createRandomBlob('image/png'), prefix + '/' + filename);
|
||||
addReq.onsuccess = function(e) {
|
||||
// After adding the file, we go ahead and grab the timestamp of the file
|
||||
// that we just added
|
||||
var getReq = storage.get(prefix + '/' + filename);
|
||||
getReq.onsuccess = function(e) {
|
||||
lastFileAddedTimestamp = e.target.result.lastModifiedDate;
|
||||
callback();
|
||||
}
|
||||
getReq.onerror = function(e) {
|
||||
ok(false, "getError was called : " + e.target.error.name);
|
||||
SimpleTest.finish();
|
||||
};
|
||||
}
|
||||
addReq.onerror = function(e) {
|
||||
ok(false, "addError was called : " + e.target.error.name);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
function addFileArray(fileArray, callback) {
|
||||
var i = 0;
|
||||
function addNextFile() {
|
||||
i = i + 1;
|
||||
if (i == fileArray.length) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
addFile(fileArray[i], addNextFile);
|
||||
}
|
||||
addFile(fileArray[0], addNextFile);
|
||||
}
|
||||
|
||||
function delFile(filename, callback) {
|
||||
var req = storage.delete(prefix + '/' + filename);
|
||||
req.onsuccess = function(e) {
|
||||
callback();
|
||||
};
|
||||
req.onerror = function(e) {
|
||||
ok(false, "delError was called : " + e.target.error.name);
|
||||
SimpleTest.finish();
|
||||
};
|
||||
}
|
||||
|
||||
function afterNewFiles() {
|
||||
var cursor = storage.enumerate(prefix, {"since": timestamp});
|
||||
cursor.onsuccess = function(e) {
|
||||
verifyAndDelete(prefix, newFiles, e);
|
||||
if (e.target.result) {
|
||||
e.target.continue();
|
||||
}
|
||||
};
|
||||
cursor.onerror = function (e) {
|
||||
ok(false, "handleError was called : " + e.target.error.name);
|
||||
SimpleTest.finish();
|
||||
};
|
||||
}
|
||||
|
||||
function waitForTimestampChange() {
|
||||
// We've added a new file. See if the timestamp differs from
|
||||
// oldFileAddedTimestamp, and if it's the same wait for a bit
|
||||
// and try again.
|
||||
if (lastFileAddedTimestamp.valueOf() === timestamp.valueOf()) {
|
||||
delFile(timeFile, function() {
|
||||
setTimeout(function() {
|
||||
addFile(timeFile, waitForTimestampChange);
|
||||
}, 1000);
|
||||
});
|
||||
} else {
|
||||
timestamp = lastFileAddedTimestamp;
|
||||
// The timestamp has changed. Go ahead and add the rest of the new files
|
||||
delFile(timeFile, function() {
|
||||
addFileArray(newFiles, afterNewFiles);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function afterOldFiles() {
|
||||
timestamp = lastFileAddedTimestamp;
|
||||
setTimeout(function() {
|
||||
// We've added our old files and waited for a second.
|
||||
// Add a new file until the timestamp changes
|
||||
addFile(timeFile, waitForTimestampChange);
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
function addOldFiles() {
|
||||
addFileArray(oldFiles, afterOldFiles);
|
||||
}
|
||||
|
||||
addOldFiles();
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,163 +0,0 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html> <!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=717103
|
||||
-->
|
||||
<head>
|
||||
<title>Test for the device storage API </title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="devicestorage_common.js"></script>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=717103">Mozilla Bug 717103</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
devicestorage_setup(function () {
|
||||
|
||||
var gFileName = "devicestorage/" + randomFilename(12) + "/hi.png";
|
||||
var gData = "My name is Doug Turner. My IRC nick is DougT. I like Maple cookies."
|
||||
var gDataBlob = new Blob([gData], {type: 'image/png'});
|
||||
var gFileReader = new FileReader();
|
||||
|
||||
function getAfterDeleteSuccess(e) {
|
||||
ok(false, "file was deleted not successfully");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function getAfterDeleteError(e) {
|
||||
ok(true, "file was deleted successfully");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function deleteSuccess(e) {
|
||||
|
||||
ok(e.target.result == gFileName, "File name should match");
|
||||
dump(e.target.result + "\n")
|
||||
|
||||
// File was deleted using the sdcard stoage area. It should be gone
|
||||
// from the pictures as well.
|
||||
var storage = navigator.getDeviceStorage("pictures");
|
||||
request = storage.get(e.target.result);
|
||||
request.onsuccess = getAfterDeleteSuccess;
|
||||
request.onerror = getAfterDeleteError;
|
||||
}
|
||||
|
||||
function deleteError(e) {
|
||||
ok(false, "deleteError was called : " + e.target.error.name);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function getSuccess(e) {
|
||||
// We wrote the file out using pictures type. Since we've over-ridden the
|
||||
// root directory, we should be able to read it back using the sdcard
|
||||
// storage area.
|
||||
var storage = navigator.getDeviceStorage("sdcard");
|
||||
ok(navigator.getDeviceStorage, "Should have getDeviceStorage");
|
||||
|
||||
ok(e.target.result.name == gFileName, "File name should match");
|
||||
ok(e.target.result.size > 0, "File size be greater than zero");
|
||||
ok(e.target.result.type, "File should have a mime type");
|
||||
ok(e.target.result.lastModifiedDate, "File should have a last modified date");
|
||||
|
||||
var name = e.target.result.name;
|
||||
|
||||
gFileReader.readAsArrayBuffer(gDataBlob);
|
||||
gFileReader.onload = function(e) {
|
||||
readerCallback(e);
|
||||
|
||||
request = storage.delete(name)
|
||||
request.onsuccess = deleteSuccess;
|
||||
request.onerror = deleteError;
|
||||
}
|
||||
}
|
||||
|
||||
function readerCallback(e) {
|
||||
|
||||
ab = e.target.result;
|
||||
|
||||
is(ab.byteLength, gData.length, "wrong arraybuffer byteLength");
|
||||
var u8v = new Uint8Array(ab);
|
||||
is(String.fromCharCode.apply(String, u8v), gData, "wrong values");
|
||||
}
|
||||
|
||||
function getError(e) {
|
||||
ok(false, "getError was called : " + e.target.error.name);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function addSuccess(e) {
|
||||
|
||||
var filename = e.target.result;
|
||||
if (filename[0] == "/") {
|
||||
// We got /storageName/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
|
||||
}
|
||||
}
|
||||
ok(filename == gFileName, "File name should match");
|
||||
|
||||
// Update gFileName to be the fully qualified name so that
|
||||
// further checks will pass.
|
||||
gFileName = e.target.result;
|
||||
|
||||
var storage = navigator.getDeviceStorage("pictures");
|
||||
request = storage.get(gFileName);
|
||||
request.onsuccess = getSuccess;
|
||||
request.onerror = getError;
|
||||
|
||||
ok(true, "addSuccess was called");
|
||||
}
|
||||
|
||||
function addError(e) {
|
||||
ok(false, "addError was called : " + e.target.error.name);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function startTest() {
|
||||
ok(navigator.getDeviceStorage, "Should have getDeviceStorage");
|
||||
|
||||
var storage = navigator.getDeviceStorage("pictures");
|
||||
ok(storage, "Should have gotten a storage");
|
||||
|
||||
request = storage.addNamed(gDataBlob, gFileName);
|
||||
ok(request, "Should have a non-null request");
|
||||
|
||||
request.onsuccess = addSuccess;
|
||||
request.onerror = addError;
|
||||
}
|
||||
|
||||
try {
|
||||
const Cc = SpecialPowers.Cc;
|
||||
const Ci = SpecialPowers.Ci;
|
||||
var directoryService = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
|
||||
var f = directoryService.get("TmpD", Ci.nsIFile);
|
||||
f.appendRelativePath("device-storage-sdcard");
|
||||
try {
|
||||
// The remove will fail if the directory doesn't exist, which is fine.
|
||||
f.remove(true);
|
||||
} catch (e) {}
|
||||
SpecialPowers.pushPrefEnv({'set': [["device.storage.overrideRootDir", f.path]]},
|
||||
function() {
|
||||
startTest();
|
||||
});
|
||||
} catch(e) {}
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=717103
|
||||
-->
|
||||
<head>
|
||||
<title>Test for basic sanity of the device storage API </title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="devicestorage_common.js"></script>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=717103">Mozilla Bug 717103</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
var filename = "devicestorage/aaaa.png"
|
||||
|
||||
devicestorage_setup(function () {
|
||||
|
||||
|
||||
function deleteSuccess(e) {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function deleteError(e) {
|
||||
ok(false, "deleteError was called : " + e.target.error.name);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function addOverwritingSuccess(e) {
|
||||
ok(false, "addOverwritingSuccess was called.");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function addOverwritingError(e) {
|
||||
ok(true, "Adding to the same location should fail");
|
||||
ok(e.target.error.name == "NoModificationAllowedError", "Error must be NoModificationAllowedError");
|
||||
|
||||
var storage = navigator.getDeviceStorage("pictures");
|
||||
request = storage.delete(filename)
|
||||
request.onsuccess = deleteSuccess;
|
||||
request.onerror = deleteError;
|
||||
}
|
||||
|
||||
function addSuccess(e) {
|
||||
ok(true, "addSuccess was called");
|
||||
|
||||
var storage = navigator.getDeviceStorage("pictures");
|
||||
ok(navigator.getDeviceStorage, "Should have getDeviceStorage");
|
||||
|
||||
request = storage.addNamed(createRandomBlob('image/png'), filename);
|
||||
ok(request, "Should have a non-null request");
|
||||
|
||||
request.onsuccess = addOverwritingSuccess;
|
||||
request.onerror = addOverwritingError;
|
||||
}
|
||||
|
||||
function addError(e) {
|
||||
// test file is already exists. clean it up and try again..
|
||||
var storage = navigator.getDeviceStorage("pictures");
|
||||
request = storage.delete(filename)
|
||||
request.onsuccess = runtest;
|
||||
}
|
||||
|
||||
function runtest() {
|
||||
var storage = navigator.getDeviceStorage("pictures");
|
||||
ok(navigator.getDeviceStorage, "Should have getDeviceStorage");
|
||||
|
||||
request = storage.addNamed(createRandomBlob('image/png'), filename);
|
||||
ok(request, "Should have a non-null request");
|
||||
|
||||
request.onsuccess = addSuccess;
|
||||
request.onerror = addError;
|
||||
}
|
||||
|
||||
runtest();
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=717103
|
||||
-->
|
||||
<head>
|
||||
<title>Test for basic sanity of the device storage API </title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="devicestorage_common.js"></script>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=717103">Mozilla Bug 717103</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
devicestorage_setup(function () {
|
||||
|
||||
ok(navigator.getDeviceStorage, "Should have getDeviceStorage");
|
||||
|
||||
var storage;
|
||||
|
||||
var throws = false;
|
||||
try {
|
||||
storage = navigator.getDeviceStorage();
|
||||
} catch(e) {throws = true}
|
||||
ok(throws, "getDeviceStorage takes one arg");
|
||||
|
||||
storage = navigator.getDeviceStorage("kilimanjaro");
|
||||
ok(!storage, "kilimanjaro - Should not have this type of storage");
|
||||
|
||||
storage = navigator.getDeviceStorage("pictures");
|
||||
ok(storage, "pictures - Should have getDeviceStorage");
|
||||
|
||||
storage = navigator.getDeviceStorage("music");
|
||||
ok(storage, "music - Should have getDeviceStorage");
|
||||
|
||||
storage = navigator.getDeviceStorage("videos");
|
||||
ok(storage, "videos - Should have getDeviceStorage");
|
||||
|
||||
var cursor = storage.enumerate();
|
||||
ok(cursor, "Should have a non-null cursor");
|
||||
|
||||
SimpleTest.finish();
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html> <!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=717103
|
||||
-->
|
||||
<head>
|
||||
<title>Test for the device storage API </title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="devicestorage_common.js"></script>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=717103">Mozilla Bug 717103</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
devicestorage_setup(function () {
|
||||
|
||||
function usedSpaceSuccess(e) {
|
||||
ok(e.target.result > 0, "total bytes should exist and be greater than zero");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function usedSpaceError(e) {
|
||||
ok(false, "usedSpaceError was called");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
var storage = navigator.getDeviceStorage("pictures");
|
||||
|
||||
function addError(e) {
|
||||
ok(false, "addError was called : " + e.target.error.name);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function addSuccess(e) {
|
||||
request = storage.usedSpace();
|
||||
ok(request, "Should have a non-null request");
|
||||
|
||||
request.onsuccess = usedSpaceSuccess;
|
||||
request.onerror = usedSpaceError;
|
||||
}
|
||||
|
||||
var prefix = "devicestorage/" + randomFilename(12);
|
||||
request = storage.addNamed(createRandomBlob('image/png'), prefix + "/a/b.png");
|
||||
request.onsuccess = addSuccess;
|
||||
request.onerror = addError;
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html> <!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=717103
|
||||
-->
|
||||
<head>
|
||||
<title>Test for the device storage API </title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="devicestorage_common.js"></script>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=717103">Mozilla Bug 717103</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
devicestorage_setup(function () {
|
||||
|
||||
var gFileName = randomFilename(20) + ".png"
|
||||
|
||||
function addSuccess(e) {
|
||||
}
|
||||
|
||||
function addError(e) {
|
||||
ok(false, "addError was called : " + e.target.error.name);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function onChange(e) {
|
||||
|
||||
dump("we saw: " + e.path + " " + e.reason + "\n");
|
||||
|
||||
var filename = e.path;
|
||||
if (filename[0] == "/") {
|
||||
// We got /storageName/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 == gFileName) {
|
||||
ok(true, "we saw the file get created");
|
||||
storage.removeEventListener("change", onChange);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
else {
|
||||
// we may see other file changes during the test, and
|
||||
// that is completely ok
|
||||
}
|
||||
}
|
||||
|
||||
var storage = navigator.getDeviceStorage("pictures");
|
||||
ok(storage, "Should have storage");
|
||||
storage.addEventListener("change", onChange);
|
||||
|
||||
request = storage.addNamed(createRandomBlob('image/png'), gFileName);
|
||||
ok(request, "Should have a non-null request");
|
||||
|
||||
request.onsuccess = addSuccess;
|
||||
request.onerror = addError;
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,86 +0,0 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html> <!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=717103
|
||||
-->
|
||||
<head>
|
||||
<title>Test for the device storage API </title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="devicestorage_common.js"></script>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=717103">Mozilla Bug 717103</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
devicestorage_setup(function () {
|
||||
|
||||
var gFileName = randomFilename(20) + ".png"
|
||||
|
||||
function addSuccess(e) {
|
||||
}
|
||||
|
||||
function addError(e) {
|
||||
ok(false, "addError was called : " + e.target.error.name);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function onChange(e) {
|
||||
|
||||
dump("we saw: " + e.path + " " + e.reason + "\n");
|
||||
|
||||
var filename = e.path;
|
||||
if (filename[0] == "/") {
|
||||
// We got /storageName/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 == gFileName) {
|
||||
ok(true, "we saw the file get created");
|
||||
storage.removeEventListener("change", onChange);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
else {
|
||||
// we may see other file changes during the test, and
|
||||
// that is completely ok
|
||||
}
|
||||
}
|
||||
|
||||
function onChangeFail(e) {
|
||||
dump("onChangeFail: " + e.path + " " + e.reason + "\n");
|
||||
ok(false, "We should never see any changes");
|
||||
}
|
||||
|
||||
var storage = navigator.getDeviceStorage("pictures");
|
||||
ok(storage, "Should have storage");
|
||||
storage.addEventListener("change", onChange);
|
||||
|
||||
var storageOther = navigator.getDeviceStorage("music");
|
||||
ok(storageOther, "Should have storage");
|
||||
storageOther.addEventListener("change", onChangeFail);
|
||||
|
||||
request = storage.addNamed(createRandomBlob('image/png'), gFileName);
|
||||
ok(request, "Should have a non-null request");
|
||||
|
||||
request.onsuccess = addSuccess;
|
||||
request.onerror = addError;
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
#include "mozilla/dom/DeviceStorageFileSystem.h"
|
||||
|
||||
#include "DeviceStorage.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/dom/Directory.h"
|
||||
#include "mozilla/dom/File.h"
|
||||
|
|
@ -15,7 +14,6 @@
|
|||
#include "mozilla/Unused.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsDeviceStorage.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsGlobalWindow.h"
|
||||
|
|
@ -42,34 +40,6 @@ DeviceStorageFileSystem::DeviceStorageFileSystem(const nsAString& aStorageType,
|
|||
} else {
|
||||
AssertIsOnBackgroundThread();
|
||||
}
|
||||
|
||||
// Get the permission name required to access the file system.
|
||||
DebugOnly<nsresult> rv =
|
||||
DeviceStorageTypeChecker::GetPermissionForType(mStorageType, mPermission);
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "GetPermissionForType failed");
|
||||
|
||||
// Get the local path of the file system root.
|
||||
nsCOMPtr<nsIFile> rootFile;
|
||||
DeviceStorageFile::GetRootDirectoryForType(aStorageType,
|
||||
aStorageName,
|
||||
getter_AddRefs(rootFile));
|
||||
|
||||
Unused <<
|
||||
NS_WARN_IF(!rootFile ||
|
||||
NS_FAILED(rootFile->GetPath(mLocalOrDeviceStorageRootPath)));
|
||||
|
||||
if (!XRE_IsParentProcess()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// DeviceStorageTypeChecker is a singleton object and must be initialized on
|
||||
// the main thread. We initialize it here so that we can use it on the worker
|
||||
// thread.
|
||||
if (NS_IsMainThread()) {
|
||||
DebugOnly<DeviceStorageTypeChecker*> typeChecker =
|
||||
DeviceStorageTypeChecker::CreateOrGet();
|
||||
MOZ_ASSERT(typeChecker);
|
||||
}
|
||||
}
|
||||
|
||||
DeviceStorageFileSystem::~DeviceStorageFileSystem()
|
||||
|
|
|
|||
|
|
@ -175,7 +175,6 @@
|
|||
#endif
|
||||
|
||||
#include "mozilla/dom/File.h"
|
||||
#include "mozilla/dom/devicestorage/DeviceStorageRequestChild.h"
|
||||
#include "mozilla/dom/PPresentationChild.h"
|
||||
#include "mozilla/dom/PresentationIPCService.h"
|
||||
#include "mozilla/ipc/InputStreamUtils.h"
|
||||
|
|
@ -188,7 +187,6 @@
|
|||
#include "URIUtils.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsDeviceStorage.h"
|
||||
#include "DomainPolicy.h"
|
||||
#include "mozilla/dom/ipc/StructuredCloneData.h"
|
||||
#include "mozilla/dom/time/DateCacheCleaner.h"
|
||||
|
|
@ -211,7 +209,6 @@
|
|||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::docshell;
|
||||
using namespace mozilla::dom::devicestorage;
|
||||
using namespace mozilla::dom::ipc;
|
||||
using namespace mozilla::dom::workers;
|
||||
using namespace mozilla::media;
|
||||
|
|
@ -1679,19 +1676,6 @@ ContentChild::RecvPTestShellConstructor(PTestShellChild* actor)
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
PDeviceStorageRequestChild*
|
||||
ContentChild::AllocPDeviceStorageRequestChild(const DeviceStorageParams& aParams)
|
||||
{
|
||||
return new DeviceStorageRequestChild();
|
||||
}
|
||||
|
||||
bool
|
||||
ContentChild::DeallocPDeviceStorageRequestChild(PDeviceStorageRequestChild* aDeviceStorage)
|
||||
{
|
||||
delete aDeviceStorage;
|
||||
return true;
|
||||
}
|
||||
|
||||
PNeckoChild*
|
||||
ContentChild::AllocPNeckoChild()
|
||||
{
|
||||
|
|
@ -2371,28 +2355,6 @@ ContentChild::RecvLastPrivateDocShellDestroyed()
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ContentChild::RecvFilePathUpdate(const nsString& aStorageType,
|
||||
const nsString& aStorageName,
|
||||
const nsString& aPath,
|
||||
const nsCString& aReason)
|
||||
{
|
||||
if (nsDOMDeviceStorage::InstanceCount() == 0) {
|
||||
// No device storage instances in this process. Don't try and
|
||||
// and create a DeviceStorageFile since it will fail.
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
RefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(aStorageType, aStorageName, aPath);
|
||||
|
||||
nsString reason;
|
||||
CopyASCIItoUTF16(aReason, reason);
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
obs->NotifyObservers(dsf, "file-watcher-update", reason.get());
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ContentChild::RecvNotifyProcessPriorityChanged(
|
||||
const hal::ProcessPriority& aPriority)
|
||||
|
|
|
|||
|
|
@ -177,12 +177,6 @@ public:
|
|||
|
||||
virtual bool DeallocPBrowserChild(PBrowserChild*) override;
|
||||
|
||||
virtual PDeviceStorageRequestChild*
|
||||
AllocPDeviceStorageRequestChild(const DeviceStorageParams&) override;
|
||||
|
||||
virtual bool
|
||||
DeallocPDeviceStorageRequestChild(PDeviceStorageRequestChild*) override;
|
||||
|
||||
virtual PBlobChild*
|
||||
AllocPBlobChild(const BlobConstructorParams& aParams) override;
|
||||
|
||||
|
|
@ -401,11 +395,6 @@ public:
|
|||
|
||||
virtual mozilla::ipc::IPCResult RecvLastPrivateDocShellDestroyed() override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvFilePathUpdate(const nsString& aStorageType,
|
||||
const nsString& aStorageName,
|
||||
const nsString& aPath,
|
||||
const nsCString& aReason) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult
|
||||
RecvNotifyProcessPriorityChanged(const hal::ProcessPriority& aPriority) override;
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@
|
|||
|
||||
#include "mozilla/a11y/PDocAccessible.h"
|
||||
#include "AudioChannelService.h"
|
||||
#include "DeviceStorageStatics.h"
|
||||
#include "GMPServiceParent.h"
|
||||
#include "HandlerServiceParent.h"
|
||||
#include "IHistory.h"
|
||||
|
|
@ -53,7 +52,6 @@
|
|||
#include "mozilla/dom/ServiceWorkerRegistrar.h"
|
||||
#include "mozilla/dom/Storage.h"
|
||||
#include "mozilla/dom/StorageIPC.h"
|
||||
#include "mozilla/dom/devicestorage/DeviceStorageRequestParent.h"
|
||||
#include "mozilla/dom/power/PowerManagerService.h"
|
||||
#include "mozilla/dom/Permissions.h"
|
||||
#include "mozilla/dom/PresentationParent.h"
|
||||
|
|
@ -270,7 +268,6 @@ using base::KillProcess;
|
|||
#ifdef MOZ_CRASHREPORTER
|
||||
using namespace CrashReporter;
|
||||
#endif
|
||||
using namespace mozilla::dom::devicestorage;
|
||||
using namespace mozilla::dom::power;
|
||||
using namespace mozilla::media;
|
||||
using namespace mozilla::embedding;
|
||||
|
|
@ -2800,12 +2797,6 @@ ContentParent::Observe(nsISupports* aSubject,
|
|||
else if (!strcmp(aTopic, "last-pb-context-exited")) {
|
||||
Unused << SendLastPrivateDocShellDestroyed();
|
||||
}
|
||||
else if (!strcmp(aTopic, "file-watcher-update")) {
|
||||
nsCString creason;
|
||||
CopyUTF16toUTF8(aData, creason);
|
||||
DeviceStorageFile* file = static_cast<DeviceStorageFile*>(aSubject);
|
||||
Unused << SendFilePathUpdate(file->mStorageType, file->mStorageName, file->mPath, creason);
|
||||
}
|
||||
#ifdef ACCESSIBILITY
|
||||
else if (aData && !strcmp(aTopic, "a11y-init-or-shutdown")) {
|
||||
if (*aData == '1') {
|
||||
|
|
@ -2889,22 +2880,6 @@ ContentParent::DeallocPBrowserParent(PBrowserParent* frame)
|
|||
return nsIContentParent::DeallocPBrowserParent(frame);
|
||||
}
|
||||
|
||||
PDeviceStorageRequestParent*
|
||||
ContentParent::AllocPDeviceStorageRequestParent(const DeviceStorageParams& aParams)
|
||||
{
|
||||
RefPtr<DeviceStorageRequestParent> result = new DeviceStorageRequestParent(aParams);
|
||||
result->Dispatch();
|
||||
return result.forget().take();
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::DeallocPDeviceStorageRequestParent(PDeviceStorageRequestParent* doomed)
|
||||
{
|
||||
DeviceStorageRequestParent *parent = static_cast<DeviceStorageRequestParent*>(doomed);
|
||||
NS_RELEASE(parent);
|
||||
return true;
|
||||
}
|
||||
|
||||
PBlobParent*
|
||||
ContentParent::AllocPBlobParent(const BlobConstructorParams& aParams)
|
||||
{
|
||||
|
|
@ -3719,25 +3694,6 @@ ContentParent::RecvAsyncMessage(const nsString& aMsg,
|
|||
aData);
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ContentParent::RecvFilePathUpdateNotify(const nsString& aType,
|
||||
const nsString& aStorageName,
|
||||
const nsString& aFilePath,
|
||||
const nsCString& aReason)
|
||||
{
|
||||
RefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(aType,
|
||||
aStorageName,
|
||||
aFilePath);
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (!obs) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
obs->NotifyObservers(dsf, "file-watcher-update",
|
||||
NS_ConvertASCIItoUTF16(aReason).get());
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
static int32_t
|
||||
AddGeolocationListener(nsIDOMGeoPositionCallback* watcher,
|
||||
nsIDOMGeoPositionErrorCallback* errorCallBack,
|
||||
|
|
@ -4770,25 +4726,6 @@ ContentParent::RecvEndDriverCrashGuard(const uint32_t& aGuardType)
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ContentParent::RecvGetDeviceStorageLocation(const nsString& aType,
|
||||
nsString* aPath)
|
||||
{
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
mozilla::AndroidBridge::GetExternalPublicDirectory(aType, *aPath);
|
||||
return IPC_OK();
|
||||
#else
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ContentParent::RecvGetDeviceStorageLocations(DeviceStorageLocationInfo* info)
|
||||
{
|
||||
DeviceStorageStatics::GetDeviceStorageLocationsForIPC(info);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ContentParent::RecvGetAndroidSystemInfo(AndroidSystemInfo* aInfo)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -782,12 +782,6 @@ private:
|
|||
|
||||
virtual bool DeallocPBrowserParent(PBrowserParent* frame) override;
|
||||
|
||||
virtual PDeviceStorageRequestParent*
|
||||
AllocPDeviceStorageRequestParent(const DeviceStorageParams&) override;
|
||||
|
||||
virtual bool
|
||||
DeallocPDeviceStorageRequestParent(PDeviceStorageRequestParent*) override;
|
||||
|
||||
virtual PBlobParent*
|
||||
AllocPBlobParent(const BlobConstructorParams& aParams) override;
|
||||
|
||||
|
|
@ -973,11 +967,6 @@ private:
|
|||
const IPC::Principal& aPrincipal,
|
||||
const ClonedMessageData& aData) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvFilePathUpdateNotify(const nsString& aType,
|
||||
const nsString& aStorageName,
|
||||
const nsString& aFilePath,
|
||||
const nsCString& aReason) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvAddGeolocationListener(const IPC::Principal& aPrincipal,
|
||||
const bool& aHighAccuracy) override;
|
||||
virtual mozilla::ipc::IPCResult RecvRemoveGeolocationListener() override;
|
||||
|
|
@ -1074,11 +1063,6 @@ private:
|
|||
|
||||
void StartProfiler(nsIProfilerStartParams* aParams);
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvGetDeviceStorageLocation(const nsString& aType,
|
||||
nsString* aPath) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvGetDeviceStorageLocations(DeviceStorageLocationInfo* info) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvGetAndroidSystemInfo(AndroidSystemInfo* aInfo) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvNotifyBenchmarkResult(const nsString& aCodecName,
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ include protocol PCycleCollectWithLogs;
|
|||
include protocol PPSMContentDownloader;
|
||||
include protocol PExternalHelperApp;
|
||||
include protocol PHandlerService;
|
||||
include protocol PDeviceStorageRequest;
|
||||
include protocol PFileDescriptorSet;
|
||||
include protocol PHal;
|
||||
include protocol PHeapSnapshotTempFileHelper;
|
||||
|
|
@ -124,120 +123,6 @@ struct FontFamilyListEntry {
|
|||
uint8_t entryType;
|
||||
};
|
||||
|
||||
struct DeviceStorageFreeSpaceParams
|
||||
{
|
||||
nsString type;
|
||||
nsString storageName;
|
||||
};
|
||||
|
||||
struct DeviceStorageUsedSpaceParams
|
||||
{
|
||||
nsString type;
|
||||
nsString storageName;
|
||||
};
|
||||
|
||||
struct DeviceStorageAvailableParams
|
||||
{
|
||||
nsString type;
|
||||
nsString storageName;
|
||||
};
|
||||
|
||||
struct DeviceStorageStatusParams
|
||||
{
|
||||
nsString type;
|
||||
nsString storageName;
|
||||
};
|
||||
|
||||
struct DeviceStorageFormatParams
|
||||
{
|
||||
nsString type;
|
||||
nsString storageName;
|
||||
};
|
||||
|
||||
struct DeviceStorageMountParams
|
||||
{
|
||||
nsString type;
|
||||
nsString storageName;
|
||||
};
|
||||
|
||||
struct DeviceStorageUnmountParams
|
||||
{
|
||||
nsString type;
|
||||
nsString storageName;
|
||||
};
|
||||
|
||||
struct DeviceStorageAddParams
|
||||
{
|
||||
nsString type;
|
||||
nsString storageName;
|
||||
nsString relpath;
|
||||
PBlob blob;
|
||||
};
|
||||
|
||||
struct DeviceStorageAppendParams
|
||||
{
|
||||
nsString type;
|
||||
nsString storageName;
|
||||
nsString relpath;
|
||||
PBlob blob;
|
||||
};
|
||||
|
||||
struct DeviceStorageCreateFdParams
|
||||
{
|
||||
nsString type;
|
||||
nsString storageName;
|
||||
nsString relpath;
|
||||
};
|
||||
|
||||
struct DeviceStorageGetParams
|
||||
{
|
||||
nsString type;
|
||||
nsString storageName;
|
||||
nsString rootDir;
|
||||
nsString relpath;
|
||||
};
|
||||
|
||||
struct DeviceStorageDeleteParams
|
||||
{
|
||||
nsString type;
|
||||
nsString storageName;
|
||||
nsString relpath;
|
||||
};
|
||||
|
||||
struct DeviceStorageEnumerationParams
|
||||
{
|
||||
nsString type;
|
||||
nsString storageName;
|
||||
nsString rootdir;
|
||||
uint64_t since;
|
||||
};
|
||||
|
||||
union DeviceStorageParams
|
||||
{
|
||||
DeviceStorageAddParams;
|
||||
DeviceStorageAppendParams;
|
||||
DeviceStorageCreateFdParams;
|
||||
DeviceStorageGetParams;
|
||||
DeviceStorageDeleteParams;
|
||||
DeviceStorageEnumerationParams;
|
||||
DeviceStorageFreeSpaceParams;
|
||||
DeviceStorageUsedSpaceParams;
|
||||
DeviceStorageAvailableParams;
|
||||
DeviceStorageStatusParams;
|
||||
DeviceStorageFormatParams;
|
||||
DeviceStorageMountParams;
|
||||
DeviceStorageUnmountParams;
|
||||
};
|
||||
|
||||
struct DeviceStorageLocationInfo {
|
||||
nsString music;
|
||||
nsString pictures;
|
||||
nsString videos;
|
||||
nsString sdcard;
|
||||
nsString apps;
|
||||
nsString crashes;
|
||||
};
|
||||
|
||||
union PrefValue {
|
||||
nsCString;
|
||||
int32_t;
|
||||
|
|
@ -385,7 +270,6 @@ nested(upto inside_cpow) sync protocol PContent
|
|||
manages PBrowser;
|
||||
manages PContentPermissionRequest;
|
||||
manages PCycleCollectWithLogs;
|
||||
manages PDeviceStorageRequest;
|
||||
manages PPSMContentDownloader;
|
||||
manages PExternalHelperApp;
|
||||
manages PFileDescriptorSet;
|
||||
|
|
@ -564,9 +448,6 @@ child:
|
|||
// Notify child that last-pb-context-exited notification was observed
|
||||
async LastPrivateDocShellDestroyed();
|
||||
|
||||
async FilePathUpdate(nsString storageType, nsString storageName, nsString filepath,
|
||||
nsCString reasons);
|
||||
|
||||
async NotifyProcessPriorityChanged(ProcessPriority priority);
|
||||
async MinimizeMemoryUsage();
|
||||
|
||||
|
|
@ -750,7 +631,6 @@ parent:
|
|||
async PJavaScript();
|
||||
|
||||
async PRemoteSpellcheckEngine();
|
||||
async PDeviceStorageRequest(DeviceStorageParams params);
|
||||
|
||||
async InitCrashReporter(Shmem shmem, NativeThreadId tid);
|
||||
|
||||
|
|
@ -936,11 +816,6 @@ parent:
|
|||
|
||||
async AudioChannelChangeDefVolChannel(int32_t aChannel, bool aHidden);
|
||||
|
||||
async FilePathUpdateNotify(nsString aType,
|
||||
nsString aStorageName,
|
||||
nsString aFilepath,
|
||||
nsCString aReason);
|
||||
|
||||
sync KeywordToURI(nsCString keyword)
|
||||
returns (nsString providerName, OptionalInputStreamParams postData, OptionalURIParams uri);
|
||||
|
||||
|
|
@ -1125,12 +1000,6 @@ parent:
|
|||
OriginAttributes aOpenerOriginAttributes,
|
||||
float aFullZoom);
|
||||
|
||||
sync GetDeviceStorageLocation(nsString type)
|
||||
returns (nsString path);
|
||||
|
||||
sync GetDeviceStorageLocations()
|
||||
returns (DeviceStorageLocationInfo info);
|
||||
|
||||
sync GetAndroidSystemInfo()
|
||||
returns (AndroidSystemInfo info);
|
||||
|
||||
|
|
|
|||
|
|
@ -123,7 +123,6 @@ LOCAL_INCLUDES += [
|
|||
'/chrome',
|
||||
'/docshell/base',
|
||||
'/dom/base',
|
||||
'/dom/devicestorage',
|
||||
'/dom/events',
|
||||
'/dom/filesystem',
|
||||
'/dom/geolocation',
|
||||
|
|
|
|||
|
|
@ -50,7 +50,6 @@ DIRS += [
|
|||
'canvas',
|
||||
'commandhandler',
|
||||
'crypto',
|
||||
'devicestorage',
|
||||
'encoding',
|
||||
'events',
|
||||
'fetch',
|
||||
|
|
|
|||
|
|
@ -281,10 +281,6 @@ var interfaceNamesInGlobalScope =
|
|||
"DeviceOrientationEvent",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
"DeviceProximityEvent",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{ name: "DeviceStorageAreaListener", desktop: false},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{ name: "DeviceStorage", desktop: false},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
"Directory",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
|
|
|
|||
|
|
@ -1,95 +0,0 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
dictionary DeviceStorageEnumerationParameters {
|
||||
Date since;
|
||||
};
|
||||
|
||||
[Pref="device.storage.enabled"]
|
||||
interface DeviceStorage : EventTarget {
|
||||
attribute EventHandler onchange;
|
||||
|
||||
[Throws]
|
||||
DOMRequest? add(Blob? aBlob);
|
||||
[Throws]
|
||||
DOMRequest? addNamed(Blob? aBlob, DOMString aName);
|
||||
|
||||
/**
|
||||
* Append data to a given file.
|
||||
* If the file doesn't exist, a "NotFoundError" event will be dispatched.
|
||||
* In the same time, it is a request.onerror case.
|
||||
* If the file exists, it will be opened with the following permission:
|
||||
* "PR_WRONLY|PR_CREATE_FILE|PR_APPEND".
|
||||
* The function will return null when blob file is null and other unexpected situations.
|
||||
* @parameter aBlob: A Blob object representing the data to append
|
||||
* @parameter aName: A string representing the full name (path + file name) of the file
|
||||
* to append data to.
|
||||
*/
|
||||
[Throws]
|
||||
DOMRequest? appendNamed(Blob? aBlob, DOMString aName);
|
||||
|
||||
[Throws]
|
||||
DOMRequest get(DOMString aName);
|
||||
[Throws]
|
||||
DOMRequest getEditable(DOMString aName);
|
||||
[Throws]
|
||||
DOMRequest delete(DOMString aName);
|
||||
|
||||
[Throws]
|
||||
DOMCursor enumerate(optional DeviceStorageEnumerationParameters options);
|
||||
[Throws]
|
||||
DOMCursor enumerate(DOMString path,
|
||||
optional DeviceStorageEnumerationParameters options);
|
||||
[Throws]
|
||||
DOMCursor enumerateEditable(optional DeviceStorageEnumerationParameters options);
|
||||
[Throws]
|
||||
DOMCursor enumerateEditable(DOMString path,
|
||||
optional DeviceStorageEnumerationParameters options);
|
||||
|
||||
[Throws]
|
||||
DOMRequest freeSpace();
|
||||
[Throws]
|
||||
DOMRequest usedSpace();
|
||||
[Throws]
|
||||
DOMRequest available();
|
||||
[Throws]
|
||||
DOMRequest storageStatus();
|
||||
[Throws]
|
||||
DOMRequest format();
|
||||
[Throws]
|
||||
DOMRequest mount();
|
||||
[Throws]
|
||||
DOMRequest unmount();
|
||||
|
||||
// Note that the storageName is just a name (like sdcard), and doesn't
|
||||
// include any path information.
|
||||
readonly attribute DOMString storageName;
|
||||
|
||||
// Indicates if the storage area denoted by storageName is capable of
|
||||
// being mounted and unmounted.
|
||||
readonly attribute boolean canBeMounted;
|
||||
|
||||
// Indicates if the storage area denoted by storageName is capable of
|
||||
// being shared and unshared.
|
||||
readonly attribute boolean canBeShared;
|
||||
|
||||
// Indicates if the storage area denoted by storageName is capable of
|
||||
// being formatted.
|
||||
readonly attribute boolean canBeFormatted;
|
||||
|
||||
// Determines if this storage area is the one which will be used by default
|
||||
// for storing new files.
|
||||
readonly attribute boolean default;
|
||||
|
||||
// Indicates if the storage area denoted by storageName is removable
|
||||
readonly attribute boolean isRemovable;
|
||||
|
||||
// True if the storage area is close to being full
|
||||
readonly attribute boolean lowDiskSpace;
|
||||
|
||||
[NewObject]
|
||||
// XXXbz what type does this really return?
|
||||
Promise<any> getRoot();
|
||||
};
|
||||
|
|
@ -484,7 +484,6 @@ WEBIDL_FILES = [
|
|||
'DelayNode.webidl',
|
||||
'DesktopNotification.webidl',
|
||||
'DeviceMotionEvent.webidl',
|
||||
'DeviceStorage.webidl',
|
||||
'Directory.webidl',
|
||||
'Document.webidl',
|
||||
'DocumentFragment.webidl',
|
||||
|
|
|
|||
|
|
@ -819,10 +819,6 @@ description =
|
|||
description =
|
||||
[PContent::CreateWindow]
|
||||
description =
|
||||
[PContent::GetDeviceStorageLocation]
|
||||
description =
|
||||
[PContent::GetDeviceStorageLocations]
|
||||
description =
|
||||
[PContent::GetAndroidSystemInfo]
|
||||
description =
|
||||
[PContent::UngrabPointer]
|
||||
|
|
|
|||
|
|
@ -129,7 +129,6 @@ using namespace mozilla::system;
|
|||
#include "TouchManager.h"
|
||||
#include "MediaDecoder.h"
|
||||
#include "MediaPrefs.h"
|
||||
#include "mozilla/dom/devicestorage/DeviceStorageStatics.h"
|
||||
#include "mozilla/ServoBindings.h"
|
||||
#include "mozilla/StaticPresData.h"
|
||||
#include "mozilla/dom/WebIDLGlobalNameHash.h"
|
||||
|
|
@ -310,8 +309,6 @@ nsLayoutStatics::Initialize()
|
|||
|
||||
PromiseDebugging::Init();
|
||||
|
||||
mozilla::dom::devicestorage::DeviceStorageStatics::Initialize();
|
||||
|
||||
mozilla::dom::WebCryptoThreadPool::Initialize();
|
||||
|
||||
#ifdef MOZ_STYLO
|
||||
|
|
|
|||
|
|
@ -13,10 +13,6 @@ Cu.import("resource://gre/modules/Services.jsm");
|
|||
const kEntities = {
|
||||
"contacts": "contacts",
|
||||
"desktop-notification": "desktopNotification2",
|
||||
"device-storage:music": "deviceStorageMusic",
|
||||
"device-storage:pictures": "deviceStoragePictures",
|
||||
"device-storage:sdcard": "deviceStorageSdcard",
|
||||
"device-storage:videos": "deviceStorageVideos",
|
||||
"geolocation": "geolocation",
|
||||
"flyweb-publish-server": "flyWebPublishServer",
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2189,44 +2189,6 @@ public class GeckoAppShell
|
|||
return connection.getContentType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the absolute path of an external storage directory.
|
||||
*
|
||||
* @param type The type of directory to return
|
||||
* @return Absolute path of the specified directory or null on failure
|
||||
*/
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
private static String getExternalPublicDirectory(final String type) {
|
||||
final String state = Environment.getExternalStorageState();
|
||||
if (!Environment.MEDIA_MOUNTED.equals(state) &&
|
||||
!Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
|
||||
// External storage is not available.
|
||||
return null;
|
||||
}
|
||||
|
||||
if ("sdcard".equals(type)) {
|
||||
// SD card has a separate path.
|
||||
return Environment.getExternalStorageDirectory().getAbsolutePath();
|
||||
}
|
||||
|
||||
final String systemType;
|
||||
if ("downloads".equals(type)) {
|
||||
systemType = Environment.DIRECTORY_DOWNLOADS;
|
||||
} else if ("pictures".equals(type)) {
|
||||
systemType = Environment.DIRECTORY_PICTURES;
|
||||
} else if ("videos".equals(type)) {
|
||||
systemType = Environment.DIRECTORY_MOVIES;
|
||||
} else if ("music".equals(type)) {
|
||||
systemType = Environment.DIRECTORY_MUSIC;
|
||||
} else if ("apps".equals(type)) {
|
||||
File appInternalStorageDirectory = getApplicationContext().getFilesDir();
|
||||
return new File(appInternalStorageDirectory, "mozilla").getAbsolutePath();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return Environment.getExternalStoragePublicDirectory(systemType).getAbsolutePath();
|
||||
}
|
||||
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
private static int getMaxTouchPoints() {
|
||||
PackageManager pm = getApplicationContext().getPackageManager();
|
||||
|
|
|
|||
|
|
@ -145,35 +145,6 @@ flyWebPublishServer.publishServer=Publish Server
|
|||
imageblocking.downloadedImage=Image unblocked
|
||||
imageblocking.showAllImages=Show All
|
||||
|
||||
# Device Storage API
|
||||
deviceStorageMusic.allow=Allow
|
||||
deviceStorageMusic.dontAllow=Don't allow
|
||||
deviceStorageMusic.ask=Allow %S access to your music?
|
||||
# LOCALIZATION NOTE (deviceStorageMusic.dontAskAgain): This label appears next to a
|
||||
# checkbox to indicate whether or not the user wants to make a permanent decision.
|
||||
deviceStorageMusic.dontAskAgain=Don't ask again for this site
|
||||
|
||||
deviceStoragePictures.allow=Allow
|
||||
deviceStoragePictures.dontAllow=Don't allow
|
||||
deviceStoragePictures.ask=Allow %S access to your images?
|
||||
# LOCALIZATION NOTE (deviceStoragePictures.dontAskAgain): This label appears next to a
|
||||
# checkbox to indicate whether or not the user wants to make a permanent decision.
|
||||
deviceStoragePictures.dontAskAgain=Don't ask again for this site
|
||||
|
||||
deviceStorageSdcard.allow=Allow
|
||||
deviceStorageSdcard.dontAllow=Don't allow
|
||||
deviceStorageSdcard.ask=Allow %S access to external storage?
|
||||
# LOCALIZATION NOTE (deviceStorageSdcard.dontAskAgain): This label appears next to a
|
||||
# checkbox to indicate whether or not the user wants to make a permanent decision.
|
||||
deviceStorageSdcard.dontAskAgain=Don't ask again for this site
|
||||
|
||||
deviceStorageVideos.allow=Allow
|
||||
deviceStorageVideos.dontAllow=Don't allow
|
||||
deviceStorageVideos.ask=Allow %S access to your videos?
|
||||
# LOCALIZATION NOTE (deviceStorageVideos.dontAskAgain): This label appears next to a
|
||||
# checkbox to indicate whether or not the user wants to make a permanent decision.
|
||||
deviceStorageVideos.dontAskAgain=Don't ask again for this site
|
||||
|
||||
# New Tab Popup
|
||||
# LOCALIZATION NOTE (newtabpopup, newprivatetabpopup): Semicolon-separated list of plural forms.
|
||||
# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
|
||||
|
|
|
|||
|
|
@ -40,9 +40,6 @@ Content-Type: application/x-web-app-manifest+json\r
|
|||
{
|
||||
"systemXHR": {
|
||||
"description": "Needed to download stuff"
|
||||
},
|
||||
"devicestorage:pictures": {
|
||||
"description": "Need to load pictures"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
|
|
|||
|
|
@ -273,43 +273,6 @@ this.DownloadIntegration = {
|
|||
yield new DownloadAutoSaveView(list, this._store).initialize();
|
||||
}),
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
/**
|
||||
* Finds the default download directory which can be either in the
|
||||
* internal storage or on the sdcard.
|
||||
*
|
||||
* @return {Promise}
|
||||
* @resolves The downloads directory string path.
|
||||
*/
|
||||
_getDefaultDownloadDirectory: Task.async(function* () {
|
||||
let directoryPath;
|
||||
let win = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let storages = win.navigator.getDeviceStorages("sdcard");
|
||||
let preferredStorageName;
|
||||
// Use the first one or the default storage.
|
||||
storages.forEach((aStorage) => {
|
||||
if (aStorage.default || !preferredStorageName) {
|
||||
preferredStorageName = aStorage.storageName;
|
||||
}
|
||||
});
|
||||
|
||||
// Now get the path for this storage area.
|
||||
if (preferredStorageName) {
|
||||
let volume = volumeService.getVolumeByName(preferredStorageName);
|
||||
if (volume && volume.state === Ci.nsIVolume.STATE_MOUNTED){
|
||||
directoryPath = OS.Path.join(volume.mountPoint, "downloads");
|
||||
yield OS.File.makeDir(directoryPath, { ignoreExisting: true });
|
||||
}
|
||||
}
|
||||
if (directoryPath) {
|
||||
return directoryPath;
|
||||
} else {
|
||||
throw new Components.Exception("No suitable storage for downloads.",
|
||||
Cr.NS_ERROR_FILE_UNRECOGNIZED_PATH);
|
||||
}
|
||||
}),
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Determines if a Download object from the list of persistent downloads
|
||||
* should be saved into a file, so that it can be restored across sessions.
|
||||
|
|
@ -382,8 +345,6 @@ this.DownloadIntegration = {
|
|||
throw new Components.Exception("DOWNLOADS_DIRECTORY is not set.",
|
||||
Cr.NS_ERROR_FILE_UNRECOGNIZED_PATH);
|
||||
}
|
||||
#elifdef MOZ_WIDGET_GONK
|
||||
directoryPath = this._getDefaultDownloadDirectory();
|
||||
#else
|
||||
// For Linux, use XDG download dir, with a fallback to Home/Downloads
|
||||
// if the XDG user dirs are disabled.
|
||||
|
|
@ -410,9 +371,6 @@ this.DownloadIntegration = {
|
|||
*/
|
||||
getPreferredDownloadsDirectory: Task.async(function* () {
|
||||
let directoryPath = null;
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
directoryPath = this._getDefaultDownloadDirectory();
|
||||
#else
|
||||
let prefValue = Services.prefs.getIntPref("browser.download.folderList", 1);
|
||||
|
||||
switch(prefValue) {
|
||||
|
|
@ -436,7 +394,6 @@ this.DownloadIntegration = {
|
|||
default:
|
||||
directoryPath = yield this.getSystemDownloadsDirectory();
|
||||
}
|
||||
#endif
|
||||
return directoryPath;
|
||||
}),
|
||||
|
||||
|
|
|
|||
|
|
@ -190,18 +190,6 @@ nsresult DownloadPlatform::DownloadDone(nsIURI* aSource, nsIURI* aReferrer, nsIF
|
|||
}
|
||||
}
|
||||
#endif
|
||||
if (mozilla::Preferences::GetBool("device.storage.enabled", true)) {
|
||||
// Tell DeviceStorage that a new file may have been added.
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
nsCOMPtr<nsISupportsString> pathString
|
||||
= do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
|
||||
if (obs && pathString) {
|
||||
if (NS_SUCCEEDED(pathString->SetData(path))) {
|
||||
(void)obs->NotifyObservers(pathString, "download-watcher-notify",
|
||||
u"modified");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -2273,86 +2273,6 @@ add_task(function* test_toSerializable_startTime() {
|
|||
do_check_eq(download1.startTime.toJSON(), download2.startTime.toJSON());
|
||||
});
|
||||
|
||||
/**
|
||||
* This test will call the platform specific operations within
|
||||
* DownloadPlatform::DownloadDone. While there is no test to verify the
|
||||
* specific behaviours, this at least ensures that there is no error or crash.
|
||||
*/
|
||||
add_task(function* test_platform_integration() {
|
||||
let downloadFiles = [];
|
||||
let oldDeviceStorageEnabled = Services.prefs.getBoolPref("device.storage.enabled", false);
|
||||
let downloadWatcherNotified = false;
|
||||
let observer = {
|
||||
observe(subject, topic, data) {
|
||||
do_check_eq(topic, "download-watcher-notify");
|
||||
do_check_eq(data, "modified");
|
||||
downloadWatcherNotified = true;
|
||||
}
|
||||
}
|
||||
Services.obs.addObserver(observer, "download-watcher-notify", false);
|
||||
Services.prefs.setBoolPref("device.storage.enabled", true);
|
||||
let downloadDoneCalled = false;
|
||||
let monitorFn = base => ({
|
||||
__proto__: base,
|
||||
downloadDone() {
|
||||
return super.downloadDone(...arguments).then(() => {
|
||||
downloadDoneCalled = true;
|
||||
});
|
||||
},
|
||||
});
|
||||
Integration.downloads.register(monitorFn);
|
||||
DownloadIntegration.allowDirectories = true;
|
||||
function cleanup() {
|
||||
for (let file of downloadFiles) {
|
||||
file.remove(true);
|
||||
}
|
||||
Services.obs.removeObserver(observer, "download-watcher-notify");
|
||||
Services.prefs.setBoolPref("device.storage.enabled", oldDeviceStorageEnabled);
|
||||
Integration.downloads.unregister(monitorFn);
|
||||
DownloadIntegration.allowDirectories = false;
|
||||
}
|
||||
|
||||
for (let isPrivate of [false, true]) {
|
||||
downloadDoneCalled = false;
|
||||
|
||||
// Some platform specific operations only operate on files outside the
|
||||
// temporary directory or in the Downloads directory (such as setting
|
||||
// the Windows searchable attribute, and the Mac Downloads icon bouncing),
|
||||
// so use the system Downloads directory for the target file.
|
||||
let targetFilePath = yield DownloadIntegration.getSystemDownloadsDirectory();
|
||||
targetFilePath = OS.Path.join(targetFilePath,
|
||||
"test" + (Math.floor(Math.random() * 1000000)));
|
||||
let targetFile = new FileUtils.File(targetFilePath);
|
||||
downloadFiles.push(targetFile);
|
||||
|
||||
let download;
|
||||
if (gUseLegacySaver) {
|
||||
download = yield promiseStartLegacyDownload(httpUrl("source.txt"),
|
||||
{ isPrivate, targetFile });
|
||||
} else {
|
||||
download = yield Downloads.createDownload({
|
||||
source: { url: httpUrl("source.txt"), isPrivate },
|
||||
target: targetFile,
|
||||
});
|
||||
download.start().catch(() => {});
|
||||
}
|
||||
|
||||
// Wait for the whenSucceeded promise to be resolved first.
|
||||
// downloadDone should be called before the whenSucceeded promise is resolved.
|
||||
yield download.whenSucceeded().then(function() {
|
||||
do_check_true(downloadDoneCalled);
|
||||
do_check_true(downloadWatcherNotified);
|
||||
});
|
||||
|
||||
// Then, wait for the promise returned by "start" to be resolved.
|
||||
yield promiseDownloadStopped(download);
|
||||
|
||||
yield promiseVerifyTarget(download.target, TEST_DATA_SHORT);
|
||||
}
|
||||
|
||||
cleanup();
|
||||
});
|
||||
|
||||
/**
|
||||
* Checks that downloads are added to browsing history when they start.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,4 +0,0 @@
|
|||
# Extensions we recognize for DeviceStorage storage areas
|
||||
pictures=*.jpe; *.jpg; *.jpeg; *.gif; *.png; *.bmp;
|
||||
music=*.mp3; *.oga; *.ogg; *.m4a; *.m4b; *.m4p; *.m4r; *.3gp; *.3gpp; *.mp4; *.m3u; *.pls; *.opus; *.amr; *.wav; *.lcka; *.mka; *.flac;
|
||||
videos=*.mp4; *.mpeg; *.mpg; *.ogv; *.ogx; *.webm; *.3gp; *.3gpp; *.3g2; *.ogg; *.m4v; *.ts; *.m2ts; *.avi; *.divx; *.mkv;
|
||||
|
|
@ -46,7 +46,6 @@ toolkit.jar:
|
|||
content/global/customizeToolbar.xul
|
||||
#endif
|
||||
content/global/datepicker.xhtml
|
||||
content/global/devicestorage.properties
|
||||
#ifndef MOZ_FENNEC
|
||||
content/global/editMenuOverlay.js
|
||||
* content/global/editMenuOverlay.xul
|
||||
|
|
@ -119,4 +118,4 @@ toolkit.jar:
|
|||
content/global/macWindowMenu.js
|
||||
#endif
|
||||
content/global/gmp-sources/openh264.json (gmp-sources/openh264.json)
|
||||
content/global/gmp-sources/widevinecdm.json (gmp-sources/widevinecdm.json)
|
||||
content/global/gmp-sources/widevinecdm.json (gmp-sources/widevinecdm.json)
|
||||
|
|
|
|||
|
|
@ -107,10 +107,6 @@
|
|||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/ipc/URIUtils.h"
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
#include "nsDeviceStorage.h"
|
||||
#endif
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::ipc;
|
||||
|
||||
|
|
@ -327,55 +323,6 @@ static nsresult GetDownloadDirectory(nsIFile **_directory,
|
|||
getter_AddRefs(dir));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
#elif defined(MOZ_WIDGET_GONK)
|
||||
// On Gonk, store the files on the sdcard in the downloads directory.
|
||||
// We need to check with the volume manager which storage point is
|
||||
// available.
|
||||
|
||||
// Pick the default storage in case multiple (internal and external) ones
|
||||
// are available.
|
||||
nsString storageName;
|
||||
nsDOMDeviceStorage::GetDefaultStorageName(NS_LITERAL_STRING("sdcard"),
|
||||
storageName);
|
||||
|
||||
RefPtr<DeviceStorageFile> dsf(
|
||||
new DeviceStorageFile(NS_LITERAL_STRING("sdcard"),
|
||||
storageName,
|
||||
NS_LITERAL_STRING("downloads")));
|
||||
NS_ENSURE_TRUE(dsf->mFile, NS_ERROR_FILE_ACCESS_DENIED);
|
||||
|
||||
// If we're not checking for availability we're done.
|
||||
if (aSkipChecks) {
|
||||
dsf->mFile.forget(_directory);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Check device storage status before continuing.
|
||||
nsString storageStatus;
|
||||
dsf->GetStatus(storageStatus);
|
||||
|
||||
// If we get an "unavailable" status, it means the sd card is not present.
|
||||
// We'll also catch internal errors by looking for an empty string and assume
|
||||
// the SD card isn't present when this occurs.
|
||||
if (storageStatus.EqualsLiteral("unavailable") ||
|
||||
storageStatus.IsEmpty()) {
|
||||
return NS_ERROR_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
// If we get a status other than 'available' here it means the card is busy
|
||||
// because it's mounted via USB or it is being formatted.
|
||||
if (!storageStatus.EqualsLiteral("available")) {
|
||||
return NS_ERROR_FILE_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
bool alreadyThere;
|
||||
nsresult rv = dsf->mFile->Exists(&alreadyThere);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!alreadyThere) {
|
||||
rv = dsf->mFile->Create(nsIFile::DIRECTORY_TYPE, 0770);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
dir = dsf->mFile;
|
||||
#elif defined(ANDROID)
|
||||
// We ask Java for the temporary download directory. The directory will be
|
||||
// different depending on whether we have the permission to write to the
|
||||
|
|
|
|||
|
|
@ -1130,37 +1130,3 @@ nsresult AndroidBridge::InputStreamRead(Object::Param obj, char *aBuf, uint32_t
|
|||
*aRead = read;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult AndroidBridge::GetExternalPublicDirectory(const nsAString& aType, nsAString& aPath) {
|
||||
if (XRE_IsContentProcess()) {
|
||||
nsString key(aType);
|
||||
nsAutoString path;
|
||||
if (AndroidBridge::sStoragePaths.Get(key, &path)) {
|
||||
aPath = path;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Lazily get the value from the parent.
|
||||
dom::ContentChild* child = dom::ContentChild::GetSingleton();
|
||||
if (child) {
|
||||
nsAutoString type(aType);
|
||||
child->SendGetDeviceStorageLocation(type, &path);
|
||||
if (!path.IsEmpty()) {
|
||||
AndroidBridge::sStoragePaths.Put(key, path);
|
||||
aPath = path;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
ALOG_BRIDGE("AndroidBridge::GetExternalPublicDirectory no cache for %s",
|
||||
NS_ConvertUTF16toUTF8(aType).get());
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
auto path = GeckoAppShell::GetExternalPublicDirectory(aType);
|
||||
if (!path) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
aPath = path->ToString();
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -196,8 +196,6 @@ public:
|
|||
static uint32_t InputStreamAvailable(jni::Object::Param obj);
|
||||
static nsresult InputStreamRead(jni::Object::Param obj, char *aBuf, uint32_t aCount, uint32_t *aRead);
|
||||
|
||||
static nsresult GetExternalPublicDirectory(const nsAString& aType, nsAString& aPath);
|
||||
|
||||
protected:
|
||||
static nsDataHashtable<nsStringHashKey, nsString> sStoragePaths;
|
||||
|
||||
|
|
|
|||
|
|
@ -335,14 +335,6 @@ auto GeckoAppShell::GetExtensionFromMimeType(mozilla::jni::String::Param a0) ->
|
|||
return mozilla::jni::Method<GetExtensionFromMimeType_t>::Call(GeckoAppShell::Context(), nullptr, a0);
|
||||
}
|
||||
|
||||
constexpr char GeckoAppShell::GetExternalPublicDirectory_t::name[];
|
||||
constexpr char GeckoAppShell::GetExternalPublicDirectory_t::signature[];
|
||||
|
||||
auto GeckoAppShell::GetExternalPublicDirectory(mozilla::jni::String::Param a0) -> mozilla::jni::String::LocalRef
|
||||
{
|
||||
return mozilla::jni::Method<GetExternalPublicDirectory_t>::Call(GeckoAppShell::Context(), nullptr, a0);
|
||||
}
|
||||
|
||||
constexpr char GeckoAppShell::GetHWDecoderCapability_t::name[];
|
||||
constexpr char GeckoAppShell::GetHWDecoderCapability_t::signature[];
|
||||
|
||||
|
|
|
|||
|
|
@ -951,26 +951,6 @@ public:
|
|||
|
||||
static auto GetExtensionFromMimeType(mozilla::jni::String::Param) -> mozilla::jni::String::LocalRef;
|
||||
|
||||
struct GetExternalPublicDirectory_t {
|
||||
typedef GeckoAppShell Owner;
|
||||
typedef mozilla::jni::String::LocalRef ReturnType;
|
||||
typedef mozilla::jni::String::Param SetterType;
|
||||
typedef mozilla::jni::Args<
|
||||
mozilla::jni::String::Param> Args;
|
||||
static constexpr char name[] = "getExternalPublicDirectory";
|
||||
static constexpr char signature[] =
|
||||
"(Ljava/lang/String;)Ljava/lang/String;";
|
||||
static const bool isStatic = true;
|
||||
static const mozilla::jni::ExceptionMode exceptionMode =
|
||||
mozilla::jni::ExceptionMode::ABORT;
|
||||
static const mozilla::jni::CallingThread callingThread =
|
||||
mozilla::jni::CallingThread::GECKO;
|
||||
static const mozilla::jni::DispatchTarget dispatchTarget =
|
||||
mozilla::jni::DispatchTarget::CURRENT;
|
||||
};
|
||||
|
||||
static auto GetExternalPublicDirectory(mozilla::jni::String::Param) -> mozilla::jni::String::LocalRef;
|
||||
|
||||
struct GetHWDecoderCapability_t {
|
||||
typedef GeckoAppShell Owner;
|
||||
typedef bool ReturnType;
|
||||
|
|
|
|||
|
|
@ -160,7 +160,6 @@
|
|||
#endif
|
||||
#include "mozilla/dom/DataContainerEventBinding.h"
|
||||
#include "mozilla/dom/DataTransferBinding.h"
|
||||
#include "mozilla/dom/DeviceStorageBinding.h"
|
||||
#include "mozilla/dom/DOMCursorBinding.h"
|
||||
#include "mozilla/dom/DOMExceptionBinding.h"
|
||||
#include "mozilla/dom/DOMParserBinding.h"
|
||||
|
|
|
|||
Loading…
Reference in a new issue