| 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 ConnectionSet& connections = connections_[origin_url]; | |
| 341 ConnectionSet::iterator it = connections.begin(); | |
| 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 } | |
| 352 if (factory_) | 340 if (factory_) |
| 353 factory_->ForceClose(origin_url); | 341 factory_->ForceClose(origin_url); |
| 342 DCHECK_EQ(0UL, GetConnectionCount(origin_url)); |
| 354 } | 343 } |
| 355 | 344 |
| 356 size_t IndexedDBContextImpl::GetConnectionCount(const GURL& origin_url) { | 345 size_t IndexedDBContextImpl::GetConnectionCount(const GURL& origin_url) { |
| 357 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); | 346 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); |
| 358 if (data_path_.empty() || !IsInOriginSet(origin_url)) | 347 if (data_path_.empty() || !IsInOriginSet(origin_url)) |
| 359 return 0; | 348 return 0; |
| 360 | 349 |
| 361 if (connections_.find(origin_url) == connections_.end()) | 350 if (!factory_) |
| 362 return 0; | 351 return 0; |
| 363 | 352 |
| 364 return connections_[origin_url].size(); | 353 return factory_->GetConnectionCount(origin_url); |
| 365 } | 354 } |
| 366 | 355 |
| 367 base::FilePath IndexedDBContextImpl::GetFilePath(const GURL& origin_url) const { | 356 base::FilePath IndexedDBContextImpl::GetFilePath(const GURL& origin_url) const { |
| 368 std::string origin_id = webkit_database::GetIdentifierFromOrigin(origin_url); | 357 std::string origin_id = webkit_database::GetIdentifierFromOrigin(origin_url); |
| 369 return GetIndexedDBFilePath(origin_id); | 358 return GetIndexedDBFilePath(origin_id); |
| 370 } | 359 } |
| 371 | 360 |
| 372 base::FilePath IndexedDBContextImpl::GetFilePathForTesting( | 361 base::FilePath IndexedDBContextImpl::GetFilePathForTesting( |
| 373 const std::string& origin_id) const { | 362 const std::string& origin_id) const { |
| 374 return GetIndexedDBFilePath(origin_id); | 363 return GetIndexedDBFilePath(origin_id); |
| 375 } | 364 } |
| 376 | 365 |
| 377 void IndexedDBContextImpl::SetTaskRunnerForTesting( | 366 void IndexedDBContextImpl::SetTaskRunnerForTesting( |
| 378 base::SequencedTaskRunner* task_runner) { | 367 base::SequencedTaskRunner* task_runner) { |
| 379 DCHECK(!task_runner_); | 368 DCHECK(!task_runner_); |
| 380 task_runner_ = task_runner; | 369 task_runner_ = task_runner; |
| 381 } | 370 } |
| 382 | 371 |
| 383 void IndexedDBContextImpl::ConnectionOpened(const GURL& origin_url, | 372 void IndexedDBContextImpl::ConnectionOpened(const GURL& origin_url, |
| 384 IndexedDBConnection* connection) { | 373 IndexedDBConnection* connection) { |
| 385 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); | 374 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); |
| 386 DCHECK_EQ(connections_[origin_url].count(connection), 0UL); | |
| 387 if (quota_manager_proxy()) { | 375 if (quota_manager_proxy()) { |
| 388 quota_manager_proxy()->NotifyStorageAccessed( | 376 quota_manager_proxy()->NotifyStorageAccessed( |
| 389 quota::QuotaClient::kIndexedDatabase, | 377 quota::QuotaClient::kIndexedDatabase, |
| 390 origin_url, | 378 origin_url, |
| 391 quota::kStorageTypeTemporary); | 379 quota::kStorageTypeTemporary); |
| 392 } | 380 } |
| 393 connections_[origin_url].insert(connection); | |
| 394 if (AddToOriginSet(origin_url)) { | 381 if (AddToOriginSet(origin_url)) { |
| 395 // A newly created db, notify the quota system. | 382 // A newly created db, notify the quota system. |
| 396 QueryDiskAndUpdateQuotaUsage(origin_url); | 383 QueryDiskAndUpdateQuotaUsage(origin_url); |
| 397 } else { | 384 } else { |
| 398 EnsureDiskUsageCacheInitialized(origin_url); | 385 EnsureDiskUsageCacheInitialized(origin_url); |
| 399 } | 386 } |
| 400 QueryAvailableQuota(origin_url); | 387 QueryAvailableQuota(origin_url); |
| 401 } | 388 } |
| 402 | 389 |
| 403 void IndexedDBContextImpl::ConnectionClosed(const GURL& origin_url, | 390 void IndexedDBContextImpl::ConnectionClosed(const GURL& origin_url, |
| 404 IndexedDBConnection* connection) { | 391 IndexedDBConnection* connection) { |
| 405 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); | 392 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()) { | 393 if (quota_manager_proxy()) { |
| 411 quota_manager_proxy()->NotifyStorageAccessed( | 394 quota_manager_proxy()->NotifyStorageAccessed( |
| 412 quota::QuotaClient::kIndexedDatabase, | 395 quota::QuotaClient::kIndexedDatabase, |
| 413 origin_url, | 396 origin_url, |
| 414 quota::kStorageTypeTemporary); | 397 quota::kStorageTypeTemporary); |
| 415 } | 398 } |
| 416 connections_[origin_url].erase(connection); | 399 if (factory_ && factory_->GetConnectionCount(origin_url) == 0) |
| 417 if (connections_[origin_url].size() == 0) { | |
| 418 QueryDiskAndUpdateQuotaUsage(origin_url); | 400 QueryDiskAndUpdateQuotaUsage(origin_url); |
| 419 connections_.erase(origin_url); | |
| 420 } | |
| 421 } | 401 } |
| 422 | 402 |
| 423 void IndexedDBContextImpl::TransactionComplete(const GURL& origin_url) { | 403 void IndexedDBContextImpl::TransactionComplete(const GURL& origin_url) { |
| 424 DCHECK(connections_.find(origin_url) != connections_.end() && | 404 DCHECK(!factory_ || factory_->GetConnectionCount(origin_url) > 0); |
| 425 connections_[origin_url].size() > 0); | |
| 426 QueryDiskAndUpdateQuotaUsage(origin_url); | 405 QueryDiskAndUpdateQuotaUsage(origin_url); |
| 427 QueryAvailableQuota(origin_url); | 406 QueryAvailableQuota(origin_url); |
| 428 } | 407 } |
| 429 | 408 |
| 430 void IndexedDBContextImpl::DatabaseDeleted(const GURL& origin_url) { | 409 void IndexedDBContextImpl::DatabaseDeleted(const GURL& origin_url) { |
| 431 AddToOriginSet(origin_url); | 410 AddToOriginSet(origin_url); |
| 432 QueryDiskAndUpdateQuotaUsage(origin_url); | 411 QueryDiskAndUpdateQuotaUsage(origin_url); |
| 433 QueryAvailableQuota(origin_url); | 412 QueryAvailableQuota(origin_url); |
| 434 } | 413 } |
| 435 | 414 |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 582 origin_set_.reset(); | 561 origin_set_.reset(); |
| 583 origin_size_map_.clear(); | 562 origin_size_map_.clear(); |
| 584 space_available_map_.clear(); | 563 space_available_map_.clear(); |
| 585 } | 564 } |
| 586 | 565 |
| 587 base::TaskRunner* IndexedDBContextImpl::TaskRunner() const { | 566 base::TaskRunner* IndexedDBContextImpl::TaskRunner() const { |
| 588 return task_runner_; | 567 return task_runner_; |
| 589 } | 568 } |
| 590 | 569 |
| 591 } // namespace content | 570 } // namespace content |
| OLD | NEW |