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

Side by Side Diff: content/child/webblobregistry_impl.cc

Issue 1234813004: [BlobAsync] Asynchronous Blob Construction Final Patch (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@blob-protocol-change
Patch Set: comments/fixes Created 4 years, 10 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 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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/webblobregistry_impl.h" 5 #include "content/child/webblobregistry_impl.h"
6 6
7 #include "base/bind.h"
7 #include "base/files/file_path.h" 8 #include "base/files/file_path.h"
8 #include "base/guid.h" 9 #include "base/guid.h"
10 #include "base/location.h"
9 #include "base/memory/ref_counted.h" 11 #include "base/memory/ref_counted.h"
10 #include "base/memory/scoped_ptr.h" 12 #include "base/memory/scoped_ptr.h"
11 #include "base/memory/shared_memory.h" 13 #include "base/memory/shared_memory.h"
12 #include "base/message_loop/message_loop.h" 14 #include "base/message_loop/message_loop.h"
13 #include "base/trace_event/trace_event.h" 15 #include "base/trace_event/trace_event.h"
16 #include "content/child/blob_storage/blob_consolidation.h"
17 #include "content/child/blob_storage/blob_transport_controller.h"
14 #include "content/child/child_thread_impl.h" 18 #include "content/child/child_thread_impl.h"
15 #include "content/child/thread_safe_sender.h" 19 #include "content/child/thread_safe_sender.h"
16 #include "content/common/fileapi/webblob_messages.h" 20 #include "content/common/fileapi/webblob_messages.h"
21 #include "storage/common/blob_storage/blob_storage_constants.h"
17 #include "third_party/WebKit/public/platform/WebBlobData.h" 22 #include "third_party/WebKit/public/platform/WebBlobData.h"
18 #include "third_party/WebKit/public/platform/WebString.h" 23 #include "third_party/WebKit/public/platform/WebString.h"
19 #include "third_party/WebKit/public/platform/WebThreadSafeData.h" 24 #include "third_party/WebKit/public/platform/WebThreadSafeData.h"
20 #include "third_party/WebKit/public/platform/WebURL.h" 25 #include "third_party/WebKit/public/platform/WebURL.h"
21 26
22 using blink::WebBlobData; 27 using blink::WebBlobData;
23 using blink::WebString; 28 using blink::WebString;
24 using blink::WebThreadSafeData; 29 using blink::WebThreadSafeData;
25 using blink::WebURL; 30 using blink::WebURL;
26 using blink::WebBlobRegistry; 31 using blink::WebBlobRegistry;
27 using storage::DataElement; 32 using storage::DataElement;
28 33
29 namespace content { 34 namespace content {
30 35
31 namespace { 36 WebBlobRegistryImpl::WebBlobRegistryImpl(
32 37 base::SingleThreadTaskRunner* io_runner,
33 const size_t kLargeThresholdBytes = 250 * 1024; 38 ThreadSafeSender* sender)
34 const size_t kMaxSharedMemoryBytes = 10 * 1024 * 1024; 39 : io_runner_(io_runner), sender_(sender) {
35
36 } // namespace
37
38 WebBlobRegistryImpl::WebBlobRegistryImpl(ThreadSafeSender* sender)
39 : sender_(sender) {
40 // Record a dummy trace event on startup so the 'Storage' category shows up 40 // Record a dummy trace event on startup so the 'Storage' category shows up
41 // in the chrome://tracing viewer. 41 // in the chrome://tracing viewer.
42 TRACE_EVENT0("Blob", "Init"); 42 TRACE_EVENT0("Blob", "Init");
43 } 43 }
44 44
45 WebBlobRegistryImpl::~WebBlobRegistryImpl() { 45 WebBlobRegistryImpl::~WebBlobRegistryImpl() {
46 } 46 }
47 47
48 blink::WebBlobRegistry::Builder* WebBlobRegistryImpl::createBuilder( 48 blink::WebBlobRegistry::Builder* WebBlobRegistryImpl::createBuilder(
49 const blink::WebString& uuid, 49 const blink::WebString& uuid,
50 const blink::WebString& contentType) { 50 const blink::WebString& content_type) {
51 return new BuilderImpl(uuid, contentType, sender_.get()); 51 return new BuilderImpl(uuid, content_type, sender_.get(), io_runner_.get());
52 } 52 }
53 53
54 void WebBlobRegistryImpl::registerBlobData(const blink::WebString& uuid, 54 void WebBlobRegistryImpl::registerBlobData(const blink::WebString& uuid,
55 const blink::WebBlobData& data) { 55 const blink::WebBlobData& data) {
56 TRACE_EVENT0("Blob", "Registry::RegisterBlob"); 56 TRACE_EVENT0("Blob", "Registry::RegisterBlob");
57 scoped_ptr<Builder> builder(createBuilder(uuid, data.contentType())); 57 scoped_ptr<Builder> builder(createBuilder(uuid, data.contentType()));
58 58
59 // This is temporary until we move to createBuilder() as our blob creation 59 // This is temporary until we move to createBuilder() as our blob creation
60 // method. 60 // method.
61 size_t i = 0; 61 size_t i = 0;
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 DCHECK(ChildThreadImpl::current()); 126 DCHECK(ChildThreadImpl::current());
127 sender_->Send(new StreamHostMsg_Clone(url, src_url)); 127 sender_->Send(new StreamHostMsg_Clone(url, src_url));
128 } 128 }
129 129
130 void WebBlobRegistryImpl::addDataToStream(const WebURL& url, 130 void WebBlobRegistryImpl::addDataToStream(const WebURL& url,
131 const char* data, 131 const char* data,
132 size_t length) { 132 size_t length) {
133 DCHECK(ChildThreadImpl::current()); 133 DCHECK(ChildThreadImpl::current());
134 if (length == 0) 134 if (length == 0)
135 return; 135 return;
136 if (length < kLargeThresholdBytes) { 136 if (length < storage::kBlobStorageIPCThresholdBytes) {
137 DataElement item; 137 DataElement item;
138 item.SetToBytes(data, length); 138 item.SetToBytes(data, length);
139 sender_->Send(new StreamHostMsg_AppendBlobDataItem(url, item)); 139 sender_->Send(new StreamHostMsg_AppendBlobDataItem(url, item));
140 } else { 140 } else {
141 // We handle larger amounts of data via SharedMemory instead of 141 // We handle larger amounts of data via SharedMemory instead of
142 // writing it directly to the IPC channel. 142 // writing it directly to the IPC channel.
143 size_t shared_memory_size = std::min(length, kMaxSharedMemoryBytes); 143 size_t shared_memory_size =
144 std::min(length, storage::kBlobStorageMaxSharedMemoryBytes);
144 scoped_ptr<base::SharedMemory> shared_memory( 145 scoped_ptr<base::SharedMemory> shared_memory(
145 ChildThreadImpl::AllocateSharedMemory(shared_memory_size, 146 ChildThreadImpl::AllocateSharedMemory(shared_memory_size,
146 sender_.get())); 147 sender_.get()));
147 CHECK(shared_memory.get()); 148 CHECK(shared_memory.get());
148 if (!shared_memory->Map(shared_memory_size)) 149 if (!shared_memory->Map(shared_memory_size))
149 CHECK(false); 150 CHECK(false);
150 151
151 size_t remaining_bytes = length; 152 size_t remaining_bytes = length;
152 const char* current_ptr = data; 153 const char* current_ptr = data;
153 while (remaining_bytes) { 154 while (remaining_bytes) {
(...skipping 23 matching lines...) Expand all
177 } 178 }
178 179
179 void WebBlobRegistryImpl::unregisterStreamURL(const WebURL& url) { 180 void WebBlobRegistryImpl::unregisterStreamURL(const WebURL& url) {
180 DCHECK(ChildThreadImpl::current()); 181 DCHECK(ChildThreadImpl::current());
181 sender_->Send(new StreamHostMsg_Remove(url)); 182 sender_->Send(new StreamHostMsg_Remove(url));
182 } 183 }
183 184
184 WebBlobRegistryImpl::BuilderImpl::BuilderImpl( 185 WebBlobRegistryImpl::BuilderImpl::BuilderImpl(
185 const blink::WebString& uuid, 186 const blink::WebString& uuid,
186 const blink::WebString& content_type, 187 const blink::WebString& content_type,
187 ThreadSafeSender* sender) 188 ThreadSafeSender* sender,
188 : uuid_(uuid.utf8()), content_type_(content_type.utf8()), sender_(sender) { 189 base::SingleThreadTaskRunner* io_runner)
189 } 190 : uuid_(uuid.utf8()),
191 content_type_(content_type.utf8()),
192 consolidation_(new BlobConsolidation()),
193 sender_(sender),
194 io_runner_(io_runner) {}
190 195
191 WebBlobRegistryImpl::BuilderImpl::~BuilderImpl() { 196 WebBlobRegistryImpl::BuilderImpl::~BuilderImpl() {
192 } 197 }
193 198
194 void WebBlobRegistryImpl::BuilderImpl::appendData( 199 void WebBlobRegistryImpl::BuilderImpl::appendData(
195 const WebThreadSafeData& data) { 200 const WebThreadSafeData& data) {
196 consolidation_.AddDataItem(data); 201 consolidation_->AddDataItem(data);
197 } 202 }
198 203
199 void WebBlobRegistryImpl::BuilderImpl::appendBlob(const WebString& uuid, 204 void WebBlobRegistryImpl::BuilderImpl::appendBlob(const WebString& uuid,
200 uint64_t offset, 205 uint64_t offset,
201 uint64_t length) { 206 uint64_t length) {
202 consolidation_.AddBlobItem(uuid.utf8(), offset, length); 207 consolidation_->AddBlobItem(uuid.utf8(), offset, length);
203 } 208 }
204 209
205 void WebBlobRegistryImpl::BuilderImpl::appendFile( 210 void WebBlobRegistryImpl::BuilderImpl::appendFile(
206 const WebString& path, 211 const WebString& path,
207 uint64_t offset, 212 uint64_t offset,
208 uint64_t length, 213 uint64_t length,
209 double expected_modification_time) { 214 double expected_modification_time) {
210 consolidation_.AddFileItem( 215 consolidation_->AddFileItem(
211 base::FilePath::FromUTF16Unsafe(base::string16(path)), offset, length, 216 base::FilePath::FromUTF16Unsafe(base::string16(path)), offset, length,
212 expected_modification_time); 217 expected_modification_time);
213 } 218 }
214 219
215 void WebBlobRegistryImpl::BuilderImpl::appendFileSystemURL( 220 void WebBlobRegistryImpl::BuilderImpl::appendFileSystemURL(
216 const WebURL& fileSystemURL, 221 const WebURL& fileSystemURL,
217 uint64_t offset, 222 uint64_t offset,
218 uint64_t length, 223 uint64_t length,
219 double expected_modification_time) { 224 double expected_modification_time) {
220 DCHECK(GURL(fileSystemURL).SchemeIsFileSystem()); 225 DCHECK(GURL(fileSystemURL).SchemeIsFileSystem());
221 consolidation_.AddFileSystemItem(GURL(fileSystemURL), offset, length, 226 consolidation_->AddFileSystemItem(GURL(fileSystemURL), offset, length,
222 expected_modification_time); 227 expected_modification_time);
223 } 228 }
224 229
225 void WebBlobRegistryImpl::BuilderImpl::build() { 230 void WebBlobRegistryImpl::BuilderImpl::build() {
226 sender_->Send(new BlobHostMsg_StartBuilding(uuid_)); 231 sender_->Send(new BlobStorageMsg_RegisterBlobUUID(uuid_, content_type_, ""));
227 const auto& items = consolidation_.consolidated_items(); 232 io_runner_->PostTask(
228 233 FROM_HERE, base::Bind(&WebBlobRegistryImpl::StartBlobAsyncConstruction,
229 // We still need a buffer to hold the continuous block of data so the 234 uuid_, base::Passed(&consolidation_), sender_));
230 // DataElement can hold it.
231 size_t buffer_size = 0;
232 scoped_ptr<char[]> buffer;
233 for (size_t i = 0; i < items.size(); i++) {
234 const BlobConsolidation::ConsolidatedItem& item = items[i];
235 DataElement element;
236 // NOTE: length == -1 when we want to use the whole file. This
237 // only happens when we are creating a file object in Blink, and the file
238 // object is the only item in the 'blob'. If we use that file blob to
239 // create another blob, it is sent here as a 'file' item and not a blob,
240 // and the correct size is populated.
241 // static_cast<uint64_t>(-1) == kuint64max, which is what DataElement uses
242 // to specificy "use the whole file".
243 switch (item.type) {
244 case DataElement::TYPE_BYTES:
245 if (item.length > kLargeThresholdBytes) {
246 SendOversizedDataForBlob(i);
247 break;
248 }
249 if (buffer_size < item.length) {
250 buffer.reset(new char[item.length]);
251 buffer_size = item.length;
252 }
253 consolidation_.ReadMemory(i, 0, item.length, buffer.get());
254 element.SetToSharedBytes(buffer.get(), item.length);
255 sender_->Send(new BlobHostMsg_AppendBlobDataItem(uuid_, element));
256 break;
257 case DataElement::TYPE_FILE:
258 element.SetToFilePathRange(
259 item.path, item.offset, item.length,
260 base::Time::FromDoubleT(item.expected_modification_time));
261 sender_->Send(new BlobHostMsg_AppendBlobDataItem(uuid_, element));
262 break;
263 case DataElement::TYPE_BLOB:
264 element.SetToBlobRange(item.blob_uuid, item.offset, item.length);
265 sender_->Send(new BlobHostMsg_AppendBlobDataItem(uuid_, element));
266 break;
267 case DataElement::TYPE_FILE_FILESYSTEM:
268 element.SetToFileSystemUrlRange(
269 item.filesystem_url, item.offset, item.length,
270 base::Time::FromDoubleT(item.expected_modification_time));
271 sender_->Send(new BlobHostMsg_AppendBlobDataItem(uuid_, element));
272 break;
273 default:
274 NOTREACHED();
275 }
276 }
277 sender_->Send(new BlobHostMsg_FinishBuilding(uuid_, content_type_));
278 } 235 }
279 236
280 void WebBlobRegistryImpl::BuilderImpl::SendOversizedDataForBlob( 237 /* static */
281 size_t consolidated_item_index) { 238 void WebBlobRegistryImpl::StartBlobAsyncConstruction(
282 TRACE_EVENT0("Blob", "Registry::SendOversizedBlobData"); 239 const std::string& uuid,
283 const BlobConsolidation::ConsolidatedItem& item = 240 scoped_ptr<BlobConsolidation> consolidation,
284 consolidation_.consolidated_items()[consolidated_item_index]; 241 const scoped_refptr<ThreadSafeSender>& sender) {
285 // We handle larger amounts of data via SharedMemory instead of 242 BlobTransportController::GetInstance()->InitiateBlobTransfer(
286 // writing it directly to the IPC channel. 243 uuid, std::move(consolidation), sender.get());
287
288 size_t data_size = item.length;
289 size_t shared_memory_size = std::min(data_size, kMaxSharedMemoryBytes);
290 scoped_ptr<base::SharedMemory> shared_memory(
291 ChildThreadImpl::AllocateSharedMemory(shared_memory_size, sender_.get()));
292 CHECK(shared_memory.get());
293 const bool mapped = shared_memory->Map(shared_memory_size);
294 CHECK(mapped) << "Unable to map shared memory.";
295
296 size_t offset = 0;
297 while (data_size) {
298 TRACE_EVENT0("Blob", "Registry::SendOversizedBlobItem");
299 size_t chunk_size = std::min(data_size, shared_memory_size);
300 consolidation_.ReadMemory(consolidated_item_index, offset, chunk_size,
301 shared_memory->memory());
302 sender_->Send(new BlobHostMsg_SyncAppendSharedMemory(
303 uuid_, shared_memory->handle(), chunk_size));
304 data_size -= chunk_size;
305 offset += chunk_size;
306 }
307 } 244 }
308 245
309 } // namespace content 246 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698