dom/indexedDB/Client.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim: set ts=2 et sw=2 tw=80: */
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     5  * You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #include "Client.h"
     9 #include "mozilla/dom/quota/QuotaManager.h"
    10 #include "mozilla/dom/quota/UsageInfo.h"
    11 #include "mozilla/dom/quota/Utilities.h"
    13 #include "IDBDatabase.h"
    14 #include "IndexedDatabaseManager.h"
    15 #include "TransactionThreadPool.h"
    16 #include "nsISimpleEnumerator.h"
    18 USING_INDEXEDDB_NAMESPACE
    19 using mozilla::dom::quota::AssertIsOnIOThread;
    20 using mozilla::dom::quota::QuotaManager;
    22 namespace {
    24 bool
    25 GetDatabaseBaseFilename(const nsAString& aFilename,
    26                         nsAString& aDatabaseBaseFilename)
    27 {
    28   NS_ASSERTION(!aFilename.IsEmpty(), "Bad argument!");
    30   NS_NAMED_LITERAL_STRING(sqlite, ".sqlite");
    32   if (!StringEndsWith(aFilename, sqlite)) {
    33     return false;
    34   }
    36   aDatabaseBaseFilename =
    37     Substring(aFilename, 0, aFilename.Length() - sqlite.Length());
    39   return true;
    40 }
    42 } // anonymous namespace
    44 // This needs to be fully qualified to not confuse trace refcnt assertions.
    45 NS_IMPL_ADDREF(mozilla::dom::indexedDB::Client)
    46 NS_IMPL_RELEASE(mozilla::dom::indexedDB::Client)
    48 nsresult
    49 Client::InitOrigin(PersistenceType aPersistenceType, const nsACString& aGroup,
    50                    const nsACString& aOrigin, UsageInfo* aUsageInfo)
    51 {
    52   AssertIsOnIOThread();
    54   nsCOMPtr<nsIFile> directory;
    55   nsresult rv =
    56     GetDirectory(aPersistenceType, aOrigin, getter_AddRefs(directory));
    57   NS_ENSURE_SUCCESS(rv, rv);
    59   // We need to see if there are any files in the directory already. If they
    60   // are database files then we need to cleanup stored files (if it's needed)
    61   // and also get the usage.
    63   nsAutoTArray<nsString, 20> subdirsToProcess;
    64   nsAutoTArray<nsCOMPtr<nsIFile> , 20> unknownFiles;
    65   nsTHashtable<nsStringHashKey> validSubdirs(20);
    67   nsCOMPtr<nsISimpleEnumerator> entries;
    68   rv = directory->GetDirectoryEntries(getter_AddRefs(entries));
    69   NS_ENSURE_SUCCESS(rv, rv);
    71   bool hasMore;
    72   while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) &&
    73          hasMore && (!aUsageInfo || !aUsageInfo->Canceled())) {
    74     nsCOMPtr<nsISupports> entry;
    75     rv = entries->GetNext(getter_AddRefs(entry));
    76     NS_ENSURE_SUCCESS(rv, rv);
    78     nsCOMPtr<nsIFile> file = do_QueryInterface(entry);
    79     NS_ENSURE_TRUE(file, NS_NOINTERFACE);
    81     nsString leafName;
    82     rv = file->GetLeafName(leafName);
    83     NS_ENSURE_SUCCESS(rv, rv);
    85     if (StringEndsWith(leafName, NS_LITERAL_STRING(".sqlite-journal"))) {
    86       continue;
    87     }
    89     if (leafName.EqualsLiteral(DSSTORE_FILE_NAME)) {
    90       continue;
    91     }
    93     bool isDirectory;
    94     rv = file->IsDirectory(&isDirectory);
    95     NS_ENSURE_SUCCESS(rv, rv);
    97     if (isDirectory) {
    98       if (!validSubdirs.GetEntry(leafName)) {
    99         subdirsToProcess.AppendElement(leafName);
   100       }
   101       continue;
   102     }
   104     nsString dbBaseFilename;
   105     if (!GetDatabaseBaseFilename(leafName, dbBaseFilename)) {
   106       unknownFiles.AppendElement(file);
   107       continue;
   108     }
   110     nsCOMPtr<nsIFile> fmDirectory;
   111     rv = directory->Clone(getter_AddRefs(fmDirectory));
   112     NS_ENSURE_SUCCESS(rv, rv);
   114     rv = fmDirectory->Append(dbBaseFilename);
   115     NS_ENSURE_SUCCESS(rv, rv);
   117     rv = FileManager::InitDirectory(fmDirectory, file, aPersistenceType, aGroup,
   118                                     aOrigin);
   119     NS_ENSURE_SUCCESS(rv, rv);
   121     if (aUsageInfo) {
   122       int64_t fileSize;
   123       rv = file->GetFileSize(&fileSize);
   124       NS_ENSURE_SUCCESS(rv, rv);
   126       NS_ASSERTION(fileSize >= 0, "Negative size?!");
   128       aUsageInfo->AppendToDatabaseUsage(uint64_t(fileSize));
   130       uint64_t usage;
   131       rv = FileManager::GetUsage(fmDirectory, &usage);
   132       NS_ENSURE_SUCCESS(rv, rv);
   134       aUsageInfo->AppendToFileUsage(usage);
   135     }
   137     validSubdirs.PutEntry(dbBaseFilename);
   138   }
   139   NS_ENSURE_SUCCESS(rv, rv);
   141   for (uint32_t i = 0; i < subdirsToProcess.Length(); i++) {
   142     const nsString& subdir = subdirsToProcess[i];
   143     if (!validSubdirs.GetEntry(subdir)) {
   144       NS_WARNING("Unknown subdirectory found!");
   145       return NS_ERROR_UNEXPECTED;
   146     }
   147   }
   149   for (uint32_t i = 0; i < unknownFiles.Length(); i++) {
   150     nsCOMPtr<nsIFile>& unknownFile = unknownFiles[i];
   152     // Some temporary SQLite files could disappear, so we have to check if the
   153     // unknown file still exists.
   154     bool exists;
   155     rv = unknownFile->Exists(&exists);
   156     NS_ENSURE_SUCCESS(rv, rv);
   158     if (exists) {
   159       nsString leafName;
   160       unknownFile->GetLeafName(leafName);
   162       // The journal file may exists even after db has been correctly opened.
   163       if (!StringEndsWith(leafName, NS_LITERAL_STRING(".sqlite-journal"))) {
   164         NS_WARNING("Unknown file found!");
   165         return NS_ERROR_UNEXPECTED;
   166       }
   167     }
   168   }
   170   return NS_OK;
   171 }
   173 nsresult
   174 Client::GetUsageForOrigin(PersistenceType aPersistenceType,
   175                           const nsACString& aGroup, const nsACString& aOrigin,
   176                           UsageInfo* aUsageInfo)
   177 {
   178   AssertIsOnIOThread();
   179   NS_ASSERTION(aUsageInfo, "Null pointer!");
   181   nsCOMPtr<nsIFile> directory;
   182   nsresult rv =
   183     GetDirectory(aPersistenceType, aOrigin, getter_AddRefs(directory));
   184   NS_ENSURE_SUCCESS(rv, rv);
   186   rv = GetUsageForDirectoryInternal(directory, aUsageInfo, true);
   187   NS_ENSURE_SUCCESS(rv, rv);
   189   return NS_OK;
   190 }
   192 void
   193 Client::OnOriginClearCompleted(PersistenceType aPersistenceType,
   194                                const OriginOrPatternString& aOriginOrPattern)
   195 {
   196   AssertIsOnIOThread();
   198   IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
   199   if (mgr) {
   200     mgr->InvalidateFileManagers(aPersistenceType, aOriginOrPattern);
   201   }
   202 }
   204 void
   205 Client::ReleaseIOThreadObjects()
   206 {
   207   AssertIsOnIOThread();
   209   IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
   210   if (mgr) {
   211     mgr->InvalidateAllFileManagers();
   212   }
   213 }
   215 bool
   216 Client::IsTransactionServiceActivated()
   217 {
   218   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   220   return !!TransactionThreadPool::Get();
   221 }
   223 void
   224 Client::WaitForStoragesToComplete(nsTArray<nsIOfflineStorage*>& aStorages,
   225                                   nsIRunnable* aCallback)
   226 {
   227   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   228   NS_ASSERTION(!aStorages.IsEmpty(), "No storages to wait on!");
   229   NS_ASSERTION(aCallback, "Passed null callback!");
   231   TransactionThreadPool* pool = TransactionThreadPool::Get();
   232   NS_ASSERTION(pool, "Should have checked if transaction service is active!");
   234   nsTArray<nsRefPtr<IDBDatabase> > databases(aStorages.Length());
   235   for (uint32_t index = 0; index < aStorages.Length(); index++) {
   236     IDBDatabase* database = IDBDatabase::FromStorage(aStorages[index]);
   237     if (!database) {
   238       MOZ_CRASH();
   239     }
   241     databases.AppendElement(database);
   242   }
   244   pool->WaitForDatabasesToComplete(databases, aCallback);
   245 }
   247 void
   248 Client::AbortTransactionsForStorage(nsIOfflineStorage* aStorage)
   249 {
   250   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   251   NS_ASSERTION(aStorage, "Passed null storage!");
   253   TransactionThreadPool* pool = TransactionThreadPool::Get();
   254   NS_ASSERTION(pool, "Should have checked if transaction service is active!");
   256   IDBDatabase* database = IDBDatabase::FromStorage(aStorage);
   257   NS_ASSERTION(database, "This shouldn't be null!");
   259   pool->AbortTransactionsForDatabase(database);
   260 }
   262 bool
   263 Client::HasTransactionsForStorage(nsIOfflineStorage* aStorage)
   264 {
   265   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   267   TransactionThreadPool* pool = TransactionThreadPool::Get();
   268   NS_ASSERTION(pool, "Should have checked if transaction service is active!");
   270   IDBDatabase* database = IDBDatabase::FromStorage(aStorage);
   271   NS_ASSERTION(database, "This shouldn't be null!");
   273   return pool->HasTransactionsForDatabase(database);
   274 }
   276 void
   277 Client::ShutdownTransactionService()
   278 {
   279   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   281   TransactionThreadPool::Shutdown();
   282 }
   284 nsresult
   285 Client::GetDirectory(PersistenceType aPersistenceType,
   286                      const nsACString& aOrigin, nsIFile** aDirectory)
   287 {
   288   QuotaManager* quotaManager = QuotaManager::Get();
   289   NS_ASSERTION(quotaManager, "This should never fail!");
   291   nsCOMPtr<nsIFile> directory;
   292   nsresult rv = quotaManager->GetDirectoryForOrigin(aPersistenceType, aOrigin,
   293                                                     getter_AddRefs(directory));
   294   NS_ENSURE_SUCCESS(rv, rv);
   296   NS_ASSERTION(directory, "What?");
   298   rv = directory->Append(NS_LITERAL_STRING(IDB_DIRECTORY_NAME));
   299   NS_ENSURE_SUCCESS(rv, rv);
   301   directory.forget(aDirectory);
   302   return NS_OK;
   303 }
   305 nsresult
   306 Client::GetUsageForDirectoryInternal(nsIFile* aDirectory,
   307                                      UsageInfo* aUsageInfo,
   308                                      bool aDatabaseFiles)
   309 {
   310   NS_ASSERTION(aDirectory, "Null pointer!");
   311   NS_ASSERTION(aUsageInfo, "Null pointer!");
   313   nsCOMPtr<nsISimpleEnumerator> entries;
   314   nsresult rv = aDirectory->GetDirectoryEntries(getter_AddRefs(entries));
   315   NS_ENSURE_SUCCESS(rv, rv);
   317   if (!entries) {
   318     return NS_OK;
   319   }
   321   bool hasMore;
   322   while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) &&
   323          hasMore && !aUsageInfo->Canceled()) {
   324     nsCOMPtr<nsISupports> entry;
   325     rv = entries->GetNext(getter_AddRefs(entry));
   326     NS_ENSURE_SUCCESS(rv, rv);
   328     nsCOMPtr<nsIFile> file(do_QueryInterface(entry));
   329     NS_ASSERTION(file, "Don't know what this is!");
   331     bool isDirectory;
   332     rv = file->IsDirectory(&isDirectory);
   333     NS_ENSURE_SUCCESS(rv, rv);
   335     if (isDirectory) {
   336       if (aDatabaseFiles) {
   337         rv = GetUsageForDirectoryInternal(file, aUsageInfo, false);
   338         NS_ENSURE_SUCCESS(rv, rv);
   339       }
   340       else {
   341         nsString leafName;
   342         rv = file->GetLeafName(leafName);
   343         NS_ENSURE_SUCCESS(rv, rv);
   345         if (!leafName.EqualsLiteral(JOURNAL_DIRECTORY_NAME)) {
   346           NS_WARNING("Unknown directory found!");
   347         }
   348       }
   350       continue;
   351     }
   353     int64_t fileSize;
   354     rv = file->GetFileSize(&fileSize);
   355     NS_ENSURE_SUCCESS(rv, rv);
   357     NS_ASSERTION(fileSize >= 0, "Negative size?!");
   359     if (aDatabaseFiles) {
   360       aUsageInfo->AppendToDatabaseUsage(uint64_t(fileSize));
   361     }
   362     else {
   363       aUsageInfo->AppendToFileUsage(uint64_t(fileSize));
   364     }
   365   }
   366   NS_ENSURE_SUCCESS(rv, rv);
   368   return NS_OK;
   369 }

mercurial