head	1.1;
access;
symbols;
locks; strict;
comment	@# @;


1.1
date	2013.01.10.23.03.35;	author svnexp;	state Exp;
branches;
next	;


desc
@@


1.1
log
@## SVN ## Exported commit - http://svnweb.freebsd.org/changeset/base/310207
## SVN ## CVS IS DEPRECATED: http://wiki.freebsd.org/CvsIsDeprecated
## SVN ##
## SVN ## ------------------------------------------------------------------------
## SVN ## r310207 | flo | 2013-01-10 22:29:23 +0000 (Thu, 10 Jan 2013) | 9 lines
## SVN ##
## SVN ## - update www/firefox to 18.0
## SVN ## - update www/firefox-esr to 17.0.2
## SVN ## - update www/seamonkey to 2.15 (enigmail to 1.5.0)
## SVN ## - remove QT4 option to avoid confusion (it turned out to be too experimental)
## SVN ##
## SVN ## In collaboration with: Jan Beich <jbeich@@tormail.org>
## SVN ##
## SVN ## Security:	http://www.vuxml.org/freebsd/a4ed6632-5aa9-11e2-8fcb-c8600054b392.html
## SVN ##
## SVN ## ------------------------------------------------------------------------
## SVN ##
@
text
@commit 74997f1
Author: Jan Varga <jan.varga@@gmail.com>
Date:   Mon Dec 17 20:25:10 2012 +0100

    Bug 787804 - Rewrite quota handling (eliminate test_quota.c). r=bent,asuth,vladan
---
 db/sqlite3/README.MOZILLA                          |    4 +-
 db/sqlite3/src/sqlite.def                          |    1 +
 db/sqlite3/src/test_quota.c                        | 2001 --------------------
 db/sqlite3/src/test_quota.h                        |  274 ---
 dom/Makefile.in                                    |    1 +
 dom/dom-config.mk                                  |    1 +
 dom/file/FileStreamWrappers.cpp                    |   11 -
 dom/file/LockedFile.cpp                            |    8 +-
 dom/file/nsIFileStorage.h                          |   40 +-
 dom/indexedDB/FileManager.cpp                      |   33 +-
 dom/indexedDB/FileManager.h                        |   20 +-
 dom/indexedDB/FileStream.cpp                       |  321 ----
 dom/indexedDB/FileStream.h                         |  140 --
 dom/indexedDB/IDBDatabase.cpp                      |    6 +
 dom/indexedDB/IDBFactory.cpp                       |   28 +-
 dom/indexedDB/IDBFactory.h                         |    8 +-
 dom/indexedDB/IDBFileHandle.cpp                    |   25 +-
 dom/indexedDB/IDBObjectStore.cpp                   |   10 +-
 dom/indexedDB/IDBTransaction.cpp                   |    3 +-
 dom/indexedDB/IndexedDatabaseInlines.h             |   13 +
 dom/indexedDB/IndexedDatabaseManager.cpp           |  162 +-
 dom/indexedDB/IndexedDatabaseManager.h             |   11 +-
 dom/indexedDB/Makefile.in                          |    2 -
 dom/indexedDB/OpenDatabaseHelper.cpp               |  104 +-
 dom/indexedDB/OpenDatabaseHelper.h                 |   12 +-
 dom/indexedDB/nsIStandardFileStream.idl            |   60 -
 dom/indexedDB/test/Makefile.in                     |    2 +
 dom/indexedDB/test/file.js                         |   21 +-
 dom/indexedDB/test/test_file_quota.html            |   14 +-
 dom/indexedDB/test/test_filehandle_quota.html      |    5 +-
 dom/quota/FileStreams.cpp                          |  123 ++
 dom/quota/FileStreams.h                            |  115 ++
 dom/quota/Makefile.in                              |   33 +
 dom/quota/QuotaCommon.h                            |   23 +
 dom/quota/QuotaManager.cpp                         |  294 +++
 dom/quota/QuotaManager.h                           |  147 ++
 layout/build/Makefile.in                           |    1 +
 netwerk/base/src/Makefile.in                       |    1 +
 netwerk/base/src/nsFileStreams.cpp                 |  103 +-
 netwerk/base/src/nsFileStreams.h                   |   12 +-
 storage/public/Makefile.in                         |    1 -
 storage/public/mozIStorageService.idl              |   13 +-
 .../public/mozIStorageServiceQuotaManagement.idl   |   99 -
 storage/public/storage.h                           |    1 -
 storage/src/TelemetryVFS.cpp                       |   35 +-
 storage/src/mozStorageConnection.cpp               |   85 +-
 storage/src/mozStorageConnection.h                 |   27 +-
 storage/src/mozStorageService.cpp                  |  168 +-
 storage/src/mozStorageService.h                    |    3 -
 toolkit/toolkit-makefiles.sh                       |    1 +
 50 files changed, 1239 insertions(+), 3387 deletions(-)

diff --git dom/Makefile.in dom/Makefile.in
index 672e065..47cd253 100644
--- dom/Makefile.in
+++ dom/Makefile.in
@@@@ -58,6 +58,7 @@@@ PARALLEL_DIRS += \
   media \
   messages \
   power \
+  quota \
   settings \
   sms \
   mms \
diff --git dom/dom-config.mk dom/dom-config.mk
index d0f46cc..1cf57ed 100644
--- dom/dom-config.mk
+++ dom/dom-config.mk
@@@@ -8,6 +8,7 @@@@ DOM_SRCDIRS = \
   dom/encoding \
   dom/file \
   dom/power \
+  dom/quota \
   dom/media \
   dom/network/src \
   dom/settings \
diff --git dom/file/FileStreamWrappers.cpp dom/file/FileStreamWrappers.cpp
index 2283266..c4cf102 100644
--- dom/file/FileStreamWrappers.cpp
+++ dom/file/FileStreamWrappers.cpp
@@@@ -8,7 +8,6 @@@@
 
 #include "nsIFileStorage.h"
 #include "nsISeekableStream.h"
-#include "nsIStandardFileStream.h"
 #include "mozilla/Attributes.h"
 
 #include "FileHelper.h"
@@@@ -246,16 +245,6 @@@@ FileOutputStreamWrapper::Close()
   nsresult rv = NS_OK;
 
   if (!mFirstTime) {
-    // We must flush buffers of the stream on the same thread on which we wrote
-    // some data.
-    nsCOMPtr<nsIStandardFileStream> sstream = do_QueryInterface(mFileStream);
-    if (sstream) {
-      rv = sstream->FlushBuffers();
-      if (NS_FAILED(rv)) {
-        NS_WARNING("Failed to flush buffers of the stream!");
-      }
-    }
-
     NS_ASSERTION(PR_GetCurrentThread() == mWriteThread,
                  "Unsetting thread locals on wrong thread!");
     mFileHelper->mFileStorage->UnsetThreadLocals();
diff --git dom/file/LockedFile.cpp dom/file/LockedFile.cpp
index 0fca730..926df91 100644
--- dom/file/LockedFile.cpp
+++ dom/file/LockedFile.cpp
@@@@ -953,10 +953,10 @@@@ FinishHelper::Run()
   }
 
   for (uint32_t index = 0; index < mParallelStreams.Length(); index++) {
-    nsCOMPtr<nsIOutputStream> ostream =
+    nsCOMPtr<nsIInputStream> stream =
       do_QueryInterface(mParallelStreams[index]);
 
-    if (NS_FAILED(ostream->Close())) {
+    if (NS_FAILED(stream->Close())) {
       NS_WARNING("Failed to close stream!");
     }
 
@@@@ -964,9 +964,9 @@@@ FinishHelper::Run()
   }
 
   if (mStream) {
-    nsCOMPtr<nsIOutputStream> ostream = do_QueryInterface(mStream);
+    nsCOMPtr<nsIInputStream> stream = do_QueryInterface(mStream);
 
-    if (NS_FAILED(ostream->Close())) {
+    if (NS_FAILED(stream->Close())) {
       NS_WARNING("Failed to close stream!");
     }
 
diff --git dom/file/nsIFileStorage.h dom/file/nsIFileStorage.h
index 92bb608..e985f0a 100644
--- dom/file/nsIFileStorage.h
+++ dom/file/nsIFileStorage.h
@@@@ -10,14 +10,17 @@@@
 #include "nsISupports.h"
 
 #define NS_FILESTORAGE_IID \
-  {0xbba9c2ff, 0x85c9, 0x47c1, \
-  { 0xaf, 0xce, 0x0a, 0x7e, 0x6f, 0x21, 0x50, 0x95 } }
+  {0xa0801944, 0x2f1c, 0x4203, \
+  { 0x9c, 0xaa, 0xaa, 0x47, 0xe0, 0x0c, 0x67, 0x92 } }
 
 class nsIFileStorage : public nsISupports
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_FILESTORAGE_IID)
 
+  virtual const nsACString&
+  StorageOrigin() = 0;
+
   virtual nsISupports*
   StorageId() = 0;
 
@@@@ -36,20 +39,23 @@@@ public:
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIFileStorage, NS_FILESTORAGE_IID)
 
-#define NS_DECL_NSIFILESTORAGE \
-  virtual nsISupports*         \
-  StorageId();                 \
-                               \
-  virtual bool                 \
-  IsStorageInvalidated();      \
-                               \
-  virtual bool                 \
-  IsStorageShuttingDown();     \
-                               \
-  virtual void                 \
-  SetThreadLocals();           \
-                               \
-  virtual void                 \
-  UnsetThreadLocals();
+#define NS_DECL_NSIFILESTORAGE                                                 \
+  virtual const nsACString&                                                    \
+  StorageOrigin() MOZ_OVERRIDE;                                                \
+                                                                               \
+  virtual nsISupports*                                                         \
+  StorageId() MOZ_OVERRIDE;                                                    \
+                                                                               \
+  virtual bool                                                                 \
+  IsStorageInvalidated() MOZ_OVERRIDE;                                         \
+                                                                               \
+  virtual bool                                                                 \
+  IsStorageShuttingDown() MOZ_OVERRIDE;                                        \
+                                                                               \
+  virtual void                                                                 \
+  SetThreadLocals() MOZ_OVERRIDE;                                              \
+                                                                               \
+  virtual void                                                                 \
+  UnsetThreadLocals() MOZ_OVERRIDE;
 
 #endif // nsIFileStorage_h__
diff --git dom/indexedDB/FileManager.cpp dom/indexedDB/FileManager.cpp
index 9db56e8..4ed6e9e 100644
--- dom/indexedDB/FileManager.cpp
+++ dom/indexedDB/FileManager.cpp
@@@@ -7,8 +7,8 @@@@
 #include "FileManager.h"
 
 #include "mozIStorageConnection.h"
-#include "mozIStorageServiceQuotaManagement.h"
 #include "mozIStorageStatement.h"
+#include "nsIInputStream.h"
 #include "nsISimpleEnumerator.h"
 
 #include "mozStorageCID.h"
@@@@ -18,6 +18,8 @@@@
 #include "IndexedDatabaseManager.h"
 #include "OpenDatabaseHelper.h"
 
+#include "IndexedDatabaseInlines.h"
+
 #define JOURNAL_DIRECTORY_NAME "journals"
 
 USING_INDEXEDDB_NAMESPACE
@@@@ -262,13 +264,11 @@@@ FileManager::GetFileForId(nsIFile* aDirectory, int64_t aId)
 
 // static
 nsresult
-FileManager::InitDirectory(mozIStorageServiceQuotaManagement* aService,
-                           nsIFile* aDirectory,
+FileManager::InitDirectory(nsIFile* aDirectory,
                            nsIFile* aDatabaseFile,
-                           FactoryPrivilege aPrivilege)
+                           const nsACString& aOrigin)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
-  NS_ASSERTION(aService, "Null service!");
   NS_ASSERTION(aDirectory, "Null directory!");
   NS_ASSERTION(aDatabaseFile, "Null database file!");
 
@@@@ -310,8 +310,8 @@@@ FileManager::InitDirectory(mozIStorageServiceQuotaManagement* aService,
 
     if (hasElements) {
       nsCOMPtr<mozIStorageConnection> connection;
-      rv = OpenDatabaseHelper::CreateDatabaseConnection(
-        NullString(), aDatabaseFile, aDirectory, getter_AddRefs(connection));
+      rv = OpenDatabaseHelper::CreateDatabaseConnection(aDatabaseFile,
+        aDirectory, NullString(), aOrigin, getter_AddRefs(connection));
       NS_ENSURE_SUCCESS(rv, rv);
 
       mozStorageTransaction transaction(connection, false);
@@@@ -377,12 +377,17 @@@@ FileManager::InitDirectory(mozIStorageServiceQuotaManagement* aService,
     }
   }
 
-  if (aPrivilege == Chrome) {
-    return NS_OK;
-  }
+  return NS_OK;
+}
+
+// static
+nsresult
+FileManager::GetUsage(nsIFile* aDirectory, uint64_t* aUsage)
+{
+  uint64_t usage = 0;
 
   nsCOMPtr<nsISimpleEnumerator> entries;
-  rv = aDirectory->GetDirectoryEntries(getter_AddRefs(entries));
+  nsresult rv = aDirectory->GetDirectoryEntries(getter_AddRefs(entries));
   NS_ENSURE_SUCCESS(rv, rv);
 
   bool hasMore;
@@@@ -402,9 +407,13 @@@@ FileManager::InitDirectory(mozIStorageServiceQuotaManagement* aService,
       continue;
     }
 
-    rv = aService->UpdateQuotaInformationForFile(file);
+    int64_t fileSize;
+    rv = file->GetFileSize(&fileSize);
     NS_ENSURE_SUCCESS(rv, rv);
+
+    IncrementUsage(&usage, uint64_t(fileSize));
   }
 
+  *aUsage = usage;
   return NS_OK;
 }
diff --git dom/indexedDB/FileManager.h dom/indexedDB/FileManager.h
index 2c72d0a..370d4a8 100644
--- dom/indexedDB/FileManager.h
+++ dom/indexedDB/FileManager.h
@@@@ -24,10 +24,10 @@@@ class FileManager
   friend class FileInfo;
 
 public:
-  FileManager(const nsACString& aOrigin,
+  FileManager(const nsACString& aOrigin, FactoryPrivilege aPrivilege,
               const nsAString& aDatabaseName)
-  : mOrigin(aOrigin), mDatabaseName(aDatabaseName), mLastFileId(0),
-    mInvalidated(false)
+  : mOrigin(aOrigin), mPrivilege(aPrivilege), mDatabaseName(aDatabaseName),
+    mLastFileId(0), mInvalidated(false)
   { }
 
   ~FileManager()
@@@@ -40,6 +40,11 @@@@ public:
     return mOrigin;
   }
 
+  const FactoryPrivilege& Privilege() const
+  {
+    return mPrivilege;
+  }
+
   const nsAString& DatabaseName() const
   {
     return mDatabaseName;
@@@@ -68,12 +73,15 @@@@ public:
   static already_AddRefed<nsIFile> GetFileForId(nsIFile* aDirectory,
                                                 int64_t aId);
 
-  static nsresult InitDirectory(mozIStorageServiceQuotaManagement* aService,
-                                nsIFile* aDirectory, nsIFile* aDatabaseFile,
-                                FactoryPrivilege aPrivilege);
+  static nsresult InitDirectory(nsIFile* aDirectory,
+                                nsIFile* aDatabaseFile,
+                                const nsACString& aOrigin);
+
+  static nsresult GetUsage(nsIFile* aDirectory, uint64_t* aUsage);
 
 private:
   nsCString mOrigin;
+  FactoryPrivilege mPrivilege;
   nsString mDatabaseName;
 
   nsString mDirectoryPath;
diff --git dom/indexedDB/FileStream.cpp dom/indexedDB/FileStream.cpp
deleted file mode 100644
index dddf5d5..0000000
--- dom/indexedDB/FileStream.cpp
+++ /dev/null
@@@@ -1,321 +0,0 @@@@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "FileStream.h"
-
-#include "nsIFile.h"
-
-#include "nsThreadUtils.h"
-#include "test_quota.h"
-
-USING_INDEXEDDB_NAMESPACE
-
-NS_IMPL_THREADSAFE_ADDREF(FileStream)
-NS_IMPL_THREADSAFE_RELEASE(FileStream)
-
-NS_INTERFACE_MAP_BEGIN(FileStream)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStandardFileStream)
-  NS_INTERFACE_MAP_ENTRY(nsISeekableStream)
-  NS_INTERFACE_MAP_ENTRY(nsIInputStream)
-  NS_INTERFACE_MAP_ENTRY(nsIOutputStream)
-  NS_INTERFACE_MAP_ENTRY(nsIStandardFileStream)
-  NS_INTERFACE_MAP_ENTRY(nsIFileMetadata)
-NS_INTERFACE_MAP_END
-
-NS_IMETHODIMP
-FileStream::Seek(int32_t aWhence, int64_t aOffset)
-{
-  // TODO: Add support for 64 bit file sizes, bug 752431
-  NS_ENSURE_TRUE(aOffset <= INT32_MAX, NS_ERROR_INVALID_ARG);
-
-  nsresult rv = DoPendingOpen();
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (!mQuotaFile) {
-    return NS_BASE_STREAM_CLOSED;
-  }
-
-  int whence;
-  switch (aWhence) {
-    case nsISeekableStream::NS_SEEK_SET:
-      whence = SEEK_SET;
-      break;
-    case nsISeekableStream::NS_SEEK_CUR:
-      whence = SEEK_CUR;
-      break;
-    case nsISeekableStream::NS_SEEK_END:
-      whence = SEEK_END;
-      break;
-    default:
-      return NS_ERROR_INVALID_ARG;
-  }
-
-  NS_ASSERTION(!NS_IsMainThread(), "Performing sync IO on the main thread!");
-
-  int rc = sqlite3_quota_fseek(mQuotaFile, aOffset, whence);
-  NS_ENSURE_TRUE(rc == 0, NS_BASE_STREAM_OSERROR);
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-FileStream::Tell(int64_t* aResult)
-{
-  nsresult rv = DoPendingOpen();
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (!mQuotaFile) {
-    return NS_BASE_STREAM_CLOSED;
-  }
-
-  NS_ASSERTION(!NS_IsMainThread(), "Performing sync IO on the main thread!");
-
-  long rc = sqlite3_quota_ftell(mQuotaFile);
-  NS_ENSURE_TRUE(rc >= 0, NS_BASE_STREAM_OSERROR);
-
-  *aResult = rc;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-FileStream::SetEOF()
-{
-  int64_t pos;
-  nsresult rv = Tell(&pos);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  NS_ASSERTION(!NS_IsMainThread(), "Performing sync IO on the main thread!");
-
-  int rc = sqlite3_quota_ftruncate(mQuotaFile, pos);
-  NS_ENSURE_TRUE(rc == 0, NS_BASE_STREAM_OSERROR);
-
-  return NS_OK;
-}
-
-
-NS_IMETHODIMP
-FileStream::Close()
-{
-  CleanUpOpen();
-
-  if (mQuotaFile) {
-    NS_ASSERTION(!NS_IsMainThread(), "Performing sync IO on the main thread!");
-
-    int rc = sqlite3_quota_fclose(mQuotaFile);
-    mQuotaFile = nullptr;
-
-    NS_ENSURE_TRUE(rc == 0, NS_BASE_STREAM_OSERROR);
-  }
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-FileStream::Available(uint64_t* aResult)
-{
-  nsresult rv = DoPendingOpen();
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (!mQuotaFile) {
-    return NS_BASE_STREAM_CLOSED;
-  }
-
-  NS_ASSERTION(!NS_IsMainThread(), "Performing sync IO on the main thread!");
-
-  long rc = sqlite3_quota_file_available(mQuotaFile);
-  NS_ENSURE_TRUE(rc >= 0, NS_BASE_STREAM_OSERROR);
-
-  *aResult = rc;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-FileStream::Read(char* aBuf, uint32_t aCount, uint32_t* aResult)
-{
-  nsresult rv = DoPendingOpen();
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (!mQuotaFile) {
-    return NS_BASE_STREAM_CLOSED;
-  }
-
-  NS_ASSERTION(!NS_IsMainThread(), "Performing sync IO on the main thread!");
-
-  size_t bytesRead = sqlite3_quota_fread(aBuf, 1, aCount, mQuotaFile);
-  if (bytesRead < aCount && sqlite3_quota_ferror(mQuotaFile)) {
-    return NS_BASE_STREAM_OSERROR;
-  }
-
-  *aResult = bytesRead;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-FileStream::ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
-                         uint32_t aCount, uint32_t* aResult)
-{
-  NS_NOTREACHED("Don't call me!");
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-FileStream::IsNonBlocking(bool *aNonBlocking)
-{
-  *aNonBlocking = false;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-FileStream::Write(const char* aBuf, uint32_t aCount, uint32_t *aResult)
-{
-  nsresult rv = DoPendingOpen();
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (!mQuotaFile) {
-    return NS_BASE_STREAM_CLOSED;
-  }
-
-  NS_ASSERTION(!NS_IsMainThread(), "Performing sync IO on the main thread!");
-
-  size_t bytesWritten = sqlite3_quota_fwrite(aBuf, 1, aCount, mQuotaFile);
-  if (bytesWritten < aCount) {
-    return NS_BASE_STREAM_OSERROR;
-  }
-
-  *aResult = bytesWritten;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-FileStream::Flush()
-{
-  nsresult rv = DoPendingOpen();
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (!mQuotaFile) {
-    return NS_BASE_STREAM_CLOSED;
-  }
-
-  NS_ASSERTION(!NS_IsMainThread(), "Performing sync IO on the main thread!");
-
-  int rc = sqlite3_quota_fflush(mQuotaFile, 1);
-  NS_ENSURE_TRUE(rc == 0, NS_BASE_STREAM_OSERROR);
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-FileStream::WriteFrom(nsIInputStream *inStr, uint32_t count, uint32_t *_retval)
-{
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-FileStream::WriteSegments(nsReadSegmentFun reader, void * closure, uint32_t count, uint32_t *_retval)
-{
-  NS_NOTREACHED("Don't call me!");
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-FileStream::Init(nsIFile* aFile, const nsAString& aMode, int32_t aFlags)
-{
-  NS_ASSERTION(!mQuotaFile && !mDeferredOpen, "Already initialized!");
-
-  nsresult rv = aFile->GetPath(mFilePath);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  mMode = aMode;
-  mFlags = aFlags;
- 
-  if (mFlags & nsIStandardFileStream::FLAGS_DEFER_OPEN) {
-    mDeferredOpen = true;
-    return NS_OK;
-  }
-
-  return DoOpen();
-}
-
-NS_IMETHODIMP
-FileStream::GetSize(int64_t* _retval)
-{
-  nsresult rv = DoPendingOpen();
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (!mQuotaFile) {
-    return NS_BASE_STREAM_CLOSED;
-  }
-
-  NS_ASSERTION(!NS_IsMainThread(), "Performing sync IO on the main thread!");
-
-  // TODO: Use sqlite3_quota_file_size() here, bug 760783
-  int64_t rc = sqlite3_quota_file_truesize(mQuotaFile);
-
-  NS_ASSERTION(rc >= 0, "The file is not under quota management!");
-
-  *_retval = rc;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-FileStream::GetLastModified(int64_t* _retval)
-{
-  nsresult rv = DoPendingOpen();
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (!mQuotaFile) {
-    return NS_BASE_STREAM_CLOSED;
-  }
-
-  NS_ASSERTION(!NS_IsMainThread(), "Performing sync IO on the main thread!");
-
-  time_t mtime;
-  int rc = sqlite3_quota_file_mtime(mQuotaFile, &mtime);
-  NS_ENSURE_TRUE(rc == 0, NS_BASE_STREAM_OSERROR);
-
-  *_retval = mtime * PR_MSEC_PER_SEC;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-FileStream::FlushBuffers()
-{
-  nsresult rv = DoPendingOpen();
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (!mQuotaFile) {
-    return NS_BASE_STREAM_CLOSED;
-  }
-
-  NS_ASSERTION(!NS_IsMainThread(), "Performing sync IO on the main thread!");
-
-  int rc = sqlite3_quota_fflush(mQuotaFile, 0);
-  NS_ENSURE_TRUE(rc == 0, NS_BASE_STREAM_OSERROR);
-
-  return NS_OK;
-}
-
-nsresult
-FileStream::DoOpen()
-{
-  NS_ASSERTION(!mFilePath.IsEmpty(), "Must have a file path");
-
-  NS_ASSERTION(!NS_IsMainThread(), "Performing sync IO on the main thread!");
-
-  quota_FILE* quotaFile =
-    sqlite3_quota_fopen(NS_ConvertUTF16toUTF8(mFilePath).get(),
-                        NS_ConvertUTF16toUTF8(mMode).get());
-
-  CleanUpOpen();
-
-  if (!quotaFile) {
-    return NS_BASE_STREAM_OSERROR;
-  }
-
-  mQuotaFile = quotaFile;
-
-  return NS_OK;
-}
diff --git dom/indexedDB/FileStream.h dom/indexedDB/FileStream.h
deleted file mode 100644
index 09648b1..0000000
--- dom/indexedDB/FileStream.h
+++ /dev/null
@@@@ -1,140 +0,0 @@@@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_indexeddb_filestream_h__
-#define mozilla_dom_indexeddb_filestream_h__
-
-#include "IndexedDatabase.h"
-
-#include "nsIFileStreams.h"
-#include "nsIInputStream.h"
-#include "nsIOutputStream.h"
-#include "nsISeekableStream.h"
-#include "nsIStandardFileStream.h"
-
-class nsIFile;
-struct quota_FILE;
-
-BEGIN_INDEXEDDB_NAMESPACE
-
-class FileStream : public nsISeekableStream,
-                   public nsIInputStream,
-                   public nsIOutputStream,
-                   public nsIStandardFileStream,
-                   public nsIFileMetadata
-{
-public:
-  FileStream()
-  : mFlags(0),
-    mDeferredOpen(false),
-    mQuotaFile(nullptr)
-  { }
-
-  virtual ~FileStream()
-  {
-    Close();
-  }
-
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSISEEKABLESTREAM
-  NS_DECL_NSISTANDARDFILESTREAM
-  NS_DECL_NSIFILEMETADATA
-
-  // nsIInputStream
-  NS_IMETHOD
-  Close();
-
-  NS_IMETHOD
-  Available(uint64_t* _retval);
-
-  NS_IMETHOD
-  Read(char* aBuf, uint32_t aCount, uint32_t* _retval);
-
-  NS_IMETHOD
-  ReadSegments(nsWriteSegmentFun aWriter, void* aClosure, uint32_t aCount,
-               uint32_t* _retval);
-
-  NS_IMETHOD
-  IsNonBlocking(bool* _retval);
-
-  // nsIOutputStream
-
-  // Close() already declared
-
-  NS_IMETHOD
-  Flush();
-
-  NS_IMETHOD
-  Write(const char* aBuf, uint32_t aCount, uint32_t* _retval);
-
-  NS_IMETHOD
-  WriteFrom(nsIInputStream* aFromStream, uint32_t aCount, uint32_t* _retval);
-
-  NS_IMETHOD
-  WriteSegments(nsReadSegmentFun aReader, void* aClosure, uint32_t aCount,
-                uint32_t* _retval);
-
-  // IsNonBlocking() already declared
-
-protected:
-  /**
-   * Cleans up data prepared in Init.
-   */
-  void
-  CleanUpOpen()
-  {
-    mFilePath.Truncate();
-    mDeferredOpen = false;
-  }
-
-  /**
-   * Open the file. This is called either from Init
-   * or from DoPendingOpen (if FLAGS_DEFER_OPEN is used when initializing this
-   * stream). The default behavior of DoOpen is to open the file and save the
-   * file descriptor.
-   */
-  virtual nsresult
-  DoOpen();
-
-  /**
-   * If there is a pending open, do it now. It's important for this to be
-   * inlined since we do it in almost every stream API call.
-   */
-  nsresult
-  DoPendingOpen()
-  {
-    if (!mDeferredOpen) {
-      return NS_OK;
-    }
-
-    return DoOpen();
-  }
-
-  /**
-   * Data we need to do an open.
-   */
-  nsString mFilePath;
-  nsString mMode;
-
-  /**
-   * Flags describing our behavior.  See the IDL file for possible values.
-   */
-  int32_t mFlags;
-
-  /**
-   * Whether we have a pending open (see FLAGS_DEFER_OPEN in the IDL file).
-   */
-  bool mDeferredOpen;
-
-  /**
-   * File descriptor for opened file.
-   */
-  quota_FILE* mQuotaFile;
-};
-
-END_INDEXEDDB_NAMESPACE
-
-#endif // mozilla_dom_indexeddb_filestream_h__
diff --git dom/indexedDB/IDBDatabase.cpp dom/indexedDB/IDBDatabase.cpp
index 63500b0..8842daf 100644
--- dom/indexedDB/IDBDatabase.cpp
+++ dom/indexedDB/IDBDatabase.cpp
@@@@ -779,6 +779,12 @@@@ IDBDatabase::Close()
   return NS_OK;
 }
 
+const nsACString&
+IDBDatabase::StorageOrigin()
+{
+  return Origin();
+}
+
 nsISupports*
 IDBDatabase::StorageId()
 {
diff --git dom/indexedDB/IDBFactory.cpp dom/indexedDB/IDBFactory.cpp
index 1007df1..c1f573e 100644
--- dom/indexedDB/IDBFactory.cpp
+++ dom/indexedDB/IDBFactory.cpp
@@@@ -253,8 +253,26 @@@@ IDBFactory::Create(ContentParent* aContentParent,
 }
 
 // static
+already_AddRefed<nsIFileURL>
+IDBFactory::GetDatabaseFileURL(nsIFile* aDatabaseFile, const nsACString& aOrigin)
+{
+  nsCOMPtr<nsIURI> uri;
+  nsresult rv = NS_NewFileURI(getter_AddRefs(uri), aDatabaseFile);
+  NS_ENSURE_SUCCESS(rv, nullptr);
+
+  nsCOMPtr<nsIFileURL> fileUrl = do_QueryInterface(uri);
+  NS_ASSERTION(fileUrl, "This should always succeed!");
+
+  rv = fileUrl->SetQuery(NS_LITERAL_CSTRING("origin=") + aOrigin);
+  NS_ENSURE_SUCCESS(rv, nullptr);
+
+  return fileUrl.forget();
+}
+
+// static
 already_AddRefed<mozIStorageConnection>
-IDBFactory::GetConnection(const nsAString& aDatabaseFilePath)
+IDBFactory::GetConnection(const nsAString& aDatabaseFilePath,
+                          const nsACString& aOrigin)
 {
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
   NS_ASSERTION(StringEndsWith(aDatabaseFilePath, NS_LITERAL_STRING(".sqlite")),
@@@@ -271,13 +289,15 @@@@ IDBFactory::GetConnection(const nsAString& aDatabaseFilePath)
   NS_ENSURE_SUCCESS(rv, nullptr);
   NS_ENSURE_TRUE(exists, nullptr);
 
-  nsCOMPtr<mozIStorageServiceQuotaManagement> ss =
+  nsCOMPtr<nsIFileURL> dbFileUrl = GetDatabaseFileURL(dbFile, aOrigin);
+  NS_ENSURE_TRUE(dbFileUrl, nullptr);
+
+  nsCOMPtr<mozIStorageService> ss =
     do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID);
   NS_ENSURE_TRUE(ss, nullptr);
 
   nsCOMPtr<mozIStorageConnection> connection;
-  rv = ss->OpenDatabaseWithVFS(dbFile, NS_LITERAL_CSTRING("quota"),
-                               getter_AddRefs(connection));
+  rv = ss->OpenDatabaseWithFileURL(dbFileUrl, getter_AddRefs(connection));
   NS_ENSURE_SUCCESS(rv, nullptr);
 
   // Turn on foreign key constraints and recursive triggers.
diff --git dom/indexedDB/IDBFactory.h dom/indexedDB/IDBFactory.h
index d5461f7..49dad42 100644
--- dom/indexedDB/IDBFactory.h
+++ dom/indexedDB/IDBFactory.h
@@@@ -15,6 +15,8 @@@@
 #include "nsCycleCollectionParticipant.h"
 
 class nsIAtom;
+class nsIFile;
+class nsIFileURL;
 class nsPIDOMWindow;
 
 namespace mozilla {
@@@@ -75,8 +77,12 @@@@ public:
   static nsresult Create(ContentParent* aContentParent,
                          IDBFactory** aFactory);
 
+  static already_AddRefed<nsIFileURL>
+  GetDatabaseFileURL(nsIFile* aDatabaseFile, const nsACString& aOrigin);
+
   static already_AddRefed<mozIStorageConnection>
-  GetConnection(const nsAString& aDatabaseFilePath);
+  GetConnection(const nsAString& aDatabaseFilePath,
+                const nsACString& aOrigin);
 
   static nsresult
   LoadDatabaseInformation(mozIStorageConnection* aConnection,
diff --git dom/indexedDB/IDBFileHandle.cpp dom/indexedDB/IDBFileHandle.cpp
index e0340ff..f71fd56 100644
--- dom/indexedDB/IDBFileHandle.cpp
+++ dom/indexedDB/IDBFileHandle.cpp
@@@@ -6,15 +6,14 @@@@
 
 #include "IDBFileHandle.h"
 
-#include "nsIStandardFileStream.h"
-
 #include "mozilla/dom/file/File.h"
+#include "mozilla/dom/quota/FileStreams.h"
 #include "nsDOMClassInfoID.h"
 
-#include "FileStream.h"
 #include "IDBDatabase.h"
 
 USING_INDEXEDDB_NAMESPACE
+USING_QUOTA_NAMESPACE
 
 namespace {
 
@@@@ -68,22 +67,22 @@@@ IDBFileHandle::Create(IDBDatabase* aDatabase,
 already_AddRefed<nsISupports>
 IDBFileHandle::CreateStream(nsIFile* aFile, bool aReadOnly)
 {
-  nsRefPtr<FileStream> stream = new FileStream();
+  const nsACString& origin = mFileStorage->StorageOrigin();
+
+  nsCOMPtr<nsISupports> result;
 
-  nsString streamMode;
   if (aReadOnly) {
-    streamMode.AssignLiteral("rb");
+    nsRefPtr<FileInputStream> stream = FileInputStream::Create(
+      origin, aFile, -1, -1, nsIFileInputStream::DEFER_OPEN);
+    result = NS_ISUPPORTS_CAST(nsIFileInputStream*, stream);
   }
   else {
-    streamMode.AssignLiteral("r+b");
+    nsRefPtr<FileStream> stream = FileStream::Create(
+      origin, aFile, -1, -1, nsIFileStream::DEFER_OPEN);
+    result = NS_ISUPPORTS_CAST(nsIFileStream*, stream);
   }
+  NS_ENSURE_TRUE(result, nullptr);
 
-  nsresult rv = stream->Init(aFile, streamMode,
-                             nsIStandardFileStream::FLAGS_DEFER_OPEN);
-  NS_ENSURE_SUCCESS(rv, nullptr);
-
-  nsCOMPtr<nsISupports> result =
-    NS_ISUPPORTS_CAST(nsIStandardFileStream*, stream);
   return result.forget();
 }
 
diff --git dom/indexedDB/IDBObjectStore.cpp dom/indexedDB/IDBObjectStore.cpp
index 746d473..1f16d26 100644
--- dom/indexedDB/IDBObjectStore.cpp
+++ dom/indexedDB/IDBObjectStore.cpp
@@@@ -17,6 +17,7 @@@@
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/StructuredCloneTags.h"
 #include "mozilla/dom/ipc/Blob.h"
+#include "mozilla/dom/quota/FileStreams.h"
 #include "mozilla/storage.h"
 #include "nsContentUtils.h"
 #include "nsDOMClassInfo.h"
@@@@ -27,10 +28,8 @@@@
 #include "nsServiceManagerUtils.h"
 #include "nsThreadUtils.h"
 #include "snappy/snappy.h"
-#include "test_quota.h"
 
 #include "AsyncConnectionHelper.h"
-#include "FileStream.h"
 #include "IDBCursor.h"
 #include "IDBEvents.h"
 #include "IDBFileHandle.h"
@@@@ -51,6 +50,7 @@@@
 USING_INDEXEDDB_NAMESPACE
 using namespace mozilla::dom;
 using namespace mozilla::dom::indexedDB::ipc;
+using mozilla::dom::quota::FileOutputStream;
 
 namespace {
 
@@@@ -2734,9 +2734,9 @@@@ AddHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
         nativeFile = fileManager->GetFileForId(directory, id);
         NS_ENSURE_TRUE(nativeFile, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
-        nsRefPtr<FileStream> outputStream = new FileStream();
-        rv = outputStream->Init(nativeFile, NS_LITERAL_STRING("wb"), 0);
-        NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
+        nsRefPtr<FileOutputStream> outputStream = FileOutputStream::Create(
+          mObjectStore->Transaction()->Database()->Origin(), nativeFile);
+        NS_ENSURE_TRUE(outputStream, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
         rv = CopyData(inputStream, outputStream);
         NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
diff --git dom/indexedDB/IDBTransaction.cpp dom/indexedDB/IDBTransaction.cpp
index fcef7cc..a5345e2 100644
--- dom/indexedDB/IDBTransaction.cpp
+++ dom/indexedDB/IDBTransaction.cpp
@@@@ -352,7 +352,8 @@@@ IDBTransaction::GetOrCreateConnection(mozIStorageConnection** aResult)
 
   if (!mConnection) {
     nsCOMPtr<mozIStorageConnection> connection =
-      IDBFactory::GetConnection(mDatabase->FilePath());
+      IDBFactory::GetConnection(mDatabase->FilePath(),
+                                mDatabase->Origin());
     NS_ENSURE_TRUE(connection, NS_ERROR_FAILURE);
 
     nsresult rv;
diff --git dom/indexedDB/IndexedDatabaseInlines.h dom/indexedDB/IndexedDatabaseInlines.h
index 62e65d6..f27d60c 100644
--- dom/indexedDB/IndexedDatabaseInlines.h
+++ dom/indexedDB/IndexedDatabaseInlines.h
@@@@ -79,4 +79,17 @@@@ AppendConditionClause(const nsACString& aColumnName,
   aResult += NS_LITERAL_CSTRING(" :") + aArgName;
 }
 
+inline void
+IncrementUsage(uint64_t* aUsage, uint64_t aDelta)
+{
+  // Watch for overflow!
+  if ((UINT64_MAX - *aUsage) < aDelta) {
+    NS_WARNING("Usage exceeds the maximum!");
+    *aUsage = UINT64_MAX;
+  }
+  else {
+    *aUsage += aDelta;
+  }
+}
+
 END_INDEXEDDB_NAMESPACE
diff --git dom/indexedDB/IndexedDatabaseManager.cpp dom/indexedDB/IndexedDatabaseManager.cpp
index e4ad647..88f09da 100644
--- dom/indexedDB/IndexedDatabaseManager.cpp
+++ dom/indexedDB/IndexedDatabaseManager.cpp
@@@@ -22,6 +22,7 @@@@
 #include "nsITimer.h"
 
 #include "mozilla/dom/file/FileService.h"
+#include "mozilla/dom/quota/QuotaManager.h"
 #include "mozilla/dom/TabContext.h"
 #include "mozilla/LazyIdleThread.h"
 #include "mozilla/Preferences.h"
@@@@ -36,7 +37,6 @@@@
 #include "nsThreadUtils.h"
 #include "nsXPCOM.h"
 #include "nsXPCOMPrivate.h"
-#include "test_quota.h"
 #include "xpcpublic.h"
 
 #include "AsyncConnectionHelper.h"
@@@@ -48,6 +48,8 @@@@
 #include "OpenDatabaseHelper.h"
 #include "TransactionThreadPool.h"
 
+#include "IndexedDatabaseInlines.h"
+
 // The amount of time, in milliseconds, that our IO thread will stay alive
 // after the last event it processes.
 #define DEFAULT_THREAD_TIMEOUT_MS 30000
@@@@ -70,6 +72,7 @@@@ using namespace mozilla::services;
 using namespace mozilla::dom;
 using mozilla::Preferences;
 using mozilla::dom::file::FileService;
+using mozilla::dom::quota::QuotaManager;
 
 static NS_DEFINE_CID(kDOMSOF_CID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
 
@@@@ -103,29 +106,6 @@@@ GetDatabaseBaseFilename(const nsAString& aFilename,
   return true;
 }
 
-class QuotaCallback MOZ_FINAL : public mozIStorageQuotaCallback
-{
-public:
-  NS_DECL_ISUPPORTS
-
-  NS_IMETHOD
-  QuotaExceeded(const nsACString& aFilename,
-                int64_t aCurrentSizeLimit,
-                int64_t aCurrentTotalSize,
-                nsISupports* aUserData,
-                int64_t* _retval)
-  {
-    if (IndexedDatabaseManager::QuotaIsLifted()) {
-      *_retval = 0;
-      return NS_OK;
-    }
-
-    return NS_ERROR_FAILURE;
-  }
-};
-
-NS_IMPL_THREADSAFE_ISUPPORTS1(QuotaCallback, mozIStorageQuotaCallback)
-
 // Adds all databases in the hash to the given array.
 template <class T>
 PLDHashOperator
@@@@ -440,8 +420,8 @@@@ IndexedDatabaseManager::GetOrCreate()
                            NS_LITERAL_CSTRING("IndexedDB I/O"),
                            LazyIdleThread::ManualShutdown);
 
-      // We need one quota callback object to hand to SQLite.
-      instance->mQuotaCallbackSingleton = new QuotaCallback();
+      // Make sure that the quota manager is up.
+      NS_ENSURE_TRUE(QuotaManager::GetOrCreate(), nullptr);
 
       // Make a timer here to avoid potential failures later. We don't actually
       // initialize the timer until shutdown.
@@@@ -996,37 +976,15 @@@@ IndexedDatabaseManager::EnsureOriginIsInitialized(const nsACString& aOrigin,
     return NS_OK;
   }
 
-  // First figure out the filename pattern we'll use.
-  nsCOMPtr<nsIFile> patternFile;
-  rv = directory->Clone(getter_AddRefs(patternFile));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  rv = patternFile->Append(NS_LITERAL_STRING("*"));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsString pattern;
-  rv = patternFile->GetPath(pattern);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // Now tell SQLite to start tracking this pattern for content.
-  nsCOMPtr<mozIStorageServiceQuotaManagement> ss =
-    do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID);
-  NS_ENSURE_TRUE(ss, NS_ERROR_FAILURE);
-
-  if (aPrivilege != Chrome) {
-    rv = ss->SetQuotaForFilenamePattern(NS_ConvertUTF16toUTF8(pattern),
-                                        GetIndexedDBQuotaMB() * 1024 * 1024,
-                                        mQuotaCallbackSingleton, nullptr);
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-
   // We need to see if there are any files in the directory already. If they
   // are database files then we need to cleanup stored files (if it's needed)
-  // and also tell SQLite about all of them.
+  // and also initialize the quota.
 
   nsAutoTArray<nsString, 20> subdirsToProcess;
   nsAutoTArray<nsCOMPtr<nsIFile> , 20> unknownFiles;
 
+  uint64_t usage = 0;
+
   nsTHashtable<nsStringHashKey> validSubdirs;
   validSubdirs.Init(20);
 
@@@@ -1068,20 +1026,28 @@@@ IndexedDatabaseManager::EnsureOriginIsInitialized(const nsACString& aOrigin,
       continue;
     }
 
-    nsCOMPtr<nsIFile> fileManagerDirectory;
-    rv = directory->Clone(getter_AddRefs(fileManagerDirectory));
+    nsCOMPtr<nsIFile> fmDirectory;
+    rv = directory->Clone(getter_AddRefs(fmDirectory));
     NS_ENSURE_SUCCESS(rv, rv);
 
-    rv = fileManagerDirectory->Append(dbBaseFilename);
+    rv = fmDirectory->Append(dbBaseFilename);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    rv = FileManager::InitDirectory(ss, fileManagerDirectory, file,
-                                    aPrivilege);
+    rv = FileManager::InitDirectory(fmDirectory, file, aOrigin);
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (aPrivilege != Chrome) {
-      rv = ss->UpdateQuotaInformationForFile(file);
+      uint64_t fileUsage;
+      rv = FileManager::GetUsage(fmDirectory, &fileUsage);
       NS_ENSURE_SUCCESS(rv, rv);
+
+      IncrementUsage(&usage, fileUsage);
+
+      int64_t fileSize;
+      rv = file->GetFileSize(&fileSize);
+      NS_ENSURE_SUCCESS(rv, rv);
+
+      IncrementUsage(&usage, uint64_t(fileSize));
     }
 
     validSubdirs.PutEntry(dbBaseFilename);
@@@@ -1117,12 +1083,39 @@@@ IndexedDatabaseManager::EnsureOriginIsInitialized(const nsACString& aOrigin,
     }
   }
 
+  if (aPrivilege != Chrome) {
+    QuotaManager* quotaManager = QuotaManager::Get();
+    NS_ASSERTION(quotaManager, "Shouldn't be null!");
+
+    quotaManager->InitQuotaForOrigin(aOrigin, GetIndexedDBQuotaMB(), usage);
+  }
+
   mInitializedOrigins.AppendElement(aOrigin);
 
   NS_ADDREF(*aDirectory = directory);
   return NS_OK;
 }
 
+void
+IndexedDatabaseManager::UninitializeOriginsByPattern(
+                                                    const nsACString& aPattern)
+{
+#ifdef DEBUG
+  {
+    bool correctThread;
+    NS_ASSERTION(NS_SUCCEEDED(mIOThread->IsOnCurrentThread(&correctThread)) &&
+                 correctThread,
+                 "Running on the wrong thread!");
+  }
+#endif
+
+  for (int32_t i = mInitializedOrigins.Length() - 1; i >= 0; i--) {
+    if (PatternMatchesOrigin(aPattern, mInitializedOrigins[i])) {
+      mInitializedOrigins.RemoveElementAt(i);
+    }
+  }
+}
+
 bool
 IndexedDatabaseManager::QuotaIsLiftedInternal()
 {
@@@@ -1250,16 +1243,14 @@@@ IndexedDatabaseManager::GetFileManager(const nsACString& aOrigin,
 }
 
 void
-IndexedDatabaseManager::AddFileManager(const nsACString& aOrigin,
-                                       const nsAString& aDatabaseName,
-                                       FileManager* aFileManager)
+IndexedDatabaseManager::AddFileManager(FileManager* aFileManager)
 {
   NS_ASSERTION(aFileManager, "Null file manager!");
 
   nsTArray<nsRefPtr<FileManager> >* array;
-  if (!mFileManagers.Get(aOrigin, &array)) {
+  if (!mFileManagers.Get(aFileManager->Origin(), &array)) {
     array = new nsTArray<nsRefPtr<FileManager> >();
-    mFileManagers.Put(aOrigin, array);
+    mFileManagers.Put(aFileManager->Origin(), array);
   }
 
   array->AppendElement(aFileManager);
@@@@ -1783,6 +1774,13 @@@@ OriginClearRunnable::DeleteFiles(IndexedDatabaseManager* aManager)
       // correctly...
       NS_ERROR("Failed to remove directory!");
     }
+
+    QuotaManager* quotaManager = QuotaManager::Get();
+    NS_ASSERTION(quotaManager, "Shouldn't be null!");
+
+    quotaManager->RemoveQuotaForPattern(mOriginOrPattern);
+
+    aManager->UninitializeOriginsByPattern(mOriginOrPattern);
   }
 }
 
@@@@ -1880,19 +1878,6 @@@@ IndexedDatabaseManager::AsyncUsageRunnable::Cancel()
   }
 }
 
-inline void
-IncrementUsage(uint64_t* aUsage, uint64_t aDelta)
-{
-  // Watch for overflow!
-  if ((INT64_MAX - *aUsage) <= aDelta) {
-    NS_WARNING("Database sizes exceed max we can report!");
-    *aUsage = INT64_MAX;
-  }
-  else {
-    *aUsage += aDelta;
-  }
-}
-
 nsresult
 IndexedDatabaseManager::AsyncUsageRunnable::TakeShortcut()
 {
@@@@ -2295,25 +2280,22 @@@@ IndexedDatabaseManager::AsyncDeleteFileRunnable::Run()
   nsCOMPtr<nsIFile> file = mFileManager->GetFileForId(directory, mFileId);
   NS_ENSURE_TRUE(file, NS_ERROR_FAILURE);
 
-  nsString filePath;
-  nsresult rv = file->GetPath(filePath);
-  NS_ENSURE_SUCCESS(rv, rv);
+  nsresult rv;
+  int64_t fileSize;
 
-  int rc = sqlite3_quota_remove(NS_ConvertUTF16toUTF8(filePath).get());
-  if (rc != SQLITE_OK) {
-    NS_WARNING("Failed to delete stored file!");
-    return NS_ERROR_FAILURE;
+  if (mFileManager->Privilege() != Chrome) {
+    rv = file->GetFileSize(&fileSize);
+    NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
   }
 
-  // sqlite3_quota_remove won't actually remove anything if we're not tracking
-  // the quota here. Manually remove the file if it exists.
-  bool exists;
-  rv = file->Exists(&exists);
-  NS_ENSURE_SUCCESS(rv, rv);
+  rv = file->Remove(false);
+  NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
 
-  if (exists) {
-    rv = file->Remove(false);
-    NS_ENSURE_SUCCESS(rv, rv);
+  if (mFileManager->Privilege() != Chrome) {
+    QuotaManager* quotaManager = QuotaManager::Get();
+    NS_ASSERTION(quotaManager, "Shouldn't be null!");
+
+    quotaManager->DecreaseUsageForOrigin(mFileManager->Origin(), fileSize);
   }
 
   directory = mFileManager->GetJournalDirectory();
diff --git dom/indexedDB/IndexedDatabaseManager.h dom/indexedDB/IndexedDatabaseManager.h
index f9fbbf2..1ea5425 100644
--- dom/indexedDB/IndexedDatabaseManager.h
+++ dom/indexedDB/IndexedDatabaseManager.h
@@@@ -23,7 +23,6 @@@@
 
 #define INDEXEDDB_MANAGER_CONTRACTID "@@mozilla.org/dom/indexeddb/manager;1"
 
-class mozIStorageQuotaCallback;
 class nsIAtom;
 class nsIFile;
 class nsITimer;
@@@@ -134,6 +133,8 @@@@ public:
                                      FactoryPrivilege aPrivilege,
                                      nsIFile** aDirectory);
 
+  void UninitializeOriginsByPattern(const nsACString& aPattern);
+
   // Determine if the quota is lifted for the Window the current thread is
   // using.
   static inline bool
@@@@ -172,9 +173,7 @@@@ public:
                  const nsAString& aDatabaseName);
 
   void
-  AddFileManager(const nsACString& aOrigin,
-                 const nsAString& aDatabaseName,
-                 FileManager* aFileManager);
+  AddFileManager(FileManager* aFileManager);
 
   void InvalidateFileManagersForPattern(const nsACString& aPattern);
 
@@@@ -502,10 +501,6 @@@@ private:
   // A timer that gets activated at shutdown to ensure we close all databases.
   nsCOMPtr<nsITimer> mShutdownTimer;
 
-  // A single threadsafe instance of our quota callback. Created on the main
-  // thread during GetOrCreate().
-  nsCOMPtr<mozIStorageQuotaCallback> mQuotaCallbackSingleton;
-
   // A list of all successfully initialized origins. This list isn't protected
   // by any mutex but it is only ever touched on the IO thread.
   nsTArray<nsCString> mInitializedOrigins;
diff --git dom/indexedDB/Makefile.in dom/indexedDB/Makefile.in
index fef0858..09d4853 100644
--- dom/indexedDB/Makefile.in
+++ dom/indexedDB/Makefile.in
@@@@ -25,7 +25,6 @@@@ CPPSRCS = \
   DatabaseInfo.cpp \
   FileInfo.cpp \
   FileManager.cpp \
-  FileStream.cpp \
   IDBCursor.cpp \
   IDBDatabase.cpp \
   IDBEvents.cpp \
@@@@ -93,7 +92,6 @@@@ XPIDLSRCS = \
   nsIIDBVersionChangeEvent.idl \
   nsIIDBOpenDBRequest.idl \
   nsIIndexedDatabaseManager.idl \
-  nsIStandardFileStream.idl \
   $(NULL)
 
 DIRS += ipc
diff --git dom/indexedDB/OpenDatabaseHelper.cpp dom/indexedDB/OpenDatabaseHelper.cpp
index e71cad4..4cd7f61 100644
--- dom/indexedDB/OpenDatabaseHelper.cpp
+++ dom/indexedDB/OpenDatabaseHelper.cpp
@@@@ -8,11 +8,12 @@@@
 
 #include "nsIFile.h"
 
+#include "mozilla/dom/quota/QuotaManager.h"
 #include "mozilla/storage.h"
 #include "nsEscape.h"
+#include "nsNetUtil.h"
 #include "nsThreadUtils.h"
 #include "snappy/snappy.h"
-#include "test_quota.h"
 
 #include "nsIBFCacheEntry.h"
 #include "IDBEvents.h"
@@@@ -21,6 +22,7 @@@@
 
 using namespace mozilla;
 USING_INDEXEDDB_NAMESPACE
+USING_QUOTA_NAMESPACE
 
 namespace {
 
@@@@ -1632,15 +1634,15 @@@@ OpenDatabaseHelper::DoDatabaseWork()
   rv = dbFile->GetPath(mDatabaseFilePath);
   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
-  nsCOMPtr<nsIFile> fileManagerDirectory;
-  rv = dbDirectory->Clone(getter_AddRefs(fileManagerDirectory));
+  nsCOMPtr<nsIFile> fmDirectory;
+  rv = dbDirectory->Clone(getter_AddRefs(fmDirectory));
   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
-  rv = fileManagerDirectory->Append(filename);
+  rv = fmDirectory->Append(filename);
   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
   nsCOMPtr<mozIStorageConnection> connection;
-  rv = CreateDatabaseConnection(mName, dbFile, fileManagerDirectory,
+  rv = CreateDatabaseConnection(dbFile, fmDirectory, mName, mASCIIOrigin,
                                 getter_AddRefs(connection));
   if (NS_FAILED(rv) &&
       NS_ERROR_GET_MODULE(rv) != NS_ERROR_MODULE_DOM_INDEXEDDB) {
@@@@ -1691,12 +1693,12 @@@@ OpenDatabaseHelper::DoDatabaseWork()
 
   nsRefPtr<FileManager> fileManager = mgr->GetFileManager(mASCIIOrigin, mName);
   if (!fileManager) {
-    fileManager = new FileManager(mASCIIOrigin, mName);
+    fileManager = new FileManager(mASCIIOrigin, mPrivilege, mName);
 
-    rv = fileManager->Init(fileManagerDirectory, connection);
+    rv = fileManager->Init(fmDirectory, connection);
     NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
-    mgr->AddFileManager(mASCIIOrigin, mName, fileManager);
+    mgr->AddFileManager(fileManager);
   }
 
   mFileManager = fileManager.forget();
@@@@ -1707,23 +1709,26 @@@@ OpenDatabaseHelper::DoDatabaseWork()
 // static
 nsresult
 OpenDatabaseHelper::CreateDatabaseConnection(
-                                        const nsAString& aName,
                                         nsIFile* aDBFile,
-                                        nsIFile* aFileManagerDirectory,
+                                        nsIFile* aFMDirectory,
+                                        const nsAString& aName,
+                                        const nsACString& aOrigin,
                                         mozIStorageConnection** aConnection)
 {
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
 
-  NS_NAMED_LITERAL_CSTRING(quotaVFSName, "quota");
+  nsCOMPtr<nsIFileURL> dbFileUrl =
+    IDBFactory::GetDatabaseFileURL(aDBFile, aOrigin);
+  NS_ENSURE_TRUE(dbFileUrl, NS_ERROR_FAILURE);
 
-  nsCOMPtr<mozIStorageServiceQuotaManagement> ss =
+  nsCOMPtr<mozIStorageService> ss =
     do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID);
   NS_ENSURE_TRUE(ss, NS_ERROR_FAILURE);
 
   nsCOMPtr<mozIStorageConnection> connection;
-  nsresult rv = ss->OpenDatabaseWithVFS(aDBFile, quotaVFSName,
-                                        getter_AddRefs(connection));
+  nsresult rv =
+    ss->OpenDatabaseWithFileURL(dbFileUrl, getter_AddRefs(connection));
   if (rv == NS_ERROR_FILE_CORRUPTED) {
     // If we're just opening the database during origin initialization, then
     // we don't want to erase any files. The failure here will fail origin
@@@@ -1737,21 +1742,20 @@@@ OpenDatabaseHelper::CreateDatabaseConnection(
     NS_ENSURE_SUCCESS(rv, rv);
 
     bool exists;
-    rv = aFileManagerDirectory->Exists(&exists);
+    rv = aFMDirectory->Exists(&exists);
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (exists) {
       bool isDirectory;
-      rv = aFileManagerDirectory->IsDirectory(&isDirectory);
+      rv = aFMDirectory->IsDirectory(&isDirectory);
       NS_ENSURE_SUCCESS(rv, rv);
       NS_ENSURE_TRUE(isDirectory, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
-      rv = aFileManagerDirectory->Remove(true);
+      rv = aFMDirectory->Remove(true);
       NS_ENSURE_SUCCESS(rv, rv);
     }
 
-    rv = ss->OpenDatabaseWithVFS(aDBFile, quotaVFSName,
-                                 getter_AddRefs(connection));
+    rv = ss->OpenDatabaseWithFileURL(dbFileUrl, getter_AddRefs(connection));
   }
   NS_ENSURE_SUCCESS(rv, rv);
 
@@@@ -2347,6 +2351,8 @@@@ DeleteDatabaseHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
 {
   NS_ASSERTION(!aConnection, "How did we get a connection here?");
 
+  const FactoryPrivilege& privilege = mOpenHelper->Privilege();
+
   IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
   NS_ASSERTION(mgr, "This should never fail!");
 
@@@@ -2372,59 +2378,57 @@@@ DeleteDatabaseHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
   rv = dbFile->Exists(&exists);
   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
-  int rc;
-
   if (exists) {
-    nsString dbFilePath;
-    rv = dbFile->GetPath(dbFilePath);
-    NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
+    int64_t fileSize;
 
-    rc = sqlite3_quota_remove(NS_ConvertUTF16toUTF8(dbFilePath).get());
-    if (rc != SQLITE_OK) {
-      NS_WARNING("Failed to delete db file!");
-      return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
+    if (privilege != Chrome) {
+      rv = dbFile->GetFileSize(&fileSize);
+      NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
     }
 
-    // sqlite3_quota_remove won't actually remove anything if we're not tracking
-    // the quota here. Manually remove the file if it exists.
-    rv = dbFile->Exists(&exists);
+    rv = dbFile->Remove(false);
     NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
-    if (exists) {
-      rv = dbFile->Remove(false);
-      NS_ENSURE_SUCCESS(rv, rv);
+    if (privilege != Chrome) {
+      QuotaManager* quotaManager = QuotaManager::Get();
+      NS_ASSERTION(quotaManager, "Shouldn't be null!");
+
+      quotaManager->DecreaseUsageForOrigin(mASCIIOrigin, fileSize);
     }
   }
 
-  nsCOMPtr<nsIFile> fileManagerDirectory;
-  rv = directory->Clone(getter_AddRefs(fileManagerDirectory));
-  NS_ENSURE_SUCCESS(rv, rv);
+  nsCOMPtr<nsIFile> fmDirectory;
+  rv = directory->Clone(getter_AddRefs(fmDirectory));
+  NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
-  rv = fileManagerDirectory->Append(filename);
+  rv = fmDirectory->Append(filename);
   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
-  rv = fileManagerDirectory->Exists(&exists);
+  rv = fmDirectory->Exists(&exists);
   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
   if (exists) {
     bool isDirectory;
-    rv = fileManagerDirectory->IsDirectory(&isDirectory);
+    rv = fmDirectory->IsDirectory(&isDirectory);
     NS_ENSURE_SUCCESS(rv, rv);
     NS_ENSURE_TRUE(isDirectory, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
-    nsString fileManagerDirectoryPath;
-    rv = fileManagerDirectory->GetPath(fileManagerDirectoryPath);
-    NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
+    uint64_t usage = 0;
 
-    rc = sqlite3_quota_remove(
-      NS_ConvertUTF16toUTF8(fileManagerDirectoryPath).get());
-    if (rc != SQLITE_OK) {
-      NS_WARNING("Failed to delete file directory!");
-      return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
+    if (privilege != Chrome) {
+      rv = FileManager::GetUsage(fmDirectory, &usage);
+      NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
     }
 
-    rv = fileManagerDirectory->Remove(true);
-    NS_ENSURE_SUCCESS(rv, rv);
+    rv = fmDirectory->Remove(true);
+    NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
+
+    if (privilege != Chrome) {
+      QuotaManager* quotaManager = QuotaManager::Get();
+      NS_ASSERTION(quotaManager, "Shouldn't be null!");
+
+      quotaManager->DecreaseUsageForOrigin(mASCIIOrigin, usage);
+    }
   }
 
   return NS_OK;
diff --git dom/indexedDB/OpenDatabaseHelper.h dom/indexedDB/OpenDatabaseHelper.h
index 587301b..5a3d987 100644
--- dom/indexedDB/OpenDatabaseHelper.h
+++ dom/indexedDB/OpenDatabaseHelper.h
@@@@ -77,10 +77,16 @@@@ public:
     return mDatabase;
   }
 
+  const FactoryPrivilege& Privilege() const
+  {
+    return mPrivilege;
+  }
+
   static
-  nsresult CreateDatabaseConnection(const nsAString& aName,
-                                    nsIFile* aDBFile,
-                                    nsIFile* aFileManagerDirectory,
+  nsresult CreateDatabaseConnection(nsIFile* aDBFile,
+                                    nsIFile* aFMDirectory,
+                                    const nsAString& aName,
+                                    const nsACString& aOrigin,
                                     mozIStorageConnection** aConnection);
 
 protected:
diff --git dom/indexedDB/nsIStandardFileStream.idl dom/indexedDB/nsIStandardFileStream.idl
deleted file mode 100644
index 265c3ed..0000000
--- dom/indexedDB/nsIStandardFileStream.idl
+++ /dev/null
@@@@ -1,60 +0,0 @@@@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-interface nsIFile;
-
-/**
- * A stream that allows you to read from a file or stream to a file
- * using standard file APIs.
- */
-[scriptable, uuid(ebbbb779-92a3-4b2a-b7cf-6efbe904c453)]
-interface nsIStandardFileStream : nsISupports
-{
-  /**
-   * If this is set, the file will be opened (i.e., a call to
-   * fopen done) only when we do an actual operation on the stream,
-   * or more specifically, when one of the following is called:
-   *   - Seek
-   *   - Tell
-   *   - SetEOF
-   *   - Available
-   *   - Read
-   *   - Write
-   *   - Flush
-   *   - GetSize
-   *   - GetLastModified
-   *   - Sync
-   *
-   * FLAGS_DEFER_OPEN is useful if we use the stream on a background
-   * thread, so that the opening and possible |stat|ing of the file
-   * happens there as well.
-   *
-   * @@note Using this flag results in the file not being opened
-   *       during the call to Init.  This means that any errors that might
-   *       happen when this flag is not set would happen during the
-   *       first read.  Also, the file is not locked when Init is called,
-   *       so it might be deleted before we try to read from it.
-   */
-  const long FLAGS_DEFER_OPEN = 1 << 0;
-
-  /**
-   * @@param file          file to read from or stream to
-   * @@param mode          file open mode (see fopen documentation)
-   * @@param flags         flags specifying various behaviors of the class
-   *        (see enumerations in the class)
-   */
-  void init(in nsIFile file,
-            in AString mode,
-            in long flags);
-
-  /**
-   * Flush all written content held in memory buffers out to disk.
-   * This is the equivalent of fflush()
-   */
-  void flushBuffers();
-};
diff --git dom/indexedDB/test/Makefile.in dom/indexedDB/test/Makefile.in
index 9c79b14..4c9a201 100644
--- dom/indexedDB/test/Makefile.in
+++ dom/indexedDB/test/Makefile.in
@@@@ -54,11 +54,13 @@@@ MOCHITEST_FILES = \
   test_file_os_delete.html \
   test_file_put_get_object.html \
   test_file_put_get_values.html \
+  test_file_quota.html \
   test_file_replace.html \
   test_file_resurrection_delete.html \
   test_file_resurrection_transaction_abort.html \
   test_file_sharing.html \
   test_file_transaction_abort.html \
+  test_filehandle_quota.html \
   test_filehandle_serialization.html \
   test_filehandle_store_snapshot.html \
   test_getAll.html \
diff --git dom/indexedDB/test/file.js dom/indexedDB/test/file.js
index 07bd10a..3c6194a 100644
--- dom/indexedDB/test/file.js
+++ dom/indexedDB/test/file.js
@@@@ -3,6 +3,8 @@@@
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
+const DEFAULT_QUOTA = 50 * 1024 * 1024;
+
 var bufferCache = [];
 var utils = SpecialPowers.getDOMWindowUtils(window);
 
@@@@ -184,25 +186,6 @@@@ function getUsage(usageHandler)
   idbManager.getUsageForURI(uri, callback);
 }
 
-function getUsageSync()
-{
-  let usage;
-
-  getUsage(function(aUsage, aFileUsage) {
-    usage = aUsage;
-  });
-
-  let comp = SpecialPowers.wrap(Components);
-  let thread = comp.classes["@@mozilla.org/thread-manager;1"]
-                   .getService(comp.interfaces.nsIThreadManager)
-                   .currentThread;
-  while (!usage) {
-    thread.processNextEvent(true);
-  }
-
-  return usage;
-}
-
 function scheduleGC()
 {
   SpecialPowers.exactGC(window, continueToNextStep);
diff --git dom/indexedDB/test/test_file_quota.html dom/indexedDB/test/test_file_quota.html
index b07880d..9fbc0c0 100644
--- dom/indexedDB/test/test_file_quota.html
+++ dom/indexedDB/test/test_file_quota.html
@@@@ -13,14 +13,12 @@@@
   function testSteps()
   {
     const READ_WRITE = IDBTransaction.READ_WRITE;
-    const DEFAULT_QUOTA_MB = 50;
 
     const name = window.location.pathname;
 
     const objectStoreName = "Blobs";
 
-    const testData = { key: 0, value: {} };
-    const fileData = { key: 1, file: null };
+    const fileData = { key: 1, file: getNullFile("random.bin", DEFAULT_QUOTA) };
 
     let request = indexedDB.open(name, 1);
     request.onerror = errorHandler;
@@@@ -32,21 +30,17 @@@@
 
     let db = event.target.result;
 
-    let objectStore = db.createObjectStore(objectStoreName, { });
-    objectStore.add(testData.value, testData.key);
-
-    let size = (DEFAULT_QUOTA_MB + 1) * 1024 * 1024 - getUsageSync();
-    fileData.file = getNullFile("random.bin", size);
+    db.createObjectStore(objectStoreName, { });
 
     event = yield;
 
     is(event.type, "success", "Got correct event type");
 
     trans = db.transaction([objectStoreName], READ_WRITE);
-    objectStore = trans.objectStore(objectStoreName);
+    let objectStore = trans.objectStore(objectStoreName);
 
     request = objectStore.add(fileData.file, fileData.key);
-    request.addEventListener("error", new ExpectError("UnknownError"));
+    request.addEventListener("error", new ExpectError("UnknownError", true));
     request.onsuccess = unexpectedSuccessHandler;
     event = yield;
 
diff --git dom/indexedDB/test/test_filehandle_quota.html dom/indexedDB/test/test_filehandle_quota.html
index addaf01..0506279 100644
--- dom/indexedDB/test/test_filehandle_quota.html
+++ dom/indexedDB/test/test_filehandle_quota.html
@@@@ -13,7 +13,6 @@@@
   function testSteps()
   {
     const READ_WRITE = IDBTransaction.READ_WRITE;
-    const DEFAULT_QUOTA_MB = 50;
 
     const name = window.location.pathname;
 
@@@@ -39,10 +38,10 @@@@
 
     let lockedFile = fileHandle.open("readwrite");
 
-    let blob = getNullBlob((50 + 1) * 1024 * 1024 - getUsageSync());
+    let blob = getNullBlob(DEFAULT_QUOTA);
 
     request = lockedFile.write(blob);
-    request.addEventListener("error", new ExpectError("UnknownError"));
+    request.addEventListener("error", new ExpectError("UnknownError", true));
     request.onsuccess = unexpectedSuccessHandler;
     event = yield;
 
diff --git dom/quota/FileStreams.cpp dom/quota/FileStreams.cpp
new file mode 100644
index 0000000..9de244f
--- /dev/null
+++ dom/quota/FileStreams.cpp
@@@@ -0,0 +1,123 @@@@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "FileStreams.h"
+
+USING_QUOTA_NAMESPACE
+
+template <class FileStreamBase>
+NS_IMETHODIMP
+FileQuotaStream<FileStreamBase>::SetEOF()
+{
+  nsresult rv = FileStreamBase::SetEOF();
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (mQuotaObject) {
+    int64_t offset;
+    nsresult rv = FileStreamBase::Tell(&offset);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    mQuotaObject->UpdateSize(offset);
+  }
+
+  return NS_OK;
+}
+
+template <class FileStreamBase>
+NS_IMETHODIMP
+FileQuotaStream<FileStreamBase>::Close()
+{
+  nsresult rv = FileStreamBase::Close();
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  mQuotaObject = nullptr;
+
+  return NS_OK;
+}
+
+template <class FileStreamBase>
+nsresult
+FileQuotaStream<FileStreamBase>::DoOpen()
+{
+  QuotaManager* quotaManager = QuotaManager::Get();
+  NS_ASSERTION(quotaManager, "Shouldn't be null!");
+
+  NS_ASSERTION(!mQuotaObject, "Creating quota object more than once?");
+  mQuotaObject = quotaManager->GetQuotaObject(mOrigin,
+    FileStreamBase::mOpenParams.localFile);
+
+  nsresult rv = FileStreamBase::DoOpen();
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (mQuotaObject && (FileStreamBase::mOpenParams.ioFlags & PR_TRUNCATE)) {
+    mQuotaObject->UpdateSize(0);
+  }
+
+  return NS_OK;
+}
+
+template <class FileStreamBase>
+NS_IMETHODIMP
+FileQuotaStreamWithWrite<FileStreamBase>::Write(const char* aBuf,
+                                                uint32_t aCount,
+                                                uint32_t* _retval)
+{
+  nsresult rv;
+
+  if (FileQuotaStreamWithWrite::mQuotaObject) {
+    int64_t offset;
+    rv = FileStreamBase::Tell(&offset);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    if (!FileQuotaStreamWithWrite::
+         mQuotaObject->MaybeAllocateMoreSpace(offset, aCount)) {
+      return NS_ERROR_FAILURE;
+    }
+  }
+
+  rv = FileStreamBase::Write(aBuf, aCount, _retval);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  return NS_OK;
+}
+
+NS_IMPL_ISUPPORTS_INHERITED0(FileInputStream, nsFileInputStream)
+
+already_AddRefed<FileInputStream>
+FileInputStream::Create(const nsACString& aOrigin, nsIFile* aFile,
+                        int32_t aIOFlags, int32_t aPerm,
+                        int32_t aBehaviorFlags)
+{
+  nsRefPtr<FileInputStream> stream = new FileInputStream(aOrigin);
+  nsresult rv = stream->Init(aFile, aIOFlags, aPerm, aBehaviorFlags);
+  NS_ENSURE_SUCCESS(rv, nullptr);
+  return stream.forget();
+}
+
+NS_IMPL_ISUPPORTS_INHERITED0(FileOutputStream, nsFileOutputStream)
+
+already_AddRefed<FileOutputStream>
+FileOutputStream::Create(const nsACString& aOrigin, nsIFile* aFile,
+                         int32_t aIOFlags, int32_t aPerm,
+                         int32_t aBehaviorFlags)
+{
+  nsRefPtr<FileOutputStream> stream = new FileOutputStream(aOrigin);
+  nsresult rv = stream->Init(aFile, aIOFlags, aPerm, aBehaviorFlags);
+  NS_ENSURE_SUCCESS(rv, nullptr);
+  return stream.forget();
+}
+
+NS_IMPL_ISUPPORTS_INHERITED0(FileStream, nsFileStream)
+
+already_AddRefed<FileStream>
+FileStream::Create(const nsACString& aOrigin, nsIFile* aFile, int32_t aIOFlags,
+                   int32_t aPerm, int32_t aBehaviorFlags)
+{
+  nsRefPtr<FileStream> stream = new FileStream(aOrigin);
+  nsresult rv = stream->Init(aFile, aIOFlags, aPerm, aBehaviorFlags);
+  NS_ENSURE_SUCCESS(rv, nullptr);
+  return stream.forget();
+}
diff --git dom/quota/FileStreams.h dom/quota/FileStreams.h
new file mode 100644
index 0000000..77bfad4
--- /dev/null
+++ dom/quota/FileStreams.h
@@@@ -0,0 +1,115 @@@@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_quota_filestreams_h__
+#define mozilla_dom_quota_filestreams_h__
+
+#include "QuotaCommon.h"
+
+#include "nsFileStreams.h"
+
+#include "QuotaManager.h"
+
+BEGIN_QUOTA_NAMESPACE
+
+template <class FileStreamBase>
+class FileQuotaStream : public FileStreamBase
+{
+public:
+  // nsFileStreamBase override
+  NS_IMETHOD
+  SetEOF() MOZ_OVERRIDE;
+
+  NS_IMETHOD
+  Close() MOZ_OVERRIDE;
+
+protected:
+  FileQuotaStream(const nsACString& aOrigin)
+  : mOrigin(aOrigin)
+  { }
+
+  // nsFileStreamBase override
+  virtual nsresult
+  DoOpen() MOZ_OVERRIDE;
+
+  nsCString mOrigin;
+  nsRefPtr<QuotaObject> mQuotaObject;
+};
+
+template <class FileStreamBase>
+class FileQuotaStreamWithWrite : public FileQuotaStream<FileStreamBase>
+{
+public:
+  // nsFileStreamBase override
+  NS_IMETHOD
+  Write(const char* aBuf, uint32_t aCount, uint32_t* _retval) MOZ_OVERRIDE;
+
+protected:
+  FileQuotaStreamWithWrite(const nsACString& aOrigin)
+  : FileQuotaStream<FileStreamBase>(aOrigin)
+  { }
+};
+
+class FileInputStream : public FileQuotaStream<nsFileInputStream>
+{
+public:
+  NS_DECL_ISUPPORTS_INHERITED
+
+  static already_AddRefed<FileInputStream>
+  Create(const nsACString& aOrigin, nsIFile* aFile, int32_t aIOFlags = -1,
+         int32_t aPerm = -1, int32_t aBehaviorFlags = 0);
+
+private:
+  FileInputStream(const nsACString& aOrigin)
+  : FileQuotaStream<nsFileInputStream>(aOrigin)
+  { }
+
+  virtual ~FileInputStream() {
+    Close();
+  }
+};
+
+class FileOutputStream : public FileQuotaStreamWithWrite<nsFileOutputStream>
+{
+public:
+  NS_DECL_ISUPPORTS_INHERITED
+
+  static already_AddRefed<FileOutputStream>
+  Create(const nsACString& aOrigin, nsIFile* aFile, int32_t aIOFlags = -1,
+         int32_t aPerm = -1, int32_t aBehaviorFlags = 0);
+
+private:
+  FileOutputStream(const nsACString& aOrigin)
+  : FileQuotaStreamWithWrite<nsFileOutputStream>(aOrigin)
+  { }
+
+  virtual ~FileOutputStream() {
+    Close();
+  }
+};
+
+class FileStream : public FileQuotaStreamWithWrite<nsFileStream>
+{
+public:
+  NS_DECL_ISUPPORTS_INHERITED
+
+  static already_AddRefed<FileStream>
+  Create(const nsACString& aOrigin, nsIFile* aFile, int32_t aIOFlags = -1,
+         int32_t aPerm = -1, int32_t aBehaviorFlags = 0);
+
+private:
+  FileStream(const nsACString& aOrigin)
+  : FileQuotaStreamWithWrite<nsFileStream>(aOrigin)
+  { }
+
+  virtual ~FileStream() {
+    Close();
+  }
+};
+
+END_QUOTA_NAMESPACE
+
+#endif /* mozilla_dom_quota_filestreams_h__ */
diff --git dom/quota/Makefile.in dom/quota/Makefile.in
new file mode 100644
index 0000000..49be551
--- /dev/null
+++ dom/quota/Makefile.in
@@@@ -0,0 +1,33 @@@@
+# 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/.
+
+DEPTH            = ../..
+topsrcdir        = @@top_srcdir@@
+srcdir           = @@srcdir@@
+VPATH            = @@srcdir@@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE           = dom
+LIBRARY_NAME     = domquota_s
+XPIDL_MODULE     = dom_quota
+LIBXUL_LIBRARY   = 1
+FORCE_STATIC_LIB = 1
+
+include $(topsrcdir)/dom/dom-config.mk
+
+EXPORTS_NAMESPACES = mozilla/dom/quota
+
+CPPSRCS = \
+  FileStreams.cpp \
+  QuotaManager.cpp \
+  $(NULL)
+
+EXPORTS_mozilla/dom/quota = \
+  FileStreams.h \
+  QuotaCommon.h \
+  QuotaManager.h \
+  $(NULL)
+
+include $(topsrcdir)/config/rules.mk
diff --git dom/quota/QuotaCommon.h dom/quota/QuotaCommon.h
new file mode 100644
index 0000000..a415d17
--- /dev/null
+++ dom/quota/QuotaCommon.h
@@@@ -0,0 +1,23 @@@@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_quota_quotacommon_h__
+#define mozilla_dom_quota_quotacommon_h__
+
+#include "nsAutoPtr.h"
+#include "nsCOMPtr.h"
+#include "nsDebug.h"
+#include "nsStringGlue.h"
+#include "nsTArray.h"
+
+#define BEGIN_QUOTA_NAMESPACE \
+  namespace mozilla { namespace dom { namespace quota {
+#define END_QUOTA_NAMESPACE \
+  } /* namespace quota */ } /* namespace dom */ } /* namespace mozilla */
+#define USING_QUOTA_NAMESPACE \
+  using namespace mozilla::dom::quota;
+
+#endif // mozilla_dom_quota_quotacommon_h__
diff --git dom/quota/QuotaManager.cpp dom/quota/QuotaManager.cpp
new file mode 100644
index 0000000..b251606
--- /dev/null
+++ dom/quota/QuotaManager.cpp
@@@@ -0,0 +1,294 @@@@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "QuotaManager.h"
+
+#include "nsIFile.h"
+
+#include "mozilla/ClearOnShutdown.h"
+#include "nsComponentManagerUtils.h"
+
+#include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
+
+USING_QUOTA_NAMESPACE
+
+namespace {
+
+nsAutoPtr<QuotaManager> gInstance;
+
+PLDHashOperator
+RemoveQuotaForPatternCallback(const nsACString& aKey,
+                              nsRefPtr<OriginInfo>& aValue,
+                              void* aUserArg)
+{
+  NS_ASSERTION(!aKey.IsEmpty(), "Empty key!");
+  NS_ASSERTION(aValue, "Null pointer!");
+  NS_ASSERTION(aUserArg, "Null pointer!");
+
+  const nsACString* pattern =
+    static_cast<const nsACString*>(aUserArg);
+
+  if (StringBeginsWith(aKey, *pattern)) {
+    return PL_DHASH_REMOVE;
+  }
+
+  return PL_DHASH_NEXT;
+}
+
+} // anonymous namespace
+
+void
+QuotaObject::AddRef()
+{
+  QuotaManager* quotaManager = QuotaManager::Get();
+  if (!quotaManager) {
+    NS_ERROR("Null quota manager, this shouldn't happen, possible leak!");
+
+    NS_AtomicIncrementRefcnt(mRefCnt);
+
+    return;
+  }
+
+  MutexAutoLock lock(quotaManager->mQuotaMutex);
+
+  ++mRefCnt;
+}
+
+void
+QuotaObject::Release()
+{
+  QuotaManager* quotaManager = QuotaManager::Get();
+  if (!quotaManager) {
+    NS_ERROR("Null quota manager, this shouldn't happen, possible leak!");
+
+    nsrefcnt count = NS_AtomicDecrementRefcnt(mRefCnt);
+    if (count == 0) {
+      mRefCnt = 1;
+      delete this;
+    }
+
+    return;
+  }
+
+  {
+    MutexAutoLock lock(quotaManager->mQuotaMutex);
+
+    --mRefCnt;
+
+    if (mRefCnt > 0) {
+      return;
+    }
+
+    if (mOriginInfo) {
+      mOriginInfo->mQuotaObjects.Remove(mPath);
+    }
+  }
+
+  delete this;
+}
+
+void
+QuotaObject::UpdateSize(int64_t aSize)
+{
+  QuotaManager* quotaManager = QuotaManager::Get();
+  NS_ASSERTION(quotaManager, "Shouldn't be null!");
+
+  MutexAutoLock lock(quotaManager->mQuotaMutex);
+
+  if (mOriginInfo) {
+    mOriginInfo->mUsage -= mSize;
+    mSize = aSize;
+    mOriginInfo->mUsage += mSize;
+  }
+}
+
+bool
+QuotaObject::MaybeAllocateMoreSpace(int64_t aOffset, int32_t aCount)
+{
+  int64_t end = aOffset + aCount;
+
+  QuotaManager* quotaManager = QuotaManager::Get();
+  NS_ASSERTION(quotaManager, "Shouldn't be null!");
+
+  MutexAutoLock lock(quotaManager->mQuotaMutex);
+
+  if (mSize >= end || !mOriginInfo) {
+    return true;
+  }
+
+  int64_t newUsage = mOriginInfo->mUsage - mSize + end;
+  if (newUsage > mOriginInfo->mLimit) {
+    if (!indexedDB::IndexedDatabaseManager::QuotaIsLifted()) {
+      return false;
+    }
+
+    nsCString origin = mOriginInfo->mOrigin;
+
+    mOriginInfo->LockedClearOriginInfos();
+    NS_ASSERTION(!mOriginInfo,
+                 "Should have cleared in LockedClearOriginInfos!");
+
+    quotaManager->mOriginInfos.Remove(origin);
+
+    mSize = end;
+
+    return true;
+  }
+
+  mOriginInfo->mUsage = newUsage;
+  mSize = end;
+
+  return true;
+}
+
+#ifdef DEBUG
+void
+OriginInfo::LockedClearOriginInfos()
+{
+  QuotaManager* quotaManager = QuotaManager::Get();
+  NS_ASSERTION(quotaManager, "Shouldn't be null!");
+
+  quotaManager->mQuotaMutex.AssertCurrentThreadOwns();
+
+  mQuotaObjects.EnumerateRead(ClearOriginInfoCallback, nullptr);
+}
+#endif
+
+// static
+PLDHashOperator
+OriginInfo::ClearOriginInfoCallback(const nsAString& aKey,
+                                    QuotaObject* aValue,
+                                    void* aUserArg)
+{
+  NS_ASSERTION(!aKey.IsEmpty(), "Empty key!");
+  NS_ASSERTION(aValue, "Null pointer!");
+
+  aValue->mOriginInfo = nullptr;
+
+  return PL_DHASH_NEXT;
+}
+
+// static
+QuotaManager*
+QuotaManager::GetOrCreate()
+{
+  if (!gInstance) {
+    NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+
+    gInstance = new QuotaManager();
+
+    ClearOnShutdown(&gInstance);
+  }
+
+  return gInstance;
+}
+
+// static
+QuotaManager*
+QuotaManager::Get()
+{
+  // Does not return an owning reference.
+  return gInstance;
+}
+
+void
+QuotaManager::InitQuotaForOrigin(const nsACString& aOrigin,
+                                 int64_t aLimit,
+                                 int64_t aUsage)
+{
+  OriginInfo* info = new OriginInfo(aOrigin, aLimit * 1024 * 1024, aUsage);
+
+  MutexAutoLock lock(mQuotaMutex);
+
+  NS_ASSERTION(!mOriginInfos.GetWeak(aOrigin), "Replacing an existing entry!");
+  mOriginInfos.Put(aOrigin, info);
+}
+
+void
+QuotaManager::DecreaseUsageForOrigin(const nsACString& aOrigin,
+                                     int64_t aSize)
+{
+  MutexAutoLock lock(mQuotaMutex);
+
+  nsRefPtr<OriginInfo> originInfo;
+  mOriginInfos.Get(aOrigin, getter_AddRefs(originInfo));
+
+  if (originInfo) {
+    originInfo->mUsage -= aSize;
+  }
+}
+
+void
+QuotaManager::RemoveQuotaForPattern(const nsACString& aPattern)
+{
+  NS_ASSERTION(!aPattern.IsEmpty(), "Empty pattern!");
+
+  MutexAutoLock lock(mQuotaMutex);
+
+  mOriginInfos.Enumerate(RemoveQuotaForPatternCallback,
+                         const_cast<nsACString*>(&aPattern));
+}
+
+already_AddRefed<QuotaObject>
+QuotaManager::GetQuotaObject(const nsACString& aOrigin,
+                             nsIFile* aFile)
+{
+  NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+
+  nsString path;
+  nsresult rv = aFile->GetPath(path);
+  NS_ENSURE_SUCCESS(rv, nullptr);
+
+  int64_t fileSize;
+
+  bool exists;
+  rv = aFile->Exists(&exists);
+  NS_ENSURE_SUCCESS(rv, nullptr);
+
+  if (exists) {
+    rv = aFile->GetFileSize(&fileSize);
+    NS_ENSURE_SUCCESS(rv, nullptr);
+  }
+  else {
+    fileSize = 0;
+  }
+
+  QuotaObject* info = nullptr;
+  {
+    MutexAutoLock lock(mQuotaMutex);
+
+    nsRefPtr<OriginInfo> originInfo;
+    mOriginInfos.Get(aOrigin, getter_AddRefs(originInfo));
+
+    if (!originInfo) {
+      return nullptr;
+    }
+
+    originInfo->mQuotaObjects.Get(path, &info);
+
+    if (!info) {
+      info = new QuotaObject(originInfo, path, fileSize);
+      originInfo->mQuotaObjects.Put(path, info);
+    }
+  }
+
+  nsRefPtr<QuotaObject> result = info;
+  return result.forget();
+}
+
+already_AddRefed<QuotaObject>
+QuotaManager::GetQuotaObject(const nsACString& aOrigin,
+                             const nsAString& aPath)
+{
+  nsresult rv;
+  nsCOMPtr<nsIFile> file = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
+  NS_ENSURE_SUCCESS(rv, nullptr);
+
+  rv = file->InitWithPath(aPath);
+  NS_ENSURE_SUCCESS(rv, nullptr);
+
+  return GetQuotaObject(aOrigin, file);
+}
diff --git dom/quota/QuotaManager.h dom/quota/QuotaManager.h
new file mode 100644
index 0000000..e19acdd
--- /dev/null
+++ dom/quota/QuotaManager.h
@@@@ -0,0 +1,147 @@@@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_quota_quotamanager_h__
+#define mozilla_dom_quota_quotamanager_h__
+
+#include "QuotaCommon.h"
+
+#include "mozilla/Mutex.h"
+#include "nsDataHashtable.h"
+#include "nsRefPtrHashtable.h"
+#include "nsThreadUtils.h"
+
+BEGIN_QUOTA_NAMESPACE
+
+class OriginInfo;
+class QuotaManager;
+
+class QuotaObject
+{
+  friend class OriginInfo;
+  friend class QuotaManager;
+
+public:
+  void
+  AddRef();
+
+  void
+  Release();
+
+  void
+  UpdateSize(int64_t aSize);
+
+  bool
+  MaybeAllocateMoreSpace(int64_t aOffset, int32_t aCount);
+
+private:
+  QuotaObject(OriginInfo* aOriginInfo, const nsAString& aPath, int64_t aSize)
+  : mOriginInfo(aOriginInfo), mPath(aPath), mSize(aSize)
+  { }
+
+  virtual ~QuotaObject()
+  { }
+
+  nsAutoRefCnt mRefCnt;
+
+  OriginInfo* mOriginInfo;
+  nsString mPath;
+  int64_t mSize;
+};
+
+class OriginInfo
+{
+  friend class QuotaManager;
+  friend class QuotaObject;
+
+public:
+  OriginInfo(const nsACString& aOrigin, int64_t aLimit, int64_t aUsage)
+  : mOrigin(aOrigin), mLimit(aLimit), mUsage(aUsage)
+  {
+    mQuotaObjects.Init();
+  }
+
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(OriginInfo)
+
+private:
+  void
+#ifdef DEBUG
+  LockedClearOriginInfos();
+#else
+  LockedClearOriginInfos()
+  {
+    mQuotaObjects.EnumerateRead(ClearOriginInfoCallback, nullptr);
+  }
+#endif
+
+  static PLDHashOperator
+  ClearOriginInfoCallback(const nsAString& aKey,
+                          QuotaObject* aValue, void* aUserArg);
+
+  nsDataHashtable<nsStringHashKey, QuotaObject*> mQuotaObjects;
+
+  nsCString mOrigin;
+  int64_t mLimit;
+  int64_t mUsage;
+};
+
+class QuotaManager
+{
+  friend class nsAutoPtr<QuotaManager>;
+  friend class OriginInfo;
+  friend class QuotaObject;
+
+public:
+  // Returns a non-owning reference.
+  static QuotaManager*
+  GetOrCreate();
+
+  // Returns a non-owning reference.
+  static QuotaManager*
+  Get();
+
+  void
+  InitQuotaForOrigin(const nsACString& aOrigin,
+                     int64_t aLimit,
+                     int64_t aUsage);
+
+  void
+  DecreaseUsageForOrigin(const nsACString& aOrigin,
+                         int64_t aSize);
+
+  void
+  RemoveQuotaForPattern(const nsACString& aPattern);
+
+  already_AddRefed<QuotaObject>
+  GetQuotaObject(const nsACString& aOrigin,
+                 nsIFile* aFile);
+
+  already_AddRefed<QuotaObject>
+  GetQuotaObject(const nsACString& aOrigin,
+                 const nsAString& aPath);
+
+private:
+  QuotaManager()
+  : mQuotaMutex("QuotaManager.mQuotaMutex")
+  {
+    NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+
+    mOriginInfos.Init();
+  }
+
+  virtual ~QuotaManager()
+  {
+    NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+  }
+
+  mozilla::Mutex mQuotaMutex;
+
+  nsRefPtrHashtable<nsCStringHashKey, OriginInfo> mOriginInfos;
+};
+
+END_QUOTA_NAMESPACE
+
+#endif /* mozilla_dom_quota_quotamanager_h__ */
diff --git layout/build/Makefile.in layout/build/Makefile.in
index e6b32da..496b55f 100644
--- layout/build/Makefile.in
+++ layout/build/Makefile.in
@@@@ -69,6 +69,7 @@@@ SHARED_LIBRARY_LIBS = \
 	$(DEPTH)/dom/encoding/$(LIB_PREFIX)domencoding_s.$(LIB_SUFFIX) \
 	$(DEPTH)/dom/file/$(LIB_PREFIX)domfile_s.$(LIB_SUFFIX) \
 	$(DEPTH)/dom/power/$(LIB_PREFIX)dom_power_s.$(LIB_SUFFIX) \
+	$(DEPTH)/dom/quota/$(LIB_PREFIX)domquota_s.$(LIB_SUFFIX) \
 	$(DEPTH)/dom/settings/$(LIB_PREFIX)jsdomsettings_s.$(LIB_SUFFIX) \
 	$(DEPTH)/dom/permission/$(LIB_PREFIX)jsdompermissionsettings_s.$(LIB_SUFFIX) \
 	$(DEPTH)/dom/network/src/$(LIB_PREFIX)dom_network_s.$(LIB_SUFFIX) \
diff --git netwerk/base/src/Makefile.in netwerk/base/src/Makefile.in
index 0c0d60e..e8cef48 100644
--- netwerk/base/src/Makefile.in
+++ netwerk/base/src/Makefile.in
@@@@ -19,6 +19,7 @@@@ LIBXUL_LIBRARY  = 1
 EXPORTS = \
 		nsMIMEInputStream.h \
 		nsURLHelper.h \
+		nsFileStreams.h \
 		$(NULL)
 
 EXPORTS_NAMESPACES = mozilla/net
diff --git netwerk/base/src/nsFileStreams.cpp netwerk/base/src/nsFileStreams.cpp
index 2420ffc..ecc26aa 100644
--- netwerk/base/src/nsFileStreams.cpp
+++ netwerk/base/src/nsFileStreams.cpp
@@@@ -51,7 +51,9 @@@@ nsFileStreamBase::~nsFileStreamBase()
     Close();
 }
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(nsFileStreamBase, nsISeekableStream)
+NS_IMPL_THREADSAFE_ISUPPORTS2(nsFileStreamBase,
+                              nsISeekableStream,
+                              nsIFileMetadata)
 
 NS_IMETHODIMP
 nsFileStreamBase::Seek(int32_t whence, int64_t offset)
@@@@ -124,6 +126,52 @@@@ nsFileStreamBase::SetEOF()
     return NS_OK;
 }
 
+NS_IMETHODIMP
+nsFileStreamBase::GetSize(int64_t* _retval)
+{
+    nsresult rv = DoPendingOpen();
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    if (!mFD) {
+        return NS_BASE_STREAM_CLOSED;
+    }
+
+    PRFileInfo64 info;
+    if (PR_GetOpenFileInfo64(mFD, &info) == PR_FAILURE) {
+        return NS_BASE_STREAM_OSERROR;
+    }
+
+    *_retval = int64_t(info.size);
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFileStreamBase::GetLastModified(int64_t* _retval)
+{
+    nsresult rv = DoPendingOpen();
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    if (!mFD) {
+        return NS_BASE_STREAM_CLOSED;
+    }
+
+    PRFileInfo64 info;
+    if (PR_GetOpenFileInfo64(mFD, &info) == PR_FAILURE) {
+        return NS_BASE_STREAM_OSERROR;
+    }
+
+    int64_t modTime = int64_t(info.modifyTime);
+    if (modTime == 0) {
+        *_retval = 0;
+    }
+    else {
+        *_retval = modTime / int64_t(PR_USEC_PER_MSEC);
+    }
+
+    return NS_OK;
+}
+
 nsresult
 nsFileStreamBase::Close()
 {
@@@@ -934,13 +982,12 @@@@ nsSafeFileOutputStream::Write(const char *buf, uint32_t count, uint32_t *result)
 ////////////////////////////////////////////////////////////////////////////////
 // nsFileStream
 
-NS_IMPL_ISUPPORTS_INHERITED4(nsFileStream, 
+NS_IMPL_ISUPPORTS_INHERITED3(nsFileStream,
                              nsFileStreamBase,
                              nsIInputStream,
                              nsIOutputStream,
-                             nsIFileStream,
-                             nsIFileMetadata)
- 
+                             nsIFileStream)
+
 NS_IMETHODIMP
 nsFileStream::Init(nsIFile* file, int32_t ioFlags, int32_t perm,
                    int32_t behaviorFlags)
@@@@ -959,50 +1006,4 @@@@ nsFileStream::Init(nsIFile* file, int32_t ioFlags, int32_t perm,
                      mBehaviorFlags & nsIFileStream::DEFER_OPEN);
 }
 
-NS_IMETHODIMP
-nsFileStream::GetSize(int64_t* _retval)
-{
-    nsresult rv = DoPendingOpen();
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    if (!mFD) {
-        return NS_BASE_STREAM_CLOSED;
-    }
-
-    PRFileInfo64 info;
-    if (PR_GetOpenFileInfo64(mFD, &info) == PR_FAILURE) {
-        return NS_BASE_STREAM_OSERROR;
-    }
-
-    *_retval = int64_t(info.size);
-
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsFileStream::GetLastModified(int64_t* _retval)
-{
-    nsresult rv = DoPendingOpen();
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    if (!mFD) {
-        return NS_BASE_STREAM_CLOSED;
-    }
-
-    PRFileInfo64 info;
-    if (PR_GetOpenFileInfo64(mFD, &info) == PR_FAILURE) {
-        return NS_BASE_STREAM_OSERROR;
-    }
-
-    int64_t modTime = int64_t(info.modifyTime);
-    if (modTime == 0) {
-        *_retval = 0;
-    }
-    else {
-        *_retval = modTime / int64_t(PR_USEC_PER_MSEC);
-    }
-
-    return NS_OK;
-}
-
 ////////////////////////////////////////////////////////////////////////////////
diff --git netwerk/base/src/nsFileStreams.h netwerk/base/src/nsFileStreams.h
index 13e5b45..1aa6a82 100644
--- netwerk/base/src/nsFileStreams.h
+++ netwerk/base/src/nsFileStreams.h
@@@@ -24,11 +24,13 @@@@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-class nsFileStreamBase : public nsISeekableStream
+class nsFileStreamBase : public nsISeekableStream,
+                         public nsIFileMetadata
 {
 public:
     NS_DECL_ISUPPORTS
     NS_DECL_NSISEEKABLESTREAM
+    NS_DECL_NSIFILEMETADATA
 
     nsFileStreamBase();
     virtual ~nsFileStreamBase();
@@@@ -124,8 +126,8 @@@@ public:
     NS_IMETHOD IsNonBlocking(bool* _retval)
     {
         return nsFileStreamBase::IsNonBlocking(_retval);
-    } 
-    
+    }
+
     // Overrided from nsFileStreamBase
     NS_IMETHOD Seek(int32_t aWhence, int64_t aOffset);
 
@@@@ -260,13 +262,11 @@@@ protected:
 class nsFileStream : public nsFileStreamBase,
                      public nsIInputStream,
                      public nsIOutputStream,
-                     public nsIFileStream,
-                     public nsIFileMetadata
+                     public nsIFileStream
 {
 public:
     NS_DECL_ISUPPORTS_INHERITED
     NS_DECL_NSIFILESTREAM
-    NS_DECL_NSIFILEMETADATA
     NS_FORWARD_NSIINPUTSTREAM(nsFileStreamBase::)
 
     // Can't use NS_FORWARD_NSIOUTPUTSTREAM due to overlapping methods
diff --git storage/public/Makefile.in storage/public/Makefile.in
index c485d4e..c05e6f3 100644
--- storage/public/Makefile.in
+++ storage/public/Makefile.in
@@@@ -36,7 +36,6 @@@@ XPIDLSRCS = \
   mozIStorageCompletionCallback.idl \
   mozIStorageBaseStatement.idl \
   mozIStorageAsyncStatement.idl \
-  mozIStorageServiceQuotaManagement.idl \
   mozIStorageVacuumParticipant.idl \
 	$(NULL)
 # SEE ABOVE NOTE!
diff --git storage/public/mozIStorageService.idl storage/public/mozIStorageService.idl
index 3087a11..483649b 100644
--- storage/public/mozIStorageService.idl
+++ storage/public/mozIStorageService.idl
@@@@ -7,6 +7,7 @@@@
 
 interface mozIStorageConnection;
 interface nsIFile;
+interface nsIFileURL;
 
 /**
  * The mozIStorageService interface is intended to be implemented by
@@@@ -15,7 +16,7 @@@@ interface nsIFile;
  *
  * This is the only way to open a database connection.
  */
-[scriptable, uuid(fe8e95cb-b377-4c8d-bccb-d9198c67542b)]
+[scriptable, uuid(12bfad34-cca3-40fb-8736-d8bf9db61a27)]
 interface mozIStorageService : nsISupports {
   /**
    * Get a connection to a named special database storage.
@@@@ -106,6 +107,16 @@@@ interface mozIStorageService : nsISupports {
    */
   mozIStorageConnection openUnsharedDatabase(in nsIFile aDatabaseFile);
 
+  /**
+   * See openDatabase(). Exactly the same only initialized with a file URL.
+   * Custom parameters can be passed to SQLite and VFS implementations through
+   * the query part of the URL.
+   *
+   * @@param aURL
+   *        A nsIFileURL that represents the database that is to be opened.
+   */
+  mozIStorageConnection openDatabaseWithFileURL(in nsIFileURL aFileURL);
+
   /*
    * Utilities
    */
diff --git storage/public/mozIStorageServiceQuotaManagement.idl storage/public/mozIStorageServiceQuotaManagement.idl
deleted file mode 100644
index ee5086b..0000000
--- storage/public/mozIStorageServiceQuotaManagement.idl
+++ /dev/null
@@@@ -1,99 +0,0 @@@@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-interface mozIStorageConnection;
-interface nsIFile;
-
-[scriptable, function, uuid(ae94f0a5-ebdf-48f4-9959-085e13235d8d)]
-interface mozIStorageQuotaCallback : nsISupports
-{
-  /**
-   * Called when the file size quota for a group of databases is exceeded.
-   *
-   * @@param aFilename
-   *        The filename of the database that has exceeded the quota.
-   *
-   * @@param aCurrentSizeLimit
-   *        The current size (in bytes) of the quota.
-   *
-   * @@param aCurrentTotalSize
-   *        The current size of all databases in the quota group.
-   *
-   * @@param aUserData
-   *        Any additional data that was provided to the
-   *        setQuotaForFilenamePattern function.
-   *
-   * @@returns A new quota size. A new quota of 0 will disable the quota callback
-   *          and any quota value less than aCurrentTotalSize will cause the
-   *          database operation to fail with NS_ERROR_FILE_NO_DEVICE_SPACE.
-   */
-  long long quotaExceeded(in ACString aFilename,
-                          in long long aCurrentSizeLimit,
-                          in long long aCurrentTotalSize,
-                          in nsISupports aUserData);
-};
-
-/**
- * This is a temporary interface that should eventually merge with
- * mozIStorageService.
- */
-[scriptable, uuid(4d81faf5-fe01-428b-99b8-c94cba12fd72)]
-interface mozIStorageServiceQuotaManagement : nsISupports
-{
-  /**
-   * See mozIStorageService.openDatabase. Exactly the same only with a custom
-   * SQLite VFS.
-   */
-  mozIStorageConnection openDatabaseWithVFS(in nsIFile aDatabaseFile,
-                                            in ACString aVFSName);
-
-  /**
-   * Set a file size quota for a group of databases matching the given filename
-   * pattern, optionally specifying a callback when the quota is exceeded.
-   *
-   * @@param aPattern
-   *        A pattern to match filenames for inclusion in the quota system. May
-   *        contain the following special characters:
-   *          '*'    Matches any sequence of zero or more characters.
-   *          '?'    Matches exactly one character.
-   *          [...]  Matches one character from the enclosed list of characters.
-   *          [^...] Matches one character not in the enclosed list.
-   *
-   * @@param aSizeLimit
-   *        The size limit (in bytes) for the quota group.
-   *
-   * @@param aCallback
-   *        A callback that will be used when the quota is exceeded.
-   *
-   * @@param aUserData
-   *        Additional information to be passed to the callback.
-   */
-  void setQuotaForFilenamePattern(in ACString aPattern,
-                                  in long long aSizeLimit,
-                                  in mozIStorageQuotaCallback aCallback,
-                                  in nsISupports aUserData);
-
-  /**
-   * Adds, removes, or updates the file size information maintained by the quota
-   * system for files not opened through openDatabaseWithVFS().
-   *
-   * Use this function when you want files to be included in quota calculations
-   * that are either a) not SQLite databases, or b) SQLite databases that have
-   * not been opened.
-   *
-   * This function will have no effect on files that do not match an existing
-   * quota pattern (set previously by setQuotaForFilenamePattern()).
-   * 
-   * @@param aFile
-   *        The file for which quota information should be updated. If the file
-   *        exists then its size information will be added or refreshed. If the
-   *        file does not exist then the file will be removed from tracking
-   *        under the quota system.
-   */
-  void updateQuotaInformationForFile(in nsIFile aFile);
-};
diff --git storage/public/storage.h storage/public/storage.h
index 8e571e2..08f39f3 100644
--- storage/public/storage.h
+++ storage/public/storage.h
@@@@ -24,7 +24,6 @@@@
 #include "mozIStorageStatementCallback.h"
 #include "mozIStorageBindingParamsArray.h"
 #include "mozIStorageBindingParams.h"
-#include "mozIStorageServiceQuotaManagement.h"
 #include "mozIStorageVacuumParticipant.h"
 #include "mozIStorageCompletionCallback.h"
 #include "mozIStorageAsyncStatement.h"
diff --git storage/src/TelemetryVFS.cpp storage/src/TelemetryVFS.cpp
index 60de5c4..e4fce09 100644
--- storage/src/TelemetryVFS.cpp
+++ storage/src/TelemetryVFS.cpp
@@@@ -10,6 +10,7 @@@@
 #include "sqlite3.h"
 #include "nsThreadUtils.h"
 #include "mozilla/Util.h"
+#include "mozilla/dom/quota/QuotaManager.h"
 
 /**
  * This preference is a workaround to allow users/sysadmins to identify
@@@@ -24,6 +25,7 @@@@
 namespace {
 
 using namespace mozilla;
+using namespace mozilla::dom::quota;
 
 struct Histograms {
   const char *name;
@@@@ -82,9 +84,17 @@@@ private:
 };
 
 struct telemetry_file {
-  sqlite3_file base;        // Base class.  Must be first
-  Histograms *histograms;   // histograms pertaining to this file
-  sqlite3_file pReal[1];    // This contains the vfs that actually does work
+  // Base class.  Must be first
+  sqlite3_file base;
+
+  // histograms pertaining to this file
+  Histograms *histograms;
+
+  // quota object for this file
+  nsRefPtr<QuotaObject> quotaObject;
+
+  // This contains the vfs that actually does work
+  sqlite3_file pReal[1];
 };
 
 /*
@@@@ -99,6 +109,7 @@@@ xClose(sqlite3_file *pFile)
   if( rc==SQLITE_OK ){
     delete p->base.pMethods;
     p->base.pMethods = NULL;
+    p->quotaObject = nullptr;
   }
   return rc;
 }
@@@@ -126,6 +137,9 @@@@ int
 xWrite(sqlite3_file *pFile, const void *zBuf, int iAmt, sqlite_int64 iOfst)
 {
   telemetry_file *p = (telemetry_file *)pFile;
+  if (p->quotaObject && !p->quotaObject->MaybeAllocateMoreSpace(iOfst, iAmt)) {
+    return SQLITE_FULL;
+  }
   IOThreadAutoTimer ioTimer(p->histograms->writeMS);
   int rc;
   rc = p->pReal->pMethods->xWrite(p->pReal, zBuf, iAmt, iOfst);
@@@@ -144,6 +158,9 @@@@ xTruncate(sqlite3_file *pFile, sqlite_int64 size)
   int rc;
   Telemetry::AutoTimer<Telemetry::MOZ_SQLITE_TRUNCATE_MS> timer;
   rc = p->pReal->pMethods->xTruncate(p->pReal, size);
+  if (rc == SQLITE_OK && p->quotaObject) {
+    p->quotaObject->UpdateSize(size);
+  }
   return rc;
 }
 
@@@@ -300,6 +317,18 @@@@ xOpen(sqlite3_vfs* vfs, const char *zName, sqlite3_file* pFile,
       break;
   }
   p->histograms = h;
+
+  const char* origin;
+  if ((flags & SQLITE_OPEN_URI) &&
+      (origin = sqlite3_uri_parameter(zName, "origin"))) {
+    QuotaManager* quotaManager = QuotaManager::Get();
+    MOZ_ASSERT(quotaManager);
+
+    p->quotaObject = quotaManager->GetQuotaObject(nsDependentCString(origin),
+                                                  NS_ConvertUTF8toUTF16(zName));
+
+  }
+
   rc = orig_vfs->xOpen(orig_vfs, zName, p->pReal, flags, pOutFlags);
   if( rc != SQLITE_OK )
     return rc;
diff --git storage/src/mozStorageConnection.cpp storage/src/mozStorageConnection.cpp
index 3afd3e1b..430824a 100644
--- storage/src/mozStorageConnection.cpp
+++ storage/src/mozStorageConnection.cpp
@@@@ -12,6 +12,7 @@@@
 #include "nsIMemoryReporter.h"
 #include "nsThreadUtils.h"
 #include "nsIFile.h"
+#include "nsIFileURL.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/Mutex.h"
 #include "mozilla/CondVar.h"
@@@@ -471,34 +472,83 @@@@ Connection::getAsyncExecutionTarget()
 }
 
 nsresult
-Connection::initialize(nsIFile *aDatabaseFile,
-                       const char* aVFSName)
+Connection::initialize()
 {
   NS_ASSERTION (!mDBConn, "Initialize called on already opened database!");
   SAMPLE_LABEL("storage", "Connection::initialize");
 
-  int srv;
-  nsresult rv;
+  // in memory database requested, sqlite uses a magic file name
+  int srv = ::sqlite3_open_v2(":memory:", &mDBConn, mFlags, NULL);
+  if (srv != SQLITE_OK) {
+    mDBConn = nullptr;
+    return convertResultCode(srv);
+  }
+
+  return initializeInternal(nullptr);
+}
+
+nsresult
+Connection::initialize(nsIFile *aDatabaseFile)
+{
+  NS_ASSERTION (aDatabaseFile, "Passed null file!");
+  NS_ASSERTION (!mDBConn, "Initialize called on already opened database!");
+  SAMPLE_LABEL("storage", "Connection::initialize");
 
   mDatabaseFile = aDatabaseFile;
 
-  if (aDatabaseFile) {
-    nsAutoString path;
-    rv = aDatabaseFile->GetPath(path);
-    NS_ENSURE_SUCCESS(rv, rv);
+  nsAutoString path;
+  nsresult rv = aDatabaseFile->GetPath(path);
+  NS_ENSURE_SUCCESS(rv, rv);
 
-    srv = ::sqlite3_open_v2(NS_ConvertUTF16toUTF8(path).get(), &mDBConn, mFlags,
-                            aVFSName);
-  }
-  else {
-    // in memory database requested, sqlite uses a magic file name
-    srv = ::sqlite3_open_v2(":memory:", &mDBConn, mFlags, aVFSName);
+  int srv = ::sqlite3_open_v2(NS_ConvertUTF16toUTF8(path).get(), &mDBConn,
+                              mFlags, NULL);
+  if (srv != SQLITE_OK) {
+    mDBConn = nullptr;
+    return convertResultCode(srv);
   }
+
+  rv = initializeInternal(aDatabaseFile);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  mDatabaseFile = aDatabaseFile;
+
+  return NS_OK;
+}
+
+nsresult
+Connection::initialize(nsIFileURL *aFileURL)
+{
+  NS_ASSERTION (aFileURL, "Passed null file URL!");
+  NS_ASSERTION (!mDBConn, "Initialize called on already opened database!");
+  SAMPLE_LABEL("storage", "Connection::initialize");
+
+  nsCOMPtr<nsIFile> databaseFile;
+  nsresult rv = aFileURL->GetFile(getter_AddRefs(databaseFile));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsAutoCString spec;
+  rv = aFileURL->GetSpec(spec);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  int srv = ::sqlite3_open_v2(spec.get(), &mDBConn, mFlags, NULL);
   if (srv != SQLITE_OK) {
     mDBConn = nullptr;
     return convertResultCode(srv);
   }
 
+  rv = initializeInternal(databaseFile);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  mFileURL = aFileURL;
+  mDatabaseFile = databaseFile;
+
+  return NS_OK;
+}
+
+
+nsresult
+Connection::initializeInternal(nsIFile* aDatabaseFile)
+{
   // Properly wrap the database handle's mutex.
   sharedDBMutex.initWithMutex(sqlite3_db_mutex(mDBConn));
 
@@@@ -522,14 +572,14 @@@@ Connection::initialize(nsIFile *aDatabaseFile,
   nsAutoCString pageSizeQuery(MOZ_STORAGE_UNIQUIFY_QUERY_STR
                               "PRAGMA page_size = ");
   pageSizeQuery.AppendInt(pageSize);
-  rv = ExecuteSimpleSQL(pageSizeQuery);
+  nsresult rv = ExecuteSimpleSQL(pageSizeQuery);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Get the current page_size, since it may differ from the specified value.
   sqlite3_stmt *stmt;
   NS_NAMED_LITERAL_CSTRING(pragma_page_size,
                            MOZ_STORAGE_UNIQUIFY_QUERY_STR "PRAGMA page_size");
-  srv = prepareStatement(pragma_page_size, &stmt);
+  int srv = prepareStatement(pragma_page_size, &stmt);
   if (srv == SQLITE_OK) {
     if (SQLITE_ROW == stepStatement(stmt)) {
       pageSize = ::sqlite3_column_int64(stmt, 0);
@@@@ -962,7 +1012,8 @@@@ Connection::Clone(bool aReadOnly,
   nsRefPtr<Connection> clone = new Connection(mStorageService, flags);
   NS_ENSURE_TRUE(clone, NS_ERROR_OUT_OF_MEMORY);
 
-  nsresult rv = clone->initialize(mDatabaseFile);
+  nsresult rv = mFileURL ? clone->initialize(mFileURL)
+                         : clone->initialize(mDatabaseFile);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Copy over pragmas from the original connection.
diff --git storage/src/mozStorageConnection.h storage/src/mozStorageConnection.h
index b71f5db..97f5cf8 100644
--- storage/src/mozStorageConnection.h
+++ storage/src/mozStorageConnection.h
@@@@ -25,6 +25,7 @@@@
 
 struct PRLock;
 class nsIFile;
+class nsIFileURL;
 class nsIEventTarget;
 class nsIThread;
 
@@@@ -63,18 +64,27 @@@@ public:
   Connection(Service *aService, int aFlags);
 
   /**
+   * Creates the connection to an in-memory database.
+   */
+  nsresult initialize();
+
+  /**
    * Creates the connection to the database.
    *
    * @@param aDatabaseFile
    *        The nsIFile of the location of the database to open, or create if it
-   *        does not exist.  Passing in nullptr here creates an in-memory
-   *        database.
-   * @@param aVFSName
-   *        The VFS that SQLite will use when opening this database. NULL means
-   *        "default".
+   *        does not exist.
    */
-  nsresult initialize(nsIFile *aDatabaseFile,
-                      const char* aVFSName = NULL);
+  nsresult initialize(nsIFile *aDatabaseFile);
+
+  /**
+   * Creates the connection to the database.
+   *
+   * @@param aFileURL
+   *        The nsIFileURL of the location of the database to open, or create if it
+   *        does not exist.
+   */
+  nsresult initialize(nsIFileURL *aFileURL);
 
   // fetch the native handle
   sqlite3 *GetNativeConnection() { return mDBConn; }
@@@@ -155,6 +165,8 @@@@ public:
 private:
   ~Connection();
 
+  nsresult initializeInternal(nsIFile *aDatabaseFile);
+
   /**
    * Sets the database into a closed state so no further actions can be
    * performed.
@@@@ -206,6 +218,7 @@@@ private:
   int progressHandler();
 
   sqlite3 *mDBConn;
+  nsCOMPtr<nsIFileURL> mFileURL;
   nsCOMPtr<nsIFile> mDatabaseFile;
 
   /**
diff --git storage/src/mozStorageService.cpp storage/src/mozStorageService.cpp
index 00661d6..862a7da 100644
--- storage/src/mozStorageService.cpp
+++ storage/src/mozStorageService.cpp
@@@@ -24,8 +24,6 @@@@
 #include "mozilla/Preferences.h"
 
 #include "sqlite3.h"
-#include "test_quota.h"
-#include "test_quota.c"
 
 #ifdef SQLITE_OS_WIN
 // "windows.h" was included and it can #define lots of things we care about...
@@@@ -35,61 +33,6 @@@@
 #include "nsIPromptService.h"
 #include "nsIMemoryReporter.h"
 
-namespace {
-
-class QuotaCallbackData
-{
-public:
-  QuotaCallbackData(mozIStorageQuotaCallback *aCallback,
-                    nsISupports *aUserData)
-  : callback(aCallback), userData(aUserData)
-  {
-    MOZ_COUNT_CTOR(QuotaCallbackData);
-  }
-
-  ~QuotaCallbackData()
-  {
-    MOZ_COUNT_DTOR(QuotaCallbackData);
-  }
-
-  static void Callback(const char *zFilename,
-                       sqlite3_int64 *piLimit,
-                       sqlite3_int64 iSize,
-                       void *pArg)
-  {
-    NS_ASSERTION(zFilename && strlen(zFilename), "Null or empty filename!");
-    NS_ASSERTION(piLimit, "Null pointer!");
-
-    QuotaCallbackData *data = static_cast<QuotaCallbackData*>(pArg);
-    if (!data) {
-      // No callback specified, return immediately.
-      return;
-    }
-
-    NS_ASSERTION(data->callback, "Should never have a null callback!");
-
-    nsDependentCString filename(zFilename);
-
-    int64_t newLimit;
-    if (NS_SUCCEEDED(data->callback->QuotaExceeded(filename, *piLimit,
-                                                   iSize, data->userData,
-                                                   &newLimit))) {
-      *piLimit = newLimit;
-    }
-  }
-
-  static void Destroy(void *aUserData)
-  {
-    delete static_cast<QuotaCallbackData*>(aUserData);
-  }
-
-private:
-  nsCOMPtr<mozIStorageQuotaCallback> callback;
-  nsCOMPtr<nsISupports> userData;
-};
-
-} // anonymous namespace
-
 ////////////////////////////////////////////////////////////////////////////////
 //// Defines
 
@@@@ -345,11 +288,10 @@@@ private:
 ////////////////////////////////////////////////////////////////////////////////
 //// Service
 
-NS_IMPL_THREADSAFE_ISUPPORTS3(
+NS_IMPL_THREADSAFE_ISUPPORTS2(
   Service,
   mozIStorageService,
-  nsIObserver,
-  mozIStorageServiceQuotaManagement
+  nsIObserver
 )
 
 Service *Service::gService = nullptr;
@@@@ -438,10 +380,6 @@@@ Service::~Service()
 
   // Shutdown the sqlite3 API.  Warn if shutdown did not turn out okay, but
   // there is nothing actionable we can do in that case.
-  rc = ::sqlite3_quota_shutdown();
-  if (rc != SQLITE_OK)
-    NS_WARNING("sqlite3 did not shutdown cleanly.");
-
   rc = ::sqlite3_shutdown();
   if (rc != SQLITE_OK)
     NS_WARNING("sqlite3 did not shutdown cleanly.");
@@@@ -636,9 +574,6 @@@@ Service::initialize()
   } else {
     NS_WARNING("Failed to register telemetry VFS");
   }
-  rc = ::sqlite3_quota_initialize("telemetry-vfs", 0);
-  if (rc != SQLITE_OK)
-    return convertResultCode(rc);
 
   // Set the default value for the toolkit.storage.synchronous pref.  It will be
   // updated with the user preference on the main thread.
@@@@ -739,28 +674,24 @@@@ Service::OpenSpecialDatabase(const char *aStorageKey,
     // connection to use a memory DB.
   }
   else if (::strcmp(aStorageKey, "profile") == 0) {
-
     rv = NS_GetSpecialDirectory(NS_APP_STORAGE_50_FILE,
                                 getter_AddRefs(storageFile));
     NS_ENSURE_SUCCESS(rv, rv);
 
-    nsString filename;
-    storageFile->GetPath(filename);
-    nsCString filename8 = NS_ConvertUTF16toUTF8(filename.get());
     // fall through to DB initialization
   }
   else {
     return NS_ERROR_INVALID_ARG;
   }
 
-  Connection *msc = new Connection(this, SQLITE_OPEN_READWRITE);
-  NS_ENSURE_TRUE(msc, NS_ERROR_OUT_OF_MEMORY);
+  nsRefPtr<Connection> msc = new Connection(this, SQLITE_OPEN_READWRITE);
 
-  rv = msc->initialize(storageFile);
+  rv = storageFile ? msc->initialize(storageFile) : msc->initialize();
   NS_ENSURE_SUCCESS(rv, rv);
 
-  NS_ADDREF(*_connection = msc);
+  msc.forget(_connection);
   return NS_OK;
+
 }
 
 NS_IMETHODIMP
@@@@ -774,12 +705,11 @@@@ Service::OpenDatabase(nsIFile *aDatabaseFile,
   int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_SHAREDCACHE |
               SQLITE_OPEN_CREATE;
   nsRefPtr<Connection> msc = new Connection(this, flags);
-  NS_ENSURE_TRUE(msc, NS_ERROR_OUT_OF_MEMORY);
 
   nsresult rv = msc->initialize(aDatabaseFile);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  NS_ADDREF(*_connection = msc);
+  msc.forget(_connection);
   return NS_OK;
 }
 
@@@@ -794,12 +724,30 @@@@ Service::OpenUnsharedDatabase(nsIFile *aDatabaseFile,
   int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_PRIVATECACHE |
               SQLITE_OPEN_CREATE;
   nsRefPtr<Connection> msc = new Connection(this, flags);
-  NS_ENSURE_TRUE(msc, NS_ERROR_OUT_OF_MEMORY);
 
   nsresult rv = msc->initialize(aDatabaseFile);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  NS_ADDREF(*_connection = msc);
+  msc.forget(_connection);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+Service::OpenDatabaseWithFileURL(nsIFileURL *aFileURL,
+                                 mozIStorageConnection **_connection)
+{
+  NS_ENSURE_ARG(aFileURL);
+
+  // Always ensure that SQLITE_OPEN_CREATE is passed in for compatibility
+  // reasons.
+  int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_SHAREDCACHE |
+              SQLITE_OPEN_CREATE | SQLITE_OPEN_URI;
+  nsRefPtr<Connection> msc = new Connection(this, flags);
+
+  nsresult rv = msc->initialize(aFileURL);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  msc.forget(_connection);
   return NS_OK;
 }
 
@@@@ -885,67 +833,5 @@@@ Service::Observe(nsISupports *, const char *aTopic, const PRUnichar *)
   return NS_OK;
 }
 
-////////////////////////////////////////////////////////////////////////////////
-//// mozIStorageServiceQuotaManagement
-
-NS_IMETHODIMP
-Service::OpenDatabaseWithVFS(nsIFile *aDatabaseFile,
-                             const nsACString &aVFSName,
-                             mozIStorageConnection **_connection)
-{
-  NS_ENSURE_ARG(aDatabaseFile);
-
-  // Always ensure that SQLITE_OPEN_CREATE is passed in for compatibility
-  // reasons.
-  int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_SHAREDCACHE |
-              SQLITE_OPEN_CREATE;
-  nsRefPtr<Connection> msc = new Connection(this, flags);
-  NS_ENSURE_TRUE(msc, NS_ERROR_OUT_OF_MEMORY);
-
-  nsresult rv = msc->initialize(aDatabaseFile,
-                                PromiseFlatCString(aVFSName).get());
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  NS_ADDREF(*_connection = msc);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-Service::SetQuotaForFilenamePattern(const nsACString &aPattern,
-                                    int64_t aSizeLimit,
-                                    mozIStorageQuotaCallback *aCallback,
-                                    nsISupports *aUserData)
-{
-  NS_ENSURE_FALSE(aPattern.IsEmpty(), NS_ERROR_INVALID_ARG);
-
-  nsAutoPtr<QuotaCallbackData> data;
-  if (aSizeLimit && aCallback) {
-    data = new QuotaCallbackData(aCallback, aUserData);
-  }
-
-  int rc = ::sqlite3_quota_set(PromiseFlatCString(aPattern).get(),
-                               aSizeLimit, QuotaCallbackData::Callback,
-                               data, QuotaCallbackData::Destroy);
-  NS_ENSURE_TRUE(rc == SQLITE_OK, convertResultCode(rc));
-
-  data.forget();
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-Service::UpdateQuotaInformationForFile(nsIFile *aFile)
-{
-  NS_ENSURE_ARG_POINTER(aFile);
-
-  nsString path;
-  nsresult rv = aFile->GetPath(path);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  int rc = ::sqlite3_quota_file(NS_ConvertUTF16toUTF8(path).get());
-  NS_ENSURE_TRUE(rc == SQLITE_OK, convertResultCode(rc));
-
-  return NS_OK;
-}
-
 } // namespace storage
 } // namespace mozilla
diff --git storage/src/mozStorageService.h storage/src/mozStorageService.h
index 21c1ff8..3f5a546 100644
--- storage/src/mozStorageService.h
+++ storage/src/mozStorageService.h
@@@@ -15,7 +15,6 @@@@
 #include "mozilla/Mutex.h"
 
 #include "mozIStorageService.h"
-#include "mozIStorageServiceQuotaManagement.h"
 
 class nsIMemoryReporter;
 class nsIMemoryMultiReporter;
@@@@ -28,7 +27,6 @@@@ namespace storage {
 class Connection;
 class Service : public mozIStorageService
               , public nsIObserver
-              , public mozIStorageServiceQuotaManagement
 {
 public:
   /**
@@@@ -58,7 +56,6 @@@@ public:
   NS_DECL_ISUPPORTS
   NS_DECL_MOZISTORAGESERVICE
   NS_DECL_NSIOBSERVER
-  NS_DECL_MOZISTORAGESERVICEQUOTAMANAGEMENT
 
   /**
    * Obtains an already AddRefed pointer to XPConnect.  This is used by
diff --git toolkit/toolkit-makefiles.sh toolkit/toolkit-makefiles.sh
index 6a7d714..8f1bbe0 100644
--- toolkit/toolkit-makefiles.sh
+++ toolkit/toolkit-makefiles.sh
@@@@ -68,6 +68,7 @@@@ MAKEFILES_dom="
   dom/plugins/base/Makefile
   dom/plugins/ipc/Makefile
   dom/power/Makefile
+  dom/quota/Makefile
   dom/settings/Makefile
   dom/sms/Makefile
   dom/sms/interfaces/Makefile
@
