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

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

Issue 1098853003: [BlobAsync] Patch 4: Browser Classes & Logic. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: maybe fixed windows 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "storage/browser/blob/blob_async_builder_host.h"
6
7 #include <utility>
8
9 #include "base/memory/shared_memory.h"
10
11 namespace storage {
12
13 using MemoryItemRequest = BlobAsyncTransportStrategy::RendererMemoryItemRequest;
14
15 BlobAsyncBuilderHost::BlobBuildingState::BlobBuildingState()
16 : next_request(0),
17 num_fulfilled_requests(0),
18 num_shared_memory_requests(0),
19 current_shared_memory_handle_index(0) {}
20
21 BlobAsyncBuilderHost::BlobBuildingState::~BlobBuildingState() {}
22
23 BlobAsyncBuilderHost::BlobAsyncBuilderHost() {}
24
25 BlobAsyncBuilderHost::~BlobAsyncBuilderHost() {}
26
27 bool BlobAsyncBuilderHost::StartBuildingBlob(
28 const std::string& uuid,
29 const std::string& type,
30 const std::vector<DataElement>& descriptions,
31 size_t memory_available,
32 const base::Callback<void(const std::vector<storage::BlobItemBytesRequest>&,
33 const std::vector<base::SharedMemoryHandle>&,
34 const std::vector<uint64_t>&)>& request_memory,
35 const base::Callback<void(const BlobDataBuilder&)>& done,
36 const base::Callback<void(IPCBlobCreationCancelCode)>& cancel) {
37 if (async_blob_map_.find(uuid) != async_blob_map_.end())
38 return false;
39 if (BlobAsyncTransportStrategy::ShouldBeShortcut(descriptions,
40 memory_available)) {
41 // We have enough memory, and all the data is here, so we use the shortcut
42 // method and populate the old way.
43 BlobDataBuilder builder(uuid);
44 builder.set_content_type(type);
45 for (const DataElement& element : descriptions) {
46 builder.AppendIPCDataElement(element);
47 }
48 done.Run(builder);
49 return true;
50 }
51
52 scoped_ptr<BlobBuildingState> state(new BlobBuildingState());
53 BlobBuildingState* state_ptr = state.get();
54 async_blob_map_[uuid] = std::move(state);
55 state_ptr->type = type;
56 state_ptr->request_memory_callback = request_memory;
57 state_ptr->done_callback = done;
58 state_ptr->cancel_callback = cancel;
59
60 // We are currently only operating in 'no disk' mode. This will change in
61 // future patches to enable disk storage.
62 // Since we don't have a disk yet, we put 0 for disk_space_left.
63 state_ptr->transport_strategy.Initialize(
64 max_ipc_memory_size_, max_shared_memory_size_, max_file_size_,
65 0 /* disk_space_left */, memory_available, uuid, descriptions);
66
67 switch (state_ptr->transport_strategy.error()) {
68 case BlobAsyncTransportStrategy::ERROR_TOO_LARGE:
69 // Cancel cleanly, we're out of memory.
70 CancelAndCleanup(uuid, IPCBlobCreationCancelCode::OUT_OF_MEMORY);
71 return true;
72 case BlobAsyncTransportStrategy::ERROR_INVALID_PARAMS:
73 // Bad IPC, so we ignore and clean up.
74 async_blob_map_.erase(async_blob_map_.find(uuid));
75 VLOG(1) << "Error initializing transport strategy: "
76 << state_ptr->transport_strategy.error();
77 return false;
78 case BlobAsyncTransportStrategy::ERROR_NONE:
79 ContinueBlobMemoryRequests(uuid);
80 return true;
81 }
82 return false;
83 }
84
85 bool BlobAsyncBuilderHost::OnMemoryResponses(
86 const std::string& uuid,
87 const std::vector<BlobItemBytesResponse>& responses) {
88 if (responses.empty()) {
89 return false;
90 }
91 AsyncBlobMap::const_iterator state_it = async_blob_map_.find(uuid);
92 if (state_it == async_blob_map_.end()) {
93 // 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.
95 DVLOG(1) << "Could not find blob " << uuid;
96 return true;
97 }
98 BlobAsyncBuilderHost::BlobBuildingState* state = state_it->second.get();
99 BlobAsyncTransportStrategy& strategy = state->transport_strategy;
100 bool invalid_ipc = false;
101 bool memory_error = false;
102 const auto& requests = strategy.requests();
103 for (const BlobItemBytesResponse& response : responses) {
104 if (response.request_number >= requests.size()) {
105 // Bad IPC, so we delete our record and ignore.
106 DVLOG(1) << "Invalid request number " << response.request_number;
107 async_blob_map_.erase(state_it);
108 return false;
109 }
110 const MemoryItemRequest& request = requests[response.request_number];
111 if (request.received) {
112 // Bad IPC, so we delete our record.
113 DVLOG(1) << "Already received response for that request.";
114 async_blob_map_.erase(state_it);
115 return false;
116 }
117 strategy.MarkRequestAsReceived(response.request_number);
118 switch (request.message.transport_strategy) {
119 case IPCBlobItemRequestStrategy::IPC:
120 if (response.inline_data.size() < request.message.size) {
121 DVLOG(1) << "Invalid data size " << response.inline_data.size()
122 << " vs requested size of " << request.message.size;
123 invalid_ipc = true;
124 break;
125 }
126 invalid_ipc = !strategy.blob_builder()->PopulateFutureData(
127 request.browser_item_index, &response.inline_data[0],
128 request.browser_item_offset, request.message.size);
129 break;
130 case IPCBlobItemRequestStrategy::SHARED_MEMORY:
131 if (state->num_shared_memory_requests == 0) {
132 DVLOG(1) << "Received too many responses for shared memory.";
133 invalid_ipc = true;
134 break;
135 }
136 state->num_shared_memory_requests--;
137 if (!state->shared_memory_block->memory()) {
138 // 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
140 // MapAt, remove the mapped boolean, and then exclude the
141 // handle_offset below.
142 size_t handle_size = strategy.shared_memory_handle_sizes().at(
143 state->current_shared_memory_handle_index);
144 if (!state->shared_memory_block->Map(handle_size)) {
145 DVLOG(1) << "Unable to map memory to size " << handle_size;
146 memory_error = true;
147 break;
148 }
149 }
150
151 invalid_ipc = !strategy.blob_builder()->PopulateFutureData(
152 request.browser_item_index,
153 static_cast<const char*>(state->shared_memory_block->memory()) +
154 request.message.handle_offset,
155 request.browser_item_offset, request.message.size);
156 break;
157 case IPCBlobItemRequestStrategy::FILE:
158 case IPCBlobItemRequestStrategy::UNKNOWN:
159 DVLOG(1) << "Not implemented.";
160 invalid_ipc = true;
161 break;
162 }
163 if (invalid_ipc) {
164 // Bad IPC, so we delete our record and return false.
165 async_blob_map_.erase(state_it);
166 return false;
167 }
168 if (memory_error) {
169 DVLOG(1) << "Shared memory error.";
170 CancelAndCleanup(uuid, IPCBlobCreationCancelCode::OUT_OF_MEMORY);
171 return true;
172 }
173 state->num_fulfilled_requests++;
174 }
175 ContinueBlobMemoryRequests(uuid);
176 return true;
177 }
178
179 void BlobAsyncBuilderHost::StopBuildingBlob(const std::string& uuid) {
180 async_blob_map_.erase(async_blob_map_.find(uuid));
181 }
182
183 void BlobAsyncBuilderHost::ContinueBlobMemoryRequests(const std::string& uuid) {
184 AsyncBlobMap::const_iterator state_it = async_blob_map_.find(uuid);
185 DCHECK(state_it != async_blob_map_.end());
186 BlobAsyncBuilderHost::BlobBuildingState* state = state_it->second.get();
187
188 const std::vector<MemoryItemRequest>& requests =
189 state->transport_strategy.requests();
190 BlobAsyncTransportStrategy& strategy = state->transport_strategy;
191 size_t num_requests = requests.size();
192 if (state->num_fulfilled_requests == num_requests) {
193 DoneAndCleanup(uuid);
194 return;
195 }
196 DCHECK_LT(state->num_fulfilled_requests, num_requests);
197 if (state->next_request == num_requests) {
198 // We are still waiting on other requests to come back.
199 return;
200 }
201
202 std::vector<BlobItemBytesRequest> byte_requests;
203 std::vector<base::SharedMemoryHandle> shared_memory;
204 std::vector<uint64_t> files;
205
206 for (; state->next_request < num_requests; ++state->next_request) {
207 const MemoryItemRequest& request = requests[state->next_request];
208
209 bool stop_accumulating = false;
210 bool using_shared_memory_handle = state->num_shared_memory_requests > 0;
211 switch (request.message.transport_strategy) {
212 case IPCBlobItemRequestStrategy::IPC:
213 byte_requests.push_back(request.message);
214 break;
215 case IPCBlobItemRequestStrategy::SHARED_MEMORY:
216 if (using_shared_memory_handle &&
217 state->current_shared_memory_handle_index !=
218 request.message.handle_index) {
219 // We only want one shared memory per requesting blob.
220 stop_accumulating = true;
221 break;
222 }
223 using_shared_memory_handle = true;
224 state->current_shared_memory_handle_index =
225 request.message.handle_index;
226 state->num_shared_memory_requests++;
227
228 if (!state->shared_memory_block) {
229 state->shared_memory_block.reset(new base::SharedMemory());
230 size_t size =
231 strategy
232 .shared_memory_handle_sizes()[request.message.handle_index];
233 if (!state->shared_memory_block->CreateAnonymous(size)) {
234 DVLOG(1) << "Unable to allocate shared memory for blob transfer.";
235 CancelAndCleanup(uuid, IPCBlobCreationCancelCode::OUT_OF_MEMORY);
236 return;
237 }
238 }
239 shared_memory.push_back(state->shared_memory_block->handle());
240 byte_requests.push_back(request.message);
241 // Since we are only using one handle at a time, transform our handle
242 // index correctly back to 0.
243 byte_requests.back().handle_index = 0;
244 break;
245 case IPCBlobItemRequestStrategy::FILE:
246 case IPCBlobItemRequestStrategy::UNKNOWN:
247 NOTREACHED() << "Not implemented yet.";
248 break;
249 }
250 if (stop_accumulating) {
251 break;
252 }
253 }
254
255 DCHECK(!requests.empty());
256
257 state->request_memory_callback.Run(byte_requests, shared_memory, files);
258 }
259
260 void BlobAsyncBuilderHost::CancelAndCleanup(const std::string& uuid,
261 IPCBlobCreationCancelCode code) {
262 scoped_ptr<BlobBuildingState> state = std::move(async_blob_map_[uuid]);
263 async_blob_map_.erase(uuid);
264 state->cancel_callback.Run(code);
265 }
266
267 void BlobAsyncBuilderHost::DoneAndCleanup(const std::string& uuid) {
268 scoped_ptr<BlobBuildingState> state = std::move(async_blob_map_[uuid]);
269 async_blob_map_.erase(uuid);
270 BlobDataBuilder* builder = state->transport_strategy.blob_builder();
271 builder->set_content_type(state->type);
272 state->done_callback.Run(*builder);
273 }
274
275 } // namespace storage
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698