| 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::pair<IndexedDBFactory::OriginDBMapIterator, | 190 std::vector<IndexedDBDatabase*> databases = |
| 191 IndexedDBFactory::OriginDBMapIterator> range = | |
| 192 factory_->GetOpenDatabasesForOrigin(origin_url); | 191 factory_->GetOpenDatabasesForOrigin(origin_url); |
| 193 // TODO(jsbell): Sort by name? | 192 // TODO(jsbell): Sort by name? |
| 194 scoped_ptr<base::ListValue> database_list(new base::ListValue()); | 193 scoped_ptr<base::ListValue> database_list(new base::ListValue()); |
| 195 | 194 |
| 196 for (IndexedDBFactory::OriginDBMapIterator it = range.first; | 195 for (std::vector<IndexedDBDatabase*>::iterator it = databases.begin(); |
| 197 it != range.second; | 196 it != databases.end(); |
| 198 ++it) { | 197 ++it) { |
| 199 | 198 |
| 200 const IndexedDBDatabase* db = it->second; | 199 const IndexedDBDatabase* db = *it; |
| 201 scoped_ptr<base::DictionaryValue> db_info(new base::DictionaryValue()); | 200 scoped_ptr<base::DictionaryValue> db_info(new base::DictionaryValue()); |
| 202 | 201 |
| 203 db_info->SetString("name", db->name()); | 202 db_info->SetString("name", db->name()); |
| 204 db_info->SetDouble("pending_opens", db->PendingOpenCount()); | 203 db_info->SetDouble("pending_opens", db->PendingOpenCount()); |
| 205 db_info->SetDouble("pending_upgrades", db->PendingUpgradeCount()); | 204 db_info->SetDouble("pending_upgrades", db->PendingUpgradeCount()); |
| 206 db_info->SetDouble("running_upgrades", db->RunningUpgradeCount()); | 205 db_info->SetDouble("running_upgrades", db->RunningUpgradeCount()); |
| 207 db_info->SetDouble("pending_deletes", db->PendingDeleteCount()); | 206 db_info->SetDouble("pending_deletes", db->PendingDeleteCount()); |
| 208 db_info->SetDouble("connection_count", | 207 db_info->SetDouble("connection_count", |
| 209 db->ConnectionCount() - db->PendingUpgradeCount() - | 208 db->ConnectionCount() - db->PendingUpgradeCount() - |
| 210 db->RunningUpgradeCount()); | 209 db->RunningUpgradeCount()); |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 330 origin_size_map_.erase(origin_url); | 329 origin_size_map_.erase(origin_url); |
| 331 space_available_map_.erase(origin_url); | 330 space_available_map_.erase(origin_url); |
| 332 } | 331 } |
| 333 } | 332 } |
| 334 | 333 |
| 335 void IndexedDBContextImpl::ForceClose(const GURL origin_url) { | 334 void IndexedDBContextImpl::ForceClose(const GURL origin_url) { |
| 336 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); | 335 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); |
| 337 if (data_path_.empty() || !IsInOriginSet(origin_url)) | 336 if (data_path_.empty() || !IsInOriginSet(origin_url)) |
| 338 return; | 337 return; |
| 339 | 338 |
| 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 } |
| 340 if (factory_) | 352 if (factory_) |
| 341 factory_->ForceClose(origin_url); | 353 factory_->ForceClose(origin_url); |
| 342 DCHECK_EQ(0UL, GetConnectionCount(origin_url)); | |
| 343 } | 354 } |
| 344 | 355 |
| 345 size_t IndexedDBContextImpl::GetConnectionCount(const GURL& origin_url) { | 356 size_t IndexedDBContextImpl::GetConnectionCount(const GURL& origin_url) { |
| 346 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); | 357 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); |
| 347 if (data_path_.empty() || !IsInOriginSet(origin_url)) | 358 if (data_path_.empty() || !IsInOriginSet(origin_url)) |
| 348 return 0; | 359 return 0; |
| 349 | 360 |
| 350 if (!factory_) | 361 if (connections_.find(origin_url) == connections_.end()) |
| 351 return 0; | 362 return 0; |
| 352 | 363 |
| 353 return factory_->GetConnectionCount(origin_url); | 364 return connections_[origin_url].size(); |
| 354 } | 365 } |
| 355 | 366 |
| 356 base::FilePath IndexedDBContextImpl::GetFilePath(const GURL& origin_url) const { | 367 base::FilePath IndexedDBContextImpl::GetFilePath(const GURL& origin_url) const { |
| 357 std::string origin_id = webkit_database::GetIdentifierFromOrigin(origin_url); | 368 std::string origin_id = webkit_database::GetIdentifierFromOrigin(origin_url); |
| 358 return GetIndexedDBFilePath(origin_id); | 369 return GetIndexedDBFilePath(origin_id); |
| 359 } | 370 } |
| 360 | 371 |
| 361 base::FilePath IndexedDBContextImpl::GetFilePathForTesting( | 372 base::FilePath IndexedDBContextImpl::GetFilePathForTesting( |
| 362 const std::string& origin_id) const { | 373 const std::string& origin_id) const { |
| 363 return GetIndexedDBFilePath(origin_id); | 374 return GetIndexedDBFilePath(origin_id); |
| 364 } | 375 } |
| 365 | 376 |
| 366 void IndexedDBContextImpl::SetTaskRunnerForTesting( | 377 void IndexedDBContextImpl::SetTaskRunnerForTesting( |
| 367 base::SequencedTaskRunner* task_runner) { | 378 base::SequencedTaskRunner* task_runner) { |
| 368 DCHECK(!task_runner_); | 379 DCHECK(!task_runner_); |
| 369 task_runner_ = task_runner; | 380 task_runner_ = task_runner; |
| 370 } | 381 } |
| 371 | 382 |
| 372 void IndexedDBContextImpl::ConnectionOpened(const GURL& origin_url, | 383 void IndexedDBContextImpl::ConnectionOpened(const GURL& origin_url, |
| 373 IndexedDBConnection* connection) { | 384 IndexedDBConnection* connection) { |
| 374 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); | 385 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); |
| 386 DCHECK_EQ(connections_[origin_url].count(connection), 0UL); |
| 375 if (quota_manager_proxy()) { | 387 if (quota_manager_proxy()) { |
| 376 quota_manager_proxy()->NotifyStorageAccessed( | 388 quota_manager_proxy()->NotifyStorageAccessed( |
| 377 quota::QuotaClient::kIndexedDatabase, | 389 quota::QuotaClient::kIndexedDatabase, |
| 378 origin_url, | 390 origin_url, |
| 379 quota::kStorageTypeTemporary); | 391 quota::kStorageTypeTemporary); |
| 380 } | 392 } |
| 393 connections_[origin_url].insert(connection); |
| 381 if (AddToOriginSet(origin_url)) { | 394 if (AddToOriginSet(origin_url)) { |
| 382 // A newly created db, notify the quota system. | 395 // A newly created db, notify the quota system. |
| 383 QueryDiskAndUpdateQuotaUsage(origin_url); | 396 QueryDiskAndUpdateQuotaUsage(origin_url); |
| 384 } else { | 397 } else { |
| 385 EnsureDiskUsageCacheInitialized(origin_url); | 398 EnsureDiskUsageCacheInitialized(origin_url); |
| 386 } | 399 } |
| 387 QueryAvailableQuota(origin_url); | 400 QueryAvailableQuota(origin_url); |
| 388 } | 401 } |
| 389 | 402 |
| 390 void IndexedDBContextImpl::ConnectionClosed(const GURL& origin_url, | 403 void IndexedDBContextImpl::ConnectionClosed(const GURL& origin_url, |
| 391 IndexedDBConnection* connection) { | 404 IndexedDBConnection* connection) { |
| 392 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); | 405 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; |
| 393 if (quota_manager_proxy()) { | 410 if (quota_manager_proxy()) { |
| 394 quota_manager_proxy()->NotifyStorageAccessed( | 411 quota_manager_proxy()->NotifyStorageAccessed( |
| 395 quota::QuotaClient::kIndexedDatabase, | 412 quota::QuotaClient::kIndexedDatabase, |
| 396 origin_url, | 413 origin_url, |
| 397 quota::kStorageTypeTemporary); | 414 quota::kStorageTypeTemporary); |
| 398 } | 415 } |
| 399 if (factory_ && factory_->GetConnectionCount(origin_url) == 0) | 416 connections_[origin_url].erase(connection); |
| 417 if (connections_[origin_url].size() == 0) { |
| 400 QueryDiskAndUpdateQuotaUsage(origin_url); | 418 QueryDiskAndUpdateQuotaUsage(origin_url); |
| 419 connections_.erase(origin_url); |
| 420 } |
| 401 } | 421 } |
| 402 | 422 |
| 403 void IndexedDBContextImpl::TransactionComplete(const GURL& origin_url) { | 423 void IndexedDBContextImpl::TransactionComplete(const GURL& origin_url) { |
| 404 DCHECK(!factory_ || factory_->GetConnectionCount(origin_url) > 0); | 424 DCHECK(connections_.find(origin_url) != connections_.end() && |
| 425 connections_[origin_url].size() > 0); |
| 405 QueryDiskAndUpdateQuotaUsage(origin_url); | 426 QueryDiskAndUpdateQuotaUsage(origin_url); |
| 406 QueryAvailableQuota(origin_url); | 427 QueryAvailableQuota(origin_url); |
| 407 } | 428 } |
| 408 | 429 |
| 409 void IndexedDBContextImpl::DatabaseDeleted(const GURL& origin_url) { | 430 void IndexedDBContextImpl::DatabaseDeleted(const GURL& origin_url) { |
| 410 AddToOriginSet(origin_url); | 431 AddToOriginSet(origin_url); |
| 411 QueryDiskAndUpdateQuotaUsage(origin_url); | 432 QueryDiskAndUpdateQuotaUsage(origin_url); |
| 412 QueryAvailableQuota(origin_url); | 433 QueryAvailableQuota(origin_url); |
| 413 } | 434 } |
| 414 | 435 |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 561 origin_set_.reset(); | 582 origin_set_.reset(); |
| 562 origin_size_map_.clear(); | 583 origin_size_map_.clear(); |
| 563 space_available_map_.clear(); | 584 space_available_map_.clear(); |
| 564 } | 585 } |
| 565 | 586 |
| 566 base::TaskRunner* IndexedDBContextImpl::TaskRunner() const { | 587 base::TaskRunner* IndexedDBContextImpl::TaskRunner() const { |
| 567 return task_runner_; | 588 return task_runner_; |
| 568 } | 589 } |
| 569 | 590 |
| 570 } // namespace content | 591 } // namespace content |
| OLD | NEW |