| 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 <utility> | 7 #include <utility> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
| 11 #include "base/memory/scoped_vector.h" | 11 #include "base/memory/scoped_vector.h" |
| 12 #include "base/memory/shared_memory.h" | 12 #include "base/memory/shared_memory.h" |
| 13 #include "base/single_thread_task_runner.h" | 13 #include "base/single_thread_task_runner.h" |
| 14 #include "base/threading/platform_thread.h" |
| 14 #include "base/stl_util.h" | 15 #include "base/stl_util.h" |
| 15 #include "content/child/blob_storage/blob_consolidation.h" | 16 #include "content/child/blob_storage/blob_consolidation.h" |
| 16 #include "content/child/child_process.h" | 17 #include "content/child/child_process.h" |
| 17 #include "content/child/thread_safe_sender.h" | 18 #include "content/child/thread_safe_sender.h" |
| 18 #include "content/common/fileapi/webblob_messages.h" | 19 #include "content/common/fileapi/webblob_messages.h" |
| 19 #include "ipc/ipc_sender.h" | 20 #include "ipc/ipc_sender.h" |
| 20 #include "storage/common/blob_storage/blob_item_bytes_request.h" | 21 #include "storage/common/blob_storage/blob_item_bytes_request.h" |
| 21 #include "storage/common/blob_storage/blob_item_bytes_response.h" | 22 #include "storage/common/blob_storage/blob_item_bytes_response.h" |
| 22 #include "storage/common/data_element.h" | 23 #include "storage/common/data_element.h" |
| 23 #include "third_party/WebKit/public/platform/Platform.h" | 24 #include "third_party/WebKit/public/platform/Platform.h" |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 59 } | 60 } |
| 60 | 61 |
| 61 // static | 62 // static |
| 62 void BlobTransportController::InitiateBlobTransfer( | 63 void BlobTransportController::InitiateBlobTransfer( |
| 63 const std::string& uuid, | 64 const std::string& uuid, |
| 64 const std::string& content_type, | 65 const std::string& content_type, |
| 65 std::unique_ptr<BlobConsolidation> consolidation, | 66 std::unique_ptr<BlobConsolidation> consolidation, |
| 66 scoped_refptr<ThreadSafeSender> sender, | 67 scoped_refptr<ThreadSafeSender> sender, |
| 67 base::SingleThreadTaskRunner* io_runner, | 68 base::SingleThreadTaskRunner* io_runner, |
| 68 scoped_refptr<base::SingleThreadTaskRunner> main_runner) { | 69 scoped_refptr<base::SingleThreadTaskRunner> main_runner) { |
| 70 BlobTransportController* controller = BlobTransportController::GetInstance(); |
| 71 if (consolidation->total_memory() > kBlobStorageIPCThresholdBytes) { |
| 72 LOG(ERROR) |
| 73 << uuid |
| 74 << " is about to be saved and send messages to browser. Instance: " |
| 75 << controller << ", " << base::PlatformThread::GetName(); |
| 76 } |
| 69 if (main_runner->BelongsToCurrentThread()) { | 77 if (main_runner->BelongsToCurrentThread()) { |
| 70 IncChildProcessRefCount(); | 78 IncChildProcessRefCount(); |
| 71 } else { | 79 } else { |
| 72 main_runner->PostTask(FROM_HERE, base::Bind(&IncChildProcessRefCount)); | 80 main_runner->PostTask(FROM_HERE, base::Bind(&IncChildProcessRefCount)); |
| 73 } | 81 } |
| 74 | 82 |
| 75 std::vector<storage::DataElement> descriptions; | 83 std::vector<storage::DataElement> descriptions; |
| 76 std::set<std::string> referenced_blobs = consolidation->referenced_blobs(); | 84 std::set<std::string> referenced_blobs = consolidation->referenced_blobs(); |
| 77 BlobTransportController::GetDescriptions( | 85 BlobTransportController::GetDescriptions( |
| 78 consolidation.get(), kBlobStorageIPCThresholdBytes, &descriptions); | 86 consolidation.get(), kBlobStorageIPCThresholdBytes, &descriptions); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 97 const std::vector<IPC::PlatformFileForTransit>& file_handles, | 105 const std::vector<IPC::PlatformFileForTransit>& file_handles, |
| 98 IPC::Sender* sender) { | 106 IPC::Sender* sender) { |
| 99 std::vector<storage::BlobItemBytesResponse> responses; | 107 std::vector<storage::BlobItemBytesResponse> responses; |
| 100 ResponsesStatus status = | 108 ResponsesStatus status = |
| 101 GetResponses(uuid, requests, memory_handles, file_handles, &responses); | 109 GetResponses(uuid, requests, memory_handles, file_handles, &responses); |
| 102 | 110 |
| 103 switch (status) { | 111 switch (status) { |
| 104 case ResponsesStatus::BLOB_NOT_FOUND: | 112 case ResponsesStatus::BLOB_NOT_FOUND: |
| 105 // sender->Send(new BlobStorageMsg_CancelBuildingBlob(uuid, | 113 // sender->Send(new BlobStorageMsg_CancelBuildingBlob(uuid, |
| 106 // IPCBlobCreationCancelCode::UNKNOWN)); | 114 // IPCBlobCreationCancelCode::UNKNOWN)); |
| 115 CHECK(false) << "Could not find " << uuid << " Instance: " << this << ", " |
| 116 << base::PlatformThread::GetName(); |
| 107 return; | 117 return; |
| 108 case ResponsesStatus::SHARED_MEMORY_MAP_FAILED: | 118 case ResponsesStatus::SHARED_MEMORY_MAP_FAILED: |
| 109 // This would happen if the renderer process doesn't have enough memory | 119 // This would happen if the renderer process doesn't have enough memory |
| 110 // to map the shared memory, which is possible if we don't have much | 120 // to map the shared memory, which is possible if we don't have much |
| 111 // memory. If this scenario happens often, we could delay the response | 121 // memory. If this scenario happens often, we could delay the response |
| 112 // until we have enough memory. For now we just fail. | 122 // until we have enough memory. For now we just fail. |
| 113 CHECK(false) << "Unable to map shared memory to send blob " << uuid | 123 CHECK(false) << "Unable to map shared memory to send blob " << uuid |
| 114 << "."; | 124 << "."; |
| 115 break; | 125 break; |
| 116 case ResponsesStatus::SUCCESS: | 126 case ResponsesStatus::SUCCESS: |
| 117 break; | 127 break; |
| 118 } | 128 } |
| 119 | 129 |
| 120 sender->Send(new BlobStorageMsg_MemoryItemResponse(uuid, responses)); | 130 sender->Send(new BlobStorageMsg_MemoryItemResponse(uuid, responses)); |
| 121 } | 131 } |
| 122 | 132 |
| 123 void BlobTransportController::OnCancel( | 133 void BlobTransportController::OnCancel( |
| 124 const std::string& uuid, | 134 const std::string& uuid, |
| 125 storage::IPCBlobCreationCancelCode code) { | 135 storage::IPCBlobCreationCancelCode code) { |
| 126 DVLOG(1) << "Received blob cancel for blob " << uuid | 136 LOG(ERROR) << "Received blob cancel for blob " << uuid |
| 127 << " with code: " << static_cast<int>(code); | 137 << " with code: " << static_cast<int>(code); |
| 128 ReleaseBlobConsolidation(uuid); | 138 ReleaseBlobConsolidation(uuid); |
| 129 } | 139 } |
| 130 | 140 |
| 131 void BlobTransportController::OnDone(const std::string& uuid) { | 141 void BlobTransportController::OnDone(const std::string& uuid) { |
| 142 |
| 143 auto it = blob_storage_.find(uuid); |
| 144 if (it != blob_storage_.end()) { |
| 145 |
| 146 BlobConsolidation* consolidation = it->second.get(); |
| 147 if (consolidation->total_memory() > kBlobStorageIPCThresholdBytes) { |
| 148 LOG(ERROR) << uuid << " got done for shared memory."; |
| 149 } |
| 150 } |
| 132 ReleaseBlobConsolidation(uuid); | 151 ReleaseBlobConsolidation(uuid); |
| 133 } | 152 } |
| 134 | 153 |
| 135 // static | 154 // static |
| 136 void BlobTransportController::GetDescriptions( | 155 void BlobTransportController::GetDescriptions( |
| 137 BlobConsolidation* consolidation, | 156 BlobConsolidation* consolidation, |
| 138 size_t max_data_population, | 157 size_t max_data_population, |
| 139 std::vector<storage::DataElement>* out) { | 158 std::vector<storage::DataElement>* out) { |
| 140 DCHECK(out->empty()); | 159 DCHECK(out->empty()); |
| 141 DCHECK(consolidation); | 160 DCHECK(consolidation); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 195 main_thread_runner_->PostTask(FROM_HERE, | 214 main_thread_runner_->PostTask(FROM_HERE, |
| 196 base::Bind(&DecChildProcessRefCount)); | 215 base::Bind(&DecChildProcessRefCount)); |
| 197 } | 216 } |
| 198 blob_storage_.clear(); | 217 blob_storage_.clear(); |
| 199 } | 218 } |
| 200 | 219 |
| 201 void BlobTransportController::StoreBlobDataForRequests( | 220 void BlobTransportController::StoreBlobDataForRequests( |
| 202 const std::string& uuid, | 221 const std::string& uuid, |
| 203 std::unique_ptr<BlobConsolidation> consolidation, | 222 std::unique_ptr<BlobConsolidation> consolidation, |
| 204 scoped_refptr<base::SingleThreadTaskRunner> main_runner) { | 223 scoped_refptr<base::SingleThreadTaskRunner> main_runner) { |
| 224 |
| 205 if (!main_thread_runner_.get()) { | 225 if (!main_thread_runner_.get()) { |
| 206 main_thread_runner_ = std::move(main_runner); | 226 main_thread_runner_ = std::move(main_runner); |
| 207 } | 227 } |
| 228 if (consolidation->total_memory() > kBlobStorageIPCThresholdBytes) { |
| 229 LOG(ERROR) << uuid << " storing shared memory consolidation on " |
| 230 << base::PlatformThread::GetName(); |
| 231 } |
| 208 blob_storage_[uuid] = std::move(consolidation); | 232 blob_storage_[uuid] = std::move(consolidation); |
| 209 } | 233 } |
| 210 | 234 |
| 211 BlobTransportController::ResponsesStatus BlobTransportController::GetResponses( | 235 BlobTransportController::ResponsesStatus BlobTransportController::GetResponses( |
| 212 const std::string& uuid, | 236 const std::string& uuid, |
| 213 const std::vector<BlobItemBytesRequest>& requests, | 237 const std::vector<BlobItemBytesRequest>& requests, |
| 214 std::vector<SharedMemoryHandle>* memory_handles, | 238 std::vector<SharedMemoryHandle>* memory_handles, |
| 215 const std::vector<IPC::PlatformFileForTransit>& file_handles, | 239 const std::vector<IPC::PlatformFileForTransit>& file_handles, |
| 216 std::vector<BlobItemBytesResponse>* out) { | 240 std::vector<BlobItemBytesResponse>* out) { |
| 217 DCHECK(out->empty()); | 241 DCHECK(out->empty()); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 242 BlobItemBytesResponse& response = out->back(); | 266 BlobItemBytesResponse& response = out->back(); |
| 243 ReadStatus status = consolidation->ReadMemory( | 267 ReadStatus status = consolidation->ReadMemory( |
| 244 request.renderer_item_index, request.renderer_item_offset, | 268 request.renderer_item_index, request.renderer_item_offset, |
| 245 request.size, response.allocate_mutable_data(request.size)); | 269 request.size, response.allocate_mutable_data(request.size)); |
| 246 DCHECK(status == ReadStatus::OK) | 270 DCHECK(status == ReadStatus::OK) |
| 247 << "Error reading from consolidated blob: " | 271 << "Error reading from consolidated blob: " |
| 248 << static_cast<int>(status); | 272 << static_cast<int>(status); |
| 249 break; | 273 break; |
| 250 } | 274 } |
| 251 case IPCBlobItemRequestStrategy::SHARED_MEMORY: { | 275 case IPCBlobItemRequestStrategy::SHARED_MEMORY: { |
| 276 LOG(ERROR) << uuid << " got shared memory request on " |
| 277 << base::PlatformThread::GetName(); |
| 252 DCHECK_LT(request.handle_index, memory_handles->size()) | 278 DCHECK_LT(request.handle_index, memory_handles->size()) |
| 253 << "Invalid handle index."; | 279 << "Invalid handle index."; |
| 254 SharedMemory* memory = opened_memory[request.handle_index]; | 280 SharedMemory* memory = opened_memory[request.handle_index]; |
| 255 if (!memory) { | 281 if (!memory) { |
| 256 SharedMemoryHandle& handle = (*memory_handles)[request.handle_index]; | 282 SharedMemoryHandle& handle = (*memory_handles)[request.handle_index]; |
| 257 DCHECK(SharedMemory::IsHandleValid(handle)); | 283 DCHECK(SharedMemory::IsHandleValid(handle)); |
| 258 std::unique_ptr<SharedMemory> shared_memory( | 284 std::unique_ptr<SharedMemory> shared_memory( |
| 259 new SharedMemory(handle, false)); | 285 new SharedMemory(handle, false)); |
| 260 if (!shared_memory->Map(request.size)) | 286 if (!shared_memory->Map(request.size)) |
| 261 return ResponsesStatus::SHARED_MEMORY_MAP_FAILED; | 287 return ResponsesStatus::SHARED_MEMORY_MAP_FAILED; |
| 262 memory = shared_memory.get(); | 288 memory = shared_memory.get(); |
| 263 opened_memory[request.handle_index] = shared_memory.release(); | 289 opened_memory[request.handle_index] = shared_memory.release(); |
| 264 } | 290 } |
| 265 CHECK(memory->memory()) << "Couldn't map memory for blob transfer."; | 291 CHECK(memory->memory()) << "Couldn't map memory for blob transfer."; |
| 266 ReadStatus status = consolidation->ReadMemory( | 292 ReadStatus status = consolidation->ReadMemory( |
| 267 request.renderer_item_index, request.renderer_item_offset, | 293 request.renderer_item_index, request.renderer_item_offset, |
| 268 request.size, | 294 request.size, |
| 269 static_cast<char*>(memory->memory()) + request.handle_offset); | 295 static_cast<char*>(memory->memory()) + request.handle_offset); |
| 270 DCHECK(status == ReadStatus::OK) | 296 CHECK(status == ReadStatus::OK) |
| 271 << "Error reading from consolidated blob: " | 297 << "Error reading from consolidated blob: " |
| 272 << static_cast<int>(status); | 298 << static_cast<int>(status); |
| 273 break; | 299 break; |
| 274 } | 300 } |
| 275 case IPCBlobItemRequestStrategy::FILE: | 301 case IPCBlobItemRequestStrategy::FILE: |
| 276 NOTREACHED() << "TODO(dmurph): Not implemented."; | 302 NOTREACHED() << "TODO(dmurph): Not implemented."; |
| 277 break; | 303 break; |
| 278 case IPCBlobItemRequestStrategy::UNKNOWN: | 304 case IPCBlobItemRequestStrategy::UNKNOWN: |
| 279 NOTREACHED(); | 305 NOTREACHED(); |
| 280 break; | 306 break; |
| 281 } | 307 } |
| 282 } | 308 } |
| 283 return ResponsesStatus::SUCCESS; | 309 return ResponsesStatus::SUCCESS; |
| 284 } | 310 } |
| 285 | 311 |
| 286 void BlobTransportController::ReleaseBlobConsolidation( | 312 void BlobTransportController::ReleaseBlobConsolidation( |
| 287 const std::string& uuid) { | 313 const std::string& uuid) { |
| 288 if (blob_storage_.erase(uuid)) { | 314 if (blob_storage_.erase(uuid)) { |
| 289 main_thread_runner_->PostTask(FROM_HERE, | 315 main_thread_runner_->PostTask(FROM_HERE, |
| 290 base::Bind(&DecChildProcessRefCount)); | 316 base::Bind(&DecChildProcessRefCount)); |
| 291 } | 317 } |
| 292 } | 318 } |
| 293 | 319 |
| 294 } // namespace content | 320 } // namespace content |
| OLD | NEW |