Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/child/blob_storage/blob_transport_controller.h" | 5 #include "content/child/blob_storage/blob_transport_controller.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 #include <memory> | 8 #include <memory> |
| 9 #include <utility> | 9 #include <utility> |
| 10 #include <vector> | 10 #include <vector> |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 42 using base::SharedMemory; | 42 using base::SharedMemory; |
| 43 using base::SharedMemoryHandle; | 43 using base::SharedMemoryHandle; |
| 44 using storage::BlobItemBytesRequest; | 44 using storage::BlobItemBytesRequest; |
| 45 using storage::BlobItemBytesResponse; | 45 using storage::BlobItemBytesResponse; |
| 46 using storage::IPCBlobItemRequestStrategy; | 46 using storage::IPCBlobItemRequestStrategy; |
| 47 using storage::DataElement; | 47 using storage::DataElement; |
| 48 using storage::kBlobStorageIPCThresholdBytes; | 48 using storage::kBlobStorageIPCThresholdBytes; |
| 49 | 49 |
| 50 using storage::BlobItemBytesResponse; | 50 using storage::BlobItemBytesResponse; |
| 51 using storage::BlobItemBytesRequest; | 51 using storage::BlobItemBytesRequest; |
| 52 using storage::IPCBlobCreationCancelCode; | 52 using storage::BlobStatus; |
| 53 | 53 |
| 54 namespace content { | 54 namespace content { |
| 55 using ConsolidatedItem = BlobConsolidation::ConsolidatedItem; | 55 using ConsolidatedItem = BlobConsolidation::ConsolidatedItem; |
| 56 using ReadStatus = BlobConsolidation::ReadStatus; | 56 using ReadStatus = BlobConsolidation::ReadStatus; |
| 57 | 57 |
| 58 namespace { | 58 namespace { |
| 59 static base::LazyInstance<BlobTransportController>::Leaky g_controller = | 59 static base::LazyInstance<BlobTransportController>::Leaky g_controller = |
| 60 LAZY_INSTANCE_INITIALIZER; | 60 LAZY_INSTANCE_INITIALIZER; |
| 61 | 61 |
| 62 // This keeps the process alive while blobs are being transferred. | 62 // This keeps the process alive while blobs are being transferred. |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 108 BlobConsolidation::ReadStatus status = consolidation->VisitMemory( | 108 BlobConsolidation::ReadStatus status = consolidation->VisitMemory( |
| 109 request.renderer_item_index, request.renderer_item_offset, request.size, | 109 request.renderer_item_index, request.renderer_item_offset, request.size, |
| 110 base::Bind(&WriteSingleChunk, file)); | 110 base::Bind(&WriteSingleChunk, file)); |
| 111 if (status != BlobConsolidation::ReadStatus::OK) | 111 if (status != BlobConsolidation::ReadStatus::OK) |
| 112 return base::nullopt; | 112 return base::nullopt; |
| 113 File::Info info; | 113 File::Info info; |
| 114 file->GetInfo(&info); | 114 file->GetInfo(&info); |
| 115 return base::make_optional(info.last_modified); | 115 return base::make_optional(info.last_modified); |
| 116 } | 116 } |
| 117 | 117 |
| 118 // This returns either the responses, or if they're empty, an error code. | 118 std::pair<BlobStatus, std::vector<BlobItemBytesResponse>> WriteDiskRequests( |
| 119 std::pair<std::vector<storage::BlobItemBytesResponse>, | |
| 120 IPCBlobCreationCancelCode> | |
| 121 WriteDiskRequests( | |
| 122 scoped_refptr<BlobConsolidation> consolidation, | 119 scoped_refptr<BlobConsolidation> consolidation, |
| 123 std::unique_ptr<std::vector<BlobItemBytesRequest>> requests, | 120 std::unique_ptr<std::vector<BlobItemBytesRequest>> requests, |
| 124 const std::vector<IPC::PlatformFileForTransit>& file_handles) { | 121 const std::vector<IPC::PlatformFileForTransit>& file_handles) { |
| 125 std::vector<BlobItemBytesResponse> responses; | 122 std::vector<BlobItemBytesResponse> responses; |
| 126 std::vector<base::Time> last_modified_times; | 123 std::vector<base::Time> last_modified_times; |
| 127 last_modified_times.resize(file_handles.size()); | 124 last_modified_times.resize(file_handles.size()); |
| 128 // We grab ownership of the file handles here. When this vector is destroyed | 125 // We grab ownership of the file handles here. When this vector is destroyed |
| 129 // it will close the files. | 126 // it will close the files. |
| 130 std::vector<File> files; | 127 std::vector<File> files; |
| 131 files.reserve(file_handles.size()); | 128 files.reserve(file_handles.size()); |
| 132 for (const auto& file_handle : file_handles) { | 129 for (const auto& file_handle : file_handles) { |
| 133 files.emplace_back(IPC::PlatformFileForTransitToFile(file_handle)); | 130 files.emplace_back(IPC::PlatformFileForTransitToFile(file_handle)); |
| 134 } | 131 } |
| 135 for (const auto& request : *requests) { | 132 for (const auto& request : *requests) { |
| 136 base::Optional<base::Time> last_modified = WriteSingleRequestToDisk( | 133 base::Optional<base::Time> last_modified = WriteSingleRequestToDisk( |
| 137 consolidation.get(), request, &files[request.handle_index]); | 134 consolidation.get(), request, &files[request.handle_index]); |
| 138 if (!last_modified) { | 135 if (!last_modified) { |
| 139 return std::make_pair(std::vector<storage::BlobItemBytesResponse>(), | 136 return std::make_pair(BlobStatus::FILE_WRITE_FAILED, |
| 140 IPCBlobCreationCancelCode::FILE_WRITE_FAILED); | 137 std::vector<storage::BlobItemBytesResponse>()); |
| 141 } | 138 } |
| 142 last_modified_times[request.handle_index] = last_modified.value(); | 139 last_modified_times[request.handle_index] = last_modified.value(); |
| 143 } | 140 } |
| 144 for (const auto& request : *requests) { | 141 for (const auto& request : *requests) { |
| 145 responses.push_back(BlobItemBytesResponse(request.request_number)); | 142 responses.push_back(BlobItemBytesResponse(request.request_number)); |
| 146 responses.back().time_file_modified = | 143 responses.back().time_file_modified = |
| 147 last_modified_times[request.handle_index]; | 144 last_modified_times[request.handle_index]; |
| 148 } | 145 } |
| 149 | 146 |
| 150 return std::make_pair(responses, IPCBlobCreationCancelCode::UNKNOWN); | 147 return std::make_pair(BlobStatus::DONE, responses); |
| 151 } | 148 } |
| 152 | 149 |
| 153 } // namespace | 150 } // namespace |
| 154 | 151 |
| 155 BlobTransportController* BlobTransportController::GetInstance() { | 152 BlobTransportController* BlobTransportController::GetInstance() { |
| 156 return g_controller.Pointer(); | 153 return g_controller.Pointer(); |
| 157 } | 154 } |
| 158 | 155 |
| 159 // static | 156 // static |
| 160 void BlobTransportController::InitiateBlobTransfer( | 157 void BlobTransportController::InitiateBlobTransfer( |
| 161 const std::string& uuid, | 158 const std::string& uuid, |
| 162 const std::string& content_type, | 159 const std::string& content_type, |
| 163 scoped_refptr<BlobConsolidation> consolidation, | 160 scoped_refptr<BlobConsolidation> consolidation, |
| 164 scoped_refptr<ThreadSafeSender> sender, | 161 scoped_refptr<ThreadSafeSender> sender, |
| 165 base::SingleThreadTaskRunner* io_runner, | 162 base::SingleThreadTaskRunner* io_runner, |
| 166 scoped_refptr<base::SingleThreadTaskRunner> main_runner) { | 163 scoped_refptr<base::SingleThreadTaskRunner> main_runner) { |
| 167 if (main_runner->BelongsToCurrentThread()) { | 164 if (main_runner->BelongsToCurrentThread()) { |
| 168 IncChildProcessRefCount(); | 165 IncChildProcessRefCount(); |
| 169 } else { | 166 } else { |
| 170 main_runner->PostTask(FROM_HERE, base::Bind(&IncChildProcessRefCount)); | 167 main_runner->PostTask(FROM_HERE, base::Bind(&IncChildProcessRefCount)); |
| 171 } | 168 } |
| 172 | 169 |
| 173 std::vector<storage::DataElement> descriptions; | 170 std::vector<storage::DataElement> descriptions; |
| 174 std::set<std::string> referenced_blobs = consolidation->referenced_blobs(); | |
| 175 BlobTransportController::GetDescriptions( | 171 BlobTransportController::GetDescriptions( |
| 176 consolidation.get(), kBlobStorageIPCThresholdBytes, &descriptions); | 172 consolidation.get(), kBlobStorageIPCThresholdBytes, &descriptions); |
| 177 // I post the task first to make sure that we store our consolidation before | 173 // I post the task first to make sure that we store our consolidation before |
| 178 // we get a request back from the browser. | 174 // we get a request back from the browser. |
| 179 io_runner->PostTask( | 175 io_runner->PostTask( |
| 180 FROM_HERE, | 176 FROM_HERE, |
| 181 base::Bind(&BlobTransportController::StoreBlobDataForRequests, | 177 base::Bind(&BlobTransportController::StoreBlobDataForRequests, |
| 182 base::Unretained(BlobTransportController::GetInstance()), uuid, | 178 base::Unretained(BlobTransportController::GetInstance()), uuid, |
| 183 base::Passed(std::move(consolidation)), | 179 base::Passed(std::move(consolidation)), |
| 184 base::Passed(std::move(main_runner)))); | 180 base::Passed(std::move(main_runner)))); |
| 185 // TODO(dmurph): Merge register and start messages. | 181 sender->Send( |
| 186 sender->Send(new BlobStorageMsg_RegisterBlobUUID(uuid, content_type, "", | 182 new BlobStorageMsg_RegisterBlob(uuid, content_type, "", descriptions)); |
| 187 referenced_blobs)); | |
| 188 sender->Send(new BlobStorageMsg_StartBuildingBlob(uuid, descriptions)); | |
| 189 } | 183 } |
| 190 | 184 |
| 191 void BlobTransportController::OnMemoryRequest( | 185 void BlobTransportController::OnMemoryRequest( |
| 192 const std::string& uuid, | 186 const std::string& uuid, |
| 193 const std::vector<storage::BlobItemBytesRequest>& requests, | 187 const std::vector<storage::BlobItemBytesRequest>& requests, |
| 194 std::vector<base::SharedMemoryHandle>* memory_handles, | 188 std::vector<base::SharedMemoryHandle>* memory_handles, |
| 195 const std::vector<IPC::PlatformFileForTransit>& file_handles, | 189 const std::vector<IPC::PlatformFileForTransit>& file_handles, |
| 196 base::TaskRunner* file_runner, | 190 base::TaskRunner* file_runner, |
| 197 IPC::Sender* sender) { | 191 IPC::Sender* sender) { |
| 198 std::vector<BlobItemBytesResponse> responses; | 192 std::vector<BlobItemBytesResponse> responses; |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 297 base::Bind(&WriteDiskRequests, make_scoped_refptr(consolidation), | 291 base::Bind(&WriteDiskRequests, make_scoped_refptr(consolidation), |
| 298 base::Passed(&file_requests), file_handles), | 292 base::Passed(&file_requests), file_handles), |
| 299 base::Bind(&BlobTransportController::OnFileWriteComplete, | 293 base::Bind(&BlobTransportController::OnFileWriteComplete, |
| 300 weak_factory_.GetWeakPtr(), sender, uuid)); | 294 weak_factory_.GetWeakPtr(), sender, uuid)); |
| 301 } | 295 } |
| 302 | 296 |
| 303 if (!responses.empty()) | 297 if (!responses.empty()) |
| 304 sender->Send(new BlobStorageMsg_MemoryItemResponse(uuid, responses)); | 298 sender->Send(new BlobStorageMsg_MemoryItemResponse(uuid, responses)); |
| 305 } | 299 } |
| 306 | 300 |
| 307 void BlobTransportController::OnCancel( | 301 void BlobTransportController::OnBlobStatus(const std::string& uuid, |
| 308 const std::string& uuid, | 302 storage::BlobStatus code) { |
| 309 storage::IPCBlobCreationCancelCode code) { | 303 if (storage::BlobStatusIsError(code)) { |
| 310 DVLOG(1) << "Received blob cancel for blob " << uuid | 304 DVLOG(1) << "Received blob error for blob " << uuid |
| 311 << " with code: " << static_cast<int>(code); | 305 << " with code: " << static_cast<int>(code); |
| 306 ReleaseBlobConsolidation(uuid); | |
|
michaeln
2016/07/15 02:12:07
since ReleaseBlobConsolidation() happens in all ca
dmurph
2016/07/15 20:18:15
Done.
| |
| 307 return; | |
| 308 } | |
| 309 DCHECK(code == storage::BlobStatus::DONE); | |
| 312 ReleaseBlobConsolidation(uuid); | 310 ReleaseBlobConsolidation(uuid); |
| 313 } | 311 } |
| 314 | 312 |
| 315 void BlobTransportController::OnDone(const std::string& uuid) { | |
| 316 ReleaseBlobConsolidation(uuid); | |
| 317 } | |
| 318 | |
| 319 void BlobTransportController::CancelAllBlobTransfers() { | 313 void BlobTransportController::CancelAllBlobTransfers() { |
| 320 weak_factory_.InvalidateWeakPtrs(); | 314 weak_factory_.InvalidateWeakPtrs(); |
| 321 if (!blob_storage_.empty() && main_thread_runner_) { | 315 if (!blob_storage_.empty() && main_thread_runner_) { |
| 322 main_thread_runner_->PostTask( | 316 main_thread_runner_->PostTask( |
| 323 FROM_HERE, | 317 FROM_HERE, |
| 324 base::Bind(&DecChildProcessRefCountTimes, blob_storage_.size())); | 318 base::Bind(&DecChildProcessRefCountTimes, blob_storage_.size())); |
| 325 } | 319 } |
| 326 main_thread_runner_ = nullptr; | 320 main_thread_runner_ = nullptr; |
| 327 blob_storage_.clear(); | 321 blob_storage_.clear(); |
| 328 } | 322 } |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 381 } | 375 } |
| 382 } | 376 } |
| 383 | 377 |
| 384 BlobTransportController::BlobTransportController() : weak_factory_(this) {} | 378 BlobTransportController::BlobTransportController() : weak_factory_(this) {} |
| 385 | 379 |
| 386 BlobTransportController::~BlobTransportController() {} | 380 BlobTransportController::~BlobTransportController() {} |
| 387 | 381 |
| 388 void BlobTransportController::OnFileWriteComplete( | 382 void BlobTransportController::OnFileWriteComplete( |
| 389 IPC::Sender* sender, | 383 IPC::Sender* sender, |
| 390 const std::string& uuid, | 384 const std::string& uuid, |
| 391 const std::pair<std::vector<BlobItemBytesResponse>, | 385 const std::pair<BlobStatus, std::vector<BlobItemBytesResponse>>& result) { |
| 392 IPCBlobCreationCancelCode>& result) { | |
| 393 if (blob_storage_.find(uuid) == blob_storage_.end()) | 386 if (blob_storage_.find(uuid) == blob_storage_.end()) |
| 394 return; | 387 return; |
| 395 if (!result.first.empty()) { | 388 if (BlobStatusIsError(result.first)) { |
| 396 sender->Send(new BlobStorageMsg_MemoryItemResponse(uuid, result.first)); | 389 sender->Send(new BlobStorageMsg_SendBlobStatus(uuid, result.first)); |
| 390 ReleaseBlobConsolidation(uuid); | |
| 397 return; | 391 return; |
| 398 } | 392 } |
| 399 sender->Send(new BlobStorageMsg_CancelBuildingBlob(uuid, result.second)); | 393 sender->Send(new BlobStorageMsg_MemoryItemResponse(uuid, result.second)); |
| 400 ReleaseBlobConsolidation(uuid); | |
| 401 } | 394 } |
| 402 | 395 |
| 403 void BlobTransportController::StoreBlobDataForRequests( | 396 void BlobTransportController::StoreBlobDataForRequests( |
| 404 const std::string& uuid, | 397 const std::string& uuid, |
| 405 scoped_refptr<BlobConsolidation> consolidation, | 398 scoped_refptr<BlobConsolidation> consolidation, |
| 406 scoped_refptr<base::SingleThreadTaskRunner> main_runner) { | 399 scoped_refptr<base::SingleThreadTaskRunner> main_runner) { |
| 407 if (!main_thread_runner_.get()) { | 400 if (!main_thread_runner_.get()) { |
| 408 main_thread_runner_ = std::move(main_runner); | 401 main_thread_runner_ = std::move(main_runner); |
| 409 } | 402 } |
| 410 blob_storage_[uuid] = std::move(consolidation); | 403 blob_storage_[uuid] = std::move(consolidation); |
| 411 } | 404 } |
| 412 | 405 |
| 413 void BlobTransportController::ReleaseBlobConsolidation( | 406 void BlobTransportController::ReleaseBlobConsolidation( |
| 414 const std::string& uuid) { | 407 const std::string& uuid) { |
| 415 if (blob_storage_.erase(uuid)) { | 408 if (blob_storage_.erase(uuid)) { |
| 416 main_thread_runner_->PostTask(FROM_HERE, | 409 main_thread_runner_->PostTask(FROM_HERE, |
| 417 base::Bind(&DecChildProcessRefCount)); | 410 base::Bind(&DecChildProcessRefCount)); |
| 418 } | 411 } |
| 419 } | 412 } |
| 420 | 413 |
| 421 } // namespace content | 414 } // namespace content |
| OLD | NEW |