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
3 // found in the LICENSE file.
5 #include "content/child/webblobregistry_impl.h"
7 #include "base/files/file_path.h"
9 #include "base/memory/ref_counted.h"
10 #include "base/memory/shared_memory.h"
11 #include "base/message_loop/message_loop.h"
12 #include "content/child/child_thread.h"
13 #include "content/child/thread_safe_sender.h"
14 #include "content/common/fileapi/webblob_messages.h"
15 #include "third_party/WebKit/public/platform/WebBlobData.h"
16 #include "third_party/WebKit/public/platform/WebString.h"
17 #include "third_party/WebKit/public/platform/WebThreadSafeData.h"
18 #include "third_party/WebKit/public/platform/WebURL.h"
19 #include "webkit/common/blob/blob_data.h"
21 using blink::WebBlobData
;
22 using blink::WebString
;
23 using blink::WebThreadSafeData
;
30 const size_t kLargeThresholdBytes
= 250 * 1024;
31 const size_t kMaxSharedMemoryBytes
= 10 * 1024 * 1024;
35 WebBlobRegistryImpl::WebBlobRegistryImpl(ThreadSafeSender
* sender
)
39 WebBlobRegistryImpl::~WebBlobRegistryImpl() {
42 void WebBlobRegistryImpl::registerBlobData(
43 const blink::WebString
& uuid
, const blink::WebBlobData
& data
) {
44 const std::string
uuid_str(uuid
.utf8());
46 sender_
->Send(new BlobHostMsg_StartBuilding(uuid_str
));
48 WebBlobData::Item data_item
;
49 while (data
.itemAt(i
++, data_item
)) {
50 switch (data_item
.type
) {
51 case WebBlobData::Item::TypeData
: {
52 // WebBlobData does not allow partial data items.
53 DCHECK(!data_item
.offset
&& data_item
.length
== -1);
54 SendDataForBlob(uuid_str
, data_item
.data
);
57 case WebBlobData::Item::TypeFile
:
58 if (data_item
.length
) {
59 webkit_blob::BlobData::Item item
;
60 item
.SetToFilePathRange(
61 base::FilePath::FromUTF16Unsafe(data_item
.filePath
),
62 static_cast<uint64
>(data_item
.offset
),
63 static_cast<uint64
>(data_item
.length
),
64 base::Time::FromDoubleT(data_item
.expectedModificationTime
));
66 new BlobHostMsg_AppendBlobDataItem(uuid_str
, item
));
69 case WebBlobData::Item::TypeBlob
:
70 if (data_item
.length
) {
71 webkit_blob::BlobData::Item item
;
73 data_item
.blobUUID
.utf8(),
74 static_cast<uint64
>(data_item
.offset
),
75 static_cast<uint64
>(data_item
.length
));
77 new BlobHostMsg_AppendBlobDataItem(uuid_str
, item
));
80 case WebBlobData::Item::TypeFileSystemURL
:
81 if (data_item
.length
) {
82 // We only support filesystem URL as of now.
83 DCHECK(GURL(data_item
.fileSystemURL
).SchemeIsFileSystem());
84 webkit_blob::BlobData::Item item
;
85 item
.SetToFileSystemUrlRange(
86 data_item
.fileSystemURL
,
87 static_cast<uint64
>(data_item
.offset
),
88 static_cast<uint64
>(data_item
.length
),
89 base::Time::FromDoubleT(data_item
.expectedModificationTime
));
91 new BlobHostMsg_AppendBlobDataItem(uuid_str
, item
));
98 sender_
->Send(new BlobHostMsg_FinishBuilding(
99 uuid_str
, data
.contentType().utf8().data()));
102 void WebBlobRegistryImpl::addBlobDataRef(const WebString
& uuid
) {
103 sender_
->Send(new BlobHostMsg_IncrementRefCount(uuid
.utf8()));
106 void WebBlobRegistryImpl::removeBlobDataRef(const WebString
& uuid
) {
107 sender_
->Send(new BlobHostMsg_DecrementRefCount(uuid
.utf8()));
110 void WebBlobRegistryImpl::registerPublicBlobURL(
111 const WebURL
& url
, const WebString
& uuid
) {
112 sender_
->Send(new BlobHostMsg_RegisterPublicURL(url
, uuid
.utf8()));
115 void WebBlobRegistryImpl::revokePublicBlobURL(const WebURL
& url
) {
116 sender_
->Send(new BlobHostMsg_RevokePublicURL(url
));
119 void WebBlobRegistryImpl::SendDataForBlob(const std::string
& uuid_str
,
120 const WebThreadSafeData
& data
) {
122 if (data
.size() == 0)
124 if (data
.size() < kLargeThresholdBytes
) {
125 webkit_blob::BlobData::Item item
;
126 item
.SetToBytes(data
.data(), data
.size());
127 sender_
->Send(new BlobHostMsg_AppendBlobDataItem(uuid_str
, item
));
129 // We handle larger amounts of data via SharedMemory instead of
130 // writing it directly to the IPC channel.
131 size_t shared_memory_size
= std::min(
132 data
.size(), kMaxSharedMemoryBytes
);
133 scoped_ptr
<base::SharedMemory
> shared_memory(
134 ChildThread::AllocateSharedMemory(shared_memory_size
,
136 CHECK(shared_memory
.get());
138 size_t data_size
= data
.size();
139 const char* data_ptr
= data
.data();
141 size_t chunk_size
= std::min(data_size
, shared_memory_size
);
142 memcpy(shared_memory
->memory(), data_ptr
, chunk_size
);
143 sender_
->Send(new BlobHostMsg_SyncAppendSharedMemory(
144 uuid_str
, shared_memory
->handle(), chunk_size
));
145 data_size
-= chunk_size
;
146 data_ptr
+= chunk_size
;
151 // ------ streams stuff -----
153 void WebBlobRegistryImpl::registerStreamURL(
154 const WebURL
& url
, const WebString
& content_type
) {
155 DCHECK(ChildThread::current());
156 sender_
->Send(new StreamHostMsg_StartBuilding(url
, content_type
.utf8()));
159 void WebBlobRegistryImpl::registerStreamURL(
160 const WebURL
& url
, const WebURL
& src_url
) {
161 DCHECK(ChildThread::current());
162 sender_
->Send(new StreamHostMsg_Clone(url
, src_url
));
165 void WebBlobRegistryImpl::addDataToStream(const WebURL
& url
,
166 WebThreadSafeData
& data
) {
167 DCHECK(ChildThread::current());
168 if (data
.size() == 0)
170 if (data
.size() < kLargeThresholdBytes
) {
171 webkit_blob::BlobData::Item item
;
172 item
.SetToBytes(data
.data(), data
.size());
173 sender_
->Send(new StreamHostMsg_AppendBlobDataItem(url
, item
));
175 // We handle larger amounts of data via SharedMemory instead of
176 // writing it directly to the IPC channel.
177 size_t shared_memory_size
= std::min(
178 data
.size(), kMaxSharedMemoryBytes
);
179 scoped_ptr
<base::SharedMemory
> shared_memory(
180 ChildThread::AllocateSharedMemory(shared_memory_size
,
182 CHECK(shared_memory
.get());
184 size_t data_size
= data
.size();
185 const char* data_ptr
= data
.data();
187 size_t chunk_size
= std::min(data_size
, shared_memory_size
);
188 memcpy(shared_memory
->memory(), data_ptr
, chunk_size
);
189 sender_
->Send(new StreamHostMsg_SyncAppendSharedMemory(
190 url
, shared_memory
->handle(), chunk_size
));
191 data_size
-= chunk_size
;
192 data_ptr
+= chunk_size
;
197 void WebBlobRegistryImpl::finalizeStream(const WebURL
& url
) {
198 DCHECK(ChildThread::current());
199 sender_
->Send(new StreamHostMsg_FinishBuilding(url
));
202 void WebBlobRegistryImpl::abortStream(const WebURL
& url
) {
203 DCHECK(ChildThread::current());
204 sender_
->Send(new StreamHostMsg_AbortBuilding(url
));
207 void WebBlobRegistryImpl::unregisterStreamURL(const WebURL
& url
) {
208 DCHECK(ChildThread::current());
209 sender_
->Send(new StreamHostMsg_Remove(url
));
212 } // namespace content