| Index: content/browser/blob_storage/blob_dispatcher_host_unittest.cc | 
| diff --git a/content/browser/blob_storage/blob_dispatcher_host_unittest.cc b/content/browser/blob_storage/blob_dispatcher_host_unittest.cc | 
| index e51df6baa50f1bb4d3d3e3a4a60ede5089af3913..aca858fa1a440f68fbbc23be8a9a08a807612d91 100644 | 
| --- a/content/browser/blob_storage/blob_dispatcher_host_unittest.cc | 
| +++ b/content/browser/blob_storage/blob_dispatcher_host_unittest.cc | 
| @@ -11,6 +11,7 @@ | 
| #include "base/command_line.h" | 
| #include "base/memory/shared_memory.h" | 
| #include "base/run_loop.h" | 
| +#include "base/strings/string_number_conversions.h" | 
| #include "content/browser/blob_storage/chrome_blob_storage_context.h" | 
| #include "content/common/fileapi/webblob_messages.h" | 
| #include "content/public/common/content_switches.h" | 
| @@ -33,12 +34,10 @@ using storage::BlobDataBuilder; | 
| using storage::BlobDataHandle; | 
| using storage::BlobItemBytesRequest; | 
| using storage::BlobItemBytesResponse; | 
| +using storage::BlobStatus; | 
| using storage::BlobStorageContext; | 
| -using storage::BlobTransportResult; | 
| using storage::DataElement; | 
| -using storage::IPCBlobCreationCancelCode; | 
| -using RequestMemoryCallback = | 
| -    storage::BlobAsyncBuilderHost::RequestMemoryCallback; | 
| +using RequestMemoryCallback = storage::BlobTransportHost::RequestMemoryCallback; | 
|  | 
| namespace content { | 
| namespace { | 
| @@ -50,14 +49,16 @@ const size_t kDataSize = 6; | 
|  | 
| const size_t kTestBlobStorageIPCThresholdBytes = 20; | 
| const size_t kTestBlobStorageMaxSharedMemoryBytes = 50; | 
| +const size_t kTestBlobStorageMaxBlobMemorySize = 400; | 
| +const uint64_t kTestBlobStorageMaxDiskSpace = 1000; | 
| +const uint64_t kTestBlobStorageMinFileSizeBytes = 10; | 
| const uint64_t kTestBlobStorageMaxFileSizeBytes = 100; | 
|  | 
| -void ConstructionCompletePopulator(bool* succeeded_pointer, | 
| -                                   IPCBlobCreationCancelCode* reason_pointer, | 
| -                                   bool succeeded, | 
| -                                   IPCBlobCreationCancelCode reason) { | 
| -  *succeeded_pointer = succeeded; | 
| +void ConstructionCompletePopulator(bool* success_pointer, | 
| +                                   BlobStatus* reason_pointer, | 
| +                                   BlobStatus reason) { | 
| *reason_pointer = reason; | 
| +  *success_pointer = reason == BlobStatus::DONE; | 
| } | 
|  | 
| // TODO(dmurph): Create file test that verifies security policy. | 
| @@ -69,11 +70,7 @@ class TestableBlobDispatcherHost : public BlobDispatcherHost { | 
| : BlobDispatcherHost(0 /* process_id */, | 
| make_scoped_refptr(blob_storage_context), | 
| make_scoped_refptr(file_system_context)), | 
| -        sink_(sink) { | 
| -    this->SetMemoryConstantsForTesting(kTestBlobStorageIPCThresholdBytes, | 
| -                                       kTestBlobStorageMaxSharedMemoryBytes, | 
| -                                       kTestBlobStorageMaxFileSizeBytes); | 
| -  } | 
| +        sink_(sink) {} | 
|  | 
| bool Send(IPC::Message* message) override { return sink_->Send(message); } | 
|  | 
| @@ -112,7 +109,16 @@ class BlobDispatcherHostTest : public testing::Test { | 
| // We run the run loop to initialize the chrome blob storage context. | 
| base::RunLoop().RunUntilIdle(); | 
| context_ = chrome_blob_storage_context_->context(); | 
| -    DCHECK(context_); | 
| +    ASSERT_TRUE(context_); | 
| + | 
| +    storage::BlobStorageLimits limits; | 
| +    limits.max_ipc_memory_size = kTestBlobStorageIPCThresholdBytes; | 
| +    limits.max_shared_memory_size = kTestBlobStorageMaxSharedMemoryBytes; | 
| +    limits.max_blob_in_memory_space = kTestBlobStorageMaxBlobMemorySize; | 
| +    limits.max_blob_disk_space = kTestBlobStorageMaxDiskSpace; | 
| +    limits.min_page_file_size = kTestBlobStorageMinFileSizeBytes; | 
| +    limits.max_file_size = kTestBlobStorageMaxFileSizeBytes; | 
| +    context_->mutable_memory_controller()->set_limits_for_testing(limits); | 
| } | 
|  | 
| void ExpectBlobNotExist(const std::string& id) { | 
| @@ -124,14 +130,11 @@ class BlobDispatcherHostTest : public testing::Test { | 
| void AsyncShortcutBlobTransfer(const std::string& id) { | 
| sink_.ClearMessages(); | 
| ExpectBlobNotExist(id); | 
| -    host_->OnRegisterBlobUUID(id, std::string(kContentType), | 
| -                              std::string(kContentDisposition), | 
| -                              std::set<std::string>()); | 
| -    EXPECT_FALSE(host_->shutdown_for_bad_message_); | 
| DataElement element; | 
| element.SetToBytes(kData, kDataSize); | 
| std::vector<DataElement> elements = {element}; | 
| -    host_->OnStartBuildingBlob(id, elements); | 
| +    host_->OnRegisterBlob(id, std::string(kContentType), | 
| +                          std::string(kContentDisposition), elements); | 
| EXPECT_FALSE(host_->shutdown_for_bad_message_); | 
| ExpectDone(id); | 
| sink_.ClearMessages(); | 
| @@ -140,14 +143,11 @@ class BlobDispatcherHostTest : public testing::Test { | 
| void AsyncBlobTransfer(const std::string& id) { | 
| sink_.ClearMessages(); | 
| ExpectBlobNotExist(id); | 
| -    host_->OnRegisterBlobUUID(id, std::string(kContentType), | 
| -                              std::string(kContentDisposition), | 
| -                              std::set<std::string>()); | 
| -    EXPECT_FALSE(host_->shutdown_for_bad_message_); | 
| DataElement element; | 
| element.SetToBytesDescription(kDataSize); | 
| std::vector<DataElement> elements = {element}; | 
| -    host_->OnStartBuildingBlob(id, elements); | 
| +    host_->OnRegisterBlob(id, std::string(kContentType), | 
| +                          std::string(kContentDisposition), elements); | 
| EXPECT_FALSE(host_->shutdown_for_bad_message_); | 
|  | 
| // Expect our request. | 
| @@ -187,9 +187,7 @@ class BlobDispatcherHostTest : public testing::Test { | 
| const std::string& expected_uuid, | 
| const std::vector<BlobItemBytesRequest>& expected_requests) { | 
| EXPECT_FALSE( | 
| -        sink_.GetFirstMessageMatching(BlobStorageMsg_DoneBuildingBlob::ID)); | 
| -    EXPECT_FALSE( | 
| -        sink_.GetFirstMessageMatching(BlobStorageMsg_CancelBuildingBlob::ID)); | 
| +        sink_.GetFirstMessageMatching(BlobStorageMsg_SendBlobStatus::ID)); | 
| const IPC::Message* message = | 
| sink_.GetUniqueMessageMatching(BlobStorageMsg_RequestMemoryItem::ID); | 
| ASSERT_TRUE(message); | 
| @@ -211,9 +209,7 @@ class BlobDispatcherHostTest : public testing::Test { | 
| const std::vector<BlobItemBytesRequest>& expected_requests, | 
| std::vector<base::SharedMemoryHandle>* shared_memory_handles) { | 
| EXPECT_FALSE( | 
| -        sink_.GetFirstMessageMatching(BlobStorageMsg_DoneBuildingBlob::ID)); | 
| -    EXPECT_FALSE( | 
| -        sink_.GetFirstMessageMatching(BlobStorageMsg_CancelBuildingBlob::ID)); | 
| +        sink_.GetFirstMessageMatching(BlobStorageMsg_SendBlobStatus::ID)); | 
| const IPC::Message* message = | 
| sink_.GetUniqueMessageMatching(BlobStorageMsg_RequestMemoryItem::ID); | 
| ASSERT_TRUE(message); | 
| @@ -231,17 +227,14 @@ class BlobDispatcherHostTest : public testing::Test { | 
| *shared_memory_handles = std::move(std::get<2>(args)); | 
| } | 
|  | 
| -  void ExpectCancel(const std::string& expected_uuid, | 
| -                    IPCBlobCreationCancelCode code) { | 
| +  void ExpectCancel(const std::string& expected_uuid, BlobStatus code) { | 
| EXPECT_FALSE( | 
| sink_.GetFirstMessageMatching(BlobStorageMsg_RequestMemoryItem::ID)); | 
| -    EXPECT_FALSE( | 
| -        sink_.GetFirstMessageMatching(BlobStorageMsg_DoneBuildingBlob::ID)); | 
| const IPC::Message* message = | 
| -        sink_.GetUniqueMessageMatching(BlobStorageMsg_CancelBuildingBlob::ID); | 
| +        sink_.GetUniqueMessageMatching(BlobStorageMsg_SendBlobStatus::ID); | 
| ASSERT_TRUE(message); | 
| -    std::tuple<std::string, IPCBlobCreationCancelCode> args; | 
| -    BlobStorageMsg_CancelBuildingBlob::Read(message, &args); | 
| +    std::tuple<std::string, BlobStatus> args; | 
| +    BlobStorageMsg_SendBlobStatus::Read(message, &args); | 
| EXPECT_EQ(expected_uuid, std::get<0>(args)); | 
| EXPECT_EQ(code, std::get<1>(args)); | 
| } | 
| @@ -249,17 +242,21 @@ class BlobDispatcherHostTest : public testing::Test { | 
| void ExpectDone(const std::string& expected_uuid) { | 
| EXPECT_FALSE( | 
| sink_.GetFirstMessageMatching(BlobStorageMsg_RequestMemoryItem::ID)); | 
| -    EXPECT_FALSE( | 
| -        sink_.GetFirstMessageMatching(BlobStorageMsg_CancelBuildingBlob::ID)); | 
| const IPC::Message* message = | 
| -        sink_.GetUniqueMessageMatching(BlobStorageMsg_DoneBuildingBlob::ID); | 
| -    std::tuple<std::string> args; | 
| -    BlobStorageMsg_DoneBuildingBlob::Read(message, &args); | 
| +        sink_.GetUniqueMessageMatching(BlobStorageMsg_SendBlobStatus::ID); | 
| +    ASSERT_TRUE(message); | 
| +    std::tuple<std::string, BlobStatus> args; | 
| +    BlobStorageMsg_SendBlobStatus::Read(message, &args); | 
| EXPECT_EQ(expected_uuid, std::get<0>(args)); | 
| +    EXPECT_EQ(BlobStatus::DONE, std::get<1>(args)); | 
| } | 
|  | 
| bool IsBeingBuiltInHost(const std::string& uuid) { | 
| -    return host_->async_builder_.IsBeingBuilt(uuid); | 
| +    return host_->transport_host_.IsBeingBuilt(uuid); | 
| +  } | 
| + | 
| +  bool IsBeingBuiltInContext(const std::string& uuid) { | 
| +    return BlobStatusIsPending(context_->GetBlobStatus(uuid)); | 
| } | 
|  | 
| IPC::TestSink sink_; | 
| @@ -272,13 +269,12 @@ class BlobDispatcherHostTest : public testing::Test { | 
| }; | 
|  | 
| TEST_F(BlobDispatcherHostTest, EmptyUUIDs) { | 
| -  host_->OnRegisterBlobUUID("", "", "", std::set<std::string>()); | 
| -  ExpectAndResetBadMessage(); | 
| -  host_->OnStartBuildingBlob("", std::vector<DataElement>()); | 
| +  host_->OnRegisterBlob("", "", "", std::vector<DataElement>()); | 
| ExpectAndResetBadMessage(); | 
| host_->OnMemoryItemResponse("", std::vector<BlobItemBytesResponse>()); | 
| ExpectAndResetBadMessage(); | 
| -  host_->OnCancelBuildingBlob("", IPCBlobCreationCancelCode::UNKNOWN); | 
| +  host_->OnCancelBuildingBlob("", | 
| +                              BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS); | 
| ExpectAndResetBadMessage(); | 
| } | 
|  | 
| @@ -311,23 +307,16 @@ TEST_F(BlobDispatcherHostTest, RegularTransfer) { | 
| TEST_F(BlobDispatcherHostTest, MultipleTransfers) { | 
| const std::string kId = "uuid"; | 
| const int kNumIters = 10; | 
| -  for (int i = 0; i < kNumIters; i++) { | 
| -    std::string id = kId; | 
| -    id += ('0' + i); | 
| -    ExpectBlobNotExist(id); | 
| -    host_->OnRegisterBlobUUID(id, std::string(kContentType), | 
| -                              std::string(kContentDisposition), | 
| -                              std::set<std::string>()); | 
| -    EXPECT_FALSE(host_->shutdown_for_bad_message_); | 
| -  } | 
| sink_.ClearMessages(); | 
| for (int i = 0; i < kNumIters; i++) { | 
| std::string id = kId; | 
| id += ('0' + i); | 
| +    ExpectBlobNotExist(id); | 
| DataElement element; | 
| element.SetToBytesDescription(kDataSize); | 
| std::vector<DataElement> elements = {element}; | 
| -    host_->OnStartBuildingBlob(id, elements); | 
| +    host_->OnRegisterBlob(id, std::string(kContentType), | 
| +                          std::string(kContentDisposition), elements); | 
| EXPECT_FALSE(host_->shutdown_for_bad_message_); | 
| // Expect our request. | 
| std::vector<BlobItemBytesRequest> expected_requests = { | 
| @@ -354,25 +343,23 @@ TEST_F(BlobDispatcherHostTest, SharedMemoryTransfer) { | 
| std::vector<base::SharedMemoryHandle> shared_memory_handles; | 
|  | 
| ExpectBlobNotExist(kId); | 
| -  host_->OnRegisterBlobUUID(kId, std::string(kContentType), | 
| -                            std::string(kContentDisposition), | 
| -                            std::set<std::string>()); | 
| +  DataElement element; | 
| +  element.SetToBytesDescription(kLargeSize); | 
| +  std::vector<DataElement> elements = {element}; | 
| +  host_->OnRegisterBlob(kId, std::string(kContentType), | 
| +                        std::string(kContentDisposition), elements); | 
| +  EXPECT_FALSE(host_->shutdown_for_bad_message_); | 
|  | 
| // Grab the handle. | 
| std::unique_ptr<BlobDataHandle> blob_data_handle = | 
| context_->GetBlobDataFromUUID(kId); | 
| bool built = false; | 
| -  IPCBlobCreationCancelCode error_code = IPCBlobCreationCancelCode::UNKNOWN; | 
| +  BlobStatus error_code = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS; | 
| blob_data_handle->RunOnConstructionComplete( | 
| base::Bind(&ConstructionCompletePopulator, &built, &error_code)); | 
| EXPECT_FALSE(built); | 
|  | 
| EXPECT_FALSE(host_->shutdown_for_bad_message_); | 
| -  DataElement element; | 
| -  element.SetToBytesDescription(kLargeSize); | 
| -  std::vector<DataElement> elements = {element}; | 
| -  host_->OnStartBuildingBlob(kId, elements); | 
| -  EXPECT_FALSE(host_->shutdown_for_bad_message_); | 
|  | 
| // Expect our first request. | 
| std::vector<BlobItemBytesRequest> expected_requests = { | 
| @@ -447,24 +434,23 @@ TEST_F(BlobDispatcherHostTest, OnCancelBuildingBlob) { | 
| const std::string kId("id"); | 
| // We ignore blobs that are unknown, as it could have been cancelled earlier | 
| // and the renderer didn't know about it yet. | 
| -  host_->OnCancelBuildingBlob(kId, IPCBlobCreationCancelCode::UNKNOWN); | 
| +  host_->OnCancelBuildingBlob(kId, | 
| +                              BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS); | 
| EXPECT_FALSE(host_->shutdown_for_bad_message_); | 
|  | 
| // Start building blob. | 
| -  host_->OnRegisterBlobUUID(kId, std::string(kContentType), | 
| -                            std::string(kContentDisposition), | 
| -                            std::set<std::string>()); | 
| -  EXPECT_FALSE(host_->shutdown_for_bad_message_); | 
| DataElement element; | 
| element.SetToBytesDescription(kDataSize); | 
| std::vector<DataElement> elements = {element}; | 
| -  host_->OnStartBuildingBlob(kId, elements); | 
| +  host_->OnRegisterBlob(kId, std::string(kContentType), | 
| +                        std::string(kContentDisposition), elements); | 
| // It should have requested memory here. | 
| EXPECT_FALSE(host_->shutdown_for_bad_message_); | 
| sink_.ClearMessages(); | 
|  | 
| // Cancel in middle of construction. | 
| -  host_->OnCancelBuildingBlob(kId, IPCBlobCreationCancelCode::UNKNOWN); | 
| +  host_->OnCancelBuildingBlob(kId, BlobStatus::ERR_OUT_OF_MEMORY); | 
| +  EXPECT_FALSE(host_->shutdown_for_bad_message_); | 
| EXPECT_TRUE(context_->registry().HasEntry(kId)); | 
| EXPECT_TRUE(host_->IsInUseInHost(kId)); | 
| EXPECT_FALSE(IsBeingBuiltInHost(kId)); | 
| @@ -492,7 +478,7 @@ TEST_F(BlobDispatcherHostTest, OnCancelBuildingBlob) { | 
| ExpectHandleEqualsData(handle.get(), expecteds); | 
|  | 
| // Verify we can't cancel after the fact. | 
| -  host_->OnCancelBuildingBlob(kId, IPCBlobCreationCancelCode::UNKNOWN); | 
| +  host_->OnCancelBuildingBlob(kId, BlobStatus::ERR_OUT_OF_MEMORY); | 
| ExpectAndResetBadMessage(); | 
| } | 
|  | 
| @@ -524,9 +510,11 @@ TEST_F(BlobDispatcherHostTest, BlobReferenceWhileConstructing) { | 
| const std::string kId("id"); | 
|  | 
| // Start building blob. | 
| -  host_->OnRegisterBlobUUID(kId, std::string(kContentType), | 
| -                            std::string(kContentDisposition), | 
| -                            std::set<std::string>()); | 
| +  DataElement element; | 
| +  element.SetToBytesDescription(kDataSize); | 
| +  std::vector<DataElement> elements = {element}; | 
| +  host_->OnRegisterBlob(kId, std::string(kContentType), | 
| +                        std::string(kContentDisposition), elements); | 
|  | 
| // Grab the handle. | 
| std::unique_ptr<BlobDataHandle> blob_data_handle = | 
| @@ -534,15 +522,10 @@ TEST_F(BlobDispatcherHostTest, BlobReferenceWhileConstructing) { | 
| EXPECT_TRUE(blob_data_handle); | 
| EXPECT_TRUE(blob_data_handle->IsBeingBuilt()); | 
| bool built = false; | 
| -  IPCBlobCreationCancelCode error_code = IPCBlobCreationCancelCode::UNKNOWN; | 
| +  BlobStatus error_code = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS; | 
| blob_data_handle->RunOnConstructionComplete( | 
| base::Bind(&ConstructionCompletePopulator, &built, &error_code)); | 
|  | 
| -  // Continue building. | 
| -  DataElement element; | 
| -  element.SetToBytesDescription(kDataSize); | 
| -  std::vector<DataElement> elements = {element}; | 
| -  host_->OnStartBuildingBlob(kId, elements); | 
| sink_.ClearMessages(); | 
|  | 
| // Send data. | 
| @@ -557,41 +540,15 @@ TEST_F(BlobDispatcherHostTest, BlobReferenceWhileConstructing) { | 
| EXPECT_TRUE(built) << "Error code: " << static_cast<int>(error_code); | 
| } | 
|  | 
| -TEST_F(BlobDispatcherHostTest, BlobReferenceWhileShortcutConstructing) { | 
| +TEST_F(BlobDispatcherHostTest, BlobReferenceWhileConstructingCancelled) { | 
| const std::string kId("id"); | 
|  | 
| // Start building blob. | 
| -  host_->OnRegisterBlobUUID(kId, std::string(kContentType), | 
| -                            std::string(kContentDisposition), | 
| -                            std::set<std::string>()); | 
| - | 
| -  // Grab the handle. | 
| -  std::unique_ptr<BlobDataHandle> blob_data_handle = | 
| -      context_->GetBlobDataFromUUID(kId); | 
| -  EXPECT_TRUE(blob_data_handle); | 
| -  EXPECT_TRUE(blob_data_handle->IsBeingBuilt()); | 
| -  bool built = false; | 
| -  IPCBlobCreationCancelCode error_code = IPCBlobCreationCancelCode::UNKNOWN; | 
| -  blob_data_handle->RunOnConstructionComplete( | 
| -      base::Bind(&ConstructionCompletePopulator, &built, &error_code)); | 
| - | 
| -  // Continue building. | 
| DataElement element; | 
| -  element.SetToBytes(kData, kDataSize); | 
| +  element.SetToBytesDescription(kDataSize); | 
| std::vector<DataElement> elements = {element}; | 
| -  host_->OnStartBuildingBlob(kId, elements); | 
| -  ExpectDone(kId); | 
| -  base::RunLoop().RunUntilIdle(); | 
| -  EXPECT_TRUE(built) << "Error code: " << static_cast<int>(error_code); | 
| -} | 
| - | 
| -TEST_F(BlobDispatcherHostTest, BlobReferenceWhileConstructingCancelled) { | 
| -  const std::string kId("id"); | 
| - | 
| -  // Start building blob. | 
| -  host_->OnRegisterBlobUUID(kId, std::string(kContentType), | 
| -                            std::string(kContentDisposition), | 
| -                            std::set<std::string>()); | 
| +  host_->OnRegisterBlob(kId, std::string(kContentType), | 
| +                        std::string(kContentDisposition), elements); | 
|  | 
| // Grab the handle. | 
| std::unique_ptr<BlobDataHandle> blob_data_handle = | 
| @@ -599,25 +556,25 @@ TEST_F(BlobDispatcherHostTest, BlobReferenceWhileConstructingCancelled) { | 
| EXPECT_TRUE(blob_data_handle); | 
| EXPECT_TRUE(blob_data_handle->IsBeingBuilt()); | 
| bool built = true; | 
| -  IPCBlobCreationCancelCode error_code = IPCBlobCreationCancelCode::UNKNOWN; | 
| +  BlobStatus error_code = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS; | 
| blob_data_handle->RunOnConstructionComplete( | 
| base::Bind(&ConstructionCompletePopulator, &built, &error_code)); | 
|  | 
| // Cancel in middle of construction. | 
| -  host_->OnCancelBuildingBlob(kId, IPCBlobCreationCancelCode::UNKNOWN); | 
| +  host_->OnCancelBuildingBlob(kId, BlobStatus::ERR_OUT_OF_MEMORY); | 
| base::RunLoop().RunUntilIdle(); | 
| EXPECT_TRUE(context_->registry().HasEntry(kId)); | 
| EXPECT_TRUE(host_->IsInUseInHost(kId)); | 
| EXPECT_FALSE(IsBeingBuiltInHost(kId)); | 
| EXPECT_TRUE(blob_data_handle->IsBroken()); | 
| EXPECT_FALSE(built); | 
| -  EXPECT_EQ(IPCBlobCreationCancelCode::UNKNOWN, error_code); | 
| -  error_code = IPCBlobCreationCancelCode::UNKNOWN; | 
| +  EXPECT_EQ(BlobStatus::ERR_OUT_OF_MEMORY, error_code); | 
| +  error_code = BlobStatus::ERR_OUT_OF_MEMORY; | 
| built = true; | 
| blob_data_handle->RunOnConstructionComplete( | 
| base::Bind(&ConstructionCompletePopulator, &built, &error_code)); | 
| EXPECT_FALSE(built); | 
| -  EXPECT_EQ(IPCBlobCreationCancelCode::UNKNOWN, error_code); | 
| +  EXPECT_EQ(BlobStatus::ERR_OUT_OF_MEMORY, error_code); | 
|  | 
| // Remove it. | 
| blob_data_handle.reset(); | 
| @@ -627,59 +584,15 @@ TEST_F(BlobDispatcherHostTest, BlobReferenceWhileConstructingCancelled) { | 
| ExpectBlobNotExist(kId); | 
| } | 
|  | 
| -TEST_F(BlobDispatcherHostTest, DecrementRefAfterRegister) { | 
| -  const std::string kId("id"); | 
| -  // Decrement the refcount while building (renderer blob gc'd before | 
| -  // construction was completed). | 
| -  host_->OnRegisterBlobUUID(kId, std::string(kContentType), | 
| -                            std::string(kContentDisposition), | 
| -                            std::set<std::string>()); | 
| -  EXPECT_TRUE(context_->registry().HasEntry(kId)); | 
| -  host_->OnDecrementBlobRefCount(kId); | 
| -  EXPECT_FALSE(context_->registry().HasEntry(kId)); | 
| -  EXPECT_FALSE(IsBeingBuiltInHost(kId)); | 
| -  ExpectCancel(kId, | 
| -               IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING); | 
| -  sink_.ClearMessages(); | 
| - | 
| -  // Do the same, but this time grab a handle before we decrement. | 
| -  host_->OnRegisterBlobUUID(kId, std::string(kContentType), | 
| -                            std::string(kContentDisposition), | 
| -                            std::set<std::string>()); | 
| -  std::unique_ptr<BlobDataHandle> blob_data_handle = | 
| -      context_->GetBlobDataFromUUID(kId); | 
| -  host_->OnDecrementBlobRefCount(kId); | 
| -  EXPECT_TRUE(context_->registry().HasEntry(kId)); | 
| -  EXPECT_TRUE(IsBeingBuiltInHost(kId)); | 
| - | 
| -  // Finish up the blob, and verify we got the done message. | 
| -  DataElement element; | 
| -  element.SetToBytes(kData, kDataSize); | 
| -  std::vector<DataElement> elements = {element}; | 
| -  host_->OnStartBuildingBlob(kId, elements); | 
| -  EXPECT_FALSE(host_->shutdown_for_bad_message_); | 
| -  ExpectDone(kId); | 
| -  sink_.ClearMessages(); | 
| -  // Get rid of the handle, and verify it's gone. | 
| -  blob_data_handle.reset(); | 
| -  base::RunLoop().RunUntilIdle(); | 
| -  // Check that it's no longer around. | 
| -  EXPECT_FALSE(context_->registry().HasEntry(kId)); | 
| -  EXPECT_FALSE(IsBeingBuiltInHost(kId)); | 
| -} | 
| - | 
| TEST_F(BlobDispatcherHostTest, DecrementRefAfterOnStart) { | 
| const std::string kId("id"); | 
|  | 
| // Decrement the refcount while building, after we call OnStartBuildlingBlob. | 
| -  host_->OnRegisterBlobUUID(kId, std::string(kContentType), | 
| -                            std::string(kContentDisposition), | 
| -                            std::set<std::string>()); | 
| -  EXPECT_FALSE(host_->shutdown_for_bad_message_); | 
| DataElement element; | 
| element.SetToBytesDescription(kDataSize); | 
| std::vector<DataElement> elements = {element}; | 
| -  host_->OnStartBuildingBlob(kId, elements); | 
| +  host_->OnRegisterBlob(kId, std::string(kContentType), | 
| +                        std::string(kContentDisposition), elements); | 
| EXPECT_FALSE(host_->shutdown_for_bad_message_); | 
|  | 
| std::vector<BlobItemBytesRequest> expected_requests = { | 
| @@ -690,16 +603,12 @@ TEST_F(BlobDispatcherHostTest, DecrementRefAfterOnStart) { | 
| host_->OnDecrementBlobRefCount(kId); | 
| EXPECT_FALSE(context_->registry().HasEntry(kId)); | 
| EXPECT_FALSE(IsBeingBuiltInHost(kId)); | 
| -  ExpectCancel(kId, | 
| -               IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING); | 
| +  ExpectCancel(kId, BlobStatus::ERR_BLOB_DEREFERENCED_WHILE_BUILDING); | 
| sink_.ClearMessages(); | 
|  | 
| // Do the same, but this time grab a handle to keep it alive. | 
| -  host_->OnRegisterBlobUUID(kId, std::string(kContentType), | 
| -                            std::string(kContentDisposition), | 
| -                            std::set<std::string>()); | 
| -  EXPECT_FALSE(host_->shutdown_for_bad_message_); | 
| -  host_->OnStartBuildingBlob(kId, elements); | 
| +  host_->OnRegisterBlob(kId, std::string(kContentType), | 
| +                        std::string(kContentDisposition), elements); | 
| EXPECT_FALSE(host_->shutdown_for_bad_message_); | 
| ExpectRequest(kId, expected_requests); | 
| sink_.ClearMessages(); | 
| @@ -710,6 +619,7 @@ TEST_F(BlobDispatcherHostTest, DecrementRefAfterOnStart) { | 
| host_->OnDecrementBlobRefCount(kId); | 
| EXPECT_TRUE(context_->registry().HasEntry(kId)); | 
| EXPECT_TRUE(IsBeingBuiltInHost(kId)); | 
| +  EXPECT_EQ(0u, sink_.message_count()); | 
|  | 
| // We finish the blob, and verify that we send 'Done' back to the renderer. | 
| BlobItemBytesResponse response(0); | 
| @@ -734,25 +644,21 @@ TEST_F(BlobDispatcherHostTest, DecrementRefAfterOnStartWithHandle) { | 
| const std::string kId("id"); | 
| // Decrement the refcount while building, after we call | 
| // OnStartBuildlingBlob, except we have another handle. | 
| -  host_->OnRegisterBlobUUID(kId, std::string(kContentType), | 
| -                            std::string(kContentDisposition), | 
| -                            std::set<std::string>()); | 
| +  DataElement element; | 
| +  element.SetToBytesDescription(kDataSize); | 
| +  std::vector<DataElement> elements = {element}; | 
| +  host_->OnRegisterBlob(kId, std::string(kContentType), | 
| +                        std::string(kContentDisposition), elements); | 
| EXPECT_FALSE(host_->shutdown_for_bad_message_); | 
|  | 
| std::unique_ptr<BlobDataHandle> blob_data_handle = | 
| context_->GetBlobDataFromUUID(kId); | 
| EXPECT_TRUE(blob_data_handle->IsBeingBuilt()); | 
| bool built = true; | 
| -  IPCBlobCreationCancelCode error_code = IPCBlobCreationCancelCode::UNKNOWN; | 
| +  BlobStatus error_code = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS; | 
| blob_data_handle->RunOnConstructionComplete( | 
| base::Bind(&ConstructionCompletePopulator, &built, &error_code)); | 
|  | 
| -  DataElement element; | 
| -  element.SetToBytesDescription(kDataSize); | 
| -  std::vector<DataElement> elements = {element}; | 
| -  host_->OnStartBuildingBlob(kId, elements); | 
| -  EXPECT_FALSE(host_->shutdown_for_bad_message_); | 
| - | 
| // Check that we got the expected request. | 
| std::vector<BlobItemBytesRequest> expected_requests = { | 
| BlobItemBytesRequest::CreateIPCRequest(0, 0, 0, kDataSize)}; | 
| @@ -767,14 +673,14 @@ TEST_F(BlobDispatcherHostTest, DecrementRefAfterOnStartWithHandle) { | 
| EXPECT_TRUE(blob_data_handle->IsBeingBuilt()); | 
| EXPECT_TRUE(IsBeingBuiltInHost(kId)); | 
| // Cancel to clean up. | 
| -  host_->OnCancelBuildingBlob(kId, IPCBlobCreationCancelCode::UNKNOWN); | 
| +  host_->OnCancelBuildingBlob(kId, BlobStatus::ERR_OUT_OF_MEMORY); | 
| // Run loop to propagate the handle decrement in the host. | 
| base::RunLoop().RunUntilIdle(); | 
| // We still have the entry because of our earlier handle. | 
| EXPECT_TRUE(context_->registry().HasEntry(kId)); | 
| EXPECT_FALSE(IsBeingBuiltInHost(kId)); | 
| EXPECT_FALSE(built); | 
| -  EXPECT_EQ(IPCBlobCreationCancelCode::UNKNOWN, error_code); | 
| +  EXPECT_EQ(BlobStatus::ERR_OUT_OF_MEMORY, error_code); | 
| sink_.ClearMessages(); | 
|  | 
| // Should disappear after dropping the handle. | 
| @@ -784,52 +690,15 @@ TEST_F(BlobDispatcherHostTest, DecrementRefAfterOnStartWithHandle) { | 
| EXPECT_FALSE(context_->registry().HasEntry(kId)); | 
| } | 
|  | 
| -TEST_F(BlobDispatcherHostTest, HostDisconnectAfterRegisterWithHandle) { | 
| -  const std::string kId("id"); | 
| - | 
| -  // Delete host with a handle to the blob. | 
| -  host_->OnRegisterBlobUUID(kId, std::string(kContentType), | 
| -                            std::string(kContentDisposition), | 
| -                            std::set<std::string>()); | 
| - | 
| -  std::unique_ptr<BlobDataHandle> blob_data_handle = | 
| -      context_->GetBlobDataFromUUID(kId); | 
| -  EXPECT_TRUE(blob_data_handle->IsBeingBuilt()); | 
| -  bool built = true; | 
| -  IPCBlobCreationCancelCode error_code = IPCBlobCreationCancelCode::UNKNOWN; | 
| -  blob_data_handle->RunOnConstructionComplete( | 
| -      base::Bind(&ConstructionCompletePopulator, &built, &error_code)); | 
| -  // Get rid of host, which was doing the constructing. | 
| -  host_ = nullptr; | 
| -  EXPECT_FALSE(blob_data_handle->IsBeingBuilt()); | 
| -  base::RunLoop().RunUntilIdle(); | 
| -  EXPECT_FALSE(built); | 
| -  EXPECT_EQ(IPCBlobCreationCancelCode::SOURCE_DIED_IN_TRANSIT, error_code); | 
| - | 
| -  // Should still be there due to the handle. | 
| -  std::unique_ptr<BlobDataHandle> another_handle = | 
| -      context_->GetBlobDataFromUUID(kId); | 
| -  EXPECT_TRUE(another_handle); | 
| - | 
| -  // Should disappear after dropping both handles. | 
| -  blob_data_handle.reset(); | 
| -  another_handle.reset(); | 
| -  base::RunLoop().RunUntilIdle(); | 
| -  EXPECT_FALSE(context_->registry().HasEntry(kId)); | 
| -} | 
| - | 
| TEST_F(BlobDispatcherHostTest, HostDisconnectAfterOnStart) { | 
| const std::string kId("id"); | 
|  | 
| // Host deleted after OnStartBuilding. | 
| -  host_->OnRegisterBlobUUID(kId, std::string(kContentType), | 
| -                            std::string(kContentDisposition), | 
| -                            std::set<std::string>()); | 
| - | 
| DataElement element; | 
| element.SetToBytesDescription(kDataSize); | 
| std::vector<DataElement> elements = {element}; | 
| -  host_->OnStartBuildingBlob(kId, elements); | 
| +  host_->OnRegisterBlob(kId, std::string(kContentType), | 
| +                        std::string(kContentDisposition), elements); | 
|  | 
| std::vector<BlobItemBytesRequest> expected_requests = { | 
| BlobItemBytesRequest::CreateIPCRequest(0, 0, 0, kDataSize)}; | 
| @@ -845,15 +714,13 @@ TEST_F(BlobDispatcherHostTest, HostDisconnectAfterOnMemoryResponse) { | 
| const std::string kId("id"); | 
|  | 
| // Host deleted after OnMemoryItemResponse. | 
| -  host_->OnRegisterBlobUUID(kId, std::string(kContentType), | 
| -                            std::string(kContentDisposition), | 
| -                            std::set<std::string>()); | 
| - | 
| -  // Create list of two items. | 
| DataElement element; | 
| element.SetToBytesDescription(kDataSize); | 
| std::vector<DataElement> elements = {element, element}; | 
| -  host_->OnStartBuildingBlob(kId, elements); | 
| +  host_->OnRegisterBlob(kId, std::string(kContentType), | 
| +                        std::string(kContentDisposition), elements); | 
| + | 
| +  // Create list of two items. | 
| std::vector<BlobItemBytesRequest> expected_requests = { | 
| BlobItemBytesRequest::CreateIPCRequest(0, 0, 0, kDataSize), | 
| BlobItemBytesRequest::CreateIPCRequest(1, 1, 0, kDataSize)}; | 
| @@ -878,37 +745,41 @@ TEST_F(BlobDispatcherHostTest, CreateBlobWithBrokenReference) { | 
|  | 
| // First, let's test a circular reference. | 
| const std::string kCircularId("id1"); | 
| -  host_->OnRegisterBlobUUID(kCircularId, std::string(kContentType), | 
| -                            std::string(kContentDisposition), {kCircularId}); | 
| +  DataElement element; | 
| +  element.SetToBlob(kCircularId); | 
| +  std::vector<DataElement> elements = {element}; | 
| +  host_->OnRegisterBlob(kCircularId, std::string(kContentType), | 
| +                        std::string(kContentDisposition), elements); | 
| ExpectAndResetBadMessage(); | 
| +  // Remove the blob. | 
| +  host_->OnDecrementBlobRefCount(kCircularId); | 
| +  sink_.ClearMessages(); | 
|  | 
| // Next, test a blob that references a broken blob. | 
| -  host_->OnRegisterBlobUUID(kBrokenId, std::string(kContentType), | 
| -                            std::string(kContentDisposition), | 
| -                            std::set<std::string>()); | 
| -  host_->OnCancelBuildingBlob(kBrokenId, IPCBlobCreationCancelCode::UNKNOWN); | 
| +  element.SetToBytesDescription(kDataSize); | 
| +  elements = {element}; | 
| +  host_->OnRegisterBlob(kBrokenId, std::string(kContentType), | 
| +                        std::string(kContentDisposition), elements); | 
| +  EXPECT_FALSE(host_->shutdown_for_bad_message_); | 
| +  sink_.ClearMessages(); | 
| +  host_->OnCancelBuildingBlob(kBrokenId, BlobStatus::ERR_OUT_OF_MEMORY); | 
| EXPECT_FALSE(host_->shutdown_for_bad_message_); | 
| +  sink_.ClearMessages(); | 
| EXPECT_TRUE(context_->GetBlobDataFromUUID(kBrokenId)->IsBroken()); | 
|  | 
| // Create referencing blob. We should be broken right away, but also ignore | 
| // the subsequent OnStart message. | 
| -  host_->OnRegisterBlobUUID(kReferencingId, std::string(kContentType), | 
| -                            std::string(kContentDisposition), {kBrokenId}); | 
| +  element.SetToBytesDescription(kDataSize); | 
| +  elements = {element}; | 
| +  element.SetToBlob(kBrokenId); | 
| +  elements.push_back(element); | 
| +  host_->OnRegisterBlob(kReferencingId, std::string(kContentType), | 
| +                        std::string(kContentDisposition), elements); | 
| EXPECT_TRUE(context_->GetBlobDataFromUUID(kReferencingId)->IsBroken()); | 
| EXPECT_FALSE(IsBeingBuiltInHost(kReferencingId)); | 
| EXPECT_TRUE(context_->registry().HasEntry(kReferencingId)); | 
| -  ExpectCancel(kReferencingId, | 
| -               IPCBlobCreationCancelCode::REFERENCED_BLOB_BROKEN); | 
| +  ExpectCancel(kReferencingId, BlobStatus::ERR_REFERENCED_BLOB_BROKEN); | 
| sink_.ClearMessages(); | 
| - | 
| -  DataElement element; | 
| -  element.SetToBytesDescription(kDataSize); | 
| -  std::vector<DataElement> elements = {element}; | 
| -  element.SetToBlob(kBrokenId); | 
| -  elements.push_back(element); | 
| -  host_->OnStartBuildingBlob(kReferencingId, elements); | 
| -  EXPECT_EQ(0u, sink_.message_count()); | 
| -  base::RunLoop().RunUntilIdle(); | 
| } | 
|  | 
| TEST_F(BlobDispatcherHostTest, DeferenceBlobOnDifferentHost) { | 
| @@ -932,66 +803,46 @@ TEST_F(BlobDispatcherHostTest, DeferenceBlobOnDifferentHost) { | 
| // verify that a building message from the renderer will kill it. | 
|  | 
| // Test OnStartBuilding after double dereference. | 
| -  host_->OnRegisterBlobUUID(kId, std::string(kContentType), | 
| -                            std::string(kContentDisposition), | 
| -                            std::set<std::string>()); | 
| -  host2->OnIncrementBlobRefCount(kId); | 
| -  host_->OnDecrementBlobRefCount(kId); | 
| -  EXPECT_FALSE(host_->IsInUseInHost(kId)); | 
| -  host2->OnDecrementBlobRefCount(kId); | 
| -  // So no more blob in the context, but we're still being built in host 1. | 
| -  EXPECT_FALSE(context_->registry().HasEntry(kId)); | 
| -  EXPECT_TRUE(host_->async_builder_.IsBeingBuilt(kId)); | 
| -  host_->OnStartBuildingBlob(kId, elements); | 
| +  host_->OnRegisterBlob(kId, std::string(kContentType), | 
| +                        std::string(kContentDisposition), elements); | 
| EXPECT_FALSE(host_->shutdown_for_bad_message_); | 
| -  // We should be cleaned up. | 
| -  EXPECT_FALSE(host_->async_builder_.IsBeingBuilt(kId)); | 
| -  ExpectCancel(kId, | 
| -               IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING); | 
| +  ExpectRequest(kId, expected_requests); | 
| sink_.ClearMessages(); | 
| - | 
| -  // Same as above, but test OnMemoryItemResponse after double dereference. | 
| -  host_->OnRegisterBlobUUID(kId, std::string(kContentType), | 
| -                            std::string(kContentDisposition), | 
| -                            std::set<std::string>()); | 
| host2->OnIncrementBlobRefCount(kId); | 
| host_->OnDecrementBlobRefCount(kId); | 
| EXPECT_FALSE(host_->IsInUseInHost(kId)); | 
| -  host_->OnStartBuildingBlob(kId, elements); | 
| -  ExpectRequest(kId, expected_requests); | 
| -  sink_.ClearMessages(); | 
| - | 
| host2->OnDecrementBlobRefCount(kId); | 
| -  // So no more blob in the context, but we're still being built in host 1. | 
| +  // Blob is gone as we've been decremented from both hosts. | 
| EXPECT_FALSE(context_->registry().HasEntry(kId)); | 
| -  EXPECT_TRUE(host_->async_builder_.IsBeingBuilt(kId)); | 
| +  // Send the memory. When the host sees the entry doesn't exist, it should | 
| +  // cancel and clean up. | 
| +  EXPECT_TRUE(host_->transport_host_.IsBeingBuilt(kId)); | 
| host_->OnMemoryItemResponse(kId, responses); | 
| -  EXPECT_FALSE(host_->shutdown_for_bad_message_); | 
| // We should be cleaned up. | 
| -  EXPECT_FALSE(host_->async_builder_.IsBeingBuilt(kId)); | 
| -  ExpectCancel(kId, | 
| -               IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING); | 
| +  EXPECT_FALSE(context_->registry().HasEntry(kId)); | 
| +  EXPECT_FALSE(host_->transport_host_.IsBeingBuilt(kId)); | 
| +  ExpectCancel(kId, BlobStatus::ERR_BLOB_DEREFERENCED_WHILE_BUILDING); | 
| sink_.ClearMessages(); | 
|  | 
| // Same, but now for OnCancel. | 
| -  host_->OnRegisterBlobUUID(kId, std::string(kContentType), | 
| -                            std::string(kContentDisposition), | 
| -                            std::set<std::string>()); | 
| +  host_->OnRegisterBlob(kId, std::string(kContentType), | 
| +                        std::string(kContentDisposition), elements); | 
| host2->OnIncrementBlobRefCount(kId); | 
| host_->OnDecrementBlobRefCount(kId); | 
| EXPECT_FALSE(host_->IsInUseInHost(kId)); | 
| -  host_->OnStartBuildingBlob(kId, elements); | 
| ExpectRequest(kId, expected_requests); | 
| sink_.ClearMessages(); | 
|  | 
| host2->OnDecrementBlobRefCount(kId); | 
| -  // So no more blob in the context, but we're still being built in host 1. | 
| +  // Blob is gone as we've been decremented from both hosts. | 
| EXPECT_FALSE(context_->registry().HasEntry(kId)); | 
| -  EXPECT_TRUE(host_->async_builder_.IsBeingBuilt(kId)); | 
| -  host_->OnCancelBuildingBlob(kId, IPCBlobCreationCancelCode::UNKNOWN); | 
| +  EXPECT_TRUE(host_->transport_host_.IsBeingBuilt(kId)); | 
| +  host_->OnCancelBuildingBlob(kId, BlobStatus::ERR_OUT_OF_MEMORY); | 
| EXPECT_FALSE(host_->shutdown_for_bad_message_); | 
| +  EXPECT_FALSE(context_->registry().HasEntry(kId)); | 
| // We should be cleaned up. | 
| -  EXPECT_FALSE(host_->async_builder_.IsBeingBuilt(kId)); | 
| +  EXPECT_FALSE(host_->transport_host_.IsBeingBuilt(kId)); | 
| +  ExpectCancel(kId, BlobStatus::ERR_BLOB_DEREFERENCED_WHILE_BUILDING); | 
| } | 
|  | 
| TEST_F(BlobDispatcherHostTest, BuildingReferenceChain) { | 
| @@ -1000,12 +851,16 @@ TEST_F(BlobDispatcherHostTest, BuildingReferenceChain) { | 
| const std::string kDifferentHostReferencingId("id3"); | 
| // Data elements for our transfer & checking messages. | 
| DataElement element; | 
| -  element.SetToBytes(kData, kDataSize); | 
| -  std::vector<DataElement> elements = {element}; | 
| +  element.SetToBytesDescription(kDataSize); | 
| DataElement referencing_element; | 
| referencing_element.SetToBlob(kId); | 
| +  std::vector<DataElement> elements = {element}; | 
| std::vector<DataElement> referencing_elements = {referencing_element}; | 
| -  std::set<std::string> referenced_blobs_set = {kId}; | 
| +  std::vector<BlobItemBytesRequest> expected_requests = { | 
| +      BlobItemBytesRequest::CreateIPCRequest(0, 0, 0, kDataSize)}; | 
| +  BlobItemBytesResponse response(0); | 
| +  std::memcpy(response.allocate_mutable_data(kDataSize), kData, kDataSize); | 
| +  std::vector<BlobItemBytesResponse> responses = {response}; | 
|  | 
| scoped_refptr<TestableBlobDispatcherHost> host2( | 
| new TestableBlobDispatcherHost(chrome_blob_storage_context_, | 
| @@ -1016,39 +871,44 @@ TEST_F(BlobDispatcherHostTest, BuildingReferenceChain) { | 
| // after the referenced blob is finished. | 
|  | 
| // First we start the referenced blob. | 
| -  host_->OnRegisterBlobUUID(kId, std::string(kContentType), | 
| -                            std::string(kContentDisposition), | 
| -                            std::set<std::string>()); | 
| +  host_->OnRegisterBlob(kId, std::string(kContentType), | 
| +                        std::string(kContentDisposition), elements); | 
| +  ExpectRequest(kId, expected_requests); | 
| +  sink_.ClearMessages(); | 
| EXPECT_TRUE(host_->IsInUseInHost(kId)); | 
| +  EXPECT_TRUE(IsBeingBuiltInContext(kId)); | 
|  | 
| // Next we start the referencing blobs in both the same and different host. | 
| -  host_->OnRegisterBlobUUID(kSameHostReferencingId, std::string(kContentType), | 
| -                            std::string(kContentDisposition), | 
| -                            referenced_blobs_set); | 
| -  EXPECT_FALSE(host_->shutdown_for_bad_message_); | 
| -  host_->OnStartBuildingBlob(kSameHostReferencingId, referencing_elements); | 
| +  host_->OnRegisterBlob(kSameHostReferencingId, std::string(kContentType), | 
| +                        std::string(kContentDisposition), referencing_elements); | 
| EXPECT_FALSE(host_->shutdown_for_bad_message_); | 
| ExpectDone(kSameHostReferencingId); | 
| -  EXPECT_TRUE(host_->async_builder_.IsBeingBuilt(kSameHostReferencingId)); | 
| sink_.ClearMessages(); | 
| +  EXPECT_FALSE( | 
| +      context_->GetBlobDataFromUUID(kSameHostReferencingId)->IsBroken()); | 
| +  EXPECT_FALSE(host_->transport_host_.IsBeingBuilt(kSameHostReferencingId)); | 
| +  EXPECT_TRUE(IsBeingBuiltInContext(kSameHostReferencingId)); | 
| + | 
| // Now the other host. | 
| -  host2->OnRegisterBlobUUID( | 
| -      kDifferentHostReferencingId, std::string(kContentType), | 
| -      std::string(kContentDisposition), referenced_blobs_set); | 
| -  EXPECT_FALSE(host2->shutdown_for_bad_message_); | 
| -  host2->OnStartBuildingBlob(kDifferentHostReferencingId, referencing_elements); | 
| +  host2->OnRegisterBlob(kDifferentHostReferencingId, std::string(kContentType), | 
| +                        std::string(kContentDisposition), referencing_elements); | 
| EXPECT_FALSE(host2->shutdown_for_bad_message_); | 
| ExpectDone(kDifferentHostReferencingId); | 
| -  EXPECT_TRUE(host2->async_builder_.IsBeingBuilt(kDifferentHostReferencingId)); | 
| sink_.ClearMessages(); | 
| +  EXPECT_FALSE( | 
| +      context_->GetBlobDataFromUUID(kDifferentHostReferencingId)->IsBroken()); | 
| +  EXPECT_FALSE( | 
| +      host2->transport_host_.IsBeingBuilt(kDifferentHostReferencingId)); | 
| +  EXPECT_TRUE(IsBeingBuiltInContext(kDifferentHostReferencingId)); | 
|  | 
| // Now we finish the first blob, and we expect all blobs to finish. | 
| -  host_->OnStartBuildingBlob(kId, elements); | 
| +  host_->OnMemoryItemResponse(kId, responses); | 
| ExpectDone(kId); | 
| // We need to run the message loop to propagate the construction callbacks. | 
| base::RunLoop().RunUntilIdle(); | 
| -  EXPECT_FALSE(host2->async_builder_.IsBeingBuilt(kDifferentHostReferencingId)); | 
| -  EXPECT_FALSE(host_->async_builder_.IsBeingBuilt(kSameHostReferencingId)); | 
| +  EXPECT_FALSE( | 
| +      host2->transport_host_.IsBeingBuilt(kDifferentHostReferencingId)); | 
| +  EXPECT_FALSE(host_->transport_host_.IsBeingBuilt(kSameHostReferencingId)); | 
| EXPECT_FALSE( | 
| context_->GetBlobDataFromUUID(kSameHostReferencingId)->IsBroken()); | 
| EXPECT_FALSE( | 
| @@ -1058,7 +918,10 @@ TEST_F(BlobDispatcherHostTest, BuildingReferenceChain) { | 
| // Finally check that our data is correct in the child elements. | 
| std::unique_ptr<BlobDataHandle> handle = | 
| context_->GetBlobDataFromUUID(kDifferentHostReferencingId); | 
| -  ExpectHandleEqualsData(handle.get(), elements); | 
| +  DataElement expected; | 
| +  expected.SetToBytes(kData, kDataSize); | 
| +  std::vector<DataElement> expecteds = {expected}; | 
| +  ExpectHandleEqualsData(handle.get(), expecteds); | 
| } | 
|  | 
| TEST_F(BlobDispatcherHostTest, BuildingReferenceChainWithCancel) { | 
| @@ -1066,59 +929,73 @@ TEST_F(BlobDispatcherHostTest, BuildingReferenceChainWithCancel) { | 
| const std::string kSameHostReferencingId("id2"); | 
| const std::string kDifferentHostReferencingId("id3"); | 
| // Data elements for our transfer & checking messages. | 
| +  DataElement element; | 
| +  element.SetToBytesDescription(kDataSize); | 
| DataElement referencing_element; | 
| referencing_element.SetToBlob(kId); | 
| +  std::vector<DataElement> elements = {element}; | 
| std::vector<DataElement> referencing_elements = {referencing_element}; | 
| -  std::set<std::string> referenced_blobs_set = {kId}; | 
| +  std::vector<BlobItemBytesRequest> expected_requests = { | 
| +      BlobItemBytesRequest::CreateIPCRequest(0, 0, 0, kDataSize)}; | 
|  | 
| scoped_refptr<TestableBlobDispatcherHost> host2( | 
| new TestableBlobDispatcherHost(chrome_blob_storage_context_, | 
| file_system_context_.get(), &sink_)); | 
|  | 
| // We want to have a blob referencing another blob that is building, both on | 
| -  // the same host and a different host. After we cancel the first blob, the | 
| -  // others should cancel as well. | 
| +  // the same host and a different host. We should successfully build all blobs | 
| +  // after the referenced blob is finished. | 
|  | 
| // First we start the referenced blob. | 
| -  host_->OnRegisterBlobUUID(kId, std::string(kContentType), | 
| -                            std::string(kContentDisposition), | 
| -                            std::set<std::string>()); | 
| +  host_->OnRegisterBlob(kId, std::string(kContentType), | 
| +                        std::string(kContentDisposition), elements); | 
| +  ExpectRequest(kId, expected_requests); | 
| +  sink_.ClearMessages(); | 
| EXPECT_TRUE(host_->IsInUseInHost(kId)); | 
| +  EXPECT_TRUE(IsBeingBuiltInContext(kId)); | 
|  | 
| // Next we start the referencing blobs in both the same and different host. | 
| -  host_->OnRegisterBlobUUID(kSameHostReferencingId, std::string(kContentType), | 
| -                            std::string(kContentDisposition), | 
| -                            referenced_blobs_set); | 
| -  host_->OnStartBuildingBlob(kSameHostReferencingId, referencing_elements); | 
| +  host_->OnRegisterBlob(kSameHostReferencingId, std::string(kContentType), | 
| +                        std::string(kContentDisposition), referencing_elements); | 
| +  EXPECT_FALSE(host_->shutdown_for_bad_message_); | 
| ExpectDone(kSameHostReferencingId); | 
| -  EXPECT_TRUE(host_->async_builder_.IsBeingBuilt(kSameHostReferencingId)); | 
| sink_.ClearMessages(); | 
| +  EXPECT_FALSE( | 
| +      context_->GetBlobDataFromUUID(kSameHostReferencingId)->IsBroken()); | 
| +  EXPECT_FALSE(host_->transport_host_.IsBeingBuilt(kSameHostReferencingId)); | 
| +  EXPECT_TRUE(IsBeingBuiltInContext(kSameHostReferencingId)); | 
| + | 
| // Now the other host. | 
| -  host2->OnRegisterBlobUUID( | 
| -      kDifferentHostReferencingId, std::string(kContentType), | 
| -      std::string(kContentDisposition), referenced_blobs_set); | 
| -  host2->OnStartBuildingBlob(kDifferentHostReferencingId, referencing_elements); | 
| +  host2->OnRegisterBlob(kDifferentHostReferencingId, std::string(kContentType), | 
| +                        std::string(kContentDisposition), referencing_elements); | 
| +  EXPECT_FALSE(host2->shutdown_for_bad_message_); | 
| ExpectDone(kDifferentHostReferencingId); | 
| -  EXPECT_TRUE(host2->async_builder_.IsBeingBuilt(kDifferentHostReferencingId)); | 
| sink_.ClearMessages(); | 
| +  EXPECT_FALSE( | 
| +      context_->GetBlobDataFromUUID(kDifferentHostReferencingId)->IsBroken()); | 
| +  EXPECT_FALSE( | 
| +      host2->transport_host_.IsBeingBuilt(kDifferentHostReferencingId)); | 
| +  EXPECT_TRUE(IsBeingBuiltInContext(kDifferentHostReferencingId)); | 
| + | 
| bool built = false; | 
| -  IPCBlobCreationCancelCode error_code = IPCBlobCreationCancelCode::UNKNOWN; | 
| +  BlobStatus error_code = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS; | 
| context_->GetBlobDataFromUUID(kDifferentHostReferencingId) | 
| ->RunOnConstructionComplete( | 
| base::Bind(&ConstructionCompletePopulator, &built, &error_code)); | 
|  | 
| // Now we cancel the first blob, and we expect all blobs to cancel. | 
| -  host_->OnCancelBuildingBlob(kId, IPCBlobCreationCancelCode::UNKNOWN); | 
| +  host_->OnCancelBuildingBlob(kId, BlobStatus::ERR_OUT_OF_MEMORY); | 
| // We need to run the message loop to propagate the construction callbacks. | 
| base::RunLoop().RunUntilIdle(); | 
| -  EXPECT_FALSE(host2->async_builder_.IsBeingBuilt(kDifferentHostReferencingId)); | 
| -  EXPECT_FALSE(host_->async_builder_.IsBeingBuilt(kSameHostReferencingId)); | 
| +  EXPECT_FALSE( | 
| +      host2->transport_host_.IsBeingBuilt(kDifferentHostReferencingId)); | 
| +  EXPECT_FALSE(host_->transport_host_.IsBeingBuilt(kSameHostReferencingId)); | 
| EXPECT_TRUE( | 
| context_->GetBlobDataFromUUID(kSameHostReferencingId)->IsBroken()); | 
| EXPECT_TRUE( | 
| context_->GetBlobDataFromUUID(kDifferentHostReferencingId)->IsBroken()); | 
| EXPECT_FALSE(built); | 
| -  EXPECT_EQ(IPCBlobCreationCancelCode::REFERENCED_BLOB_BROKEN, error_code); | 
| +  EXPECT_EQ(BlobStatus::ERR_REFERENCED_BLOB_BROKEN, error_code); | 
| sink_.ClearMessages(); | 
| } | 
|  | 
| @@ -1127,61 +1004,67 @@ TEST_F(BlobDispatcherHostTest, BuildingReferenceChainWithSourceDeath) { | 
| const std::string kSameHostReferencingId("id2"); | 
| const std::string kDifferentHostReferencingId("id3"); | 
| // Data elements for our transfer & checking messages. | 
| +  DataElement element; | 
| +  element.SetToBytesDescription(kDataSize); | 
| DataElement referencing_element; | 
| referencing_element.SetToBlob(kId); | 
| +  std::vector<DataElement> elements = {element}; | 
| std::vector<DataElement> referencing_elements = {referencing_element}; | 
| -  std::set<std::string> referenced_blobs_set = {kId}; | 
| +  std::vector<BlobItemBytesRequest> expected_requests = { | 
| +      BlobItemBytesRequest::CreateIPCRequest(0, 0, 0, kDataSize)}; | 
| +  BlobItemBytesResponse response(0); | 
| +  std::memcpy(response.allocate_mutable_data(kDataSize), kData, kDataSize); | 
| +  std::vector<BlobItemBytesResponse> responses = {response}; | 
|  | 
| scoped_refptr<TestableBlobDispatcherHost> host2( | 
| new TestableBlobDispatcherHost(chrome_blob_storage_context_, | 
| file_system_context_.get(), &sink_)); | 
|  | 
| // We want to have a blob referencing another blob that is building, both on | 
| -  // the same host and a different host. When we destroy the host, the other | 
| -  // blob should cancel, as well as the blob on the other host. | 
| +  // the same host and a different host. We should successfully build all blobs | 
| +  // after the referenced blob is finished. | 
|  | 
| // First we start the referenced blob. | 
| -  host_->OnRegisterBlobUUID(kId, std::string(kContentType), | 
| -                            std::string(kContentDisposition), | 
| -                            std::set<std::string>()); | 
| +  host_->OnRegisterBlob(kId, std::string(kContentType), | 
| +                        std::string(kContentDisposition), elements); | 
| +  ExpectRequest(kId, expected_requests); | 
| +  sink_.ClearMessages(); | 
| EXPECT_TRUE(host_->IsInUseInHost(kId)); | 
| +  EXPECT_TRUE(IsBeingBuiltInContext(kId)); | 
|  | 
| // Next we start the referencing blobs in both the same and different host. | 
| -  host_->OnRegisterBlobUUID(kSameHostReferencingId, std::string(kContentType), | 
| -                            std::string(kContentDisposition), | 
| -                            referenced_blobs_set); | 
| -  host_->OnStartBuildingBlob(kSameHostReferencingId, referencing_elements); | 
| +  host_->OnRegisterBlob(kSameHostReferencingId, std::string(kContentType), | 
| +                        std::string(kContentDisposition), referencing_elements); | 
| +  EXPECT_FALSE(host_->shutdown_for_bad_message_); | 
| ExpectDone(kSameHostReferencingId); | 
| -  EXPECT_TRUE(host_->async_builder_.IsBeingBuilt(kSameHostReferencingId)); | 
| sink_.ClearMessages(); | 
| + | 
| // Now the other host. | 
| -  host2->OnRegisterBlobUUID( | 
| -      kDifferentHostReferencingId, std::string(kContentType), | 
| -      std::string(kContentDisposition), referenced_blobs_set); | 
| -  host2->OnStartBuildingBlob(kDifferentHostReferencingId, referencing_elements); | 
| +  host2->OnRegisterBlob(kDifferentHostReferencingId, std::string(kContentType), | 
| +                        std::string(kContentDisposition), referencing_elements); | 
| +  EXPECT_FALSE(host2->shutdown_for_bad_message_); | 
| ExpectDone(kDifferentHostReferencingId); | 
| -  EXPECT_TRUE(host2->async_builder_.IsBeingBuilt(kDifferentHostReferencingId)); | 
| sink_.ClearMessages(); | 
|  | 
| // Grab handles & add listeners. | 
| bool built = true; | 
| -  IPCBlobCreationCancelCode error_code = IPCBlobCreationCancelCode::UNKNOWN; | 
| +  BlobStatus error_code = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS; | 
| std::unique_ptr<BlobDataHandle> blob_handle = | 
| context_->GetBlobDataFromUUID(kId); | 
| blob_handle->RunOnConstructionComplete( | 
| base::Bind(&ConstructionCompletePopulator, &built, &error_code)); | 
|  | 
| bool same_host_built = true; | 
| -  IPCBlobCreationCancelCode same_host_error_code = | 
| -      IPCBlobCreationCancelCode::UNKNOWN; | 
| +  BlobStatus same_host_error_code = | 
| +      BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS; | 
| std::unique_ptr<BlobDataHandle> same_host_blob_handle = | 
| context_->GetBlobDataFromUUID(kSameHostReferencingId); | 
| same_host_blob_handle->RunOnConstructionComplete(base::Bind( | 
| &ConstructionCompletePopulator, &same_host_built, &same_host_error_code)); | 
|  | 
| bool other_host_built = true; | 
| -  IPCBlobCreationCancelCode other_host_error_code = | 
| -      IPCBlobCreationCancelCode::UNKNOWN; | 
| +  BlobStatus other_host_error_code = | 
| +      BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS; | 
| std::unique_ptr<BlobDataHandle> other_host_blob_handle = | 
| context_->GetBlobDataFromUUID(kDifferentHostReferencingId); | 
| other_host_blob_handle->RunOnConstructionComplete( | 
| @@ -1192,7 +1075,8 @@ TEST_F(BlobDispatcherHostTest, BuildingReferenceChainWithSourceDeath) { | 
| host_ = nullptr; | 
| // We need to run the message loop to propagate the construction callbacks. | 
| base::RunLoop().RunUntilIdle(); | 
| -  EXPECT_FALSE(host2->async_builder_.IsBeingBuilt(kDifferentHostReferencingId)); | 
| +  EXPECT_FALSE( | 
| +      host2->transport_host_.IsBeingBuilt(kDifferentHostReferencingId)); | 
| EXPECT_TRUE( | 
| context_->GetBlobDataFromUUID(kSameHostReferencingId)->IsBroken()); | 
| EXPECT_TRUE( | 
| @@ -1200,13 +1084,11 @@ TEST_F(BlobDispatcherHostTest, BuildingReferenceChainWithSourceDeath) { | 
|  | 
| // Check our callbacks | 
| EXPECT_FALSE(built); | 
| -  EXPECT_EQ(IPCBlobCreationCancelCode::SOURCE_DIED_IN_TRANSIT, error_code); | 
| +  EXPECT_EQ(BlobStatus::ERR_SOURCE_DIED_IN_TRANSIT, error_code); | 
| EXPECT_FALSE(same_host_built); | 
| -  EXPECT_EQ(IPCBlobCreationCancelCode::SOURCE_DIED_IN_TRANSIT, | 
| -            same_host_error_code); | 
| +  EXPECT_EQ(BlobStatus::ERR_REFERENCED_BLOB_BROKEN, same_host_error_code); | 
| EXPECT_FALSE(other_host_built); | 
| -  EXPECT_EQ(IPCBlobCreationCancelCode::SOURCE_DIED_IN_TRANSIT, | 
| -            other_host_error_code); | 
| +  EXPECT_EQ(BlobStatus::ERR_REFERENCED_BLOB_BROKEN, other_host_error_code); | 
|  | 
| sink_.ClearMessages(); | 
| } | 
|  |