Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(66)

Unified Diff: content/browser/blob_storage/blob_dispatcher_host.cc

Issue 2448353002: [BlobAsync] Moving async handling into BlobStorageContext & quota out. (Closed)
Patch Set: comments Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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 2269cc645efa1d56ac2b50ef544149f84c9de160..bea813ddc5c4f7abdfc20eccc633918fb790b792 100644
--- a/content/browser/blob_storage/blob_dispatcher_host.cc
+++ b/content/browser/blob_storage/blob_dispatcher_host.cc
@@ -14,8 +14,9 @@
#include "content/browser/fileapi/browser_file_system_helper.h"
#include "content/common/fileapi/webblob_messages.h"
#include "ipc/ipc_platform_file.h"
+#include "storage/browser/blob/blob_data_handle.h"
+#include "storage/browser/blob/blob_entry.h"
#include "storage/browser/blob/blob_storage_context.h"
-#include "storage/browser/blob/blob_transport_result.h"
#include "storage/browser/fileapi/file_system_context.h"
#include "storage/browser/fileapi/file_system_url.h"
#include "storage/common/blob_storage/blob_item_bytes_request.h"
@@ -25,13 +26,17 @@
using storage::BlobStorageContext;
using storage::BlobStorageRegistry;
-using storage::BlobTransportResult;
+using storage::BlobStatus;
using storage::DataElement;
-using storage::IPCBlobCreationCancelCode;
using storage::FileSystemURL;
namespace content {
namespace {
+using storage::BlobStorageContext;
+using storage::BlobStorageRegistry;
+using storage::BlobStatus;
+using storage::DataElement;
+using storage::FileSystemURL;
// These are used for UMA stats, don't change.
enum RefcountOperation {
@@ -42,6 +47,16 @@ enum RefcountOperation {
} // namespace
+BlobDispatcherHost::HostedBlobState::HostedBlobState(
+ std::unique_ptr<storage::BlobDataHandle> handle)
+ : handle(std::move(handle)) {}
+BlobDispatcherHost::HostedBlobState::~HostedBlobState() {}
+
+BlobDispatcherHost::HostedBlobState::HostedBlobState(HostedBlobState&&) =
+ default;
+BlobDispatcherHost::HostedBlobState& BlobDispatcherHost::HostedBlobState::
+operator=(BlobDispatcherHost::HostedBlobState&&) = default;
+
BlobDispatcherHost::BlobDispatcherHost(
int process_id,
scoped_refptr<ChromeBlobStorageContext> blob_storage_context,
@@ -63,11 +78,11 @@ void BlobDispatcherHost::OnChannelClosing() {
bool BlobDispatcherHost::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
+ // Note: The only time a renderer sends a blob status message is to cancel.
IPC_BEGIN_MESSAGE_MAP(BlobDispatcherHost, message)
- IPC_MESSAGE_HANDLER(BlobStorageMsg_RegisterBlobUUID, OnRegisterBlobUUID)
- IPC_MESSAGE_HANDLER(BlobStorageMsg_StartBuildingBlob, OnStartBuildingBlob)
+ IPC_MESSAGE_HANDLER(BlobStorageMsg_RegisterBlob, OnRegisterBlob)
IPC_MESSAGE_HANDLER(BlobStorageMsg_MemoryItemResponse, OnMemoryItemResponse)
- IPC_MESSAGE_HANDLER(BlobStorageMsg_CancelBuildingBlob, OnCancelBuildingBlob)
+ IPC_MESSAGE_HANDLER(BlobStorageMsg_SendBlobStatus, OnCancelBuildingBlob)
IPC_MESSAGE_HANDLER(BlobHostMsg_IncrementRefCount, OnIncrementBlobRefCount)
IPC_MESSAGE_HANDLER(BlobHostMsg_DecrementRefCount, OnDecrementBlobRefCount)
IPC_MESSAGE_HANDLER(BlobHostMsg_RegisterPublicURL, OnRegisterPublicBlobURL)
@@ -77,75 +92,20 @@ bool BlobDispatcherHost::OnMessageReceived(const IPC::Message& message) {
return handled;
}
-void BlobDispatcherHost::OnRegisterBlobUUID(
+void BlobDispatcherHost::OnRegisterBlob(
const std::string& uuid,
const std::string& content_type,
const std::string& content_disposition,
- const std::set<std::string>& referenced_blob_uuids) {
+ const std::vector<storage::DataElement>& descriptions) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
BlobStorageContext* context = this->context();
if (uuid.empty() || context->registry().HasEntry(uuid) ||
- async_builder_.IsBeingBuilt(uuid)) {
+ transport_host_.IsBeingBuilt(uuid)) {
bad_message::ReceivedBadMessage(this, bad_message::BDH_UUID_REGISTERED);
return;
}
- blobs_inuse_map_[uuid] = 1;
- BlobTransportResult result = async_builder_.RegisterBlobUUID(
- uuid, content_type, content_disposition, referenced_blob_uuids, context);
- switch (result) {
- case BlobTransportResult::BAD_IPC:
- blobs_inuse_map_.erase(uuid);
- bad_message::ReceivedBadMessage(this,
- bad_message::BDH_CONSTRUCTION_FAILED);
- 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.
- Send(new BlobStorageMsg_CancelBuildingBlob(
- uuid, IPCBlobCreationCancelCode::REFERENCED_BLOB_BROKEN));
- break;
- case BlobTransportResult::DONE:
- break;
- case BlobTransportResult::CANCEL_MEMORY_FULL:
- case BlobTransportResult::CANCEL_FILE_ERROR:
- case BlobTransportResult::CANCEL_UNKNOWN:
- case BlobTransportResult::PENDING_RESPONSES:
- NOTREACHED();
- break;
- }
-}
-void BlobDispatcherHost::OnStartBuildingBlob(
- const std::string& uuid,
- const std::vector<storage::DataElement>& descriptions) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (uuid.empty()) {
- SendIPCResponse(uuid, BlobTransportResult::BAD_IPC);
- return;
- }
- BlobStorageContext* context = this->context();
- const BlobStorageRegistry::Entry* entry = context->registry().GetEntry(uuid);
- if (!entry || entry->state == BlobStorageRegistry::BlobState::BROKEN) {
- // We ignore messages for blobs that don't exist to handle the case where
- // 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 RegisterBlobUUID is called.
- // 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.
- if (async_builder_.IsBeingBuilt(uuid)) {
- async_builder_.CancelBuildingBlob(
- uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING,
- context);
- Send(new BlobStorageMsg_CancelBuildingBlob(
- uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING));
- }
- return;
- }
- if (!async_builder_.IsBeingBuilt(uuid)) {
- SendIPCResponse(uuid, BlobTransportResult::BAD_IPC);
- return;
- }
+ DCHECK(!base::ContainsKey(blobs_inuse_map_, uuid));
ChildProcessSecurityPolicyImpl* security_policy =
ChildProcessSecurityPolicyImpl::GetInstance();
@@ -159,20 +119,24 @@ void BlobDispatcherHost::OnStartBuildingBlob(
if (!FileSystemURLIsValid(file_system_context_.get(), filesystem_url) ||
!security_policy->CanReadFileSystemFile(process_id_,
filesystem_url)) {
- async_builder_.CancelBuildingBlob(
- uuid, IPCBlobCreationCancelCode::FILE_WRITE_FAILED, context);
- Send(new BlobStorageMsg_CancelBuildingBlob(
- uuid, IPCBlobCreationCancelCode::FILE_WRITE_FAILED));
+ HostedBlobState hosted_state(
+ context->AddBrokenBlob(uuid, content_type, content_disposition,
+ BlobStatus::ERR_FILE_WRITE_FAILED));
+ blobs_inuse_map_.insert(
+ std::make_pair(uuid, std::move(hosted_state)));
+ SendFinalBlobStatus(uuid, BlobStatus::ERR_FILE_WRITE_FAILED);
return;
}
break;
}
case storage::DataElement::TYPE_FILE: {
if (!security_policy->CanReadFile(process_id_, item.path())) {
- async_builder_.CancelBuildingBlob(
- uuid, IPCBlobCreationCancelCode::FILE_WRITE_FAILED, context);
- Send(new BlobStorageMsg_CancelBuildingBlob(
- uuid, IPCBlobCreationCancelCode::FILE_WRITE_FAILED));
+ HostedBlobState hosted_state(
+ context->AddBrokenBlob(uuid, content_type, content_disposition,
+ BlobStatus::ERR_FILE_WRITE_FAILED));
+ blobs_inuse_map_.insert(
+ std::make_pair(uuid, std::move(hosted_state)));
+ SendFinalBlobStatus(uuid, BlobStatus::ERR_FILE_WRITE_FAILED);
return;
}
break;
@@ -193,12 +157,13 @@ void BlobDispatcherHost::OnStartBuildingBlob(
}
}
- // |this| owns async_builder_ so using base::Unretained(this) is safe.
- BlobTransportResult result = async_builder_.StartBuildingBlob(
- uuid, descriptions, context->memory_available(), context,
+ HostedBlobState hosted_state(transport_host_.StartBuildingBlob(
+ uuid, content_type, content_disposition, descriptions, context,
base::Bind(&BlobDispatcherHost::SendMemoryRequest, base::Unretained(this),
- uuid));
- SendIPCResponse(uuid, result);
+ uuid),
+ base::Bind(&BlobDispatcherHost::SendFinalBlobStatus,
+ base::Unretained(this), uuid)));
+ blobs_inuse_map_.insert(std::make_pair(uuid, std::move(hosted_state)));
}
void BlobDispatcherHost::OnMemoryItemResponse(
@@ -206,71 +171,65 @@ void BlobDispatcherHost::OnMemoryItemResponse(
const std::vector<storage::BlobItemBytesResponse>& responses) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (uuid.empty()) {
- SendIPCResponse(uuid, BlobTransportResult::BAD_IPC);
+ bad_message::ReceivedBadMessage(this, bad_message::BDH_CONSTRUCTION_FAILED);
return;
}
BlobStorageContext* context = this->context();
- const BlobStorageRegistry::Entry* entry = context->registry().GetEntry(uuid);
- if (!entry || entry->state == BlobStorageRegistry::BlobState::BROKEN) {
+ const storage::BlobEntry* entry = context->registry().GetEntry(uuid);
+ if (!entry || BlobStatusIsError(entry->status())) {
// We ignore messages for blobs that don't exist to handle the case where
// 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.
+ // Note: if a blob is broken, then it can't be in the transport_host.
// 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.
- if (async_builder_.IsBeingBuilt(uuid)) {
- async_builder_.CancelBuildingBlob(
- uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING,
- context);
- Send(new BlobStorageMsg_CancelBuildingBlob(
- uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING));
+ if (transport_host_.IsBeingBuilt(uuid)) {
+ transport_host_.CancelBuildingBlob(
+ uuid, BlobStatus::ERR_BLOB_DEREFERENCED_WHILE_BUILDING, context);
}
return;
}
- if (!async_builder_.IsBeingBuilt(uuid)) {
- SendIPCResponse(uuid, BlobTransportResult::BAD_IPC);
+ if (!transport_host_.IsBeingBuilt(uuid)) {
+ bad_message::ReceivedBadMessage(this, bad_message::BDH_CONSTRUCTION_FAILED);
return;
}
- BlobTransportResult result =
- async_builder_.OnMemoryResponses(uuid, responses, context);
- SendIPCResponse(uuid, result);
+ transport_host_.OnMemoryResponses(uuid, responses, context);
}
-void BlobDispatcherHost::OnCancelBuildingBlob(
- const std::string& uuid,
- const storage::IPCBlobCreationCancelCode code) {
+void BlobDispatcherHost::OnCancelBuildingBlob(const std::string& uuid,
+ const storage::BlobStatus code) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (uuid.empty()) {
- SendIPCResponse(uuid, BlobTransportResult::BAD_IPC);
+ bad_message::ReceivedBadMessage(this, bad_message::BDH_CONSTRUCTION_FAILED);
return;
}
BlobStorageContext* context = this->context();
- const BlobStorageRegistry::Entry* entry = context->registry().GetEntry(uuid);
- if (!entry || entry->state == BlobStorageRegistry::BlobState::BROKEN) {
+ const storage::BlobEntry* entry = context->registry().GetEntry(uuid);
+ if (!entry || BlobStatusIsError(entry->status())) {
// We ignore messages for blobs that don't exist to handle the case where
// 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.
+ // Note: if a blob is broken, then it can't be in the transport_host.
// 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.
- if (async_builder_.IsBeingBuilt(uuid)) {
- async_builder_.CancelBuildingBlob(
- uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING,
- context);
+ if (transport_host_.IsBeingBuilt(uuid)) {
+ transport_host_.CancelBuildingBlob(
+ uuid, BlobStatus::ERR_BLOB_DEREFERENCED_WHILE_BUILDING, context);
}
return;
}
- if (!async_builder_.IsBeingBuilt(uuid)) {
- SendIPCResponse(uuid, BlobTransportResult::BAD_IPC);
+ if (!transport_host_.IsBeingBuilt(uuid) ||
+ !storage::BlobStatusIsError(code)) {
+ bad_message::ReceivedBadMessage(this, bad_message::BDH_CONSTRUCTION_FAILED);
return;
}
VLOG(1) << "Blob construction of " << uuid << " cancelled by renderer. "
<< " Reason: " << static_cast<int>(code) << ".";
- async_builder_.CancelBuildingBlob(uuid, code, context);
+ transport_host_.CancelBuildingBlob(uuid, code, context);
}
void BlobDispatcherHost::OnIncrementBlobRefCount(const std::string& uuid) {
@@ -286,8 +245,13 @@ void BlobDispatcherHost::OnIncrementBlobRefCount(const std::string& uuid) {
BDH_TRACING_ENUM_LAST);
return;
}
- context->IncrementBlobRefCount(uuid);
- blobs_inuse_map_[uuid] += 1;
+ auto state_it = blobs_inuse_map_.find(uuid);
+ if (state_it != blobs_inuse_map_.end()) {
+ state_it->second.refcount += 1;
+ return;
+ }
+ blobs_inuse_map_.insert(std::make_pair(
+ uuid, HostedBlobState(context->GetBlobDataFromUUID(uuid))));
}
void BlobDispatcherHost::OnDecrementBlobRefCount(const std::string& uuid) {
@@ -297,26 +261,23 @@ void BlobDispatcherHost::OnDecrementBlobRefCount(const std::string& uuid) {
this, bad_message::BDH_INVALID_REFCOUNT_OPERATION);
return;
}
- if (!IsInUseInHost(uuid)) {
+ auto state_it = blobs_inuse_map_.find(uuid);
+ if (state_it == blobs_inuse_map_.end()) {
UMA_HISTOGRAM_ENUMERATION("Storage.Blob.InvalidReference", BDH_DECREMENT,
BDH_TRACING_ENUM_LAST);
return;
}
- BlobStorageContext* context = this->context();
- context->DecrementBlobRefCount(uuid);
- blobs_inuse_map_[uuid] -= 1;
- if (blobs_inuse_map_[uuid] == 0) {
- blobs_inuse_map_.erase(uuid);
- // If the blob has been deleted in the context and we're still building it,
- // this means we have no references waiting to read it. Clear the building
- // state and send a cancel message to the renderer.
- if (async_builder_.IsBeingBuilt(uuid) &&
+ state_it->second.refcount -= 1;
+ if (state_it->second.refcount == 0) {
+ blobs_inuse_map_.erase(state_it);
+
+ // If we're being built still and we don't have any other references, cancel
+ // construction.
+ BlobStorageContext* context = this->context();
+ if (transport_host_.IsBeingBuilt(uuid) &&
!context->registry().HasEntry(uuid)) {
- async_builder_.CancelBuildingBlob(
- uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING,
- context);
- Send(new BlobStorageMsg_CancelBuildingBlob(
- uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING));
+ transport_host_.CancelBuildingBlob(
+ uuid, BlobStatus::ERR_BLOB_DEREFERENCED_WHILE_BUILDING, context);
}
}
}
@@ -372,55 +333,33 @@ storage::BlobStorageContext* BlobDispatcherHost::context() {
void BlobDispatcherHost::SendMemoryRequest(
const std::string& uuid,
- std::unique_ptr<std::vector<storage::BlobItemBytesRequest>> requests,
- std::unique_ptr<std::vector<base::SharedMemoryHandle>> memory_handles,
- std::unique_ptr<std::vector<base::File>> files) {
+ std::vector<storage::BlobItemBytesRequest> requests,
+ std::vector<base::SharedMemoryHandle> memory_handles,
+ std::vector<base::File> files) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
std::vector<IPC::PlatformFileForTransit> file_handles;
- // TODO(dmurph): Support file-backed blob transportation.
- DCHECK(files->empty());
- Send(new BlobStorageMsg_RequestMemoryItem(uuid, *requests, *memory_handles,
+ for (base::File& file : files) {
+ file_handles.push_back(IPC::TakePlatformFileForTransit(std::move(file)));
+ }
+ Send(new BlobStorageMsg_RequestMemoryItem(uuid, requests, memory_handles,
file_handles));
}
-void BlobDispatcherHost::SendIPCResponse(const std::string& uuid,
- storage::BlobTransportResult result) {
- switch (result) {
- case BlobTransportResult::BAD_IPC:
- bad_message::ReceivedBadMessage(this,
- bad_message::BDH_CONSTRUCTION_FAILED);
- return;
- case BlobTransportResult::CANCEL_MEMORY_FULL:
- Send(new BlobStorageMsg_CancelBuildingBlob(
- uuid, IPCBlobCreationCancelCode::OUT_OF_MEMORY));
- return;
- case BlobTransportResult::CANCEL_FILE_ERROR:
- Send(new BlobStorageMsg_CancelBuildingBlob(
- uuid, IPCBlobCreationCancelCode::FILE_WRITE_FAILED));
- return;
- case BlobTransportResult::CANCEL_REFERENCED_BLOB_BROKEN:
- Send(new BlobStorageMsg_CancelBuildingBlob(
- uuid, IPCBlobCreationCancelCode::REFERENCED_BLOB_BROKEN));
- return;
- case BlobTransportResult::CANCEL_UNKNOWN:
- Send(new BlobStorageMsg_CancelBuildingBlob(
- uuid, IPCBlobCreationCancelCode::UNKNOWN));
- return;
- case BlobTransportResult::PENDING_RESPONSES:
- return;
- case BlobTransportResult::DONE:
- Send(new BlobStorageMsg_DoneBuildingBlob(uuid));
- return;
+void BlobDispatcherHost::SendFinalBlobStatus(const std::string& uuid,
+ BlobStatus status) {
+ DCHECK(!BlobStatusIsPending(status));
+ if (storage::BlobStatusIsBadIPC(status)) {
+ bad_message::ReceivedBadMessage(this, bad_message::BDH_CONSTRUCTION_FAILED);
}
- NOTREACHED();
+ Send(new BlobStorageMsg_SendBlobStatus(uuid, status));
}
bool BlobDispatcherHost::IsInUseInHost(const std::string& uuid) {
- return blobs_inuse_map_.find(uuid) != blobs_inuse_map_.end();
+ return base::ContainsKey(blobs_inuse_map_, uuid);
}
bool BlobDispatcherHost::IsUrlRegisteredInHost(const GURL& blob_url) {
- return public_blob_urls_.find(blob_url) != public_blob_urls_.end();
+ return base::ContainsKey(public_blob_urls_, blob_url);
}
void BlobDispatcherHost::ClearHostFromBlobStorageContext() {
@@ -428,11 +367,9 @@ void BlobDispatcherHost::ClearHostFromBlobStorageContext() {
for (const auto& url : public_blob_urls_) {
context->RevokePublicBlobURL(url);
}
- for (const auto& uuid_refnum_pair : blobs_inuse_map_) {
- for (int i = 0; i < uuid_refnum_pair.second; ++i)
- context->DecrementBlobRefCount(uuid_refnum_pair.first);
- }
- async_builder_.CancelAll(context);
+ // Keep the blobs alive for the BlobTransportHost call.
+ transport_host_.CancelAll(context);
+ blobs_inuse_map_.clear();
}
} // namespace content
« no previous file with comments | « content/browser/blob_storage/blob_dispatcher_host.h ('k') | content/browser/blob_storage/blob_dispatcher_host_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698