| 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/metrics/histogram_macros.h" |
| 9 #include "base/numerics/safe_math.h" |
| 9 #include "base/sequenced_task_runner.h" | 10 #include "base/sequenced_task_runner.h" |
| 10 #include "base/threading/thread_checker.h" | 11 #include "base/threading/thread_checker.h" |
| 11 #include "base/threading/thread_task_runner_handle.h" | 12 #include "base/threading/thread_task_runner_handle.h" |
| 12 #include "content/browser/bad_message.h" | 13 #include "content/browser/bad_message.h" |
| 13 #include "content/browser/child_process_security_policy_impl.h" | 14 #include "content/browser/child_process_security_policy_impl.h" |
| 14 #include "content/browser/indexed_db/indexed_db_connection.h" | 15 #include "content/browser/indexed_db/indexed_db_connection.h" |
| 15 #include "content/browser/indexed_db/indexed_db_context_impl.h" | 16 #include "content/browser/indexed_db/indexed_db_context_impl.h" |
| 16 #include "content/browser/indexed_db/indexed_db_dispatcher_host.h" | 17 #include "content/browser/indexed_db/indexed_db_dispatcher_host.h" |
| 17 #include "content/browser/indexed_db/indexed_db_transaction.h" | 18 #include "content/browser/indexed_db/indexed_db_transaction.h" |
| 18 #include "content/browser/indexed_db/indexed_db_value.h" | 19 #include "content/browser/indexed_db/indexed_db_value.h" |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 274 ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks_info) { | 275 ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks_info) { |
| 275 ChildProcessSecurityPolicyImpl* policy = | 276 ChildProcessSecurityPolicyImpl* policy = |
| 276 ChildProcessSecurityPolicyImpl::GetInstance(); | 277 ChildProcessSecurityPolicyImpl::GetInstance(); |
| 277 | 278 |
| 278 scoped_refptr<IndexedDBCallbacks> callbacks( | 279 scoped_refptr<IndexedDBCallbacks> callbacks( |
| 279 new IndexedDBCallbacks(dispatcher_host_->AsWeakPtr(), origin_, | 280 new IndexedDBCallbacks(dispatcher_host_->AsWeakPtr(), origin_, |
| 280 std::move(callbacks_info), idb_runner_)); | 281 std::move(callbacks_info), idb_runner_)); |
| 281 | 282 |
| 282 std::vector<std::unique_ptr<storage::BlobDataHandle>> handles( | 283 std::vector<std::unique_ptr<storage::BlobDataHandle>> handles( |
| 283 value->blob_or_file_info.size()); | 284 value->blob_or_file_info.size()); |
| 285 base::CheckedNumeric<uint64_t> total_blob_size = 0; |
| 284 std::vector<IndexedDBBlobInfo> blob_info(value->blob_or_file_info.size()); | 286 std::vector<IndexedDBBlobInfo> blob_info(value->blob_or_file_info.size()); |
| 285 for (size_t i = 0; i < value->blob_or_file_info.size(); ++i) { | 287 for (size_t i = 0; i < value->blob_or_file_info.size(); ++i) { |
| 286 ::indexed_db::mojom::BlobInfoPtr& info = value->blob_or_file_info[i]; | 288 ::indexed_db::mojom::BlobInfoPtr& info = value->blob_or_file_info[i]; |
| 287 | 289 |
| 288 std::unique_ptr<storage::BlobDataHandle> handle = | 290 std::unique_ptr<storage::BlobDataHandle> handle = |
| 289 dispatcher_host_->blob_storage_context()->GetBlobDataFromUUID( | 291 dispatcher_host_->blob_storage_context()->GetBlobDataFromUUID( |
| 290 info->uuid); | 292 info->uuid); |
| 291 | 293 |
| 292 // Due to known issue crbug.com/351753, blobs can die while being passed to | 294 // Due to known issue crbug.com/351753, blobs can die while being passed to |
| 293 // a different process. So this case must be handled gracefully. | 295 // a different process. So this case must be handled gracefully. |
| 294 // TODO(dmurph): Revert back to using mojo::ReportBadMessage once fixed. | 296 // TODO(dmurph): Revert back to using mojo::ReportBadMessage once fixed. |
| 295 UMA_HISTOGRAM_BOOLEAN("Storage.IndexedDB.PutValidBlob", | 297 UMA_HISTOGRAM_BOOLEAN("Storage.IndexedDB.PutValidBlob", |
| 296 handle.get() != nullptr); | 298 handle.get() != nullptr); |
| 297 if (!handle) { | 299 if (!handle) { |
| 298 IndexedDBDatabaseError error(blink::kWebIDBDatabaseExceptionUnknownError, | 300 IndexedDBDatabaseError error(blink::kWebIDBDatabaseExceptionUnknownError, |
| 299 kInvalidBlobUuid); | 301 kInvalidBlobUuid); |
| 300 idb_runner_->PostTask( | 302 idb_runner_->PostTask( |
| 301 FROM_HERE, base::Bind(&IDBThreadHelper::AbortWithError, | 303 FROM_HERE, base::Bind(&IDBThreadHelper::AbortWithError, |
| 302 base::Unretained(helper_), transaction_id, | 304 base::Unretained(helper_), transaction_id, |
| 303 base::Passed(&callbacks), error)); | 305 base::Passed(&callbacks), error)); |
| 304 return; | 306 return; |
| 305 } | 307 } |
| 306 UMA_HISTOGRAM_MEMORY_KB("Storage.IndexedDB.PutBlobSizeKB", | 308 uint64_t size = handle->size(); |
| 307 handle->size() / 1024ull); | 309 UMA_HISTOGRAM_MEMORY_KB("Storage.IndexedDB.PutBlobSizeKB", size / 1024ull); |
| 308 | 310 total_blob_size += size; |
| 309 handles[i] = std::move(handle); | 311 handles[i] = std::move(handle); |
| 310 | 312 |
| 311 if (info->file) { | 313 if (info->file) { |
| 312 if (!info->file->path.empty() && | 314 if (!info->file->path.empty() && |
| 313 !policy->CanReadFile(dispatcher_host_->ipc_process_id(), | 315 !policy->CanReadFile(dispatcher_host_->ipc_process_id(), |
| 314 info->file->path)) { | 316 info->file->path)) { |
| 315 mojo::ReportBadMessage(kInvalidBlobFilePath); | 317 mojo::ReportBadMessage(kInvalidBlobFilePath); |
| 316 return; | 318 return; |
| 317 } | 319 } |
| 318 blob_info[i] = IndexedDBBlobInfo(info->uuid, info->file->path, | 320 blob_info[i] = IndexedDBBlobInfo(info->uuid, info->file->path, |
| 319 info->file->name, info->mime_type); | 321 info->file->name, info->mime_type); |
| 320 if (info->size != -1) { | 322 if (info->size != -1) { |
| 321 blob_info[i].set_last_modified(info->file->last_modified); | 323 blob_info[i].set_last_modified(info->file->last_modified); |
| 322 blob_info[i].set_size(info->size); | 324 blob_info[i].set_size(info->size); |
| 323 } | 325 } |
| 324 } else { | 326 } else { |
| 325 blob_info[i] = IndexedDBBlobInfo(info->uuid, info->mime_type, info->size); | 327 blob_info[i] = IndexedDBBlobInfo(info->uuid, info->mime_type, info->size); |
| 326 } | 328 } |
| 327 } | 329 } |
| 328 | 330 UMA_HISTOGRAM_COUNTS_1000("WebCore.IndexedDB.PutBlobsCount", |
| 331 blob_info.size()); |
| 332 uint64_t blob_size = 0; |
| 333 total_blob_size.AssignIfValid(&blob_size); |
| 334 if (blob_size != 0) { |
| 335 // 1KB to 1GB. |
| 336 UMA_HISTOGRAM_COUNTS_1M("WebCore.IndexedDB.PutBlobsTotalSize", |
| 337 blob_size / 1024); |
| 338 } |
| 329 idb_runner_->PostTask( | 339 idb_runner_->PostTask( |
| 330 FROM_HERE, | 340 FROM_HERE, |
| 331 base::Bind(&IDBThreadHelper::Put, base::Unretained(helper_), | 341 base::Bind(&IDBThreadHelper::Put, base::Unretained(helper_), |
| 332 transaction_id, object_store_id, base::Passed(&value), | 342 transaction_id, object_store_id, base::Passed(&value), |
| 333 base::Passed(&handles), base::Passed(&blob_info), key, mode, | 343 base::Passed(&handles), base::Passed(&blob_info), key, mode, |
| 334 index_keys, base::Passed(&callbacks))); | 344 index_keys, base::Passed(&callbacks))); |
| 335 } | 345 } |
| 336 | 346 |
| 337 void DatabaseImpl::SetIndexKeys( | 347 void DatabaseImpl::SetIndexKeys( |
| 338 int64_t transaction_id, | 348 int64_t transaction_id, |
| (...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 654 scoped_refptr<IndexedDBCallbacks> callbacks) { | 664 scoped_refptr<IndexedDBCallbacks> callbacks) { |
| 655 DCHECK(idb_thread_checker_.CalledOnValidThread()); | 665 DCHECK(idb_thread_checker_.CalledOnValidThread()); |
| 656 if (!connection_->IsConnected()) | 666 if (!connection_->IsConnected()) |
| 657 return; | 667 return; |
| 658 | 668 |
| 659 IndexedDBTransaction* transaction = | 669 IndexedDBTransaction* transaction = |
| 660 connection_->GetTransaction(transaction_id); | 670 connection_->GetTransaction(transaction_id); |
| 661 if (!transaction) | 671 if (!transaction) |
| 662 return; | 672 return; |
| 663 | 673 |
| 664 uint64_t commit_size = mojo_value->bits.size(); | 674 // Value size recorded in IDBObjectStore before we can auto-wrap in a blob. |
| 675 // 1KB to 10MB. |
| 676 UMA_HISTOGRAM_COUNTS_10000("WebCore.IndexedDB.PutKeySize", |
| 677 key.size_estimate() / 1024); |
| 678 |
| 679 uint64_t commit_size = mojo_value->bits.size() + key.size_estimate(); |
| 665 IndexedDBValue value; | 680 IndexedDBValue value; |
| 666 swap(value.bits, mojo_value->bits); | 681 swap(value.bits, mojo_value->bits); |
| 667 swap(value.blob_info, blob_info); | 682 swap(value.blob_info, blob_info); |
| 668 connection_->database()->Put(transaction, object_store_id, &value, &handles, | 683 connection_->database()->Put(transaction, object_store_id, &value, &handles, |
| 669 base::MakeUnique<IndexedDBKey>(key), mode, | 684 base::MakeUnique<IndexedDBKey>(key), mode, |
| 670 std::move(callbacks), index_keys); | 685 std::move(callbacks), index_keys); |
| 671 | 686 |
| 672 // Size can't be big enough to overflow because it represents the | 687 // Size can't be big enough to overflow because it represents the |
| 673 // actual bytes passed through IPC. | 688 // actual bytes passed through IPC. |
| 674 transaction->set_size(transaction->size() + commit_size); | 689 transaction->set_size(transaction->size() + commit_size); |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 916 usage + transaction->size() <= quota) { | 931 usage + transaction->size() <= quota) { |
| 917 connection_->database()->Commit(transaction); | 932 connection_->database()->Commit(transaction); |
| 918 } else { | 933 } else { |
| 919 connection_->AbortTransaction( | 934 connection_->AbortTransaction( |
| 920 transaction, | 935 transaction, |
| 921 IndexedDBDatabaseError(blink::kWebIDBDatabaseExceptionQuotaError)); | 936 IndexedDBDatabaseError(blink::kWebIDBDatabaseExceptionQuotaError)); |
| 922 } | 937 } |
| 923 } | 938 } |
| 924 | 939 |
| 925 } // namespace content | 940 } // namespace content |
| OLD | NEW |