| 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_dispatcher_host.h" | 5 #include "content/browser/indexed_db/indexed_db_dispatcher_host.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 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 18 matching lines...) Expand all Loading... |
| 29 #include "content/public/browser/browser_thread.h" | 29 #include "content/public/browser/browser_thread.h" |
| 30 #include "content/public/browser/user_metrics.h" | 30 #include "content/public/browser/user_metrics.h" |
| 31 #include "content/public/common/content_switches.h" | 31 #include "content/public/common/content_switches.h" |
| 32 #include "content/public/common/result_codes.h" | 32 #include "content/public/common/result_codes.h" |
| 33 #include "storage/browser/blob/blob_data_builder.h" | 33 #include "storage/browser/blob/blob_data_builder.h" |
| 34 #include "storage/browser/blob/blob_storage_context.h" | 34 #include "storage/browser/blob/blob_storage_context.h" |
| 35 #include "storage/browser/database/database_util.h" | 35 #include "storage/browser/database/database_util.h" |
| 36 #include "storage/browser/quota/quota_manager_proxy.h" | 36 #include "storage/browser/quota/quota_manager_proxy.h" |
| 37 #include "storage/common/database/database_identifier.h" | 37 #include "storage/common/database/database_identifier.h" |
| 38 #include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabaseExc
eption.h" | 38 #include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabaseExc
eption.h" |
| 39 #include "url/gurl.h" | 39 #include "url/origin.h" |
| 40 | 40 |
| 41 using storage::DatabaseUtil; | 41 using storage::DatabaseUtil; |
| 42 using blink::WebIDBKey; | 42 using blink::WebIDBKey; |
| 43 | 43 |
| 44 namespace content { | 44 namespace content { |
| 45 | 45 |
| 46 namespace { | 46 namespace { |
| 47 | 47 |
| 48 bool IsValidOrigin(const url::Origin& origin) { | 48 bool IsValidOrigin(const url::Origin& origin) { |
| 49 return !origin.unique(); | 49 return !origin.unique(); |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 173 | 173 |
| 174 int32_t IndexedDBDispatcherHost::Add(IndexedDBCursor* cursor) { | 174 int32_t IndexedDBDispatcherHost::Add(IndexedDBCursor* cursor) { |
| 175 if (!cursor_dispatcher_host_) { | 175 if (!cursor_dispatcher_host_) { |
| 176 return 0; | 176 return 0; |
| 177 } | 177 } |
| 178 return cursor_dispatcher_host_->map_.Add(cursor); | 178 return cursor_dispatcher_host_->map_.Add(cursor); |
| 179 } | 179 } |
| 180 | 180 |
| 181 int32_t IndexedDBDispatcherHost::Add(IndexedDBConnection* connection, | 181 int32_t IndexedDBDispatcherHost::Add(IndexedDBConnection* connection, |
| 182 int32_t ipc_thread_id, | 182 int32_t ipc_thread_id, |
| 183 const GURL& origin_url) { | 183 const url::Origin& origin) { |
| 184 if (!database_dispatcher_host_) { | 184 if (!database_dispatcher_host_) { |
| 185 connection->Close(); | 185 connection->Close(); |
| 186 delete connection; | 186 delete connection; |
| 187 return -1; | 187 return -1; |
| 188 } | 188 } |
| 189 int32_t ipc_database_id = database_dispatcher_host_->map_.Add(connection); | 189 int32_t ipc_database_id = database_dispatcher_host_->map_.Add(connection); |
| 190 context()->ConnectionOpened(origin_url, connection); | 190 context()->ConnectionOpened(origin, connection); |
| 191 database_dispatcher_host_->database_url_map_[ipc_database_id] = origin_url; | 191 database_dispatcher_host_->database_origin_map_[ipc_database_id] = origin; |
| 192 return ipc_database_id; | 192 return ipc_database_id; |
| 193 } | 193 } |
| 194 | 194 |
| 195 void IndexedDBDispatcherHost::RegisterTransactionId(int64_t host_transaction_id, | 195 void IndexedDBDispatcherHost::RegisterTransactionId(int64_t host_transaction_id, |
| 196 const GURL& url) { | 196 const url::Origin& origin) { |
| 197 if (!database_dispatcher_host_) | 197 if (!database_dispatcher_host_) |
| 198 return; | 198 return; |
| 199 database_dispatcher_host_->transaction_size_map_[host_transaction_id] = 0; | 199 database_dispatcher_host_->transaction_size_map_[host_transaction_id] = 0; |
| 200 database_dispatcher_host_->transaction_url_map_[host_transaction_id] = url; | 200 database_dispatcher_host_->transaction_origin_map_[host_transaction_id] = |
| 201 origin; |
| 201 } | 202 } |
| 202 | 203 |
| 203 int64_t IndexedDBDispatcherHost::HostTransactionId(int64_t transaction_id) { | 204 int64_t IndexedDBDispatcherHost::HostTransactionId(int64_t transaction_id) { |
| 204 // Inject the renderer process id into the transaction id, to | 205 // Inject the renderer process id into the transaction id, to |
| 205 // uniquely identify this transaction, and effectively bind it to | 206 // uniquely identify this transaction, and effectively bind it to |
| 206 // the renderer that initiated it. The lower 32 bits of | 207 // the renderer that initiated it. The lower 32 bits of |
| 207 // transaction_id are guaranteed to be unique within that renderer. | 208 // transaction_id are guaranteed to be unique within that renderer. |
| 208 base::ProcessId pid = peer_pid(); | 209 base::ProcessId pid = peer_pid(); |
| 209 DCHECK(!(transaction_id >> 32)) << "Transaction ids can only be 32 bits"; | 210 DCHECK(!(transaction_id >> 32)) << "Transaction ids can only be 32 bits"; |
| 210 static_assert(sizeof(base::ProcessId) <= sizeof(int32_t), | 211 static_assert(sizeof(base::ProcessId) <= sizeof(int32_t), |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 342 | 343 |
| 343 base::TimeTicks begin_time = base::TimeTicks::Now(); | 344 base::TimeTicks begin_time = base::TimeTicks::Now(); |
| 344 base::FilePath indexed_db_path = indexed_db_context_->data_path(); | 345 base::FilePath indexed_db_path = indexed_db_context_->data_path(); |
| 345 | 346 |
| 346 int64_t host_transaction_id = HostTransactionId(params.transaction_id); | 347 int64_t host_transaction_id = HostTransactionId(params.transaction_id); |
| 347 | 348 |
| 348 // TODO(dgrogan): Don't let a non-existing database be opened (and therefore | 349 // TODO(dgrogan): Don't let a non-existing database be opened (and therefore |
| 349 // created) if this origin is already over quota. | 350 // created) if this origin is already over quota. |
| 350 scoped_refptr<IndexedDBCallbacks> callbacks = new IndexedDBCallbacks( | 351 scoped_refptr<IndexedDBCallbacks> callbacks = new IndexedDBCallbacks( |
| 351 this, params.ipc_thread_id, params.ipc_callbacks_id, | 352 this, params.ipc_thread_id, params.ipc_callbacks_id, |
| 352 params.ipc_database_callbacks_id, host_transaction_id, | 353 params.ipc_database_callbacks_id, host_transaction_id, params.origin); |
| 353 GURL(params.origin.Serialize())); | |
| 354 callbacks->SetConnectionOpenStartTime(begin_time); | 354 callbacks->SetConnectionOpenStartTime(begin_time); |
| 355 scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks = | 355 scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks = |
| 356 new IndexedDBDatabaseCallbacks( | 356 new IndexedDBDatabaseCallbacks( |
| 357 this, params.ipc_thread_id, params.ipc_database_callbacks_id); | 357 this, params.ipc_thread_id, params.ipc_database_callbacks_id); |
| 358 IndexedDBPendingConnection connection(callbacks, | 358 IndexedDBPendingConnection connection(callbacks, |
| 359 database_callbacks, | 359 database_callbacks, |
| 360 ipc_process_id_, | 360 ipc_process_id_, |
| 361 host_transaction_id, | 361 host_transaction_id, |
| 362 params.version); | 362 params.version); |
| 363 DCHECK(request_context_); | 363 DCHECK(request_context_); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 396 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 396 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 397 for (const auto& uuid : uuids) | 397 for (const auto& uuid : uuids) |
| 398 DropBlobData(uuid); | 398 DropBlobData(uuid); |
| 399 } | 399 } |
| 400 | 400 |
| 401 void IndexedDBDispatcherHost::FinishTransaction(int64_t host_transaction_id, | 401 void IndexedDBDispatcherHost::FinishTransaction(int64_t host_transaction_id, |
| 402 bool committed) { | 402 bool committed) { |
| 403 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | 403 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); |
| 404 if (!database_dispatcher_host_) | 404 if (!database_dispatcher_host_) |
| 405 return; | 405 return; |
| 406 TransactionIDToURLMap& transaction_url_map = | 406 TransactionIDToOriginMap& transaction_origin_map = |
| 407 database_dispatcher_host_->transaction_url_map_; | 407 database_dispatcher_host_->transaction_origin_map_; |
| 408 TransactionIDToSizeMap& transaction_size_map = | 408 TransactionIDToSizeMap& transaction_size_map = |
| 409 database_dispatcher_host_->transaction_size_map_; | 409 database_dispatcher_host_->transaction_size_map_; |
| 410 TransactionIDToDatabaseIDMap& transaction_database_map = | 410 TransactionIDToDatabaseIDMap& transaction_database_map = |
| 411 database_dispatcher_host_->transaction_database_map_; | 411 database_dispatcher_host_->transaction_database_map_; |
| 412 if (committed) | 412 if (committed) |
| 413 context()->TransactionComplete(transaction_url_map[host_transaction_id]); | 413 context()->TransactionComplete(transaction_origin_map[host_transaction_id]); |
| 414 transaction_url_map.erase(host_transaction_id); | 414 transaction_origin_map.erase(host_transaction_id); |
| 415 transaction_size_map.erase(host_transaction_id); | 415 transaction_size_map.erase(host_transaction_id); |
| 416 transaction_database_map.erase(host_transaction_id); | 416 transaction_database_map.erase(host_transaction_id); |
| 417 } | 417 } |
| 418 | 418 |
| 419 ////////////////////////////////////////////////////////////////////// | 419 ////////////////////////////////////////////////////////////////////// |
| 420 // Helper templates. | 420 // Helper templates. |
| 421 // | 421 // |
| 422 | 422 |
| 423 template <typename ObjectType> | 423 template <typename ObjectType> |
| 424 ObjectType* IndexedDBDispatcherHost::GetOrTerminateProcess( | 424 ObjectType* IndexedDBDispatcherHost::GetOrTerminateProcess( |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 461 | 461 |
| 462 IndexedDBDispatcherHost::DatabaseDispatcherHost::DatabaseDispatcherHost( | 462 IndexedDBDispatcherHost::DatabaseDispatcherHost::DatabaseDispatcherHost( |
| 463 IndexedDBDispatcherHost* parent) | 463 IndexedDBDispatcherHost* parent) |
| 464 : parent_(parent), weak_factory_(this) { | 464 : parent_(parent), weak_factory_(this) { |
| 465 map_.set_check_on_null_data(true); | 465 map_.set_check_on_null_data(true); |
| 466 } | 466 } |
| 467 | 467 |
| 468 IndexedDBDispatcherHost::DatabaseDispatcherHost::~DatabaseDispatcherHost() { | 468 IndexedDBDispatcherHost::DatabaseDispatcherHost::~DatabaseDispatcherHost() { |
| 469 // TODO(alecflett): uncomment these when we find the source of these leaks. | 469 // TODO(alecflett): uncomment these when we find the source of these leaks. |
| 470 // DCHECK(transaction_size_map_.empty()); | 470 // DCHECK(transaction_size_map_.empty()); |
| 471 // DCHECK(transaction_url_map_.empty()); | 471 // DCHECK(transaction_origin_map_.empty()); |
| 472 } | 472 } |
| 473 | 473 |
| 474 void IndexedDBDispatcherHost::DatabaseDispatcherHost::CloseAll() { | 474 void IndexedDBDispatcherHost::DatabaseDispatcherHost::CloseAll() { |
| 475 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread()); | 475 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread()); |
| 476 // Abort outstanding transactions started by connections in the associated | 476 // Abort outstanding transactions started by connections in the associated |
| 477 // front-end to unblock later transactions. This should only occur on unclean | 477 // front-end to unblock later transactions. This should only occur on unclean |
| 478 // (crash) or abrupt (process-kill) shutdowns. | 478 // (crash) or abrupt (process-kill) shutdowns. |
| 479 for (TransactionIDToDatabaseIDMap::iterator iter = | 479 for (TransactionIDToDatabaseIDMap::iterator iter = |
| 480 transaction_database_map_.begin(); | 480 transaction_database_map_.begin(); |
| 481 iter != transaction_database_map_.end();) { | 481 iter != transaction_database_map_.end();) { |
| 482 int64_t transaction_id = iter->first; | 482 int64_t transaction_id = iter->first; |
| 483 int32_t ipc_database_id = iter->second; | 483 int32_t ipc_database_id = iter->second; |
| 484 ++iter; | 484 ++iter; |
| 485 IndexedDBConnection* connection = map_.Lookup(ipc_database_id); | 485 IndexedDBConnection* connection = map_.Lookup(ipc_database_id); |
| 486 if (connection && connection->IsConnected()) { | 486 if (connection && connection->IsConnected()) { |
| 487 connection->database()->Abort( | 487 connection->database()->Abort( |
| 488 transaction_id, | 488 transaction_id, |
| 489 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError)); | 489 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError)); |
| 490 } | 490 } |
| 491 } | 491 } |
| 492 DCHECK(transaction_database_map_.empty()); | 492 DCHECK(transaction_database_map_.empty()); |
| 493 | 493 |
| 494 for (const auto& iter : database_url_map_) { | 494 for (const auto& iter : database_origin_map_) { |
| 495 IndexedDBConnection* connection = map_.Lookup(iter.first); | 495 IndexedDBConnection* connection = map_.Lookup(iter.first); |
| 496 if (connection && connection->IsConnected()) { | 496 if (connection && connection->IsConnected()) { |
| 497 connection->Close(); | 497 connection->Close(); |
| 498 parent_->context()->ConnectionClosed(iter.second, connection); | 498 parent_->context()->ConnectionClosed(iter.second, connection); |
| 499 } | 499 } |
| 500 } | 500 } |
| 501 } | 501 } |
| 502 | 502 |
| 503 bool IndexedDBDispatcherHost::DatabaseDispatcherHost::OnMessageReceived( | 503 bool IndexedDBDispatcherHost::DatabaseDispatcherHost::OnMessageReceived( |
| 504 const IPC::Message& message) { | 504 const IPC::Message& message) { |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 583 | 583 |
| 584 if (ContainsKey(transaction_database_map_, host_transaction_id)) { | 584 if (ContainsKey(transaction_database_map_, host_transaction_id)) { |
| 585 DLOG(ERROR) << "Duplicate host_transaction_id."; | 585 DLOG(ERROR) << "Duplicate host_transaction_id."; |
| 586 return; | 586 return; |
| 587 } | 587 } |
| 588 | 588 |
| 589 connection->database()->CreateTransaction( | 589 connection->database()->CreateTransaction( |
| 590 host_transaction_id, connection, params.object_store_ids, params.mode); | 590 host_transaction_id, connection, params.object_store_ids, params.mode); |
| 591 transaction_database_map_[host_transaction_id] = params.ipc_database_id; | 591 transaction_database_map_[host_transaction_id] = params.ipc_database_id; |
| 592 parent_->RegisterTransactionId(host_transaction_id, | 592 parent_->RegisterTransactionId(host_transaction_id, |
| 593 database_url_map_[params.ipc_database_id]); | 593 database_origin_map_[params.ipc_database_id]); |
| 594 } | 594 } |
| 595 | 595 |
| 596 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnClose( | 596 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnClose( |
| 597 int32_t ipc_database_id) { | 597 int32_t ipc_database_id) { |
| 598 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread()); | 598 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread()); |
| 599 IndexedDBConnection* connection = | 599 IndexedDBConnection* connection = |
| 600 parent_->GetOrTerminateProcess(&map_, ipc_database_id); | 600 parent_->GetOrTerminateProcess(&map_, ipc_database_id); |
| 601 if (!connection || !connection->IsConnected()) | 601 if (!connection || !connection->IsConnected()) |
| 602 return; | 602 return; |
| 603 connection->Close(); | 603 connection->Close(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 615 | 615 |
| 616 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnDestroyed( | 616 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnDestroyed( |
| 617 int32_t ipc_object_id) { | 617 int32_t ipc_object_id) { |
| 618 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread()); | 618 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread()); |
| 619 IndexedDBConnection* connection = | 619 IndexedDBConnection* connection = |
| 620 parent_->GetOrTerminateProcess(&map_, ipc_object_id); | 620 parent_->GetOrTerminateProcess(&map_, ipc_object_id); |
| 621 if (!connection) | 621 if (!connection) |
| 622 return; | 622 return; |
| 623 if (connection->IsConnected()) | 623 if (connection->IsConnected()) |
| 624 connection->Close(); | 624 connection->Close(); |
| 625 parent_->context()->ConnectionClosed(database_url_map_[ipc_object_id], | 625 parent_->context()->ConnectionClosed(database_origin_map_[ipc_object_id], |
| 626 connection); | 626 connection); |
| 627 database_url_map_.erase(ipc_object_id); | 627 database_origin_map_.erase(ipc_object_id); |
| 628 parent_->DestroyObject(&map_, ipc_object_id); | 628 parent_->DestroyObject(&map_, ipc_object_id); |
| 629 } | 629 } |
| 630 | 630 |
| 631 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnGet( | 631 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnGet( |
| 632 const IndexedDBHostMsg_DatabaseGet_Params& params) { | 632 const IndexedDBHostMsg_DatabaseGet_Params& params) { |
| 633 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread()); | 633 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread()); |
| 634 IndexedDBConnection* connection = | 634 IndexedDBConnection* connection = |
| 635 parent_->GetOrTerminateProcess(&map_, params.ipc_database_id); | 635 parent_->GetOrTerminateProcess(&map_, params.ipc_database_id); |
| 636 if (!connection || !connection->IsConnected()) | 636 if (!connection || !connection->IsConnected()) |
| 637 return; | 637 return; |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 877 int64_t transaction_size = transaction_size_map_[host_transaction_id]; | 877 int64_t transaction_size = transaction_size_map_[host_transaction_id]; |
| 878 | 878 |
| 879 // Always allow empty or delete-only transactions. | 879 // Always allow empty or delete-only transactions. |
| 880 if (!transaction_size) { | 880 if (!transaction_size) { |
| 881 connection->database()->Commit(host_transaction_id); | 881 connection->database()->Commit(host_transaction_id); |
| 882 return; | 882 return; |
| 883 } | 883 } |
| 884 | 884 |
| 885 parent_->context()->quota_manager_proxy()->GetUsageAndQuota( | 885 parent_->context()->quota_manager_proxy()->GetUsageAndQuota( |
| 886 parent_->context()->TaskRunner(), | 886 parent_->context()->TaskRunner(), |
| 887 transaction_url_map_[host_transaction_id], storage::kStorageTypeTemporary, | 887 GURL(transaction_origin_map_[host_transaction_id].Serialize()), |
| 888 storage::kStorageTypeTemporary, |
| 888 base::Bind(&IndexedDBDispatcherHost::DatabaseDispatcherHost:: | 889 base::Bind(&IndexedDBDispatcherHost::DatabaseDispatcherHost:: |
| 889 OnGotUsageAndQuotaForCommit, | 890 OnGotUsageAndQuotaForCommit, |
| 890 weak_factory_.GetWeakPtr(), ipc_database_id, transaction_id)); | 891 weak_factory_.GetWeakPtr(), ipc_database_id, transaction_id)); |
| 891 } | 892 } |
| 892 | 893 |
| 893 void IndexedDBDispatcherHost::DatabaseDispatcherHost:: | 894 void IndexedDBDispatcherHost::DatabaseDispatcherHost:: |
| 894 OnGotUsageAndQuotaForCommit(int32_t ipc_database_id, | 895 OnGotUsageAndQuotaForCommit(int32_t ipc_database_id, |
| 895 int64_t transaction_id, | 896 int64_t transaction_id, |
| 896 storage::QuotaStatusCode status, | 897 storage::QuotaStatusCode status, |
| 897 int64_t usage, | 898 int64_t usage, |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1054 DLOG(ERROR) << "Unable to reset prefetch"; | 1055 DLOG(ERROR) << "Unable to reset prefetch"; |
| 1055 } | 1056 } |
| 1056 | 1057 |
| 1057 void IndexedDBDispatcherHost::CursorDispatcherHost::OnDestroyed( | 1058 void IndexedDBDispatcherHost::CursorDispatcherHost::OnDestroyed( |
| 1058 int32_t ipc_object_id) { | 1059 int32_t ipc_object_id) { |
| 1059 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread()); | 1060 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread()); |
| 1060 parent_->DestroyObject(&map_, ipc_object_id); | 1061 parent_->DestroyObject(&map_, ipc_object_id); |
| 1061 } | 1062 } |
| 1062 | 1063 |
| 1063 } // namespace content | 1064 } // namespace content |
| OLD | NEW |