Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1391)

Unified Diff: content/browser/indexed_db/indexed_db_factory.cc

Issue 313883003: Split IndexedDBFactory into virtual base + impl. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/indexed_db/indexed_db_factory.cc
diff --git a/content/browser/indexed_db/indexed_db_factory.cc b/content/browser/indexed_db/indexed_db_factory.cc
deleted file mode 100644
index dccec5f58121164cfd2d91ef1474d3dde01115f5..0000000000000000000000000000000000000000
--- a/content/browser/indexed_db/indexed_db_factory.cc
+++ /dev/null
@@ -1,478 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/indexed_db/indexed_db_factory.h"
-
-#include "base/logging.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/time/time.h"
-#include "content/browser/indexed_db/indexed_db_backing_store.h"
-#include "content/browser/indexed_db/indexed_db_context_impl.h"
-#include "content/browser/indexed_db/indexed_db_database_error.h"
-#include "content/browser/indexed_db/indexed_db_tracing.h"
-#include "content/browser/indexed_db/indexed_db_transaction_coordinator.h"
-#include "third_party/WebKit/public/platform/WebIDBDatabaseException.h"
-#include "third_party/leveldatabase/env_chromium.h"
-#include "webkit/common/database/database_identifier.h"
-
-using base::ASCIIToUTF16;
-
-namespace content {
-
-const int64 kBackingStoreGracePeriodMs = 2000;
-
-IndexedDBFactory::IndexedDBFactory(IndexedDBContextImpl* context)
- : context_(context) {}
-
-IndexedDBFactory::~IndexedDBFactory() {}
-
-void IndexedDBFactory::RemoveDatabaseFromMaps(
- const IndexedDBDatabase::Identifier& identifier) {
- IndexedDBDatabaseMap::iterator it = database_map_.find(identifier);
- DCHECK(it != database_map_.end());
- IndexedDBDatabase* database = it->second;
- database_map_.erase(it);
-
- std::pair<OriginDBMap::iterator, OriginDBMap::iterator> range =
- origin_dbs_.equal_range(database->identifier().first);
- DCHECK(range.first != range.second);
- for (OriginDBMap::iterator it2 = range.first; it2 != range.second; ++it2) {
- if (it2->second == database) {
- origin_dbs_.erase(it2);
- break;
- }
- }
-}
-
-void IndexedDBFactory::ReleaseDatabase(
- const IndexedDBDatabase::Identifier& identifier,
- bool forcedClose) {
-
- DCHECK(!database_map_.find(identifier)->second->backing_store());
-
- RemoveDatabaseFromMaps(identifier);
-
- // No grace period on a forced-close, as the initiator is
- // assuming the backing store will be released once all
- // connections are closed.
- ReleaseBackingStore(identifier.first, forcedClose);
-}
-
-void IndexedDBFactory::ReleaseBackingStore(const GURL& origin_url,
- bool immediate) {
- if (immediate) {
- IndexedDBBackingStoreMap::iterator it =
- backing_stores_with_active_blobs_.find(origin_url);
- if (it != backing_stores_with_active_blobs_.end()) {
- it->second->active_blob_registry()->ForceShutdown();
- backing_stores_with_active_blobs_.erase(it);
- }
- }
-
- // Only close if this is the last reference.
- if (!HasLastBackingStoreReference(origin_url))
- return;
-
- // If this factory does hold the last reference to the backing store, it can
- // be closed - but unless requested to close it immediately, keep it around
- // for a short period so that a re-open is fast.
- if (immediate) {
- CloseBackingStore(origin_url);
- return;
- }
-
- // Start a timer to close the backing store, unless something else opens it
- // in the mean time.
- DCHECK(!backing_store_map_[origin_url]->close_timer()->IsRunning());
- backing_store_map_[origin_url]->close_timer()->Start(
- FROM_HERE,
- base::TimeDelta::FromMilliseconds(kBackingStoreGracePeriodMs),
- base::Bind(&IndexedDBFactory::MaybeCloseBackingStore, this, origin_url));
-}
-
-void IndexedDBFactory::MaybeCloseBackingStore(const GURL& origin_url) {
- // Another reference may have opened since the maybe-close was posted, so it
- // is necessary to check again.
- if (HasLastBackingStoreReference(origin_url))
- CloseBackingStore(origin_url);
-}
-
-void IndexedDBFactory::CloseBackingStore(const GURL& origin_url) {
- IndexedDBBackingStoreMap::iterator it = backing_store_map_.find(origin_url);
- DCHECK(it != backing_store_map_.end());
- // Stop the timer (if it's running) - this may happen if the timer was started
- // and then a forced close occurs.
- it->second->close_timer()->Stop();
- backing_store_map_.erase(it);
-}
-
-bool IndexedDBFactory::HasLastBackingStoreReference(const GURL& origin_url)
- const {
- IndexedDBBackingStore* ptr;
- {
- // Scope so that the implicit scoped_refptr<> is freed.
- IndexedDBBackingStoreMap::const_iterator it =
- backing_store_map_.find(origin_url);
- DCHECK(it != backing_store_map_.end());
- ptr = it->second.get();
- }
- return ptr->HasOneRef();
-}
-
-void IndexedDBFactory::ForceClose(const GURL& origin_url) {
- std::pair<OriginDBMapIterator, OriginDBMapIterator> range =
- GetOpenDatabasesForOrigin(origin_url);
-
- while (range.first != range.second) {
- IndexedDBDatabase* db = range.first->second;
- ++range.first;
- db->ForceClose();
- }
-
- if (backing_store_map_.find(origin_url) != backing_store_map_.end())
- ReleaseBackingStore(origin_url, true /* immediate */);
-}
-
-void IndexedDBFactory::ContextDestroyed() {
- // Timers on backing stores hold a reference to this factory. When the
- // context (which nominally owns this factory) is destroyed during thread
- // termination the timers must be stopped so that this factory and the
- // stores can be disposed of.
- for (IndexedDBBackingStoreMap::iterator it = backing_store_map_.begin();
- it != backing_store_map_.end();
- ++it)
- it->second->close_timer()->Stop();
- backing_store_map_.clear();
- backing_stores_with_active_blobs_.clear();
- context_ = NULL;
-}
-
-void IndexedDBFactory::ReportOutstandingBlobs(const GURL& origin_url,
- bool blobs_outstanding) {
- if (!context_)
- return;
- if (blobs_outstanding) {
- DCHECK(!backing_stores_with_active_blobs_.count(origin_url));
- IndexedDBBackingStoreMap::iterator it = backing_store_map_.find(origin_url);
- if (it != backing_store_map_.end())
- backing_stores_with_active_blobs_.insert(*it);
- else
- DCHECK(false);
- } else {
- IndexedDBBackingStoreMap::iterator it =
- backing_stores_with_active_blobs_.find(origin_url);
- if (it != backing_stores_with_active_blobs_.end()) {
- backing_stores_with_active_blobs_.erase(it);
- ReleaseBackingStore(origin_url, false /* immediate */);
- }
- }
-}
-
-void IndexedDBFactory::GetDatabaseNames(
- scoped_refptr<IndexedDBCallbacks> callbacks,
- const GURL& origin_url,
- const base::FilePath& data_directory,
- net::URLRequestContext* request_context) {
- IDB_TRACE("IndexedDBFactory::GetDatabaseNames");
- // TODO(dgrogan): Plumb data_loss back to script eventually?
- blink::WebIDBDataLoss data_loss;
- std::string data_loss_message;
- bool disk_full;
- scoped_refptr<IndexedDBBackingStore> backing_store =
- OpenBackingStore(origin_url,
- data_directory,
- request_context,
- &data_loss,
- &data_loss_message,
- &disk_full);
- if (!backing_store) {
- callbacks->OnError(
- IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
- "Internal error opening backing store for "
- "indexedDB.webkitGetDatabaseNames."));
- return;
- }
-
- leveldb::Status s;
- std::vector<base::string16> names = backing_store->GetDatabaseNames(&s);
- if (!s.ok()) {
- // TODO(cmumford): Handle this error
- DLOG(ERROR) << "Internal error getting database names";
- }
- callbacks->OnSuccess(names);
- backing_store = NULL;
- ReleaseBackingStore(origin_url, false /* immediate */);
-}
-
-void IndexedDBFactory::DeleteDatabase(
- const base::string16& name,
- net::URLRequestContext* request_context,
- scoped_refptr<IndexedDBCallbacks> callbacks,
- const GURL& origin_url,
- const base::FilePath& data_directory) {
- IDB_TRACE("IndexedDBFactory::DeleteDatabase");
- IndexedDBDatabase::Identifier unique_identifier(origin_url, name);
- IndexedDBDatabaseMap::iterator it = database_map_.find(unique_identifier);
- if (it != database_map_.end()) {
- // If there are any connections to the database, directly delete the
- // database.
- it->second->DeleteDatabase(callbacks);
- return;
- }
-
- // TODO(dgrogan): Plumb data_loss back to script eventually?
- blink::WebIDBDataLoss data_loss;
- std::string data_loss_message;
- bool disk_full = false;
- scoped_refptr<IndexedDBBackingStore> backing_store =
- OpenBackingStore(origin_url,
- data_directory,
- request_context,
- &data_loss,
- &data_loss_message,
- &disk_full);
- if (!backing_store) {
- callbacks->OnError(
- IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
- ASCIIToUTF16(
- "Internal error opening backing store "
- "for indexedDB.deleteDatabase.")));
- return;
- }
-
- leveldb::Status s;
- scoped_refptr<IndexedDBDatabase> database = IndexedDBDatabase::Create(
- name, backing_store, this, unique_identifier, &s);
- if (!database) {
- IndexedDBDatabaseError error(
- blink::WebIDBDatabaseExceptionUnknownError,
- ASCIIToUTF16(
- "Internal error creating database backend for "
- "indexedDB.deleteDatabase."));
- callbacks->OnError(error);
- if (leveldb_env::IsCorruption(s))
- HandleBackingStoreCorruption(origin_url, error);
- return;
- }
-
- database_map_[unique_identifier] = database;
- origin_dbs_.insert(std::make_pair(origin_url, database));
- database->DeleteDatabase(callbacks);
- RemoveDatabaseFromMaps(unique_identifier);
- database = NULL;
- backing_store = NULL;
- ReleaseBackingStore(origin_url, false /* immediate */);
-}
-
-void IndexedDBFactory::DatabaseDeleted(
- const IndexedDBDatabase::Identifier& identifier) {
- // NULL after ContextDestroyed() called, and in some unit tests.
- if (!context_)
- return;
- context_->DatabaseDeleted(identifier.first);
-}
-
-void IndexedDBFactory::HandleBackingStoreFailure(const GURL& origin_url) {
- // NULL after ContextDestroyed() called, and in some unit tests.
- if (!context_)
- return;
- context_->ForceClose(origin_url,
- IndexedDBContextImpl::FORCE_CLOSE_BACKING_STORE_FAILURE);
-}
-
-void IndexedDBFactory::HandleBackingStoreCorruption(
- const GURL& origin_url,
- const IndexedDBDatabaseError& error) {
- // Make a copy of origin_url as this is likely a reference to a member of a
- // backing store which this function will be deleting.
- GURL saved_origin_url(origin_url);
- DCHECK(context_);
- base::FilePath path_base = context_->data_path();
- IndexedDBBackingStore::RecordCorruptionInfo(
- path_base, saved_origin_url, base::UTF16ToUTF8(error.message()));
- HandleBackingStoreFailure(saved_origin_url);
- // Note: DestroyBackingStore only deletes LevelDB files, leaving all others,
- // so our corruption info file will remain.
- leveldb::Status s =
- IndexedDBBackingStore::DestroyBackingStore(path_base, saved_origin_url);
- if (!s.ok())
- DLOG(ERROR) << "Unable to delete backing store: " << s.ToString();
-}
-
-bool IndexedDBFactory::IsDatabaseOpen(const GURL& origin_url,
- const base::string16& name) const {
-
- return !!database_map_.count(IndexedDBDatabase::Identifier(origin_url, name));
-}
-
-bool IndexedDBFactory::IsBackingStoreOpen(const GURL& origin_url) const {
- return backing_store_map_.find(origin_url) != backing_store_map_.end();
-}
-
-bool IndexedDBFactory::IsBackingStorePendingClose(const GURL& origin_url)
- const {
- IndexedDBBackingStoreMap::const_iterator it =
- backing_store_map_.find(origin_url);
- if (it == backing_store_map_.end())
- return false;
- return it->second->close_timer()->IsRunning();
-}
-
-scoped_refptr<IndexedDBBackingStore> IndexedDBFactory::OpenBackingStoreHelper(
- const GURL& origin_url,
- const base::FilePath& data_directory,
- net::URLRequestContext* request_context,
- blink::WebIDBDataLoss* data_loss,
- std::string* data_loss_message,
- bool* disk_full,
- bool first_time) {
- return IndexedDBBackingStore::Open(this,
- origin_url,
- data_directory,
- request_context,
- data_loss,
- data_loss_message,
- disk_full,
- context_->TaskRunner(),
- first_time);
-}
-
-scoped_refptr<IndexedDBBackingStore> IndexedDBFactory::OpenBackingStore(
- const GURL& origin_url,
- const base::FilePath& data_directory,
- net::URLRequestContext* request_context,
- blink::WebIDBDataLoss* data_loss,
- std::string* data_loss_message,
- bool* disk_full) {
- const bool open_in_memory = data_directory.empty();
-
- IndexedDBBackingStoreMap::iterator it2 = backing_store_map_.find(origin_url);
- if (it2 != backing_store_map_.end()) {
- it2->second->close_timer()->Stop();
- return it2->second;
- }
-
- scoped_refptr<IndexedDBBackingStore> backing_store;
- bool first_time = false;
- if (open_in_memory) {
- backing_store =
- IndexedDBBackingStore::OpenInMemory(origin_url, context_->TaskRunner());
- } else {
- first_time = !backends_opened_since_boot_.count(origin_url);
-
- backing_store = OpenBackingStoreHelper(origin_url,
- data_directory,
- request_context,
- data_loss,
- data_loss_message,
- disk_full,
- first_time);
- }
-
- if (backing_store.get()) {
- if (first_time)
- backends_opened_since_boot_.insert(origin_url);
- backing_store_map_[origin_url] = backing_store;
- // If an in-memory database, bind lifetime to this factory instance.
- if (open_in_memory)
- session_only_backing_stores_.insert(backing_store);
-
- // All backing stores associated with this factory should be of the same
- // type.
- DCHECK_NE(session_only_backing_stores_.empty(), open_in_memory);
-
- return backing_store;
- }
-
- return 0;
-}
-
-void IndexedDBFactory::Open(const base::string16& name,
- const IndexedDBPendingConnection& connection,
- net::URLRequestContext* request_context,
- const GURL& origin_url,
- const base::FilePath& data_directory) {
- IDB_TRACE("IndexedDBFactory::Open");
- scoped_refptr<IndexedDBDatabase> database;
- IndexedDBDatabase::Identifier unique_identifier(origin_url, name);
- IndexedDBDatabaseMap::iterator it = database_map_.find(unique_identifier);
- blink::WebIDBDataLoss data_loss =
- blink::WebIDBDataLossNone;
- std::string data_loss_message;
- bool disk_full = false;
- bool was_open = (it != database_map_.end());
- if (!was_open) {
- scoped_refptr<IndexedDBBackingStore> backing_store =
- OpenBackingStore(origin_url,
- data_directory,
- request_context,
- &data_loss,
- &data_loss_message,
- &disk_full);
- if (!backing_store) {
- if (disk_full) {
- connection.callbacks->OnError(
- IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionQuotaError,
- ASCIIToUTF16(
- "Encountered full disk while opening "
- "backing store for indexedDB.open.")));
- return;
- }
- connection.callbacks->OnError(IndexedDBDatabaseError(
- blink::WebIDBDatabaseExceptionUnknownError,
- ASCIIToUTF16(
- "Internal error opening backing store for indexedDB.open.")));
- return;
- }
-
- leveldb::Status s;
- database = IndexedDBDatabase::Create(
- name, backing_store, this, unique_identifier, &s);
- if (!database) {
- DLOG(ERROR) << "Unable to create the database";
- IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
- ASCIIToUTF16(
- "Internal error creating "
- "database backend for "
- "indexedDB.open."));
- connection.callbacks->OnError(error);
- if (leveldb_env::IsCorruption(s)) {
- backing_store = NULL; // Closes the LevelDB so that it can be deleted
- HandleBackingStoreCorruption(origin_url, error);
- }
- return;
- }
- } else {
- database = it->second;
- }
-
- if (data_loss != blink::WebIDBDataLossNone)
- connection.callbacks->OnDataLoss(data_loss, data_loss_message);
-
- database->OpenConnection(connection);
-
- if (!was_open && database->ConnectionCount() > 0) {
- database_map_[unique_identifier] = database;
- origin_dbs_.insert(std::make_pair(origin_url, database));
- }
-}
-
-std::pair<IndexedDBFactory::OriginDBMapIterator,
- IndexedDBFactory::OriginDBMapIterator>
-IndexedDBFactory::GetOpenDatabasesForOrigin(const GURL& origin_url) const {
- return origin_dbs_.equal_range(origin_url);
-}
-
-size_t IndexedDBFactory::GetConnectionCount(const GURL& origin_url) const {
- size_t count(0);
-
- std::pair<OriginDBMapIterator, OriginDBMapIterator> range =
- GetOpenDatabasesForOrigin(origin_url);
- for (OriginDBMapIterator it = range.first; it != range.second; ++it)
- count += it->second->ConnectionCount();
-
- return count;
-}
-
-} // namespace content

Powered by Google App Engine
This is Rietveld 408576698