From 6a1067553963d4cbc2c0e7c6762b136a70f487ab Mon Sep 17 00:00:00 2001 From: Doug Turner Date: Fri, 8 Jun 2012 20:15:04 -0700 Subject: [PATCH] Bug 758273 - Device Storage - enumeration option to filter based on last modification date. r=smaug --- dom/devicestorage/nsDeviceStorage.cpp | 103 ++++++++++++---- dom/devicestorage/nsDeviceStorage.h | 19 ++- .../devicestorage/nsIDOMDeviceStorage.idl | 13 +- dom/tests/mochitest/devicestorage/Makefile.in | 2 + .../devicestorage/devicestorage_common.js | 11 ++ .../devicestorage/test_enumerate.html | 11 -- .../devicestorage/test_enumerateOptions.html | 81 +++++++++++++ .../test_lastModificationFilter.html | 111 ++++++++++++++++++ js/xpconnect/src/dictionary_helper_gen.conf | 1 + 9 files changed, 314 insertions(+), 38 deletions(-) create mode 100644 dom/tests/mochitest/devicestorage/test_enumerateOptions.html create mode 100644 dom/tests/mochitest/devicestorage/test_lastModificationFilter.html diff --git a/dom/devicestorage/nsDeviceStorage.cpp b/dom/devicestorage/nsDeviceStorage.cpp index fe02bda462d4..f6c9e84ac7fd 100644 --- a/dom/devicestorage/nsDeviceStorage.cpp +++ b/dom/devicestorage/nsDeviceStorage.cpp @@ -16,6 +16,7 @@ #include "nsIPrincipal.h" #include "mozilla/Preferences.h" #include "nsJSUtils.h" +#include "DictionaryHelpers.h" using namespace mozilla::dom; @@ -307,7 +308,8 @@ public: nsDOMDeviceStorageCursor(nsIDOMWindow* aWindow, nsIURI* aURI, DeviceStorageFile* aFile, - bool aEditable); + bool aEditable, + PRUint64 aSince); private: ~nsDOMDeviceStorageCursor(); @@ -319,6 +321,7 @@ protected: nsRefPtr mFile; nsCOMPtr mURI; bool mEditable; + PRUint64 mSince; // to access mFiles friend class InitCursorEvent; @@ -508,6 +511,15 @@ public: nsCOMPtr f; while (NS_SUCCEEDED(files->GetNextFile(getter_AddRefs(f))) && f) { + nsDOMDeviceStorageCursor* cursor = static_cast(mRequest.get()); + + PRInt64 msecs; + f->GetLastModifiedTime(&msecs); + + if (msecs < (PRInt64) cursor->mSince) { + continue; + } + bool isDir; f->IsDirectory(&isDir); @@ -534,7 +546,6 @@ public: collectFiles(dsf); } else if (isFile) { - nsDOMDeviceStorageCursor* cursor = static_cast(mRequest.get()); cursor->mFiles.AppendElement(dsf); } } @@ -561,12 +572,14 @@ NS_IMPL_RELEASE_INHERITED(nsDOMDeviceStorageCursor, DOMRequest) nsDOMDeviceStorageCursor::nsDOMDeviceStorageCursor(nsIDOMWindow* aWindow, nsIURI* aURI, DeviceStorageFile* aFile, - bool aEditable) + bool aEditable, + PRUint64 aSince) : DOMRequest(aWindow) , mOkToCallContinue(false) , mFile(aFile) , mURI(aURI) , mEditable(aEditable) + , mSince(aSince) { } @@ -1153,7 +1166,7 @@ nsDOMDeviceStorage::AddNamed(nsIDOMBlob *aBlob, } NS_IMETHODIMP -nsDOMDeviceStorage::Get(const JS::Value & aPath, +nsDOMDeviceStorage::Get(const JS::Value& aPath, JSContext* aCx, nsIDOMDOMRequest * *_retval NS_OUTPARAM) { @@ -1161,7 +1174,7 @@ nsDOMDeviceStorage::Get(const JS::Value & aPath, } NS_IMETHODIMP -nsDOMDeviceStorage::GetEditable(const JS::Value & aPath, +nsDOMDeviceStorage::GetEditable(const JS::Value& aPath, JSContext* aCx, nsIDOMDOMRequest * *_retval NS_OUTPARAM) { @@ -1169,7 +1182,7 @@ nsDOMDeviceStorage::GetEditable(const JS::Value & aPath, } nsresult -nsDOMDeviceStorage::GetInternal(const JS::Value & aPath, +nsDOMDeviceStorage::GetInternal(const JS::Value& aPath, JSContext* aCx, nsIDOMDOMRequest * *_retval NS_OUTPARAM, bool aEditable) @@ -1208,7 +1221,7 @@ nsDOMDeviceStorage::GetInternal(const JS::Value & aPath, } NS_IMETHODIMP -nsDOMDeviceStorage::Delete(const JS::Value & aPath, JSContext* aCx, nsIDOMDOMRequest * *_retval NS_OUTPARAM) +nsDOMDeviceStorage::Delete(const JS::Value& aPath, JSContext* aCx, nsIDOMDOMRequest * *_retval NS_OUTPARAM) { nsCOMPtr r; @@ -1243,35 +1256,85 @@ nsDOMDeviceStorage::Delete(const JS::Value & aPath, JSContext* aCx, nsIDOMDOMReq } NS_IMETHODIMP -nsDOMDeviceStorage::Enumerate(const nsAString & aPath, - nsIDOMDeviceStorageCursor * *_retval NS_OUTPARAM) +nsDOMDeviceStorage::Enumerate(const JS::Value& aName, + const JS::Value& aOptions, + JSContext* aCx, + PRUint8 aArgc, + nsIDOMDeviceStorageCursor** aRetval) { - return EnumerateInternal(aPath, _retval, false); + return EnumerateInternal(aName, aOptions, aCx, aArgc, false, aRetval); } NS_IMETHODIMP -nsDOMDeviceStorage::EnumerateEditable(const nsAString & aPath, - nsIDOMDeviceStorageCursor * *_retval NS_OUTPARAM) +nsDOMDeviceStorage::EnumerateEditable(const JS::Value& aName, + const JS::Value& aOptions, + JSContext* aCx, + PRUint8 aArgc, + nsIDOMDeviceStorageCursor** aRetval) { - return EnumerateInternal(aPath, _retval, true); + return EnumerateInternal(aName, aOptions, aCx, aArgc, true, aRetval); +} + + +static PRTime +ExtractDateFromOptions(JSContext* aCx, const JS::Value& aOptions) +{ + PRTime result = 0; + DeviceStorageEnumerationParameters params; + if (!JSVAL_IS_VOID(aOptions) && !aOptions.isNull()) { + nsresult rv = params.Init(aCx, &aOptions); + if (NS_SUCCEEDED(rv) && !JSVAL_IS_VOID(params.since) && !params.since.isNull() && params.since.isObject()) { + JSObject* obj = JSVAL_TO_OBJECT(params.since); + if (JS_ObjectIsDate(aCx, obj) && js_DateIsValid(aCx, obj)) { + result = js_DateGetMsecSinceEpoch(aCx, obj); + } + } + } + return result; } nsresult -nsDOMDeviceStorage::EnumerateInternal(const nsAString & aPath, - nsIDOMDeviceStorageCursor * *_retval NS_OUTPARAM, - bool aEditable) +nsDOMDeviceStorage::EnumerateInternal(const JS::Value& aName, + const JS::Value& aOptions, + JSContext* aCx, + PRUint8 aArgc, + bool aEditable, + nsIDOMDeviceStorageCursor** aRetval) { nsCOMPtr win = do_QueryReferent(mOwner); if (!win) return NS_ERROR_UNEXPECTED; - nsRefPtr dsf = new DeviceStorageFile(mFile, aPath); - - nsRefPtr cursor = new nsDOMDeviceStorageCursor(win, mURI, dsf, aEditable); - NS_ADDREF(*_retval = cursor); + PRTime since = 0; + nsString path; + path.SetIsVoid(true); + if (aArgc > 0) { + // inspect the first value to see if it is a string + if (JSVAL_IS_STRING(aName)) { + JSString* jsstr = JS_ValueToString(aCx, aName); + nsDependentJSString jspath; + jspath.init(aCx, jsstr); + path.Assign(jspath); + } else if (!JSVAL_IS_PRIMITIVE(aName)) { + // it also might be an options object + since = ExtractDateFromOptions(aCx, aName); + } else { + return NS_ERROR_FAILURE; + } + + if (aArgc == 2 && (JSVAL_IS_VOID(aOptions) || aOptions.isNull() || !aOptions.isObject())) { + return NS_ERROR_FAILURE; + } + since = ExtractDateFromOptions(aCx, aOptions); + } + + nsRefPtr dsf = new DeviceStorageFile(mFile, path); + nsRefPtr cursor = new nsDOMDeviceStorageCursor(win, mURI, dsf, aEditable, since); nsRefPtr r = new DeviceStorageCursorRequest(cursor); + NS_ADDREF(*aRetval = cursor); + if (mozilla::Preferences::GetBool("device.storage.prompt.testing", false)) { r->Allow(); return NS_OK; diff --git a/dom/devicestorage/nsDeviceStorage.h b/dom/devicestorage/nsDeviceStorage.h index d237a5d96b65..0434ae30ddbc 100644 --- a/dom/devicestorage/nsDeviceStorage.h +++ b/dom/devicestorage/nsDeviceStorage.h @@ -28,18 +28,29 @@ public: nsDOMDeviceStorage(); - nsresult Init(nsPIDOMWindow* aWindow, const nsAString &aType, const PRInt32 aIndex); + nsresult Init(nsPIDOMWindow* aWindow, const nsAString&aType, const PRInt32 aIndex); PRInt32 SetRootFileForType(const nsAString& aType, const PRInt32 aIndex); - static void CreateDeviceStoragesFor(nsPIDOMWindow* aWin, const nsAString &aType, nsIVariant** _retval); + static void CreateDeviceStoragesFor(nsPIDOMWindow* aWin, + const nsAString& aType, + nsIVariant** aRetval); private: ~nsDOMDeviceStorage(); - nsresult GetInternal(const JS::Value & aName, JSContext* aCx, nsIDOMDOMRequest * *_retval NS_OUTPARAM, bool aEditable); - nsresult EnumerateInternal(const nsAString & aName, nsIDOMDeviceStorageCursor * *_retval NS_OUTPARAM, bool aEditable); + nsresult GetInternal(const JS::Value& aName, + JSContext* aCx, + nsIDOMDOMRequest** aRetval, + bool aEditable); + + nsresult EnumerateInternal(const JS::Value& aName, + const JS::Value& aOptions, + JSContext* aCx, + PRUint8 aArgc, + bool aEditable, + nsIDOMDeviceStorageCursor** aRetval); PRInt32 mStorageType; nsCOMPtr mFile; diff --git a/dom/interfaces/devicestorage/nsIDOMDeviceStorage.idl b/dom/interfaces/devicestorage/nsIDOMDeviceStorage.idl index 5b24231689c5..b85213d9c451 100644 --- a/dom/interfaces/devicestorage/nsIDOMDeviceStorage.idl +++ b/dom/interfaces/devicestorage/nsIDOMDeviceStorage.idl @@ -7,7 +7,12 @@ interface nsIDOMBlob; interface nsIDOMDOMRequest; interface nsIDOMDeviceStorageCursor; -[scriptable, uuid(05C0D0C8-D698-4CCD-899C-7198A33BD7EC)] +dictionary DeviceStorageEnumerationParameters +{ + jsval since; +}; + +[scriptable, uuid(6cdf3d8e-4a9f-4582-9d99-769bf9922cfb)] interface nsIDOMDeviceStorage : nsISupports { /* @@ -28,7 +33,9 @@ interface nsIDOMDeviceStorage : nsISupports [implicit_jscontext] nsIDOMDOMRequest delete(in jsval aName); - nsIDOMDeviceStorageCursor enumerate([optional] in DOMString directory); + [optional_argc, implicit_jscontext] + nsIDOMDeviceStorageCursor enumerate([optional] in jsval aName, /* DeviceStorageEnumerationParameters */ [optional] in jsval options); - nsIDOMDeviceStorageCursor enumerateEditable([optional] in DOMString directory); + [optional_argc, implicit_jscontext] + nsIDOMDeviceStorageCursor enumerateEditable([optional] in jsval aName, /* DeviceStorageEnumerationParameters */ [optional] in jsval options); }; diff --git a/dom/tests/mochitest/devicestorage/Makefile.in b/dom/tests/mochitest/devicestorage/Makefile.in index 575bbbcc3e6a..844f0f1e0621 100644 --- a/dom/tests/mochitest/devicestorage/Makefile.in +++ b/dom/tests/mochitest/devicestorage/Makefile.in @@ -19,6 +19,8 @@ _TEST_FILES = \ test_enumerateMultipleContinue.html \ test_overwrite.html \ test_dotdot.html \ + test_enumerateOptions.html \ + test_lastModificationFilter.html \ devicestorage_common.js \ $(NULL) diff --git a/dom/tests/mochitest/devicestorage/devicestorage_common.js b/dom/tests/mochitest/devicestorage/devicestorage_common.js index 8aa986b347e2..629dc41ca8e8 100644 --- a/dom/tests/mochitest/devicestorage/devicestorage_common.js +++ b/dom/tests/mochitest/devicestorage/devicestorage_common.js @@ -5,6 +5,13 @@ var oldVal = false; +// 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); +}; + function devicestorage_setup() { SimpleTest.waitForExplicitFinish(); try { @@ -46,3 +53,7 @@ function randomFilename(l) { return result; } +function reportErrorAndQuit(e) { + ok(false, "handleError was called : " + e.target.error.name); + devicestorage_cleanup(); +} diff --git a/dom/tests/mochitest/devicestorage/test_enumerate.html b/dom/tests/mochitest/devicestorage/test_enumerate.html index b9af36954e56..d328f7a8faf5 100644 --- a/dom/tests/mochitest/devicestorage/test_enumerate.html +++ b/dom/tests/mochitest/devicestorage/test_enumerate.html @@ -22,27 +22,16 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=717103
 
+  
+
+
+
+
+Mozilla Bug 717103
+

+ +
+
+
+ + + diff --git a/dom/tests/mochitest/devicestorage/test_lastModificationFilter.html b/dom/tests/mochitest/devicestorage/test_lastModificationFilter.html new file mode 100644 index 000000000000..484bafaa4267 --- /dev/null +++ b/dom/tests/mochitest/devicestorage/test_lastModificationFilter.html @@ -0,0 +1,111 @@ + + + + + Test for the device storage API + + + + + + +Mozilla Bug 717103 +

+ +
+
+
+ + + diff --git a/js/xpconnect/src/dictionary_helper_gen.conf b/js/xpconnect/src/dictionary_helper_gen.conf index 88438da4427d..20a146458d0c 100644 --- a/js/xpconnect/src/dictionary_helper_gen.conf +++ b/js/xpconnect/src/dictionary_helper_gen.conf @@ -24,6 +24,7 @@ dictionaries = [ [ 'DeviceLightEventInit', 'nsIDOMDeviceLightEvent.idl' ], [ 'DOMFileMetadataParameters', 'nsIDOMLockedFile.idl' ], [ 'XMLHttpRequestParameters', 'nsIXMLHttpRequest.idl' ], + [ 'DeviceStorageEnumerationParameters', 'nsIDOMDeviceStorage.idl' ] ] # include file names