Bug 777088 - device Storage - file stat API. r=bent

This commit is contained in:
Doug Turner 2012-07-31 12:28:23 -07:00
parent b3518b52c3
commit 84dd794e39
15 changed files with 459 additions and 35 deletions

View File

@ -420,6 +420,7 @@
// Device Storage
#include "nsIDOMDeviceStorage.h"
#include "nsIDOMDeviceStorageCursor.h"
#include "nsIDOMDeviceStorageStat.h"
// Drag and drop
#include "nsIDOMDataTransfer.h"
@ -1441,6 +1442,9 @@ static nsDOMClassInfoData sClassInfoData[] = {
NS_DEFINE_CLASSINFO_DATA(DeviceStorageCursor, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(DeviceStorageStat, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(GeoGeolocation, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
@ -4041,6 +4045,10 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(DeviceStorageStat, nsIDOMDeviceStorageStat)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMDeviceStorageStat)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(GeoGeolocation, nsIDOMGeoGeolocation)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMGeoGeolocation)
DOM_CLASSINFO_MAP_END

View File

@ -386,6 +386,7 @@ DOMCI_CLASS(MessageEvent)
DOMCI_CLASS(DeviceStorage)
DOMCI_CLASS(DeviceStorageCursor)
DOMCI_CLASS(DeviceStorageStat)
// Geolocation
DOMCI_CLASS(GeoGeolocation)

View File

@ -55,7 +55,17 @@ DeviceStorageRequestChild::Recv__delete__(const DeviceStorageResponseValue& aVal
BlobChild* actor = static_cast<BlobChild*>(r.blobChild());
nsCOMPtr<nsIDOMBlob> blob = actor->GetBlob();
jsval result = BlobToJsval(mRequest->GetOwner(), blob);
jsval result = InterfaceToJsval(mRequest->GetOwner(), blob, &NS_GET_IID(nsIDOMBlob));
mRequest->FireSuccess(result);
break;
}
case DeviceStorageResponseValue::TStatStorageResponse:
{
StatStorageResponse r = aValue;
nsRefPtr<nsIDOMDeviceStorageStat> domstat = new nsDOMDeviceStorageStat(r.freeBytes(), r.totalBytes());
jsval result = InterfaceToJsval(mRequest->GetOwner(), domstat, &NS_GET_IID(nsIDOMDeviceStorageStat));
mRequest->FireSuccess(result);
break;
}
@ -68,7 +78,10 @@ DeviceStorageRequestChild::Recv__delete__(const DeviceStorageResponseValue& aVal
PRUint32 count = r.paths().Length();
for (PRUint32 i = 0; i < count; i++) {
nsCOMPtr<nsIFile> f;
NS_NewLocalFile(r.paths()[i].fullpath(), false, getter_AddRefs(f));
nsresult rv = NS_NewLocalFile(r.paths()[i].fullpath(), false, getter_AddRefs(f));
if (NS_FAILED(rv)) {
continue;
}
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(f);
dsf->SetPath(r.paths()[i].name());

View File

@ -77,6 +77,22 @@ DeviceStorageRequestParent::DeviceStorageRequestParent(const DeviceStorageParams
break;
}
case DeviceStorageParams::TDeviceStorageStatParams:
{
DeviceStorageStatParams p = aParams;
nsCOMPtr<nsIFile> f;
NS_NewLocalFile(p.fullpath(), false, getter_AddRefs(f));
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(f);
nsRefPtr<StatFileEvent> r = new StatFileEvent(this, dsf);
nsCOMPtr<nsIEventTarget> target = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
NS_ASSERTION(target, "Must have stream transport service");
target->Dispatch(r, NS_DISPATCH_NORMAL);
break;
}
case DeviceStorageParams::TDeviceStorageEnumerationParams:
{
DeviceStorageEnumerationParams p = aParams;
@ -257,7 +273,7 @@ DeviceStorageRequestParent::DeleteFileEvent::~DeleteFileEvent()
nsresult
DeviceStorageRequestParent::DeleteFileEvent::CancelableRun()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
mFile->mFile->Remove(true);
@ -276,6 +292,36 @@ DeviceStorageRequestParent::DeleteFileEvent::CancelableRun()
return NS_OK;
}
DeviceStorageRequestParent::StatFileEvent::StatFileEvent(DeviceStorageRequestParent* aParent,
DeviceStorageFile* aFile)
: CancelableRunnable(aParent)
, mFile(aFile)
{
}
DeviceStorageRequestParent::StatFileEvent::~StatFileEvent()
{
}
nsresult
DeviceStorageRequestParent::StatFileEvent::CancelableRun()
{
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
nsCOMPtr<nsIRunnable> r;
PRUint64 diskUsage = DeviceStorageFile::DirectoryDiskUsage(mFile->mFile);
PRInt64 freeSpace = 0;
nsresult rv = mFile->mFile->GetDiskSpaceAvailable(&freeSpace);
if (NS_FAILED(rv)) {
r = new PostErrorEvent(mParent, POST_ERROR_EVENT_UNKNOWN);
NS_DispatchToMainThread(r);
return NS_OK;
}
r = new PostStatResultEvent(mParent, diskUsage, freeSpace);
NS_DispatchToMainThread(r);
return NS_OK;
}
DeviceStorageRequestParent::ReadFileEvent::ReadFileEvent(DeviceStorageRequestParent* aParent,
DeviceStorageFile* aFile)
: CancelableRunnable(aParent)
@ -297,7 +343,7 @@ DeviceStorageRequestParent::ReadFileEvent::~ReadFileEvent()
nsresult
DeviceStorageRequestParent::ReadFileEvent::CancelableRun()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
nsCOMPtr<nsIRunnable> r;
bool check = false;
@ -338,7 +384,7 @@ DeviceStorageRequestParent::EnumerateFileEvent::~EnumerateFileEvent()
nsresult
DeviceStorageRequestParent::EnumerateFileEvent::CancelableRun()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
nsCOMPtr<nsIRunnable> r;
bool check = false;
@ -389,6 +435,29 @@ DeviceStorageRequestParent::PostPathResultEvent::CancelableRun()
return NS_OK;
}
DeviceStorageRequestParent::PostStatResultEvent::PostStatResultEvent(DeviceStorageRequestParent* aParent,
PRInt64 aFreeBytes,
PRInt64 aTotalBytes)
: CancelableRunnable(aParent)
, mFreeBytes(aFreeBytes)
, mTotalBytes(aTotalBytes)
{
}
DeviceStorageRequestParent::PostStatResultEvent::~PostStatResultEvent()
{
}
nsresult
DeviceStorageRequestParent::PostStatResultEvent::CancelableRun()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
StatStorageResponse response(mFreeBytes, mTotalBytes);
unused << mParent->Send__delete__(mParent, response);
return NS_OK;
}
} // namespace devicestorage
} // namespace dom

View File

@ -127,6 +127,16 @@ private:
nsRefPtr<DeviceStorageFile> mFile;
};
class StatFileEvent : public CancelableRunnable
{
public:
StatFileEvent(DeviceStorageRequestParent* aParent, DeviceStorageFile* aFile);
virtual ~StatFileEvent();
virtual nsresult CancelableRun();
private:
nsRefPtr<DeviceStorageFile> mFile;
};
class ReadFileEvent : public CancelableRunnable
{
public:
@ -160,6 +170,18 @@ private:
nsString mPath;
};
class PostStatResultEvent : public CancelableRunnable
{
public:
PostStatResultEvent(DeviceStorageRequestParent* aParent,
PRInt64 aFreeBytes,
PRInt64 aTotalBytes);
virtual ~PostStatResultEvent();
virtual nsresult CancelableRun();
private:
PRInt64 mFreeBytes, mTotalBytes;
};
protected:
void AddRunnable(CancelableRunnable* aRunnable) {
mRunnables.AppendElement(aRunnable);

View File

@ -36,12 +36,19 @@ struct EnumerationResponse
DeviceStorageFileValue[] paths;
};
struct StatStorageResponse
{
PRInt64 totalBytes;
PRInt64 freeBytes;
};
union DeviceStorageResponseValue
{
ErrorResponse;
SuccessResponse;
BlobResponse;
EnumerationResponse;
StatStorageResponse;
};
sync protocol PDeviceStorageRequest {

View File

@ -281,6 +281,60 @@ DeviceStorageFile::collectFilesInternal(nsTArray<nsRefPtr<DeviceStorageFile> > &
}
}
PRUint64
DeviceStorageFile::DirectoryDiskUsage(nsIFile* aFile, PRUint64 aSoFar)
{
if (!aFile) {
return aSoFar;
}
nsresult rv;
nsCOMPtr<nsISimpleEnumerator> e;
rv = aFile->GetDirectoryEntries(getter_AddRefs(e));
if (NS_FAILED(rv) || !e) {
return aSoFar;
}
nsCOMPtr<nsIDirectoryEnumerator> files = do_QueryInterface(e);
NS_ASSERTION(files, "GetDirectoryEntries must return a nsIDirectoryEnumerator");
nsCOMPtr<nsIFile> f;
while (NS_SUCCEEDED(files->GetNextFile(getter_AddRefs(f))) && f) {
bool isDir;
rv = f->IsDirectory(&isDir);
if (NS_FAILED(rv)) {
continue;
}
bool isFile;
rv = f->IsFile(&isFile);
if (NS_FAILED(rv)) {
continue;
}
bool isLink;
rv = f->IsSymlink(&isLink);
if (NS_FAILED(rv)) {
continue;
}
if (isLink) {
// for now, lets just totally ignore symlinks.
NS_WARNING("DirectoryDiskUsage ignores symlinks");
} else if (isDir) {
aSoFar += DirectoryDiskUsage(f, aSoFar);
} else if (isFile) {
PRInt64 size;
rv = f->GetFileSize(&size);
if (NS_SUCCEEDED(rv)) {
aSoFar += size;
}
}
}
return aSoFar;
}
NS_IMPL_THREADSAFE_ISUPPORTS0(DeviceStorageFile)
#ifdef MOZ_WIDGET_GONK
@ -359,26 +413,7 @@ nsDOMDeviceStorage::SetRootFileForType(const nsAString& aType)
mFile = f;
}
static jsval nsIFileToJsval(nsPIDOMWindow* aWindow, DeviceStorageFile* aFile)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(aWindow, "Null Window");
if (aFile->mEditable) {
// TODO - needs janv's file handle support.
return JSVAL_NULL;
}
if (aFile == nullptr) {
return JSVAL_NULL;
}
nsCOMPtr<nsIDOMBlob> blob = new nsDOMFileFile(aFile->mFile, aFile->mPath);
return BlobToJsval(aWindow, blob);
}
jsval BlobToJsval(nsPIDOMWindow* aWindow, nsIDOMBlob* aBlob)
jsval InterfaceToJsval(nsPIDOMWindow* aWindow, nsISupports* aObject, const nsIID* aIID)
{
nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(aWindow);
if (!sgo) {
@ -395,19 +430,38 @@ jsval BlobToJsval(nsPIDOMWindow* aWindow, nsIDOMBlob* aBlob)
return JSVAL_NULL;
}
jsval wrappedFile;
jsval someJsVal;
nsresult rv = nsContentUtils::WrapNative(cx,
JS_GetGlobalObject(cx),
aBlob,
&NS_GET_IID(nsIDOMFile),
&wrappedFile);
aObject,
aIID,
&someJsVal);
if (NS_FAILED(rv)) {
return JSVAL_NULL;
}
return wrappedFile;
return someJsVal;
}
jsval nsIFileToJsval(nsPIDOMWindow* aWindow, DeviceStorageFile* aFile)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(aWindow, "Null Window");
if (aFile->mEditable) {
// TODO - needs janv's file handle support.
return JSVAL_NULL;
}
if (aFile == nullptr) {
return JSVAL_NULL;
}
nsCOMPtr<nsIDOMBlob> blob = new nsDOMFileFile(aFile->mFile, aFile->mPath);
return InterfaceToJsval(aWindow, blob, &NS_GET_IID(nsIDOMBlob));
}
jsval StringToJsval(nsPIDOMWindow* aWindow, nsAString& aString)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
@ -762,6 +816,39 @@ nsDOMDeviceStorageCursor::IPDLRelease()
Release();
}
class PostStatResultEvent : public nsRunnable
{
public:
PostStatResultEvent(nsRefPtr<DOMRequest>& aRequest, PRInt64 aFreeBytes, PRInt64 aTotalBytes)
: mFreeBytes(aFreeBytes)
, mTotalBytes(aTotalBytes)
{
mRequest.swap(aRequest);
}
~PostStatResultEvent() {}
NS_IMETHOD Run()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
nsRefPtr<nsIDOMDeviceStorageStat> domstat = new nsDOMDeviceStorageStat(mFreeBytes, mTotalBytes);
jsval result = InterfaceToJsval(mRequest->GetOwner(),
domstat,
&NS_GET_IID(nsIDOMDeviceStorageStat));
mRequest->FireSuccess(result);
mRequest = nsnull;
return NS_OK;
}
private:
PRInt64 mFreeBytes, mTotalBytes;
nsRefPtr<DOMRequest> mRequest;
};
class PostResultEvent : public nsRunnable
{
public:
@ -920,6 +1007,40 @@ private:
nsRefPtr<DOMRequest> mRequest;
};
class StatFileEvent : public nsRunnable
{
public:
StatFileEvent(DeviceStorageFile* aFile, nsRefPtr<DOMRequest>& aRequest)
: mFile(aFile)
{
mRequest.swap(aRequest);
}
~StatFileEvent() {}
NS_IMETHOD Run()
{
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
nsCOMPtr<nsIRunnable> r;
PRUint64 diskUsage = DeviceStorageFile::DirectoryDiskUsage(mFile->mFile);
PRInt64 freeSpace = 0;
nsresult rv = mFile->mFile->GetDiskSpaceAvailable(&freeSpace);
if (NS_FAILED(rv)) {
r = new PostErrorEvent(mRequest, POST_ERROR_EVENT_UNKNOWN, mFile);
NS_DispatchToMainThread(r);
return NS_OK;
}
r = new PostStatResultEvent(mRequest, diskUsage, freeSpace);
NS_DispatchToMainThread(r);
return NS_OK;
}
private:
nsRefPtr<DeviceStorageFile> mFile;
nsRefPtr<DOMRequest> mRequest;
};
class DeviceStorageRequest MOZ_FINAL
: public nsIContentPermissionRequest
, public nsIRunnable
@ -931,7 +1052,8 @@ public:
DEVICE_STORAGE_REQUEST_READ,
DEVICE_STORAGE_REQUEST_WRITE,
DEVICE_STORAGE_REQUEST_DELETE,
DEVICE_STORAGE_REQUEST_WATCH
DEVICE_STORAGE_REQUEST_WATCH,
DEVICE_STORAGE_REQUEST_STAT
};
DeviceStorageRequest(const DeviceStorageRequestType aRequestType,
@ -1100,6 +1222,18 @@ public:
break;
}
case DEVICE_STORAGE_REQUEST_STAT:
{
if (XRE_GetProcessType() != GeckoProcessType_Default) {
PDeviceStorageRequestChild* child = new DeviceStorageRequestChild(mRequest, mFile);
DeviceStorageStatParams params(fullpath);
ContentChild::GetSingleton()->SendPDeviceStorageRequestConstructor(child, params);
return NS_OK;
}
r = new StatFileEvent(mFile, mRequest);
break;
}
case DEVICE_STORAGE_REQUEST_WATCH:
{
if (XRE_GetProcessType() != GeckoProcessType_Default) {
@ -1410,6 +1544,27 @@ nsDOMDeviceStorage::Delete(const JS::Value & aPath, JSContext* aCx, nsIDOMDOMReq
return NS_OK;
}
NS_IMETHODIMP
nsDOMDeviceStorage::Stat(nsIDOMDOMRequest** aRetval)
{
nsCOMPtr<nsPIDOMWindow> win = GetOwner();
if (!win) {
return NS_ERROR_UNEXPECTED;
}
nsRefPtr<DOMRequest> request = new DOMRequest(win);
NS_ADDREF(*aRetval = request);
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mFile);
nsCOMPtr<nsIRunnable> r = new DeviceStorageRequest(DeviceStorageRequest::DEVICE_STORAGE_REQUEST_STAT,
win,
mPrincipal,
dsf,
request);
NS_DispatchToMainThread(r);
return NS_OK;
}
NS_IMETHODIMP
nsDOMDeviceStorage::Enumerate(const JS::Value & aName,
const JS::Value & aOptions,
@ -1547,6 +1702,41 @@ nsDOMDeviceStorage::DispatchMountChangeEvent(bool aMounted)
}
#endif
DOMCI_DATA(DeviceStorageStat, nsDOMDeviceStorageStat)
NS_INTERFACE_MAP_BEGIN(nsDOMDeviceStorageStat)
NS_INTERFACE_MAP_ENTRY(nsIDOMDeviceStorageStat)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(DeviceStorageStat)
NS_INTERFACE_MAP_END
NS_IMPL_ADDREF(nsDOMDeviceStorageStat)
NS_IMPL_RELEASE(nsDOMDeviceStorageStat)
nsDOMDeviceStorageStat::nsDOMDeviceStorageStat(PRUint64 aFreeBytes, PRUint64 aTotalBytes)
: mFreeBytes(aFreeBytes)
, mTotalBytes(aTotalBytes)
{
}
nsDOMDeviceStorageStat::~nsDOMDeviceStorageStat()
{
}
NS_IMETHODIMP
nsDOMDeviceStorageStat::GetTotalBytes(PRUint64 *aTotalBytes)
{
*aTotalBytes = mTotalBytes;
return NS_OK;
}
NS_IMETHODIMP
nsDOMDeviceStorageStat::GetFreeBytes(PRUint64 *aFreeBytes)
{
*aFreeBytes = mFreeBytes;
return NS_OK;
}
NS_IMETHODIMP
nsDOMDeviceStorage::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *aData)
{

View File

@ -15,6 +15,7 @@ class nsPIDOMWindow;
#include "nsIClassInfo.h"
#include "nsIContentPermissionPrompt.h"
#include "nsIDOMDeviceStorageCursor.h"
#include "nsIDOMDeviceStorageStat.h"
#include "nsIDOMWindow.h"
#include "nsIURI.h"
#include "nsInterfaceHashtable.h"
@ -34,10 +35,12 @@ class nsPIDOMWindow;
#define POST_ERROR_EVENT_ILLEGAL_FILE_NAME "Illegal file name"
#define POST_ERROR_EVENT_UNKNOWN "Unknown"
#define POST_ERROR_EVENT_NON_STRING_TYPE_UNSUPPORTED "Non-string type unsupported"
#define POST_ERROR_EVENT_NOT_IMPLEMENTED "Not implemented"
using namespace mozilla::dom;
class DeviceStorageFile MOZ_FINAL : public nsISupports {
class DeviceStorageFile MOZ_FINAL
: public nsISupports {
public:
nsCOMPtr<nsIFile> mFile;
nsString mPath;
@ -59,6 +62,8 @@ public:
void CollectFiles(nsTArray<nsRefPtr<DeviceStorageFile> > &aFiles, PRUint64 aSince = 0);
void collectFilesInternal(nsTArray<nsRefPtr<DeviceStorageFile> > &aFiles, PRUint64 aSince, nsAString& aRootPath);
static PRUint64 DirectoryDiskUsage(nsIFile* aFile, PRUint64 aSoFar = 0);
private:
void NormalizeFilePath();
void AppendRelativePath();
@ -106,10 +111,24 @@ private:
nsCOMPtr<nsIPrincipal> mPrincipal;
};
class nsDOMDeviceStorageStat MOZ_FINAL
: public nsIDOMDeviceStorageStat
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIDOMDEVICESTORAGESTAT
nsDOMDeviceStorageStat(PRUint64 aFreeBytes, PRUint64 aTotalBytes);
private:
~nsDOMDeviceStorageStat();
PRUint64 mFreeBytes, mTotalBytes;
};
//helpers
jsval StringToJsval(nsPIDOMWindow* aWindow, nsAString& aString);
jsval nsIFileToJsval(nsPIDOMWindow* aWindow, DeviceStorageFile* aFile, bool aEditable);
jsval BlobToJsval(nsPIDOMWindow* aWindow, nsIDOMBlob* aBlob);
jsval nsIFileToJsval(nsPIDOMWindow* aWindow, DeviceStorageFile* aFile);
jsval InterfaceToJsval(nsPIDOMWindow* aWindow, nsISupports* aObject, const nsIID* aIID);
#endif

View File

@ -19,6 +19,7 @@ MOCHITEST_FILES = \
test_dotdot.html \
test_enumerateOptions.html \
test_lastModificationFilter.html \
test_stat.html \
devicestorage_common.js \
$(NULL)

View File

@ -0,0 +1,72 @@
<!--
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 statSuccess(e) {
ok(e.target.result.freeBytes > 0, "free bytes should exist and be greater than zero");
ok(e.target.result.totalBytes > 0, "total bytes should exist and be greater than zero");
devicestorage_cleanup();
}
function statError(e) {
ok(false, "statError was called");
devicestorage_cleanup();
}
var isMac = /Mac/.test(navigator.platform);
var isWin = /Win/.test(navigator.platform);
if (isMac || isWin) {
todo(false, "stat is not available on mac or windows yet. see bug xxxx");
devicestorage_cleanup();
} else {
var storage = navigator.getDeviceStorage("testing");
ok(navigator.getDeviceStorage, "Should have getDeviceStorage");
function addError(e) {
ok(false, "addError was called : " + e.target.error.name);
devicestorage_cleanup();
}
function addSuccess(e) {
request = storage.stat();
ok(request, "Should have a non-null request");
request.onsuccess = statSuccess;
request.onerror = statError;
}
request = storage.addNamed(createRandomBlob(), "a/b");
request.onsuccess = addSuccess;
request.onerror = addError;
}
</script>
</pre>
</body>
</html>

View File

@ -19,6 +19,7 @@ include $(topsrcdir)/dom/dom-config.mk
XPIDLSRCS = \
nsIDOMDeviceStorage.idl \
nsIDOMDeviceStorageStat.idl \
nsIDOMDeviceStorageCursor.idl \
nsIDOMNavigatorDeviceStorage.idl \
nsIDOMDeviceStorageChangeEvent.idl

View File

@ -15,7 +15,7 @@ dictionary DeviceStorageEnumerationParameters
jsval since;
};
[scriptable, uuid(3dbe0137-ca73-44c5-bcde-25c297bf7c65), builtinclass]
[scriptable, uuid(36f3b16b-a398-4b19-944e-ce299b714725), builtinclass]
interface nsIDOMDeviceStorage : nsIDOMEventTarget
{
attribute nsIDOMEventListener onchange;
@ -36,4 +36,6 @@ interface nsIDOMDeviceStorage : nsIDOMEventTarget
[optional_argc, implicit_jscontext]
nsIDOMDeviceStorageCursor enumerateEditable([optional] in jsval aName, /* DeviceStorageEnumerationParameters */ [optional] in jsval options);
nsIDOMDOMRequest stat();
};

View File

@ -0,0 +1,12 @@
/* 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 "domstubs.idl"
[scriptable, uuid(b951ec07-d5db-42fc-bf4c-4eded202f7f5)]
interface nsIDOMDeviceStorageStat : nsISupports
{
readonly attribute PRUint64 totalBytes;
readonly attribute PRUint64 freeBytes;
};

View File

@ -71,6 +71,11 @@ struct FontListEntry {
PRUint8 index;
};
struct DeviceStorageStatParams
{
nsString fullpath;
};
struct DeviceStorageAddParams
{
PBlob blob;
@ -101,6 +106,7 @@ union DeviceStorageParams
DeviceStorageGetParams;
DeviceStorageDeleteParams;
DeviceStorageEnumerationParams;
DeviceStorageStatParams;
};
struct SlicedBlobConstructorParams

View File

@ -70,6 +70,7 @@ var interfaceNamesInGlobalScope =
"MediaError",
"DeviceStorageCursor",
"DeviceStorageChangeEvent",
"DeviceStorageStat",
"PageTransitionEvent",
"DataContainerEvent",
"MozCSSKeyframesRule",