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

Side by Side Diff: storage/browser/blob/blob_async_builder_host.cc

Issue 1528233004: [Blob] Blob paging to disk patch. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@blob-disk1
Patch Set: Created 5 years 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 "storage/browser/blob/blob_async_builder_host.h" 5 #include "storage/browser/blob/blob_async_builder_host.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/bind.h"
10 #include "base/files/file.h"
9 #include "base/memory/shared_memory.h" 11 #include "base/memory/shared_memory.h"
12 #include "storage/browser/blob/blob_memory_controller.h"
13 #include "storage/browser/blob/shareable_file_reference.h"
10 14
11 namespace storage { 15 namespace storage {
12 16 using BlobTrasportationMemoryStrategyResult =
17 BlobMemoryController::BlobTrasportationMemoryStrategyResult;
18 using FileCreationInfo = BlobMemoryController::FileCreationInfo;
13 using MemoryItemRequest = BlobAsyncTransportStrategy::RendererMemoryItemRequest; 19 using MemoryItemRequest = BlobAsyncTransportStrategy::RendererMemoryItemRequest;
14 20
15 BlobAsyncBuilderHost::BlobBuildingState::BlobBuildingState() 21 BlobAsyncBuilderHost::BlobBuildingState::BlobBuildingState(
16 : next_request(0), 22 const std::string& uuid)
17 num_fulfilled_requests(0), 23 : builder(uuid) {}
18 num_shared_memory_requests(0),
19 current_shared_memory_handle_index(0) {}
20 24
21 BlobAsyncBuilderHost::BlobBuildingState::~BlobBuildingState() {} 25 BlobAsyncBuilderHost::BlobBuildingState::~BlobBuildingState() {}
22 26
23 BlobAsyncBuilderHost::BlobAsyncBuilderHost() {} 27 BlobAsyncBuilderHost::BlobAsyncBuilderHost() : weak_ptr_factory_(this) {}
24 28
25 BlobAsyncBuilderHost::~BlobAsyncBuilderHost() {} 29 BlobAsyncBuilderHost::~BlobAsyncBuilderHost() {}
26 30
27 bool BlobAsyncBuilderHost::StartBuildingBlob( 31 bool BlobAsyncBuilderHost::StartBuildingBlob(
28 const std::string& uuid, 32 const std::string& uuid,
29 const std::string& type, 33 const std::string& type,
30 const std::vector<DataElement>& descriptions, 34 const std::vector<DataElement>& descriptions,
31 size_t memory_available, 35 storage::BlobMemoryController* memory_controller,
32 const base::Callback<void(const std::vector<storage::BlobItemBytesRequest>&, 36 const base::Callback<void(const std::vector<storage::BlobItemBytesRequest>&,
33 const std::vector<base::SharedMemoryHandle>&, 37 const std::vector<base::SharedMemoryHandle>&,
34 const std::vector<uint64_t>&)>& request_memory, 38 const std::vector<uint64_t>&)>& request_memory,
35 const base::Callback<void(const BlobDataBuilder&)>& done, 39 const base::Callback<void(const BlobDataBuilder&)>& done,
36 const base::Callback<void(IPCBlobCreationCancelCode)>& cancel) { 40 const base::Callback<void(IPCBlobCreationCancelCode)>& cancel) {
41 DCHECK(memory_controller);
37 if (async_blob_map_.find(uuid) != async_blob_map_.end()) 42 if (async_blob_map_.find(uuid) != async_blob_map_.end())
38 return false; 43 return false;
39 if (BlobAsyncTransportStrategy::ShouldBeShortcut(descriptions, 44
40 memory_available)) { 45 uint64_t total_memory_size_bytes;
41 // We have enough memory, and all the data is here, so we use the shortcut 46 BlobMemoryController::BlobTrasportationMemoryStrategyResult strategy;
42 // method and populate the old way. 47 if (!memory_controller->DecideBlobTransportationMemoryStrategy(
43 BlobDataBuilder builder(uuid); 48 descriptions, &total_memory_size_bytes, &strategy)) {
44 builder.set_content_type(type); 49 return false;
45 for (const DataElement& element : descriptions) {
46 builder.AppendIPCDataElement(element);
47 }
48 done.Run(builder);
49 return true;
50 } 50 }
51 51
52 scoped_ptr<BlobBuildingState> state(new BlobBuildingState()); 52 switch (strategy) {
53 case BlobTrasportationMemoryStrategyResult::TOO_LARGE:
54 cancel.Run(IPCBlobCreationCancelCode::OUT_OF_MEMORY);
55 return true;
56 case BlobTrasportationMemoryStrategyResult::NONE_NEEDED:
57 case BlobTrasportationMemoryStrategyResult::SHORTCUT: {
58 // We either have enough memory & the data is populated, or we don't have
59 // any data to populate.
60 BlobDataBuilder builder(uuid);
61 builder.set_content_type(type);
62 for (const DataElement& element : descriptions) {
63 builder.AppendIPCDataElement(element);
64 }
65 done.Run(builder);
66 return true;
67 }
68 case BlobTrasportationMemoryStrategyResult::IPC:
69 case BlobTrasportationMemoryStrategyResult::SHARED_MEMORY:
70 case BlobTrasportationMemoryStrategyResult::FILE:
71 // Handle these in next switch, as we need to create our state first.
72 break;
73 }
74
75 scoped_ptr<BlobBuildingState> state(new BlobBuildingState(uuid));
53 BlobBuildingState* state_ptr = state.get(); 76 BlobBuildingState* state_ptr = state.get();
54 async_blob_map_[uuid] = std::move(state); 77 async_blob_map_[uuid] = std::move(state);
55 state_ptr->type = type; 78 state_ptr->type = type;
56 state_ptr->request_memory_callback = request_memory; 79 state_ptr->request_memory_callback = request_memory;
57 state_ptr->done_callback = done; 80 state_ptr->done_callback = done;
58 state_ptr->cancel_callback = cancel; 81 state_ptr->cancel_callback = cancel;
59 82
60 // We are currently only operating in 'no disk' mode. This will change in 83 switch (strategy) {
61 // future patches to enable disk storage. 84 case BlobTrasportationMemoryStrategyResult::IPC:
62 // Since we don't have a disk yet, we put 0 for disk_space_left. 85 state_ptr->transport_strategy.InitializeForIPCTransportation(
63 state_ptr->transport_strategy.Initialize( 86 max_ipc_memory_size_, uuid, total_memory_size_bytes, descriptions,
64 max_ipc_memory_size_, max_shared_memory_size_, max_file_size_, 87 &(state_ptr->builder));
65 0 /* disk_space_left */, memory_available, uuid, descriptions); 88 break;
89 case BlobTrasportationMemoryStrategyResult::SHARED_MEMORY:
90 state_ptr->transport_strategy.InitializeForSharedMemoryRequests(
91 max_shared_memory_size_, uuid, total_memory_size_bytes, descriptions,
92 &(state_ptr->builder));
93 break;
94 case BlobTrasportationMemoryStrategyResult::FILE:
95 state_ptr->transport_strategy.InitializeForFileRequests(
96 max_file_size_, uuid, total_memory_size_bytes, descriptions,
97 &(state_ptr->builder));
98 break;
99 case BlobTrasportationMemoryStrategyResult::TOO_LARGE:
100 case BlobTrasportationMemoryStrategyResult::NONE_NEEDED:
101 case BlobTrasportationMemoryStrategyResult::SHORTCUT:
102 // These cases should be handled above.
103 CHECK(false);
104 break;
105 }
106 state_ptr->request_received.resize(
107 state_ptr->transport_strategy.requests().size(), false);
66 108
67 switch (state_ptr->transport_strategy.error()) { 109 memory_controller->NotifyWhenBlobCanBeRequested(
68 case BlobAsyncTransportStrategy::ERROR_TOO_LARGE: 110 total_memory_size_bytes,
69 // Cancel cleanly, we're out of memory. 111 base::Bind(&BlobAsyncBuilderHost::StartRequestingBlobAndCreateFileHandles,
70 CancelAndCleanup(uuid, IPCBlobCreationCancelCode::OUT_OF_MEMORY); 112 weak_ptr_factory_.GetWeakPtr(), uuid,
71 return true; 113 memory_controller->AsWeakPtr()));
72 case BlobAsyncTransportStrategy::ERROR_INVALID_PARAMS: 114 return true;
73 // Bad IPC, so we ignore and clean up.
74 VLOG(1) << "Error initializing transport strategy: "
75 << state_ptr->transport_strategy.error();
76 async_blob_map_.erase(async_blob_map_.find(uuid));
77 return false;
78 case BlobAsyncTransportStrategy::ERROR_NONE:
79 ContinueBlobMemoryRequests(uuid);
80 return true;
81 }
82 return false;
83 } 115 }
84 116
85 bool BlobAsyncBuilderHost::OnMemoryResponses( 117 bool BlobAsyncBuilderHost::OnMemoryResponses(
86 const std::string& uuid, 118 const std::string& uuid,
87 const std::vector<BlobItemBytesResponse>& responses) { 119 const std::vector<BlobItemBytesResponse>& responses) {
88 if (responses.empty()) { 120 if (responses.empty()) {
89 return false; 121 return false;
90 } 122 }
91 AsyncBlobMap::const_iterator state_it = async_blob_map_.find(uuid); 123 AsyncBlobMap::const_iterator state_it = async_blob_map_.find(uuid);
92 if (state_it == async_blob_map_.end()) { 124 if (state_it == async_blob_map_.end()) {
93 // There's a possibility that we had a shared memory error, and there were 125 // There's a possibility that we had a shared memory error, and there were
94 // still responses in flight. So we don't fail here, we just ignore. 126 // still responses in flight. So we don't fail here, we just ignore.
95 DVLOG(1) << "Could not find blob " << uuid; 127 DVLOG(1) << "Could not find blob " << uuid;
96 return true; 128 return true;
97 } 129 }
98 BlobAsyncBuilderHost::BlobBuildingState* state = state_it->second.get(); 130 BlobAsyncBuilderHost::BlobBuildingState* state = state_it->second.get();
99 BlobAsyncTransportStrategy& strategy = state->transport_strategy; 131 BlobAsyncTransportStrategy& strategy = state->transport_strategy;
100 bool invalid_ipc = false; 132 bool invalid_ipc = false;
101 bool memory_error = false; 133 bool memory_error = false;
102 const auto& requests = strategy.requests(); 134 const auto& requests = strategy.requests();
103 for (const BlobItemBytesResponse& response : responses) { 135 for (const BlobItemBytesResponse& response : responses) {
104 if (response.request_number >= requests.size()) { 136 if (response.request_number >= requests.size()) {
105 // Bad IPC, so we delete our record and ignore. 137 // Bad IPC, so we delete our record and ignore.
106 DVLOG(1) << "Invalid request number " << response.request_number; 138 DVLOG(1) << "Invalid request number " << response.request_number;
107 async_blob_map_.erase(state_it); 139 async_blob_map_.erase(state_it);
108 return false; 140 return false;
109 } 141 }
110 const MemoryItemRequest& request = requests[response.request_number]; 142 const MemoryItemRequest& request = requests[response.request_number];
111 if (request.received) { 143 if (state->request_received[response.request_number]) {
112 // Bad IPC, so we delete our record. 144 // Bad IPC, so we delete our record.
113 DVLOG(1) << "Already received response for that request."; 145 DVLOG(1) << "Already received response for that request.";
114 async_blob_map_.erase(state_it); 146 async_blob_map_.erase(state_it);
115 return false; 147 return false;
116 } 148 }
117 strategy.MarkRequestAsReceived(response.request_number); 149 state->request_received[response.request_number] = true;
118 switch (request.message.transport_strategy) { 150 switch (request.message.transport_strategy) {
119 case IPCBlobItemRequestStrategy::IPC: 151 case IPCBlobItemRequestStrategy::IPC:
120 if (response.inline_data.size() < request.message.size) { 152 if (response.inline_data.size() < request.message.size) {
121 DVLOG(1) << "Invalid data size " << response.inline_data.size() 153 DVLOG(1) << "Invalid data size " << response.inline_data.size()
122 << " vs requested size of " << request.message.size; 154 << " vs requested size of " << request.message.size;
123 invalid_ipc = true; 155 invalid_ipc = true;
124 break; 156 break;
125 } 157 }
126 invalid_ipc = !strategy.blob_builder()->PopulateFutureData( 158 invalid_ipc = !state->builder.PopulateFutureData(
127 request.browser_item_index, &response.inline_data[0], 159 request.browser_item_index, &response.inline_data[0],
128 request.browser_item_offset, request.message.size); 160 request.browser_item_offset, request.message.size);
129 break; 161 break;
130 case IPCBlobItemRequestStrategy::SHARED_MEMORY: 162 case IPCBlobItemRequestStrategy::SHARED_MEMORY:
131 if (state->num_shared_memory_requests == 0) { 163 if (state->num_shared_memory_requests == 0) {
132 DVLOG(1) << "Received too many responses for shared memory."; 164 DVLOG(1) << "Received too many responses for shared memory.";
133 invalid_ipc = true; 165 invalid_ipc = true;
134 break; 166 break;
135 } 167 }
136 state->num_shared_memory_requests--; 168 state->num_shared_memory_requests--;
137 if (!state->shared_memory_block->memory()) { 169 if (!state->shared_memory_block->memory()) {
138 // We just map the whole block, as we'll probably be accessing the 170 // We just map the whole block, as we'll probably be accessing the
139 // whole thing in this group of responses. Another option is to use 171 // whole thing in this group of responses. Another option is to use
140 // MapAt, remove the mapped boolean, and then exclude the 172 // MapAt, remove the mapped boolean, and then exclude the
141 // handle_offset below. 173 // handle_offset below.
142 size_t handle_size = strategy.handle_sizes().at( 174 size_t handle_size = strategy.shared_memory_handle_sizes().at(
143 state->current_shared_memory_handle_index); 175 state->current_shared_memory_handle_index);
144 if (!state->shared_memory_block->Map(handle_size)) { 176 if (!state->shared_memory_block->Map(handle_size)) {
145 DVLOG(1) << "Unable to map memory to size " << handle_size; 177 DVLOG(1) << "Unable to map memory to size " << handle_size;
146 memory_error = true; 178 memory_error = true;
147 break; 179 break;
148 } 180 }
149 } 181 }
150 182
151 invalid_ipc = !strategy.blob_builder()->PopulateFutureData( 183 invalid_ipc = !state->builder.PopulateFutureData(
152 request.browser_item_index, 184 request.browser_item_index,
153 static_cast<const char*>(state->shared_memory_block->memory()) + 185 static_cast<const char*>(state->shared_memory_block->memory()) +
154 request.message.handle_offset, 186 request.message.handle_offset,
155 request.browser_item_offset, request.message.size); 187 request.browser_item_offset, request.message.size);
156 break; 188 break;
157 case IPCBlobItemRequestStrategy::FILE: 189 case IPCBlobItemRequestStrategy::FILE: {
190 const FileCreationInfo& file_info =
191 state->files_created[request.message.handle_offset];
192 if (!file_info.file_reference.get() ||
193 file_info.error != base::File::FILE_OK) {
194 invalid_ipc = true;
195 break;
196 }
197 invalid_ipc = !state->builder.PopulateFutureFile(
198 request.browser_item_index, file_info.file_reference,
199 response.time_modified);
200 }
158 case IPCBlobItemRequestStrategy::UNKNOWN: 201 case IPCBlobItemRequestStrategy::UNKNOWN:
159 DVLOG(1) << "Not implemented."; 202 DVLOG(1) << "Not implemented.";
160 invalid_ipc = true; 203 invalid_ipc = true;
161 break; 204 break;
162 } 205 }
163 if (invalid_ipc) { 206 if (invalid_ipc) {
164 // Bad IPC, so we delete our record and return false. 207 // Bad IPC, so we delete our record and return false.
165 async_blob_map_.erase(state_it); 208 async_blob_map_.erase(state_it);
166 return false; 209 return false;
167 } 210 }
168 if (memory_error) { 211 if (memory_error) {
169 DVLOG(1) << "Shared memory error."; 212 DVLOG(1) << "Shared memory error.";
170 CancelAndCleanup(uuid, IPCBlobCreationCancelCode::OUT_OF_MEMORY); 213 CancelAndCleanup(uuid, IPCBlobCreationCancelCode::OUT_OF_MEMORY);
171 return true; 214 return true;
172 } 215 }
173 state->num_fulfilled_requests++; 216 state->num_fulfilled_requests++;
174 } 217 }
175 ContinueBlobMemoryRequests(uuid); 218 ContinueBlobMemoryRequests(uuid);
176 return true; 219 return true;
177 } 220 }
178 221
179 void BlobAsyncBuilderHost::StopBuildingBlob(const std::string& uuid) { 222 void BlobAsyncBuilderHost::StopBuildingBlob(const std::string& uuid) {
180 async_blob_map_.erase(async_blob_map_.find(uuid)); 223 async_blob_map_.erase(async_blob_map_.find(uuid));
181 } 224 }
182 225
226 void BlobAsyncBuilderHost::StartRequestingBlobAndCreateFileHandles(
227 const std::string& uuid,
228 base::WeakPtr<BlobMemoryController> memory_controller,
229 bool can_request) {
230 if (!can_request) {
231 CancelAndCleanup(uuid, IPCBlobCreationCancelCode::UNKNOWN);
232 return;
233 }
234 BlobAsyncBuilderHost::BlobBuildingState* state = async_blob_map_[uuid].get();
235 DCHECK(state);
236 DCHECK(!state->requests_started);
237 if (!memory_controller.get()) {
238 async_blob_map_.erase(uuid);
239 return;
240 }
241
242 size_t file_handles_count =
243 state->transport_strategy.file_handle_sizes().size();
244 if (file_handles_count != 0) {
245 state->files_created.resize(file_handles_count, FileCreationInfo());
246 // Create file handles.
247 for (int i = 0; i < file_handles_count; ++i) {
248 size_t file_handle_size =
249 state->transport_strategy.file_handle_sizes()[i];
250 memory_controller->CreateTemporaryFileForRenderer(
251 file_handle_size,
252 base::Bind(&BlobAsyncBuilderHost::FileCreatedForBlob,
253 weak_ptr_factory_.GetWeakPtr(), uuid, i));
254 }
255 }
256
257 ContinueBlobMemoryRequests(uuid);
258 }
259
183 void BlobAsyncBuilderHost::ContinueBlobMemoryRequests(const std::string& uuid) { 260 void BlobAsyncBuilderHost::ContinueBlobMemoryRequests(const std::string& uuid) {
184 AsyncBlobMap::const_iterator state_it = async_blob_map_.find(uuid); 261 BlobAsyncBuilderHost::BlobBuildingState* state = async_blob_map_[uuid].get();
185 DCHECK(state_it != async_blob_map_.end()); 262 DCHECK(state);
186 BlobAsyncBuilderHost::BlobBuildingState* state = state_it->second.get(); 263 DCHECK(state->requests_started);
187 264
188 const std::vector<MemoryItemRequest>& requests = 265 const std::vector<MemoryItemRequest>& requests =
189 state->transport_strategy.requests(); 266 state->transport_strategy.requests();
190 BlobAsyncTransportStrategy& strategy = state->transport_strategy; 267 BlobAsyncTransportStrategy& strategy = state->transport_strategy;
191 size_t num_requests = requests.size(); 268 size_t num_requests = requests.size();
192 if (state->num_fulfilled_requests == num_requests) { 269 if (state->num_fulfilled_requests == num_requests) {
193 DoneAndCleanup(uuid); 270 DoneAndCleanup(uuid);
194 return; 271 return;
195 } 272 }
196 DCHECK_LT(state->num_fulfilled_requests, num_requests); 273 DCHECK_LT(state->num_fulfilled_requests, num_requests);
197 if (state->next_request == num_requests) { 274 if (state->next_request == num_requests) {
198 // We are still waiting on other requests to come back. 275 // We are still waiting on other requests to come back.
199 return; 276 return;
200 } 277 }
201 278
202 std::vector<BlobItemBytesRequest> byte_requests; 279 std::vector<BlobItemBytesRequest> byte_requests;
203 std::vector<base::SharedMemoryHandle> shared_memory; 280 std::vector<base::SharedMemoryHandle> shared_memory;
204 std::vector<uint64_t> files;
205 281
206 for (; state->next_request < num_requests; ++state->next_request) { 282 for (; state->next_request < num_requests; ++state->next_request) {
207 const MemoryItemRequest& request = requests[state->next_request]; 283 const MemoryItemRequest& request = requests[state->next_request];
208 284
209 bool stop_accumulating = false; 285 bool stop_accumulating = false;
210 bool using_shared_memory_handle = state->num_shared_memory_requests > 0; 286 bool using_shared_memory_handle = state->num_shared_memory_requests > 0;
211 switch (request.message.transport_strategy) { 287 switch (request.message.transport_strategy) {
212 case IPCBlobItemRequestStrategy::IPC: 288 case IPCBlobItemRequestStrategy::IPC:
213 byte_requests.push_back(request.message); 289 byte_requests.push_back(request.message);
214 break; 290 break;
215 case IPCBlobItemRequestStrategy::SHARED_MEMORY: 291 case IPCBlobItemRequestStrategy::SHARED_MEMORY:
216 if (using_shared_memory_handle && 292 if (using_shared_memory_handle &&
217 state->current_shared_memory_handle_index != 293 state->current_shared_memory_handle_index !=
218 request.message.handle_index) { 294 request.message.handle_index) {
219 // We only want one shared memory per requesting blob. 295 // We only want one shared memory per requesting blob.
220 stop_accumulating = true; 296 stop_accumulating = true;
221 break; 297 break;
222 } 298 }
223 using_shared_memory_handle = true; 299 using_shared_memory_handle = true;
224 state->current_shared_memory_handle_index = 300 state->current_shared_memory_handle_index =
225 request.message.handle_index; 301 request.message.handle_index;
226 state->num_shared_memory_requests++; 302 state->num_shared_memory_requests++;
227 303
228 if (!state->shared_memory_block) { 304 if (!state->shared_memory_block) {
229 state->shared_memory_block.reset(new base::SharedMemory()); 305 state->shared_memory_block.reset(new base::SharedMemory());
230 size_t size = strategy.handle_sizes()[request.message.handle_index]; 306 size_t size =
307 strategy
308 .shared_memory_handle_sizes()[request.message.handle_index];
231 if (!state->shared_memory_block->CreateAnonymous(size)) { 309 if (!state->shared_memory_block->CreateAnonymous(size)) {
232 DVLOG(1) << "Unable to allocate shared memory for blob transfer."; 310 DVLOG(1) << "Unable to allocate shared memory for blob transfer.";
233 CancelAndCleanup(uuid, IPCBlobCreationCancelCode::OUT_OF_MEMORY); 311 CancelAndCleanup(uuid, IPCBlobCreationCancelCode::OUT_OF_MEMORY);
234 return; 312 return;
235 } 313 }
236 } 314 }
237 shared_memory.push_back(state->shared_memory_block->handle()); 315 shared_memory.push_back(state->shared_memory_block->handle());
238 byte_requests.push_back(request.message); 316 byte_requests.push_back(request.message);
239 // Since we are only using one handle at a time, transform our handle 317 // Since we are only using one handle at a time, transform our handle
240 // index correctly back to 0. 318 // index correctly back to 0.
241 byte_requests.back().handle_index = 0; 319 byte_requests.back().handle_index = 0;
242 break; 320 break;
243 case IPCBlobItemRequestStrategy::FILE: 321 case IPCBlobItemRequestStrategy::FILE:
322 // We ignore file requests because we send them in our
323 // FileCreatedForBlob callback after the file is created.
324 break;
244 case IPCBlobItemRequestStrategy::UNKNOWN: 325 case IPCBlobItemRequestStrategy::UNKNOWN:
245 NOTREACHED() << "Not implemented yet."; 326 NOTREACHED() << "Not implemented yet.";
246 break; 327 break;
247 } 328 }
248 if (stop_accumulating) { 329 if (stop_accumulating) {
249 break; 330 break;
250 } 331 }
251 } 332 }
252 333
253 DCHECK(!requests.empty()); 334 if (byte_requests.empty()) {
335 return;
336 }
254 337
255 state->request_memory_callback.Run(byte_requests, shared_memory, files); 338 state->request_memory_callback.Run(
339 byte_requests, shared_memory,
340 std::vector<scoped_refptr<ShareableFileReference>>());
341 }
342
343 void BlobAsyncBuilderHost::FileCreatedForBlob(
344 const std::string& uuid,
345 size_t handle_index,
346 const BlobMemoryController::FileCreationInfo& creation_info) {
347 auto it = async_blob_map_.find(uuid);
348 if (it == async_blob_map_.end()) {
349 // We must have killed the blob. Returning should kill the file, as it is
350 // managed by the ShareableFileReference in the creation info.
351 return;
352 }
353 BlobAsyncBuilderHost::BlobBuildingState* state = it->second.get();
354 DCHECK(state);
355 DCHECK(state->requests_started);
356 if (creation_info.error != base::File::FILE_OK) {
357 CancelAndCleanup(uuid, IPCBlobCreationCancelCode::UNKNOWN);
358 return;
359 }
360 state->files_created[handle_index] = creation_info;
361
362 std::vector<BlobItemBytesRequest> byte_requests;
363 std::vector<scoped_refptr<ShareableFileReference>> file_handles = {
364 creation_info.file_reference};
365
366 // We send all requests that use this handle.
367 for (const auto& request : state->transport_strategy.requests()) {
368 const BlobItemBytesRequest& message = request.message;
369 if (message.transport_strategy != IPCBlobItemRequestStrategy::FILE ||
370 message.handle_index != handle_index) {
371 continue;
372 }
373 byte_requests.push_back(request.message);
374 byte_requests.back().handle_index = 0;
375 }
376
377 state->request_memory_callback.Run(
378 byte_requests, std::vector<base::SharedMemoryHandle>(), file_handles);
256 } 379 }
257 380
258 void BlobAsyncBuilderHost::CancelAndCleanup(const std::string& uuid, 381 void BlobAsyncBuilderHost::CancelAndCleanup(const std::string& uuid,
259 IPCBlobCreationCancelCode code) { 382 IPCBlobCreationCancelCode code) {
260 scoped_ptr<BlobBuildingState> state = std::move(async_blob_map_[uuid]); 383 scoped_ptr<BlobBuildingState> state = std::move(async_blob_map_[uuid]);
261 async_blob_map_.erase(uuid); 384 async_blob_map_.erase(uuid);
262 state->cancel_callback.Run(code); 385 state->cancel_callback.Run(code);
263 } 386 }
264 387
265 void BlobAsyncBuilderHost::DoneAndCleanup(const std::string& uuid) { 388 void BlobAsyncBuilderHost::DoneAndCleanup(const std::string& uuid) {
266 scoped_ptr<BlobBuildingState> state = std::move(async_blob_map_[uuid]); 389 scoped_ptr<BlobBuildingState> state = std::move(async_blob_map_[uuid]);
267 async_blob_map_.erase(uuid); 390 async_blob_map_.erase(uuid);
268 BlobDataBuilder* builder = state->transport_strategy.blob_builder(); 391 state->builder.set_content_type(state->type);
269 builder->set_content_type(state->type); 392 state->done_callback.Run(state->builder);
270 state->done_callback.Run(*builder);
271 } 393 }
272 394
273 } // namespace storage 395 } // namespace storage
OLDNEW
« no previous file with comments | « storage/browser/blob/blob_async_builder_host.h ('k') | storage/browser/blob/blob_async_transport_strategy.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698