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

Side by Side Diff: content/child/blob_storage/blob_transport_controller.cc

Issue 1414123002: [BlobAsync] Renderer support for blob file writing. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@blob-hookup
Patch Set: Added test & simplified IPC callback[ Created 4 years, 8 months 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 unified diff | Download patch
OLDNEW
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 <utility> 8 #include <utility>
8 #include <vector> 9 #include <vector>
9 10
11 #include "base/bind.h"
12 #include "base/bind_helpers.h"
13 #include "base/callback.h"
14 #include "base/files/file.h"
10 #include "base/lazy_instance.h" 15 #include "base/lazy_instance.h"
16 #include "base/location.h"
17 #include "base/memory/ptr_util.h"
11 #include "base/memory/scoped_vector.h" 18 #include "base/memory/scoped_vector.h"
12 #include "base/memory/shared_memory.h" 19 #include "base/memory/shared_memory.h"
13 #include "base/single_thread_task_runner.h" 20 #include "base/single_thread_task_runner.h"
14 #include "base/stl_util.h" 21 #include "base/stl_util.h"
22 #include "base/task_runner.h"
15 #include "content/child/blob_storage/blob_consolidation.h" 23 #include "content/child/blob_storage/blob_consolidation.h"
16 #include "content/child/child_process.h" 24 #include "content/child/child_process.h"
17 #include "content/child/thread_safe_sender.h" 25 #include "content/child/thread_safe_sender.h"
18 #include "content/common/fileapi/webblob_messages.h" 26 #include "content/common/fileapi/webblob_messages.h"
27 #include "ipc/ipc_message.h"
19 #include "ipc/ipc_sender.h" 28 #include "ipc/ipc_sender.h"
20 #include "storage/common/blob_storage/blob_item_bytes_request.h" 29 #include "storage/common/blob_storage/blob_item_bytes_request.h"
21 #include "storage/common/blob_storage/blob_item_bytes_response.h" 30 #include "storage/common/blob_storage/blob_item_bytes_response.h"
22 #include "storage/common/data_element.h" 31 #include "storage/common/data_element.h"
23 #include "third_party/WebKit/public/platform/Platform.h" 32 #include "third_party/WebKit/public/platform/Platform.h"
24 33
34 using base::File;
25 using base::SharedMemory; 35 using base::SharedMemory;
26 using base::SharedMemoryHandle; 36 using base::SharedMemoryHandle;
27 using storage::BlobItemBytesRequest; 37 using storage::BlobItemBytesRequest;
28 using storage::BlobItemBytesResponse; 38 using storage::BlobItemBytesResponse;
29 using storage::IPCBlobItemRequestStrategy; 39 using storage::IPCBlobItemRequestStrategy;
30 using storage::DataElement; 40 using storage::DataElement;
31 using storage::kBlobStorageIPCThresholdBytes; 41 using storage::kBlobStorageIPCThresholdBytes;
32 42
43 using storage::BlobItemBytesResponse;
44 using storage::BlobItemBytesRequest;
45 using storage::IPCBlobCreationCancelCode;
46
33 namespace content { 47 namespace content {
34 48 using ResponseCallback = base::Callback<void(
35 using storage::IPCBlobCreationCancelCode; 49 const std::vector<storage::BlobItemBytesResponse>& /* responses */)>;
50 using CancelCallback =
51 base::Callback<void(storage::IPCBlobCreationCancelCode /* reason */)>;
36 52
37 using ConsolidatedItem = BlobConsolidation::ConsolidatedItem; 53 using ConsolidatedItem = BlobConsolidation::ConsolidatedItem;
38 using ReadStatus = BlobConsolidation::ReadStatus; 54 using ReadStatus = BlobConsolidation::ReadStatus;
39 55
40 namespace { 56 namespace {
41 static base::LazyInstance<BlobTransportController>::Leaky g_controller = 57 static base::LazyInstance<BlobTransportController>::Leaky g_controller =
42 LAZY_INSTANCE_INITIALIZER; 58 LAZY_INSTANCE_INITIALIZER;
43 59
44 // This keeps the process alive while blobs are being transferred. 60 // This keeps the process alive while blobs are being transferred.
45 // These need to be called on the main thread. 61 // These need to be called on the main thread.
46 void IncChildProcessRefCount() { 62 void IncChildProcessRefCount() {
47 blink::Platform::current()->suddenTerminationChanged(false); 63 blink::Platform::current()->suddenTerminationChanged(false);
48 ChildProcess::current()->AddRefProcess(); 64 ChildProcess::current()->AddRefProcess();
49 } 65 }
50 66
51 void DecChildProcessRefCount() { 67 void DecChildProcessRefCount() {
52 blink::Platform::current()->suddenTerminationChanged(true); 68 blink::Platform::current()->suddenTerminationChanged(true);
53 ChildProcess::current()->ReleaseProcess(); 69 ChildProcess::current()->ReleaseProcess();
54 } 70 }
71
72 bool WriteSingleChunk(base::File* file,
73 size_t total_read,
74 const char* memory,
75 size_t size) {
76 size_t written = 0;
77 size_t max_int = static_cast<size_t>(std::numeric_limits<int>::max());
78 while (written < size) {
79 size_t writing_size = std::min(max_int, size - written);
80 int actual_written =
81 file->WriteAtCurrentPos(memory, static_cast<int>(writing_size));
82 if (actual_written < 0) {
83 LOG(ERROR) << "Error writing to file " << actual_written;
84 return false;
85 }
86 written += writing_size;
87 }
88 return true;
89 }
90
91 bool WriteSingleRequestToDisk(const BlobConsolidation* consolidation,
92 const BlobItemBytesRequest& request,
93 const IPC::PlatformFileForTransit& transit_file) {
94 File file = IPC::PlatformFileForTransitToFile(transit_file);
95 if (!file.IsValid())
96 return false;
97 CHECK_LE(request.handle_offset,
98 static_cast<uint64_t>(std::numeric_limits<int64_t>::max()));
99 int64_t seek_distance =
100 file.Seek(File::FROM_BEGIN, static_cast<int64_t>(request.handle_offset));
101 if (seek_distance < 0) {
102 LOG(ERROR) << "Error seeking " << request.handle_offset << " in file, got "
103 << seek_distance
104 << ". File error: " << File::ErrorToString(file.error_details());
105 return false;
106 }
107 BlobConsolidation::ReadStatus status = consolidation->VisitMemory(
108 request.renderer_item_index, request.renderer_item_offset, request.size,
109 base::Bind(&WriteSingleChunk, &file));
110 // We need to release the file so we don't automatically close the file.
111 file.TakePlatformFile();
112 return status == ReadStatus::OK;
113 }
114
115 void WriteDiskRequests(
116 scoped_refptr<BlobConsolidation> consolidation,
117 std::unique_ptr<std::vector<BlobItemBytesRequest>> requests,
118 const std::vector<IPC::PlatformFileForTransit>& file_handles,
119 const ResponseCallback& response_callback,
120 const CancelCallback& error_callback,
121 scoped_refptr<base::TaskRunner> io_task_runner) {
122 for (const auto& request : *requests) {
123 bool success = WriteSingleRequestToDisk(consolidation.get(), request,
124 file_handles[request.handle_index]);
125 if (!success) {
126 io_task_runner->PostTask(
127 FROM_HERE, base::Bind(error_callback,
128 IPCBlobCreationCancelCode::FILE_WRITE_FAILED));
129 return;
130 }
131 io_task_runner->PostTask(
132 FROM_HERE,
133 base::Bind(response_callback,
134 std::vector<BlobItemBytesResponse>{
135 BlobItemBytesResponse(request.request_number)}));
michaeln 2016/04/21 01:58:41 is BlobItemBytesResponse.time_file_modified not ne
dmurph 2016/04/22 22:37:09 Oh right, I need to add that.
136 }
137 }
55 } // namespace 138 } // namespace
56 139
57 BlobTransportController* BlobTransportController::GetInstance() { 140 BlobTransportController* BlobTransportController::GetInstance() {
58 return g_controller.Pointer(); 141 return g_controller.Pointer();
59 } 142 }
60 143
61 // static 144 // static
62 void BlobTransportController::InitiateBlobTransfer( 145 void BlobTransportController::InitiateBlobTransfer(
63 const std::string& uuid, 146 const std::string& uuid,
64 const std::string& content_type, 147 const std::string& content_type,
65 std::unique_ptr<BlobConsolidation> consolidation, 148 scoped_refptr<BlobConsolidation> consolidation,
66 scoped_refptr<ThreadSafeSender> sender, 149 scoped_refptr<ThreadSafeSender> sender,
67 base::SingleThreadTaskRunner* io_runner, 150 base::SingleThreadTaskRunner* io_runner,
68 scoped_refptr<base::SingleThreadTaskRunner> main_runner) { 151 scoped_refptr<base::SingleThreadTaskRunner> main_runner) {
69 if (main_runner->BelongsToCurrentThread()) { 152 if (main_runner->BelongsToCurrentThread()) {
70 IncChildProcessRefCount(); 153 IncChildProcessRefCount();
71 } else { 154 } else {
72 main_runner->PostTask(FROM_HERE, base::Bind(&IncChildProcessRefCount)); 155 main_runner->PostTask(FROM_HERE, base::Bind(&IncChildProcessRefCount));
73 } 156 }
74 157
75 std::vector<storage::DataElement> descriptions; 158 std::vector<storage::DataElement> descriptions;
76 std::set<std::string> referenced_blobs = consolidation->referenced_blobs(); 159 std::set<std::string> referenced_blobs = consolidation->referenced_blobs();
77 BlobTransportController::GetDescriptions( 160 BlobTransportController::GetDescriptions(
78 consolidation.get(), kBlobStorageIPCThresholdBytes, &descriptions); 161 consolidation.get(), kBlobStorageIPCThresholdBytes, &descriptions);
79 // I post the task first to make sure that we store our consolidation before 162 // I post the task first to make sure that we store our consolidation before
80 // we get a request back from the browser. 163 // we get a request back from the browser.
81 io_runner->PostTask( 164 io_runner->PostTask(
82 FROM_HERE, 165 FROM_HERE,
83 base::Bind(&BlobTransportController::StoreBlobDataForRequests, 166 base::Bind(&BlobTransportController::StoreBlobDataForRequests,
84 base::Unretained(BlobTransportController::GetInstance()), uuid, 167 base::Unretained(BlobTransportController::GetInstance()), uuid,
85 base::Passed(std::move(consolidation)), 168 base::Passed(&consolidation), base::Passed(&main_runner)));
86 base::Passed(std::move(main_runner))));
87 // TODO(dmurph): Merge register and start messages. 169 // TODO(dmurph): Merge register and start messages.
88 sender->Send(new BlobStorageMsg_RegisterBlobUUID(uuid, content_type, "", 170 sender->Send(new BlobStorageMsg_RegisterBlobUUID(uuid, content_type, "",
89 referenced_blobs)); 171 referenced_blobs));
90 sender->Send(new BlobStorageMsg_StartBuildingBlob(uuid, descriptions)); 172 sender->Send(new BlobStorageMsg_StartBuildingBlob(uuid, descriptions));
91 } 173 }
92 174
93 void BlobTransportController::OnMemoryRequest( 175 void BlobTransportController::OnMemoryRequest(
94 const std::string& uuid, 176 const std::string& uuid,
95 const std::vector<storage::BlobItemBytesRequest>& requests, 177 const std::vector<storage::BlobItemBytesRequest>& requests,
96 std::vector<base::SharedMemoryHandle>* memory_handles, 178 std::vector<base::SharedMemoryHandle>* memory_handles,
97 const std::vector<IPC::PlatformFileForTransit>& file_handles, 179 const std::vector<IPC::PlatformFileForTransit>& file_handles,
98 IPC::Sender* sender) { 180 scoped_refptr<base::TaskRunner> io_runner,
181 base::TaskRunner* file_runner,
182 const IPCSender& ipc_sender) {
99 std::vector<storage::BlobItemBytesResponse> responses; 183 std::vector<storage::BlobItemBytesResponse> responses;
100 ResponsesStatus status = 184 ResponsesStatus status = GetResponses(
101 GetResponses(uuid, requests, memory_handles, file_handles, &responses); 185 uuid, requests, memory_handles, file_handles, &responses,
186 std::move(io_runner), file_runner,
187 base::Bind(&BlobTransportController::SendResponses,
188 base::Unretained(this), ipc_sender, uuid),
189 base::Bind(&BlobTransportController::SendCancelAndReleaseConsolidation,
190 base::Unretained(this), ipc_sender, uuid));
102 191
103 switch (status) { 192 switch (status) {
104 case ResponsesStatus::BLOB_NOT_FOUND: 193 case ResponsesStatus::BLOB_NOT_FOUND:
105 // sender->Send(new BlobStorageMsg_CancelBuildingBlob(uuid, 194 // sender->Send(new BlobStorageMsg_CancelBuildingBlob(uuid,
michaeln 2016/04/21 18:51:43 is this needed?
dmurph 2016/04/22 22:37:09 Probably not. Removed.
106 // IPCBlobCreationCancelCode::UNKNOWN)); 195 // IPCBlobCreationCancelCode::UNKNOWN));
107 return; 196 return;
108 case ResponsesStatus::SHARED_MEMORY_MAP_FAILED: 197 case ResponsesStatus::SHARED_MEMORY_MAP_FAILED:
109 // This would happen if the renderer process doesn't have enough memory 198 // 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 199 // 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 200 // memory. If this scenario happens often, we could delay the response
112 // until we have enough memory. For now we just fail. 201 // until we have enough memory. For now we just fail.
113 CHECK(false) << "Unable to map shared memory to send blob " << uuid 202 CHECK(false) << "Unable to map shared memory to send blob " << uuid
114 << "."; 203 << ".";
115 break; 204 break;
116 case ResponsesStatus::SUCCESS: 205 case ResponsesStatus::SUCCESS:
206 case ResponsesStatus::PENDING_IO:
117 break; 207 break;
118 } 208 }
119 209
120 sender->Send(new BlobStorageMsg_MemoryItemResponse(uuid, responses)); 210 if (!responses.empty())
211 ipc_sender.Run(base::WrapUnique(
michaeln 2016/04/21 18:51:43 As coded, the GetResponses helper is responsible f
dmurph 2016/04/22 22:37:09 Ok, done, check it out.
dmurph 2016/04/22 22:37:09 sgtm.
212 new BlobStorageMsg_MemoryItemResponse(uuid, responses)));
121 } 213 }
122 214
123 void BlobTransportController::OnCancel( 215 void BlobTransportController::OnCancel(
124 const std::string& uuid, 216 const std::string& uuid,
125 storage::IPCBlobCreationCancelCode code) { 217 storage::IPCBlobCreationCancelCode code) {
126 DVLOG(1) << "Received blob cancel for blob " << uuid 218 DVLOG(1) << "Received blob cancel for blob " << uuid
127 << " with code: " << static_cast<int>(code); 219 << " with code: " << static_cast<int>(code);
128 ReleaseBlobConsolidation(uuid); 220 ReleaseBlobConsolidation(uuid);
129 } 221 }
130 222
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
191 BlobTransportController::~BlobTransportController() {} 283 BlobTransportController::~BlobTransportController() {}
192 284
193 void BlobTransportController::ClearForTesting() { 285 void BlobTransportController::ClearForTesting() {
194 if (!blob_storage_.empty() && main_thread_runner_) { 286 if (!blob_storage_.empty() && main_thread_runner_) {
195 main_thread_runner_->PostTask(FROM_HERE, 287 main_thread_runner_->PostTask(FROM_HERE,
196 base::Bind(&DecChildProcessRefCount)); 288 base::Bind(&DecChildProcessRefCount));
197 } 289 }
198 blob_storage_.clear(); 290 blob_storage_.clear();
199 } 291 }
200 292
293 void BlobTransportController::SendResponses(
294 const IPCSender& ipc_sender,
295 const std::string& uuid,
296 const std::vector<storage::BlobItemBytesResponse>& responses) {
297 ipc_sender.Run(
298 base::WrapUnique(new BlobStorageMsg_MemoryItemResponse(uuid, responses)));
299 }
300
301 void BlobTransportController::SendCancelAndReleaseConsolidation(
302 const IPCSender& ipc_sender,
303 const std::string& uuid,
304 storage::IPCBlobCreationCancelCode reason) {
305 ipc_sender.Run(
306 base::WrapUnique(new BlobStorageMsg_CancelBuildingBlob(uuid, reason)));
307 ReleaseBlobConsolidation(uuid);
308 }
309
201 void BlobTransportController::StoreBlobDataForRequests( 310 void BlobTransportController::StoreBlobDataForRequests(
202 const std::string& uuid, 311 const std::string& uuid,
203 std::unique_ptr<BlobConsolidation> consolidation, 312 scoped_refptr<BlobConsolidation> consolidation,
204 scoped_refptr<base::SingleThreadTaskRunner> main_runner) { 313 scoped_refptr<base::SingleThreadTaskRunner> main_runner) {
205 if (!main_thread_runner_.get()) { 314 if (!main_thread_runner_.get()) {
206 main_thread_runner_ = std::move(main_runner); 315 main_thread_runner_ = std::move(main_runner);
207 } 316 }
208 blob_storage_[uuid] = std::move(consolidation); 317 blob_storage_[uuid] = std::move(consolidation);
209 } 318 }
210 319
211 BlobTransportController::ResponsesStatus BlobTransportController::GetResponses( 320 BlobTransportController::ResponsesStatus BlobTransportController::GetResponses(
212 const std::string& uuid, 321 const std::string& uuid,
213 const std::vector<BlobItemBytesRequest>& requests, 322 const std::vector<BlobItemBytesRequest>& requests,
214 std::vector<SharedMemoryHandle>* memory_handles, 323 std::vector<SharedMemoryHandle>* memory_handles,
215 const std::vector<IPC::PlatformFileForTransit>& file_handles, 324 const std::vector<IPC::PlatformFileForTransit>& file_handles,
216 std::vector<BlobItemBytesResponse>* out) { 325 std::vector<BlobItemBytesResponse>* out,
326 scoped_refptr<base::TaskRunner> io_runner,
327 base::TaskRunner* file_runner,
328 const ResponseCallback& response_callback,
329 const CancelCallback& error_callback) {
217 DCHECK(out->empty()); 330 DCHECK(out->empty());
218 auto it = blob_storage_.find(uuid); 331 auto it = blob_storage_.find(uuid);
219 if (it == blob_storage_.end()) 332 if (it == blob_storage_.end())
220 return ResponsesStatus::BLOB_NOT_FOUND; 333 return ResponsesStatus::BLOB_NOT_FOUND;
221 334
222 BlobConsolidation* consolidation = it->second.get(); 335 BlobConsolidation* consolidation = it->second.get();
223 const auto& consolidated_items = consolidation->consolidated_items(); 336 const auto& consolidated_items = consolidation->consolidated_items();
224 337
338 scoped_ptr<std::vector<BlobItemBytesRequest>> file_requests(
339 new std::vector<BlobItemBytesRequest>());
340
225 // Since we can be writing to the same shared memory handle from multiple 341 // Since we can be writing to the same shared memory handle from multiple
226 // requests, we keep them in a vector and lazily create them. 342 // requests, we keep them in a vector and lazily create them.
227 ScopedVector<SharedMemory> opened_memory; 343 ScopedVector<SharedMemory> opened_memory;
228 opened_memory.resize(memory_handles->size()); 344 opened_memory.resize(memory_handles->size());
229 for (const BlobItemBytesRequest& request : requests) { 345 for (const BlobItemBytesRequest& request : requests) {
230 DCHECK_LT(request.renderer_item_index, consolidated_items.size()) 346 DCHECK_LT(request.renderer_item_index, consolidated_items.size())
231 << "Invalid item index"; 347 << "Invalid item index";
232 348
233 const ConsolidatedItem& item = 349 const ConsolidatedItem& item =
234 consolidated_items[request.renderer_item_index]; 350 consolidated_items[request.renderer_item_index];
235 DCHECK_LE(request.renderer_item_offset + request.size, item.length) 351 DCHECK_LE(request.renderer_item_offset + request.size, item.length)
236 << "Invalid data range"; 352 << "Invalid data range";
237 DCHECK_EQ(item.type, DataElement::TYPE_BYTES) << "Invalid element type"; 353 DCHECK_EQ(item.type, DataElement::TYPE_BYTES) << "Invalid element type";
238 354
239 out->push_back(BlobItemBytesResponse(request.request_number));
240 switch (request.transport_strategy) { 355 switch (request.transport_strategy) {
241 case IPCBlobItemRequestStrategy::IPC: { 356 case IPCBlobItemRequestStrategy::IPC: {
357 out->push_back(BlobItemBytesResponse(request.request_number));
242 BlobItemBytesResponse& response = out->back(); 358 BlobItemBytesResponse& response = out->back();
243 ReadStatus status = consolidation->ReadMemory( 359 ReadStatus status = consolidation->ReadMemory(
244 request.renderer_item_index, request.renderer_item_offset, 360 request.renderer_item_index, request.renderer_item_offset,
245 request.size, response.allocate_mutable_data(request.size)); 361 request.size, response.allocate_mutable_data(request.size));
246 DCHECK(status == ReadStatus::OK) 362 DCHECK(status == ReadStatus::OK)
247 << "Error reading from consolidated blob: " 363 << "Error reading from consolidated blob: "
248 << static_cast<int>(status); 364 << static_cast<int>(status);
249 break; 365 break;
250 } 366 }
251 case IPCBlobItemRequestStrategy::SHARED_MEMORY: { 367 case IPCBlobItemRequestStrategy::SHARED_MEMORY: {
368 out->push_back(BlobItemBytesResponse(request.request_number));
252 DCHECK_LT(request.handle_index, memory_handles->size()) 369 DCHECK_LT(request.handle_index, memory_handles->size())
253 << "Invalid handle index."; 370 << "Invalid handle index.";
254 SharedMemory* memory = opened_memory[request.handle_index]; 371 SharedMemory* memory = opened_memory[request.handle_index];
255 if (!memory) { 372 if (!memory) {
256 SharedMemoryHandle& handle = (*memory_handles)[request.handle_index]; 373 SharedMemoryHandle& handle = (*memory_handles)[request.handle_index];
257 DCHECK(SharedMemory::IsHandleValid(handle)); 374 DCHECK(SharedMemory::IsHandleValid(handle));
258 std::unique_ptr<SharedMemory> shared_memory( 375 std::unique_ptr<SharedMemory> shared_memory(
259 new SharedMemory(handle, false)); 376 new SharedMemory(handle, false));
260 if (!shared_memory->Map(request.size)) 377 if (!shared_memory->Map(request.size))
261 return ResponsesStatus::SHARED_MEMORY_MAP_FAILED; 378 return ResponsesStatus::SHARED_MEMORY_MAP_FAILED;
262 memory = shared_memory.get(); 379 memory = shared_memory.get();
263 opened_memory[request.handle_index] = shared_memory.release(); 380 opened_memory[request.handle_index] = shared_memory.release();
264 } 381 }
265 CHECK(memory->memory()) << "Couldn't map memory for blob transfer."; 382 CHECK(memory->memory()) << "Couldn't map memory for blob transfer.";
266 ReadStatus status = consolidation->ReadMemory( 383 ReadStatus status = consolidation->ReadMemory(
267 request.renderer_item_index, request.renderer_item_offset, 384 request.renderer_item_index, request.renderer_item_offset,
268 request.size, 385 request.size,
269 static_cast<char*>(memory->memory()) + request.handle_offset); 386 static_cast<char*>(memory->memory()) + request.handle_offset);
270 DCHECK(status == ReadStatus::OK) 387 DCHECK(status == ReadStatus::OK)
271 << "Error reading from consolidated blob: " 388 << "Error reading from consolidated blob: "
272 << static_cast<int>(status); 389 << static_cast<int>(status);
273 break; 390 break;
274 } 391 }
275 case IPCBlobItemRequestStrategy::FILE: 392 case IPCBlobItemRequestStrategy::FILE:
276 NOTREACHED() << "TODO(dmurph): Not implemented."; 393 DCHECK_LT(request.handle_index, file_handles.size())
394 << "Invalid handle index.";
395 file_requests->push_back(request);
277 break; 396 break;
278 case IPCBlobItemRequestStrategy::UNKNOWN: 397 case IPCBlobItemRequestStrategy::UNKNOWN:
279 NOTREACHED(); 398 NOTREACHED();
280 break; 399 break;
281 } 400 }
282 } 401 }
283 return ResponsesStatus::SUCCESS; 402 if (file_requests->empty()) {
403 return ResponsesStatus::SUCCESS;
404 }
405 file_runner->PostTask(
406 FROM_HERE,
407 base::Bind(&WriteDiskRequests, consolidation,
408 base::Passed(&file_requests), file_handles, response_callback,
409 error_callback, base::Passed(&io_runner)));
michaeln 2016/04/21 01:58:41 Passing in a reply task runner seems odd. I'd expe
dmurph 2016/04/22 22:37:09 Done.
410 return ResponsesStatus::PENDING_IO;
284 } 411 }
285 412
286 void BlobTransportController::ReleaseBlobConsolidation( 413 void BlobTransportController::ReleaseBlobConsolidation(
287 const std::string& uuid) { 414 const std::string& uuid) {
288 if (blob_storage_.erase(uuid)) { 415 if (blob_storage_.erase(uuid)) {
289 main_thread_runner_->PostTask(FROM_HERE, 416 main_thread_runner_->PostTask(FROM_HERE,
290 base::Bind(&DecChildProcessRefCount)); 417 base::Bind(&DecChildProcessRefCount));
291 } 418 }
292 } 419 }
293 420
294 } // namespace content 421 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698