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

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

Powered by Google App Engine
This is Rietveld 408576698