Merge b2g-inbound to m-c FIREFOX_AURORA_25_BASE
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Mon, 05 Aug 2013 11:22:48 +0200
changeset 141367 ad0ae007aa9e03cd74e9005cd6652e544139b3b5
parent 141355 54434a926c5f2f8ff7506499a400ebb56d7ee2a6 (current diff)
parent 141366 87ae4544f967a29ebce7a13d7546cfda574285ee (diff)
child 141368 ecaf1c5a310c37a7123f0da82b3becd50cc8068f
child 141373 8fd10790fdf146280b3cb8997c70cfd5e35c2339
child 141398 7bbaba1b712f689d37217b2c7eea02520c3e8315
child 141417 8747aae67a8a13738dc74cbcc4345b425ff95cff
child 155631 12b32f5dcd530c5865e92a1c1edb3e8b028caa65
push id25055
push usercbook@mozilla.com
push dateMon, 05 Aug 2013 09:23:21 +0000
treeherdermozilla-central@ad0ae007aa9e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone25.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
Merge b2g-inbound to m-c
dom/base/Navigator.cpp
dom/bindings/Bindings.conf
dom/webidl/WebIDL.mk
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,4 +1,4 @@
 {
-    "revision": "7669b3265def0eed0473acd938897704007afaf3", 
+    "revision": "5e7a8bbe525c0a43852770665ce9498fdb93ea81", 
     "repo_path": "/integration/gaia-central"
 }
--- a/dom/base/Crypto.cpp
+++ b/dom/base/Crypto.cpp
@@ -1,198 +1,147 @@
 /* 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 "Crypto.h"
-#include "nsIDOMClassInfo.h"
 #include "DOMError.h"
 #include "nsString.h"
-#include "jsapi.h"
 #include "jsfriendapi.h"
 #include "nsIServiceManager.h"
 #include "nsCOMPtr.h"
 #include "nsIRandomGenerator.h"
 
 #include "mozilla/dom/ContentChild.h"
+#include "mozilla/dom/CryptoBinding.h"
 
 using mozilla::dom::ContentChild;
 
 using namespace js::ArrayBufferView;
 
 namespace mozilla {
 namespace dom {
 
-NS_INTERFACE_MAP_BEGIN(Crypto)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Crypto)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY(nsIDOMCrypto)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Crypto)
 NS_INTERFACE_MAP_END
 
-NS_IMPL_ADDREF(Crypto)
-NS_IMPL_RELEASE(Crypto)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(Crypto)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(Crypto)
+
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(Crypto, mWindow)
 
 Crypto::Crypto()
 {
   MOZ_COUNT_CTOR(Crypto);
+  SetIsDOMBinding();
 }
 
 Crypto::~Crypto()
 {
   MOZ_COUNT_DTOR(Crypto);
 }
 
-NS_IMETHODIMP
-Crypto::GetRandomValues(const JS::Value& aData, JSContext *cx,
-                        JS::Value* _retval)
+void
+Crypto::Init(nsIDOMWindow* aWindow)
+{
+  mWindow = do_QueryInterface(aWindow);
+  MOZ_ASSERT(mWindow);
+}
+
+/* virtual */ JSObject*
+Crypto::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
+{
+  return CryptoBinding::Wrap(aCx, aScope, this);
+}
+
+JSObject *
+Crypto::GetRandomValues(JSContext* aCx, ArrayBufferView& aArray, ErrorResult& aRv)
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Called on the wrong thread");
 
-  // Make sure this is a JavaScript object
-  if (!aData.isObject()) {
-    return NS_ERROR_DOM_NOT_OBJECT_ERR;
-  }
-
-  JS::Rooted<JSObject*> view(cx, &aData.toObject());
-
-  // Make sure this object is an ArrayBufferView
-  if (!JS_IsTypedArrayObject(view)) {
-    return NS_ERROR_DOM_TYPE_MISMATCH_ERR;
-  }
+  JS::Rooted<JSObject*> view(aCx, aArray.Obj());
 
   // Throw if the wrong type of ArrayBufferView is passed in
   // (Part of the Web Crypto API spec)
   switch (JS_GetArrayBufferViewType(view)) {
     case TYPE_INT8:
     case TYPE_UINT8:
     case TYPE_UINT8_CLAMPED:
     case TYPE_INT16:
     case TYPE_UINT16:
     case TYPE_INT32:
     case TYPE_UINT32:
       break;
     default:
-      return NS_ERROR_DOM_TYPE_MISMATCH_ERR;
+      aRv.Throw(NS_ERROR_DOM_TYPE_MISMATCH_ERR);
+      return nullptr;
   }
 
-  uint32_t dataLen = JS_GetTypedArrayByteLength(view);
-
+  uint32_t dataLen = aArray.Length();
   if (dataLen == 0) {
     NS_WARNING("ArrayBufferView length is 0, cannot continue");
-    return NS_OK;
+    return view;
   } else if (dataLen > 65536) {
-    return NS_ERROR_DOM_QUOTA_EXCEEDED_ERR;
+    aRv.Throw(NS_ERROR_DOM_QUOTA_EXCEEDED_ERR);
+    return nullptr;
   }
 
-  void *dataptr = JS_GetArrayBufferViewData(view);
-  NS_ENSURE_TRUE(dataptr, NS_ERROR_FAILURE);
-  unsigned char* data =
-    static_cast<unsigned char*>(dataptr);
+  uint8_t* data = aArray.Data();
 
   if (XRE_GetProcessType() != GeckoProcessType_Default) {
     InfallibleTArray<uint8_t> randomValues;
     // Tell the parent process to generate random values via PContent
     ContentChild* cc = ContentChild::GetSingleton();
     if (!cc->SendGetRandomValues(dataLen, &randomValues)) {
-      return NS_ERROR_FAILURE;
+      aRv.Throw(NS_ERROR_FAILURE);
+      return nullptr;
     }
     NS_ASSERTION(dataLen == randomValues.Length(),
                  "Invalid length returned from parent process!");
     memcpy(data, randomValues.Elements(), dataLen);
   } else {
     uint8_t *buf = GetRandomValues(dataLen);
 
     if (!buf) {
-      return NS_ERROR_FAILURE;
+      aRv.Throw(NS_ERROR_FAILURE);
+      return nullptr;
     }
 
     memcpy(data, buf, dataLen);
     NS_Free(buf);
   }
 
-  *_retval = OBJECT_TO_JSVAL(view);
-
-  return NS_OK;
+  return view;
 }
 
 #ifndef MOZ_DISABLE_CRYPTOLEGACY
 // Stub out the legacy nsIDOMCrypto methods. The actual
 // implementations are in security/manager/ssl/src/nsCrypto.{cpp,h}
 
 NS_IMETHODIMP
-Crypto::GetVersion(nsAString & aVersion)
-{
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
 Crypto::GetEnableSmartCardEvents(bool *aEnableSmartCardEvents)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
 Crypto::SetEnableSmartCardEvents(bool aEnableSmartCardEvents)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
-
-NS_IMETHODIMP
-Crypto::GenerateCRMFRequest(nsIDOMCRMFObject * *_retval)
-{
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-Crypto::ImportUserCertificates(const nsAString & nickname,
-                               const nsAString & cmmfResponse,
-                               bool doForcedBackup, nsAString & _retval)
-{
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-Crypto::PopChallengeResponse(const nsAString & challenge,
-                             nsAString & _retval)
-{
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-Crypto::Random(int32_t numBytes, nsAString & _retval)
-{
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-Crypto::SignText(const nsAString & stringToSign, const nsAString & caOption,
-                 nsAString & _retval)
-{
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-Crypto::Logout()
-{
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-Crypto::DisableRightClick()
-{
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
 #endif
 
-uint8_t*
+/* static */ uint8_t*
 Crypto::GetRandomValues(uint32_t aLength)
 {
   nsCOMPtr<nsIRandomGenerator> randomGenerator;
   nsresult rv;
-  randomGenerator =
-    do_GetService("@mozilla.org/security/random-generator;1");
+  randomGenerator = do_GetService("@mozilla.org/security/random-generator;1");
   NS_ENSURE_TRUE(randomGenerator, nullptr);
 
   uint8_t* buf;
   rv = randomGenerator->GenerateRandomBytes(aLength, &buf);
 
   NS_ENSURE_SUCCESS(rv, nullptr);
 
   return buf;
--- a/dom/base/Crypto.h
+++ b/dom/base/Crypto.h
@@ -3,33 +3,97 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 #ifndef mozilla_dom_Crypto_h
 #define mozilla_dom_Crypto_h
 
 #ifdef MOZ_DISABLE_CRYPTOLEGACY
 #include "nsIDOMCrypto.h"
 #else
 #include "nsIDOMCryptoLegacy.h"
+#include "nsIDOMCRMFObject.h"
 #endif
 
+#include "nsPIDOMWindow.h"
+#include "nsWrapperCache.h"
+#include "mozilla/dom/BindingDeclarations.h"
+#include "mozilla/dom/TypedArray.h"
 #define NS_DOMCRYPTO_CID \
   {0x929d9320, 0x251e, 0x11d4, { 0x8a, 0x7c, 0x00, 0x60, 0x08, 0xc8, 0x44, 0xc3} }
 
 namespace mozilla {
 namespace dom {
 
-class Crypto : public nsIDOMCrypto
+class Crypto : public nsIDOMCrypto,
+               public nsWrapperCache
 {
 public:
   Crypto();
   virtual ~Crypto();
 
-  NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMCRYPTO
 
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Crypto)
+
+  JSObject *
+  GetRandomValues(JSContext* aCx, ArrayBufferView& aArray, ErrorResult& aRv);
+
+#ifndef MOZ_DISABLE_CRYPTOLEGACY
+  virtual bool EnableSmartCardEvents() = 0;
+  virtual void SetEnableSmartCardEvents(bool aEnable, ErrorResult& aRv) = 0;
+
+  virtual void GetVersion(nsString& aVersion) = 0;
+
+  virtual already_AddRefed<nsIDOMCRMFObject>
+  GenerateCRMFRequest(JSContext* aContext,
+                      const nsCString& aReqDN,
+                      const nsCString& aRegToken,
+                      const nsCString& aAuthenticator,
+                      const nsCString& aEaCert,
+                      const nsCString& aJsCallback,
+                      const Sequence<JS::Value>& aArgs,
+                      ErrorResult& aRv) = 0;
+
+  virtual void ImportUserCertificates(const nsAString& aNickname,
+                                      const nsAString& aCmmfResponse,
+                                      bool aDoForcedBackup,
+                                      nsAString& aReturn,
+                                      ErrorResult& aRv) = 0;
+
+  virtual void PopChallengeResponse(const nsAString& aChallenge,
+                                    nsAString& aReturn,
+                                    ErrorResult& aRv) = 0;
+
+  virtual void Random(int32_t aNumBytes, nsAString& aReturn, ErrorResult& aRv) = 0;
+
+  virtual void SignText(JSContext* aContext,
+                        const nsAString& aStringToSign,
+                        const nsAString& aCaOption,
+                        const Sequence<nsCString>& aArgs,
+                        nsAString& aReturn) = 0;
+
+  virtual void Logout(ErrorResult& aRv) = 0;
+
+  virtual void DisableRightClick(ErrorResult& aRv) = 0;
+#endif
+
+  // WebIDL
+
+  nsPIDOMWindow*
+  GetParentObject() const
+  {
+    return mWindow;
+  }
+
+  virtual JSObject*
+  WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
+
   static uint8_t*
   GetRandomValues(uint32_t aLength);
+
+private:
+  nsCOMPtr<nsPIDOMWindow> mWindow;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_Crypto_h
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -950,17 +950,17 @@ Navigator::GetDeviceStorages(const nsASt
                              nsTArray<nsRefPtr<nsDOMDeviceStorage> >& aStores,
                              ErrorResult& aRv)
 {
   if (!mWindow || !mWindow->GetOuterWindow() || !mWindow->GetDocShell()) {
     aRv.Throw(NS_ERROR_FAILURE);
     return;
   }
 
-  nsDOMDeviceStorage::CreateDeviceStoragesFor(mWindow, aType, aStores, false);
+  nsDOMDeviceStorage::CreateDeviceStoragesFor(mWindow, aType, aStores);
 
   mDeviceStorageStores.AppendElements(aStores);
 }
 
 Geolocation*
 Navigator::GetGeolocation(ErrorResult& aRv)
 {
   if (mGeolocation) {
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -155,19 +155,16 @@
 #include "nsIDOMMozCSSKeyframesRule.h"
 #include "nsIDOMCSSPageRule.h"
 #include "nsIDOMCSSStyleRule.h"
 #include "nsIDOMCSSStyleSheet.h"
 #include "nsIDOMDeviceMotionEvent.h" //nsIDOMDeviceAcceleration
 #include "nsIDOMXULCommandDispatcher.h"
 #ifndef MOZ_DISABLE_CRYPTOLEGACY
 #include "nsIDOMCRMFObject.h"
-#include "nsIDOMCryptoLegacy.h"
-#else
-#include "nsIDOMCrypto.h"
 #endif
 #include "nsIControllers.h"
 #include "nsISelection.h"
 #include "nsIBoxObject.h"
 #ifdef MOZ_XUL
 #include "nsITreeSelection.h"
 #include "nsITreeContentView.h"
 #include "nsITreeView.h"
@@ -314,17 +311,16 @@ static const char kDOMStringBundleURL[] 
  */
 #define DOMCI_DATA_NO_CLASS(_dom_class)                                       \
 const uint32_t kDOMClassInfo_##_dom_class##_interfaces =                      \
   0;
 
 #ifndef MOZ_DISABLE_CRYPTOLEGACY
 DOMCI_DATA_NO_CLASS(CRMFObject)
 #endif
-DOMCI_DATA_NO_CLASS(Crypto)
 
 DOMCI_DATA_NO_CLASS(ContentFrameMessageManager)
 DOMCI_DATA_NO_CLASS(ChromeMessageBroadcaster)
 DOMCI_DATA_NO_CLASS(ChromeMessageSender)
 
 DOMCI_DATA_NO_CLASS(DOMPrototype)
 DOMCI_DATA_NO_CLASS(DOMConstructor)
 
@@ -497,18 +493,16 @@ static nsDOMClassInfoData sClassInfoData
                                        DEFAULT_SCRIPTABLE_FLAGS)
 #endif
 
   // Crypto classes
 #ifndef MOZ_DISABLE_CRYPTOLEGACY
   NS_DEFINE_CLASSINFO_DATA(CRMFObject, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 #endif
-  NS_DEFINE_CLASSINFO_DATA(Crypto, nsDOMGenericSH,
-                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   // DOM Chrome Window class.
   NS_DEFINE_CLASSINFO_DATA(ChromeWindow, nsWindowSH,
                            DEFAULT_SCRIPTABLE_FLAGS |
                            WINDOW_SCRIPTABLE_FLAGS)
 
 #ifdef MOZ_XUL
   NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA(XULTemplateBuilder, nsDOMGenericSH,
@@ -1335,20 +1329,16 @@ nsDOMClassInfo::Init()
 #endif
 
 #ifndef MOZ_DISABLE_CRYPTOLEGACY
    DOM_CLASSINFO_MAP_BEGIN(CRMFObject, nsIDOMCRMFObject)
      DOM_CLASSINFO_MAP_ENTRY(nsIDOMCRMFObject)
    DOM_CLASSINFO_MAP_END
 #endif
 
-  DOM_CLASSINFO_MAP_BEGIN(Crypto, nsIDOMCrypto)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMCrypto)
-  DOM_CLASSINFO_MAP_END
-
   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ChromeWindow, nsIDOMWindow)
     DOM_CLASSINFO_WINDOW_MAP_ENTRIES(true)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMChromeWindow)
 #ifdef MOZ_WEBSPEECH
     DOM_CLASSINFO_MAP_ENTRY(nsISpeechSynthesisGetter)
 #endif
   DOM_CLASSINFO_MAP_END
 
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -40,17 +40,16 @@ DOMCI_CLASS(BoxObject)
 DOMCI_CLASS(TreeSelection)
 DOMCI_CLASS(TreeContentView)
 #endif
 
 // Crypto classes
 #ifndef MOZ_DISABLE_CRYPTOLEGACY
 DOMCI_CLASS(CRMFObject)
 #endif
-DOMCI_CLASS(Crypto)
 
 // DOM Chrome Window class, almost identical to Window
 DOMCI_CLASS(ChromeWindow)
 
 #ifdef MOZ_XUL
 DOMCI_CLASS(XULTemplateBuilder)
 DOMCI_CLASS(XULTreeBuilder)
 #endif
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -1674,16 +1674,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAudioContexts)
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMenubar)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mToolbar)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocationbar)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPersonalbar)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStatusbar)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mScrollbars)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCrypto)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindow)
   nsGlobalWindow::CleanupCachedXBLHandlers(tmp);
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mContext)
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mControllers)
@@ -1728,16 +1729,17 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mAudioContexts)
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mMenubar)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mToolbar)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocationbar)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mPersonalbar)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mStatusbar)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mScrollbars)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mCrypto)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 struct TraceData
 {
   const TraceCallbacks& callbacks;
   void* closure;
 };
 
@@ -3873,20 +3875,23 @@ nsGlobalWindow::GetApplicationCache(nsID
 
 NS_IMETHODIMP
 nsGlobalWindow::GetCrypto(nsIDOMCrypto** aCrypto)
 {
   FORWARD_TO_OUTER(GetCrypto, (aCrypto), NS_ERROR_NOT_INITIALIZED);
 
   if (!mCrypto) {
 #ifndef MOZ_DISABLE_CRYPTOLEGACY
-    mCrypto = do_CreateInstance(NS_CRYPTO_CONTRACTID);
+    nsresult rv;
+    mCrypto = do_CreateInstance(NS_CRYPTO_CONTRACTID, &rv);
+    NS_ENSURE_SUCCESS(rv, rv);
 #else
     mCrypto = new Crypto();
 #endif
+    mCrypto->Init(this);
   }
   NS_IF_ADDREF(*aCrypto = mCrypto);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetPkcs11(nsIDOMPkcs11** aPkcs11)
 {
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -201,16 +201,21 @@ DOMInterfaces = {
     'implicitJSContext': [ 'buffer' ],
     'resultNotAddRefed': [ 'buffer' ],
 },
 
 'Coordinates': {
     'headerFile': 'nsGeoPosition.h'
 },
 
+'Crypto' : {
+  'implicitJSContext': [ 'generateCRMFRequest', 'signText' ],
+  'headerFile': 'Crypto.h'
+},
+
 'CSS': {
     'concrete': False,
 },
 
 'CSS2Properties': {
   'nativeType': 'nsDOMCSSDeclaration'
 },
 
--- a/dom/devicestorage/DeviceStorage.h
+++ b/dom/devicestorage/DeviceStorage.h
@@ -45,36 +45,37 @@ public:
 
   // 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.
+  // 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(nsAString& aFileName,
+               uint32_t aFileType,
+               uint32_t aFileAttributes);
 
   NS_DECL_THREADSAFE_ISUPPORTS
 
   bool IsAvailable();
-  bool IsComposite();
-  void GetCompositePath(nsAString& aCompositePath);
+  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();
   bool IsSafePath(const nsAString& aPath);
 
   void Dump(const char* label);
 
@@ -97,17 +98,16 @@ public:
 
   nsresult CalculateSizeAndModifiedDate();
   nsresult CalculateMimeType();
 
 private:
   void Init();
   void NormalizeFilePath();
   void AppendRelativePath(const nsAString& aPath);
-  void GetStatusInternal(nsAString& aStorageName, nsAString& aStatus);
   void AccumDirectoryUsage(nsIFile* aFile,
                            uint64_t* aPicturesSoFar,
                            uint64_t* aVideosSoFar,
                            uint64_t* aMusicSoFar,
                            uint64_t* aTotalSoFar);
 };
 
 /*
@@ -148,36 +148,42 @@ class nsDOMDeviceStorage MOZ_FINAL
 public:
   typedef nsTArray<nsString> VolumeNameArray;
 
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIDOMDEVICESTORAGE
 
   NS_DECL_NSIOBSERVER
   NS_DECL_NSIDOMEVENTTARGET
-  virtual void AddEventListener(const nsAString& aType,
-                                nsIDOMEventListener* aListener,
-                                bool aUseCapture,
-                                const mozilla::dom::Nullable<bool>& aWantsUntrusted,
-                                ErrorResult& aRv) MOZ_OVERRIDE;
+
+  virtual void
+  AddEventListener(const nsAString& aType,
+                   nsIDOMEventListener* aListener,
+                   bool aUseCapture,
+                   const mozilla::dom::Nullable<bool>& aWantsUntrusted,
+                   ErrorResult& aRv) MOZ_OVERRIDE;
+
   virtual void RemoveEventListener(const nsAString& aType,
                                    nsIDOMEventListener* aListener,
                                    bool aUseCapture,
                                    ErrorResult& aRv) MOZ_OVERRIDE;
 
   nsDOMDeviceStorage();
 
   nsresult Init(nsPIDOMWindow* aWindow, const nsAString& aType,
-                nsTArray<nsRefPtr<nsDOMDeviceStorage> >& aStores);
-  nsresult Init(nsPIDOMWindow* 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);
+  void SetRootDirectoryForType(const nsAString& aType,
+                               const nsAString& aVolName);
 
   // WebIDL
   nsPIDOMWindow*
   GetParentObject() const
   {
     return GetOwner();
   }
   virtual JSObject*
@@ -223,34 +229,36 @@ public:
   already_AddRefed<DOMRequest> FreeSpace(ErrorResult& aRv);
   already_AddRefed<DOMRequest> UsedSpace(ErrorResult& aRv);
   already_AddRefed<DOMRequest> Available(ErrorResult& aRv);
 
   bool Default();
 
   // Uses XPCOM GetStorageName
 
-  static void CreateDeviceStorageFor(nsPIDOMWindow* aWin,
-                                     const nsAString& aType,
-                                     nsDOMDeviceStorage** aStore);
+  static void
+  CreateDeviceStorageFor(nsPIDOMWindow* aWin,
+                         const nsAString& aType,
+                         nsDOMDeviceStorage** aStore);
 
-  static void CreateDeviceStoragesFor(nsPIDOMWindow* aWin,
-                                      const nsAString& aType,
-                                      nsTArray<nsRefPtr<nsDOMDeviceStorage> >& aStores,
-                                      bool aCompositeComponent);
+  static void
+  CreateDeviceStoragesFor(nsPIDOMWindow* aWin,
+                          const nsAString& aType,
+                          nsTArray<nsRefPtr<nsDOMDeviceStorage> >& aStores);
+
   void Shutdown();
 
   static void GetOrderedVolumeNames(nsTArray<nsString>& aVolumeNames);
 
-  static void GetWritableStorageName(const nsAString& aStorageType,
-                                     nsAString &aStorageName);
+  static void GetDefaultStorageName(const nsAString& aStorageType,
+                                    nsAString &aStorageName);
 
-  static bool ParseCompositePath(const nsAString& aCompositePath,
-                                 nsAString& aOutStorageName,
-                                 nsAString& aOutStoragePath);
+  static bool ParseFullPath(const nsAString& aFullPath,
+                            nsAString& aOutStorageName,
+                            nsAString& aOutStoragePath);
 private:
   ~nsDOMDeviceStorage();
 
   already_AddRefed<DOMRequest>
   GetInternal(const nsAString& aPath, bool aEditable, ErrorResult& aRv);
 
   void
   GetInternal(nsPIDOMWindow* aWin, const nsAString& aPath, DOMRequest* aRequest,
@@ -263,35 +271,21 @@ private:
   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
-  // mStores and will each have a unique mStorageName. The composite storage
-  // object will have mStorageName == "", and mRootDirectory will be null.
-  // 
-  // Note that on desktop (or other non-gonk), composite storage areas
-  // don't exist, and mStorageName will also be "".
-  //
-  // A device storage object which is stored in mStores is considered to be
-  // a composite component.
-
-  bool IsComposite() { return mStores.Length() > 0; }
-  bool IsCompositeComponent() { return mCompositeComponent; }
-  nsTArray<nsRefPtr<nsDOMDeviceStorage> > mStores;
-  already_AddRefed<nsDOMDeviceStorage> GetStorage(const nsAString& aCompositePath,
+  already_AddRefed<nsDOMDeviceStorage> GetStorage(const nsAString& aFullPath,
                                                   nsAString& aOutStoragePath);
-  already_AddRefed<nsDOMDeviceStorage> GetStorageByName(const nsAString &aStorageName);
+  already_AddRefed<nsDOMDeviceStorage>
+    GetStorageByName(const nsAString &aStorageName);
 
   nsCOMPtr<nsIPrincipal> mPrincipal;
 
   bool mIsWatchingFile;
   bool mAllowedToWatchFile;
 
   nsresult Notify(const char* aReason, class DeviceStorageFile* aFile);
 
@@ -301,18 +295,17 @@ private:
   class VolumeNameCache : public mozilla::RefCounted<VolumeNameCache>
   {
   public:
     nsTArray<nsString>  mVolumeNames;
   };
   static mozilla::StaticRefPtr<VolumeNameCache> sVolumeNameCache;
 
 #ifdef MOZ_WIDGET_GONK
-  void DispatchMountChangeEvent(nsAString& aVolumeName,
-                                nsAString& aVolumeStatus);
+  void DispatchMountChangeEvent(nsAString& aVolumeStatus);
 #endif
 
   // nsIDOMDeviceStorage.type
   enum {
       DEVICE_STORAGE_TYPE_DEFAULT = 0,
       DEVICE_STORAGE_TYPE_SHARED,
       DEVICE_STORAGE_TYPE_EXTERNAL
   };
--- a/dom/devicestorage/DeviceStorageRequestChild.cpp
+++ b/dom/devicestorage/DeviceStorageRequestChild.cpp
@@ -28,17 +28,18 @@ DeviceStorageRequestChild::DeviceStorage
   MOZ_COUNT_CTOR(DeviceStorageRequestChild);
 }
 
 DeviceStorageRequestChild::~DeviceStorageRequestChild() {
   MOZ_COUNT_DTOR(DeviceStorageRequestChild);
 }
 
 bool
-DeviceStorageRequestChild::Recv__delete__(const DeviceStorageResponseValue& aValue)
+DeviceStorageRequestChild::
+  Recv__delete__(const DeviceStorageResponseValue& aValue)
 {
   if (mCallback) {
     mCallback->RequestComplete();
     mCallback = nullptr;
   }
 
   switch (aValue.type()) {
 
@@ -46,21 +47,21 @@ DeviceStorageRequestChild::Recv__delete_
     {
       ErrorResponse r = aValue;
       mRequest->FireError(r.error());
       break;
     }
 
     case DeviceStorageResponseValue::TSuccessResponse:
     {
-      nsString compositePath;
-      mFile->GetCompositePath(compositePath);
+      nsString fullPath;
+      mFile->GetFullPath(fullPath);
       AutoJSContext cx;
       JS::Rooted<JS::Value> result(cx,
-        StringToJsval(mRequest->GetOwner(), compositePath));
+        StringToJsval(mRequest->GetOwner(), fullPath));
       mRequest->FireSuccess(result);
       break;
     }
 
     case DeviceStorageResponseValue::TBlobResponse:
     {
       BlobResponse r = aValue;
       BlobChild* actor = static_cast<BlobChild*>(r.blobChild());
@@ -100,24 +101,24 @@ DeviceStorageRequestChild::Recv__delete_
         cx, StringToJsval(mRequest->GetOwner(), r.mountState()));
       mRequest->FireSuccess(result);
       break;
     }
 
     case DeviceStorageResponseValue::TEnumerationResponse:
     {
       EnumerationResponse r = aValue;
-      nsDOMDeviceStorageCursor* cursor = static_cast<nsDOMDeviceStorageCursor*>(mRequest.get());
+      nsDOMDeviceStorageCursor* cursor
+        = static_cast<nsDOMDeviceStorageCursor*>(mRequest.get());
 
       uint32_t count = r.paths().Length();
       for (uint32_t i = 0; i < count; i++) {
-        nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(r.type(),
-                                                                r.paths()[i].storageName(),
-                                                                r.rootdir(),
-                                                                r.paths()[i].name());
+        nsRefPtr<DeviceStorageFile> dsf
+          = new DeviceStorageFile(r.type(), r.paths()[i].storageName(),
+                                  r.rootdir(), r.paths()[i].name());
         cursor->mFiles.AppendElement(dsf);
       }
 
       nsCOMPtr<ContinueCursorEvent> event = new ContinueCursorEvent(cursor);
       event->Continue();
       break;
     }
 
@@ -126,16 +127,17 @@ DeviceStorageRequestChild::Recv__delete_
       NS_RUNTIMEABORT("not reached");
       break;
     }
   }
   return true;
 }
 
 void
-DeviceStorageRequestChild::SetCallback(DeviceStorageRequestChildCallback *aCallback)
+DeviceStorageRequestChild::
+  SetCallback(DeviceStorageRequestChildCallback *aCallback)
 {
   mCallback = aCallback;
 }
 
 } // namespace devicestorage
 } // namespace dom
 } // namespace mozilla
--- a/dom/devicestorage/DeviceStorageRequestParent.cpp
+++ b/dom/devicestorage/DeviceStorageRequestParent.cpp
@@ -13,24 +13,26 @@
 #include "nsProxyRelease.h"
 #include "AppProcessChecker.h"
 #include "mozilla/Preferences.h"
 
 namespace mozilla {
 namespace dom {
 namespace devicestorage {
 
-DeviceStorageRequestParent::DeviceStorageRequestParent(const DeviceStorageParams& aParams)
+DeviceStorageRequestParent::DeviceStorageRequestParent(
+  const DeviceStorageParams& aParams)
   : mParams(aParams)
   , mMutex("DeviceStorageRequestParent::mMutex")
   , mActorDestoryed(false)
 {
   MOZ_COUNT_CTOR(DeviceStorageRequestParent);
 
-  DebugOnly<DeviceStorageUsedSpaceCache*> usedSpaceCache = DeviceStorageUsedSpaceCache::CreateOrGet();
+  DebugOnly<DeviceStorageUsedSpaceCache*> usedSpaceCache
+    = DeviceStorageUsedSpaceCache::CreateOrGet();
   NS_ASSERTION(usedSpaceCache, "DeviceStorageUsedSpaceCache is null");
 }
 
 void
 DeviceStorageRequestParent::Dispatch()
 {
   switch (mParams.type()) {
     case DeviceStorageParams::TDeviceStorageAddParams:
@@ -43,66 +45,72 @@ DeviceStorageRequestParent::Dispatch()
       BlobParent* bp = static_cast<BlobParent*>(p.blobParent());
       nsCOMPtr<nsIDOMBlob> blob = bp->GetBlob();
 
       nsCOMPtr<nsIInputStream> stream;
       blob->GetInternalStream(getter_AddRefs(stream));
 
       nsRefPtr<CancelableRunnable> r = new WriteFileEvent(this, dsf, stream);
 
-      nsCOMPtr<nsIEventTarget> target = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
+      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::TDeviceStorageGetParams:
     {
       DeviceStorageGetParams p = mParams;
       nsRefPtr<DeviceStorageFile> dsf =
-        new DeviceStorageFile(p.type(), p.storageName(), p.rootDir(), p.relpath());
+        new DeviceStorageFile(p.type(), p.storageName(),
+                              p.rootDir(), p.relpath());
       nsRefPtr<CancelableRunnable> r = new ReadFileEvent(this, dsf);
 
-      nsCOMPtr<nsIEventTarget> target = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
+      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::TDeviceStorageDeleteParams:
     {
       DeviceStorageDeleteParams p = mParams;
 
       nsRefPtr<DeviceStorageFile> dsf =
         new DeviceStorageFile(p.type(), p.storageName(), p.relpath());
       nsRefPtr<CancelableRunnable> r = new DeleteFileEvent(this, dsf);
 
-      nsCOMPtr<nsIEventTarget> target = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
+      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::TDeviceStorageFreeSpaceParams:
     {
       DeviceStorageFreeSpaceParams p = mParams;
 
       nsRefPtr<DeviceStorageFile> dsf =
         new DeviceStorageFile(p.type(), p.storageName());
       nsRefPtr<FreeSpaceFileEvent> r = new FreeSpaceFileEvent(this, dsf);
 
-      nsCOMPtr<nsIEventTarget> target = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
+      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::TDeviceStorageUsedSpaceParams:
     {
-      DeviceStorageUsedSpaceCache* usedSpaceCache = DeviceStorageUsedSpaceCache::CreateOrGet();
+      DeviceStorageUsedSpaceCache* usedSpaceCache
+        = DeviceStorageUsedSpaceCache::CreateOrGet();
       NS_ASSERTION(usedSpaceCache, "DeviceStorageUsedSpaceCache is null");
 
       DeviceStorageUsedSpaceParams p = mParams;
 
       nsRefPtr<DeviceStorageFile> dsf =
         new DeviceStorageFile(p.type(), p.storageName());
       nsRefPtr<UsedSpaceFileEvent> r = new UsedSpaceFileEvent(this, dsf);
 
@@ -111,43 +119,48 @@ DeviceStorageRequestParent::Dispatch()
     }
 
     case DeviceStorageParams::TDeviceStorageAvailableParams:
     {
       DeviceStorageAvailableParams p = mParams;
 
       nsRefPtr<DeviceStorageFile> dsf =
         new DeviceStorageFile(p.type(), p.storageName());
-      nsRefPtr<PostAvailableResultEvent> r = new PostAvailableResultEvent(this, dsf);
+      nsRefPtr<PostAvailableResultEvent> r
+        = new PostAvailableResultEvent(this, dsf);
       NS_DispatchToMainThread(r);
       break;
     }
 
     case DeviceStorageParams::TDeviceStorageEnumerationParams:
     {
       DeviceStorageEnumerationParams p = mParams;
       nsRefPtr<DeviceStorageFile> dsf
-        = new DeviceStorageFile(p.type(), p.storageName(), p.rootdir(), NS_LITERAL_STRING(""));
-      nsRefPtr<CancelableRunnable> r = new EnumerateFileEvent(this, dsf, p.since());
+        = new DeviceStorageFile(p.type(), p.storageName(),
+                                p.rootdir(), NS_LITERAL_STRING(""));
+      nsRefPtr<CancelableRunnable> r
+        = new EnumerateFileEvent(this, dsf, p.since());
 
-      nsCOMPtr<nsIEventTarget> target = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
+      nsCOMPtr<nsIEventTarget> target
+        = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
       NS_ASSERTION(target, "Must have stream transport service");
       target->Dispatch(r, NS_DISPATCH_NORMAL);
       break;
     }
     default:
     {
       NS_RUNTIMEABORT("not reached");
       break;
     }
   }
 }
 
 bool
-DeviceStorageRequestParent::EnsureRequiredPermissions(mozilla::dom::ContentParent* aParent)
+DeviceStorageRequestParent::EnsureRequiredPermissions(
+  mozilla::dom::ContentParent* aParent)
 {
   if (mozilla::Preferences::GetBool("device.storage.testing", false)) {
     return true;
   }
 
   nsString type;
   DeviceStorageRequestType requestType;
 
@@ -219,17 +232,18 @@ DeviceStorageRequestParent::EnsureRequir
   // if the caller has the "webapps-manage" permission.
   if (type.EqualsLiteral("apps")) {
     if (!AssertAppProcessPermission(aParent, "webapps-manage")) {
       return false;
     }
   }
 
   nsAutoCString permissionName;
-  nsresult rv = DeviceStorageTypeChecker::GetPermissionForType(type, permissionName);
+  nsresult rv = DeviceStorageTypeChecker::GetPermissionForType(type,
+                                                               permissionName);
   if (NS_FAILED(rv)) {
     return false;
   }
 
   nsCString access;
   rv = DeviceStorageTypeChecker::GetAccessForRequest(requestType, access);
   if (NS_FAILED(rv)) {
     return false;
@@ -259,93 +273,99 @@ DeviceStorageRequestParent::ActorDestroy
   MutexAutoLock lock(mMutex);
   mActorDestoryed = true;
   int32_t count = mRunnables.Length();
   for (int32_t index = 0; index < count; index++) {
     mRunnables[index]->Cancel();
   }
 }
 
-DeviceStorageRequestParent::PostFreeSpaceResultEvent::PostFreeSpaceResultEvent(DeviceStorageRequestParent* aParent,
-                                                                               uint64_t aFreeSpace)
+DeviceStorageRequestParent::PostFreeSpaceResultEvent::PostFreeSpaceResultEvent(
+  DeviceStorageRequestParent* aParent,
+  uint64_t aFreeSpace)
   : CancelableRunnable(aParent)
   , mFreeSpace(aFreeSpace)
 {
 }
 
-DeviceStorageRequestParent::PostFreeSpaceResultEvent::~PostFreeSpaceResultEvent() {}
+DeviceStorageRequestParent::PostFreeSpaceResultEvent::
+  ~PostFreeSpaceResultEvent() {}
 
 nsresult
 DeviceStorageRequestParent::PostFreeSpaceResultEvent::CancelableRun() {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   FreeSpaceStorageResponse response(mFreeSpace);
   unused << mParent->Send__delete__(mParent, response);
   return NS_OK;
 }
 
-DeviceStorageRequestParent::PostUsedSpaceResultEvent::PostUsedSpaceResultEvent(DeviceStorageRequestParent* aParent,
-                                                                               const nsAString& aType,
-                                                                               uint64_t aUsedSpace)
+DeviceStorageRequestParent::PostUsedSpaceResultEvent::
+  PostUsedSpaceResultEvent(DeviceStorageRequestParent* aParent,
+                             const nsAString& aType,
+                             uint64_t aUsedSpace)
   : CancelableRunnable(aParent)
   , mType(aType)
   , mUsedSpace(aUsedSpace)
 {
 }
 
-DeviceStorageRequestParent::PostUsedSpaceResultEvent::~PostUsedSpaceResultEvent() {}
+DeviceStorageRequestParent::PostUsedSpaceResultEvent::
+  ~PostUsedSpaceResultEvent() {}
 
 nsresult
 DeviceStorageRequestParent::PostUsedSpaceResultEvent::CancelableRun() {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   UsedSpaceStorageResponse response(mUsedSpace);
   unused << mParent->Send__delete__(mParent, response);
   return NS_OK;
 }
 
-DeviceStorageRequestParent::PostErrorEvent::PostErrorEvent(DeviceStorageRequestParent* aParent,
-                                                           const char* aError)
+DeviceStorageRequestParent::PostErrorEvent::
+  PostErrorEvent(DeviceStorageRequestParent* aParent, const char* aError)
   : CancelableRunnable(aParent)
 {
   CopyASCIItoUTF16(aError, mError);
 }
 
 DeviceStorageRequestParent::PostErrorEvent::~PostErrorEvent() {}
 
 nsresult
 DeviceStorageRequestParent::PostErrorEvent::CancelableRun() {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   ErrorResponse response(mError);
   unused << mParent->Send__delete__(mParent, response);
   return NS_OK;
 }
 
-DeviceStorageRequestParent::PostSuccessEvent::PostSuccessEvent(DeviceStorageRequestParent* aParent)
+DeviceStorageRequestParent::PostSuccessEvent::
+  PostSuccessEvent(DeviceStorageRequestParent* aParent)
   : CancelableRunnable(aParent)
 {
 }
 
 DeviceStorageRequestParent::PostSuccessEvent::~PostSuccessEvent() {}
 
 nsresult
 DeviceStorageRequestParent::PostSuccessEvent::CancelableRun() {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   SuccessResponse response;
   unused << mParent->Send__delete__(mParent, response);
   return NS_OK;
 }
 
-DeviceStorageRequestParent::PostBlobSuccessEvent::PostBlobSuccessEvent(DeviceStorageRequestParent* aParent,
-                                                                       DeviceStorageFile* aFile,
-                                                                       uint32_t aLength,
-                                                                       nsACString& aMimeType,
-                                                                       uint64_t aLastModifiedDate)
+DeviceStorageRequestParent::PostBlobSuccessEvent::
+  PostBlobSuccessEvent(DeviceStorageRequestParent* aParent,
+                       DeviceStorageFile* aFile,
+                       uint32_t aLength,
+                       nsACString& aMimeType,
+                       uint64_t aLastModifiedDate)
   : CancelableRunnable(aParent)
   , mLength(aLength)
   , mLastModificationDate(aLastModifiedDate)
   , mFile(aFile)
   , mMimeType(aMimeType)
 {
 }
 
@@ -353,60 +373,65 @@ DeviceStorageRequestParent::PostBlobSucc
 
 nsresult
 DeviceStorageRequestParent::PostBlobSuccessEvent::CancelableRun() {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   nsString mime;
   CopyASCIItoUTF16(mMimeType, mime);
 
-  nsString  compositePath;
-  mFile->GetCompositePath(compositePath);
-  nsCOMPtr<nsIDOMBlob> blob = new nsDOMFileFile(compositePath, mime, mLength, mFile->mFile, mLastModificationDate);
+  nsString fullPath;
+  mFile->GetFullPath(fullPath);
+  nsCOMPtr<nsIDOMBlob> blob = new nsDOMFileFile(fullPath, mime, mLength, 
+                                                mFile->mFile,
+                                                mLastModificationDate);
 
   ContentParent* cp = static_cast<ContentParent*>(mParent->Manager());
   BlobParent* actor = cp->GetOrCreateActorForBlob(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;
 }
 
-DeviceStorageRequestParent::PostEnumerationSuccessEvent::PostEnumerationSuccessEvent(DeviceStorageRequestParent* aParent,
-                                                                                     const nsAString& aStorageType,
-                                                                                     const nsAString& aRelPath,
-                                                                                     InfallibleTArray<DeviceStorageFileValue>& aPaths)
+DeviceStorageRequestParent::PostEnumerationSuccessEvent::
+  PostEnumerationSuccessEvent(DeviceStorageRequestParent* aParent,
+                              const nsAString& aStorageType,
+                              const nsAString& aRelPath,
+                              InfallibleTArray<DeviceStorageFileValue>& aPaths)
   : CancelableRunnable(aParent)
   , mStorageType(aStorageType)
   , mRelPath(aRelPath)
   , mPaths(aPaths)
 {
 }
 
-DeviceStorageRequestParent::PostEnumerationSuccessEvent::~PostEnumerationSuccessEvent() {}
+DeviceStorageRequestParent::PostEnumerationSuccessEvent::
+  ~PostEnumerationSuccessEvent() {}
 
 nsresult
 DeviceStorageRequestParent::PostEnumerationSuccessEvent::CancelableRun() {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   EnumerationResponse response(mStorageType, mRelPath, mPaths);
   unused << mParent->Send__delete__(mParent, response);
   return NS_OK;
 }
 
-DeviceStorageRequestParent::WriteFileEvent::WriteFileEvent(DeviceStorageRequestParent* aParent,
-                                                           DeviceStorageFile* aFile,
-                                                           nsIInputStream* aInputStream)
+DeviceStorageRequestParent::WriteFileEvent::
+  WriteFileEvent(DeviceStorageRequestParent* aParent,
+                 DeviceStorageFile* aFile,
+                 nsIInputStream* aInputStream)
   : CancelableRunnable(aParent)
   , mFile(aFile)
   , mInputStream(aInputStream)
 {
 }
 
 DeviceStorageRequestParent::WriteFileEvent::~WriteFileEvent()
 {
@@ -423,17 +448,18 @@ DeviceStorageRequestParent::WriteFileEve
     r = new PostErrorEvent(mParent, POST_ERROR_EVENT_UNKNOWN);
     NS_DispatchToMainThread(r);
     return NS_OK;
   }
 
   bool check = false;
   mFile->mFile->Exists(&check);
   if (check) {
-    nsCOMPtr<PostErrorEvent> event = new PostErrorEvent(mParent, POST_ERROR_EVENT_FILE_EXISTS);
+    nsCOMPtr<PostErrorEvent> event
+      = new PostErrorEvent(mParent, POST_ERROR_EVENT_FILE_EXISTS);
     NS_DispatchToMainThread(event);
     return NS_OK;
   }
 
   nsresult rv = mFile->Write(mInputStream);
 
   if (NS_FAILED(rv)) {
     r = new PostErrorEvent(mParent, POST_ERROR_EVENT_UNKNOWN);
@@ -442,18 +468,18 @@ DeviceStorageRequestParent::WriteFileEve
     r = new PostPathResultEvent(mParent, mFile->mPath);
   }
 
   NS_DispatchToMainThread(r);
   return NS_OK;
 }
 
 
-DeviceStorageRequestParent::DeleteFileEvent::DeleteFileEvent(DeviceStorageRequestParent* aParent,
-                                                             DeviceStorageFile* aFile)
+DeviceStorageRequestParent::DeleteFileEvent::
+  DeleteFileEvent(DeviceStorageRequestParent* aParent, DeviceStorageFile* aFile)
   : CancelableRunnable(aParent)
   , mFile(aFile)
 {
 }
 
 DeviceStorageRequestParent::DeleteFileEvent::~DeleteFileEvent()
 {
 }
@@ -475,18 +501,19 @@ DeviceStorageRequestParent::DeleteFileEv
   else {
     r = new PostPathResultEvent(mParent, mFile->mPath);
   }
 
   NS_DispatchToMainThread(r);
   return NS_OK;
 }
 
-DeviceStorageRequestParent::FreeSpaceFileEvent::FreeSpaceFileEvent(DeviceStorageRequestParent* aParent,
-                                                                   DeviceStorageFile* aFile)
+DeviceStorageRequestParent::FreeSpaceFileEvent::
+  FreeSpaceFileEvent(DeviceStorageRequestParent* aParent,
+                     DeviceStorageFile* aFile)
   : CancelableRunnable(aParent)
   , mFile(aFile)
 {
 }
 
 DeviceStorageRequestParent::FreeSpaceFileEvent::~FreeSpaceFileEvent()
 {
 }
@@ -502,18 +529,19 @@ DeviceStorageRequestParent::FreeSpaceFil
   }
 
   nsCOMPtr<nsIRunnable> r;
   r = new PostFreeSpaceResultEvent(mParent, static_cast<uint64_t>(freeSpace));
   NS_DispatchToMainThread(r);
   return NS_OK;
 }
 
-DeviceStorageRequestParent::UsedSpaceFileEvent::UsedSpaceFileEvent(DeviceStorageRequestParent* aParent,
-                                                                   DeviceStorageFile* aFile)
+DeviceStorageRequestParent::UsedSpaceFileEvent::
+  UsedSpaceFileEvent(DeviceStorageRequestParent* aParent,
+                     DeviceStorageFile* aFile)
   : CancelableRunnable(aParent)
   , mFile(aFile)
 {
 }
 
 DeviceStorageRequestParent::UsedSpaceFileEvent::~UsedSpaceFileEvent()
 {
 }
@@ -523,36 +551,38 @@ DeviceStorageRequestParent::UsedSpaceFil
 {
   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
 
   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);
+    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);
   }
   NS_DispatchToMainThread(r);
   return NS_OK;
 }
 
-DeviceStorageRequestParent::ReadFileEvent::ReadFileEvent(DeviceStorageRequestParent* aParent,
-                                                         DeviceStorageFile* aFile)
+DeviceStorageRequestParent::ReadFileEvent::
+  ReadFileEvent(DeviceStorageRequestParent* aParent, DeviceStorageFile* aFile)
   : CancelableRunnable(aParent)
   , mFile(aFile)
 {
-  nsCOMPtr<nsIMIMEService> mimeService = do_GetService(NS_MIMESERVICE_CONTRACTID);
+  nsCOMPtr<nsIMIMEService> mimeService
+    = do_GetService(NS_MIMESERVICE_CONTRACTID);
   if (mimeService) {
     nsresult rv = mimeService->GetTypeFromFile(mFile->mFile, mMimeType);
     if (NS_FAILED(rv)) {
       mMimeType.Truncate();
     }
   }
 }
 
@@ -586,24 +616,26 @@ DeviceStorageRequestParent::ReadFileEven
   PRTime modDate;
   rv = mFile->mFile->GetLastModifiedTime(&modDate);
   if (NS_FAILED(rv)) {
     r = new PostErrorEvent(mParent, POST_ERROR_EVENT_UNKNOWN);
     NS_DispatchToMainThread(r);
     return NS_OK;
   }
 
-  r = new PostBlobSuccessEvent(mParent, mFile, static_cast<uint64_t>(fileSize), mMimeType, modDate);
+  r = new PostBlobSuccessEvent(mParent, mFile, static_cast<uint64_t>(fileSize),
+                               mMimeType, modDate);
   NS_DispatchToMainThread(r);
   return NS_OK;
 }
 
-DeviceStorageRequestParent::EnumerateFileEvent::EnumerateFileEvent(DeviceStorageRequestParent* aParent,
-                                                                   DeviceStorageFile* aFile,
-                                                                   uint64_t aSince)
+DeviceStorageRequestParent::EnumerateFileEvent::
+  EnumerateFileEvent(DeviceStorageRequestParent* aParent,
+                     DeviceStorageFile* aFile,
+                     uint64_t aSince)
   : CancelableRunnable(aParent)
   , mFile(aFile)
   , mSince(aSince)
 {
 }
 
 DeviceStorageRequestParent::EnumerateFileEvent::~EnumerateFileEvent()
 {
@@ -631,24 +663,26 @@ DeviceStorageRequestParent::EnumerateFil
   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);
   }
 
-  r = new PostEnumerationSuccessEvent(mParent, mFile->mStorageType, mFile->mRootDir, values);
+  r = new PostEnumerationSuccessEvent(mParent, mFile->mStorageType,
+                                      mFile->mRootDir, values);
   NS_DispatchToMainThread(r);
   return NS_OK;
 }
 
 
-DeviceStorageRequestParent::PostPathResultEvent::PostPathResultEvent(DeviceStorageRequestParent* aParent,
-                                                                     const nsAString& aPath)
+DeviceStorageRequestParent::PostPathResultEvent::
+  PostPathResultEvent(DeviceStorageRequestParent* aParent,
+                      const nsAString& aPath)
   : CancelableRunnable(aParent)
   , mPath(aPath)
 {
 }
 
 DeviceStorageRequestParent::PostPathResultEvent::~PostPathResultEvent()
 {
 }
@@ -658,24 +692,26 @@ DeviceStorageRequestParent::PostPathResu
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   SuccessResponse response;
   unused << mParent->Send__delete__(mParent, response);
   return NS_OK;
 }
 
-DeviceStorageRequestParent::PostAvailableResultEvent::PostAvailableResultEvent(DeviceStorageRequestParent* aParent,
-                                                                               DeviceStorageFile* aFile)
+DeviceStorageRequestParent::PostAvailableResultEvent::
+  PostAvailableResultEvent(DeviceStorageRequestParent* aParent,
+                           DeviceStorageFile* aFile)
   : CancelableRunnable(aParent)
   , mFile(aFile)
 {
 }
 
-DeviceStorageRequestParent::PostAvailableResultEvent::~PostAvailableResultEvent()
+DeviceStorageRequestParent::PostAvailableResultEvent::
+  ~PostAvailableResultEvent()
 {
 }
 
 nsresult
 DeviceStorageRequestParent::PostAvailableResultEvent::CancelableRun()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
--- a/dom/devicestorage/nsDeviceStorage.cpp
+++ b/dom/devicestorage/nsDeviceStorage.cpp
@@ -54,33 +54,36 @@
 // Microsoft's API Name hackery sucks
 #undef CreateEvent
 
 #ifdef MOZ_WIDGET_GONK
 #include "nsIVolume.h"
 #include "nsIVolumeService.h"
 #endif
 
-#define DEVICESTORAGE_PROPERTIES "chrome://global/content/devicestorage.properties"
+#define DEVICESTORAGE_PROPERTIES \
+  "chrome://global/content/devicestorage.properties"
 #define DEFAULT_THREAD_TIMEOUT_MS 30000
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::dom::devicestorage;
 
 #include "nsDirectoryServiceDefs.h"
 
-StaticAutoPtr<DeviceStorageUsedSpaceCache> DeviceStorageUsedSpaceCache::sDeviceStorageUsedSpaceCache;
+StaticAutoPtr<DeviceStorageUsedSpaceCache>
+  DeviceStorageUsedSpaceCache::sDeviceStorageUsedSpaceCache;
 
 DeviceStorageUsedSpaceCache::DeviceStorageUsedSpaceCache()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
-  mIOThread = new LazyIdleThread(DEFAULT_THREAD_TIMEOUT_MS,
-                                 NS_LITERAL_CSTRING("DeviceStorageUsedSpaceCache I/O"));
+  mIOThread = new LazyIdleThread(
+    DEFAULT_THREAD_TIMEOUT_MS,
+    NS_LITERAL_CSTRING("DeviceStorageUsedSpaceCache I/O"));
 
 }
 
 DeviceStorageUsedSpaceCache::~DeviceStorageUsedSpaceCache()
 {
 }
 
 DeviceStorageUsedSpaceCache*
@@ -112,17 +115,18 @@ DeviceStorageUsedSpaceCache::GetCacheEnt
 }
 
 static int64_t
 GetFreeBytes(const nsAString& aStorageName)
 {
   // This function makes the assumption that the various types
   // are all stored on the same filesystem. So we use pictures.
 
-  DeviceStorageFile dsf(NS_LITERAL_STRING(DEVICESTORAGE_PICTURES), aStorageName);
+  DeviceStorageFile dsf(NS_LITERAL_STRING(DEVICESTORAGE_PICTURES),
+                        aStorageName);
   int64_t freeBytes = 0;
   dsf.GetDiskFreeSpace(&freeBytes);
   return freeBytes;
 }
 
 nsresult
 DeviceStorageUsedSpaceCache::AccumUsedSizes(const nsAString& aStorageName,
                                             uint64_t* aPicturesSoFar,
@@ -180,59 +184,69 @@ public:
   nsCOMPtr<nsIFile> apps;
   nsCOMPtr<nsIFile> sdcard;
 #endif
   nsCOMPtr<nsIFile> temp;
 };
 
 static StaticRefPtr<GlobalDirs> sDirs;
 
-StaticAutoPtr<DeviceStorageTypeChecker> DeviceStorageTypeChecker::sDeviceStorageTypeChecker;
+StaticAutoPtr<DeviceStorageTypeChecker>
+  DeviceStorageTypeChecker::sDeviceStorageTypeChecker;
 
 DeviceStorageTypeChecker::DeviceStorageTypeChecker()
 {
 }
 
 DeviceStorageTypeChecker::~DeviceStorageTypeChecker()
 {
 }
 
 DeviceStorageTypeChecker*
 DeviceStorageTypeChecker::CreateOrGet()
 {
   if (sDeviceStorageTypeChecker) {
     return sDeviceStorageTypeChecker;
   }
 
-  NS_ASSERTION(NS_IsMainThread(), "This can only be created on the main thread!");
-
-  nsCOMPtr<nsIStringBundleService> stringService = mozilla::services::GetStringBundleService();
+  NS_ASSERTION(NS_IsMainThread(),
+               "This can only be created on the main thread!");
+
+  nsCOMPtr<nsIStringBundleService> stringService
+    = mozilla::services::GetStringBundleService();
   if (!stringService) {
     return nullptr;
   }
 
   nsCOMPtr<nsIStringBundle> filterBundle;
-  if (NS_FAILED(stringService->CreateBundle(DEVICESTORAGE_PROPERTIES, getter_AddRefs(filterBundle)))) {
+  if (NS_FAILED(stringService->CreateBundle(DEVICESTORAGE_PROPERTIES,
+                                            getter_AddRefs(filterBundle)))) {
     return nullptr;
   }
 
   DeviceStorageTypeChecker* result = new DeviceStorageTypeChecker();
   result->InitFromBundle(filterBundle);
 
   sDeviceStorageTypeChecker = result;
   ClearOnShutdown(&sDeviceStorageTypeChecker);
   return result;
 }
 
 void
 DeviceStorageTypeChecker::InitFromBundle(nsIStringBundle* aBundle)
 {
-  aBundle->GetStringFromName(NS_ConvertASCIItoUTF16(DEVICESTORAGE_PICTURES).get(), getter_Copies(mPicturesExtensions));
-  aBundle->GetStringFromName(NS_ConvertASCIItoUTF16(DEVICESTORAGE_MUSIC).get(), getter_Copies(mMusicExtensions));
-  aBundle->GetStringFromName(NS_ConvertASCIItoUTF16(DEVICESTORAGE_VIDEOS).get(), getter_Copies(mVideosExtensions));
+  aBundle->GetStringFromName(
+    NS_ConvertASCIItoUTF16(DEVICESTORAGE_PICTURES).get(),
+    getter_Copies(mPicturesExtensions));
+  aBundle->GetStringFromName(
+    NS_ConvertASCIItoUTF16(DEVICESTORAGE_MUSIC).get(),
+    getter_Copies(mMusicExtensions));
+  aBundle->GetStringFromName(
+    NS_ConvertASCIItoUTF16(DEVICESTORAGE_VIDEOS).get(),
+    getter_Copies(mVideosExtensions));
 }
 
 
 bool
 DeviceStorageTypeChecker::Check(const nsAString& aType, nsIDOMBlob* aBlob)
 {
   NS_ASSERTION(aBlob, "Calling Check without a blob");
 
@@ -308,17 +322,18 @@ DeviceStorageTypeChecker::GetTypeFromFil
 
   nsString path;
   aFile->GetPath(path);
 
   GetTypeFromFileName(path, aType);
 }
 
 void
-DeviceStorageTypeChecker::GetTypeFromFileName(const nsAString& aFileName, nsAString& aType)
+DeviceStorageTypeChecker::GetTypeFromFileName(const nsAString& aFileName,
+                                              nsAString& aType)
 {
   aType.AssignLiteral(DEVICESTORAGE_SDCARD);
 
   nsString fileName(aFileName);
   int32_t dotIdx = fileName.RFindChar(PRUnichar('.'));
   if (dotIdx == kNotFound) {
     return;
   }
@@ -335,34 +350,36 @@ DeviceStorageTypeChecker::GetTypeFromFil
     aType.AssignLiteral(DEVICESTORAGE_VIDEOS);
   }
   else if (CaseInsensitiveFindInReadable(extensionMatch, mMusicExtensions)) {
     aType.AssignLiteral(DEVICESTORAGE_MUSIC);
   }
 }
 
 nsresult
-DeviceStorageTypeChecker::GetPermissionForType(const nsAString& aType, nsACString& aPermissionResult)
+DeviceStorageTypeChecker::GetPermissionForType(const nsAString& aType,
+                                               nsACString& aPermissionResult)
 {
   if (!aType.EqualsLiteral(DEVICESTORAGE_PICTURES) &&
       !aType.EqualsLiteral(DEVICESTORAGE_VIDEOS) &&
       !aType.EqualsLiteral(DEVICESTORAGE_MUSIC) &&
       !aType.EqualsLiteral(DEVICESTORAGE_APPS) &&
       !aType.EqualsLiteral(DEVICESTORAGE_SDCARD)) {
     // unknown type
     return NS_ERROR_FAILURE;
   }
 
   aPermissionResult.AssignLiteral("device-storage:");
   aPermissionResult.Append(NS_ConvertUTF16toUTF8(aType));
   return NS_OK;
 }
 
 nsresult
-DeviceStorageTypeChecker::GetAccessForRequest(const DeviceStorageRequestType aRequestType, nsACString& aAccessResult)
+DeviceStorageTypeChecker::GetAccessForRequest(
+  const DeviceStorageRequestType aRequestType, nsACString& aAccessResult)
 {
   switch(aRequestType) {
     case DEVICE_STORAGE_REQUEST_READ:
     case DEVICE_STORAGE_REQUEST_WATCH:
     case DEVICE_STORAGE_REQUEST_FREE_SPACE:
     case DEVICE_STORAGE_REQUEST_USED_SPACE:
     case DEVICE_STORAGE_REQUEST_AVAILABLE:
       aAccessResult.AssignLiteral("read");
@@ -421,20 +438,21 @@ FileUpdateDispatcher::Observe(nsISupport
 {
   if (XRE_GetProcessType() != GeckoProcessType_Default) {
 
     DeviceStorageFile* file = static_cast<DeviceStorageFile*>(aSubject);
     if (!file || !file->mFile) {
       NS_WARNING("Device storage file looks invalid!");
       return NS_OK;
     }
-    ContentChild::GetSingleton()->SendFilePathUpdateNotify(file->mStorageType,
-                                                           file->mStorageName,
-                                                           file->mPath,
-                                                           NS_ConvertUTF16toUTF8(aData));
+    ContentChild::GetSingleton()
+      ->SendFilePathUpdateNotify(file->mStorageType,
+                                 file->mStorageName,
+                                 file->mPath,
+                                 NS_ConvertUTF16toUTF8(aData));
   } else {
     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
     obs->NotifyObservers(aSubject, "file-watcher-update", aData);
   }
   return NS_OK;
 }
 
 class IOEventComplete : public nsRunnable
@@ -452,17 +470,18 @@ public:
   {
     NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     nsString data;
     CopyASCIItoUTF16(mType, data);
     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
 
     obs->NotifyObservers(mFile, "file-watcher-notify", data.get());
 
-    DeviceStorageUsedSpaceCache* usedSpaceCache = DeviceStorageUsedSpaceCache::CreateOrGet();
+    DeviceStorageUsedSpaceCache* usedSpaceCache
+      = DeviceStorageUsedSpaceCache::CreateOrGet();
     NS_ASSERTION(usedSpaceCache, "DeviceStorageUsedSpaceCache is null");
     usedSpaceCache->Invalidate(mFile->mStorageName);
     return NS_OK;
   }
 
 private:
   nsRefPtr<DeviceStorageFile> mFile;
   nsCString mType;
@@ -525,131 +544,143 @@ DeviceStorageFile::Dump(const char* labe
   }
   const char* ptStr;
   if (XRE_GetProcessType() == GeckoProcessType_Default) {
     ptStr = "parent";
   } else {
     ptStr = "child";
   }
 
-  printf_stderr("DSF (%s) %s: mStorageType '%s' mStorageName '%s' mRootDir '%s' mPath '%s' mFile->GetPath '%s'\n",
+  printf_stderr("DSF (%s) %s: mStorageType '%s' mStorageName '%s' "
+                "mRootDir '%s' mPath '%s' mFile->GetPath '%s'\n",
                 ptStr, label,
                 NS_LossyConvertUTF16toASCII(mStorageType).get(),
                 NS_LossyConvertUTF16toASCII(mStorageName).get(),
                 NS_LossyConvertUTF16toASCII(mRootDir).get(),
                 NS_LossyConvertUTF16toASCII(mPath).get(),
                 NS_LossyConvertUTF16toASCII(path).get());
 }
 
 void
 DeviceStorageFile::Init()
 {
   DeviceStorageFile::GetRootDirectoryForType(mStorageType,
                                              mStorageName,
                                              getter_AddRefs(mFile));
 
-  DebugOnly<DeviceStorageTypeChecker*> typeChecker = DeviceStorageTypeChecker::CreateOrGet();
+  DebugOnly<DeviceStorageTypeChecker*> typeChecker
+    = DeviceStorageTypeChecker::CreateOrGet();
   NS_ASSERTION(typeChecker, "DeviceStorageTypeChecker is null");
 }
 
 static void
 InitDirs()
 {
   if (sDirs) {
     return;
   }
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   sDirs = new GlobalDirs;
   ClearOnShutdown(&sDirs);
 
-  nsCOMPtr<nsIProperties> dirService = do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID);
+  nsCOMPtr<nsIProperties> dirService
+    = do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID);
   NS_ASSERTION(dirService, "Must have directory service");
 
 #if !defined(MOZ_WIDGET_GONK)
 
 #if defined (MOZ_WIDGET_COCOA)
-  dirService->Get(NS_OSX_PICTURE_DOCUMENTS_DIR, NS_GET_IID(nsIFile), getter_AddRefs(sDirs->pictures));
-  dirService->Get(NS_OSX_MOVIE_DOCUMENTS_DIR, NS_GET_IID(nsIFile), getter_AddRefs(sDirs->videos));
-  dirService->Get(NS_OSX_MUSIC_DOCUMENTS_DIR, NS_GET_IID(nsIFile), getter_AddRefs(sDirs->music));
+  dirService->Get(NS_OSX_PICTURE_DOCUMENTS_DIR,
+                  NS_GET_IID(nsIFile),
+                  getter_AddRefs(sDirs->pictures));
+  dirService->Get(NS_OSX_MOVIE_DOCUMENTS_DIR,
+                  NS_GET_IID(nsIFile),
+                  getter_AddRefs(sDirs->videos));
+  dirService->Get(NS_OSX_MUSIC_DOCUMENTS_DIR,
+                  NS_GET_IID(nsIFile),
+                  getter_AddRefs(sDirs->music));
 #elif defined (XP_UNIX)
-  dirService->Get(NS_UNIX_XDG_PICTURES_DIR, NS_GET_IID(nsIFile), getter_AddRefs(sDirs->pictures));
-  dirService->Get(NS_UNIX_XDG_VIDEOS_DIR, NS_GET_IID(nsIFile), getter_AddRefs(sDirs->videos));
-  dirService->Get(NS_UNIX_XDG_MUSIC_DIR, NS_GET_IID(nsIFile), getter_AddRefs(sDirs->music));
+  dirService->Get(NS_UNIX_XDG_PICTURES_DIR,
+                  NS_GET_IID(nsIFile),
+                  getter_AddRefs(sDirs->pictures));
+  dirService->Get(NS_UNIX_XDG_VIDEOS_DIR,
+                  NS_GET_IID(nsIFile),
+                  getter_AddRefs(sDirs->videos));
+  dirService->Get(NS_UNIX_XDG_MUSIC_DIR,
+                  NS_GET_IID(nsIFile),
+                  getter_AddRefs(sDirs->music));
 #elif defined (XP_WIN)
-  dirService->Get(NS_WIN_PICTURES_DIR, NS_GET_IID(nsIFile), getter_AddRefs(sDirs->pictures));
-  dirService->Get(NS_WIN_VIDEOS_DIR, NS_GET_IID(nsIFile), getter_AddRefs(sDirs->videos));
-  dirService->Get(NS_WIN_MUSIC_DIR, NS_GET_IID(nsIFile), getter_AddRefs(sDirs->music));
+  dirService->Get(NS_WIN_PICTURES_DIR,
+                  NS_GET_IID(nsIFile),
+                  getter_AddRefs(sDirs->pictures));
+  dirService->Get(NS_WIN_VIDEOS_DIR,
+                  NS_GET_IID(nsIFile),
+                  getter_AddRefs(sDirs->videos));
+  dirService->Get(NS_WIN_MUSIC_DIR,
+                  NS_GET_IID(nsIFile),
+                  getter_AddRefs(sDirs->music));
 #endif
 
-  dirService->Get(NS_APP_USER_PROFILE_50_DIR, NS_GET_IID(nsIFile), getter_AddRefs(sDirs->apps));
+  dirService->Get(NS_APP_USER_PROFILE_50_DIR, NS_GET_IID(nsIFile),
+                  getter_AddRefs(sDirs->apps));
   if (sDirs->apps) {
     sDirs->apps->AppendRelativeNativePath(NS_LITERAL_CSTRING("webapps"));
   }
 
   // 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(sDirs->sdcard));
+  dirService->Get(NS_APP_USER_PROFILE_50_DIR, NS_GET_IID(nsIFile),
+                  getter_AddRefs(sDirs->sdcard));
   if (sDirs->sdcard) {
     sDirs->sdcard->AppendRelativeNativePath(NS_LITERAL_CSTRING("fake-sdcard"));
   }
 #endif // !MOZ_WIDGET_GONK
 
   if (mozilla::Preferences::GetBool("device.storage.testing", false)) {
-    dirService->Get(NS_OS_TEMP_DIR, NS_GET_IID(nsIFile), getter_AddRefs(sDirs->temp));
+    dirService->Get(NS_OS_TEMP_DIR, NS_GET_IID(nsIFile),
+                    getter_AddRefs(sDirs->temp));
     if (sDirs->temp) {
-      sDirs->temp->AppendRelativeNativePath(NS_LITERAL_CSTRING("device-storage-testing"));
+      sDirs->temp->AppendRelativeNativePath(
+        NS_LITERAL_CSTRING("device-storage-testing"));
       sDirs->temp->Create(nsIFile::DIRECTORY_TYPE, 0777);
       sDirs->temp->Normalize();
     }
   }
 }
 
-bool DeviceStorageFile::IsComposite()
+void
+DeviceStorageFile::GetFullPath(nsAString &aFullPath)
 {
-  return DeviceStorageTypeChecker::IsVolumeBased(mStorageType) && 
-    mStorageName.EqualsLiteral("");
-}
-
-void
-DeviceStorageFile::GetCompositePath(nsAString &aCompositePath)
-{
-  aCompositePath.Truncate();
+  aFullPath.Truncate();
   if (!mStorageName.EqualsLiteral("")) {
-    aCompositePath.AppendLiteral("/");
-    aCompositePath.Append(mStorageName);
-    aCompositePath.AppendLiteral("/");
+    aFullPath.AppendLiteral("/");
+    aFullPath.Append(mStorageName);
+    aFullPath.AppendLiteral("/");
   }
   if (!mRootDir.EqualsLiteral("")) {
-    aCompositePath.Append(mRootDir);
-    aCompositePath.AppendLiteral("/");
+    aFullPath.Append(mRootDir);
+    aFullPath.AppendLiteral("/");
   }
-  aCompositePath.Append(mPath);
+  aFullPath.Append(mPath);
 }
 
 
 void
 DeviceStorageFile::GetRootDirectoryForType(const nsAString& aStorageType,
                                            const nsAString& aStorageName,
                                            nsIFile** aFile)
 {
   nsCOMPtr<nsIFile> f;
   *aFile = nullptr;
 
   InitDirs();
 
 #ifdef MOZ_WIDGET_GONK
   nsString volMountPoint;
   if (DeviceStorageTypeChecker::IsVolumeBased(aStorageType)) {
-    if (aStorageName.EqualsLiteral("")) {
-      // This DeviceStorageFile is for a composite device. Since the composite
-      // device doesn't have a root, we just allow mFile to be null. These
-      // should get resolved to real device objects later on.
-      return;
-    }
-
     nsCOMPtr<nsIVolumeService> vs = do_GetService(NS_VOLUMESERVICE_CONTRACTID);
     NS_ENSURE_TRUE_VOID(vs);
     nsresult rv;
     nsCOMPtr<nsIVolume> vol;
     rv = vs->GetVolumeByName(aStorageName, getter_AddRefs(vol));
     NS_ENSURE_SUCCESS_VOID(rv);
     vol->GetMountPoint(volMountPoint);
   }
@@ -711,37 +742,42 @@ DeviceStorageFile::GetRootDirectoryForTy
 }
 
 //static
 already_AddRefed<DeviceStorageFile>
 DeviceStorageFile::CreateUnique(nsAString& aFileName,
                                 uint32_t aFileType,
                                 uint32_t aFileAttributes)
 {
-  DeviceStorageTypeChecker* typeChecker = DeviceStorageTypeChecker::CreateOrGet();
+  DeviceStorageTypeChecker* typeChecker
+    = DeviceStorageTypeChecker::CreateOrGet();
   NS_ASSERTION(typeChecker, "DeviceStorageTypeChecker is null");
 
   nsString storageType;
   typeChecker->GetTypeFromFileName(aFileName, storageType);
 
   nsString storageName;
   nsString storagePath;
-  if (!nsDOMDeviceStorage::ParseCompositePath(aFileName, storageName, storagePath)) {
+  if (!nsDOMDeviceStorage::ParseFullPath(aFileName, storageName, storagePath)) {
     return nullptr;
   }
+  if (storageName.IsEmpty()) {
+    nsDOMDeviceStorage::GetDefaultStorageName(storageType, storageName);
+  }
   nsRefPtr<DeviceStorageFile> dsf =
     new DeviceStorageFile(storageType, storageName, storagePath);
   if (!dsf->mFile) {
     return nullptr;
   }
 
   nsresult rv = dsf->mFile->CreateUnique(aFileType, aFileAttributes);
   NS_ENSURE_SUCCESS(rv, nullptr);
 
-  // CreateUnique may cause the filename to change. So we need to update mPath to reflect that.
+  // CreateUnique may cause the filename to change. So we need to update mPath
+  // to reflect that.
   nsString leafName;
   dsf->mFile->GetLeafName(leafName);
 
   int32_t lastSlashIndex = dsf->mPath.RFindChar('/');
   if (lastSlashIndex == kNotFound) {
     dsf->mPath.Assign(leafName);
   } else {
     // Include the last '/'
@@ -865,19 +901,20 @@ DeviceStorageFile::Write(nsIInputStream*
   nsCOMPtr<nsIOutputStream> bufferedOutputStream;
   rv = NS_NewBufferedOutputStream(getter_AddRefs(bufferedOutputStream),
                                   outputStream,
                                   4096*4);
   NS_ENSURE_SUCCESS(rv, rv);
 
   while (bufSize) {
     uint32_t wrote;
-    rv = bufferedOutputStream->WriteFrom(aInputStream,
-                                         static_cast<uint32_t>(std::min<uint64_t>(bufSize, UINT32_MAX)),
-                                         &wrote);
+    rv = bufferedOutputStream->WriteFrom(
+      aInputStream,
+      static_cast<uint32_t>(std::min<uint64_t>(bufSize, UINT32_MAX)),
+      &wrote);
     if (NS_FAILED(rv)) {
       break;
     }
     bufSize -= wrote;
   }
 
   iocomplete = new IOEventComplete(this, "modified");
   NS_DispatchToMainThread(iocomplete);
@@ -993,37 +1030,25 @@ DeviceStorageFile::CalculateSizeAndModif
   return NS_OK;
 }
 
 void
 DeviceStorageFile::CollectFiles(nsTArray<nsRefPtr<DeviceStorageFile> > &aFiles,
                                 PRTime aSince)
 {
   nsString fullRootPath;
-
-  if (IsComposite()) {
-    nsDOMDeviceStorage::VolumeNameArray volNames;
-    nsDOMDeviceStorage::GetOrderedVolumeNames(volNames);
-    nsDOMDeviceStorage::VolumeNameArray::size_type numVolumes = volNames.Length();
-    nsDOMDeviceStorage::VolumeNameArray::index_type i;
-    for (i = 0; i < numVolumes; i++) {
-      DeviceStorageFile dsf(mStorageType, volNames[i], mRootDir, EmptyString());
-      dsf.mFile->GetPath(fullRootPath);
-      dsf.collectFilesInternal(aFiles, aSince, fullRootPath);
-    }
-    return;
-  }
   mFile->GetPath(fullRootPath);
   collectFilesInternal(aFiles, aSince, fullRootPath);
 }
 
 void
-DeviceStorageFile::collectFilesInternal(nsTArray<nsRefPtr<DeviceStorageFile> > &aFiles,
-                                        PRTime aSince,
-                                        nsAString& aRootPath)
+DeviceStorageFile::collectFilesInternal(
+  nsTArray<nsRefPtr<DeviceStorageFile> > &aFiles,
+  PRTime aSince,
+  nsAString& aRootPath)
 {
   if (!mFile || !IsAvailable()) {
     return;
   }
 
   nsCOMPtr<nsISimpleEnumerator> e;
   mFile->GetDirectoryEntries(getter_AddRefs(e));
 
@@ -1076,40 +1101,27 @@ DeviceStorageFile::collectFilesInternal(
 }
 
 void
 DeviceStorageFile::AccumDiskUsage(uint64_t* aPicturesSoFar,
                                   uint64_t* aVideosSoFar,
                                   uint64_t* aMusicSoFar,
                                   uint64_t* aTotalSoFar)
 {
-  if (IsComposite()) {
-    nsDOMDeviceStorage::VolumeNameArray volNames;
-    nsDOMDeviceStorage::GetOrderedVolumeNames(volNames);
-    nsDOMDeviceStorage::VolumeNameArray::size_type numVolumes = volNames.Length();
-    nsDOMDeviceStorage::VolumeNameArray::index_type i;
-    for (i = 0; i < numVolumes; i++) {
-      DeviceStorageFile dsf(mStorageType, volNames[i]);
-      dsf.AccumDiskUsage(aPicturesSoFar, aVideosSoFar,
-                         aMusicSoFar, aTotalSoFar);
-    }
-    return;
-  }
-
   if (!IsAvailable()) {
     return;
   }
 
   uint64_t pictureUsage = 0, videoUsage = 0, musicUsage = 0, totalUsage = 0;
 
   if (DeviceStorageTypeChecker::IsVolumeBased(mStorageType)) {
     DeviceStorageUsedSpaceCache* usedSpaceCache =
       DeviceStorageUsedSpaceCache::CreateOrGet();
     NS_ASSERTION(usedSpaceCache, "DeviceStorageUsedSpaceCache is null");
-    nsresult rv = usedSpaceCache->AccumUsedSizes(mStorageName, 
+    nsresult rv = usedSpaceCache->AccumUsedSizes(mStorageName,
                                                  aPicturesSoFar, aVideosSoFar,
                                                  aMusicSoFar, aTotalSoFar);
     if (NS_SUCCEEDED(rv)) {
       return;
     }
     AccumDirectoryUsage(mFile, &pictureUsage, &videoUsage,
                         &musicUsage, &totalUsage);
     usedSpaceCache->SetUsedSizes(mStorageName, pictureUsage, videoUsage,
@@ -1140,17 +1152,18 @@ DeviceStorageFile::AccumDirectoryUsage(n
   nsCOMPtr<nsISimpleEnumerator> e;
   rv = aFile->GetDirectoryEntries(getter_AddRefs(e));
 
   if (NS_FAILED(rv) || !e) {
     return;
   }
 
   nsCOMPtr<nsIDirectoryEnumerator> files = do_QueryInterface(e);
-  NS_ASSERTION(files, "GetDirectoryEntries must return a nsIDirectoryEnumerator");
+  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;
     }
@@ -1166,25 +1179,27 @@ DeviceStorageFile::AccumDirectoryUsage(n
     if (NS_FAILED(rv)) {
       continue;
     }
 
     if (isLink) {
       // for now, lets just totally ignore symlinks.
       NS_WARNING("DirectoryDiskUsage ignores symlinks");
     } else if (isDir) {
-      AccumDirectoryUsage(f, aPicturesSoFar, aVideosSoFar, aMusicSoFar, aTotalSoFar);
+      AccumDirectoryUsage(f, aPicturesSoFar, aVideosSoFar,
+                          aMusicSoFar, aTotalSoFar);
     } else if (isFile) {
 
       int64_t size;
       rv = f->GetFileSize(&size);
       if (NS_FAILED(rv)) {
         continue;
       }
-      DeviceStorageTypeChecker* typeChecker = DeviceStorageTypeChecker::CreateOrGet();
+      DeviceStorageTypeChecker* typeChecker
+        = DeviceStorageTypeChecker::CreateOrGet();
       NS_ASSERTION(typeChecker, "DeviceStorageTypeChecker is null");
       nsString type;
       typeChecker->GetTypeFromFile(f, type);
 
       if (type.EqualsLiteral(DEVICESTORAGE_PICTURES)) {
         *aPicturesSoFar += size;
       }
       else if (type.EqualsLiteral(DEVICESTORAGE_VIDEOS)) {
@@ -1196,32 +1211,21 @@ DeviceStorageFile::AccumDirectoryUsage(n
       *aTotalSoFar += size;
     }
   }
 }
 
 void
 DeviceStorageFile::GetDiskFreeSpace(int64_t* aSoFar)
 {
-  DeviceStorageTypeChecker* typeChecker = DeviceStorageTypeChecker::CreateOrGet();
+  DeviceStorageTypeChecker* typeChecker
+    = DeviceStorageTypeChecker::CreateOrGet();
   if (!typeChecker) {
     return;
   }
-  if (IsComposite()) {
-    nsDOMDeviceStorage::VolumeNameArray volNames;
-    nsDOMDeviceStorage::GetOrderedVolumeNames(volNames);
-    nsDOMDeviceStorage::VolumeNameArray::size_type numVolumes = volNames.Length();
-    nsDOMDeviceStorage::VolumeNameArray::index_type i;
-    for (i = 0; i < numVolumes; i++) {
-      DeviceStorageFile dsf(mStorageType, volNames[i]);
-      dsf.GetDiskFreeSpace(aSoFar);
-    }
-    return;
-  }
-
   if (!mFile || !IsAvailable()) {
     return;
   }
 
   int64_t storageAvail = 0;
   nsresult rv = mFile->GetDiskSpaceAvailable(&storageAvail);
   if (NS_SUCCEEDED(rv)) {
     *aSoFar += storageAvail;
@@ -1234,72 +1238,41 @@ DeviceStorageFile::IsAvailable()
   nsString status;
   GetStatus(status);
   return status.EqualsLiteral("available");
 }
 
 void
 DeviceStorageFile::GetStatus(nsAString& aStatus)
 {
-  DeviceStorageTypeChecker* typeChecker = DeviceStorageTypeChecker::CreateOrGet();
+  DeviceStorageTypeChecker* typeChecker
+    = DeviceStorageTypeChecker::CreateOrGet();
   if (!typeChecker) {
     return;
   }
   if (!typeChecker->IsVolumeBased(mStorageType)) {
     aStatus.AssignLiteral("available");
     return;
   }
 
-  if (!mStorageName.EqualsLiteral("")) {
-    GetStatusInternal(mStorageName, aStatus);
-    return;
-  }
-
-  // We want a composite status.
-
   aStatus.AssignLiteral("unavailable");
-
-  nsDOMDeviceStorage::VolumeNameArray volNames;
-  nsDOMDeviceStorage::GetOrderedVolumeNames(volNames);
-  nsDOMDeviceStorage::VolumeNameArray::size_type numVolumes = volNames.Length();
-  nsDOMDeviceStorage::VolumeNameArray::index_type i;
-  for (i = 0; i < numVolumes; i++) {
-    nsString  volStatus;
-    GetStatusInternal(volNames[i], volStatus);
-    if (volStatus.EqualsLiteral("available")) {
-      // We found an available volume. We can quit now, since the composite
-      // status is available if any are available
-      aStatus = volStatus;
-      return;
-    }
-    if (volStatus.EqualsLiteral("shared")) {
-      aStatus = volStatus;
-      // need to keep looking since we might find an available volume later.
-    }
-  }
-}
-
-void
-DeviceStorageFile::GetStatusInternal(nsAString& aStorageName, nsAString& aStatus)
-{
-  aStatus.AssignLiteral("unavailable");
-
 #ifdef MOZ_WIDGET_GONK
   nsCOMPtr<nsIVolumeService> vs = do_GetService(NS_VOLUMESERVICE_CONTRACTID);
   NS_ENSURE_TRUE_VOID(vs);
 
   nsCOMPtr<nsIVolume> vol;
-  nsresult rv = vs->GetVolumeByName(aStorageName, getter_AddRefs(vol));
+  nsresult rv = vs->GetVolumeByName(mStorageName, getter_AddRefs(vol));
   NS_ENSURE_SUCCESS_VOID(rv);
   int32_t volState;
   rv = vol->GetState(&volState);
   NS_ENSURE_SUCCESS_VOID(rv);
   if (volState == nsIVolume::STATE_MOUNTED) {
     aStatus.AssignLiteral("available");
-  } else if (volState == nsIVolume::STATE_SHARED || volState == nsIVolume::STATE_SHAREDMNT) {
+  } else if (volState == nsIVolume::STATE_SHARED ||
+             volState == nsIVolume::STATE_SHAREDMNT) {
     aStatus.AssignLiteral("shared");
   }
 #endif
 }
 
 NS_IMPL_ISUPPORTS0(DeviceStorageFile)
 
 static void
@@ -1332,17 +1305,19 @@ nsDOMDeviceStorage::SetRootDirectoryForT
   obs->AddObserver(this, "file-watcher-update", false);
   obs->AddObserver(this, "disk-space-watcher", false);
   mRootDirectory = f;
   mStorageType = aStorageType;
   mStorageName = aStorageName;
 }
 
 JS::Value
-InterfaceToJsval(nsPIDOMWindow* aWindow, nsISupports* aObject, const nsIID* aIID)
+InterfaceToJsval(nsPIDOMWindow* aWindow,
+                 nsISupports* aObject,
+                 const nsIID* aIID)
 {
   AutoJSContext cx;
   nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(aWindow);
   if (!sgo) {
     return JSVAL_NULL;
   }
 
   JS::RootedObject scopeObj(cx, sgo->GetGlobalJSObject());
@@ -1373,26 +1348,27 @@ nsIFileToJsval(nsPIDOMWindow* aWindow, D
     return JSVAL_NULL;
   }
 
   if (aFile->mEditable) {
     // TODO - needs janv's file handle support.
     return JSVAL_NULL;
   }
 
-  nsString  compositePath;
-  aFile->GetCompositePath(compositePath);
+  nsString fullPath;
+  aFile->GetFullPath(fullPath);
 
   // This check is useful to know if somewhere the DeviceStorageFile
   // has not been properly set. Mimetype is not checked because it can be
   // empty.
   NS_ASSERTION(aFile->mLength != UINT64_MAX, "Size not set");
-  NS_ASSERTION(aFile->mLastModifiedDate != UINT64_MAX, "LastModifiedDate not set");
-
-  nsCOMPtr<nsIDOMBlob> blob = new nsDOMFileFile(compositePath, aFile->mMimeType,
+  NS_ASSERTION(aFile->mLastModifiedDate != UINT64_MAX,
+               "LastModifiedDate not set");
+
+  nsCOMPtr<nsIDOMBlob> blob = new nsDOMFileFile(fullPath, aFile->mMimeType,
                                                 aFile->mLength, aFile->mFile,
                                                 aFile->mLastModifiedDate);
   return InterfaceToJsval(aWindow, blob, &NS_GET_IID(nsIDOMBlob));
 }
 
 JS::Value StringToJsval(nsPIDOMWindow* aWindow, nsAString& aString)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
@@ -1422,17 +1398,18 @@ JS::Value StringToJsval(nsPIDOMWindow* a
 }
 
 class DeviceStorageCursorRequest MOZ_FINAL
   : public nsIContentPermissionRequest
   , public PCOMContentPermissionRequestChild
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(DeviceStorageCursorRequest, nsIContentPermissionRequest)
+  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(DeviceStorageCursorRequest,
+                                           nsIContentPermissionRequest)
 
   NS_FORWARD_NSICONTENTPERMISSIONREQUEST(mCursor->);
 
   DeviceStorageCursorRequest(nsDOMDeviceStorageCursor* aCursor)
     : mCursor(aCursor) { }
 
   ~DeviceStorageCursorRequest() {}
 
@@ -1508,21 +1485,23 @@ ContinueCursorEvent::ContinueCursorEvent
 {
 }
 
 already_AddRefed<DeviceStorageFile>
 ContinueCursorEvent::GetNextFile()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
-  nsDOMDeviceStorageCursor* cursor = static_cast<nsDOMDeviceStorageCursor*>(mRequest.get());
+  nsDOMDeviceStorageCursor* cursor
+    = static_cast<nsDOMDeviceStorageCursor*>(mRequest.get());
   nsString cursorStorageType;
   cursor->GetStorageType(cursorStorageType);
 
-  DeviceStorageTypeChecker* typeChecker = DeviceStorageTypeChecker::CreateOrGet();
+  DeviceStorageTypeChecker* typeChecker
+    = DeviceStorageTypeChecker::CreateOrGet();
   if (!typeChecker) {
     return nullptr;
   }
 
   while (cursor->mFiles.Length() > 0) {
     nsRefPtr<DeviceStorageFile> file = cursor->mFiles[0];
     cursor->mFiles.RemoveElementAt(0);
     if (!typeChecker->Check(cursorStorageType, file->mFile)) {
@@ -1549,36 +1528,40 @@ ContinueCursorEvent::Continue()
   nsRefPtr<DeviceStorageFile> file = GetNextFile();
 
   if (!file) {
     // done with enumeration.
     NS_DispatchToMainThread(this);
     return;
   }
 
-  nsDOMDeviceStorageCursor* cursor = static_cast<nsDOMDeviceStorageCursor*>(mRequest.get());
+  nsDOMDeviceStorageCursor* cursor
+    = static_cast<nsDOMDeviceStorageCursor*>(mRequest.get());
   nsString cursorStorageType;
   cursor->GetStorageType(cursorStorageType);
 
-  DeviceStorageRequestChild* child = new DeviceStorageRequestChild(mRequest, file);
+  DeviceStorageRequestChild* child
+    = new DeviceStorageRequestChild(mRequest, file);
   child->SetCallback(cursor);
   DeviceStorageGetParams params(cursorStorageType,
                                 file->mStorageName,
                                 file->mRootDir,
                                 file->mPath);
-  ContentChild::GetSingleton()->SendPDeviceStorageRequestConstructor(child, params);
+  ContentChild::GetSingleton()->SendPDeviceStorageRequestConstructor(child,
+                                                                     params);
   mRequest = nullptr;
 }
 
 NS_IMETHODIMP
 ContinueCursorEvent::Run()
 {
   nsRefPtr<DeviceStorageFile> file = GetNextFile();
 
-  nsDOMDeviceStorageCursor* cursor = static_cast<nsDOMDeviceStorageCursor*>(mRequest.get());
+  nsDOMDeviceStorageCursor* cursor
+    = static_cast<nsDOMDeviceStorageCursor*>(mRequest.get());
 
   AutoJSContext cx;
   JS::Rooted<JS::Value> val(cx, nsIFileToJsval(cursor->GetOwner(), file));
 
   if (file) {
     cursor->mOkToCallContinue = true;
     cursor->FireSuccess(val);
   } else {
@@ -1602,26 +1585,29 @@ public:
   NS_IMETHOD Run() {
     NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
 
     if (mFile->mFile) {
       bool check;
       mFile->mFile->IsDirectory(&check);
       if (!check) {
         nsCOMPtr<PostErrorEvent> event =
-          new PostErrorEvent(mRequest.forget(), POST_ERROR_EVENT_FILE_NOT_ENUMERABLE);
+          new PostErrorEvent(mRequest.forget(),
+                             POST_ERROR_EVENT_FILE_NOT_ENUMERABLE);
         NS_DispatchToMainThread(event);
         return NS_OK;
       }
     }
 
-    nsDOMDeviceStorageCursor* cursor = static_cast<nsDOMDeviceStorageCursor*>(mRequest.get());
+    nsDOMDeviceStorageCursor* cursor
+      = static_cast<nsDOMDeviceStorageCursor*>(mRequest.get());
     mFile->CollectFiles(cursor->mFiles, cursor->mSince);
 
-    nsCOMPtr<ContinueCursorEvent> event = new ContinueCursorEvent(mRequest.forget());
+    nsCOMPtr<ContinueCursorEvent> event
+      = new ContinueCursorEvent(mRequest.forget());
     event->Continue();
 
     return NS_OK;
   }
 
 
 private:
   nsRefPtr<DeviceStorageFile> mFile;
@@ -1655,17 +1641,18 @@ void
 nsDOMDeviceStorageCursor::GetStorageType(nsAString & aType)
 {
   aType = mFile->mStorageType;
 }
 
 NS_IMETHODIMP
 nsDOMDeviceStorageCursor::GetType(nsACString & aType)
 {
-  return DeviceStorageTypeChecker::GetPermissionForType(mFile->mStorageType, aType);
+  return DeviceStorageTypeChecker::GetPermissionForType(mFile->mStorageType,
+                                                        aType);
 }
 
 NS_IMETHODIMP
 nsDOMDeviceStorageCursor::GetAccess(nsACString & aAccess)
 {
   aAccess = NS_LITERAL_CSTRING("read");
   return NS_OK;
 }
@@ -1689,41 +1676,46 @@ nsDOMDeviceStorageCursor::GetElement(nsI
 {
   *aRequestingElement = nullptr;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMDeviceStorageCursor::Cancel()
 {
-  nsCOMPtr<PostErrorEvent> event = new PostErrorEvent(this, POST_ERROR_EVENT_PERMISSION_DENIED);
+  nsCOMPtr<PostErrorEvent> event
+    = new PostErrorEvent(this, POST_ERROR_EVENT_PERMISSION_DENIED);
   NS_DispatchToMainThread(event);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMDeviceStorageCursor::Allow()
 {
   if (!mFile->IsSafePath()) {
-    nsCOMPtr<nsIRunnable> r = new PostErrorEvent(this, POST_ERROR_EVENT_PERMISSION_DENIED);
+    nsCOMPtr<nsIRunnable> r
+      = new PostErrorEvent(this, POST_ERROR_EVENT_PERMISSION_DENIED);
     NS_DispatchToMainThread(r);
     return NS_OK;
   }
 
   if (XRE_GetProcessType() != GeckoProcessType_Default) {
-    PDeviceStorageRequestChild* child = new DeviceStorageRequestChild(this, mFile);
+    PDeviceStorageRequestChild* child
+      = new DeviceStorageRequestChild(this, mFile);
     DeviceStorageEnumerationParams params(mFile->mStorageType,
                                           mFile->mStorageName,
                                           mFile->mRootDir,
                                           mSince);
-    ContentChild::GetSingleton()->SendPDeviceStorageRequestConstructor(child, params);
+    ContentChild::GetSingleton()->SendPDeviceStorageRequestConstructor(child,
+                                                                       params);
     return NS_OK;
   }
 
-  nsCOMPtr<nsIEventTarget> target = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
+  nsCOMPtr<nsIEventTarget> target
+    = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
   NS_ASSERTION(target, "Must have stream transport service");
 
   nsCOMPtr<InitCursorEvent> event = new InitCursorEvent(this, mFile);
   target->Dispatch(event, NS_DISPATCH_NORMAL);
   return NS_OK;
 }
 
 void
@@ -1790,41 +1782,45 @@ public:
     NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
     nsString state = NS_LITERAL_STRING("unavailable");
     if (mFile) {
       mFile->GetStatus(state);
     }
 
     AutoJSContext cx;
-    JS::Rooted<JS::Value> result(cx, StringToJsval(mRequest->GetOwner(), state));
+    JS::Rooted<JS::Value> result(cx,
+                                 StringToJsval(mRequest->GetOwner(), state));
     mRequest->FireSuccess(result);
     mRequest = nullptr;
     return NS_OK;
   }
 
 private:
   nsRefPtr<DeviceStorageFile> mFile;
   nsRefPtr<DOMRequest> mRequest;
 };
 
 class PostResultEvent : public nsRunnable
 {
 public:
-  PostResultEvent(already_AddRefed<DOMRequest> aRequest, DeviceStorageFile* aFile)
+  PostResultEvent(already_AddRefed<DOMRequest> aRequest,
+                  DeviceStorageFile* aFile)
     : mFile(aFile)
     , mRequest(aRequest)
   {}
 
-  PostResultEvent(already_AddRefed<DOMRequest> aRequest, const nsAString & aPath)
+  PostResultEvent(already_AddRefed<DOMRequest> aRequest,
+                  const nsAString & aPath)
     : mPath(aPath)
     , mRequest(aRequest)
   {}
 
-  PostResultEvent(already_AddRefed<DOMRequest> aRequest, const uint64_t aValue)
+  PostResultEvent(already_AddRefed<DOMRequest> aRequest,
+                  const uint64_t aValue)
     : mValue(aValue)
     , mRequest(aRequest)
   {}
 
   ~PostResultEvent() {}
 
   NS_IMETHOD Run()
   {
@@ -1873,34 +1869,37 @@ public:
     NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
 
     nsCOMPtr<nsIInputStream> stream;
     mBlob->GetInternalStream(getter_AddRefs(stream));
 
     bool check = false;
     mFile->mFile->Exists(&check);
     if (check) {
-      nsCOMPtr<PostErrorEvent> event = new PostErrorEvent(mRequest.forget(), POST_ERROR_EVENT_FILE_EXISTS);
+      nsCOMPtr<PostErrorEvent> event =
+        new PostErrorEvent(mRequest.forget(), POST_ERROR_EVENT_FILE_EXISTS);
       NS_DispatchToMainThread(event);
       return NS_OK;
     }
 
     nsresult rv = mFile->Write(stream);
 
     if (NS_FAILED(rv)) {
       mFile->mFile->Remove(false);
 
-      nsCOMPtr<PostErrorEvent> event = new PostErrorEvent(mRequest.forget(), POST_ERROR_EVENT_UNKNOWN);
+      nsCOMPtr<PostErrorEvent> event =
+        new PostErrorEvent(mRequest.forget(), POST_ERROR_EVENT_UNKNOWN);
       NS_DispatchToMainThread(event);
       return NS_OK;
     }
 
-    nsString compositePath;
-    mFile->GetCompositePath(compositePath);
-    nsCOMPtr<PostResultEvent> event = new PostResultEvent(mRequest.forget(), compositePath);
+    nsString fullPath;
+    mFile->GetFullPath(fullPath);
+    nsCOMPtr<PostResultEvent> event =
+      new PostResultEvent(mRequest.forget(), fullPath);
     NS_DispatchToMainThread(event);
     return NS_OK;
   }
 
 private:
   nsCOMPtr<nsIDOMBlob> mBlob;
   nsRefPtr<DeviceStorageFile> mFile;
   nsRefPtr<DOMRequest> mRequest;
@@ -1923,17 +1922,18 @@ public:
   {
     NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
 
     nsRefPtr<nsRunnable> r;
     if (!mFile->mEditable) {
       bool check = false;
       mFile->mFile->Exists(&check);
       if (!check) {
-        r = new PostErrorEvent(mRequest.forget(), POST_ERROR_EVENT_FILE_DOES_NOT_EXIST);
+        r = new PostErrorEvent(mRequest.forget(),
+                               POST_ERROR_EVENT_FILE_DOES_NOT_EXIST);
       }
     }
 
     if (!r) {
       nsresult rv = mFile->CalculateSizeAndModifiedDate();
       if (NS_FAILED(rv)) {
         r = new PostErrorEvent(mRequest.forget(), POST_ERROR_EVENT_UNKNOWN);
       }
@@ -1966,22 +1966,23 @@ public:
   {
     NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
     mFile->Remove();
 
     nsRefPtr<nsRunnable> r;
     bool check = false;
     mFile->mFile->Exists(&check);
     if (check) {
-      r = new PostErrorEvent(mRequest.forget(), POST_ERROR_EVENT_FILE_DOES_NOT_EXIST);
+      r = new PostErrorEvent(mRequest.forget(),
+                             POST_ERROR_EVENT_FILE_DOES_NOT_EXIST);
     }
     else {
-      nsString compositePath;
-      mFile->GetCompositePath(compositePath);
-      r = new PostResultEvent(mRequest.forget(), compositePath);
+      nsString fullPath;
+      mFile->GetFullPath(fullPath);
+      r = new PostResultEvent(mRequest.forget(), fullPath);
     }
     NS_DispatchToMainThread(r);
     return NS_OK;
   }
 
 private:
   nsRefPtr<DeviceStorageFile> mFile;
   nsRefPtr<DOMRequest> mRequest;
@@ -2042,17 +2043,18 @@ public:
     NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
 
     int64_t freeSpace = 0;
     if (mFile) {
       mFile->GetDiskFreeSpace(&freeSpace);
     }
 
     nsCOMPtr<nsIRunnable> r;
-    r = new PostResultEvent(mRequest.forget(), static_cast<uint64_t>(freeSpace));
+    r = new PostResultEvent(mRequest.forget(),
+                            static_cast<uint64_t>(freeSpace));
     NS_DispatchToMainThread(r);
     return NS_OK;
   }
 
 private:
   nsRefPtr<DeviceStorageFile> mFile;
   nsRefPtr<DOMRequest> mRequest;
 };
@@ -2087,17 +2089,18 @@ public:
       : mRequestType(aRequestType)
       , mWindow(aWindow)
       , mPrincipal(aPrincipal)
       , mFile(aFile)
       , mRequest(aRequest)
       , mBlob(aBlob) {}
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(DeviceStorageRequest, nsIContentPermissionRequest)
+  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(DeviceStorageRequest,
+                                           nsIContentPermissionRequest)
 
   NS_IMETHOD Run() {
 
     if (mozilla::Preferences::GetBool("device.storage.prompt.testing", false)) {
       Allow();
       return NS_OK;
     }
 
@@ -2105,56 +2108,64 @@ public:
 
       // because owner implements nsITabChild, we can assume that it is
       // the one and only TabChild.
       TabChild* child = GetTabChildFrom(mWindow->GetDocShell());
       if (!child) {
         return NS_OK;
       }
 
-      // Retain a reference so the object isn't deleted without IPDL's knowledge.
-      // Corresponding release occurs in DeallocPContentPermissionRequest.
+      // Retain a reference so the object isn't deleted without IPDL's
+      // knowledge. Corresponding release occurs in
+      // DeallocPContentPermissionRequest.
       AddRef();
 
       nsCString type;
-      nsresult rv = DeviceStorageTypeChecker::GetPermissionForType(mFile->mStorageType, type);
+      nsresult rv = DeviceStorageTypeChecker::GetPermissionForType(
+        mFile->mStorageType, type);
       if (NS_FAILED(rv)) {
         return rv;
       }
       nsCString access;
-      rv = DeviceStorageTypeChecker::GetAccessForRequest(DeviceStorageRequestType(mRequestType), access);
+      rv = DeviceStorageTypeChecker::GetAccessForRequest(
+        DeviceStorageRequestType(mRequestType), access);
       if (NS_FAILED(rv)) {
         return rv;
       }
-      child->SendPContentPermissionRequestConstructor(this, type, access, IPC::Principal(mPrincipal));
+      child->SendPContentPermissionRequestConstructor(
+        this, type, access, IPC::Principal(mPrincipal));
 
       Sendprompt();
       return NS_OK;
     }
 
-    nsCOMPtr<nsIContentPermissionPrompt> prompt = do_CreateInstance(NS_CONTENT_PERMISSION_PROMPT_CONTRACTID);
+    nsCOMPtr<nsIContentPermissionPrompt> prompt
+      = do_CreateInstance(NS_CONTENT_PERMISSION_PROMPT_CONTRACTID);
     if (prompt) {
       prompt->Prompt(this);
     }
     return NS_OK;
   }
 
   NS_IMETHOD GetType(nsACString & aType)
   {
     nsCString type;
-    nsresult rv = DeviceStorageTypeChecker::GetPermissionForType(mFile->mStorageType, aType);
+    nsresult rv
+      = DeviceStorageTypeChecker::GetPermissionForType(mFile->mStorageType,
+                                                       aType);
     if (NS_FAILED(rv)) {
       return rv;
     }
     return NS_OK;
   }
 
   NS_IMETHOD GetAccess(nsACString & aAccess)
   {
-    nsresult rv = DeviceStorageTypeChecker::GetAccessForRequest(DeviceStorageRequestType(mRequestType), aAccess);
+    nsresult rv = DeviceStorageTypeChecker::GetAccessForRequest(
+      DeviceStorageRequestType(mRequestType), aAccess);
     if (NS_FAILED(rv)) {
       return rv;
     }
     return NS_OK;
   }
 
   NS_IMETHOD GetPrincipal(nsIPrincipal * *aRequestingPrincipal)
   {
@@ -2171,17 +2182,19 @@ public:
   NS_IMETHOD GetElement(nsIDOMElement * *aRequestingElement)
   {
     *aRequestingElement = nullptr;
     return NS_OK;
   }
 
   NS_IMETHOD Cancel()
   {
-    nsCOMPtr<PostErrorEvent> event = new PostErrorEvent(mRequest.forget(), POST_ERROR_EVENT_PERMISSION_DENIED);
+    nsCOMPtr<PostErrorEvent> event
+      = new PostErrorEvent(mRequest.forget(),
+                           POST_ERROR_EVENT_PERMISSION_DENIED);
     NS_DispatchToMainThread(event);
     return NS_OK;
   }
 
   NS_IMETHOD Allow()
   {
     nsCOMPtr<nsIRunnable> r;
 
@@ -2191,164 +2204,185 @@ public:
 
     switch(mRequestType) {
       case DEVICE_STORAGE_REQUEST_CREATE:
       {
         if (!mBlob || !mFile->mFile) {
           return NS_ERROR_FAILURE;
         }
 
-        DeviceStorageTypeChecker* typeChecker = DeviceStorageTypeChecker::CreateOrGet();
+        DeviceStorageTypeChecker* typeChecker
+          = DeviceStorageTypeChecker::CreateOrGet();
         if (!typeChecker) {
           return NS_OK;
         }
 
         if (!typeChecker->Check(mFile->mStorageType, mFile->mFile) ||
             !typeChecker->Check(mFile->mStorageType, mBlob)) {
-          r = new PostErrorEvent(mRequest.forget(), POST_ERROR_EVENT_ILLEGAL_TYPE);
+          r = new PostErrorEvent(mRequest.forget(),
+                                 POST_ERROR_EVENT_ILLEGAL_TYPE);
           NS_DispatchToMainThread(r);
           return NS_OK;
         }
 
         if (XRE_GetProcessType() != GeckoProcessType_Default) {
 
-          BlobChild* actor = ContentChild::GetSingleton()->GetOrCreateActorForBlob(mBlob);
+          BlobChild* actor
+            = ContentChild::GetSingleton()->GetOrCreateActorForBlob(mBlob);
           if (!actor) {
             return NS_ERROR_FAILURE;
           }
 
           DeviceStorageAddParams params;
           params.blobChild() = actor;
           params.type() = mFile->mStorageType;
           params.storageName() = mFile->mStorageName;
           params.relpath() = mFile->mPath;
 
-          PDeviceStorageRequestChild* child = new DeviceStorageRequestChild(mRequest, mFile);
-          ContentChild::GetSingleton()->SendPDeviceStorageRequestConstructor(child, params);
+          PDeviceStorageRequestChild* child
+            = new DeviceStorageRequestChild(mRequest, mFile);
+          ContentChild::GetSingleton()
+            ->SendPDeviceStorageRequestConstructor(child, params);
           return NS_OK;
         }
         r = new WriteFileEvent(mBlob, mFile, mRequest.forget());
         break;
       }
 
       case DEVICE_STORAGE_REQUEST_READ:
       case DEVICE_STORAGE_REQUEST_WRITE:
       {
         if (!mFile->mFile) {
           return NS_ERROR_FAILURE;
         }
 
-        DeviceStorageTypeChecker* typeChecker = DeviceStorageTypeChecker::CreateOrGet();
+        DeviceStorageTypeChecker* typeChecker
+          = DeviceStorageTypeChecker::CreateOrGet();
         if (!typeChecker) {
           return NS_OK;
         }
 
         if (!typeChecker->Check(mFile->mStorageType, mFile->mFile)) {
-          r = new PostErrorEvent(mRequest.forget(), POST_ERROR_EVENT_ILLEGAL_TYPE);
+          r = new PostErrorEvent(mRequest.forget(),
+                                 POST_ERROR_EVENT_ILLEGAL_TYPE);
           NS_DispatchToMainThread(r);
           return NS_OK;
         }
 
         if (XRE_GetProcessType() != GeckoProcessType_Default) {
-          PDeviceStorageRequestChild* child = new DeviceStorageRequestChild(mRequest, mFile);
+          PDeviceStorageRequestChild* child
+            = new DeviceStorageRequestChild(mRequest, mFile);
           DeviceStorageGetParams params(mFile->mStorageType,
                                         mFile->mStorageName,
                                         mFile->mRootDir,
                                         mFile->mPath);
-          ContentChild::GetSingleton()->SendPDeviceStorageRequestConstructor(child, params);
+          ContentChild::GetSingleton()
+            ->SendPDeviceStorageRequestConstructor(child, params);
           return NS_OK;
         }
 
         r = new ReadFileEvent(mFile, mRequest.forget());
         break;
       }
 
       case DEVICE_STORAGE_REQUEST_DELETE:
       {
         if (!mFile->mFile) {
           return NS_ERROR_FAILURE;
         }
 
-        DeviceStorageTypeChecker* typeChecker = DeviceStorageTypeChecker::CreateOrGet();
+        DeviceStorageTypeChecker* typeChecker
+          = DeviceStorageTypeChecker::CreateOrGet();
         if (!typeChecker) {
           return NS_OK;
         }
 
         if (!typeChecker->Check(mFile->mStorageType, mFile->mFile)) {
-          r = new PostErrorEvent(mRequest.forget(), POST_ERROR_EVENT_ILLEGAL_TYPE);
+          r = new PostErrorEvent(mRequest.forget(),
+                                 POST_ERROR_EVENT_ILLEGAL_TYPE);
           NS_DispatchToMainThread(r);
           return NS_OK;
         }
 
         if (XRE_GetProcessType() != GeckoProcessType_Default) {
-          PDeviceStorageRequestChild* child = new DeviceStorageRequestChild(mRequest, mFile);
+          PDeviceStorageRequestChild* child
+            = new DeviceStorageRequestChild(mRequest, mFile);
           DeviceStorageDeleteParams params(mFile->mStorageType,
                                            mFile->mStorageName,
                                            mFile->mPath);
-          ContentChild::GetSingleton()->SendPDeviceStorageRequestConstructor(child, params);
+          ContentChild::GetSingleton()
+            ->SendPDeviceStorageRequestConstructor(child, params);
           return NS_OK;
         }
         r = new DeleteFileEvent(mFile, mRequest.forget());
         break;
       }
 
       case DEVICE_STORAGE_REQUEST_FREE_SPACE:
       {
         if (XRE_GetProcessType() != GeckoProcessType_Default) {
-          PDeviceStorageRequestChild* child = new DeviceStorageRequestChild(mRequest, mFile);
+          PDeviceStorageRequestChild* child
+            = new DeviceStorageRequestChild(mRequest, mFile);
           DeviceStorageFreeSpaceParams params(mFile->mStorageType,
                                               mFile->mStorageName);
-          ContentChild::GetSingleton()->SendPDeviceStorageRequestConstructor(child, params);
+          ContentChild::GetSingleton()
+            ->SendPDeviceStorageRequestConstructor(child, params);
           return NS_OK;
         }
         r = new FreeSpaceFileEvent(mFile, mRequest.forget());
         break;
       }
 
       case DEVICE_STORAGE_REQUEST_USED_SPACE:
       {
         if (XRE_GetProcessType() != GeckoProcessType_Default) {
-          PDeviceStorageRequestChild* child = new DeviceStorageRequestChild(mRequest, mFile);
+          PDeviceStorageRequestChild* child
+            = new DeviceStorageRequestChild(mRequest, mFile);
           DeviceStorageUsedSpaceParams params(mFile->mStorageType,
                                               mFile->mStorageName);
-          ContentChild::GetSingleton()->SendPDeviceStorageRequestConstructor(child, params);
+          ContentChild::GetSingleton()
+            ->SendPDeviceStorageRequestConstructor(child, params);
           return NS_OK;
         }
         // this needs to be dispatched to only one (1)
         // thread or we will do more work than required.
-        DeviceStorageUsedSpaceCache* usedSpaceCache = DeviceStorageUsedSpaceCache::CreateOrGet();
+        DeviceStorageUsedSpaceCache* usedSpaceCache
+          = DeviceStorageUsedSpaceCache::CreateOrGet();
         NS_ASSERTION(usedSpaceCache, "DeviceStorageUsedSpaceCache is null");
         r = new UsedSpaceFileEvent(mFile, mRequest.forget());
         usedSpaceCache->Dispatch(r);
         return NS_OK;
       }
 
       case DEVICE_STORAGE_REQUEST_AVAILABLE:
       {
         if (XRE_GetProcessType() != GeckoProcessType_Default) {
-          PDeviceStorageRequestChild* child = new DeviceStorageRequestChild(mRequest, mFile);
+          PDeviceStorageRequestChild* child
+            = new DeviceStorageRequestChild(mRequest, mFile);
           DeviceStorageAvailableParams params(mFile->mStorageType,
                                               mFile->mStorageName);
-          ContentChild::GetSingleton()->SendPDeviceStorageRequestConstructor(child, params);
+          ContentChild::GetSingleton()
+            ->SendPDeviceStorageRequestConstructor(child, params);
           return NS_OK;
         }
         r = new PostAvailableResultEvent(mFile, mRequest);
         NS_DispatchToMainThread(r);
         return NS_OK;
       }
 
       case DEVICE_STORAGE_REQUEST_WATCH:
       {
         mDeviceStorage->mAllowedToWatchFile = true;
         return NS_OK;
       }
     }
 
     if (r) {
-      nsCOMPtr<nsIEventTarget> target = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
+      nsCOMPtr<nsIEventTarget> target
+        = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
       NS_ASSERTION(target, "Must have stream transport service");
       target->Dispatch(r, NS_DISPATCH_NORMAL);
     }
 
     return NS_OK;
   }
 
   bool Recv__delete__(const bool& allow)
@@ -2398,79 +2432,67 @@ NS_INTERFACE_MAP_BEGIN(nsDOMDeviceStorag
   NS_INTERFACE_MAP_ENTRY(nsIDOMDeviceStorage)
   NS_INTERFACE_MAP_ENTRY(nsIObserver)
 NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
 
 NS_IMPL_ADDREF_INHERITED(nsDOMDeviceStorage, nsDOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(nsDOMDeviceStorage, nsDOMEventTargetHelper)
 
 nsDOMDeviceStorage::nsDOMDeviceStorage()
-  : mCompositeComponent(false),
-    mIsWatchingFile(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)
+                         const nsAString &aVolName)
 {
-  mStores.AppendElements(aStores);
-  nsresult rv = Init(aWindow, aType, EmptyString());
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return NS_OK;
-}
-
-nsresult
-nsDOMDeviceStorage::Init(nsPIDOMWindow* aWindow, const nsAString &aType, const nsAString &aVolName)
-{
-  DebugOnly<FileUpdateDispatcher*> observer = FileUpdateDispatcher::GetSingleton();
+  DebugOnly<FileUpdateDispatcher*> observer
+    = FileUpdateDispatcher::GetSingleton();
   NS_ASSERTION(observer, "FileUpdateDispatcher is null");
 
   NS_ASSERTION(aWindow, "Must have a content dom");
 
-  if (IsComposite()) {
-    mStorageType = aType;
-  } else {
-    SetRootDirectoryForType(aType, aVolName);
-    if (!mRootDirectory) {
-      return NS_ERROR_NOT_AVAILABLE;
-    }
+  SetRootDirectoryForType(aType, aVolName);
+  if (!mRootDirectory) {
+    return NS_ERROR_NOT_AVAILABLE;
   }
-  if (!IsCompositeComponent()) {
+  if (!mStorageName.IsEmpty()) {
     RegisterForSDCardChanges(this);
   }
 
   BindToOwner(aWindow);
 
   // Grab the principal of the document
   nsCOMPtr<nsIDocument> doc = aWindow->GetDoc();
   if (!doc) {
     return NS_ERROR_FAILURE;
   }
   mPrincipal = doc->NodePrincipal();
 
   // the 'apps' type is special.  We only want this exposed
   // if the caller has the "webapps-manage" permission.
   if (aType.EqualsLiteral("apps")) {
-    nsCOMPtr<nsIPermissionManager> permissionManager = do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
+    nsCOMPtr<nsIPermissionManager> permissionManager
+      = do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
     NS_ENSURE_TRUE(permissionManager, NS_ERROR_FAILURE);
 
     uint32_t permission;
-    nsresult rv = permissionManager->TestPermissionFromPrincipal(mPrincipal,
-                                                                 "webapps-manage",
-                                                                 &permission);
+    nsresult rv
+      = permissionManager->TestPermissionFromPrincipal(mPrincipal,
+                                                       "webapps-manage",
+                                                       &permission);
 
     if (NS_FAILED(rv) || permission != nsIPermissionManager::ALLOW_ACTION) {
       return NS_ERROR_NOT_AVAILABLE;
     }
   }
 
   return NS_OK;
 }
@@ -2479,30 +2501,32 @@ nsDOMDeviceStorage::~nsDOMDeviceStorage(
 {
 }
 
 void
 nsDOMDeviceStorage::Shutdown()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
-  if (!IsCompositeComponent()) {
+  if (!mStorageName.IsEmpty()) {
     UnregisterForSDCardChanges(this);
   }
 
   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   obs->RemoveObserver(this, "file-watcher-update");
   obs->RemoveObserver(this, "disk-space-watcher");
 }
 
-StaticRefPtr<nsDOMDeviceStorage::VolumeNameCache> nsDOMDeviceStorage::sVolumeNameCache;
+StaticRefPtr<nsDOMDeviceStorage::VolumeNameCache>
+  nsDOMDeviceStorage::sVolumeNameCache;
 
 // static
 void
-nsDOMDeviceStorage::GetOrderedVolumeNames(nsDOMDeviceStorage::VolumeNameArray &aVolumeNames)
+nsDOMDeviceStorage::GetOrderedVolumeNames(
+  nsDOMDeviceStorage::VolumeNameArray &aVolumeNames)
 {
   if (sVolumeNameCache && sVolumeNameCache->mVolumeNames.Length() > 0) {
     aVolumeNames.AppendElements(sVolumeNameCache->mVolumeNames);
     return;
   }
 #ifdef MOZ_WIDGET_GONK
   nsCOMPtr<nsIVolumeService> vs = do_GetService(NS_VOLUMESERVICE_CONTRACTID);
   if (vs) {
@@ -2526,47 +2550,38 @@ nsDOMDeviceStorage::GetOrderedVolumeName
 }
 
 // static
 void
 nsDOMDeviceStorage::CreateDeviceStorageFor(nsPIDOMWindow* aWin,
                                            const nsAString &aType,
                                            nsDOMDeviceStorage** aStore)
 {
-  // Create the underlying non-composite device storage objects
-  nsTArray<nsRefPtr<nsDOMDeviceStorage> > stores;
-  CreateDeviceStoragesFor(aWin, aType, stores, true);
-  if (stores.IsEmpty()) {
+  nsString storageName;
+  if (!DeviceStorageTypeChecker::IsVolumeBased(aType)) {
+    // The storage name will be the empty string
+    storageName.Truncate();
+  } else {
+    GetDefaultStorageName(aType, storageName);
+  }
+
+  nsRefPtr<nsDOMDeviceStorage> ds = new nsDOMDeviceStorage();
+  if (NS_FAILED(ds->Init(aWin, aType, storageName))) {
     *aStore = nullptr;
     return;
   }
-
-  if (!DeviceStorageTypeChecker::IsVolumeBased(aType)) {
-    // Since the storage type isn't volume based, don't bother creating
-    // a composite object. Just use the one we got.
-    NS_ASSERTION(stores.Length() == 1, "Only expecting a single storage object");
-    NS_ADDREF(*aStore = stores[0].get());
-    return;
-  }
-
-  // Create the composite device storage object
-  nsRefPtr<nsDOMDeviceStorage> composite = new nsDOMDeviceStorage();
-  if (NS_FAILED(composite->Init(aWin, aType, stores))) {
-    *aStore = nullptr;
-    return;
-  }
-  NS_ADDREF(*aStore = composite.get());
+  NS_ADDREF(*aStore = ds.get());
 }
 
 // static
 void
-nsDOMDeviceStorage::CreateDeviceStoragesFor(nsPIDOMWindow* aWin,
-                                            const nsAString &aType,
-                                            nsTArray<nsRefPtr<nsDOMDeviceStorage> > &aStores,
-                                            bool aCompositeComponent)
+nsDOMDeviceStorage::CreateDeviceStoragesFor(
+  nsPIDOMWindow* aWin,
+  const nsAString &aType,
+  nsTArray<nsRefPtr<nsDOMDeviceStorage> > &aStores)
 {
   nsresult rv;
 
   if (!DeviceStorageTypeChecker::IsVolumeBased(aType)) {
     nsRefPtr<nsDOMDeviceStorage> storage = new nsDOMDeviceStorage();
     rv = storage->Init(aWin, aType, EmptyString());
     if (NS_SUCCEEDED(rv)) {
       aStores.AppendElement(storage);
@@ -2574,128 +2589,118 @@ nsDOMDeviceStorage::CreateDeviceStorages
     return;
   }
   VolumeNameArray volNames;
   GetOrderedVolumeNames(volNames);
 
   VolumeNameArray::size_type numVolumeNames = volNames.Length();
   for (VolumeNameArray::index_type i = 0; i < numVolumeNames; i++) {
     nsRefPtr<nsDOMDeviceStorage> storage = new nsDOMDeviceStorage();
-    storage->mCompositeComponent = aCompositeComponent;
     rv = storage->Init(aWin, aType, volNames[i]);
     if (NS_FAILED(rv)) {
       break;
     }
     aStores.AppendElement(storage);
   }
 }
 
 // static
 bool
-nsDOMDeviceStorage::ParseCompositePath(const nsAString& aCompositePath,
-                                       nsAString& aOutStorageName,
-                                       nsAString& aOutStoragePath)
+nsDOMDeviceStorage::ParseFullPath(const nsAString& aFullPath,
+                                  nsAString& aOutStorageName,
+                                  nsAString& aOutStoragePath)
 {
   aOutStorageName.Truncate();
   aOutStoragePath.Truncate();
 
   NS_NAMED_LITERAL_STRING(slash, "/");
 
   nsDependentSubstring storageName;
 
-  if (StringBeginsWith(aCompositePath, slash)) {
-    int32_t slashIndex = aCompositePath.FindChar('/', 1);
+  if (StringBeginsWith(aFullPath, slash)) {
+    int32_t slashIndex = aFullPath.FindChar('/', 1);
     if (slashIndex == kNotFound) {
       // names of the form /filename are illegal
       return false;
     }
-    storageName.Rebind(aCompositePath, 1, slashIndex - 1);
-    aOutStoragePath = Substring(aCompositePath, slashIndex + 1);
+    storageName.Rebind(aFullPath, 1, slashIndex - 1);
+    aOutStoragePath = Substring(aFullPath, slashIndex + 1);
   } else {
-    aOutStoragePath = aCompositePath;
-  }
-
-  if (!storageName.IsEmpty()) {
-    aOutStorageName = storageName;
-    return true;
+    aOutStoragePath = aFullPath;
   }
-
-  DeviceStorageTypeChecker* typeChecker = DeviceStorageTypeChecker::CreateOrGet();
-  NS_ASSERTION(typeChecker, "DeviceStorageTypeChecker is null");
-  nsString storageType;
-  typeChecker->GetTypeFromFileName(aOutStoragePath, storageType);
-
-  nsString defStorageName;
-  GetWritableStorageName(storageType, defStorageName);
-  if (defStorageName.IsEmpty()) {
-    return false;
-  }
-  aOutStorageName = defStorageName;
+  // If no volume name was specified in aFullPath, then aOutStorageName
+  // will wind up being the empty string. It's up to the caller to figure
+  // out which storage name to actually use.
+  aOutStorageName = storageName;
   return true;
 }
 
 already_AddRefed<nsDOMDeviceStorage>
-nsDOMDeviceStorage::GetStorage(const nsAString& aCompositePath, nsAString& aOutStoragePath)
+nsDOMDeviceStorage::GetStorage(const nsAString& aFullPath,
+                               nsAString& aOutStoragePath)
 {
-  MOZ_ASSERT(IsComposite());
-
   nsString storageName;
-  if (!ParseCompositePath(aCompositePath, storageName, aOutStoragePath)) {
+  if (!ParseFullPath(aFullPath, storageName, aOutStoragePath)) {
     return nullptr;
   }
-
   nsRefPtr<nsDOMDeviceStorage> ds;
-  ds = GetStorageByName(storageName);
+  if (storageName.IsEmpty()) {
+    ds = this;
+  } else {
+    ds = GetStorageByName(storageName);
+  }
   return ds.forget();
 }
 
 already_AddRefed<nsDOMDeviceStorage>
 nsDOMDeviceStorage::GetStorageByName(const nsAString& aStorageName)
 {
-  nsTArray<nsRefPtr<nsDOMDeviceStorage> >::size_type n = mStores.Length();
-  nsTArray<nsRefPtr<nsDOMDeviceStorage> >::index_type i;
-  for (i = 0; i < n; i++) {
-    nsRefPtr<nsDOMDeviceStorage> ds = mStores[i];
-    if (ds->mStorageName == aStorageName) {
+  nsRefPtr<nsDOMDeviceStorage> ds;
+
+  if (mStorageName.Equals(aStorageName)) {
+    ds = this;
+    return ds.forget();
+  }
+  VolumeNameArray volNames;
+  GetOrderedVolumeNames(volNames);
+  VolumeNameArray::size_type numVolumes = volNames.Length();
+  VolumeNameArray::index_type i;
+  for (i = 0; i < numVolumes; i++) {
+    if (volNames[i].Equals(aStorageName)) {
+      ds = new nsDOMDeviceStorage();
+      nsresult rv = ds->Init(GetOwner(), mStorageType, aStorageName);
+      if (NS_FAILED(rv)) {
+        return nullptr;
+      }
       return ds.forget();
     }
   }
   return nullptr;
 }
 
 // static
 void
-nsDOMDeviceStorage::GetWritableStorageName(const nsAString& aStorageType,
-                                           nsAString& aStorageName)
+nsDOMDeviceStorage::GetDefaultStorageName(const nsAString& aStorageType,
+                                          nsAString& aStorageName)
 {
   // See if the preferred volume is available.
   nsRefPtr<nsDOMDeviceStorage> ds;
   nsAdoptingString prefStorageName =
     mozilla::Preferences::GetString("device.storage.writable.name");
   if (prefStorageName) {
-    DeviceStorageFile dsf(aStorageType, prefStorageName);
-    if (dsf.IsAvailable()) {
-      aStorageName = prefStorageName;
-      return;
-    }
+    aStorageName = prefStorageName;
+    return;
   }
 
-  // No preferred storage, or the preferred storage is unavailable. Find
-  // the first available storage area.
+  // No preferred storage, we'll use the first one (which should be sdcard).
 
   VolumeNameArray volNames;
   GetOrderedVolumeNames(volNames);
-  VolumeNameArray::size_type numVolumes = volNames.Length();
-  VolumeNameArray::index_type i;
-  for (i = 0; i < numVolumes; i++) {
-    DeviceStorageFile dsf(aStorageType, volNames[i]);
-    if (dsf.IsAvailable()) {
-      aStorageName = volNames[i];
-      return;
-    }
+  if (volNames.Length() > 0) {
+    aStorageName = volNames[0];
   }
 }
 
 bool
 nsDOMDeviceStorage::IsAvailable()
 {
   DeviceStorageFile dsf(mStorageType, mStorageName);
   return dsf.IsAvailable();
@@ -2725,17 +2730,18 @@ nsDOMDeviceStorage::Add(nsIDOMBlob* aBlo
 
   // 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);
 
   nsCString extension;
-  mimeSvc->GetPrimaryExtension(NS_LossyConvertUTF16toASCII(mimeType), EmptyCString(), extension);
+  mimeSvc->GetPrimaryExtension(NS_LossyConvertUTF16toASCII(mimeType),
+                               EmptyCString(), extension);
   // if extension is null here, we will ignore it for now.
   // AddNamed() will check the file path and fail.  This
   // will post an onerror to the requestee.
 
   // possible race here w/ unique filename
   char buffer[32];
   NS_MakeRandomString(buffer, ArrayLength(buffer) - 1);
 
@@ -2768,25 +2774,26 @@ nsDOMDeviceStorage::AddNamed(nsIDOMBlob*
   }
 
   nsCOMPtr<nsPIDOMWindow> win = GetOwner();
   if (!win) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return nullptr;
   }
 
-  DeviceStorageTypeChecker* typeChecker = DeviceStorageTypeChecker::CreateOrGet();
+  DeviceStorageTypeChecker* typeChecker
+    = DeviceStorageTypeChecker::CreateOrGet();
   if (!typeChecker) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
 
   nsCOMPtr<nsIRunnable> r;
 
-  if (IsComposite()) {
+  if (IsFullPath(aPath)) {
     nsString storagePath;
     nsRefPtr<nsDOMDeviceStorage> ds = GetStorage(aPath, storagePath);
     if (!ds) {
       nsRefPtr<DOMRequest> request = new DOMRequest(win);
       r = new PostErrorEvent(request, POST_ERROR_EVENT_UNKNOWN);
       NS_DispatchToMainThread(r);
       return request.forget();
     }
@@ -2838,17 +2845,17 @@ nsDOMDeviceStorage::GetInternal(const ns
   nsCOMPtr<nsPIDOMWindow> win = GetOwner();
   if (!win) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return nullptr;
   }
 
   nsRefPtr<DOMRequest> request = new DOMRequest(win);
 
-  if (IsComposite()) {
+  if (IsFullPath(aPath)) {
     nsString storagePath;
     nsRefPtr<nsDOMDeviceStorage> ds = GetStorage(aPath, storagePath);
     if (!ds) {
       nsCOMPtr<nsIRunnable> r =
         new PostErrorEvent(request, POST_ERROR_EVENT_UNKNOWN);
       NS_DispatchToMainThread(r);
       return request.forget();
     }
@@ -2869,17 +2876,18 @@ nsDOMDeviceStorage::GetInternal(nsPIDOMW
                                                           mStorageName,
                                                           aPath);
   dsf->SetEditable(aEditable);
 
   nsCOMPtr<nsIRunnable> r;
   if (!dsf->IsSafePath()) {
     r = new PostErrorEvent(aRequest, POST_ERROR_EVENT_PERMISSION_DENIED);
   } else {
-    r = new DeviceStorageRequest(aEditable ? DEVICE_STORAGE_REQUEST_WRITE : DEVICE_STORAGE_REQUEST_READ,
+    r = new DeviceStorageRequest(aEditable ? DEVICE_STORAGE_REQUEST_WRITE
+                                           : DEVICE_STORAGE_REQUEST_READ,
                                  aWin, mPrincipal, dsf, aRequest);
   }
   NS_DispatchToMainThread(r);
 }
 
 NS_IMETHODIMP
 nsDOMDeviceStorage::Delete(const nsAString& aPath, nsIDOMDOMRequest** aRetval)
 {
@@ -2895,17 +2903,17 @@ nsDOMDeviceStorage::Delete(const nsAStri
   nsCOMPtr<nsPIDOMWindow> win = GetOwner();
   if (!win) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return nullptr;
   }
 
   nsRefPtr<DOMRequest> request = new DOMRequest(win);
 
-  if (IsComposite()) {
+  if (IsFullPath(aPath)) {
     nsString storagePath;
     nsRefPtr<nsDOMDeviceStorage> ds = GetStorage(aPath, storagePath);
     if (!ds) {
       nsCOMPtr<nsIRunnable> r =
         new PostErrorEvent(request, POST_ERROR_EVENT_UNKNOWN);
       NS_DispatchToMainThread(r);
       return request.forget();
     }
@@ -2951,21 +2959,19 @@ nsDOMDeviceStorage::FreeSpace(ErrorResul
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return nullptr;
   }
 
   nsRefPtr<DOMRequest> request = new DOMRequest(win);
 
   nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType,
                                                           mStorageName);
-  nsCOMPtr<nsIRunnable> r = new DeviceStorageRequest(DEVICE_STORAGE_REQUEST_FREE_SPACE,
-                                                     win,
-                                                     mPrincipal,
-                                                     dsf,
-                                                     request);
+  nsCOMPtr<nsIRunnable> r
+    = new DeviceStorageRequest(DEVICE_STORAGE_REQUEST_FREE_SPACE,
+                               win, mPrincipal, dsf, request);
   NS_DispatchToMainThread(r);
   return request.forget();
 }
 
 NS_IMETHODIMP
 nsDOMDeviceStorage::UsedSpace(nsIDOMDOMRequest** aRetval)
 {
   ErrorResult rv;
@@ -2978,28 +2984,27 @@ already_AddRefed<DOMRequest>
 nsDOMDeviceStorage::UsedSpace(ErrorResult& aRv)
 {
   nsCOMPtr<nsPIDOMWindow> win = GetOwner();
   if (!win) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return nullptr;
   }
 
-  DebugOnly<DeviceStorageUsedSpaceCache*> usedSpaceCache = DeviceStorageUsedSpaceCache::CreateOrGet();
+  DebugOnly<DeviceStorageUsedSpaceCache*> usedSpaceCache
+    = DeviceStorageUsedSpaceCache::CreateOrGet();
   NS_ASSERTION(usedSpaceCache, "DeviceStorageUsedSpaceCache is null");
 
   nsRefPtr<DOMRequest> request = new DOMRequest(win);
 
   nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType,
                                                           mStorageName);
-  nsCOMPtr<nsIRunnable> r = new DeviceStorageRequest(DEVICE_STORAGE_REQUEST_USED_SPACE,
-                                                     win,
-                                                     mPrincipal,
-                                                     dsf,
-                                                     request);
+  nsCOMPtr<nsIRunnable> r
+    = new DeviceStorageRequest(DEVICE_STORAGE_REQUEST_USED_SPACE,
+                               win, mPrincipal, dsf, request);
   NS_DispatchToMainThread(r);
   return request.forget();
 }
 
 NS_IMETHODIMP
 nsDOMDeviceStorage::Available(nsIDOMDOMRequest** aRetval)
 {
   ErrorResult rv;
@@ -3016,47 +3021,46 @@ nsDOMDeviceStorage::Available(ErrorResul
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return nullptr;
   }
 
   nsRefPtr<DOMRequest> request = new DOMRequest(win);
 
   nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType,
                                                           mStorageName);
-  nsCOMPtr<nsIRunnable> r = new DeviceStorageRequest(DEVICE_STORAGE_REQUEST_AVAILABLE,
-                                                     win,
-                                                     mPrincipal,
-                                                     dsf,
-                                                     request);
+  nsCOMPtr<nsIRunnable> r
+    = new DeviceStorageRequest(DEVICE_STORAGE_REQUEST_AVAILABLE,
+                               win, mPrincipal, dsf, request);
   NS_DispatchToMainThread(r);
   return request.forget();
 }
 
 NS_IMETHODIMP
-nsDOMDeviceStorage::GetRootDirectoryForFile(const nsAString& aName, nsIFile** aRootDirectory)
+nsDOMDeviceStorage::GetRootDirectoryForFile(const nsAString& aName,
+                                            nsIFile** aRootDirectory)
 {
   nsRefPtr<nsDOMDeviceStorage> ds;
 
-  if (IsComposite()) {
+  if (IsFullPath(aName)) {
     nsString storagePath;
     ds = GetStorage(aName, storagePath);
   } else {
     ds = this;
   }
   if (!ds || !ds->mRootDirectory) {
     return NS_ERROR_FAILURE;
   }
   return ds->mRootDirectory->Clone(aRootDirectory);
 }
 
 bool
 nsDOMDeviceStorage::Default()
 {
   nsString defaultStorageName;
-  GetWritableStorageName(mStorageType, defaultStorageName);
+  GetDefaultStorageName(mStorageType, defaultStorageName);
   return mStorageName.Equals(defaultStorageName);
 }
 
 NS_IMETHODIMP
 nsDOMDeviceStorage::GetDefault(bool* aDefault)
 {
   *aDefault = Default();
   return NS_OK;
@@ -3103,19 +3107,20 @@ nsDOMDeviceStorage::EnumerateInternal(co
   }
 
   nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType,
                                                           mStorageName,
                                                           aPath,
                                                           EmptyString());
   dsf->SetEditable(aEditable);
 
-  nsRefPtr<nsDOMDeviceStorageCursor> cursor = new nsDOMDeviceStorageCursor(win, mPrincipal,
-                                                                           dsf, since);
-  nsRefPtr<DeviceStorageCursorRequest> r = new DeviceStorageCursorRequest(cursor);
+  nsRefPtr<nsDOMDeviceStorageCursor> cursor
+    = new nsDOMDeviceStorageCursor(win, mPrincipal, dsf, since);
+  nsRefPtr<DeviceStorageCursorRequest> r
+    = new DeviceStorageCursorRequest(cursor);
 
   if (mozilla::Preferences::GetBool("device.storage.prompt.testing", false)) {
     r->Allow();
     return cursor.forget();
   }
 
   if (XRE_GetProcessType() == GeckoProcessType_Content) {
     // because owner implements nsITabChild, we can assume that it is
@@ -3129,55 +3134,60 @@ nsDOMDeviceStorage::EnumerateInternal(co
     // Corresponding release occurs in DeallocPContentPermissionRequest.
     r->AddRef();
 
     nsCString type;
     aRv = DeviceStorageTypeChecker::GetPermissionForType(mStorageType, type);
     if (aRv.Failed()) {
       return nullptr;
     }
-    child->SendPContentPermissionRequestConstructor(r, type, NS_LITERAL_CSTRING("read"), IPC::Principal(mPrincipal));
+    child->SendPContentPermissionRequestConstructor(r, type,
+                                                    NS_LITERAL_CSTRING("read"),
+                                                    IPC::Principal(mPrincipal));
 
     r->Sendprompt();
 
     return cursor.forget();
   }
 
-  nsCOMPtr<nsIContentPermissionPrompt> prompt = do_CreateInstance(NS_CONTENT_PERMISSION_PROMPT_CONTRACTID);
+  nsCOMPtr<nsIContentPermissionPrompt> prompt
+    = do_CreateInstance(NS_CONTENT_PERMISSION_PROMPT_CONTRACTID);
   if (prompt) {
     prompt->Prompt(r);
   }
 
   return cursor.forget();
 }
 
 #ifdef MOZ_WIDGET_GONK
 void
-nsDOMDeviceStorage::DispatchMountChangeEvent(nsAString& aVolumeName,
-                                             nsAString& aVolumeStatus)
+nsDOMDeviceStorage::DispatchMountChangeEvent(nsAString& aVolumeStatus)
 {
   nsCOMPtr<nsIDOMEvent> event;
-  NS_NewDOMDeviceStorageChangeEvent(getter_AddRefs(event), this, nullptr, nullptr);
+  NS_NewDOMDeviceStorageChangeEvent(getter_AddRefs(event), this,
+                                    nullptr, nullptr);
 
   nsCOMPtr<nsIDOMDeviceStorageChangeEvent> ce = do_QueryInterface(event);
   nsresult rv = ce->InitDeviceStorageChangeEvent(NS_LITERAL_STRING("change"),
                                                  true, false,
-                                                 aVolumeName,
+                                                 mStorageName,
                                                  aVolumeStatus);
   if (NS_FAILED(rv)) {
     return;
   }
 
   bool ignore;
   DispatchEvent(ce, &ignore);
 }
 #endif
 
 NS_IMETHODIMP
-nsDOMDeviceStorage::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *aData)
+nsDOMDeviceStorage::Observe(nsISupports *aSubject,
+                            const char *aTopic,
+                            const PRUnichar *aData)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   if (!strcmp(aTopic, "file-watcher-update")) {
 
     DeviceStorageFile* file = static_cast<DeviceStorageFile*>(aSubject);
     Notify(NS_ConvertUTF16toUTF8(aData).get(), file);
     return NS_OK;
@@ -3194,35 +3204,39 @@ nsDOMDeviceStorage::Observe(nsISupports 
     } else if (!strcmp(NS_ConvertUTF16toUTF8(aData).get(), "free")) {
       Notify("available-disk-space", file);
     }
     return NS_OK;
   }
 
 #ifdef MOZ_WIDGET_GONK
   else if (!strcmp(aTopic, NS_VOLUME_STATE_CHANGED)) {
-    // We only invalidate the used space cache for the volume that actually changed state.
+    // We invalidate the used space cache for the volume that actually changed
+    // state.
     nsCOMPtr<nsIVolume> vol = do_QueryInterface(aSubject);
     if (!vol) {
       return NS_OK;
     }
     nsString volName;
     vol->GetName(volName);
 
-    DeviceStorageUsedSpaceCache* usedSpaceCache = DeviceStorageUsedSpaceCache::CreateOrGet();
+    DeviceStorageUsedSpaceCache* usedSpaceCache
+      = DeviceStorageUsedSpaceCache::CreateOrGet();
     NS_ASSERTION(usedSpaceCache, "DeviceStorageUsedSpaceCache is null");
     usedSpaceCache->Invalidate(volName);
 
-    // But if we're a composite storage area, we want to report a composite availability,
-    // so we use mStorageName here instead of volName. (Note: for composite devices,
-    // mStorageName will be the empty string).
+    if (!volName.Equals(mStorageName)) {
+      // Not our volume - we can ignore.
+      return NS_OK;
+    }
+
     DeviceStorageFile dsf(mStorageType, mStorageName);
     nsString status;
     dsf.GetStatus(status);
-    DispatchMountChangeEvent(mStorageName, status);
+    DispatchMountChangeEvent(status);
     return NS_OK;
   }
 #endif
   return NS_OK;
 }
 
 nsresult
 nsDOMDeviceStorage::Notify(const char* aReason, DeviceStorageFile* aFile)
@@ -3241,20 +3255,20 @@ nsDOMDeviceStorage::Notify(const char* a
   NS_NewDOMDeviceStorageChangeEvent(getter_AddRefs(event), this,
                                     nullptr, nullptr);
 
   nsCOMPtr<nsIDOMDeviceStorageChangeEvent> ce = do_QueryInterface(event);
 
   nsString reason;
   reason.AssignWithConversion(aReason);
 
-  nsString compositePath;
-  aFile->GetCompositePath(compositePath);
+  nsString fullPath;
+  aFile->GetFullPath(fullPath);
   nsresult rv = ce->InitDeviceStorageChangeEvent(NS_LITERAL_STRING("change"),
-                                                 true, false, compositePath,
+                                                 true, false, fullPath,
                                                  reason);
   NS_ENSURE_SUCCESS(rv, rv);
 
   bool ignore;
   DispatchEvent(ce, &ignore);
   return NS_OK;
 }
 
@@ -3264,130 +3278,90 @@ nsDOMDeviceStorage::AddEventListener(con
                                      bool aUseCapture,
                                      bool aWantsUntrusted,
                                      uint8_t aArgc)
 {
   nsCOMPtr<nsPIDOMWindow> win = GetOwner();
   if (!win) {
     return NS_ERROR_UNEXPECTED;
   }
-  if (IsComposite()) {
-    nsTArray<nsRefPtr<nsDOMDeviceStorage> >::size_type n = mStores.Length();
-    nsTArray<nsRefPtr<nsDOMDeviceStorage> >::index_type i;
-    for (i = 0; i < n; i++) {
-      nsresult rv = mStores[i]->AddEventListener(aType, aListener, aUseCapture, aWantsUntrusted, aArgc);
-      NS_ENSURE_SUCCESS(rv, rv);
-    }
-    // Fall through, so that we add an event listener for the composite object as well.
-  }
 
   nsRefPtr<DOMRequest> request = new DOMRequest(win);
   nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType,
                                                           mStorageName);
-  nsCOMPtr<nsIRunnable> r = new DeviceStorageRequest(DEVICE_STORAGE_REQUEST_WATCH,
-                                                     win, mPrincipal, dsf, request, this);
+  nsCOMPtr<nsIRunnable> r
+    = new DeviceStorageRequest(DEVICE_STORAGE_REQUEST_WATCH,
+                               win, mPrincipal, dsf, request, this);
   NS_DispatchToMainThread(r);
-  return nsDOMEventTargetHelper::AddEventListener(aType, aListener, aUseCapture, aWantsUntrusted, aArgc);
+  return nsDOMEventTargetHelper::AddEventListener(aType, aListener, aUseCapture,
+                                                  aWantsUntrusted, aArgc);
 }
 
 void
 nsDOMDeviceStorage::AddEventListener(const nsAString & aType,
                                      nsIDOMEventListener *aListener,
                                      bool aUseCapture,
                                      const Nullable<bool>& aWantsUntrusted,
                                      ErrorResult& aRv)
 {
   nsCOMPtr<nsPIDOMWindow> win = GetOwner();
   if (!win) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return;
   }
-  if (IsComposite()) {
-    nsTArray<nsRefPtr<nsDOMDeviceStorage> >::size_type n = mStores.Length();
-    nsTArray<nsRefPtr<nsDOMDeviceStorage> >::index_type i;
-    for (i = 0; i < n; i++) {
-      mStores[i]->AddEventListener(aType, aListener, aUseCapture, aWantsUntrusted, aRv);
-    }
-    // Fall through, so that we add an event listener for the composite object as well.
-  }
 
   nsRefPtr<DOMRequest> request = new DOMRequest(win);
   nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType,
                                                           mStorageName);
-  nsCOMPtr<nsIRunnable> r = new DeviceStorageRequest(DEVICE_STORAGE_REQUEST_WATCH,
-                                                     win, mPrincipal, dsf, request, this);
+  nsCOMPtr<nsIRunnable> r
+    = new DeviceStorageRequest(DEVICE_STORAGE_REQUEST_WATCH,
+                               win, mPrincipal, dsf, request, this);
   NS_DispatchToMainThread(r);
-  nsDOMEventTargetHelper::AddEventListener(aType, aListener, aUseCapture, aWantsUntrusted, aRv);
+  nsDOMEventTargetHelper::AddEventListener(aType, aListener, aUseCapture,
+                                           aWantsUntrusted, aRv);
 }
 
 NS_IMETHODIMP
 nsDOMDeviceStorage::AddSystemEventListener(const nsAString & aType,
                                            nsIDOMEventListener *aListener,
                                            bool aUseCapture,
                                            bool aWantsUntrusted,
                                            uint8_t aArgc)
 {
-  if (IsComposite()) {
-    nsTArray<nsRefPtr<nsDOMDeviceStorage> >::size_type n = mStores.Length();
-    nsTArray<nsRefPtr<nsDOMDeviceStorage> >::index_type i;
-    for (i = 0; i < n; i++) {
-      nsresult rv = mStores[i]->AddSystemEventListener(aType, aListener, aUseCapture, aWantsUntrusted, aArgc);
-      NS_ENSURE_SUCCESS(rv, rv);
-    }
-    return NS_OK;
-  }
   if (!mIsWatchingFile) {
     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
     obs->AddObserver(this, "file-watcher-update", false);
     mIsWatchingFile = true;
   }
 
-  return nsDOMDeviceStorage::AddEventListener(aType,aListener,aUseCapture,aWantsUntrusted, aArgc);
+  return nsDOMDeviceStorage::AddEventListener(aType, aListener, aUseCapture,
+                                              aWantsUntrusted, aArgc);
 }
 
 NS_IMETHODIMP
 nsDOMDeviceStorage::RemoveEventListener(const nsAString & aType,
                                         nsIDOMEventListener *aListener,
                                         bool aUseCapture)
 {
-  if (IsComposite()) {
-    nsTArray<nsRefPtr<nsDOMDeviceStorage> >::size_type n = mStores.Length();
-    nsTArray<nsRefPtr<nsDOMDeviceStorage> >::index_type i;
-    for (i = 0; i < n; i++) {
-      nsresult rv = mStores[i]->RemoveEventListener(aType, aListener, aUseCapture);
-      NS_ENSURE_SUCCESS(rv, rv);
-    }
-    // Fall through, so that we remove the event listener for the composite
-    // object as well.
-  }
   nsDOMEventTargetHelper::RemoveEventListener(aType, aListener, false);
 
   if (mIsWatchingFile && !HasListenersFor(nsGkAtoms::onchange)) {
     mIsWatchingFile = false;
     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
     obs->RemoveObserver(this, "file-watcher-update");
   }
   return NS_OK;
 }
 
 void
 nsDOMDeviceStorage::RemoveEventListener(const nsAString& aType,
                                         nsIDOMEventListener* aListener,
                                         bool aCapture,
                                         ErrorResult& aRv)
 {
-  if (IsComposite()) {
-    nsTArray<nsRefPtr<nsDOMDeviceStorage> >::size_type n = mStores.Length();
-    nsTArray<nsRefPtr<nsDOMDeviceStorage> >::index_type i;
-    for (i = 0; i < n; i++) {
-      mStores[i]->RemoveEventListener(aType, aListener, aCapture, aRv);
-    }
-    // Fall through, so that we remove the event listener for the composite
-    // object as well.
-  }
   nsDOMEventTargetHelper::RemoveEventListener(aType, aListener, aCapture, aRv);
 
   if (mIsWatchingFile && !HasListenersFor(nsGkAtoms::onchange)) {
     mIsWatchingFile = false;
     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
     obs->RemoveObserver(this, "file-watcher-update");
   }
 }
--- a/dom/interfaces/base/nsIDOMCrypto.idl
+++ b/dom/interfaces/base/nsIDOMCrypto.idl
@@ -1,12 +1,14 @@
 /* -*- 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/. */
 
 #include "nsISupports.idl"
- 
-[scriptable, uuid(a0a3bc68-eab3-4e66-b5cb-b1d86765119c)]
+
+interface nsIDOMWindow;
+
+[uuid(729cfcad-11b4-4338-b97e-5c023ae295fa)]
 interface nsIDOMCrypto : nsISupports
 {
-  [implicit_jscontext] jsval getRandomValues(in jsval aData);
+  [notxpcom] void init(in nsIDOMWindow window);
 };
--- a/dom/interfaces/base/nsIDOMCryptoLegacy.idl
+++ b/dom/interfaces/base/nsIDOMCryptoLegacy.idl
@@ -1,28 +1,16 @@
 /* -*- 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/. */
 
 #include "domstubs.idl"
 
 interface nsIDOMCRMFObject;
+interface nsIDOMWindow;
 
-[scriptable, uuid(e1df1d4d-41ef-4225-934a-107c5d612686)]
+[uuid(c25ecf08-3f46-4420-bee4-8505792fd63a)]
 interface nsIDOMCrypto : nsISupports
 {
-  readonly attribute DOMString        version;
+  [notxpcom] void init(in nsIDOMWindow window);
   attribute boolean         enableSmartCardEvents;
-
-  nsIDOMCRMFObject          generateCRMFRequest(/* ... */);
-  DOMString                 importUserCertificates(in DOMString nickname,
-                                                   in DOMString cmmfResponse,
-                                                   in boolean doForcedBackup);
-  DOMString                 popChallengeResponse(in DOMString challenge);
-  DOMString                 random(in long numBytes);
-  DOMString                 signText(in DOMString stringToSign,
-                                     in DOMString caOption /* ... */);
-  void                      logout();
-  void                      disableRightClick();
-
-  [implicit_jscontext] jsval getRandomValues(in jsval aData);
 };
--- a/dom/system/gonk/tests/test_ril_worker_clir.js
+++ b/dom/system/gonk/tests/test_ril_worker_clir.js
@@ -36,16 +36,17 @@ function _getWorker() {
 }
 
 add_test(function test_setCLIR_success() {
   let workerHelper = _getWorker();
   let worker = workerHelper.worker;
 
   worker.RIL.setCLIR = function fakeSetCLIR(options) {
     worker.RIL[REQUEST_SET_CLIR](0, {
+      rilMessageType: "setCLIR",
       rilRequestError: ERROR_SUCCESS
     });
   };
 
   worker.RIL.setCLIR({
     clirMode: CLIR_DEFAULT
   });
 
@@ -58,16 +59,17 @@ add_test(function test_setCLIR_success()
 });
 
 add_test(function test_setCLIR_generic_failure() {
   let workerHelper = _getWorker();
   let worker = workerHelper.worker;
 
   worker.RIL.setCLIR = function fakeSetCLIR(options) {
     worker.RIL[REQUEST_SET_CLIR](0, {
+      rilMessageType: "setCLIR",
       rilRequestError: ERROR_GENERIC_FAILURE
     });
   };
 
   worker.RIL.setCLIR({
     clirMode: CLIR_DEFAULT
   });
 
@@ -85,21 +87,22 @@ add_test(function test_getCLIR_n0_m1() {
 
   worker.Buf.readUint32 = function fakeReadUint32() {
     return worker.Buf.int32Array.pop();
   };
 
   worker.RIL.getCLIR = function fakeGetCLIR(options) {
     worker.Buf.int32Array = [
       1,  // Presentation indicator is used according to the subscription
-          // of the CLIR service. 
+          // of the CLIR service.
       0,  // CLIR provisioned in permanent mode.
       2   // Length.
     ];
     worker.RIL[REQUEST_GET_CLIR](1, {
+      rilMessageType: "setCLIR",
       rilRequestError: ERROR_SUCCESS
     });
   };
 
   worker.RIL.getCLIR({});
 
   let postedMessage = workerHelper.postedMessage;
 
@@ -116,21 +119,22 @@ add_test(function test_getCLIR_error_gen
 
   worker.Buf.readUint32 = function fakeReadUint32() {
     return worker.Buf.int32Array.pop();
   };
 
   worker.RIL.getCLIR = function fakeGetCLIR(options) {
     worker.Buf.int32Array = [
       1,  // Presentation indicator is used according to the subscription
-          // of the CLIR service. 
+          // of the CLIR service.
       0,  // CLIR provisioned in permanent mode.
       0   // Length (invalid one).
     ];
     worker.RIL[REQUEST_GET_CLIR](1, {
+      rilMessageType: "setCLIR",
       rilRequestError: ERROR_SUCCESS
     });
   };
 
   worker.RIL.getCLIR({});
 
   let postedMessage = workerHelper.postedMessage;
 
--- a/dom/tests/mochitest/crypto/test_getRandomValues.html
+++ b/dom/tests/mochitest/crypto/test_getRandomValues.html
@@ -120,17 +120,17 @@ function onWindowLoad()
   // Count the tests in the testData array
   ok(testCount == 11, "11 tests run via testData");
 
   // Test a null argument
   try {
     window.crypto.getRandomValues(null);
   }
   catch (ex) {
-    var test = ex.toString().search(/1003/);
+    var test = ex.toString().search(/1003|TypeError/);
     ok((test > -1), "Expected TYPE_ERR, got " + ex + ".");
   }
 
   // Test a zero-length buffer view
   try {
     var a = new Int8Array(0);
     window.crypto.getRandomValues(a);
     ok(a[0] === undefined, "The array buffer is unchanged, still 0 length");
--- a/dom/tests/mochitest/crypto/test_legacy.html
+++ b/dom/tests/mochitest/crypto/test_legacy.html
@@ -19,10 +19,38 @@ ok("importUserCertificates" in window.cr
    "importUserCertificates in window.crypto");
 ok("popChallengeResponse" in window.crypto,
    "popChallengeResponse in window.crypto");
 ok("random" in window.crypto, "random in window.crypto");
 ok("signText" in window.crypto, "signText in window.crypto");
 ok("disableRightClick" in window.crypto,
    "disableRightClick in window.crypto");
 
+function jsCallback () {
+}
+
+try {
+  window.crypto.generateCRMFRequest(null, null, null, null, jsCallback.toString());
+  ok(false, "window.crypto.generateCRMFRequest failed, should throw error");
+} catch (e) {
+  ok(e.toString().search(/Failure/) > -1,
+     "Expected error: ReqDN cannot be null");
+}
+
+try {
+  window.crypto.generateCRMFRequest(document.documentElement, null, null, null,
+                                    null);
+  ok(false, "window.crypto.generateCRMFRequest failed, should throw error");
+} catch (e) {
+  ok(e.toString().search(/Failure/) > -1,
+     "Expected error: jsCallback cannot be null");
+}
+
+try {
+  window.crypto.generateCRMFRequest(document.documentElement, null, null, null,
+                                    jsCallback.toString(), 1024);
+  ok(false, "window.crypto.generateCRMFRequest failed, should throw error");
+} catch (e) {
+  ok(e.toString().search(/TypeError/) > -1,
+     "Expected error: Not enough arguments");
+}
 </script>
 </body></html>
new file mode 100644
--- /dev/null
+++ b/dom/webidl/Crypto.webidl
@@ -0,0 +1,63 @@
+/* -*- 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/.
+ *
+ * The origin of this IDL file is
+ * http://www.w3.org/TR/WebCryptoAPI/
+ */
+
+[NoInterfaceObject]
+interface RandomSource {
+  [Throws]
+  ArrayBufferView getRandomValues(ArrayBufferView array);
+};
+
+Crypto implements RandomSource;
+
+interface Crypto {
+};
+
+#ifndef MOZ_DISABLE_CRYPTOLEGACY
+interface CRMFObject;
+
+[NoInterfaceObject]
+interface CryptoLegacy {
+  readonly attribute DOMString version;
+
+  [SetterThrows]
+  attribute boolean enableSmartCardEvents;
+
+  [Throws]
+  CRMFObject generateCRMFRequest(ByteString? reqDN,
+                                 ByteString? regToken,
+                                 ByteString? authenticator,
+                                 ByteString? eaCert,
+                                 ByteString? jsCallback,
+                                 any... args);
+
+  [Throws]
+  DOMString importUserCertificates(DOMString nickname,
+                                   DOMString cmmfResponse,
+                                   boolean doForcedBackup);
+
+  [Throws]
+  DOMString popChallengeResponse(DOMString challenge);
+
+  [Throws]
+  DOMString random(long numBytes);
+
+  DOMString signText(DOMString stringToSign,
+                     DOMString caOption,
+                     ByteString... args);
+
+  [Throws]
+  void logout();
+
+  [Throws]
+  void disableRightClick();
+};
+
+Crypto implements CryptoLegacy;
+#endif // !MOZ_DISABLE_CRYPTOLEGACY
+
--- a/dom/webidl/WebIDL.mk
+++ b/dom/webidl/WebIDL.mk
@@ -4,16 +4,17 @@
 
 webidl_base = $(topsrcdir)/dom/webidl
 
 generated_webidl_files = \
   CSS2Properties.webidl \
   $(NULL)
 
 preprocessed_webidl_files = \
+  Crypto.webidl \
   Navigator.webidl \
   $(NULL)
 
 webidl_files = \
   AnalyserNode.webidl \
   AnimationEvent.webidl \
   ArchiveReader.webidl \
   ArchiveRequest.webidl \
--- a/js/xpconnect/src/dom_quickstubs.qsconf
+++ b/js/xpconnect/src/dom_quickstubs.qsconf
@@ -14,17 +14,16 @@ name = 'DOM'
 # one of those, can be really weird, because GetCurrentNativeCallContext
 # doesn't crash--it may in fact return a plausible wrong answer.
 
 members = [ 
     # dom/interfaces/base
     #
     # Note that many implementations of interfaces in this directory
     # use GetCurrentNativeCallContext, notably:
-    #   - nsIDOMCrypto.{generateCRMFRequest,signText}
     #   - nsIDOMLocation.reload
     #   - nsIDOMNSHistory.go
     #   - nsIDOMJSPluginArray.refresh
     #   - nsIDOMWindow.postMessage
     #   - nsIDOMJSWindow.{prompt,setTimeout,setInterval,open,openDialog}
     #
     # (And nsIDOMModalContentWindow.returnValue is an attribute of type
     # nsIVariant, which qsgen.py can't handle.)
--- a/security/manager/ssl/src/nsCrypto.cpp
+++ b/security/manager/ssl/src/nsCrypto.cpp
@@ -69,19 +69,21 @@
 #include "ScopedNSSTypes.h"
 
 #include "ssl.h" // For SSL_ClearSessionCache
 
 #include "nsNSSCleaner.h"
 
 #include "nsNSSCertHelper.h"
 #include <algorithm>
+#include "nsWrapperCacheInlines.h"
 #endif
 
 using namespace mozilla;
+using namespace mozilla::dom;
 
 /*
  * These are the most common error strings that are returned
  * by the JavaScript methods in case of error.
  */
 
 #define JS_ERROR       "error:"
 #define JS_ERROR_INTERNAL  JS_ERROR"internalError"
@@ -251,59 +253,78 @@ nsCrypto::nsCrypto() :
   mEnableSmartCardEvents(false)
 {
 }
 
 nsCrypto::~nsCrypto()
 {
 }
 
-NS_IMETHODIMP
-nsCrypto::SetEnableSmartCardEvents(bool aEnable)
+void
+nsCrypto::Init(nsIDOMWindow* aWindow)
+{
+  mozilla::dom::Crypto::Init(aWindow);
+}
+
+void
+nsCrypto::SetEnableSmartCardEvents(bool aEnable, ErrorResult& aRv)
 {
   nsresult rv = NS_OK;
 
   // this has the side effect of starting the nssComponent (and initializing
-  // NSS) even if it isn't already going. Starting the nssComponent is a 
+  // NSS) even if it isn't already going. Starting the nssComponent is a
   // prerequisite for getting smartCard events.
   if (aEnable) {
     nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
   }
 
   if (NS_FAILED(rv)) {
-    return rv;
+    aRv.Throw(rv);
+    return;
   }
 
   mEnableSmartCardEvents = aEnable;
-  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsCrypto::SetEnableSmartCardEvents(bool aEnable)
+{
+  ErrorResult rv;
+  SetEnableSmartCardEvents(aEnable, rv);
+  return rv.ErrorCode();
+}
+
+bool
+nsCrypto::EnableSmartCardEvents()
+{
+  return mEnableSmartCardEvents;
 }
 
 NS_IMETHODIMP
 nsCrypto::GetEnableSmartCardEvents(bool *aEnable)
 {
-  *aEnable = mEnableSmartCardEvents;
+  *aEnable = EnableSmartCardEvents();
   return NS_OK;
 }
 
 //A quick function to let us know if the key we're trying to generate
 //can be escrowed.
 static bool
 ns_can_escrow(nsKeyGenType keyGenType)
 {
   /* For now, we only escrow rsa-encryption and ec-encryption keys. */
   return (bool)(keyGenType == rsaEnc || keyGenType == ecEnc);
 }
 
 //Retrieve crypto.version so that callers know what
 //version of PSM this is.
-NS_IMETHODIMP
-nsCrypto::GetVersion(nsAString& aVersion)
+void
+nsCrypto::GetVersion(nsString& aVersion)
 {
-  aVersion.Assign(NS_LITERAL_STRING(PSM_VERSION_STRING).get());
-  return NS_OK;
+  aVersion.Assign(NS_LITERAL_STRING(PSM_VERSION_STRING));
 }
 
 /*
  * Given an nsKeyGenType, return the PKCS11 mechanism that will
  * perform the correct key generation.
  */
 static uint32_t
 cryptojs_convert_to_mechanism(nsKeyGenType keyGenType)
@@ -1826,236 +1847,204 @@ GetISupportsFromContext(JSContext *cx)
     if (JS_GetOptions(cx) & JSOPTION_PRIVATE_IS_NSISUPPORTS)
         return static_cast<nsISupports *>(JS_GetContextPrivate(cx));
 
     return nullptr;
 }
 
 //The top level method which is a member of nsIDOMCrypto
 //for generate a base64 encoded CRMF request.
-NS_IMETHODIMP
-nsCrypto::GenerateCRMFRequest(nsIDOMCRMFObject** aReturn)
+already_AddRefed<nsIDOMCRMFObject>
+nsCrypto::GenerateCRMFRequest(JSContext* aContext,
+                              const nsCString& aReqDN,
+                              const nsCString& aRegToken,
+                              const nsCString& aAuthenticator,
+                              const nsCString& aEaCert,
+                              const nsCString& aJsCallback,
+                              const Sequence<JS::Value>& aArgs,
+                              ErrorResult& aRv)
 {
   nsNSSShutDownPreventionLock locker;
-  *aReturn = nullptr;
+  nsCOMPtr<nsIDOMCRMFObject> crmf;
   nsresult nrv;
-  nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &nrv));
-  NS_ENSURE_SUCCESS(nrv, nrv);
-
-  nsAXPCNativeCallContext *ncc = nullptr;
-
-  nrv = xpc->GetCurrentNativeCallContext(&ncc);
-  NS_ENSURE_SUCCESS(nrv, nrv);
-
-  if (!ncc)
-    return NS_ERROR_NOT_AVAILABLE;
-
-  uint32_t argc;
-
-  ncc->GetArgc(&argc);
-
-  JS::Value *argv = nullptr;
-
-  nrv = ncc->GetArgvPtr(&argv);
-  NS_ENSURE_SUCCESS(nrv, nrv);
-
-  JSContext *cx;
-
-  nrv = ncc->GetJSContext(&cx);
-  NS_ENSURE_SUCCESS(nrv, nrv);
-
-  nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
+
+  uint32_t argc = aArgs.Length();
 
   /*
    * Get all of the parameters.
    */
-  if (argc < 5 || ((argc-5) % 3) != 0) {
-    JS_ReportError(cx, "%s%s", JS_ERROR,
-                  "incorrect number of parameters");
-    return NS_ERROR_FAILURE;
-  }
-  
-  if (JSVAL_IS_NULL(argv[0])) {
-    JS_ReportError(cx, "%s%s", JS_ERROR, "no DN specified");
-    return NS_ERROR_FAILURE;
+  if (argc % 3 != 0) {
+    aRv.ThrowNotEnoughArgsError();
+    return nullptr;
   }
-  
-  JSString *jsString = JS_ValueToString(cx,argv[0]);
-  NS_ENSURE_TRUE(jsString, NS_ERROR_OUT_OF_MEMORY);
-  argv[0] = STRING_TO_JSVAL(jsString);
-  JSAutoByteString reqDN(cx,jsString);
-  NS_ENSURE_TRUE(!!reqDN, NS_ERROR_OUT_OF_MEMORY);
-
-  JSAutoByteString regToken;
-  if (!JSVAL_IS_NULL(argv[1])) {
-    jsString = JS_ValueToString(cx, argv[1]);
-    NS_ENSURE_TRUE(jsString, NS_ERROR_OUT_OF_MEMORY);
-    argv[1] = STRING_TO_JSVAL(jsString);
-    regToken.encodeLatin1(cx, jsString);
-    NS_ENSURE_TRUE(!!regToken, NS_ERROR_OUT_OF_MEMORY);
+
+  if (aReqDN.IsVoid()) {
+    NS_WARNING("no DN specified");
+    aRv.Throw(NS_ERROR_FAILURE);
+    return nullptr;
   }
-  JSAutoByteString authenticator;
-  if (!JSVAL_IS_NULL(argv[2])) {
-    jsString      = JS_ValueToString(cx, argv[2]);
-    NS_ENSURE_TRUE(jsString, NS_ERROR_OUT_OF_MEMORY);
-    argv[2] = STRING_TO_JSVAL(jsString);
-    authenticator.encodeLatin1(cx, jsString);
-    NS_ENSURE_TRUE(!!authenticator, NS_ERROR_OUT_OF_MEMORY);
-  }
-  JSAutoByteString eaCert;
-  if (!JSVAL_IS_NULL(argv[3])) {
-    jsString     = JS_ValueToString(cx, argv[3]);
-    NS_ENSURE_TRUE(jsString, NS_ERROR_OUT_OF_MEMORY);
-    argv[3] = STRING_TO_JSVAL(jsString);
-    eaCert.encodeLatin1(cx, jsString);
-    NS_ENSURE_TRUE(!!eaCert, NS_ERROR_OUT_OF_MEMORY);
+
+  if (aJsCallback.IsVoid()) {
+    NS_WARNING("no completion function specified");
+    aRv.Throw(NS_ERROR_FAILURE);
+    return nullptr;
   }
-  if (JSVAL_IS_NULL(argv[4])) {
-    JS_ReportError(cx, "%s%s", JS_ERROR, "no completion "
-                   "function specified");
-    return NS_ERROR_FAILURE;
+
+  JS::RootedObject script_obj(aContext, GetWrapper());
+  if (MOZ_UNLIKELY(!script_obj)) {
+    aRv.Throw(NS_ERROR_UNEXPECTED);
+    return nullptr;
   }
-  jsString = JS_ValueToString(cx, argv[4]);
-  NS_ENSURE_TRUE(jsString, NS_ERROR_OUT_OF_MEMORY);
-  argv[4] = STRING_TO_JSVAL(jsString);
-  JSAutoByteString jsCallback(cx, jsString);
-  NS_ENSURE_TRUE(!!jsCallback, NS_ERROR_OUT_OF_MEMORY);
-
-  nrv = xpc->WrapNative(cx, JS::CurrentGlobalOrNull(cx),
-                        static_cast<nsIDOMCrypto *>(this),
-                        NS_GET_IID(nsIDOMCrypto), getter_AddRefs(holder));
-  NS_ENSURE_SUCCESS(nrv, nrv);
-
-  JS::RootedObject script_obj(cx, holder->GetJSObject());
-  NS_ENSURE_STATE(script_obj);
-
-  //Put up some UI warning that someone is trying to 
+
+  //Put up some UI warning that someone is trying to
   //escrow the private key.
   //Don't addref this copy.  That way ths reference goes away
   //at the same the nsIX09Cert ref goes away.
   nsNSSCertificate *escrowCert = nullptr;
   nsCOMPtr<nsIX509Cert> nssCert;
   bool willEscrow = false;
-  if (!!eaCert) {
+  if (!aEaCert.IsVoid()) {
     SECItem certDer = {siBuffer, nullptr, 0};
-    SECStatus srv = ATOB_ConvertAsciiToItem(&certDer, eaCert.ptr());
+    SECStatus srv = ATOB_ConvertAsciiToItem(&certDer, aEaCert.get());
     if (srv != SECSuccess) {
-      return NS_ERROR_FAILURE;
+      aRv.Throw(NS_ERROR_FAILURE);
+      return nullptr;
     }
     ScopedCERTCertificate cert(CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
                                                        &certDer, nullptr,
                                                        false, true));
-    if (!cert)
-      return NS_ERROR_FAILURE;
+    if (!cert) {
+      aRv.Throw(NS_ERROR_FAILURE);
+      return nullptr;
+    }
 
     escrowCert = nsNSSCertificate::Create(cert);
     nssCert = escrowCert;
-    if (!nssCert)
-      return NS_ERROR_OUT_OF_MEMORY;
+    if (!nssCert) {
+      aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
+      return nullptr;
+    }
 
     nsCOMPtr<nsIDOMCryptoDialogs> dialogs;
     nsresult rv = getNSSDialogs(getter_AddRefs(dialogs),
                                 NS_GET_IID(nsIDOMCryptoDialogs),
                                 NS_DOMCRYPTODIALOGS_CONTRACTID);
-    if (NS_FAILED(rv))
-      return rv;
+    if (NS_FAILED(rv)) {
+      aRv.Throw(rv);
+      return nullptr;
+    }
 
     bool okay=false;
     {
       nsPSMUITracker tracker;
       if (tracker.isUIForbidden()) {
         okay = false;
       }
       else {
         dialogs->ConfirmKeyEscrow(nssCert, &okay);
       }
     }
-    if (!okay)
-      return NS_OK;
+    if (!okay) {
+      aRv.Throw(NS_ERROR_FAILURE);
+      return nullptr;
+    }
     willEscrow = true;
   }
   nsCOMPtr<nsIInterfaceRequestor> uiCxt = new PipUIContext;
-  int32_t numRequests = (argc - 5)/3;
+  int32_t numRequests = argc / 3;
   nsKeyPairInfo *keyids = new nsKeyPairInfo[numRequests];
   memset(keyids, 0, sizeof(nsKeyPairInfo)*numRequests);
   int keyInfoIndex;
   uint32_t i;
   PK11SlotInfo *slot = nullptr;
   // Go through all of the arguments and generate the appropriate key pairs.
-  for (i=5,keyInfoIndex=0; i<argc; i+=3,keyInfoIndex++) {
-    nrv = cryptojs_ReadArgsAndGenerateKey(cx, &argv[i], &keyids[keyInfoIndex],
-                                         uiCxt, &slot, willEscrow);
-                                       
+  for (i=0,keyInfoIndex=0; i<argc; i+=3,keyInfoIndex++) {
+    nrv = cryptojs_ReadArgsAndGenerateKey(aContext,
+                                          const_cast<JS::Value*>(&aArgs[i]),
+                                          &keyids[keyInfoIndex],
+                                          uiCxt, &slot, willEscrow);
+
     if (NS_FAILED(nrv)) {
       if (slot)
         PK11_FreeSlot(slot);
       nsFreeKeyPairInfo(keyids,numRequests);
-      return nrv;
+      aRv.Throw(nrv);
+      return nullptr;
     }
   }
   // By this time we'd better have a slot for the key gen.
   NS_ASSERTION(slot, "There was no slot selected for key generation");
-  if (slot) 
+  if (slot)
     PK11_FreeSlot(slot);
 
   char *encodedRequest = nsCreateReqFromKeyPairs(keyids,numRequests,
-                                                 reqDN.ptr(),regToken.ptr(),
-                                                 authenticator.ptr(),
+                                                 const_cast<char*>(aReqDN.get()),
+                                                 const_cast<char*>(aRegToken.get()),
+                                                 const_cast<char*>(aAuthenticator.get()),
                                                  escrowCert);
 #ifdef DEBUG_javi
   printf ("Created the folloing CRMF request:\n%s\n", encodedRequest);
 #endif
   if (!encodedRequest) {
     nsFreeKeyPairInfo(keyids, numRequests);
-    return NS_ERROR_FAILURE;
-  }                                                    
+    aRv.Throw(NS_ERROR_FAILURE);
+    return nullptr;
+  }
   nsCRMFObject *newObject = new nsCRMFObject();
   newObject->SetCRMFRequest(encodedRequest);
-  *aReturn = newObject;
-  //Give a reference to the returnee.
-  NS_ADDREF(*aReturn);
+  crmf = newObject;
   nsFreeKeyPairInfo(keyids, numRequests);
 
-  // 
   // Post an event on the UI queue so that the JS gets called after
   // we return control to the JS layer.  Why do we have to this?
   // Because when this API was implemented for PSM 1.x w/ Communicator,
   // the only way to make this method work was to have a callback
   // in the JS layer that got called after key generation had happened.
   // So for backwards compatibility, we return control and then just post
   // an event to call the JS the script provides as the code to execute
   // when the request has been generated.
   //
 
-
   nsCOMPtr<nsIScriptSecurityManager> secMan =
     do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
-  NS_ENSURE_TRUE(secMan, NS_ERROR_UNEXPECTED);
-  
+  if (MOZ_UNLIKELY(!secMan)) {
+    aRv.Throw(NS_ERROR_UNEXPECTED);
+    return nullptr;
+  }
+
   nsCOMPtr<nsIPrincipal> principals;
   nsresult rv = secMan->GetSubjectPrincipal(getter_AddRefs(principals));
-  NS_ENSURE_SUCCESS(rv, rv);
-  NS_ENSURE_TRUE(principals, NS_ERROR_UNEXPECTED);
-  
+  if (NS_FAILED(nrv)) {
+    aRv.Throw(nrv);
+    return nullptr;
+  }
+  if (MOZ_UNLIKELY(!principals)) {
+    aRv.Throw(NS_ERROR_UNEXPECTED);
+    return nullptr;
+  }
+
   nsCryptoRunArgs *args = new nsCryptoRunArgs();
 
-  args->m_cx         = cx;
-  args->m_kungFuDeathGrip = GetISupportsFromContext(cx);
+  args->m_cx         = aContext;
+  args->m_kungFuDeathGrip = GetISupportsFromContext(aContext);
   args->m_scope      = JS_GetParent(script_obj);
-
-  args->m_jsCallback.Adopt(!!jsCallback ? nsCRT::strdup(jsCallback.ptr()) : 0);
+  if (!aJsCallback.IsVoid()) {
+    args->m_jsCallback = aJsCallback;
+  }
   args->m_principals = principals;
-  
+
   nsCryptoRunnable *cryptoRunnable = new nsCryptoRunnable(args);
 
   rv = NS_DispatchToMainThread(cryptoRunnable);
-  if (NS_FAILED(rv))
+  if (NS_FAILED(rv)) {
+    aRv.Throw(rv);
     delete cryptoRunnable;
-
-  return rv;
+  }
+
+  return crmf.forget();
 }
 
 
 // Reminder that we inherit the memory passed into us here.
 // An implementation to let us back up certs as an event.
 nsP12Runnable::nsP12Runnable(nsIX509Cert **certArr, int32_t numCerts,
                              nsIPK11Token *token)
 {
@@ -2222,24 +2211,24 @@ nsCertListCount(CERTCertList *certList)
   node = CERT_LIST_HEAD(certList);
   while (!CERT_LIST_END(node, certList)) {
     numCerts++;
     node = CERT_LIST_NEXT(node);
   }
   return numCerts;
 }
 
-
 //Import user certificates that arrive as a CMMF base64 encoded
 //string.
-NS_IMETHODIMP
-nsCrypto::ImportUserCertificates(const nsAString& aNickname, 
-                                 const nsAString& aCmmfResponse, 
-                                 bool aDoForcedBackup, 
-                                 nsAString& aReturn)
+void
+nsCrypto::ImportUserCertificates(const nsAString& aNickname,
+                                 const nsAString& aCmmfResponse,
+                                 bool aDoForcedBackup,
+                                 nsAString& aReturn,
+                                 ErrorResult& aRv)
 {
   nsNSSShutDownPreventionLock locker;
   char *nickname=nullptr, *cmmfResponse=nullptr;
   CMMFCertRepContent *certRepContent = nullptr;
   int numResponses = 0;
   nsIX509Cert **certArr = nullptr;
   int i;
   CMMFCertResponse *currResponse;
@@ -2420,30 +2409,34 @@ nsCrypto::ImportUserCertificates(const n
     NS_Free(nickname);
   }
   if (cmmfResponse) {
     NS_Free(cmmfResponse);
   }
   if (certRepContent) {
     CMMF_DestroyCertRepContent(certRepContent);
   }
-  return rv;
+
+  if (NS_FAILED(rv)) {
+    aRv.Throw(rv);
+  }
 }
 
-NS_IMETHODIMP
-nsCrypto::PopChallengeResponse(const nsAString& aChallenge, 
-                               nsAString& aReturn)
+void
+nsCrypto::PopChallengeResponse(const nsAString& aChallenge,
+                               nsAString& aReturn,
+                               ErrorResult& aRv)
 {
-  return NS_ERROR_NOT_IMPLEMENTED;
+  aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
 }
 
-NS_IMETHODIMP
-nsCrypto::Random(int32_t aNumBytes, nsAString& aReturn)
+void
+nsCrypto::Random(int32_t aNumBytes, nsAString& aReturn, ErrorResult& aRv)
 {
-  return NS_ERROR_NOT_IMPLEMENTED;
+  aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
 }
 
 static void
 GetDocumentFromContext(JSContext *cx, nsIDocument **aDocument)
 {
   // Get the script context.
   nsIScriptContext* scriptContext = GetScriptContextFromJSContext(cx);
   if (!scriptContext) {
@@ -2467,177 +2460,139 @@ GetDocumentFromContext(JSContext *cx, ns
   return;
 }
 
 void signTextOutputCallback(void *arg, const char *buf, unsigned long len)
 {
   ((nsCString*)arg)->Append(buf, len);
 }
 
-NS_IMETHODIMP
-nsCrypto::SignText(const nsAString& aStringToSign, const nsAString& aCaOption,
-                   nsAString& aResult)
+void
+nsCrypto::SignText(JSContext* aContext,
+                   const nsAString& aStringToSign,
+                   const nsAString& aCaOption,
+                   const Sequence<nsCString>& aArgs,
+                   nsAString& aReturn)
 {
   // XXX This code should return error codes, but we're keeping this
   //     backwards compatible with NS4.x and so we can't throw exceptions.
   NS_NAMED_LITERAL_STRING(internalError, "error:internalError");
 
-  aResult.Truncate();
-
-  nsAXPCNativeCallContext* ncc = nullptr;
-  nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID()));
-  if (xpc) {
-    xpc->GetCurrentNativeCallContext(&ncc);
-  }
-
-  if (!ncc) {
-    aResult.Append(internalError);
-
-    return NS_OK;
-  }
-
-  uint32_t argc;
-  ncc->GetArgc(&argc);
-
-  JSContext *cx;
-  ncc->GetJSContext(&cx);
-  if (!cx) {
-    aResult.Append(internalError);
-
-    return NS_OK;
-  }
+  aReturn.Truncate();
+
+  uint32_t argc = aArgs.Length();
 
   if (!aCaOption.EqualsLiteral("auto") &&
       !aCaOption.EqualsLiteral("ask")) {
-    JS_ReportError(cx, "%s%s", JS_ERROR, "caOption argument must be ask or auto");
-
-    aResult.Append(internalError);
-
-    return NS_OK;
+    NS_WARNING("caOption argument must be ask or auto");
+    aReturn.Append(internalError);
+
+    return;
   }
 
   // It was decided to always behave as if "ask" were specified.
   // XXX Should we warn in the JS Console for auto?
 
   nsCOMPtr<nsIInterfaceRequestor> uiContext = new PipUIContext;
   if (!uiContext) {
-    aResult.Append(internalError);
-
-    return NS_OK;
+    aReturn.Append(internalError);
+
+    return;
   }
 
   bool bestOnly = true;
   bool validOnly = true;
   CERTCertList* certList =
     CERT_FindUserCertsByUsage(CERT_GetDefaultCertDB(), certUsageEmailSigner,
                               bestOnly, validOnly, uiContext);
 
-  uint32_t numCAs = argc - 2;
+  uint32_t numCAs = argc;
   if (numCAs > 0) {
-    JS::Value *argv = nullptr;
-    ncc->GetArgvPtr(&argv);
-
-    nsAutoArrayPtr<JSAutoByteString> caNameBytes(new JSAutoByteString[numCAs]);
-    if (!caNameBytes) {
-      aResult.Append(internalError);
-      return NS_OK;
+    nsAutoArrayPtr<char*> caNames(new char*[numCAs]);
+    if (!caNames) {
+      aReturn.Append(internalError);
+      return;
     }
 
-    JSAutoRequest ar(cx);
-
     uint32_t i;
-    for (i = 2; i < argc; ++i) {
-      JSString *caName = JS_ValueToString(cx, argv[i]);
-      NS_ENSURE_TRUE(caName, NS_ERROR_OUT_OF_MEMORY);
-      argv[i] = STRING_TO_JSVAL(caName);
-      caNameBytes[i - 2].encodeLatin1(cx, caName);
-      NS_ENSURE_TRUE(!!caNameBytes[i - 2], NS_ERROR_OUT_OF_MEMORY);
-    }
-
-    nsAutoArrayPtr<char*> caNames(new char*[numCAs]);
-    if (!caNames) {
-      aResult.Append(internalError);
-      return NS_OK;
-    }
-
     for (i = 0; i < numCAs; ++i)
-      caNames[i] = caNameBytes[i].ptr();
+      caNames[i] = const_cast<char*>(aArgs[i].get());
 
     if (certList &&
         CERT_FilterCertListByCANames(certList, numCAs, caNames,
                                      certUsageEmailSigner) != SECSuccess) {
-      aResult.Append(internalError);
-
-      return NS_OK;
+      aReturn.Append(internalError);
+
+      return;
     }
   }
 
   if (!certList || CERT_LIST_EMPTY(certList)) {
-    aResult.AppendLiteral("error:noMatchingCert");
-
-    return NS_OK;
+    aReturn.AppendLiteral("error:noMatchingCert");
+
+    return;
   }
 
   nsCOMPtr<nsIFormSigningDialog> fsd =
     do_CreateInstance(NS_FORMSIGNINGDIALOG_CONTRACTID);
   if (!fsd) {
-    aResult.Append(internalError);
-
-    return NS_OK;
+    aReturn.Append(internalError);
+
+    return;
   }
 
   nsCOMPtr<nsIDocument> document;
-  GetDocumentFromContext(cx, getter_AddRefs(document));
+  GetDocumentFromContext(aContext, getter_AddRefs(document));
   if (!document) {
-    aResult.Append(internalError);
-
-    return NS_OK;
+    aReturn.Append(internalError);
+
+    return;
   }
 
   // Get the hostname from the URL of the document.
   nsIURI* uri = document->GetDocumentURI();
   if (!uri) {
-    aResult.Append(internalError);
-
-    return NS_OK;
+    aReturn.Append(internalError);
+
+    return;
   }
 
   nsresult rv;
 
   nsCString host;
   rv = uri->GetHost(host);
   if (NS_FAILED(rv)) {
-    aResult.Append(internalError);
-
-    return NS_OK;
+    aReturn.Append(internalError);
+
+    return;
   }
 
   int32_t numberOfCerts = 0;
   CERTCertListNode* node;
   for (node = CERT_LIST_HEAD(certList); !CERT_LIST_END(node, certList);
        node = CERT_LIST_NEXT(node)) {
     ++numberOfCerts;
   }
 
   ScopedCERTCertNicknames nicknames(getNSSCertNicknamesFromCertList(certList));
 
   if (!nicknames) {
-    aResult.Append(internalError);
-
-    return NS_OK;
+    aReturn.Append(internalError);
+
+    return;
   }
 
   NS_ASSERTION(nicknames->numnicknames == numberOfCerts,
                "nicknames->numnicknames != numberOfCerts");
 
   nsAutoArrayPtr<PRUnichar*> certNicknameList(new PRUnichar*[nicknames->numnicknames * 2]);
   if (!certNicknameList) {
-    aResult.Append(internalError);
-
-    return NS_OK;
+    aReturn.Append(internalError);
+
+    return;
   }
 
   PRUnichar** certDetailsList = certNicknameList.get() + nicknames->numnicknames;
 
   int32_t certsToUse;
   for (node = CERT_LIST_HEAD(certList), certsToUse = 0;
        !CERT_LIST_END(node, certList) && certsToUse < nicknames->numnicknames;
        node = CERT_LIST_NEXT(node)) {
@@ -2656,19 +2611,19 @@ nsCrypto::SignText(const nsAString& aStr
           }
           ++certsToUse;
         }
       }
     }
   }
 
   if (certsToUse == 0) {
-    aResult.Append(internalError);
-
-    return NS_OK;
+    aReturn.Append(internalError);
+
+    return;
   }
 
   NS_ConvertUTF8toUTF16 utf16Host(host);
 
   CERTCertificate *signingCert = nullptr;
   bool tryAgain, canceled;
   nsAutoString password;
   do {
@@ -2709,32 +2664,32 @@ nsCrypto::SignText(const nsAString& aStr
 
   int32_t k;
   for (k = 0; k < certsToUse; ++k) {
     nsMemory::Free(certNicknameList[k]);
     nsMemory::Free(certDetailsList[k]);
   }
 
   if (NS_FAILED(rv)) { // something went wrong inside the tryAgain loop
-    aResult.Append(internalError);
-
-    return NS_OK;
+    aReturn.Append(internalError);
+
+    return;
   }
 
   if (canceled) {
-    aResult.AppendLiteral("error:userCancel");
-
-    return NS_OK;
+    aReturn.AppendLiteral("error:userCancel");
+
+    return;
   }
 
   SECKEYPrivateKey* privKey = PK11_FindKeyByAnyCert(signingCert, uiContext);
   if (!privKey) {
-    aResult.Append(internalError);
-
-    return NS_OK;
+    aReturn.Append(internalError);
+
+    return;
   }
 
   nsAutoCString charset(document->GetDocumentCharacterSet());
 
   // XXX Doing what nsFormSubmission::GetEncoder does (see
   //     http://bugzilla.mozilla.org/show_bug.cgi?id=81203).
   if (charset.EqualsLiteral("ISO-8859-1")) {
     charset.AssignLiteral("windows-1252");
@@ -2750,31 +2705,31 @@ nsCrypto::SignText(const nsAString& aStr
   }
 
   nsXPIDLCString buffer;
   if (aStringToSign.Length() > 0) {
     if (encoder && NS_SUCCEEDED(rv)) {
       rv = encoder->Convert(PromiseFlatString(aStringToSign).get(),
                             getter_Copies(buffer));
       if (NS_FAILED(rv)) {
-        aResult.Append(internalError);
-
-        return NS_OK;
+        aReturn.Append(internalError);
+
+        return;
       }
     }
     else {
       AppendUTF16toUTF8(aStringToSign, buffer);
     }
   }
 
   HASHContext *hc = HASH_Create(HASH_AlgSHA1);
   if (!hc) {
-    aResult.Append(internalError);
-
-    return NS_OK;
+    aReturn.Append(internalError);
+
+    return;
   }
 
   unsigned char hash[SHA1_LENGTH];
 
   SECItem digest;
   digest.data = hash;
 
   HASH_Begin(hc);
@@ -2799,68 +2754,65 @@ nsCrypto::SignText(const nsAString& aStr
                               uiContext);
       }
     }
 
     SEC_PKCS7DestroyContentInfo(ci);
   }
 
   if (srv != SECSuccess) {
-    aResult.Append(internalError);
-
-    return NS_OK;
+    aReturn.Append(internalError);
+
+    return;
   }
 
   SECItem binary_item;
   binary_item.data = reinterpret_cast<unsigned char*>
                                      (const_cast<char*>(p7.get()));
   binary_item.len = p7.Length();
 
   char *result = NSSBase64_EncodeItem(nullptr, nullptr, 0, &binary_item);
   if (result) {
-    AppendASCIItoUTF16(result, aResult);
+    AppendASCIItoUTF16(result, aReturn);
   }
   else {
-    aResult.Append(internalError);
+    aReturn.Append(internalError);
   }
 
   PORT_Free(result);
 
-  return NS_OK;
+  return;
 }
 
-//Logout out of all installed PKCS11 tokens.
-NS_IMETHODIMP
-nsCrypto::Logout()
+void
+nsCrypto::Logout(ErrorResult& aRv)
 {
   nsresult rv;
   nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
-  if (NS_FAILED(rv))
-    return rv;
+  if (NS_FAILED(rv)) {
+    aRv.Throw(rv);
+    return;
+  }
 
   {
     nsNSSShutDownPreventionLock locker;
     PK11_LogoutAll();
     SSL_ClearSessionCache();
   }
 
-  return nssComponent->LogoutAuthenticatedPK11();
+  rv = nssComponent->LogoutAuthenticatedPK11();
+  if (NS_FAILED(rv)) {
+    aRv.Throw(rv);
+  }
 }
 
-NS_IMETHODIMP
-nsCrypto::DisableRightClick()
+void
+nsCrypto::DisableRightClick(ErrorResult& aRv)
 {
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-nsCrypto::GetRandomValues(const JS::Value& aData, JSContext *cx,
-                          JS::Value* _retval)
-{
-  return mozilla::dom::Crypto::GetRandomValues(aData, cx, _retval);
+  aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
 }
 
 nsCRMFObject::nsCRMFObject()
 {
 }
 
 nsCRMFObject::~nsCRMFObject()
 {
--- a/security/manager/ssl/src/nsCrypto.h
+++ b/security/manager/ssl/src/nsCrypto.h
@@ -1,16 +1,18 @@
 /* -*- Mode: C++; 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/. */
 #ifndef _nsCrypto_h_
 #define _nsCrypto_h_
 
+#include "mozilla/dom/BindingDeclarations.h"
+#include "mozilla/ErrorResult.h"
 #ifndef MOZ_DISABLE_CRYPTOLEGACY
 #include "Crypto.h"
 #include "nsCOMPtr.h"
 #include "nsIDOMCRMFObject.h"
 #include "nsIDOMCryptoLegacy.h"
 #include "nsIRunnable.h"
 #include "nsString.h"
 #include "jsapi.h"
@@ -18,17 +20,16 @@
 
 #define NS_CRYPTO_CID \
   {0x929d9320, 0x251e, 0x11d4, { 0x8a, 0x7c, 0x00, 0x60, 0x08, 0xc8, 0x44, 0xc3} }
 #define PSM_VERSION_STRING "2.4"
 
 class nsIPSMComponent;
 class nsIDOMScriptObjectFactory;
 
-
 class nsCRMFObject : public nsIDOMCRMFObject
 {
 public:
   nsCRMFObject();
   virtual ~nsCRMFObject();
 
   NS_DECL_NSIDOMCRMFOBJECT
   NS_DECL_ISUPPORTS
@@ -36,29 +37,68 @@ public:
   nsresult init();
 
   nsresult SetCRMFRequest(char *inRequest);
 private:
 
   nsString mBase64Request;
 };
 
-
 class nsCrypto: public mozilla::dom::Crypto
 {
 public:
   nsCrypto();
   virtual ~nsCrypto();
 
   NS_DECL_ISUPPORTS_INHERITED
 
   // If legacy DOM crypto is enabled this is the class that actually
   // implements the legacy methods.
   NS_DECL_NSIDOMCRYPTO
 
+  virtual bool EnableSmartCardEvents() MOZ_OVERRIDE;
+  virtual void SetEnableSmartCardEvents(bool aEnable,
+                                        mozilla::ErrorResult& aRv) MOZ_OVERRIDE;
+
+  virtual void GetVersion(nsString& aVersion) MOZ_OVERRIDE;
+
+  virtual already_AddRefed<nsIDOMCRMFObject>
+  GenerateCRMFRequest(JSContext* aContext,
+                      const nsCString& aReqDN,
+                      const nsCString& aRegToken,
+                      const nsCString& aAuthenticator,
+                      const nsCString& aEaCert,
+                      const nsCString& aJsCallback,
+                      const mozilla::dom::Sequence<JS::Value>& aArgs,
+                      mozilla::ErrorResult& aRv) MOZ_OVERRIDE;
+
+  virtual void ImportUserCertificates(const nsAString& aNickname,
+                                      const nsAString& aCmmfResponse,
+                                      bool aDoForcedBackup,
+                                      nsAString& aReturn,
+                                      mozilla::ErrorResult& aRv) MOZ_OVERRIDE;
+
+  virtual void PopChallengeResponse(const nsAString& aChallenge,
+                                    nsAString& aReturn,
+                                    mozilla::ErrorResult& aRv) MOZ_OVERRIDE;
+
+  virtual void Random(int32_t aNumBytes,
+                      nsAString& aReturn,
+                      mozilla::ErrorResult& aRv) MOZ_OVERRIDE;
+
+  virtual void SignText(JSContext* aContext,
+                        const nsAString& aStringToSign,
+                        const nsAString& aCaOption,
+                        const mozilla::dom::Sequence<nsCString>& aArgs,
+                        nsAString& aReturn) MOZ_OVERRIDE;
+
+  virtual void Logout(mozilla::ErrorResult& aRv) MOZ_OVERRIDE;
+
+  virtual void DisableRightClick(mozilla::ErrorResult& aRv) MOZ_OVERRIDE;
+
 private:
   static already_AddRefed<nsIPrincipal> GetScriptPrincipal(JSContext *cx);
 
   bool mEnableSmartCardEvents;
 };
 #endif // MOZ_DISABLE_CRYPTOLEGACY
 
 #include "nsIPKCS11.h"
--- a/toolkit/devtools/server/transport.js
+++ b/toolkit/devtools/server/transport.js
@@ -120,21 +120,24 @@ DebuggerTransport.prototype = {
 
   // nsIStreamListener
   onStartRequest:
   makeInfallible(function DT_onStartRequest(aRequest, aContext) {},
                  "DebuggerTransport.prototype.onStartRequest"),
 
   onStopRequest:
   makeInfallible(function DT_onStopRequest(aRequest, aContext, aStatus) {
-    this.close();
-    if (this.hooks) {
-      this.hooks.onClosed(aStatus);
-      this.hooks = null;
-    }
+    let self = this;
+    Services.tm.currentThread.dispatch(makeInfallible(function() {
+      self.close();
+      if (self.hooks) {
+        self.hooks.onClosed(aStatus);
+        self.hooks = null;
+      }
+    }, "DebuggerTransport instance's this.close"), 0);
   }, "DebuggerTransport.prototype.onStopRequest"),
 
   onDataAvailable:
   makeInfallible(function DT_onDataAvailable(aRequest, aContext,
                                              aStream, aOffset, aCount) {
     this._incoming += NetUtil.readInputStreamToString(aStream,
                                                       aStream.available());
     while (this._processIncoming()) {};