| 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/blob_storage/blob_dispatcher_host.h" | 5 #include "content/browser/blob_storage/blob_dispatcher_host.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 44 | 44 |
| 45 const char kContentType[] = "text/plain"; | 45 const char kContentType[] = "text/plain"; |
| 46 const char kContentDisposition[] = "content_disposition"; | 46 const char kContentDisposition[] = "content_disposition"; |
| 47 const char kData[] = "data!!"; | 47 const char kData[] = "data!!"; |
| 48 const size_t kDataSize = 6; | 48 const size_t kDataSize = 6; |
| 49 | 49 |
| 50 const size_t kTestBlobStorageIPCThresholdBytes = 20; | 50 const size_t kTestBlobStorageIPCThresholdBytes = 20; |
| 51 const size_t kTestBlobStorageMaxSharedMemoryBytes = 50; | 51 const size_t kTestBlobStorageMaxSharedMemoryBytes = 50; |
| 52 const uint64_t kTestBlobStorageMaxFileSizeBytes = 100; | 52 const uint64_t kTestBlobStorageMaxFileSizeBytes = 100; |
| 53 | 53 |
| 54 template <typename T> | 54 void ConstructionCompletePopulator(bool* succeeded_pointer, |
| 55 void SetPointerValue(T* pointer, T value) { | 55 IPCBlobCreationCancelCode* reason_pointer, |
| 56 *pointer = value; | 56 bool succeeded, |
| 57 IPCBlobCreationCancelCode reason) { |
| 58 *succeeded_pointer = succeeded; |
| 59 *reason_pointer = reason; |
| 57 } | 60 } |
| 58 | 61 |
| 59 class TestableBlobDispatcherHost : public BlobDispatcherHost { | 62 class TestableBlobDispatcherHost : public BlobDispatcherHost { |
| 60 public: | 63 public: |
| 61 TestableBlobDispatcherHost(ChromeBlobStorageContext* blob_storage_context, | 64 TestableBlobDispatcherHost(ChromeBlobStorageContext* blob_storage_context, |
| 62 IPC::TestSink* sink) | 65 IPC::TestSink* sink) |
| 63 : BlobDispatcherHost(blob_storage_context), sink_(sink) { | 66 : BlobDispatcherHost(blob_storage_context), sink_(sink) { |
| 64 this->SetMemoryConstantsForTesting(kTestBlobStorageIPCThresholdBytes, | 67 this->SetMemoryConstantsForTesting(kTestBlobStorageIPCThresholdBytes, |
| 65 kTestBlobStorageMaxSharedMemoryBytes, | 68 kTestBlobStorageMaxSharedMemoryBytes, |
| 66 kTestBlobStorageMaxFileSizeBytes); | 69 kTestBlobStorageMaxFileSizeBytes); |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 301 std::vector<base::SharedMemoryHandle> shared_memory_handles; | 304 std::vector<base::SharedMemoryHandle> shared_memory_handles; |
| 302 | 305 |
| 303 ExpectBlobNotExist(kId); | 306 ExpectBlobNotExist(kId); |
| 304 host_->OnRegisterBlobUUID(kId, std::string(kContentType), | 307 host_->OnRegisterBlobUUID(kId, std::string(kContentType), |
| 305 std::string(kContentDisposition), | 308 std::string(kContentDisposition), |
| 306 std::set<std::string>()); | 309 std::set<std::string>()); |
| 307 // Grab the handle. | 310 // Grab the handle. |
| 308 scoped_ptr<BlobDataHandle> blob_data_handle = | 311 scoped_ptr<BlobDataHandle> blob_data_handle = |
| 309 context_->GetBlobDataFromUUID(kId); | 312 context_->GetBlobDataFromUUID(kId); |
| 310 bool built = false; | 313 bool built = false; |
| 314 IPCBlobCreationCancelCode error_code = IPCBlobCreationCancelCode::UNKNOWN; |
| 311 blob_data_handle->RunOnConstructionComplete( | 315 blob_data_handle->RunOnConstructionComplete( |
| 312 base::Bind(&SetPointerValue<bool>, &built)); | 316 base::Bind(&ConstructionCompletePopulator, &built, &error_code)); |
| 313 EXPECT_FALSE(built); | 317 EXPECT_FALSE(built); |
| 314 | 318 |
| 315 EXPECT_FALSE(host_->shutdown_for_bad_message_); | 319 EXPECT_FALSE(host_->shutdown_for_bad_message_); |
| 316 DataElement element; | 320 DataElement element; |
| 317 element.SetToBytesDescription(kLargeSize); | 321 element.SetToBytesDescription(kLargeSize); |
| 318 std::vector<DataElement> elements = {element}; | 322 std::vector<DataElement> elements = {element}; |
| 319 host_->OnStartBuildingBlob(kId, elements); | 323 host_->OnStartBuildingBlob(kId, elements); |
| 320 EXPECT_FALSE(host_->shutdown_for_bad_message_); | 324 EXPECT_FALSE(host_->shutdown_for_bad_message_); |
| 321 | 325 |
| 322 // Expect our first request. | 326 // Expect our first request. |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 367 std::memset(memory.memory(), 'Z', kTestBlobStorageMaxSharedMemoryBytes); | 371 std::memset(memory.memory(), 'Z', kTestBlobStorageMaxSharedMemoryBytes); |
| 368 memory.Close(); | 372 memory.Close(); |
| 369 } | 373 } |
| 370 // Send the confirmation. | 374 // Send the confirmation. |
| 371 responses = {BlobItemBytesResponse(1)}; | 375 responses = {BlobItemBytesResponse(1)}; |
| 372 host_->OnMemoryItemResponse(kId, responses); | 376 host_->OnMemoryItemResponse(kId, responses); |
| 373 | 377 |
| 374 ExpectDone(kId); | 378 ExpectDone(kId); |
| 375 sink_.ClearMessages(); | 379 sink_.ClearMessages(); |
| 376 base::RunLoop().RunUntilIdle(); | 380 base::RunLoop().RunUntilIdle(); |
| 377 EXPECT_TRUE(built); | 381 EXPECT_TRUE(built) << "Error code: " << static_cast<int>(error_code); |
| 378 EXPECT_TRUE(context_->registry().HasEntry(kId)); | 382 EXPECT_TRUE(context_->registry().HasEntry(kId)); |
| 379 scoped_ptr<BlobDataHandle> handle = context_->GetBlobDataFromUUID(kId); | 383 scoped_ptr<BlobDataHandle> handle = context_->GetBlobDataFromUUID(kId); |
| 380 EXPECT_TRUE(handle); | 384 EXPECT_TRUE(handle); |
| 381 | 385 |
| 382 DataElement expected; | 386 DataElement expected; |
| 383 expected.SetToAllocatedBytes(kLargeSize / 2); | 387 expected.SetToAllocatedBytes(kLargeSize / 2); |
| 384 std::memset(expected.mutable_bytes(), 'X', kLargeSize / 2); | 388 std::memset(expected.mutable_bytes(), 'X', kLargeSize / 2); |
| 385 elements = {expected}; | 389 elements = {expected}; |
| 386 std::memset(expected.mutable_bytes(), 'Z', kLargeSize / 2); | 390 std::memset(expected.mutable_bytes(), 'Z', kLargeSize / 2); |
| 387 elements.push_back(expected); | 391 elements.push_back(expected); |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 471 host_->OnRegisterBlobUUID(kId, std::string(kContentType), | 475 host_->OnRegisterBlobUUID(kId, std::string(kContentType), |
| 472 std::string(kContentDisposition), | 476 std::string(kContentDisposition), |
| 473 std::set<std::string>()); | 477 std::set<std::string>()); |
| 474 | 478 |
| 475 // Grab the handle. | 479 // Grab the handle. |
| 476 scoped_ptr<BlobDataHandle> blob_data_handle = | 480 scoped_ptr<BlobDataHandle> blob_data_handle = |
| 477 context_->GetBlobDataFromUUID(kId); | 481 context_->GetBlobDataFromUUID(kId); |
| 478 EXPECT_TRUE(blob_data_handle); | 482 EXPECT_TRUE(blob_data_handle); |
| 479 EXPECT_TRUE(blob_data_handle->IsBeingBuilt()); | 483 EXPECT_TRUE(blob_data_handle->IsBeingBuilt()); |
| 480 bool built = false; | 484 bool built = false; |
| 485 IPCBlobCreationCancelCode error_code = IPCBlobCreationCancelCode::UNKNOWN; |
| 481 blob_data_handle->RunOnConstructionComplete( | 486 blob_data_handle->RunOnConstructionComplete( |
| 482 base::Bind(&SetPointerValue<bool>, &built)); | 487 base::Bind(&ConstructionCompletePopulator, &built, &error_code)); |
| 483 | 488 |
| 484 // Continue building. | 489 // Continue building. |
| 485 DataElement element; | 490 DataElement element; |
| 486 element.SetToBytesDescription(kDataSize); | 491 element.SetToBytesDescription(kDataSize); |
| 487 std::vector<DataElement> elements = {element}; | 492 std::vector<DataElement> elements = {element}; |
| 488 host_->OnStartBuildingBlob(kId, elements); | 493 host_->OnStartBuildingBlob(kId, elements); |
| 489 sink_.ClearMessages(); | 494 sink_.ClearMessages(); |
| 490 | 495 |
| 491 // Send data. | 496 // Send data. |
| 492 BlobItemBytesResponse response(0); | 497 BlobItemBytesResponse response(0); |
| 493 std::memcpy(response.allocate_mutable_data(kDataSize), kData, kDataSize); | 498 std::memcpy(response.allocate_mutable_data(kDataSize), kData, kDataSize); |
| 494 std::vector<BlobItemBytesResponse> responses = {response}; | 499 std::vector<BlobItemBytesResponse> responses = {response}; |
| 495 sink_.ClearMessages(); | 500 sink_.ClearMessages(); |
| 496 host_->OnMemoryItemResponse(kId, responses); | 501 host_->OnMemoryItemResponse(kId, responses); |
| 497 | 502 |
| 498 ExpectDone(kId); | 503 ExpectDone(kId); |
| 499 base::RunLoop().RunUntilIdle(); | 504 base::RunLoop().RunUntilIdle(); |
| 500 EXPECT_TRUE(built); | 505 EXPECT_TRUE(built) << "Error code: " << static_cast<int>(error_code); |
| 501 } | 506 } |
| 502 | 507 |
| 503 TEST_F(BlobDispatcherHostTest, BlobReferenceWhileShortcutConstructing) { | 508 TEST_F(BlobDispatcherHostTest, BlobReferenceWhileShortcutConstructing) { |
| 504 const std::string kId("id"); | 509 const std::string kId("id"); |
| 505 | 510 |
| 506 // Start building blob. | 511 // Start building blob. |
| 507 host_->OnRegisterBlobUUID(kId, std::string(kContentType), | 512 host_->OnRegisterBlobUUID(kId, std::string(kContentType), |
| 508 std::string(kContentDisposition), | 513 std::string(kContentDisposition), |
| 509 std::set<std::string>()); | 514 std::set<std::string>()); |
| 510 | 515 |
| 511 // Grab the handle. | 516 // Grab the handle. |
| 512 scoped_ptr<BlobDataHandle> blob_data_handle = | 517 scoped_ptr<BlobDataHandle> blob_data_handle = |
| 513 context_->GetBlobDataFromUUID(kId); | 518 context_->GetBlobDataFromUUID(kId); |
| 514 EXPECT_TRUE(blob_data_handle); | 519 EXPECT_TRUE(blob_data_handle); |
| 515 EXPECT_TRUE(blob_data_handle->IsBeingBuilt()); | 520 EXPECT_TRUE(blob_data_handle->IsBeingBuilt()); |
| 516 bool built = false; | 521 bool built = false; |
| 522 IPCBlobCreationCancelCode error_code = IPCBlobCreationCancelCode::UNKNOWN; |
| 517 blob_data_handle->RunOnConstructionComplete( | 523 blob_data_handle->RunOnConstructionComplete( |
| 518 base::Bind(&SetPointerValue<bool>, &built)); | 524 base::Bind(&ConstructionCompletePopulator, &built, &error_code)); |
| 519 | 525 |
| 520 // Continue building. | 526 // Continue building. |
| 521 DataElement element; | 527 DataElement element; |
| 522 element.SetToBytes(kData, kDataSize); | 528 element.SetToBytes(kData, kDataSize); |
| 523 std::vector<DataElement> elements = {element}; | 529 std::vector<DataElement> elements = {element}; |
| 524 host_->OnStartBuildingBlob(kId, elements); | 530 host_->OnStartBuildingBlob(kId, elements); |
| 525 ExpectDone(kId); | 531 ExpectDone(kId); |
| 526 base::RunLoop().RunUntilIdle(); | 532 base::RunLoop().RunUntilIdle(); |
| 527 EXPECT_TRUE(built); | 533 EXPECT_TRUE(built) << "Error code: " << static_cast<int>(error_code); |
| 528 } | 534 } |
| 529 | 535 |
| 530 TEST_F(BlobDispatcherHostTest, BlobReferenceWhileConstructingCancelled) { | 536 TEST_F(BlobDispatcherHostTest, BlobReferenceWhileConstructingCancelled) { |
| 531 const std::string kId("id"); | 537 const std::string kId("id"); |
| 532 | 538 |
| 533 // Start building blob. | 539 // Start building blob. |
| 534 host_->OnRegisterBlobUUID(kId, std::string(kContentType), | 540 host_->OnRegisterBlobUUID(kId, std::string(kContentType), |
| 535 std::string(kContentDisposition), | 541 std::string(kContentDisposition), |
| 536 std::set<std::string>()); | 542 std::set<std::string>()); |
| 537 | 543 |
| 538 // Grab the handle. | 544 // Grab the handle. |
| 539 scoped_ptr<BlobDataHandle> blob_data_handle = | 545 scoped_ptr<BlobDataHandle> blob_data_handle = |
| 540 context_->GetBlobDataFromUUID(kId); | 546 context_->GetBlobDataFromUUID(kId); |
| 541 EXPECT_TRUE(blob_data_handle); | 547 EXPECT_TRUE(blob_data_handle); |
| 542 EXPECT_TRUE(blob_data_handle->IsBeingBuilt()); | 548 EXPECT_TRUE(blob_data_handle->IsBeingBuilt()); |
| 543 bool built = true; | 549 bool built = true; |
| 550 IPCBlobCreationCancelCode error_code = IPCBlobCreationCancelCode::UNKNOWN; |
| 544 blob_data_handle->RunOnConstructionComplete( | 551 blob_data_handle->RunOnConstructionComplete( |
| 545 base::Bind(&SetPointerValue<bool>, &built)); | 552 base::Bind(&ConstructionCompletePopulator, &built, &error_code)); |
| 546 | 553 |
| 547 // Cancel in middle of construction. | 554 // Cancel in middle of construction. |
| 548 host_->OnCancelBuildingBlob(kId, IPCBlobCreationCancelCode::UNKNOWN); | 555 host_->OnCancelBuildingBlob(kId, IPCBlobCreationCancelCode::UNKNOWN); |
| 549 base::RunLoop().RunUntilIdle(); | 556 base::RunLoop().RunUntilIdle(); |
| 550 EXPECT_TRUE(context_->registry().HasEntry(kId)); | 557 EXPECT_TRUE(context_->registry().HasEntry(kId)); |
| 551 EXPECT_TRUE(host_->IsInUseInHost(kId)); | 558 EXPECT_TRUE(host_->IsInUseInHost(kId)); |
| 552 EXPECT_FALSE(IsBeingBuiltInHost(kId)); | 559 EXPECT_FALSE(IsBeingBuiltInHost(kId)); |
| 553 EXPECT_TRUE(blob_data_handle->IsBroken()); | 560 EXPECT_TRUE(blob_data_handle->IsBroken()); |
| 554 EXPECT_FALSE(built); | 561 EXPECT_FALSE(built); |
| 562 EXPECT_EQ(IPCBlobCreationCancelCode::UNKNOWN, error_code); |
| 563 error_code = IPCBlobCreationCancelCode::UNKNOWN; |
| 555 built = true; | 564 built = true; |
| 556 blob_data_handle->RunOnConstructionComplete( | 565 blob_data_handle->RunOnConstructionComplete( |
| 557 base::Bind(&SetPointerValue<bool>, &built)); | 566 base::Bind(&ConstructionCompletePopulator, &built, &error_code)); |
| 558 EXPECT_FALSE(built); | 567 EXPECT_FALSE(built); |
| 568 EXPECT_EQ(IPCBlobCreationCancelCode::UNKNOWN, error_code); |
| 559 | 569 |
| 560 // Remove it. | 570 // Remove it. |
| 561 blob_data_handle.reset(); | 571 blob_data_handle.reset(); |
| 562 base::RunLoop().RunUntilIdle(); | 572 base::RunLoop().RunUntilIdle(); |
| 563 EXPECT_TRUE(context_->registry().HasEntry(kId)); | 573 EXPECT_TRUE(context_->registry().HasEntry(kId)); |
| 564 host_->OnDecrementBlobRefCount(kId); | 574 host_->OnDecrementBlobRefCount(kId); |
| 565 ExpectBlobNotExist(kId); | 575 ExpectBlobNotExist(kId); |
| 566 } | 576 } |
| 567 | 577 |
| 568 TEST_F(BlobDispatcherHostTest, DecrementRefAfterRegister) { | 578 TEST_F(BlobDispatcherHostTest, DecrementRefAfterRegister) { |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 674 // OnStartBuildlingBlob, except we have another handle. | 684 // OnStartBuildlingBlob, except we have another handle. |
| 675 host_->OnRegisterBlobUUID(kId, std::string(kContentType), | 685 host_->OnRegisterBlobUUID(kId, std::string(kContentType), |
| 676 std::string(kContentDisposition), | 686 std::string(kContentDisposition), |
| 677 std::set<std::string>()); | 687 std::set<std::string>()); |
| 678 EXPECT_FALSE(host_->shutdown_for_bad_message_); | 688 EXPECT_FALSE(host_->shutdown_for_bad_message_); |
| 679 | 689 |
| 680 scoped_ptr<BlobDataHandle> blob_data_handle = | 690 scoped_ptr<BlobDataHandle> blob_data_handle = |
| 681 context_->GetBlobDataFromUUID(kId); | 691 context_->GetBlobDataFromUUID(kId); |
| 682 EXPECT_TRUE(blob_data_handle->IsBeingBuilt()); | 692 EXPECT_TRUE(blob_data_handle->IsBeingBuilt()); |
| 683 bool built = true; | 693 bool built = true; |
| 694 IPCBlobCreationCancelCode error_code = IPCBlobCreationCancelCode::UNKNOWN; |
| 684 blob_data_handle->RunOnConstructionComplete( | 695 blob_data_handle->RunOnConstructionComplete( |
| 685 base::Bind(&SetPointerValue<bool>, &built)); | 696 base::Bind(&ConstructionCompletePopulator, &built, &error_code)); |
| 686 | 697 |
| 687 DataElement element; | 698 DataElement element; |
| 688 element.SetToBytesDescription(kDataSize); | 699 element.SetToBytesDescription(kDataSize); |
| 689 std::vector<DataElement> elements = {element}; | 700 std::vector<DataElement> elements = {element}; |
| 690 host_->OnStartBuildingBlob(kId, elements); | 701 host_->OnStartBuildingBlob(kId, elements); |
| 691 EXPECT_FALSE(host_->shutdown_for_bad_message_); | 702 EXPECT_FALSE(host_->shutdown_for_bad_message_); |
| 692 | 703 |
| 693 // Check that we got the expected request. | 704 // Check that we got the expected request. |
| 694 std::vector<BlobItemBytesRequest> expected_requests = { | 705 std::vector<BlobItemBytesRequest> expected_requests = { |
| 695 BlobItemBytesRequest::CreateIPCRequest(0, 0, 0, kDataSize)}; | 706 BlobItemBytesRequest::CreateIPCRequest(0, 0, 0, kDataSize)}; |
| 696 ExpectRequest(kId, expected_requests); | 707 ExpectRequest(kId, expected_requests); |
| 697 sink_.ClearMessages(); | 708 sink_.ClearMessages(); |
| 698 EXPECT_TRUE(context_->registry().HasEntry(kId)); | 709 EXPECT_TRUE(context_->registry().HasEntry(kId)); |
| 699 EXPECT_TRUE(IsBeingBuiltInHost(kId)); | 710 EXPECT_TRUE(IsBeingBuiltInHost(kId)); |
| 700 // Decrement, simulating where the ref goes out of scope in renderer. | 711 // Decrement, simulating where the ref goes out of scope in renderer. |
| 701 host_->OnDecrementBlobRefCount(kId); | 712 host_->OnDecrementBlobRefCount(kId); |
| 702 // We still have the blob as it's not done. | 713 // We still have the blob as it's not done. |
| 703 EXPECT_TRUE(context_->registry().HasEntry(kId)); | 714 EXPECT_TRUE(context_->registry().HasEntry(kId)); |
| 704 EXPECT_TRUE(blob_data_handle->IsBeingBuilt()); | 715 EXPECT_TRUE(blob_data_handle->IsBeingBuilt()); |
| 705 EXPECT_TRUE(IsBeingBuiltInHost(kId)); | 716 EXPECT_TRUE(IsBeingBuiltInHost(kId)); |
| 706 // Cancel to clean up. | 717 // Cancel to clean up. |
| 707 host_->OnCancelBuildingBlob(kId, IPCBlobCreationCancelCode::UNKNOWN); | 718 host_->OnCancelBuildingBlob(kId, IPCBlobCreationCancelCode::UNKNOWN); |
| 708 // Run loop to propagate the handle decrement in the host. | 719 // Run loop to propagate the handle decrement in the host. |
| 709 base::RunLoop().RunUntilIdle(); | 720 base::RunLoop().RunUntilIdle(); |
| 710 // We still have the entry because of our earlier handle. | 721 // We still have the entry because of our earlier handle. |
| 711 EXPECT_TRUE(context_->registry().HasEntry(kId)); | 722 EXPECT_TRUE(context_->registry().HasEntry(kId)); |
| 712 EXPECT_FALSE(IsBeingBuiltInHost(kId)); | 723 EXPECT_FALSE(IsBeingBuiltInHost(kId)); |
| 724 EXPECT_FALSE(built); |
| 725 EXPECT_EQ(IPCBlobCreationCancelCode::UNKNOWN, error_code); |
| 713 sink_.ClearMessages(); | 726 sink_.ClearMessages(); |
| 714 | 727 |
| 715 // Should disappear after dropping the handle. | 728 // Should disappear after dropping the handle. |
| 716 EXPECT_TRUE(blob_data_handle->IsBroken()); | 729 EXPECT_TRUE(blob_data_handle->IsBroken()); |
| 717 blob_data_handle.reset(); | 730 blob_data_handle.reset(); |
| 718 base::RunLoop().RunUntilIdle(); | 731 base::RunLoop().RunUntilIdle(); |
| 719 EXPECT_FALSE(context_->registry().HasEntry(kId)); | 732 EXPECT_FALSE(context_->registry().HasEntry(kId)); |
| 720 } | 733 } |
| 721 | 734 |
| 722 TEST_F(BlobDispatcherHostTest, HostDisconnectAfterRegisterWithHandle) { | 735 TEST_F(BlobDispatcherHostTest, HostDisconnectAfterRegisterWithHandle) { |
| 723 const std::string kId("id"); | 736 const std::string kId("id"); |
| 724 | 737 |
| 725 // Delete host with a handle to the blob. | 738 // Delete host with a handle to the blob. |
| 726 host_->OnRegisterBlobUUID(kId, std::string(kContentType), | 739 host_->OnRegisterBlobUUID(kId, std::string(kContentType), |
| 727 std::string(kContentDisposition), | 740 std::string(kContentDisposition), |
| 728 std::set<std::string>()); | 741 std::set<std::string>()); |
| 729 | 742 |
| 730 scoped_ptr<BlobDataHandle> blob_data_handle = | 743 scoped_ptr<BlobDataHandle> blob_data_handle = |
| 731 context_->GetBlobDataFromUUID(kId); | 744 context_->GetBlobDataFromUUID(kId); |
| 732 EXPECT_TRUE(blob_data_handle->IsBeingBuilt()); | 745 EXPECT_TRUE(blob_data_handle->IsBeingBuilt()); |
| 733 bool built = true; | 746 bool built = true; |
| 747 IPCBlobCreationCancelCode error_code = IPCBlobCreationCancelCode::UNKNOWN; |
| 734 blob_data_handle->RunOnConstructionComplete( | 748 blob_data_handle->RunOnConstructionComplete( |
| 735 base::Bind(&SetPointerValue<bool>, &built)); | 749 base::Bind(&ConstructionCompletePopulator, &built, &error_code)); |
| 736 // Get rid of host, which was doing the constructing. | 750 // Get rid of host, which was doing the constructing. |
| 737 host_ = nullptr; | 751 host_ = nullptr; |
| 738 EXPECT_FALSE(blob_data_handle->IsBeingBuilt()); | 752 EXPECT_FALSE(blob_data_handle->IsBeingBuilt()); |
| 739 base::RunLoop().RunUntilIdle(); | 753 base::RunLoop().RunUntilIdle(); |
| 740 EXPECT_FALSE(built); | 754 EXPECT_FALSE(built); |
| 755 EXPECT_EQ(IPCBlobCreationCancelCode::SOURCE_DIED_IN_TRANSIT, error_code); |
| 741 | 756 |
| 742 // Should still be there due to the handle. | 757 // Should still be there due to the handle. |
| 743 scoped_ptr<BlobDataHandle> another_handle = | 758 scoped_ptr<BlobDataHandle> another_handle = |
| 744 context_->GetBlobDataFromUUID(kId); | 759 context_->GetBlobDataFromUUID(kId); |
| 745 EXPECT_TRUE(another_handle); | 760 EXPECT_TRUE(another_handle); |
| 746 | 761 |
| 747 // Should disappear after dropping both handles. | 762 // Should disappear after dropping both handles. |
| 748 blob_data_handle.reset(); | 763 blob_data_handle.reset(); |
| 749 another_handle.reset(); | 764 another_handle.reset(); |
| 750 base::RunLoop().RunUntilIdle(); | 765 base::RunLoop().RunUntilIdle(); |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 919 host2->OnDecrementBlobRefCount(kId); | 934 host2->OnDecrementBlobRefCount(kId); |
| 920 // So no more blob in the context, but we're still being built in host 1. | 935 // So no more blob in the context, but we're still being built in host 1. |
| 921 EXPECT_FALSE(context_->registry().HasEntry(kId)); | 936 EXPECT_FALSE(context_->registry().HasEntry(kId)); |
| 922 EXPECT_TRUE(host_->async_builder_.IsBeingBuilt(kId)); | 937 EXPECT_TRUE(host_->async_builder_.IsBeingBuilt(kId)); |
| 923 host_->OnCancelBuildingBlob(kId, IPCBlobCreationCancelCode::UNKNOWN); | 938 host_->OnCancelBuildingBlob(kId, IPCBlobCreationCancelCode::UNKNOWN); |
| 924 EXPECT_FALSE(host_->shutdown_for_bad_message_); | 939 EXPECT_FALSE(host_->shutdown_for_bad_message_); |
| 925 // We should be cleaned up. | 940 // We should be cleaned up. |
| 926 EXPECT_FALSE(host_->async_builder_.IsBeingBuilt(kId)); | 941 EXPECT_FALSE(host_->async_builder_.IsBeingBuilt(kId)); |
| 927 } | 942 } |
| 928 | 943 |
| 944 TEST_F(BlobDispatcherHostTest, BuildingReferenceChain) { |
| 945 const std::string kId("id"); |
| 946 const std::string kSameHostReferencingId("id2"); |
| 947 const std::string kDifferentHostReferencingId("id3"); |
| 948 // Data elements for our transfer & checking messages. |
| 949 DataElement element; |
| 950 element.SetToBytes(kData, kDataSize); |
| 951 std::vector<DataElement> elements = {element}; |
| 952 DataElement referencing_element; |
| 953 referencing_element.SetToBlob(kId); |
| 954 std::vector<DataElement> referencing_elements = {referencing_element}; |
| 955 std::set<std::string> referenced_blobs_set = {kId}; |
| 956 |
| 957 scoped_refptr<TestableBlobDispatcherHost> host2( |
| 958 new TestableBlobDispatcherHost(chrome_blob_storage_context_, &sink_)); |
| 959 |
| 960 // We want to have a blob referencing another blob that is building, both on |
| 961 // the same host and a different host. We should successfully build all blobs |
| 962 // after the referenced blob is finished. |
| 963 |
| 964 // First we start the referenced blob. |
| 965 host_->OnRegisterBlobUUID(kId, std::string(kContentType), |
| 966 std::string(kContentDisposition), |
| 967 std::set<std::string>()); |
| 968 EXPECT_TRUE(host_->IsInUseInHost(kId)); |
| 969 |
| 970 // Next we start the referencing blobs in both the same and different host. |
| 971 host_->OnRegisterBlobUUID(kSameHostReferencingId, std::string(kContentType), |
| 972 std::string(kContentDisposition), |
| 973 referenced_blobs_set); |
| 974 EXPECT_FALSE(host_->shutdown_for_bad_message_); |
| 975 host_->OnStartBuildingBlob(kSameHostReferencingId, referencing_elements); |
| 976 EXPECT_FALSE(host_->shutdown_for_bad_message_); |
| 977 ExpectDone(kSameHostReferencingId); |
| 978 EXPECT_TRUE(host_->async_builder_.IsBeingBuilt(kSameHostReferencingId)); |
| 979 sink_.ClearMessages(); |
| 980 // Now the other host. |
| 981 host2->OnRegisterBlobUUID( |
| 982 kDifferentHostReferencingId, std::string(kContentType), |
| 983 std::string(kContentDisposition), referenced_blobs_set); |
| 984 EXPECT_FALSE(host2->shutdown_for_bad_message_); |
| 985 host2->OnStartBuildingBlob(kDifferentHostReferencingId, referencing_elements); |
| 986 EXPECT_FALSE(host2->shutdown_for_bad_message_); |
| 987 ExpectDone(kDifferentHostReferencingId); |
| 988 EXPECT_TRUE(host2->async_builder_.IsBeingBuilt(kDifferentHostReferencingId)); |
| 989 sink_.ClearMessages(); |
| 990 |
| 991 // Now we finish the first blob, and we expect all blobs to finish. |
| 992 host_->OnStartBuildingBlob(kId, elements); |
| 993 ExpectDone(kId); |
| 994 // We need to run the message loop to propagate the construction callbacks. |
| 995 base::RunLoop().RunUntilIdle(); |
| 996 EXPECT_FALSE(host2->async_builder_.IsBeingBuilt(kDifferentHostReferencingId)); |
| 997 EXPECT_FALSE(host_->async_builder_.IsBeingBuilt(kSameHostReferencingId)); |
| 998 EXPECT_FALSE( |
| 999 context_->GetBlobDataFromUUID(kSameHostReferencingId)->IsBroken()); |
| 1000 EXPECT_FALSE( |
| 1001 context_->GetBlobDataFromUUID(kDifferentHostReferencingId)->IsBroken()); |
| 1002 sink_.ClearMessages(); |
| 1003 |
| 1004 // Finally check that our data is correct in the child elements. |
| 1005 scoped_ptr<BlobDataHandle> handle = |
| 1006 context_->GetBlobDataFromUUID(kDifferentHostReferencingId); |
| 1007 ExpectHandleEqualsData(handle.get(), elements); |
| 1008 } |
| 1009 |
| 1010 TEST_F(BlobDispatcherHostTest, BuildingReferenceChainWithCancel) { |
| 1011 const std::string kId("id"); |
| 1012 const std::string kSameHostReferencingId("id2"); |
| 1013 const std::string kDifferentHostReferencingId("id3"); |
| 1014 // Data elements for our transfer & checking messages. |
| 1015 DataElement referencing_element; |
| 1016 referencing_element.SetToBlob(kId); |
| 1017 std::vector<DataElement> referencing_elements = {referencing_element}; |
| 1018 std::set<std::string> referenced_blobs_set = {kId}; |
| 1019 |
| 1020 scoped_refptr<TestableBlobDispatcherHost> host2( |
| 1021 new TestableBlobDispatcherHost(chrome_blob_storage_context_, &sink_)); |
| 1022 |
| 1023 // We want to have a blob referencing another blob that is building, both on |
| 1024 // the same host and a different host. After we cancel the first blob, the |
| 1025 // others should cancel as well. |
| 1026 |
| 1027 // First we start the referenced blob. |
| 1028 host_->OnRegisterBlobUUID(kId, std::string(kContentType), |
| 1029 std::string(kContentDisposition), |
| 1030 std::set<std::string>()); |
| 1031 EXPECT_TRUE(host_->IsInUseInHost(kId)); |
| 1032 |
| 1033 // Next we start the referencing blobs in both the same and different host. |
| 1034 host_->OnRegisterBlobUUID(kSameHostReferencingId, std::string(kContentType), |
| 1035 std::string(kContentDisposition), |
| 1036 referenced_blobs_set); |
| 1037 host_->OnStartBuildingBlob(kSameHostReferencingId, referencing_elements); |
| 1038 ExpectDone(kSameHostReferencingId); |
| 1039 EXPECT_TRUE(host_->async_builder_.IsBeingBuilt(kSameHostReferencingId)); |
| 1040 sink_.ClearMessages(); |
| 1041 // Now the other host. |
| 1042 host2->OnRegisterBlobUUID( |
| 1043 kDifferentHostReferencingId, std::string(kContentType), |
| 1044 std::string(kContentDisposition), referenced_blobs_set); |
| 1045 host2->OnStartBuildingBlob(kDifferentHostReferencingId, referencing_elements); |
| 1046 ExpectDone(kDifferentHostReferencingId); |
| 1047 EXPECT_TRUE(host2->async_builder_.IsBeingBuilt(kDifferentHostReferencingId)); |
| 1048 sink_.ClearMessages(); |
| 1049 bool built = false; |
| 1050 IPCBlobCreationCancelCode error_code = IPCBlobCreationCancelCode::UNKNOWN; |
| 1051 context_->GetBlobDataFromUUID(kDifferentHostReferencingId) |
| 1052 ->RunOnConstructionComplete( |
| 1053 base::Bind(&ConstructionCompletePopulator, &built, &error_code)); |
| 1054 |
| 1055 // Now we cancel the first blob, and we expect all blobs to cancel. |
| 1056 host_->OnCancelBuildingBlob(kId, IPCBlobCreationCancelCode::UNKNOWN); |
| 1057 // We need to run the message loop to propagate the construction callbacks. |
| 1058 base::RunLoop().RunUntilIdle(); |
| 1059 EXPECT_FALSE(host2->async_builder_.IsBeingBuilt(kDifferentHostReferencingId)); |
| 1060 EXPECT_FALSE(host_->async_builder_.IsBeingBuilt(kSameHostReferencingId)); |
| 1061 EXPECT_TRUE( |
| 1062 context_->GetBlobDataFromUUID(kSameHostReferencingId)->IsBroken()); |
| 1063 EXPECT_TRUE( |
| 1064 context_->GetBlobDataFromUUID(kDifferentHostReferencingId)->IsBroken()); |
| 1065 EXPECT_FALSE(built); |
| 1066 EXPECT_EQ(IPCBlobCreationCancelCode::REFERENCED_BLOB_BROKEN, error_code); |
| 1067 sink_.ClearMessages(); |
| 1068 } |
| 1069 |
| 1070 TEST_F(BlobDispatcherHostTest, BuildingReferenceChainWithSourceDeath) { |
| 1071 const std::string kId("id"); |
| 1072 const std::string kSameHostReferencingId("id2"); |
| 1073 const std::string kDifferentHostReferencingId("id3"); |
| 1074 // Data elements for our transfer & checking messages. |
| 1075 DataElement referencing_element; |
| 1076 referencing_element.SetToBlob(kId); |
| 1077 std::vector<DataElement> referencing_elements = {referencing_element}; |
| 1078 std::set<std::string> referenced_blobs_set = {kId}; |
| 1079 |
| 1080 scoped_refptr<TestableBlobDispatcherHost> host2( |
| 1081 new TestableBlobDispatcherHost(chrome_blob_storage_context_, &sink_)); |
| 1082 |
| 1083 // We want to have a blob referencing another blob that is building, both on |
| 1084 // the same host and a different host. When we destroy the host, the other |
| 1085 // blob should cancel, as well as the blob on the other host. |
| 1086 |
| 1087 // First we start the referenced blob. |
| 1088 host_->OnRegisterBlobUUID(kId, std::string(kContentType), |
| 1089 std::string(kContentDisposition), |
| 1090 std::set<std::string>()); |
| 1091 EXPECT_TRUE(host_->IsInUseInHost(kId)); |
| 1092 |
| 1093 // Next we start the referencing blobs in both the same and different host. |
| 1094 host_->OnRegisterBlobUUID(kSameHostReferencingId, std::string(kContentType), |
| 1095 std::string(kContentDisposition), |
| 1096 referenced_blobs_set); |
| 1097 host_->OnStartBuildingBlob(kSameHostReferencingId, referencing_elements); |
| 1098 ExpectDone(kSameHostReferencingId); |
| 1099 EXPECT_TRUE(host_->async_builder_.IsBeingBuilt(kSameHostReferencingId)); |
| 1100 sink_.ClearMessages(); |
| 1101 // Now the other host. |
| 1102 host2->OnRegisterBlobUUID( |
| 1103 kDifferentHostReferencingId, std::string(kContentType), |
| 1104 std::string(kContentDisposition), referenced_blobs_set); |
| 1105 host2->OnStartBuildingBlob(kDifferentHostReferencingId, referencing_elements); |
| 1106 ExpectDone(kDifferentHostReferencingId); |
| 1107 EXPECT_TRUE(host2->async_builder_.IsBeingBuilt(kDifferentHostReferencingId)); |
| 1108 sink_.ClearMessages(); |
| 1109 |
| 1110 // Grab handles & add listeners. |
| 1111 bool built = true; |
| 1112 IPCBlobCreationCancelCode error_code = IPCBlobCreationCancelCode::UNKNOWN; |
| 1113 scoped_ptr<BlobDataHandle> blob_handle = context_->GetBlobDataFromUUID(kId); |
| 1114 blob_handle->RunOnConstructionComplete( |
| 1115 base::Bind(&ConstructionCompletePopulator, &built, &error_code)); |
| 1116 |
| 1117 bool same_host_built = true; |
| 1118 IPCBlobCreationCancelCode same_host_error_code = |
| 1119 IPCBlobCreationCancelCode::UNKNOWN; |
| 1120 scoped_ptr<BlobDataHandle> same_host_blob_handle = |
| 1121 context_->GetBlobDataFromUUID(kSameHostReferencingId); |
| 1122 same_host_blob_handle->RunOnConstructionComplete(base::Bind( |
| 1123 &ConstructionCompletePopulator, &same_host_built, &same_host_error_code)); |
| 1124 |
| 1125 bool other_host_built = true; |
| 1126 IPCBlobCreationCancelCode other_host_error_code = |
| 1127 IPCBlobCreationCancelCode::UNKNOWN; |
| 1128 scoped_ptr<BlobDataHandle> other_host_blob_handle = |
| 1129 context_->GetBlobDataFromUUID(kDifferentHostReferencingId); |
| 1130 other_host_blob_handle->RunOnConstructionComplete( |
| 1131 base::Bind(&ConstructionCompletePopulator, &other_host_built, |
| 1132 &other_host_error_code)); |
| 1133 |
| 1134 // Now we kill the host. |
| 1135 host_ = nullptr; |
| 1136 // We need to run the message loop to propagate the construction callbacks. |
| 1137 base::RunLoop().RunUntilIdle(); |
| 1138 EXPECT_FALSE(host2->async_builder_.IsBeingBuilt(kDifferentHostReferencingId)); |
| 1139 EXPECT_TRUE( |
| 1140 context_->GetBlobDataFromUUID(kSameHostReferencingId)->IsBroken()); |
| 1141 EXPECT_TRUE( |
| 1142 context_->GetBlobDataFromUUID(kDifferentHostReferencingId)->IsBroken()); |
| 1143 |
| 1144 // Check our callbacks |
| 1145 EXPECT_FALSE(built); |
| 1146 EXPECT_EQ(IPCBlobCreationCancelCode::SOURCE_DIED_IN_TRANSIT, error_code); |
| 1147 EXPECT_FALSE(same_host_built); |
| 1148 EXPECT_EQ(IPCBlobCreationCancelCode::SOURCE_DIED_IN_TRANSIT, |
| 1149 same_host_error_code); |
| 1150 EXPECT_FALSE(other_host_built); |
| 1151 EXPECT_EQ(IPCBlobCreationCancelCode::SOURCE_DIED_IN_TRANSIT, |
| 1152 other_host_error_code); |
| 1153 |
| 1154 sink_.ClearMessages(); |
| 1155 } |
| 1156 |
| 929 } // namespace content | 1157 } // namespace content |
| OLD | NEW |