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 |