Chromium Code Reviews| 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 <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/metrics/histogram_macros.h" | 10 #include "base/metrics/histogram_macros.h" |
| 11 #include "content/browser/bad_message.h" | 11 #include "content/browser/bad_message.h" |
| 12 #include "content/browser/blob_storage/chrome_blob_storage_context.h" | 12 #include "content/browser/blob_storage/chrome_blob_storage_context.h" |
| 13 #include "content/common/fileapi/webblob_messages.h" | 13 #include "content/common/fileapi/webblob_messages.h" |
| 14 #include "ipc/ipc_platform_file.h" | 14 #include "ipc/ipc_platform_file.h" |
| 15 #include "storage/browser/blob/blob_data_handle.h" | |
| 15 #include "storage/browser/blob/blob_storage_context.h" | 16 #include "storage/browser/blob/blob_storage_context.h" |
| 16 #include "storage/browser/blob/blob_transport_result.h" | 17 #include "storage/browser/blob/internal_blob_data.h" |
| 17 #include "storage/common/blob_storage/blob_item_bytes_request.h" | 18 #include "storage/common/blob_storage/blob_item_bytes_request.h" |
| 18 #include "storage/common/blob_storage/blob_item_bytes_response.h" | 19 #include "storage/common/blob_storage/blob_item_bytes_response.h" |
| 19 #include "storage/common/data_element.h" | 20 #include "storage/common/data_element.h" |
| 20 #include "url/gurl.h" | 21 #include "url/gurl.h" |
| 21 | 22 |
| 22 using storage::BlobStorageContext; | 23 using storage::BlobStorageContext; |
| 23 using storage::BlobStorageRegistry; | 24 using storage::BlobStorageRegistry; |
| 24 using storage::BlobTransportResult; | 25 using storage::BlobStatus; |
| 25 using storage::IPCBlobCreationCancelCode; | |
| 26 | 26 |
| 27 namespace content { | 27 namespace content { |
| 28 namespace { | 28 namespace { |
| 29 | 29 |
| 30 // These are used for UMA stats, don't change. | 30 // These are used for UMA stats, don't change. |
| 31 enum RefcountOperation { | 31 enum RefcountOperation { |
| 32 BDH_DECREMENT = 0, | 32 BDH_DECREMENT = 0, |
| 33 BDH_INCREMENT, | 33 BDH_INCREMENT, |
| 34 BDH_TRACING_ENUM_LAST | 34 BDH_TRACING_ENUM_LAST |
| 35 }; | 35 }; |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 47 | 47 |
| 48 void BlobDispatcherHost::OnChannelClosing() { | 48 void BlobDispatcherHost::OnChannelClosing() { |
| 49 ClearHostFromBlobStorageContext(); | 49 ClearHostFromBlobStorageContext(); |
| 50 public_blob_urls_.clear(); | 50 public_blob_urls_.clear(); |
| 51 blobs_inuse_map_.clear(); | 51 blobs_inuse_map_.clear(); |
| 52 } | 52 } |
| 53 | 53 |
| 54 bool BlobDispatcherHost::OnMessageReceived(const IPC::Message& message) { | 54 bool BlobDispatcherHost::OnMessageReceived(const IPC::Message& message) { |
| 55 bool handled = true; | 55 bool handled = true; |
| 56 IPC_BEGIN_MESSAGE_MAP(BlobDispatcherHost, message) | 56 IPC_BEGIN_MESSAGE_MAP(BlobDispatcherHost, message) |
| 57 IPC_MESSAGE_HANDLER(BlobStorageMsg_RegisterBlobUUID, OnRegisterBlobUUID) | 57 IPC_MESSAGE_HANDLER(BlobStorageMsg_RegisterBlob, OnRegisterBlob) |
| 58 IPC_MESSAGE_HANDLER(BlobStorageMsg_StartBuildingBlob, OnStartBuildingBlob) | |
| 59 IPC_MESSAGE_HANDLER(BlobStorageMsg_MemoryItemResponse, OnMemoryItemResponse) | 58 IPC_MESSAGE_HANDLER(BlobStorageMsg_MemoryItemResponse, OnMemoryItemResponse) |
| 60 IPC_MESSAGE_HANDLER(BlobStorageMsg_CancelBuildingBlob, OnCancelBuildingBlob) | 59 IPC_MESSAGE_HANDLER(BlobStorageMsg_SendBlobStatus, OnCancelBuildingBob) |
| 61 IPC_MESSAGE_HANDLER(BlobHostMsg_IncrementRefCount, OnIncrementBlobRefCount) | 60 IPC_MESSAGE_HANDLER(BlobHostMsg_IncrementRefCount, OnIncrementBlobRefCount) |
| 62 IPC_MESSAGE_HANDLER(BlobHostMsg_DecrementRefCount, OnDecrementBlobRefCount) | 61 IPC_MESSAGE_HANDLER(BlobHostMsg_DecrementRefCount, OnDecrementBlobRefCount) |
| 63 IPC_MESSAGE_HANDLER(BlobHostMsg_RegisterPublicURL, OnRegisterPublicBlobURL) | 62 IPC_MESSAGE_HANDLER(BlobHostMsg_RegisterPublicURL, OnRegisterPublicBlobURL) |
| 64 IPC_MESSAGE_HANDLER(BlobHostMsg_RevokePublicURL, OnRevokePublicBlobURL) | 63 IPC_MESSAGE_HANDLER(BlobHostMsg_RevokePublicURL, OnRevokePublicBlobURL) |
| 65 IPC_MESSAGE_UNHANDLED(handled = false) | 64 IPC_MESSAGE_UNHANDLED(handled = false) |
| 66 IPC_END_MESSAGE_MAP() | 65 IPC_END_MESSAGE_MAP() |
| 67 return handled; | 66 return handled; |
| 68 } | 67 } |
| 69 | 68 |
| 70 void BlobDispatcherHost::OnRegisterBlobUUID( | 69 void BlobDispatcherHost::OnRegisterBlob( |
| 71 const std::string& uuid, | 70 const std::string& uuid, |
| 72 const std::string& content_type, | 71 const std::string& content_type, |
| 73 const std::string& content_disposition, | 72 const std::string& content_disposition, |
| 74 const std::set<std::string>& referenced_blob_uuids) { | 73 const std::vector<storage::DataElement>& descriptions) { |
| 75 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 74 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 76 BlobStorageContext* context = this->context(); | 75 BlobStorageContext* context = this->context(); |
| 77 if (uuid.empty() || context->registry().HasEntry(uuid) || | 76 if (uuid.empty() || context->registry().HasEntry(uuid) || |
| 78 async_builder_.IsBeingBuilt(uuid)) { | 77 async_builder_.IsBeingBuilt(uuid)) { |
| 79 bad_message::ReceivedBadMessage(this, bad_message::BDH_UUID_REGISTERED); | 78 bad_message::ReceivedBadMessage(this, bad_message::BDH_UUID_REGISTERED); |
| 80 return; | 79 return; |
| 81 } | 80 } |
| 82 blobs_inuse_map_[uuid] = 1; | 81 blobs_inuse_map_[uuid] = 1; |
| 83 BlobTransportResult result = async_builder_.RegisterBlobUUID( | 82 BlobStatus result = async_builder_.RegisterBlob( |
| 84 uuid, content_type, content_disposition, referenced_blob_uuids, context); | 83 uuid, content_type, content_disposition, descriptions, context, |
| 85 switch (result) { | |
| 86 case BlobTransportResult::BAD_IPC: | |
| 87 blobs_inuse_map_.erase(uuid); | |
| 88 bad_message::ReceivedBadMessage(this, | |
| 89 bad_message::BDH_CONSTRUCTION_FAILED); | |
| 90 break; | |
| 91 case BlobTransportResult::CANCEL_REFERENCED_BLOB_BROKEN: | |
| 92 // The async builder builds the blob as broken, and we just need to send | |
| 93 // the cancel message back to the renderer. | |
| 94 Send(new BlobStorageMsg_CancelBuildingBlob( | |
| 95 uuid, IPCBlobCreationCancelCode::REFERENCED_BLOB_BROKEN)); | |
| 96 break; | |
| 97 case BlobTransportResult::DONE: | |
| 98 break; | |
| 99 case BlobTransportResult::CANCEL_MEMORY_FULL: | |
| 100 case BlobTransportResult::CANCEL_FILE_ERROR: | |
| 101 case BlobTransportResult::CANCEL_UNKNOWN: | |
| 102 case BlobTransportResult::PENDING_RESPONSES: | |
| 103 NOTREACHED(); | |
| 104 break; | |
| 105 } | |
| 106 } | |
| 107 | |
| 108 void BlobDispatcherHost::OnStartBuildingBlob( | |
| 109 const std::string& uuid, | |
| 110 const std::vector<storage::DataElement>& descriptions) { | |
| 111 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 112 if (uuid.empty()) { | |
| 113 SendIPCResponse(uuid, BlobTransportResult::BAD_IPC); | |
| 114 return; | |
| 115 } | |
| 116 BlobStorageContext* context = this->context(); | |
| 117 const BlobStorageRegistry::Entry* entry = context->registry().GetEntry(uuid); | |
| 118 if (!entry || entry->state == BlobStorageRegistry::BlobState::BROKEN) { | |
| 119 // We ignore messages for blobs that don't exist to handle the case where | |
| 120 // the renderer de-refs a blob that we're still constructing, and there are | |
| 121 // no references to that blob. We ignore broken as well, in the case where | |
| 122 // we decided to break a blob after RegisterBlobUUID is called. | |
| 123 // Second, if the last dereference of the blob happened on a different host, | |
| 124 // then we still haven't gotten rid of the 'building' state in the original | |
| 125 // host. So we call cancel, and send the message just in case that happens. | |
| 126 if (async_builder_.IsBeingBuilt(uuid)) { | |
| 127 async_builder_.CancelBuildingBlob( | |
| 128 uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING, | |
| 129 context); | |
| 130 Send(new BlobStorageMsg_CancelBuildingBlob( | |
| 131 uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING)); | |
| 132 } | |
| 133 return; | |
| 134 } | |
| 135 if (!async_builder_.IsBeingBuilt(uuid)) { | |
| 136 SendIPCResponse(uuid, BlobTransportResult::BAD_IPC); | |
| 137 return; | |
| 138 } | |
| 139 // |this| owns async_builder_ so using base::Unretained(this) is safe. | |
| 140 BlobTransportResult result = async_builder_.StartBuildingBlob( | |
| 141 uuid, descriptions, context->memory_available(), context, | |
| 142 base::Bind(&BlobDispatcherHost::SendMemoryRequest, base::Unretained(this), | 84 base::Bind(&BlobDispatcherHost::SendMemoryRequest, base::Unretained(this), |
| 143 uuid)); | 85 uuid), |
| 144 SendIPCResponse(uuid, result); | 86 base::Bind(&BlobDispatcherHost::MaybeSendFinalBlobStatus, |
|
michaeln
2016/08/15 22:44:42
Seems odd that the builder is expected to call thi
dmurph
2016/08/19 00:18:31
Done.
michaeln
2016/08/23 01:31:54
Looks like this was done for OnStart handling spec
| |
| 87 base::Unretained(this), uuid)); | |
| 88 MaybeSendFinalBlobStatus(uuid, result); | |
| 145 } | 89 } |
| 146 | 90 |
| 147 void BlobDispatcherHost::OnMemoryItemResponse( | 91 void BlobDispatcherHost::OnMemoryItemResponse( |
| 148 const std::string& uuid, | 92 const std::string& uuid, |
| 149 const std::vector<storage::BlobItemBytesResponse>& responses) { | 93 const std::vector<storage::BlobItemBytesResponse>& responses) { |
| 150 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 94 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 151 if (uuid.empty()) { | 95 if (uuid.empty()) { |
| 152 SendIPCResponse(uuid, BlobTransportResult::BAD_IPC); | 96 bad_message::ReceivedBadMessage(this, bad_message::BDH_CONSTRUCTION_FAILED); |
| 153 return; | 97 return; |
| 154 } | 98 } |
| 155 BlobStorageContext* context = this->context(); | 99 BlobStorageContext* context = this->context(); |
| 156 const BlobStorageRegistry::Entry* entry = context->registry().GetEntry(uuid); | 100 const storage::InternalBlobData* entry = context->registry().GetEntry(uuid); |
| 157 if (!entry || entry->state == BlobStorageRegistry::BlobState::BROKEN) { | 101 if (!entry || BlobStatusIsError(entry->status())) { |
| 158 // We ignore messages for blobs that don't exist to handle the case where | 102 // We ignore messages for blobs that don't exist to handle the case where |
| 159 // the renderer de-refs a blob that we're still constructing, and there are | 103 // the renderer de-refs a blob that we're still constructing, and there are |
| 160 // no references to that blob. We ignore broken as well, in the case where | 104 // no references to that blob. We ignore broken as well, in the case where |
| 161 // we decided to break a blob after sending the memory request. | 105 // we decided to break a blob after sending the memory request. |
| 162 // Note: if a blob is broken, then it can't be in the async_builder. | 106 // Note: if a blob is broken, then it can't be in the async_builder. |
| 163 // Second, if the last dereference of the blob happened on a different host, | 107 // Second, if the last dereference of the blob happened on a different host, |
| 164 // then we still haven't gotten rid of the 'building' state in the original | 108 // then we still haven't gotten rid of the 'building' state in the original |
| 165 // host. So we call cancel, and send the message just in case that happens. | 109 // host. So we call cancel, and send the message just in case that happens. |
| 166 if (async_builder_.IsBeingBuilt(uuid)) { | 110 if (async_builder_.IsBeingBuilt(uuid)) { |
| 167 async_builder_.CancelBuildingBlob( | 111 async_builder_.CancelBuildingBlob( |
| 168 uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING, | 112 uuid, BlobStatus::ERR_BLOB_DEREFERENCED_WHILE_BUILDING, context); |
| 169 context); | 113 MaybeSendFinalBlobStatus( |
| 170 Send(new BlobStorageMsg_CancelBuildingBlob( | 114 uuid, BlobStatus::ERR_BLOB_DEREFERENCED_WHILE_BUILDING); |
| 171 uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING)); | |
| 172 } | 115 } |
| 173 return; | 116 return; |
| 174 } | 117 } |
| 175 if (!async_builder_.IsBeingBuilt(uuid)) { | 118 if (!async_builder_.IsBeingBuilt(uuid)) { |
| 176 SendIPCResponse(uuid, BlobTransportResult::BAD_IPC); | 119 bad_message::ReceivedBadMessage(this, bad_message::BDH_CONSTRUCTION_FAILED); |
| 177 return; | 120 return; |
| 178 } | 121 } |
| 179 BlobTransportResult result = | 122 BlobStatus result = |
| 180 async_builder_.OnMemoryResponses(uuid, responses, context); | 123 async_builder_.OnMemoryResponses(uuid, responses, context); |
| 181 SendIPCResponse(uuid, result); | 124 MaybeSendFinalBlobStatus(uuid, result); |
| 182 } | 125 } |
| 183 | 126 |
| 184 void BlobDispatcherHost::OnCancelBuildingBlob( | 127 void BlobDispatcherHost::OnCancelBuildingBob(const std::string& uuid, |
| 185 const std::string& uuid, | 128 const storage::BlobStatus code) { |
| 186 const storage::IPCBlobCreationCancelCode code) { | |
| 187 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 129 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 188 if (uuid.empty()) { | 130 if (uuid.empty()) { |
| 189 SendIPCResponse(uuid, BlobTransportResult::BAD_IPC); | 131 bad_message::ReceivedBadMessage(this, bad_message::BDH_CONSTRUCTION_FAILED); |
| 190 return; | 132 return; |
| 191 } | 133 } |
| 192 BlobStorageContext* context = this->context(); | 134 BlobStorageContext* context = this->context(); |
| 193 const BlobStorageRegistry::Entry* entry = context->registry().GetEntry(uuid); | 135 const storage::InternalBlobData* entry = context->registry().GetEntry(uuid); |
| 194 if (!entry || entry->state == BlobStorageRegistry::BlobState::BROKEN) { | 136 if (!entry || BlobStatusIsError(entry->status())) { |
| 195 // We ignore messages for blobs that don't exist to handle the case where | 137 // We ignore messages for blobs that don't exist to handle the case where |
| 196 // the renderer de-refs a blob that we're still constructing, and there are | 138 // the renderer de-refs a blob that we're still constructing, and there are |
| 197 // no references to that blob. We ignore broken as well, in the case where | 139 // no references to that blob. We ignore broken as well, in the case where |
| 198 // we decided to break a blob and the renderer also decided to cancel. | 140 // we decided to break a blob and the renderer also decided to cancel. |
| 199 // Note: if a blob is broken, then it can't be in the async_builder. | 141 // Note: if a blob is broken, then it can't be in the async_builder. |
| 200 // Second, if the last dereference of the blob happened on a different host, | 142 // Second, if the last dereference of the blob happened on a different host, |
| 201 // then we still haven't gotten rid of the 'building' state in the original | 143 // then we still haven't gotten rid of the 'building' state in the original |
| 202 // host. So we call cancel just in case this happens. | 144 // host. So we call cancel just in case this happens. |
| 203 if (async_builder_.IsBeingBuilt(uuid)) { | 145 if (async_builder_.IsBeingBuilt(uuid)) { |
| 204 async_builder_.CancelBuildingBlob( | 146 async_builder_.CancelBuildingBlob( |
| 205 uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING, | 147 uuid, BlobStatus::ERR_BLOB_DEREFERENCED_WHILE_BUILDING, context); |
| 206 context); | |
| 207 } | 148 } |
| 208 return; | 149 return; |
| 209 } | 150 } |
| 210 if (!async_builder_.IsBeingBuilt(uuid)) { | 151 // We should only get these messages for errors. |
| 211 SendIPCResponse(uuid, BlobTransportResult::BAD_IPC); | 152 if (!async_builder_.IsBeingBuilt(uuid) || !storage::BlobStatusIsError(code)) { |
| 153 bad_message::ReceivedBadMessage(this, bad_message::BDH_CONSTRUCTION_FAILED); | |
| 212 return; | 154 return; |
| 213 } | 155 } |
| 214 VLOG(1) << "Blob construction of " << uuid << " cancelled by renderer. " | 156 VLOG(1) << "Blob construction of " << uuid << " cancelled by renderer. " |
| 215 << " Reason: " << static_cast<int>(code) << "."; | 157 << " Reason: " << static_cast<int>(code) << "."; |
| 216 async_builder_.CancelBuildingBlob(uuid, code, context); | 158 async_builder_.CancelBuildingBlob(uuid, code, context); |
| 217 } | 159 } |
| 218 | 160 |
| 219 void BlobDispatcherHost::OnIncrementBlobRefCount(const std::string& uuid) { | 161 void BlobDispatcherHost::OnIncrementBlobRefCount(const std::string& uuid) { |
| 220 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 162 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 221 BlobStorageContext* context = this->context(); | 163 BlobStorageContext* context = this->context(); |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 249 context->DecrementBlobRefCount(uuid); | 191 context->DecrementBlobRefCount(uuid); |
| 250 blobs_inuse_map_[uuid] -= 1; | 192 blobs_inuse_map_[uuid] -= 1; |
| 251 if (blobs_inuse_map_[uuid] == 0) { | 193 if (blobs_inuse_map_[uuid] == 0) { |
| 252 blobs_inuse_map_.erase(uuid); | 194 blobs_inuse_map_.erase(uuid); |
| 253 // If the blob has been deleted in the context and we're still building it, | 195 // If the blob has been deleted in the context and we're still building it, |
| 254 // this means we have no references waiting to read it. Clear the building | 196 // this means we have no references waiting to read it. Clear the building |
| 255 // state and send a cancel message to the renderer. | 197 // state and send a cancel message to the renderer. |
| 256 if (async_builder_.IsBeingBuilt(uuid) && | 198 if (async_builder_.IsBeingBuilt(uuid) && |
| 257 !context->registry().HasEntry(uuid)) { | 199 !context->registry().HasEntry(uuid)) { |
| 258 async_builder_.CancelBuildingBlob( | 200 async_builder_.CancelBuildingBlob( |
| 259 uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING, | 201 uuid, BlobStatus::ERR_BLOB_DEREFERENCED_WHILE_BUILDING, context); |
| 260 context); | 202 MaybeSendFinalBlobStatus( |
| 261 Send(new BlobStorageMsg_CancelBuildingBlob( | 203 uuid, BlobStatus::ERR_BLOB_DEREFERENCED_WHILE_BUILDING); |
|
michaeln
2016/08/15 22:44:42
at callsites where there's no maybe about it, mayb
dmurph
2016/08/19 00:18:31
No more maybe.
| |
| 262 uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING)); | |
| 263 } | 204 } |
| 264 } | 205 } |
| 265 } | 206 } |
| 266 | 207 |
| 267 void BlobDispatcherHost::OnRegisterPublicBlobURL(const GURL& public_url, | 208 void BlobDispatcherHost::OnRegisterPublicBlobURL(const GURL& public_url, |
| 268 const std::string& uuid) { | 209 const std::string& uuid) { |
| 269 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 210 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 270 BlobStorageContext* context = this->context(); | 211 BlobStorageContext* context = this->context(); |
| 271 if (uuid.empty()) { | 212 if (uuid.empty()) { |
| 272 bad_message::ReceivedBadMessage(this, | 213 bad_message::ReceivedBadMessage(this, |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 297 context()->RevokePublicBlobURL(public_url); | 238 context()->RevokePublicBlobURL(public_url); |
| 298 public_blob_urls_.erase(public_url); | 239 public_blob_urls_.erase(public_url); |
| 299 } | 240 } |
| 300 | 241 |
| 301 storage::BlobStorageContext* BlobDispatcherHost::context() { | 242 storage::BlobStorageContext* BlobDispatcherHost::context() { |
| 302 return blob_storage_context_->context(); | 243 return blob_storage_context_->context(); |
| 303 } | 244 } |
| 304 | 245 |
| 305 void BlobDispatcherHost::SendMemoryRequest( | 246 void BlobDispatcherHost::SendMemoryRequest( |
| 306 const std::string& uuid, | 247 const std::string& uuid, |
| 307 std::unique_ptr<std::vector<storage::BlobItemBytesRequest>> requests, | 248 std::vector<storage::BlobItemBytesRequest> requests, |
| 308 std::unique_ptr<std::vector<base::SharedMemoryHandle>> memory_handles, | 249 std::vector<base::SharedMemoryHandle> memory_handles, |
| 309 std::unique_ptr<std::vector<base::File>> files) { | 250 std::vector<base::File> files) { |
| 310 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 251 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 311 std::vector<IPC::PlatformFileForTransit> file_handles; | 252 std::vector<IPC::PlatformFileForTransit> file_handles; |
| 312 // TODO(dmurph): Support file-backed blob transportation. | 253 for (base::File& file : files) { |
| 313 DCHECK(files->empty()); | 254 file_handles.push_back(IPC::TakePlatformFileForTransit(std::move(file))); |
| 314 Send(new BlobStorageMsg_RequestMemoryItem(uuid, *requests, *memory_handles, | 255 } |
| 256 Send(new BlobStorageMsg_RequestMemoryItem(uuid, requests, memory_handles, | |
| 315 file_handles)); | 257 file_handles)); |
| 316 } | 258 } |
| 317 | 259 |
| 318 void BlobDispatcherHost::SendIPCResponse(const std::string& uuid, | 260 void BlobDispatcherHost::MaybeSendFinalBlobStatus(const std::string& uuid, |
| 319 storage::BlobTransportResult result) { | 261 BlobStatus status) { |
| 320 switch (result) { | 262 if (storage::BlobStatusIsBadIPC(status)) { |
| 321 case BlobTransportResult::BAD_IPC: | 263 blobs_inuse_map_.erase(uuid); |
| 322 bad_message::ReceivedBadMessage(this, | 264 bad_message::ReceivedBadMessage(this, bad_message::BDH_CONSTRUCTION_FAILED); |
| 323 bad_message::BDH_CONSTRUCTION_FAILED); | 265 return; |
| 324 return; | |
| 325 case BlobTransportResult::CANCEL_MEMORY_FULL: | |
| 326 Send(new BlobStorageMsg_CancelBuildingBlob( | |
| 327 uuid, IPCBlobCreationCancelCode::OUT_OF_MEMORY)); | |
| 328 return; | |
| 329 case BlobTransportResult::CANCEL_FILE_ERROR: | |
| 330 Send(new BlobStorageMsg_CancelBuildingBlob( | |
| 331 uuid, IPCBlobCreationCancelCode::FILE_WRITE_FAILED)); | |
| 332 return; | |
| 333 case BlobTransportResult::CANCEL_REFERENCED_BLOB_BROKEN: | |
| 334 Send(new BlobStorageMsg_CancelBuildingBlob( | |
| 335 uuid, IPCBlobCreationCancelCode::REFERENCED_BLOB_BROKEN)); | |
| 336 return; | |
| 337 case BlobTransportResult::CANCEL_UNKNOWN: | |
| 338 Send(new BlobStorageMsg_CancelBuildingBlob( | |
| 339 uuid, IPCBlobCreationCancelCode::UNKNOWN)); | |
| 340 return; | |
| 341 case BlobTransportResult::PENDING_RESPONSES: | |
| 342 return; | |
| 343 case BlobTransportResult::DONE: | |
| 344 Send(new BlobStorageMsg_DoneBuildingBlob(uuid)); | |
| 345 return; | |
| 346 } | 266 } |
| 347 NOTREACHED(); | 267 if (BlobStatusIsPending(status)) |
| 268 return; | |
| 269 Send(new BlobStorageMsg_SendBlobStatus(uuid, status)); | |
| 348 } | 270 } |
| 349 | 271 |
| 350 bool BlobDispatcherHost::IsInUseInHost(const std::string& uuid) { | 272 bool BlobDispatcherHost::IsInUseInHost(const std::string& uuid) { |
| 351 return blobs_inuse_map_.find(uuid) != blobs_inuse_map_.end(); | 273 return blobs_inuse_map_.find(uuid) != blobs_inuse_map_.end(); |
| 352 } | 274 } |
| 353 | 275 |
| 354 bool BlobDispatcherHost::IsUrlRegisteredInHost(const GURL& blob_url) { | 276 bool BlobDispatcherHost::IsUrlRegisteredInHost(const GURL& blob_url) { |
| 355 return public_blob_urls_.find(blob_url) != public_blob_urls_.end(); | 277 return public_blob_urls_.find(blob_url) != public_blob_urls_.end(); |
| 356 } | 278 } |
| 357 | 279 |
| 358 void BlobDispatcherHost::ClearHostFromBlobStorageContext() { | 280 void BlobDispatcherHost::ClearHostFromBlobStorageContext() { |
| 359 BlobStorageContext* context = this->context(); | 281 BlobStorageContext* context = this->context(); |
| 360 for (const auto& url : public_blob_urls_) { | 282 for (const auto& url : public_blob_urls_) { |
| 361 context->RevokePublicBlobURL(url); | 283 context->RevokePublicBlobURL(url); |
| 362 } | 284 } |
| 363 for (const auto& uuid_refnum_pair : blobs_inuse_map_) { | 285 for (const auto& uuid_refnum_pair : blobs_inuse_map_) { |
| 364 for (int i = 0; i < uuid_refnum_pair.second; ++i) | 286 for (int i = 0; i < uuid_refnum_pair.second; ++i) |
| 365 context->DecrementBlobRefCount(uuid_refnum_pair.first); | 287 context->DecrementBlobRefCount(uuid_refnum_pair.first); |
| 366 } | 288 } |
| 367 async_builder_.CancelAll(context); | 289 async_builder_.CancelAll(context); |
| 368 } | 290 } |
| 369 | 291 |
| 370 } // namespace content | 292 } // namespace content |
| OLD | NEW |