Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/database_impl.h" | 5 #include "content/browser/indexed_db/database_impl.h" |
| 6 | 6 |
| 7 #include "base/memory/ptr_util.h" | 7 #include "base/memory/ptr_util.h" |
| 8 #include "base/metrics/histogram_macros.h" | |
| 8 #include "base/threading/thread_task_runner_handle.h" | 9 #include "base/threading/thread_task_runner_handle.h" |
| 9 #include "content/browser/bad_message.h" | 10 #include "content/browser/bad_message.h" |
| 10 #include "content/browser/child_process_security_policy_impl.h" | 11 #include "content/browser/child_process_security_policy_impl.h" |
| 11 #include "content/browser/indexed_db/indexed_db_connection.h" | 12 #include "content/browser/indexed_db/indexed_db_connection.h" |
| 12 #include "content/browser/indexed_db/indexed_db_context_impl.h" | 13 #include "content/browser/indexed_db/indexed_db_context_impl.h" |
| 13 #include "content/browser/indexed_db/indexed_db_dispatcher_host.h" | 14 #include "content/browser/indexed_db/indexed_db_dispatcher_host.h" |
| 14 #include "content/browser/indexed_db/indexed_db_transaction.h" | 15 #include "content/browser/indexed_db/indexed_db_transaction.h" |
| 15 #include "content/browser/indexed_db/indexed_db_value.h" | 16 #include "content/browser/indexed_db/indexed_db_value.h" |
| 16 #include "storage/browser/blob/blob_storage_context.h" | 17 #include "storage/browser/blob/blob_storage_context.h" |
| 17 #include "storage/browser/quota/quota_manager_proxy.h" | 18 #include "storage/browser/quota/quota_manager_proxy.h" |
| 18 #include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabaseExc eption.h" | 19 #include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabaseExc eption.h" |
| 19 | 20 |
| 20 using std::swap; | 21 using std::swap; |
| 21 | 22 |
| 22 namespace content { | 23 namespace content { |
| 24 class IndexedDBDatabaseError; | |
| 23 | 25 |
| 24 namespace { | 26 namespace { |
| 25 const char kInvalidBlobUuid[] = "Blob UUID is invalid"; | 27 const char kInvalidBlobUuid[] = "Blob does not exist"; |
| 26 const char kInvalidBlobFilePath[] = "Blob file path is invalid"; | 28 const char kInvalidBlobFilePath[] = "Blob file path is invalid"; |
| 27 } // namespace | 29 } // namespace |
| 28 | 30 |
| 29 class DatabaseImpl::IDBThreadHelper { | 31 class DatabaseImpl::IDBThreadHelper { |
| 30 public: | 32 public: |
| 31 IDBThreadHelper(std::unique_ptr<IndexedDBConnection> connection, | 33 IDBThreadHelper(std::unique_ptr<IndexedDBConnection> connection, |
| 32 const url::Origin& origin, | 34 const url::Origin& origin, |
| 33 scoped_refptr<IndexedDBDispatcherHost> dispatcher_host); | 35 scoped_refptr<IndexedDBDispatcherHost> dispatcher_host); |
| 34 ~IDBThreadHelper(); | 36 ~IDBThreadHelper(); |
| 35 | 37 |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 111 bool unique, | 113 bool unique, |
| 112 bool multi_entry); | 114 bool multi_entry); |
| 113 void DeleteIndex(int64_t transaction_id, | 115 void DeleteIndex(int64_t transaction_id, |
| 114 int64_t object_store_id, | 116 int64_t object_store_id, |
| 115 int64_t index_id); | 117 int64_t index_id); |
| 116 void RenameIndex(int64_t transaction_id, | 118 void RenameIndex(int64_t transaction_id, |
| 117 int64_t object_store_id, | 119 int64_t object_store_id, |
| 118 int64_t index_id, | 120 int64_t index_id, |
| 119 const base::string16& new_name); | 121 const base::string16& new_name); |
| 120 void Abort(int64_t transaction_id); | 122 void Abort(int64_t transaction_id); |
| 123 void AbortWithError(int64_t transaction_id, | |
| 124 const IndexedDBDatabaseError& error); | |
| 121 void Commit(int64_t transaction_id); | 125 void Commit(int64_t transaction_id); |
| 122 void OnGotUsageAndQuotaForCommit(int64_t transaction_id, | 126 void OnGotUsageAndQuotaForCommit(int64_t transaction_id, |
| 123 storage::QuotaStatusCode status, | 127 storage::QuotaStatusCode status, |
| 124 int64_t usage, | 128 int64_t usage, |
| 125 int64_t quota); | 129 int64_t quota); |
| 126 void AckReceivedBlobs(const std::vector<std::string>& uuids); | 130 void AckReceivedBlobs(const std::vector<std::string>& uuids); |
| 127 | 131 |
| 128 private: | 132 private: |
| 129 scoped_refptr<IndexedDBDispatcherHost> dispatcher_host_; | 133 scoped_refptr<IndexedDBDispatcherHost> dispatcher_host_; |
| 130 std::unique_ptr<IndexedDBConnection> connection_; | 134 std::unique_ptr<IndexedDBConnection> connection_; |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 251 int64_t transaction_id, | 255 int64_t transaction_id, |
| 252 int64_t object_store_id, | 256 int64_t object_store_id, |
| 253 ::indexed_db::mojom::ValuePtr value, | 257 ::indexed_db::mojom::ValuePtr value, |
| 254 const IndexedDBKey& key, | 258 const IndexedDBKey& key, |
| 255 blink::WebIDBPutMode mode, | 259 blink::WebIDBPutMode mode, |
| 256 const std::vector<IndexedDBIndexKeys>& index_keys, | 260 const std::vector<IndexedDBIndexKeys>& index_keys, |
| 257 ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks_info) { | 261 ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks_info) { |
| 258 ChildProcessSecurityPolicyImpl* policy = | 262 ChildProcessSecurityPolicyImpl* policy = |
| 259 ChildProcessSecurityPolicyImpl::GetInstance(); | 263 ChildProcessSecurityPolicyImpl::GetInstance(); |
| 260 | 264 |
| 265 scoped_refptr<IndexedDBCallbacks> callbacks(new IndexedDBCallbacks( | |
| 266 dispatcher_host_.get(), origin_, std::move(callbacks_info))); | |
| 267 | |
| 261 std::vector<std::unique_ptr<storage::BlobDataHandle>> handles( | 268 std::vector<std::unique_ptr<storage::BlobDataHandle>> handles( |
| 262 value->blob_or_file_info.size()); | 269 value->blob_or_file_info.size()); |
| 263 std::vector<IndexedDBBlobInfo> blob_info(value->blob_or_file_info.size()); | 270 std::vector<IndexedDBBlobInfo> blob_info(value->blob_or_file_info.size()); |
| 264 for (size_t i = 0; i < value->blob_or_file_info.size(); ++i) { | 271 for (size_t i = 0; i < value->blob_or_file_info.size(); ++i) { |
| 265 ::indexed_db::mojom::BlobInfoPtr& info = value->blob_or_file_info[i]; | 272 ::indexed_db::mojom::BlobInfoPtr& info = value->blob_or_file_info[i]; |
| 266 | 273 |
| 267 std::unique_ptr<storage::BlobDataHandle> handle = | 274 std::unique_ptr<storage::BlobDataHandle> handle = |
| 268 dispatcher_host_->blob_storage_context()->GetBlobDataFromUUID( | 275 dispatcher_host_->blob_storage_context()->GetBlobDataFromUUID( |
| 269 info->uuid); | 276 info->uuid); |
| 277 | |
| 278 // Due to known issue crbug.com/351753, blobs can die while being passed to | |
| 279 // a different process. So this case must be handled gracefully. | |
| 280 UMA_HISTOGRAM_BOOLEAN("Storage.IndexedDB.PutValidBlob", !!handle); | |
|
Mark P
2017/03/28 18:17:07
nit: !!handle looks ugly to me. Can you rewrite i
dmurph
2017/03/29 18:21:34
Done.
| |
| 270 if (!handle) { | 281 if (!handle) { |
| 271 mojo::ReportBadMessage(kInvalidBlobUuid); | 282 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, |
|
cmumford
2017/03/28 18:49:31
We do want to go back to using mojo::ReportBadMess
dmurph
2017/03/29 18:21:34
Done.
| |
| 283 kInvalidBlobUuid); | |
| 284 idb_runner_->PostTask(FROM_HERE, base::Bind(&IndexedDBCallbacks::OnError, | |
| 285 callbacks, error)); | |
| 286 idb_runner_->PostTask( | |
| 287 FROM_HERE, | |
| 288 base::Bind(&IDBThreadHelper::AbortWithError, | |
| 289 base::Unretained(helper_), transaction_id, error)); | |
| 272 return; | 290 return; |
| 273 } | 291 } |
| 292 UMA_HISTOGRAM_COUNTS("Storage.IndexedDB.PutBlobSizeKB", | |
|
Mark P
2017/03/28 18:17:07
Why not UMA_HISTOGRAM_MEMORY_KB?
dmurph
2017/03/29 18:21:34
sgtm
| |
| 293 handle->size() / 1024ull); | |
| 294 | |
| 274 handles[i] = std::move(handle); | 295 handles[i] = std::move(handle); |
| 275 | 296 |
| 276 if (info->file) { | 297 if (info->file) { |
| 277 if (!info->file->path.empty() && | 298 if (!info->file->path.empty() && |
| 278 !policy->CanReadFile(dispatcher_host_->ipc_process_id(), | 299 !policy->CanReadFile(dispatcher_host_->ipc_process_id(), |
| 279 info->file->path)) { | 300 info->file->path)) { |
| 280 mojo::ReportBadMessage(kInvalidBlobFilePath); | 301 mojo::ReportBadMessage(kInvalidBlobFilePath); |
| 281 return; | 302 return; |
| 282 } | 303 } |
| 283 blob_info[i] = IndexedDBBlobInfo(info->uuid, info->file->path, | 304 blob_info[i] = IndexedDBBlobInfo(info->uuid, info->file->path, |
| 284 info->file->name, info->mime_type); | 305 info->file->name, info->mime_type); |
| 285 if (info->size != -1) { | 306 if (info->size != -1) { |
| 286 blob_info[i].set_last_modified(info->file->last_modified); | 307 blob_info[i].set_last_modified(info->file->last_modified); |
| 287 blob_info[i].set_size(info->size); | 308 blob_info[i].set_size(info->size); |
| 288 } | 309 } |
| 289 } else { | 310 } else { |
| 290 blob_info[i] = IndexedDBBlobInfo(info->uuid, info->mime_type, info->size); | 311 blob_info[i] = IndexedDBBlobInfo(info->uuid, info->mime_type, info->size); |
| 291 } | 312 } |
| 292 } | 313 } |
| 293 | 314 |
| 294 scoped_refptr<IndexedDBCallbacks> callbacks(new IndexedDBCallbacks( | |
| 295 dispatcher_host_.get(), origin_, std::move(callbacks_info))); | |
| 296 | |
| 297 idb_runner_->PostTask( | 315 idb_runner_->PostTask( |
| 298 FROM_HERE, | 316 FROM_HERE, |
| 299 base::Bind(&IDBThreadHelper::Put, base::Unretained(helper_), | 317 base::Bind(&IDBThreadHelper::Put, base::Unretained(helper_), |
| 300 transaction_id, object_store_id, base::Passed(&value), | 318 transaction_id, object_store_id, base::Passed(&value), |
| 301 base::Passed(&handles), base::Passed(&blob_info), key, mode, | 319 base::Passed(&handles), base::Passed(&blob_info), key, mode, |
| 302 index_keys, base::Passed(&callbacks))); | 320 index_keys, base::Passed(&callbacks))); |
| 303 } | 321 } |
| 304 | 322 |
| 305 void DatabaseImpl::SetIndexKeys( | 323 void DatabaseImpl::SetIndexKeys( |
| 306 int64_t transaction_id, | 324 int64_t transaction_id, |
| (...skipping 478 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 785 return; | 803 return; |
| 786 | 804 |
| 787 IndexedDBTransaction* transaction = | 805 IndexedDBTransaction* transaction = |
| 788 connection_->GetTransaction(transaction_id); | 806 connection_->GetTransaction(transaction_id); |
| 789 if (!transaction) | 807 if (!transaction) |
| 790 return; | 808 return; |
| 791 | 809 |
| 792 connection_->AbortTransaction(transaction); | 810 connection_->AbortTransaction(transaction); |
| 793 } | 811 } |
| 794 | 812 |
| 813 void DatabaseImpl::IDBThreadHelper::AbortWithError( | |
| 814 int64_t transaction_id, | |
| 815 const IndexedDBDatabaseError& error) { | |
| 816 if (!connection_->IsConnected()) | |
| 817 return; | |
| 818 | |
| 819 IndexedDBTransaction* transaction = | |
| 820 connection_->GetTransaction(transaction_id); | |
| 821 if (!transaction) | |
| 822 return; | |
| 823 | |
| 824 connection_->AbortTransaction(transaction, error); | |
| 825 } | |
| 826 | |
| 795 void DatabaseImpl::IDBThreadHelper::Commit(int64_t transaction_id) { | 827 void DatabaseImpl::IDBThreadHelper::Commit(int64_t transaction_id) { |
| 796 if (!connection_->IsConnected()) | 828 if (!connection_->IsConnected()) |
| 797 return; | 829 return; |
| 798 | 830 |
| 799 IndexedDBTransaction* transaction = | 831 IndexedDBTransaction* transaction = |
| 800 connection_->GetTransaction(transaction_id); | 832 connection_->GetTransaction(transaction_id); |
| 801 if (!transaction) | 833 if (!transaction) |
| 802 return; | 834 return; |
| 803 | 835 |
| 804 // Always allow empty or delete-only transactions. | 836 // Always allow empty or delete-only transactions. |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 832 usage + transaction->size() <= quota) { | 864 usage + transaction->size() <= quota) { |
| 833 connection_->database()->Commit(transaction); | 865 connection_->database()->Commit(transaction); |
| 834 } else { | 866 } else { |
| 835 connection_->AbortTransaction( | 867 connection_->AbortTransaction( |
| 836 transaction, | 868 transaction, |
| 837 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionQuotaError)); | 869 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionQuotaError)); |
| 838 } | 870 } |
| 839 } | 871 } |
| 840 | 872 |
| 841 } // namespace content | 873 } // namespace content |
| OLD | NEW |