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

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

Powered by Google App Engine
This is Rietveld 408576698