Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/indexed_db/indexed_db_context_impl.h" | 5 #include "content/browser/indexed_db/indexed_db_context_impl.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 180 info->SetDouble("last_modified", | 180 info->SetDouble("last_modified", |
| 181 GetOriginLastModified(origin_url).ToJsTime()); | 181 GetOriginLastModified(origin_url).ToJsTime()); |
| 182 info->SetString("path", GetFilePath(origin_url).value()); | 182 info->SetString("path", GetFilePath(origin_url).value()); |
| 183 info->SetDouble("connection_count", GetConnectionCount(origin_url)); | 183 info->SetDouble("connection_count", GetConnectionCount(origin_url)); |
| 184 | 184 |
| 185 // This ends up being O(n^2) since we iterate over all open databases | 185 // This ends up being O(n^2) since we iterate over all open databases |
| 186 // to extract just those in the origin, and we're iterating over all | 186 // to extract just those in the origin, and we're iterating over all |
| 187 // origins in the outer loop. | 187 // origins in the outer loop. |
| 188 | 188 |
| 189 if (factory_) { | 189 if (factory_) { |
| 190 std::vector<IndexedDBDatabase*> databases = | 190 std::pair<IndexedDBFactory::OriginDBMapIterator, |
| 191 IndexedDBFactory::OriginDBMapIterator> range = | |
| 191 factory_->GetOpenDatabasesForOrigin(origin_url); | 192 factory_->GetOpenDatabasesForOrigin(origin_url); |
| 192 // TODO(jsbell): Sort by name? | 193 // TODO(jsbell): Sort by name? |
| 193 scoped_ptr<base::ListValue> database_list(new base::ListValue()); | 194 scoped_ptr<base::ListValue> database_list(new base::ListValue()); |
| 194 | 195 |
| 195 for (std::vector<IndexedDBDatabase*>::iterator it = databases.begin(); | 196 for (IndexedDBFactory::OriginDBMapIterator it = range.first; |
| 196 it != databases.end(); | 197 it != range.second; |
| 197 ++it) { | 198 ++it) { |
| 198 | 199 |
| 199 const IndexedDBDatabase* db = *it; | 200 const IndexedDBDatabase* db = it->second; |
| 200 scoped_ptr<base::DictionaryValue> db_info(new base::DictionaryValue()); | 201 scoped_ptr<base::DictionaryValue> db_info(new base::DictionaryValue()); |
| 201 | 202 |
| 202 db_info->SetString("name", db->name()); | 203 db_info->SetString("name", db->name()); |
| 203 db_info->SetDouble("pending_opens", db->PendingOpenCount()); | 204 db_info->SetDouble("pending_opens", db->PendingOpenCount()); |
| 204 db_info->SetDouble("pending_upgrades", db->PendingUpgradeCount()); | 205 db_info->SetDouble("pending_upgrades", db->PendingUpgradeCount()); |
| 205 db_info->SetDouble("running_upgrades", db->RunningUpgradeCount()); | 206 db_info->SetDouble("running_upgrades", db->RunningUpgradeCount()); |
| 206 db_info->SetDouble("pending_deletes", db->PendingDeleteCount()); | 207 db_info->SetDouble("pending_deletes", db->PendingDeleteCount()); |
| 207 db_info->SetDouble("connection_count", | 208 db_info->SetDouble("connection_count", |
| 208 db->ConnectionCount() - db->PendingUpgradeCount() - | 209 db->ConnectionCount() - db->PendingUpgradeCount() - |
| 209 db->RunningUpgradeCount()); | 210 db->RunningUpgradeCount()); |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 329 origin_size_map_.erase(origin_url); | 330 origin_size_map_.erase(origin_url); |
| 330 space_available_map_.erase(origin_url); | 331 space_available_map_.erase(origin_url); |
| 331 } | 332 } |
| 332 } | 333 } |
| 333 | 334 |
| 334 void IndexedDBContextImpl::ForceClose(const GURL origin_url) { | 335 void IndexedDBContextImpl::ForceClose(const GURL origin_url) { |
| 335 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); | 336 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); |
| 336 if (data_path_.empty() || !IsInOriginSet(origin_url)) | 337 if (data_path_.empty() || !IsInOriginSet(origin_url)) |
| 337 return; | 338 return; |
| 338 | 339 |
| 339 if (connections_.find(origin_url) != connections_.end()) { | 340 if (factory_) { |
| 340 ConnectionSet& connections = connections_[origin_url]; | 341 factory_->ForceClose(origin_url); |
| 341 ConnectionSet::iterator it = connections.begin(); | 342 DCHECK_EQ(0UL, GetConnectionCount(origin_url)); |
|
jsbell
2014/01/06 22:33:50
Nit: This DCHECK could move outside the 'if' block
cmumford
2014/01/09 00:48:25
Done.
| |
| 342 while (it != connections.end()) { | |
| 343 // Remove before closing so callbacks don't double-erase | |
| 344 IndexedDBConnection* connection = *it; | |
| 345 DCHECK(connection->IsConnected()); | |
| 346 connections.erase(it++); | |
| 347 connection->ForceClose(); | |
| 348 } | |
| 349 DCHECK_EQ(connections_[origin_url].size(), 0UL); | |
| 350 connections_.erase(origin_url); | |
| 351 } | 343 } |
| 352 if (factory_) | |
| 353 factory_->ForceClose(origin_url); | |
| 354 } | 344 } |
| 355 | 345 |
| 356 size_t IndexedDBContextImpl::GetConnectionCount(const GURL& origin_url) { | 346 size_t IndexedDBContextImpl::GetConnectionCount(const GURL& origin_url) { |
| 357 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); | 347 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); |
| 358 if (data_path_.empty() || !IsInOriginSet(origin_url)) | 348 if (data_path_.empty() || !IsInOriginSet(origin_url)) |
| 359 return 0; | 349 return 0; |
| 360 | 350 |
| 361 if (connections_.find(origin_url) == connections_.end()) | 351 if (!factory_) |
| 362 return 0; | 352 return 0; |
| 363 | 353 |
| 364 return connections_[origin_url].size(); | 354 return factory_->GetConnectionCount(origin_url); |
| 365 } | 355 } |
| 366 | 356 |
| 367 base::FilePath IndexedDBContextImpl::GetFilePath(const GURL& origin_url) const { | 357 base::FilePath IndexedDBContextImpl::GetFilePath(const GURL& origin_url) const { |
| 368 std::string origin_id = webkit_database::GetIdentifierFromOrigin(origin_url); | 358 std::string origin_id = webkit_database::GetIdentifierFromOrigin(origin_url); |
| 369 return GetIndexedDBFilePath(origin_id); | 359 return GetIndexedDBFilePath(origin_id); |
| 370 } | 360 } |
| 371 | 361 |
| 372 base::FilePath IndexedDBContextImpl::GetFilePathForTesting( | 362 base::FilePath IndexedDBContextImpl::GetFilePathForTesting( |
| 373 const std::string& origin_id) const { | 363 const std::string& origin_id) const { |
| 374 return GetIndexedDBFilePath(origin_id); | 364 return GetIndexedDBFilePath(origin_id); |
| 375 } | 365 } |
| 376 | 366 |
| 377 void IndexedDBContextImpl::SetTaskRunnerForTesting( | 367 void IndexedDBContextImpl::SetTaskRunnerForTesting( |
| 378 base::SequencedTaskRunner* task_runner) { | 368 base::SequencedTaskRunner* task_runner) { |
| 379 DCHECK(!task_runner_); | 369 DCHECK(!task_runner_); |
| 380 task_runner_ = task_runner; | 370 task_runner_ = task_runner; |
| 381 } | 371 } |
| 382 | 372 |
| 383 void IndexedDBContextImpl::ConnectionOpened(const GURL& origin_url, | 373 void IndexedDBContextImpl::ConnectionOpened(const GURL& origin_url, |
| 384 IndexedDBConnection* connection) { | 374 IndexedDBConnection* connection) { |
| 385 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); | 375 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); |
| 386 DCHECK_EQ(connections_[origin_url].count(connection), 0UL); | |
| 387 if (quota_manager_proxy()) { | 376 if (quota_manager_proxy()) { |
| 388 quota_manager_proxy()->NotifyStorageAccessed( | 377 quota_manager_proxy()->NotifyStorageAccessed( |
| 389 quota::QuotaClient::kIndexedDatabase, | 378 quota::QuotaClient::kIndexedDatabase, |
| 390 origin_url, | 379 origin_url, |
| 391 quota::kStorageTypeTemporary); | 380 quota::kStorageTypeTemporary); |
| 392 } | 381 } |
| 393 connections_[origin_url].insert(connection); | |
| 394 if (AddToOriginSet(origin_url)) { | 382 if (AddToOriginSet(origin_url)) { |
| 395 // A newly created db, notify the quota system. | 383 // A newly created db, notify the quota system. |
| 396 QueryDiskAndUpdateQuotaUsage(origin_url); | 384 QueryDiskAndUpdateQuotaUsage(origin_url); |
| 397 } else { | 385 } else { |
| 398 EnsureDiskUsageCacheInitialized(origin_url); | 386 EnsureDiskUsageCacheInitialized(origin_url); |
| 399 } | 387 } |
| 400 QueryAvailableQuota(origin_url); | 388 QueryAvailableQuota(origin_url); |
| 401 } | 389 } |
| 402 | 390 |
| 403 void IndexedDBContextImpl::ConnectionClosed(const GURL& origin_url, | 391 void IndexedDBContextImpl::ConnectionClosed(const GURL& origin_url, |
| 404 IndexedDBConnection* connection) { | 392 IndexedDBConnection* connection) { |
| 405 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); | 393 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); |
| 406 // May not be in the map if connection was forced to close | |
| 407 if (connections_.find(origin_url) == connections_.end() || | |
| 408 connections_[origin_url].count(connection) != 1) | |
| 409 return; | |
| 410 if (quota_manager_proxy()) { | 394 if (quota_manager_proxy()) { |
| 411 quota_manager_proxy()->NotifyStorageAccessed( | 395 quota_manager_proxy()->NotifyStorageAccessed( |
| 412 quota::QuotaClient::kIndexedDatabase, | 396 quota::QuotaClient::kIndexedDatabase, |
| 413 origin_url, | 397 origin_url, |
| 414 quota::kStorageTypeTemporary); | 398 quota::kStorageTypeTemporary); |
| 415 } | 399 } |
| 416 connections_[origin_url].erase(connection); | 400 if (factory_ && factory_->GetConnectionCount(origin_url) == 0) |
| 417 if (connections_[origin_url].size() == 0) { | |
| 418 QueryDiskAndUpdateQuotaUsage(origin_url); | 401 QueryDiskAndUpdateQuotaUsage(origin_url); |
| 419 connections_.erase(origin_url); | |
| 420 } | |
| 421 } | 402 } |
| 422 | 403 |
| 423 void IndexedDBContextImpl::TransactionComplete(const GURL& origin_url) { | 404 void IndexedDBContextImpl::TransactionComplete(const GURL& origin_url) { |
| 424 DCHECK(connections_.find(origin_url) != connections_.end() && | 405 DCHECK(!factory_ || factory_->GetConnectionCount(origin_url) > 0); |
| 425 connections_[origin_url].size() > 0); | |
| 426 QueryDiskAndUpdateQuotaUsage(origin_url); | 406 QueryDiskAndUpdateQuotaUsage(origin_url); |
| 427 QueryAvailableQuota(origin_url); | 407 QueryAvailableQuota(origin_url); |
| 428 } | 408 } |
| 429 | 409 |
| 430 void IndexedDBContextImpl::DatabaseDeleted(const GURL& origin_url) { | 410 void IndexedDBContextImpl::DatabaseDeleted(const GURL& origin_url) { |
| 431 AddToOriginSet(origin_url); | 411 AddToOriginSet(origin_url); |
| 432 QueryDiskAndUpdateQuotaUsage(origin_url); | 412 QueryDiskAndUpdateQuotaUsage(origin_url); |
| 433 QueryAvailableQuota(origin_url); | 413 QueryAvailableQuota(origin_url); |
| 434 } | 414 } |
| 435 | 415 |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 582 origin_set_.reset(); | 562 origin_set_.reset(); |
| 583 origin_size_map_.clear(); | 563 origin_size_map_.clear(); |
| 584 space_available_map_.clear(); | 564 space_available_map_.clear(); |
| 585 } | 565 } |
| 586 | 566 |
| 587 base::TaskRunner* IndexedDBContextImpl::TaskRunner() const { | 567 base::TaskRunner* IndexedDBContextImpl::TaskRunner() const { |
| 588 return task_runner_; | 568 return task_runner_; |
| 589 } | 569 } |
| 590 | 570 |
| 591 } // namespace content | 571 } // namespace content |
| OLD | NEW |