| 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 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 75 } | 75 } |
| 76 } | 76 } |
| 77 | 77 |
| 78 bool WriteSingleChunk(base::File* file, const char* memory, size_t size) { | 78 bool WriteSingleChunk(base::File* file, const char* memory, size_t size) { |
| 79 size_t written = 0; | 79 size_t written = 0; |
| 80 while (written < size) { | 80 while (written < size) { |
| 81 size_t writing_size = base::saturated_cast<int>(size - written); | 81 size_t writing_size = base::saturated_cast<int>(size - written); |
| 82 int actual_written = | 82 int actual_written = |
| 83 file->WriteAtCurrentPos(memory, static_cast<int>(writing_size)); | 83 file->WriteAtCurrentPos(memory, static_cast<int>(writing_size)); |
| 84 bool write_failed = actual_written < 0; | 84 bool write_failed = actual_written < 0; |
| 85 LOG_IF(ERROR, write_failed) << "Write failed"; |
| 85 UMA_HISTOGRAM_BOOLEAN("Storage.Blob.RendererFileWriteFailed", write_failed); | 86 UMA_HISTOGRAM_BOOLEAN("Storage.Blob.RendererFileWriteFailed", write_failed); |
| 86 if (write_failed) | 87 if (write_failed) |
| 87 return false; | 88 return false; |
| 88 written += actual_written; | 89 written += actual_written; |
| 89 } | 90 } |
| 90 return true; | 91 return true; |
| 91 } | 92 } |
| 92 | 93 |
| 93 base::Optional<base::Time> WriteSingleRequestToDisk( | 94 bool WriteSingleRequestToDisk(const BlobConsolidation* consolidation, |
| 94 const BlobConsolidation* consolidation, | 95 const BlobItemBytesRequest& request, |
| 95 const BlobItemBytesRequest& request, | 96 File* file) { |
| 96 File* file) { | |
| 97 if (!file->IsValid()) | 97 if (!file->IsValid()) |
| 98 return base::nullopt; | 98 return false; |
| 99 int64_t seek_distance = file->Seek( | 99 int64_t seek_distance = file->Seek( |
| 100 File::FROM_BEGIN, base::checked_cast<int64_t>(request.handle_offset)); | 100 File::FROM_BEGIN, base::checked_cast<int64_t>(request.handle_offset)); |
| 101 bool seek_failed = seek_distance < 0; | 101 bool seek_failed = seek_distance < 0; |
| 102 UMA_HISTOGRAM_BOOLEAN("Storage.Blob.RendererFileSeekFailed", seek_failed); | 102 UMA_HISTOGRAM_BOOLEAN("Storage.Blob.RendererFileSeekFailed", seek_failed); |
| 103 if (seek_failed) { | 103 if (seek_failed) { |
| 104 return base::nullopt; | 104 LOG(ERROR) << "Seek failed"; |
| 105 return false; |
| 105 } | 106 } |
| 106 BlobConsolidation::ReadStatus status = consolidation->VisitMemory( | 107 BlobConsolidation::ReadStatus status = consolidation->VisitMemory( |
| 107 request.renderer_item_index, request.renderer_item_offset, request.size, | 108 request.renderer_item_index, request.renderer_item_offset, request.size, |
| 108 base::Bind(&WriteSingleChunk, file)); | 109 base::Bind(&WriteSingleChunk, file)); |
| 109 if (status != BlobConsolidation::ReadStatus::OK) | 110 if (status != BlobConsolidation::ReadStatus::OK) |
| 110 return base::nullopt; | 111 return false; |
| 111 File::Info info; | 112 return true; |
| 112 file->GetInfo(&info); | |
| 113 return base::make_optional(info.last_modified); | |
| 114 } | 113 } |
| 115 | 114 |
| 116 base::Optional<std::vector<BlobItemBytesResponse>> WriteDiskRequests( | 115 base::Optional<std::vector<BlobItemBytesResponse>> WriteDiskRequests( |
| 117 scoped_refptr<BlobConsolidation> consolidation, | 116 scoped_refptr<BlobConsolidation> consolidation, |
| 118 std::unique_ptr<std::vector<BlobItemBytesRequest>> requests, | 117 std::unique_ptr<std::vector<BlobItemBytesRequest>> requests, |
| 119 const std::vector<IPC::PlatformFileForTransit>& file_handles) { | 118 const std::vector<IPC::PlatformFileForTransit>& file_handles) { |
| 120 std::vector<BlobItemBytesResponse> responses; | 119 std::vector<BlobItemBytesResponse> responses; |
| 121 std::vector<base::Time> last_modified_times; | |
| 122 last_modified_times.resize(file_handles.size()); | |
| 123 // We grab ownership of the file handles here. When this vector is destroyed | 120 // We grab ownership of the file handles here. When this vector is destroyed |
| 124 // it will close the files. | 121 // it will close the files. |
| 125 std::vector<File> files; | 122 std::vector<File> files; |
| 126 files.reserve(file_handles.size()); | 123 files.reserve(file_handles.size()); |
| 127 for (const auto& file_handle : file_handles) { | 124 for (const auto& file_handle : file_handles) { |
| 128 files.emplace_back(IPC::PlatformFileForTransitToFile(file_handle)); | 125 files.emplace_back(IPC::PlatformFileForTransitToFile(file_handle)); |
| 129 } | 126 } |
| 127 // First we write everything, then we flush, then we grab the last modified |
| 128 // times. |
| 130 for (const auto& request : *requests) { | 129 for (const auto& request : *requests) { |
| 131 base::Optional<base::Time> last_modified = WriteSingleRequestToDisk( | 130 if (!WriteSingleRequestToDisk(consolidation.get(), request, |
| 132 consolidation.get(), request, &files[request.handle_index]); | 131 &files[request.handle_index])) { |
| 133 if (!last_modified) { | |
| 134 return base::nullopt; | 132 return base::nullopt; |
| 135 } | 133 } |
| 136 last_modified_times[request.handle_index] = last_modified.value(); | |
| 137 } | 134 } |
| 135 std::vector<base::Time> last_modified_times; |
| 136 last_modified_times.resize(file_handles.size()); |
| 137 for (size_t i = 0; i < files.size(); ++i) { |
| 138 auto& file = files[i]; |
| 139 if (!file.Flush()) |
| 140 return base::nullopt; |
| 141 File::Info info; |
| 142 if (!file.GetInfo(&info)) |
| 143 return base::nullopt; |
| 144 LOG(ERROR) << "got post-flush modified time " |
| 145 << info.last_modified.ToInternalValue(); |
| 146 last_modified_times[i] = info.last_modified; |
| 147 } |
| 148 |
| 138 for (const auto& request : *requests) { | 149 for (const auto& request : *requests) { |
| 139 responses.push_back(BlobItemBytesResponse(request.request_number)); | 150 responses.push_back(BlobItemBytesResponse(request.request_number)); |
| 140 responses.back().time_file_modified = | 151 responses.back().time_file_modified = |
| 141 last_modified_times[request.handle_index]; | 152 last_modified_times[request.handle_index]; |
| 142 } | 153 } |
| 143 | 154 |
| 144 return responses; | 155 return responses; |
| 145 } | 156 } |
| 146 | 157 |
| 147 } // namespace | 158 } // namespace |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 374 | 385 |
| 375 BlobTransportController::~BlobTransportController() {} | 386 BlobTransportController::~BlobTransportController() {} |
| 376 | 387 |
| 377 void BlobTransportController::OnFileWriteComplete( | 388 void BlobTransportController::OnFileWriteComplete( |
| 378 IPC::Sender* sender, | 389 IPC::Sender* sender, |
| 379 const std::string& uuid, | 390 const std::string& uuid, |
| 380 const base::Optional<std::vector<storage::BlobItemBytesResponse>>& result) { | 391 const base::Optional<std::vector<storage::BlobItemBytesResponse>>& result) { |
| 381 if (blob_storage_.find(uuid) == blob_storage_.end()) | 392 if (blob_storage_.find(uuid) == blob_storage_.end()) |
| 382 return; | 393 return; |
| 383 if (!result) { | 394 if (!result) { |
| 395 LOG(ERROR) << "Error writing files"; |
| 384 sender->Send(new BlobStorageMsg_SendBlobStatus( | 396 sender->Send(new BlobStorageMsg_SendBlobStatus( |
| 385 uuid, BlobStatus::ERR_FILE_WRITE_FAILED)); | 397 uuid, BlobStatus::ERR_FILE_WRITE_FAILED)); |
| 386 ReleaseBlobConsolidation(uuid); | 398 ReleaseBlobConsolidation(uuid); |
| 387 return; | 399 return; |
| 388 } | 400 } |
| 389 sender->Send(new BlobStorageMsg_MemoryItemResponse(uuid, result.value())); | 401 sender->Send(new BlobStorageMsg_MemoryItemResponse(uuid, result.value())); |
| 390 } | 402 } |
| 391 | 403 |
| 392 void BlobTransportController::StoreBlobDataForRequests( | 404 void BlobTransportController::StoreBlobDataForRequests( |
| 393 const std::string& uuid, | 405 const std::string& uuid, |
| 394 scoped_refptr<BlobConsolidation> consolidation, | 406 scoped_refptr<BlobConsolidation> consolidation, |
| 395 scoped_refptr<base::SingleThreadTaskRunner> main_runner) { | 407 scoped_refptr<base::SingleThreadTaskRunner> main_runner) { |
| 396 if (!main_thread_runner_.get()) { | 408 if (!main_thread_runner_.get()) { |
| 397 main_thread_runner_ = std::move(main_runner); | 409 main_thread_runner_ = std::move(main_runner); |
| 398 } | 410 } |
| 399 blob_storage_[uuid] = std::move(consolidation); | 411 blob_storage_[uuid] = std::move(consolidation); |
| 400 } | 412 } |
| 401 | 413 |
| 402 void BlobTransportController::ReleaseBlobConsolidation( | 414 void BlobTransportController::ReleaseBlobConsolidation( |
| 403 const std::string& uuid) { | 415 const std::string& uuid) { |
| 404 if (blob_storage_.erase(uuid)) { | 416 if (blob_storage_.erase(uuid)) { |
| 405 main_thread_runner_->PostTask(FROM_HERE, | 417 main_thread_runner_->PostTask(FROM_HERE, |
| 406 base::Bind(&DecChildProcessRefCount)); | 418 base::Bind(&DecChildProcessRefCount)); |
| 407 } | 419 } |
| 408 } | 420 } |
| 409 | 421 |
| 410 } // namespace content | 422 } // namespace content |
| OLD | NEW |