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 |