Bug 871287 - Part c: Move DeviceStorage to WebIDL; r=smaug
authorMs2ger <ms2ger@gmail.com>
Sat, 01 Jun 2013 08:56:00 +0200
changeset 133646 49c962578899b2e25150351a8aa6bf16aef29ed8
parent 133645 468594dc72a1e1484e13c322f5b98534e09189ce
child 133647 8863f44132cb10679403e218646b4b73309e4fd7
push id24760
push userMs2ger@gmail.com
push dateSat, 01 Jun 2013 06:58:10 +0000
treeherdermozilla-central@b7344a8ee6f2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs871287
milestone24.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 871287 - Part c: Move DeviceStorage to WebIDL; r=smaug
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfoClasses.h
dom/bindings/Bindings.conf
dom/devicestorage/DeviceStorage.h
dom/devicestorage/nsDeviceStorage.cpp
dom/interfaces/devicestorage/nsIDOMDeviceStorage.idl
dom/webidl/DeviceStorage.webidl
dom/webidl/DummyBinding.webidl
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -194,19 +194,16 @@
 #include "nsIDOMSVGAnimatedNumber.h"
 #include "nsIDOMSVGAnimatedString.h"
 #include "nsIDOMSVGLength.h"
 #include "nsIDOMSVGNumber.h"
 
 // Storage includes
 #include "DOMStorage.h"
 
-// Device Storage
-#include "nsIDOMDeviceStorage.h"
-
 // Drag and drop
 #include "nsIDOMDataTransfer.h"
 
 // Geolocation
 #include "nsIDOMGeoPositionCoords.h"
 
 // User media
 #ifdef MOZ_MEDIA_NAVIGATOR
@@ -666,19 +663,16 @@ static nsDOMClassInfoData sClassInfoData
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(File, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(ModalContentWindow, nsWindowSH,
                            DEFAULT_SCRIPTABLE_FLAGS |
                            WINDOW_SCRIPTABLE_FLAGS)
 
-  NS_DEFINE_CLASSINFO_DATA(DeviceStorage, nsEventTargetSH,
-                           EVENTTARGET_SCRIPTABLE_FLAGS)
-
   NS_DEFINE_CLASSINFO_DATA(GeoPositionCoords, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(MozPowerManager, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(MozWakeLock, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
@@ -1772,21 +1766,16 @@ nsDOMClassInfo::Init()
   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ModalContentWindow, nsIDOMWindow)
     DOM_CLASSINFO_WINDOW_MAP_ENTRIES(nsGlobalWindow::HasIndexedDBSupport())
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMModalContentWindow)
 #ifdef MOZ_WEBSPEECH
     DOM_CLASSINFO_MAP_ENTRY(nsISpeechSynthesisGetter)
 #endif
   DOM_CLASSINFO_MAP_END
 
-  DOM_CLASSINFO_MAP_BEGIN(DeviceStorage, nsIDOMDeviceStorage)
-     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDeviceStorage)
-     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
-  DOM_CLASSINFO_MAP_END
-
   DOM_CLASSINFO_MAP_BEGIN(GeoPositionCoords, nsIDOMGeoPositionCoords)
      DOM_CLASSINFO_MAP_ENTRY(nsIDOMGeoPositionCoords)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(MozPowerManager, nsIDOMMozPowerManager)
      DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozPowerManager)
   DOM_CLASSINFO_MAP_END
 
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -110,18 +110,16 @@ DOMCI_CLASS(XPathResult)
 DOMCI_CLASS(Storage)
 
 DOMCI_CLASS(Blob)
 DOMCI_CLASS(File)
 
 // DOM modal content window class, almost identical to Window
 DOMCI_CLASS(ModalContentWindow)
 
-DOMCI_CLASS(DeviceStorage)
-
 // Geolocation
 DOMCI_CLASS(GeoPositionCoords)
 
 DOMCI_CLASS(MozPowerManager)
 DOMCI_CLASS(MozWakeLock)
 
 DOMCI_CLASS(MozSmsManager)
 DOMCI_CLASS(MozMobileMessageManager)
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -243,16 +243,21 @@ DOMInterfaces = {
 {
     'resultNotAddRefed': [ 'delayTime' ],
 }],
 
 'DeviceMotionEvent': {
     'nativeType': 'nsDOMDeviceMotionEvent',
 },
 
+'DeviceStorage': {
+    'nativeType': 'nsDOMDeviceStorage',
+    'headerFile': 'DeviceStorage.h',
+},
+
 'Document': [
 {
     'nativeType': 'nsIDocument',
     'resultNotAddRefed': [ 'implementation', 'doctype', 'documentElement',
                            'getElementById', 'adoptNode', 'defaultView',
                            'activeElement', 'currentScript',
                            'mozFullScreenElement', 'mozPointerLockElement',
                            'styleSheets', 'styleSheetSets', 'elementFromPoint',
--- a/dom/devicestorage/DeviceStorage.h
+++ b/dom/devicestorage/DeviceStorage.h
@@ -19,16 +19,18 @@
 #define DEVICESTORAGE_PICTURES   "pictures"
 #define DEVICESTORAGE_VIDEOS     "videos"
 #define DEVICESTORAGE_MUSIC      "music"
 #define DEVICESTORAGE_APPS       "apps"
 #define DEVICESTORAGE_SDCARD     "sdcard"
 
 namespace mozilla {
 namespace dom {
+class DeviceStorageEnumerationParameters;
+class DOMCursor;
 class DOMRequest;
 } // namespace dom
 } // namespace mozilla
 
 class DeviceStorageFile MOZ_FINAL
   : public nsISupports {
 public:
   nsCOMPtr<nsIFile> mFile;
@@ -134,16 +136,19 @@ class FileUpdateDispatcher MOZ_FINAL
 };
 
 class nsDOMDeviceStorage MOZ_FINAL
   : public nsDOMEventTargetHelper
   , public nsIDOMDeviceStorage
   , public nsIObserver
 {
   typedef mozilla::ErrorResult ErrorResult;
+  typedef mozilla::dom::DeviceStorageEnumerationParameters
+    EnumerationParameters;
+  typedef mozilla::dom::DOMCursor DOMCursor;
   typedef mozilla::dom::DOMRequest DOMRequest;
 public:
   typedef nsTArray<nsString> VolumeNameArray;
 
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIDOMDEVICESTORAGE
 
   NS_DECL_NSIOBSERVER
@@ -164,16 +169,68 @@ public:
                 nsTArray<nsRefPtr<nsDOMDeviceStorage> >& aStores);
   nsresult Init(nsPIDOMWindow* aWindow, const nsAString& aType,
                 const nsAString& aVolName);
 
   bool IsAvailable();
 
   void SetRootDirectoryForType(const nsAString& aType, const nsAString& aVolName);
 
+  // WebIDL
+  nsPIDOMWindow*
+  GetParentObject() const
+  {
+    return GetOwner();
+  }
+  virtual JSObject*
+  WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
+
+  IMPL_EVENT_HANDLER(change)
+
+  already_AddRefed<DOMRequest>
+  Add(nsIDOMBlob* aBlob, ErrorResult& aRv);
+  already_AddRefed<DOMRequest>
+  AddNamed(nsIDOMBlob* 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);
+
+  // Uses XPCOM GetStorageName
+
   static void CreateDeviceStorageFor(nsPIDOMWindow* aWin,
                                      const nsAString& aType,
                                      nsDOMDeviceStorage** aStore);
 
   static void CreateDeviceStoragesFor(nsPIDOMWindow* aWin,
                                       const nsAString& aType,
                                       nsTArray<nsRefPtr<nsDOMDeviceStorage> >& aStores,
                                       bool aCompositeComponent);
@@ -185,34 +242,31 @@ public:
                                      nsAString &aStorageName);
 
   static bool ParseCompositePath(const nsAString& aCompositePath,
                                  nsAString& aOutStorageName,
                                  nsAString& aOutStoragePath);
 private:
   ~nsDOMDeviceStorage();
 
-  nsresult GetInternal(const nsAString& aName,
-                       nsIDOMDOMRequest** aRetval,
-                       bool aEditable);
+  already_AddRefed<DOMRequest>
+  GetInternal(const nsAString& aPath, bool aEditable, ErrorResult& aRv);
 
   void
   GetInternal(nsPIDOMWindow* aWin, const nsAString& aPath, DOMRequest* aRequest,
               bool aEditable);
 
   void
   DeleteInternal(nsPIDOMWindow* aWin, const nsAString& aPath,
                  DOMRequest* aRequest);
 
-  nsresult EnumerateInternal(const JS::Value& aName,
-                             const JS::Value& aOptions,
-                             JSContext* aCx,
-                             uint8_t aArgc,
-                             bool aEditable,
-                             nsIDOMDOMCursor** aRetval);
+  already_AddRefed<DOMCursor>
+  EnumerateInternal(const nsAString& aName,
+                    const EnumerationParameters& aOptions, bool aEditable,
+                    ErrorResult& aRv);
 
   nsString mStorageType;
   nsCOMPtr<nsIFile> mRootDirectory;
   nsString mStorageName;
   bool mCompositeComponent;
 
   // A composite device storage object is one which front-ends for multiple
   // real storage objects. The real storage objects will each be stored in
--- a/dom/devicestorage/nsDeviceStorage.cpp
+++ b/dom/devicestorage/nsDeviceStorage.cpp
@@ -5,24 +5,25 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsDeviceStorage.h"
 
 #include "mozilla/Attributes.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/dom/ContentChild.h"
+#include "mozilla/dom/DeviceStorageBinding.h"
 #include "mozilla/dom/devicestorage/PDeviceStorageRequestChild.h"
 #include "mozilla/dom/ipc/Blob.h"
 #include "mozilla/dom/PBrowserChild.h"
 #include "mozilla/dom/PContentPermissionRequestChild.h"
 #include "mozilla/dom/PermissionMessageUtils.h"
+#include "mozilla/LazyIdleThread.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
-#include "mozilla/LazyIdleThread.h"
 
 #include "nsAutoPtr.h"
 #include "nsDOMEvent.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIFile.h"
 #include "nsIDirectoryEnumerator.h"
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsDirectoryServiceDefs.h"
@@ -2398,32 +2399,37 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(DeviceS
 
 NS_IMPL_CYCLE_COLLECTION_4(DeviceStorageRequest,
                            mRequest,
                            mWindow,
                            mBlob,
                            mDeviceStorage)
 
 
-DOMCI_DATA(DeviceStorage, nsDOMDeviceStorage)
-
 NS_INTERFACE_MAP_BEGIN(nsDOMDeviceStorage)
   NS_INTERFACE_MAP_ENTRY(nsIDOMDeviceStorage)
   NS_INTERFACE_MAP_ENTRY(nsIObserver)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(DeviceStorage)
 NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
 
 NS_IMPL_ADDREF_INHERITED(nsDOMDeviceStorage, nsDOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(nsDOMDeviceStorage, nsDOMEventTargetHelper)
 
 nsDOMDeviceStorage::nsDOMDeviceStorage()
   : mCompositeComponent(false),
     mIsWatchingFile(false)
   , mAllowedToWatchFile(false)
-{ }
+{
+  SetIsDOMBinding();
+}
+
+/* virtual */ JSObject*
+nsDOMDeviceStorage::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
+{
+  return DeviceStorageBinding::Wrap(aCx, aScope, this);
+}
 
 nsresult
 nsDOMDeviceStorage::Init(nsPIDOMWindow* aWindow, const nsAString &aType,
                          nsTArray<nsRefPtr<nsDOMDeviceStorage> > &aStores)
 {
   mStores.AppendElements(aStores);
   nsresult rv = Init(aWindow, aType, EmptyString());
   NS_ENSURE_SUCCESS(rv, rv);
@@ -2703,23 +2709,33 @@ nsDOMDeviceStorage::IsAvailable()
 {
   DeviceStorageFile dsf(mStorageType, mStorageName);
   return dsf.IsAvailable();
 }
 
 NS_IMETHODIMP
 nsDOMDeviceStorage::Add(nsIDOMBlob *aBlob, nsIDOMDOMRequest * *_retval)
 {
+  ErrorResult rv;
+  nsRefPtr<DOMRequest> request = Add(aBlob, rv);
+  request.forget(_retval);
+  return rv.ErrorCode();
+}
+
+already_AddRefed<DOMRequest>
+nsDOMDeviceStorage::Add(nsIDOMBlob* aBlob, ErrorResult& aRv)
+{
   if (!aBlob) {
-    return NS_OK;
+    return nullptr;
   }
 
   nsCOMPtr<nsIMIMEService> mimeSvc = do_GetService(NS_MIMESERVICE_CONTRACTID);
   if (!mimeSvc) {
-    return NS_ERROR_FAILURE;
+    aRv.Throw(NS_ERROR_FAILURE);
+    return nullptr;
   }
 
   // if mimeType isn't set, we will not get a correct
   // extension, and AddNamed() will fail.  This will post an
   // onerror to the requestee.
   nsString mimeType;
   aBlob->GetType(mimeType);
 
@@ -2733,113 +2749,129 @@ nsDOMDeviceStorage::Add(nsIDOMBlob *aBlo
   char buffer[32];
   NS_MakeRandomString(buffer, ArrayLength(buffer) - 1);
 
   nsAutoCString path;
   path.Assign(nsDependentCString(buffer));
   path.Append(".");
   path.Append(extension);
 
-  return AddNamed(aBlob, NS_ConvertASCIItoUTF16(path), _retval);
+  return AddNamed(aBlob, NS_ConvertASCIItoUTF16(path), aRv);
 }
 
 NS_IMETHODIMP
 nsDOMDeviceStorage::AddNamed(nsIDOMBlob *aBlob,
                              const nsAString & aPath,
                              nsIDOMDOMRequest * *_retval)
 {
+  ErrorResult rv;
+  nsRefPtr<DOMRequest> request = AddNamed(aBlob, aPath, rv);
+  request.forget(_retval);
+  return rv.ErrorCode();
+}
+
+already_AddRefed<DOMRequest>
+nsDOMDeviceStorage::AddNamed(nsIDOMBlob* aBlob, const nsAString& aPath,
+                             ErrorResult& aRv)
+{
   // if the blob is null here, bail
   if (!aBlob) {
-    return NS_OK;
+    return nullptr;
   }
 
   nsCOMPtr<nsPIDOMWindow> win = GetOwner();
   if (!win) {
-    return NS_ERROR_UNEXPECTED;
+    aRv.Throw(NS_ERROR_UNEXPECTED);
+    return nullptr;
   }
 
   DeviceStorageTypeChecker* typeChecker = DeviceStorageTypeChecker::CreateOrGet();
   if (!typeChecker) {
-    return NS_ERROR_FAILURE;
+    aRv.Throw(NS_ERROR_FAILURE);
+    return nullptr;
   }
 
   nsCOMPtr<nsIRunnable> r;
 
   if (IsComposite()) {
     nsString storagePath;
     nsRefPtr<nsDOMDeviceStorage> ds = GetStorage(aPath, storagePath);
     if (!ds) {
       nsRefPtr<DOMRequest> request = new DOMRequest(win);
-      NS_ADDREF(*_retval = request);
       r = new PostErrorEvent(request, POST_ERROR_EVENT_UNKNOWN);
       NS_DispatchToMainThread(r);
-      return NS_OK;
+      return request.forget();
     }
-    return ds->AddNamed(aBlob, storagePath, _retval);
+    return ds->AddNamed(aBlob, storagePath, aRv);
   }
 
   nsRefPtr<DOMRequest> request = new DOMRequest(win);
-  NS_ADDREF(*_retval = request);
 
   nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType,
                                                           mStorageName,
                                                           aPath);
   if (!dsf->IsSafePath()) {
     r = new PostErrorEvent(request, POST_ERROR_EVENT_PERMISSION_DENIED);
   } else if (!typeChecker->Check(mStorageType, dsf->mFile) ||
       !typeChecker->Check(mStorageType, aBlob)) {
     r = new PostErrorEvent(request, POST_ERROR_EVENT_ILLEGAL_TYPE);
   } else {
     r = new DeviceStorageRequest(DEVICE_STORAGE_REQUEST_CREATE,
                                  win, mPrincipal, dsf, request, aBlob);
   }
 
   NS_DispatchToMainThread(r);
-  return NS_OK;
+  return request.forget();
 }
 
 NS_IMETHODIMP
 nsDOMDeviceStorage::Get(const nsAString& aPath, nsIDOMDOMRequest** aRetval)
 {
-  return GetInternal(aPath, aRetval, false);
+  ErrorResult rv;
+  nsRefPtr<DOMRequest> request = Get(aPath, rv);
+  request.forget(aRetval);
+  return rv.ErrorCode();
 }
 
 NS_IMETHODIMP
 nsDOMDeviceStorage::GetEditable(const nsAString& aPath,
                                 nsIDOMDOMRequest** aRetval)
 {
-  return GetInternal(aPath, aRetval, true);
+  ErrorResult rv;
+  nsRefPtr<DOMRequest> request = GetEditable(aPath, rv);
+  request.forget(aRetval);
+  return rv.ErrorCode();
 }
 
-nsresult
-nsDOMDeviceStorage::GetInternal(const nsAString& aPath,
-                                nsIDOMDOMRequest** aRetval, bool aEditable)
+already_AddRefed<DOMRequest>
+nsDOMDeviceStorage::GetInternal(const nsAString& aPath, bool aEditable,
+                                ErrorResult& aRv)
 {
   nsCOMPtr<nsPIDOMWindow> win = GetOwner();
   if (!win) {
-    return NS_ERROR_UNEXPECTED;
+    aRv.Throw(NS_ERROR_UNEXPECTED);
+    return nullptr;
   }
 
   nsRefPtr<DOMRequest> request = new DOMRequest(win);
-  NS_ADDREF(*aRetval = request);
 
   if (IsComposite()) {
     nsString storagePath;
     nsRefPtr<nsDOMDeviceStorage> ds = GetStorage(aPath, storagePath);
     if (!ds) {
       nsCOMPtr<nsIRunnable> r =
         new PostErrorEvent(request, POST_ERROR_EVENT_UNKNOWN);
       NS_DispatchToMainThread(r);
-      return NS_OK;
+      return request.forget();
     }
     ds->GetInternal(win, storagePath, request, aEditable);
-    return NS_OK;
+    return request.forget();
   }
   GetInternal(win, aPath, request, aEditable);
-  return NS_OK;
+  return request.forget();
 }
 
 void
 nsDOMDeviceStorage::GetInternal(nsPIDOMWindow *aWin,
                                 const nsAString& aPath,
                                 DOMRequest* aRequest,
                                 bool aEditable)
 {
@@ -2856,44 +2888,53 @@ nsDOMDeviceStorage::GetInternal(nsPIDOMW
                                  aWin, mPrincipal, dsf, aRequest);
   }
   NS_DispatchToMainThread(r);
 }
 
 NS_IMETHODIMP
 nsDOMDeviceStorage::Delete(const nsAString& aPath, nsIDOMDOMRequest** aRetval)
 {
+  ErrorResult rv;
+  nsRefPtr<DOMRequest> request = Delete(aPath, rv);
+  request.forget(aRetval);
+  return rv.ErrorCode();
+}
+
+already_AddRefed<DOMRequest>
+nsDOMDeviceStorage::Delete(const nsAString& aPath, ErrorResult& aRv)
+{
   nsCOMPtr<nsPIDOMWindow> win = GetOwner();
   if (!win) {
-    return NS_ERROR_UNEXPECTED;
+    aRv.Throw(NS_ERROR_UNEXPECTED);
+    return nullptr;
   }
 
   nsRefPtr<DOMRequest> request = new DOMRequest(win);
-  NS_ADDREF(*aRetval = request);
 
   if (IsComposite()) {
     nsString storagePath;
     nsRefPtr<nsDOMDeviceStorage> ds = GetStorage(aPath, storagePath);
     if (!ds) {
       nsCOMPtr<nsIRunnable> r =
         new PostErrorEvent(request, POST_ERROR_EVENT_UNKNOWN);
       NS_DispatchToMainThread(r);
-      return NS_OK;
+      return request.forget();
     }
-    ds->DeleteInternal(win, storagePath, request.get());
-    return NS_OK;
+    ds->DeleteInternal(win, storagePath, request);
+    return request.forget();
   }
   DeleteInternal(win, aPath, request);
-  return NS_OK;
+  return request.forget();
 }
 
 void
 nsDOMDeviceStorage::DeleteInternal(nsPIDOMWindow *aWin,
                                    const nsAString& aPath,
-                                   mozilla::dom::DOMRequest* aRequest)
+                                   DOMRequest* aRequest)
 {
   nsCOMPtr<nsIRunnable> r;
   nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType,
                                                           mStorageName,
                                                           aPath);
   if (!dsf->IsSafePath()) {
     r = new PostErrorEvent(aRequest, POST_ERROR_EVENT_PERMISSION_DENIED);
   } else {
@@ -2901,80 +2942,107 @@ nsDOMDeviceStorage::DeleteInternal(nsPID
                                  aWin, mPrincipal, dsf, aRequest);
   }
   NS_DispatchToMainThread(r);
 }
 
 NS_IMETHODIMP
 nsDOMDeviceStorage::FreeSpace(nsIDOMDOMRequest** aRetval)
 {
+  ErrorResult rv;
+  nsRefPtr<DOMRequest> request = FreeSpace(rv);
+  request.forget(aRetval);
+  return rv.ErrorCode();
+}
+
+already_AddRefed<DOMRequest>
+nsDOMDeviceStorage::FreeSpace(ErrorResult& aRv)
+{
   nsCOMPtr<nsPIDOMWindow> win = GetOwner();
   if (!win) {
-    return NS_ERROR_UNEXPECTED;
+    aRv.Throw(NS_ERROR_UNEXPECTED);
+    return nullptr;
   }
 
   nsRefPtr<DOMRequest> request = new DOMRequest(win);
-  NS_ADDREF(*aRetval = request);
 
   nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType,
                                                           mStorageName);
   nsCOMPtr<nsIRunnable> r = new DeviceStorageRequest(DEVICE_STORAGE_REQUEST_FREE_SPACE,
                                                      win,
                                                      mPrincipal,
                                                      dsf,
                                                      request);
   NS_DispatchToMainThread(r);
-  return NS_OK;
+  return request.forget();
 }
 
 NS_IMETHODIMP
 nsDOMDeviceStorage::UsedSpace(nsIDOMDOMRequest** aRetval)
 {
-  DebugOnly<DeviceStorageUsedSpaceCache*> usedSpaceCache = DeviceStorageUsedSpaceCache::CreateOrGet();
-  NS_ASSERTION(usedSpaceCache, "DeviceStorageUsedSpaceCache is null");
-
+  ErrorResult rv;
+  nsRefPtr<DOMRequest> request = UsedSpace(rv);
+  request.forget(aRetval);
+  return rv.ErrorCode();
+}
+
+already_AddRefed<DOMRequest>
+nsDOMDeviceStorage::UsedSpace(ErrorResult& aRv)
+{
   nsCOMPtr<nsPIDOMWindow> win = GetOwner();
   if (!win) {
-    return NS_ERROR_UNEXPECTED;
+    aRv.Throw(NS_ERROR_UNEXPECTED);
+    return nullptr;
   }
 
+  DebugOnly<DeviceStorageUsedSpaceCache*> usedSpaceCache = DeviceStorageUsedSpaceCache::CreateOrGet();
+  NS_ASSERTION(usedSpaceCache, "DeviceStorageUsedSpaceCache is null");
+
   nsRefPtr<DOMRequest> request = new DOMRequest(win);
-  NS_ADDREF(*aRetval = request);
 
   nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType,
                                                           mStorageName);
   nsCOMPtr<nsIRunnable> r = new DeviceStorageRequest(DEVICE_STORAGE_REQUEST_USED_SPACE,
                                                      win,
                                                      mPrincipal,
                                                      dsf,
                                                      request);
   NS_DispatchToMainThread(r);
-  return NS_OK;
+  return request.forget();
 }
 
 NS_IMETHODIMP
 nsDOMDeviceStorage::Available(nsIDOMDOMRequest** aRetval)
 {
+  ErrorResult rv;
+  nsRefPtr<DOMRequest> request = Available(rv);
+  request.forget(aRetval);
+  return rv.ErrorCode();
+}
+
+already_AddRefed<DOMRequest>
+nsDOMDeviceStorage::Available(ErrorResult& aRv)
+{
   nsCOMPtr<nsPIDOMWindow> win = GetOwner();
   if (!win) {
-    return NS_ERROR_UNEXPECTED;
+    aRv.Throw(NS_ERROR_UNEXPECTED);
+    return nullptr;
   }
 
   nsRefPtr<DOMRequest> request = new DOMRequest(win);
-  NS_ADDREF(*aRetval = request);
 
   nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType,
                                                           mStorageName);
   nsCOMPtr<nsIRunnable> r = new DeviceStorageRequest(DEVICE_STORAGE_REQUEST_AVAILABLE,
                                                      win,
                                                      mPrincipal,
                                                      dsf,
                                                      request);
   NS_DispatchToMainThread(r);
-  return NS_OK;
+  return request.forget();
 }
 
 NS_IMETHODIMP
 nsDOMDeviceStorage::GetRootDirectoryForFile(const nsAString& aName, nsIFile** aRootDirectory)
 {
   nsRefPtr<nsDOMDeviceStorage> ds;
 
   if (IsComposite()) {
@@ -2991,141 +3059,94 @@ nsDOMDeviceStorage::GetRootDirectoryForF
 
 NS_IMETHODIMP
 nsDOMDeviceStorage::GetStorageName(nsAString& aStorageName)
 {
   aStorageName = mStorageName;
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsDOMDeviceStorage::Enumerate(const JS::Value & aName,
-                              const JS::Value & aOptions,
-                              JSContext* aCx,
-                              uint8_t aArgc,
-                              nsIDOMDOMCursor** aRetval)
+already_AddRefed<DOMCursor>
+nsDOMDeviceStorage::Enumerate(const nsAString& aPath,
+                              const EnumerationParameters& aOptions,
+                              ErrorResult& aRv)
 {
-  return EnumerateInternal(aName, aOptions, aCx, aArgc, false, aRetval);
-}
-
-NS_IMETHODIMP
-nsDOMDeviceStorage::EnumerateEditable(const JS::Value & aName,
-                                      const JS::Value & aOptions,
-                                      JSContext* aCx,
-                                      uint8_t aArgc,
-                                      nsIDOMDOMCursor** aRetval)
-{
-  return EnumerateInternal(aName, aOptions, aCx, aArgc, true, aRetval);
+  return EnumerateInternal(aPath, aOptions, false, aRv);
 }
 
-
-static bool
-ExtractDateFromOptions(JSContext* aCx, const JS::Value& aOptions, PRTime* aTime)
+already_AddRefed<DOMCursor>
+nsDOMDeviceStorage::EnumerateEditable(const nsAString& aPath,
+                                      const EnumerationParameters& aOptions,
+                                      ErrorResult& aRv)
 {
-  JS::Rooted<JS::Value> options(aCx, aOptions);
-  RootedDictionary<DeviceStorageEnumerationParameters> params(aCx);
-  if (!params.Init(aCx, options)) {
-    return false;
-  }
-  if (params.mSince.WasPassed() && !params.mSince.Value().IsUndefined()) {
-    *aTime = params.mSince.Value().TimeStamp();
-  } else {
-    *aTime = 0;
-  }
-  return true;
+  return EnumerateInternal(aPath, aOptions, true, aRv);
 }
 
-nsresult
-nsDOMDeviceStorage::EnumerateInternal(const JS::Value & aName,
-                                      const JS::Value & aOptions,
-                                      JSContext* aCx,
-                                      uint8_t aArgc,
-                                      bool aEditable,
-                                      nsIDOMDOMCursor** aRetval)
+
+already_AddRefed<DOMCursor>
+nsDOMDeviceStorage::EnumerateInternal(const nsAString& aPath,
+                                      const EnumerationParameters& aOptions,
+                                      bool aEditable, ErrorResult& aRv)
 {
   nsCOMPtr<nsPIDOMWindow> win = GetOwner();
   if (!win) {
-    return NS_ERROR_UNEXPECTED;
+    aRv.Throw(NS_ERROR_UNEXPECTED);
+    return nullptr;
   }
 
   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
-      if (!ExtractDateFromOptions(aCx, aName, &since)) {
-        return NS_ERROR_FAILURE;
-      }
-    } else {
-      return NS_ERROR_FAILURE;
-    }
-
-    if (aArgc == 2 && !aOptions.isObject()) {
-      return NS_ERROR_FAILURE;
-    }
-    if (!ExtractDateFromOptions(aCx, aOptions, &since)) {
-      return NS_ERROR_FAILURE;
-    }
+  if (aOptions.mSince.WasPassed() && !aOptions.mSince.Value().IsUndefined()) {
+    since = PRTime(aOptions.mSince.Value().TimeStamp());
   }
 
   nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType,
                                                           mStorageName,
-                                                          path,
+                                                          aPath,
                                                           EmptyString());
   dsf->SetEditable(aEditable);
 
   nsRefPtr<nsDOMDeviceStorageCursor> cursor = new nsDOMDeviceStorageCursor(win, mPrincipal,
                                                                            dsf, since);
   nsRefPtr<DeviceStorageCursorRequest> r = new DeviceStorageCursorRequest(cursor);
 
-  NS_ADDREF(*aRetval = cursor);
-
   if (mozilla::Preferences::GetBool("device.storage.prompt.testing", false)) {
     r->Allow();
-    return NS_OK;
+    return cursor.forget();
   }
 
   if (XRE_GetProcessType() == GeckoProcessType_Content) {
     // because owner implements nsITabChild, we can assume that it is
     // the one and only TabChild.
     TabChild* child = GetTabChildFrom(win->GetDocShell());
     if (!child) {
-      return NS_OK;
+      return cursor.forget();
     }
 
     // Retain a reference so the object isn't deleted without IPDL's knowledge.
     // Corresponding release occurs in DeallocPContentPermissionRequest.
     r->AddRef();
 
     nsCString type;
-    nsresult rv = DeviceStorageTypeChecker::GetPermissionForType(mStorageType, type);
-    if (NS_FAILED(rv)) {
-      return rv;
+    aRv = DeviceStorageTypeChecker::GetPermissionForType(mStorageType, type);
+    if (aRv.Failed()) {
+      return nullptr;
     }
     child->SendPContentPermissionRequestConstructor(r, type, NS_LITERAL_CSTRING("read"), IPC::Principal(mPrincipal));
 
     r->Sendprompt();
 
-    return NS_OK;
+    return cursor.forget();
   }
 
   nsCOMPtr<nsIContentPermissionPrompt> prompt = do_CreateInstance(NS_CONTENT_PERMISSION_PROMPT_CONTRACTID);
   if (prompt) {
     prompt->Prompt(r);
   }
 
-  return NS_OK;
+  return cursor.forget();
 }
 
 #ifdef MOZ_WIDGET_GONK
 void
 nsDOMDeviceStorage::DispatchMountChangeEvent(nsAString& aVolumeName,
                                              nsAString& aVolumeStatus)
 {
   nsCOMPtr<nsIDOMEvent> event;
--- a/dom/interfaces/devicestorage/nsIDOMDeviceStorage.idl
+++ b/dom/interfaces/devicestorage/nsIDOMDeviceStorage.idl
@@ -6,37 +6,29 @@
 #include "nsIDOMEventTarget.idl"
 interface nsIDOMBlob;
 interface nsIDOMDOMRequest;
 interface nsIDOMDOMCursor;
 interface nsIDOMDeviceStorageChangeEvent;
 interface nsIDOMEventListener;
 interface nsIFile;
 
-[scriptable, uuid(446b5221-e2ca-4ebe-873b-e1f06cfdafdf), builtinclass]
+[scriptable, uuid(7cef14d4-d767-4da7-a18e-32c5e009a8e4), builtinclass]
 interface nsIDOMDeviceStorage : nsIDOMEventTarget
 {
     [implicit_jscontext] attribute jsval onchange;
     nsIDOMDOMRequest add(in nsIDOMBlob aBlob);
     nsIDOMDOMRequest addNamed(in nsIDOMBlob aBlob, in DOMString aName);
 
     nsIDOMDOMRequest get([Null(Stringify)] in DOMString aName);
     nsIDOMDOMRequest getEditable([Null(Stringify)] in DOMString aName);
     nsIDOMDOMRequest delete([Null(Stringify)] in DOMString aName);
 
-    [optional_argc, implicit_jscontext]
-    nsIDOMDOMCursor enumerate([optional] in jsval aName, /* DeviceStorageEnumerationParameters */ [optional] in jsval options);
-
-    [optional_argc, implicit_jscontext]
-    nsIDOMDOMCursor enumerateEditable([optional] in jsval aName, /* DeviceStorageEnumerationParameters */ [optional] in jsval options);
-
     nsIDOMDOMRequest freeSpace();
-
     nsIDOMDOMRequest usedSpace();
-
     nsIDOMDOMRequest available();
 
     // Note that the storageName is just a name (like sdcard), and doesn't
     // include any path information.
     readonly attribute DOMString storageName;
 
     [noscript] nsIFile getRootDirectoryForFile(in DOMString aName);
 };
--- a/dom/webidl/DeviceStorage.webidl
+++ b/dom/webidl/DeviceStorage.webidl
@@ -1,12 +1,47 @@
 /* -*- 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/.
- */
+ * 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;
 };
 
-// If we start using DeviceStorageEnumerationParameters here, remove
-// it from DummyBinding.
+interface DeviceStorage : EventTarget {
+  [SetterThrows]
+  attribute EventHandler onchange;
+
+  [Throws]
+  DOMRequest? add(Blob? aBlob);
+  [Throws]
+  DOMRequest? addNamed(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();
+
+  // Note that the storageName is just a name (like sdcard), and doesn't
+  // include any path information.
+  readonly attribute DOMString storageName;
+};
--- a/dom/webidl/DummyBinding.webidl
+++ b/dom/webidl/DummyBinding.webidl
@@ -15,17 +15,16 @@ interface DummyInterface {
   InspectorRGBTriple rgbTriple();
   Function getFunction();
   void funcSocketsDict(optional SocketsDict arg);
   void funcHttpConnDict(optional HttpConnDict arg);
   void funcWebSocketDict(optional WebSocketDict arg);
   void funcDNSCacheDict(optional DNSCacheDict arg);
   void frameRequestCallback(FrameRequestCallback arg);
   void idbObjectStoreParams(optional IDBObjectStoreParameters arg);
-  void DeviceStorageEnumerationParameters(optional DeviceStorageEnumerationParameters arg);
   void CameraPictureOptions(optional CameraPictureOptions arg);
   void MmsParameters(optional MmsParameters arg);
   void MmsAttachment(optional MmsAttachment arg);
 };
 
 interface DummyInterfaceWorkers {
   BlobPropertyBag blobBag();
 };