diff options
author | jsbell@chromium.org <jsbell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-22 17:57:43 +0000 |
---|---|---|
committer | jsbell@chromium.org <jsbell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-22 17:57:43 +0000 |
commit | 8df07d2a28b8de7a857a9e1ad8df36a6026939a8 (patch) | |
tree | f4ad471887d63c5f1d7049b44da9a8807878af1a /content | |
parent | 9550261f14a4d23cbaf01fbb2a38b6fdcf1fbe82 (diff) | |
download | chromium_src-8df07d2a28b8de7a857a9e1ad8df36a6026939a8.zip chromium_src-8df07d2a28b8de7a857a9e1ad8df36a6026939a8.tar.gz chromium_src-8df07d2a28b8de7a857a9e1ad8df36a6026939a8.tar.bz2 |
Add connection/transaction diagnostics to chrome://indexeddb-internals
R=alecflett@chromium.org
BUG=261651
Review URL: https://chromiumcodereview.appspot.com/19637007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@212912 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
14 files changed, 326 insertions, 74 deletions
diff --git a/content/browser/indexed_db/indexed_db_context_impl.cc b/content/browser/indexed_db/indexed_db_context_impl.cc index 2c3b21f..38decc2 100644 --- a/content/browser/indexed_db/indexed_db_context_impl.cc +++ b/content/browser/indexed_db/indexed_db_context_impl.cc @@ -4,6 +4,8 @@ #include "content/browser/indexed_db/indexed_db_context_impl.h" +#include <algorithm> + #include "base/bind.h" #include "base/command_line.h" #include "base/file_util.h" @@ -13,18 +15,24 @@ #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/threading/thread_restrictions.h" +#include "base/values.h" #include "content/browser/browser_main_loop.h" #include "content/browser/indexed_db/indexed_db_connection.h" +#include "content/browser/indexed_db/indexed_db_database.h" #include "content/browser/indexed_db/indexed_db_factory.h" #include "content/browser/indexed_db/indexed_db_quota_client.h" +#include "content/browser/indexed_db/indexed_db_transaction.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/indexed_db_info.h" #include "content/public/common/content_switches.h" +#include "ui/base/text/bytes_formatting.h" #include "webkit/browser/database/database_util.h" #include "webkit/browser/quota/quota_manager.h" #include "webkit/browser/quota/special_storage_policy.h" #include "webkit/common/database/database_identifier.h" +using base::DictionaryValue; +using base::ListValue; using webkit_database::DatabaseUtil; namespace content { @@ -105,13 +113,13 @@ IndexedDBContextImpl::IndexedDBContextImpl( IndexedDBFactory* IndexedDBContextImpl::GetIDBFactory() { DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); - if (!idb_factory_) { + if (!factory_) { // Prime our cache of origins with existing databases so we can // detect when dbs are newly created. GetOriginSet(); - idb_factory_ = new IndexedDBFactory(); + factory_ = new IndexedDBFactory(); } - return idb_factory_; + return factory_; } std::vector<GURL> IndexedDBContextImpl::GetAllOrigins() { @@ -146,6 +154,98 @@ std::vector<IndexedDBInfo> IndexedDBContextImpl::GetAllOriginsInfo() { return result; } +static bool HostNameComparator(const GURL& i, const GURL& j) { + return i.host() < j.host(); +} + +ListValue* IndexedDBContextImpl::GetAllOriginsDetails() { + DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); + std::vector<GURL> origins = GetAllOrigins(); + + std::sort(origins.begin(), origins.end(), HostNameComparator); + + scoped_ptr<ListValue> list(new ListValue()); + for (std::vector<GURL>::const_iterator iter = origins.begin(); + iter != origins.end(); + ++iter) { + const GURL& origin_url = *iter; + + scoped_ptr<DictionaryValue> info(new DictionaryValue()); + info->SetString("url", origin_url.spec()); + info->SetString("size", ui::FormatBytes(GetOriginDiskUsage(origin_url))); + info->SetDouble("last_modified", + GetOriginLastModified(origin_url).ToJsTime()); + info->SetString("path", GetFilePath(origin_url).value()); + info->SetDouble("connection_count", GetConnectionCount(origin_url)); + + // This ends up being O(n^2) since we iterate over all open databases + // to extract just those in the origin, and we're iterating over all + // origins in the outer loop. + + if (factory_) { + std::vector<IndexedDBDatabase*> databases = + factory_->GetOpenDatabasesForOrigin( + webkit_database::GetIdentifierFromOrigin(origin_url)); + // TODO(jsbell): Sort by name? + scoped_ptr<ListValue> database_list(new ListValue()); + + for (std::vector<IndexedDBDatabase*>::iterator it = databases.begin(); + it != databases.end(); + ++it) { + + const IndexedDBDatabase* db = *it; + scoped_ptr<DictionaryValue> db_info(new DictionaryValue()); + + db_info->SetString("name", db->name()); + db_info->SetDouble("pending_opens", db->PendingOpenCount()); + db_info->SetDouble("pending_upgrades", db->PendingUpgradeCount()); + db_info->SetDouble("running_upgrades", db->RunningUpgradeCount()); + db_info->SetDouble("pending_deletes", db->PendingDeleteCount()); + db_info->SetDouble("connection_count", + db->ConnectionCount() - db->PendingUpgradeCount() - + db->RunningUpgradeCount()); + + scoped_ptr<ListValue> transaction_list(new ListValue()); + std::vector<const IndexedDBTransaction*> transactions = + db->transaction_coordinator().GetTransactions(); + for (std::vector<const IndexedDBTransaction*>::iterator trans_it = + transactions.begin(); + trans_it != transactions.end(); + ++trans_it) { + + const IndexedDBTransaction* transaction = *trans_it; + scoped_ptr<DictionaryValue> transaction_info(new DictionaryValue()); + + const char* kModes[] = { "readonly", "readwrite", "versionchange" }; + transaction_info->SetString("mode", kModes[transaction->mode()]); + transaction_info->SetBoolean("running", transaction->IsRunning()); + + scoped_ptr<ListValue> scope(new ListValue()); + for (std::set<int64>::const_iterator scope_it = + transaction->scope().begin(); + scope_it != transaction->scope().end(); + ++scope_it) { + IndexedDBDatabaseMetadata::ObjectStoreMap::const_iterator it = + db->metadata().object_stores.find(*scope_it); + if (it != db->metadata().object_stores.end()) + scope->AppendString(it->second.name); + } + + transaction_info->Set("scope", scope.release()); + transaction_list->Append(transaction_info.release()); + } + db_info->Set("transactions", transaction_list.release()); + + database_list->Append(db_info.release()); + } + info->Set("databases", database_list.release()); + } + + list->Append(info.release()); + } + return list.release(); +} + int64 IndexedDBContextImpl::GetOriginDiskUsage(const GURL& origin_url) { DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); if (data_path_.empty() || !IsInOriginSet(origin_url)) @@ -297,10 +397,10 @@ quota::QuotaManagerProxy* IndexedDBContextImpl::quota_manager_proxy() { } IndexedDBContextImpl::~IndexedDBContextImpl() { - if (idb_factory_) { - IndexedDBFactory* factory = idb_factory_; + if (factory_) { + IndexedDBFactory* factory = factory_; factory->AddRef(); - idb_factory_ = NULL; + factory_ = NULL; if (!task_runner_->ReleaseSoon(FROM_HERE, factory)) { factory->Release(); } diff --git a/content/browser/indexed_db/indexed_db_context_impl.h b/content/browser/indexed_db/indexed_db_context_impl.h index 4b23982..3c76465 100644 --- a/content/browser/indexed_db/indexed_db_context_impl.h +++ b/content/browser/indexed_db/indexed_db_context_impl.h @@ -22,6 +22,7 @@ class GURL; namespace base { +class ListValue; class FilePath; class SequencedTaskRunner; } @@ -73,6 +74,7 @@ class CONTENT_EXPORT IndexedDBContextImpl quota::QuotaManagerProxy* quota_manager_proxy(); + base::ListValue* GetAllOriginsDetails(); void ForceClose(const GURL& origin_url); base::FilePath GetFilePath(const GURL& origin_url); base::FilePath data_path() const { return data_path_; } @@ -122,7 +124,7 @@ class CONTENT_EXPORT IndexedDBContextImpl // Only for testing. void ResetCaches(); - scoped_refptr<IndexedDBFactory> idb_factory_; + scoped_refptr<IndexedDBFactory> factory_; base::FilePath data_path_; // If true, nothing (not even session-only data) should be deleted on exit. bool force_keep_session_state_; diff --git a/content/browser/indexed_db/indexed_db_database.cc b/content/browser/indexed_db/indexed_db_database.cc index 73d2b88..9eb5774 100644 --- a/content/browser/indexed_db/indexed_db_database.cc +++ b/content/browser/indexed_db/indexed_db_database.cc @@ -457,7 +457,7 @@ scoped_refptr<IndexedDBDatabase> IndexedDBDatabase::Create( const string16& name, IndexedDBBackingStore* database, IndexedDBFactory* factory, - const string16& unique_identifier) { + const Identifier& unique_identifier) { scoped_refptr<IndexedDBDatabase> backend = new IndexedDBDatabase(name, database, factory, unique_identifier); if (!backend->OpenInternal()) @@ -474,10 +474,11 @@ bool Contains(const T& container, const U& item) { } } -IndexedDBDatabase::IndexedDBDatabase(const string16& name, - IndexedDBBackingStore* backing_store, - IndexedDBFactory* factory, - const string16& unique_identifier) +IndexedDBDatabase::IndexedDBDatabase( + const string16& name, + IndexedDBBackingStore* backing_store, + IndexedDBFactory* factory, + const Identifier& unique_identifier) : backing_store_(backing_store), metadata_(name, kInvalidId, @@ -1558,6 +1559,22 @@ size_t IndexedDBDatabase::ConnectionCount() const { return connections_.size(); } +size_t IndexedDBDatabase::PendingOpenCount() const { + return pending_open_calls_.size(); +} + +size_t IndexedDBDatabase::PendingUpgradeCount() const { + return pending_run_version_change_transaction_call_ ? 1 : 0; +} + +size_t IndexedDBDatabase::RunningUpgradeCount() const { + return pending_second_half_open_ ? 1 : 0; +} + +size_t IndexedDBDatabase::PendingDeleteCount() const { + return pending_delete_calls_.size(); +} + void IndexedDBDatabase::ProcessPendingCalls() { if (pending_run_version_change_transaction_call_ && ConnectionCount() == 1) { DCHECK(pending_run_version_change_transaction_call_->Version() > diff --git a/content/browser/indexed_db/indexed_db_database.h b/content/browser/indexed_db/indexed_db_database.h index a239669..9c617f5 100644 --- a/content/browser/indexed_db/indexed_db_database.h +++ b/content/browser/indexed_db/indexed_db_database.h @@ -44,6 +44,8 @@ class CONTENT_EXPORT IndexedDBDatabase }; typedef std::vector<IndexedDBKey> IndexKeys; + // Identifier is pair of (origin identifier, database name). + typedef std::pair<std::string, base::string16> Identifier; static const int64 kInvalidId = 0; static const int64 kMinimumIndexId = 30; @@ -52,10 +54,12 @@ class CONTENT_EXPORT IndexedDBDatabase const string16& name, IndexedDBBackingStore* database, IndexedDBFactory* factory, - const string16& unique_identifier); + const Identifier& unique_identifier); scoped_refptr<IndexedDBBackingStore> BackingStore() const; int64 id() const { return metadata_.id; } + const base::string16& name() const { return metadata_.name; } + void AddObjectStore(const IndexedDBObjectStoreMetadata& metadata, int64 new_max_object_store_id); void RemoveObjectStore(int64 object_store_id); @@ -106,6 +110,9 @@ class CONTENT_EXPORT IndexedDBDatabase IndexedDBTransactionCoordinator& transaction_coordinator() { return transaction_coordinator_; } + const IndexedDBTransactionCoordinator& transaction_coordinator() const { + return transaction_coordinator_; + } void TransactionStarted(IndexedDBTransaction* transaction); void TransactionFinished(IndexedDBTransaction* transaction); @@ -155,13 +162,25 @@ class CONTENT_EXPORT IndexedDBDatabase int64 object_store_id, scoped_refptr<IndexedDBCallbacks> callbacks); + // Number of connections that have progressed passed initial open call. + size_t ConnectionCount() const; + // Number of open calls that are blocked on other connections. + size_t PendingOpenCount() const; + // Number of pending upgrades (0 or 1). Also included in ConnectionCount(). + size_t PendingUpgradeCount() const; + // Number of running upgrades (0 or 1). Also included in ConnectionCount(). + size_t RunningUpgradeCount() const; + // Number of pending deletes, blocked on other connections. + size_t PendingDeleteCount() const; + private: friend class base::RefCounted<IndexedDBDatabase>; - IndexedDBDatabase(const string16& name, - IndexedDBBackingStore* database, - IndexedDBFactory* factory, - const string16& unique_identifier); + IndexedDBDatabase( + const string16& name, + IndexedDBBackingStore* database, + IndexedDBFactory* factory, + const Identifier& unique_identifier); ~IndexedDBDatabase(); bool IsOpenConnectionBlocked() const; @@ -182,7 +201,6 @@ class CONTENT_EXPORT IndexedDBDatabase int64 transaction_id, int64 requested_version, WebKit::WebIDBCallbacks::DataLoss data_loss); - size_t ConnectionCount() const; void ProcessPendingCalls(); bool IsDeleteDatabaseBlocked() const; @@ -207,7 +225,7 @@ class CONTENT_EXPORT IndexedDBDatabase scoped_refptr<IndexedDBBackingStore> backing_store_; IndexedDBDatabaseMetadata metadata_; - string16 identifier_; + const Identifier identifier_; // This might not need to be a scoped_refptr since the factory's lifetime is // that of the page group, but it's better to be conservitive than sorry. scoped_refptr<IndexedDBFactory> factory_; diff --git a/content/browser/indexed_db/indexed_db_database_unittest.cc b/content/browser/indexed_db/indexed_db_database_unittest.cc index c1d1a349..fad9910 100644 --- a/content/browser/indexed_db/indexed_db_database_unittest.cc +++ b/content/browser/indexed_db/indexed_db_database_unittest.cc @@ -29,7 +29,10 @@ TEST(IndexedDBDatabaseTest, BackingStoreRetention) { IndexedDBFactory* factory = 0; scoped_refptr<IndexedDBDatabase> db = IndexedDBDatabase::Create( - ASCIIToUTF16("db"), backing_store, factory, ASCIIToUTF16("uniqueid")); + ASCIIToUTF16("db"), + backing_store, + factory, + IndexedDBDatabase::Identifier()); EXPECT_FALSE(backing_store->HasOneRef()); // local and db db = NULL; EXPECT_TRUE(backing_store->HasOneRef()); // local @@ -71,8 +74,11 @@ TEST(IndexedDBDatabaseTest, ConnectionLifecycle) { EXPECT_TRUE(backing_store->HasOneRef()); // local IndexedDBFactory* factory = 0; - scoped_refptr<IndexedDBDatabase> db = IndexedDBDatabase::Create( - ASCIIToUTF16("db"), backing_store, factory, ASCIIToUTF16("uniqueid")); + scoped_refptr<IndexedDBDatabase> db = + IndexedDBDatabase::Create(ASCIIToUTF16("db"), + backing_store, + factory, + IndexedDBDatabase::Identifier()); EXPECT_FALSE(backing_store->HasOneRef()); // local and db @@ -128,8 +134,11 @@ TEST(IndexedDBDatabaseTest, ForcedClose) { EXPECT_TRUE(backing_store->HasOneRef()); IndexedDBFactory* factory = 0; - scoped_refptr<IndexedDBDatabase> database = IndexedDBDatabase::Create( - ASCIIToUTF16("db"), backing_store, factory, ASCIIToUTF16("uniqueid")); + scoped_refptr<IndexedDBDatabase> database = + IndexedDBDatabase::Create(ASCIIToUTF16("db"), + backing_store, + factory, + IndexedDBDatabase::Identifier()); EXPECT_FALSE(backing_store->HasOneRef()); // local and db @@ -182,8 +191,11 @@ TEST(IndexedDBDatabaseTest, PendingDelete) { EXPECT_TRUE(backing_store->HasOneRef()); // local IndexedDBFactory* factory = 0; - scoped_refptr<IndexedDBDatabase> db = IndexedDBDatabase::Create( - ASCIIToUTF16("db"), backing_store, factory, ASCIIToUTF16("uniqueid")); + scoped_refptr<IndexedDBDatabase> db = + IndexedDBDatabase::Create(ASCIIToUTF16("db"), + backing_store, + factory, + IndexedDBDatabase::Identifier()); EXPECT_FALSE(backing_store->HasOneRef()); // local and db diff --git a/content/browser/indexed_db/indexed_db_factory.cc b/content/browser/indexed_db/indexed_db_factory.cc index eb7fa81..6b8d0c8 100644 --- a/content/browser/indexed_db/indexed_db_factory.cc +++ b/content/browser/indexed_db/indexed_db_factory.cc @@ -7,7 +7,6 @@ #include "base/logging.h" #include "base/strings/utf_string_conversions.h" #include "content/browser/indexed_db/indexed_db_backing_store.h" -#include "content/browser/indexed_db/indexed_db_database.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" @@ -31,17 +30,12 @@ static std::string ComputeFileIdentifier(const std::string& origin_identifier) { return origin_identifier + "@1"; } -static string16 ComputeUniqueIdentifier(const string16& name, - const std::string& origin_identifier) { - return ASCIIToUTF16(ComputeFileIdentifier(origin_identifier)) + name; -} - IndexedDBFactory::IndexedDBFactory() {} IndexedDBFactory::~IndexedDBFactory() {} void IndexedDBFactory::RemoveIDBDatabaseBackend( - const string16& unique_identifier) { + const IndexedDBDatabase::Identifier& unique_identifier) { DCHECK(database_backend_map_.find(unique_identifier) != database_backend_map_.end()); database_backend_map_.erase(unique_identifier); @@ -73,9 +67,7 @@ void IndexedDBFactory::DeleteDatabase( const std::string& origin_identifier, const base::FilePath& data_directory) { IDB_TRACE("IndexedDBFactory::DeleteDatabase"); - const string16 unique_identifier = - ComputeUniqueIdentifier(name, origin_identifier); - + IndexedDBDatabase::Identifier unique_identifier(origin_identifier, name); IndexedDBDatabaseMap::iterator it = database_backend_map_.find(unique_identifier); if (it != database_backend_map_.end()) { @@ -158,10 +150,8 @@ void IndexedDBFactory::Open( const std::string& origin_identifier, const base::FilePath& data_directory) { IDB_TRACE("IndexedDBFactory::Open"); - const string16 unique_identifier = - ComputeUniqueIdentifier(name, origin_identifier); - scoped_refptr<IndexedDBDatabase> database_backend; + IndexedDBDatabase::Identifier unique_identifier(origin_identifier, name); IndexedDBDatabaseMap::iterator it = database_backend_map_.find(unique_identifier); WebKit::WebIDBCallbacks::DataLoss data_loss = @@ -196,4 +186,15 @@ void IndexedDBFactory::Open( callbacks, database_callbacks, transaction_id, version, data_loss); } +std::vector<IndexedDBDatabase*> IndexedDBFactory::GetOpenDatabasesForOrigin( + const std::string& origin_identifier) const { + std::vector<IndexedDBDatabase*> result; + for (IndexedDBDatabaseMap::const_iterator it = database_backend_map_.begin(); + it != database_backend_map_.end(); ++it) { + if (it->first.first == origin_identifier) + result.push_back(it->second.get()); + } + return result; +} + } // namespace content diff --git a/content/browser/indexed_db/indexed_db_factory.h b/content/browser/indexed_db/indexed_db_factory.h index 0345b15..1666af5 100644 --- a/content/browser/indexed_db/indexed_db_factory.h +++ b/content/browser/indexed_db/indexed_db_factory.h @@ -14,6 +14,7 @@ #include "base/memory/weak_ptr.h" #include "base/strings/string16.h" #include "content/browser/indexed_db/indexed_db_callbacks.h" +#include "content/browser/indexed_db/indexed_db_database.h" #include "content/browser/indexed_db/indexed_db_database_callbacks.h" #include "content/browser/indexed_db/indexed_db_factory.h" #include "content/common/content_export.h" @@ -21,7 +22,6 @@ namespace content { class IndexedDBBackingStore; -class IndexedDBDatabase; class CONTENT_EXPORT IndexedDBFactory : NON_EXPORTED_BASE(public base::RefCounted<IndexedDBFactory>) { @@ -29,7 +29,8 @@ class CONTENT_EXPORT IndexedDBFactory IndexedDBFactory(); // Notifications from weak pointers. - void RemoveIDBDatabaseBackend(const string16& unique_identifier); + void RemoveIDBDatabaseBackend( + const IndexedDBDatabase::Identifier& unique_identifier); void GetDatabaseNames(scoped_refptr<IndexedDBCallbacks> callbacks, const std::string& origin_identifier, @@ -47,6 +48,10 @@ class CONTENT_EXPORT IndexedDBFactory const std::string& origin_identifier, const base::FilePath& data_directory); + // Iterates over all databases; for diagnostics only. + std::vector<IndexedDBDatabase*> GetOpenDatabasesForOrigin( + const std::string& origin_identifier) const; + protected: friend class base::RefCounted<IndexedDBFactory>; @@ -58,8 +63,8 @@ class CONTENT_EXPORT IndexedDBFactory WebKit::WebIDBCallbacks::DataLoss* data_loss); private: - typedef std::map<string16, scoped_refptr<IndexedDBDatabase> > - IndexedDBDatabaseMap; + typedef std::map<IndexedDBDatabase::Identifier, + scoped_refptr<IndexedDBDatabase> > IndexedDBDatabaseMap; IndexedDBDatabaseMap database_backend_map_; typedef std::map<std::string, base::WeakPtr<IndexedDBBackingStore> > diff --git a/content/browser/indexed_db/indexed_db_internals_ui.cc b/content/browser/indexed_db/indexed_db_internals_ui.cc index 1b2451f..a5c90c4 100644 --- a/content/browser/indexed_db/indexed_db_internals_ui.cc +++ b/content/browser/indexed_db/indexed_db_internals_ui.cc @@ -4,7 +4,6 @@ #include "content/browser/indexed_db/indexed_db_internals_ui.h" -#include <algorithm> #include <string> #include "base/bind.h" @@ -83,18 +82,14 @@ void IndexedDBInternalsUI::GetAllOrigins(const base::ListValue* args) { BrowserContext::ForEachStoragePartition(browser_context, cb); } -static bool HostNameComparator(const IndexedDBInfo& i, const IndexedDBInfo& j) { - return i.origin_.host() < j.origin_.host(); -} - void IndexedDBInternalsUI::GetAllOriginsOnIndexedDBThread( scoped_refptr<IndexedDBContext> context, const base::FilePath& context_path) { DCHECK(context->TaskRunner()->RunsTasksOnCurrentThread()); - scoped_ptr<std::vector<IndexedDBInfo> > info_list( - new std::vector<IndexedDBInfo>(context->GetAllOriginsInfo())); - std::sort(info_list->begin(), info_list->end(), HostNameComparator); + scoped_ptr<ListValue> info_list(static_cast<IndexedDBContextImpl*>( + context.get())->GetAllOriginsDetails()); + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(&IndexedDBInternalsUI::OnOriginsReady, @@ -103,24 +98,11 @@ void IndexedDBInternalsUI::GetAllOriginsOnIndexedDBThread( context_path)); } -void IndexedDBInternalsUI::OnOriginsReady( - scoped_ptr<std::vector<IndexedDBInfo> > origins, - const base::FilePath& path) { +void IndexedDBInternalsUI::OnOriginsReady(scoped_ptr<ListValue> origins, + const base::FilePath& path) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - base::ListValue urls; - for (std::vector<IndexedDBInfo>::const_iterator iter = origins->begin(); - iter != origins->end(); - ++iter) { - base::DictionaryValue* info = new base::DictionaryValue; - info->SetString("url", iter->origin_.spec()); - info->SetString("size", ui::FormatBytes(iter->size_)); - info->SetDouble("last_modified", iter->last_modified_.ToJsTime()); - info->SetString("path", iter->path_.value()); - info->SetDouble("connection_count", iter->connection_count_); - urls.Append(info); - } web_ui()->CallJavascriptFunction( - "indexeddb.onOriginsReady", urls, base::StringValue(path.value())); + "indexeddb.onOriginsReady", *origins, base::StringValue(path.value())); } static void FindContext(const base::FilePath& partition_path, diff --git a/content/browser/indexed_db/indexed_db_internals_ui.h b/content/browser/indexed_db/indexed_db_internals_ui.h index 3ec1925..a196e03 100644 --- a/content/browser/indexed_db/indexed_db_internals_ui.h +++ b/content/browser/indexed_db/indexed_db_internals_ui.h @@ -33,7 +33,7 @@ class IndexedDBInternalsUI : public WebUIController { void GetAllOrigins(const base::ListValue* args); void GetAllOriginsOnIndexedDBThread(scoped_refptr<IndexedDBContext> context, const base::FilePath& context_path); - void OnOriginsReady(scoped_ptr<std::vector<IndexedDBInfo> > origins, + void OnOriginsReady(scoped_ptr<base::ListValue> origins, const base::FilePath& path); void AddContextFromStoragePartition(StoragePartition* partition); diff --git a/content/browser/indexed_db/indexed_db_transaction.h b/content/browser/indexed_db/indexed_db_transaction.h index 4c37528..51b1c0a 100644 --- a/content/browser/indexed_db/indexed_db_transaction.h +++ b/content/browser/indexed_db/indexed_db_transaction.h @@ -69,6 +69,7 @@ class IndexedDBTransaction : public base::RefCounted<IndexedDBTransaction> { IndexedDBDatabase* database() const { return database_; } IndexedDBDatabaseCallbacks* connection() const { return callbacks_; } + bool IsRunning() const { return state_ == RUNNING; } protected: virtual ~IndexedDBTransaction(); diff --git a/content/browser/indexed_db/indexed_db_transaction_coordinator.cc b/content/browser/indexed_db/indexed_db_transaction_coordinator.cc index 78825b8..1f5100d 100644 --- a/content/browser/indexed_db/indexed_db_transaction_coordinator.cc +++ b/content/browser/indexed_db/indexed_db_transaction_coordinator.cc @@ -37,11 +37,10 @@ void IndexedDBTransactionCoordinator::DidFinishTransaction( DCHECK(transactions_.find(transaction) != transactions_.end()); if (queued_transactions_.has(transaction)) { - DCHECK(started_transactions_.find(transaction) == - started_transactions_.end()); + DCHECK(!started_transactions_.has(transaction)); queued_transactions_.erase(transaction); } else { - if (started_transactions_.find(transaction) != started_transactions_.end()) + if (started_transactions_.has(transaction)) started_transactions_.erase(transaction); } transactions_.erase(transaction); @@ -56,7 +55,7 @@ bool IndexedDBTransactionCoordinator::IsActive( bool found = false; if (queued_transactions_.has(transaction)) found = true; - if (started_transactions_.find(transaction) != started_transactions_.end()) { + if (started_transactions_.has(transaction)) { DCHECK(!found); found = true; } @@ -65,6 +64,26 @@ bool IndexedDBTransactionCoordinator::IsActive( } #endif +std::vector<const IndexedDBTransaction*> +IndexedDBTransactionCoordinator::GetTransactions() const { + std::vector<const IndexedDBTransaction*> result; + + for (list_set<IndexedDBTransaction*>::const_iterator it = + started_transactions_.begin(); + it != started_transactions_.end(); + ++it) { + result.push_back(*it); + } + for (list_set<IndexedDBTransaction*>::const_iterator it = + queued_transactions_.begin(); + it != queued_transactions_.end(); + ++it) { + result.push_back(*it); + } + + return result; +} + void IndexedDBTransactionCoordinator::ProcessStartedTransactions() { if (queued_transactions_.empty()) return; @@ -109,7 +128,7 @@ bool IndexedDBTransactionCoordinator::CanRunTransaction( return true; case indexed_db::TRANSACTION_READ_WRITE: - for (std::set<IndexedDBTransaction*>::const_iterator it = + for (list_set<IndexedDBTransaction*>::const_iterator it = started_transactions_.begin(); it != started_transactions_.end(); ++it) { diff --git a/content/browser/indexed_db/indexed_db_transaction_coordinator.h b/content/browser/indexed_db/indexed_db_transaction_coordinator.h index 1b0eed1..d9f9cd5 100644 --- a/content/browser/indexed_db/indexed_db_transaction_coordinator.h +++ b/content/browser/indexed_db/indexed_db_transaction_coordinator.h @@ -7,6 +7,7 @@ #include <map> #include <set> +#include <vector> #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" @@ -31,6 +32,9 @@ class IndexedDBTransactionCoordinator { bool IsActive(IndexedDBTransaction* transaction); #endif + // Makes a snapshot of the transaction queue. For diagnostics only. + std::vector<const IndexedDBTransaction*> GetTransactions() const; + private: void ProcessStartedTransactions(); bool CanRunTransaction(IndexedDBTransaction* transaction); @@ -38,9 +42,12 @@ class IndexedDBTransactionCoordinator { // This is just an efficient way to keep references to all transactions. std::map<IndexedDBTransaction*, scoped_refptr<IndexedDBTransaction> > transactions_; + // Transactions in different states are grouped below. + // list_set is used to provide stable ordering; required by spec + // for the queue, convenience for diagnostics for the rest. list_set<IndexedDBTransaction*> queued_transactions_; - std::set<IndexedDBTransaction*> started_transactions_; + list_set<IndexedDBTransaction*> started_transactions_; }; } // namespace content diff --git a/content/browser/resources/indexed_db/indexeddb_internals.css b/content/browser/resources/indexed_db/indexeddb_internals.css index 2bbea77..76653f0 100644 --- a/content/browser/resources/indexed_db/indexeddb_internals.css +++ b/content/browser/resources/indexed_db/indexeddb_internals.css @@ -29,6 +29,43 @@ white-space: nowrap; } +.indexeddb-database { + margin-bottom: 6px; + margin-top: 6px; + margin-left: 12px; + + position: relative; +} + +.indexeddb-database > div { + margin-left: 12px; +} + +.indexeddb-connection-count { + margin: 0 8px; +} +.indexeddb-connection-count.pending { + font-weight: bold; +} + +.indexeddb-transaction { + background-color: rgb(235, 239, 249); + margin: 4px 0; + border-radius: 4px; + padding: 2px; + position: relative; +} + +.indexeddb-transaction.running { + font-weight: bold; +} + +.indexeddb-transaction-mode, +.indexeddb-transaction-scope, +.indexeddb-transaction-state { + margin: 0 8px; +} + .controls a { -webkit-margin-end: 16px; color: #777; diff --git a/content/browser/resources/indexed_db/indexeddb_internals.html b/content/browser/resources/indexed_db/indexeddb_internals.html index 0625079..153aef1 100644 --- a/content/browser/resources/indexed_db/indexeddb_internals.html +++ b/content/browser/resources/indexed_db/indexeddb_internals.html @@ -45,6 +45,57 @@ jsvalues=".idb_origin_url:url;.idb_partition_path:$partition_path">Download</a> <span class="download-status" style="display: none">Loading...</span> </div> + <div class="indexeddb-database" jsselect="$this.databases"> + + <span>Open database:</span> + <span jscontent="name"></span> + + <div> + <span>Connections:</span> + + <span class="indexeddb-connection-count" + jsdisplay="connection_count"> + <span>open:</span> + <span jscontent="connection_count"></span> + </span> + + <span class="indexeddb-connection-count pending" + jsdisplay="pending_opens"> + <span>pending opens:</span> + <span jscontent="pending_opens"></span> + </span> + + <span class="indexeddb-connection-count pending" + jsdisplay="pending_upgrades"> + <span>pending upgrades:</span> + <span jscontent="pending_upgrades"></span> + </span> + + <span class="indexeddb-connection-count pending" + jsdisplay="running_upgrades"> + <span>running upgrades:</span> + <span jscontent="running_upgrades"></span> + </span> + + <span class="indexeddb-connection-count pending" + jsdisplay="pending_deletes"> + <span>pending deletes:</span> + <span jscontent="pending_deletes"></span> + </span> + + </div> + <div class="indexeddb-transaction" + jsselect="$this.transactions" + jseval="this.classList.add($this.running ? 'running' : 'waiting')"> + <span>Transaction:</span> + <span class="indexeddb-transaction-mode" jscontent="mode"></span> + <span class="indexeddb-transaction-scope" jsdisplay="scope"> + <span>scope:</span> <span jscontent="'[ ' + scope.join(', ') + ' ]'"></span> + </span> + <span class="indexeddb-transaction-state" + jscontent="running ? '(running)' : '(blocked)'"></span> + </div> + </div> </div> </div> </div> |