| Index: content/browser/blob_storage/blob_dispatcher_host.cc
|
| diff --git a/content/browser/blob_storage/blob_dispatcher_host.cc b/content/browser/blob_storage/blob_dispatcher_host.cc
|
| index 00ef8b40f71f04826f09ac935af3516c0b318f23..0e03318279c6d1f27cf237eef17c75f4affbc30a 100644
|
| --- a/content/browser/blob_storage/blob_dispatcher_host.cc
|
| +++ b/content/browser/blob_storage/blob_dispatcher_host.cc
|
| @@ -26,8 +26,10 @@ using storage::IPCBlobCreationCancelCode;
|
| namespace content {
|
|
|
| BlobDispatcherHost::BlobDispatcherHost(
|
| - ChromeBlobStorageContext* blob_storage_context)
|
| + ChromeBlobStorageContext* blob_storage_context,
|
| + SetSuddenTerminationAllowedCallback set_sudden_termination_allowed)
|
| : BrowserMessageFilter(BlobMsgStart),
|
| + set_sudden_termination_allowed_(set_sudden_termination_allowed),
|
| blob_storage_context_(blob_storage_context) {}
|
|
|
| BlobDispatcherHost::~BlobDispatcherHost() {
|
| @@ -75,7 +77,6 @@ void BlobDispatcherHost::OnRegisterBlobUUID(
|
| blobs_inuse_map_.erase(uuid);
|
| bad_message::ReceivedBadMessage(this, bad_message::BDH_INVALID_OPERATION);
|
| break;
|
| - ;
|
| case BlobTransportResult::CANCEL_REFERENCED_BLOB_BROKEN:
|
| // The async builder builds the blob as broken, and we just need to send
|
| // the cancel message back to the renderer.
|
| @@ -83,6 +84,12 @@ void BlobDispatcherHost::OnRegisterBlobUUID(
|
| uuid, IPCBlobCreationCancelCode::REFERENCED_BLOB_BROKEN));
|
| break;
|
| case BlobTransportResult::DONE:
|
| + // This means the builder used to be empty, and we're successfully
|
| + // building
|
| + // the blob.
|
| + if (async_builder_.blob_building_count() == 1) {
|
| + set_sudden_termination_allowed_.Run(false);
|
| + }
|
| break;
|
| case BlobTransportResult::CANCEL_MEMORY_FULL:
|
| case BlobTransportResult::CANCEL_FILE_ERROR:
|
| @@ -117,6 +124,7 @@ void BlobDispatcherHost::OnStartBuildingBlob(
|
| context);
|
| Send(new BlobStorageMsg_CancelBuildingBlob(
|
| uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING));
|
| + AllowSuddenTerminationIfBuilderEmpty();
|
| }
|
| return;
|
| }
|
| @@ -130,6 +138,9 @@ void BlobDispatcherHost::OnStartBuildingBlob(
|
| base::Bind(&BlobDispatcherHost::SendMemoryRequest, base::Unretained(this),
|
| uuid));
|
| SendIPCResponse(uuid, result);
|
| + if (result != BlobTransportResult::PENDING_RESPONSES) {
|
| + AllowSuddenTerminationIfBuilderEmpty();
|
| + }
|
| }
|
|
|
| void BlobDispatcherHost::OnMemoryItemResponse(
|
| @@ -147,7 +158,6 @@ void BlobDispatcherHost::OnMemoryItemResponse(
|
| // the renderer de-refs a blob that we're still constructing, and there are
|
| // no references to that blob. We ignore broken as well, in the case where
|
| // we decided to break a blob after sending the memory request.
|
| - // Note: if a blob is broken, then it can't be in the async_builder.
|
| // Second, if the last dereference of the blob happened on a different host,
|
| // then we still haven't gotten rid of the 'building' state in the original
|
| // host. So we call cancel, and send the message just in case that happens.
|
| @@ -157,6 +167,7 @@ void BlobDispatcherHost::OnMemoryItemResponse(
|
| context);
|
| Send(new BlobStorageMsg_CancelBuildingBlob(
|
| uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING));
|
| + AllowSuddenTerminationIfBuilderEmpty();
|
| }
|
| return;
|
| }
|
| @@ -167,6 +178,9 @@ void BlobDispatcherHost::OnMemoryItemResponse(
|
| BlobTransportResult result =
|
| async_builder_.OnMemoryResponses(uuid, responses, context);
|
| SendIPCResponse(uuid, result);
|
| + if (result != BlobTransportResult::PENDING_RESPONSES) {
|
| + AllowSuddenTerminationIfBuilderEmpty();
|
| + }
|
| }
|
|
|
| void BlobDispatcherHost::OnCancelBuildingBlob(
|
| @@ -184,13 +198,15 @@ void BlobDispatcherHost::OnCancelBuildingBlob(
|
| // the renderer de-refs a blob that we're still constructing, and there are
|
| // no references to that blob. We ignore broken as well, in the case where
|
| // we decided to break a blob and the renderer also decided to cancel.
|
| - // Note: if a blob is broken, then it can't be in the async_builder.
|
| // Second, if the last dereference of the blob happened on a different host,
|
| // then we still haven't gotten rid of the 'building' state in the original
|
| // host. So we call cancel just in case this happens.
|
| - async_builder_.CancelBuildingBlob(
|
| - uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING,
|
| - context);
|
| + if (async_builder_.IsBeingBuilt(uuid)) {
|
| + async_builder_.CancelBuildingBlob(
|
| + uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING,
|
| + context);
|
| + AllowSuddenTerminationIfBuilderEmpty();
|
| + }
|
| return;
|
| }
|
| if (!async_builder_.IsBeingBuilt(uuid)) {
|
| @@ -200,6 +216,7 @@ void BlobDispatcherHost::OnCancelBuildingBlob(
|
| VLOG(1) << "Blob construction of " << uuid << " cancelled by renderer. "
|
| << " Reason: " << static_cast<int>(code) << ".";
|
| async_builder_.CancelBuildingBlob(uuid, code, context);
|
| + AllowSuddenTerminationIfBuilderEmpty();
|
| }
|
|
|
| void BlobDispatcherHost::OnIncrementBlobRefCount(const std::string& uuid) {
|
| @@ -234,6 +251,7 @@ void BlobDispatcherHost::OnDecrementBlobRefCount(const std::string& uuid) {
|
| context);
|
| Send(new BlobStorageMsg_CancelBuildingBlob(
|
| uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING));
|
| + AllowSuddenTerminationIfBuilderEmpty();
|
| }
|
| }
|
| }
|
| @@ -327,7 +345,16 @@ void BlobDispatcherHost::ClearHostFromBlobStorageContext() {
|
| for (int i = 0; i < uuid_refnum_pair.second; ++i)
|
| context->DecrementBlobRefCount(uuid_refnum_pair.first);
|
| }
|
| - async_builder_.CancelAll(context);
|
| + if (!async_builder_.IsEmpty()) {
|
| + async_builder_.CancelAll(context);
|
| + set_sudden_termination_allowed_.Run(true);
|
| + }
|
| +}
|
| +
|
| +void BlobDispatcherHost::AllowSuddenTerminationIfBuilderEmpty() {
|
| + if (async_builder_.IsEmpty()) {
|
| + set_sudden_termination_allowed_.Run(true);
|
| + }
|
| }
|
|
|
| } // namespace content
|
|
|