• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "content/child/webblobregistry_impl.h"
6 
7 #include "base/files/file_path.h"
8 #include "base/guid.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"
20 
21 using blink::WebBlobData;
22 using blink::WebString;
23 using blink::WebThreadSafeData;
24 using blink::WebURL;
25 
26 namespace content {
27 
28 namespace {
29 
30 const size_t kLargeThresholdBytes = 250 * 1024;
31 const size_t kMaxSharedMemoryBytes = 10 * 1024 * 1024;
32 
33 }  // namespace
34 
WebBlobRegistryImpl(ThreadSafeSender * sender)35 WebBlobRegistryImpl::WebBlobRegistryImpl(ThreadSafeSender* sender)
36     : sender_(sender) {
37 }
38 
~WebBlobRegistryImpl()39 WebBlobRegistryImpl::~WebBlobRegistryImpl() {
40 }
41 
registerBlobData(const blink::WebString & uuid,const blink::WebBlobData & data)42 void WebBlobRegistryImpl::registerBlobData(
43     const blink::WebString& uuid, const blink::WebBlobData& data) {
44   const std::string uuid_str(uuid.utf8());
45 
46   sender_->Send(new BlobHostMsg_StartBuilding(uuid_str));
47   size_t i = 0;
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);
55         break;
56       }
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));
65           sender_->Send(
66               new BlobHostMsg_AppendBlobDataItem(uuid_str, item));
67         }
68         break;
69       case WebBlobData::Item::TypeBlob:
70         if (data_item.length) {
71           webkit_blob::BlobData::Item item;
72           item.SetToBlobRange(
73               data_item.blobUUID.utf8(),
74               static_cast<uint64>(data_item.offset),
75               static_cast<uint64>(data_item.length));
76           sender_->Send(
77               new BlobHostMsg_AppendBlobDataItem(uuid_str, item));
78         }
79         break;
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));
90           sender_->Send(
91               new BlobHostMsg_AppendBlobDataItem(uuid_str, item));
92         }
93         break;
94       default:
95         NOTREACHED();
96     }
97   }
98   sender_->Send(new BlobHostMsg_FinishBuilding(
99       uuid_str, data.contentType().utf8().data()));
100 }
101 
addBlobDataRef(const WebString & uuid)102 void WebBlobRegistryImpl::addBlobDataRef(const WebString& uuid) {
103   sender_->Send(new BlobHostMsg_IncrementRefCount(uuid.utf8()));
104 }
105 
removeBlobDataRef(const WebString & uuid)106 void WebBlobRegistryImpl::removeBlobDataRef(const WebString& uuid) {
107   sender_->Send(new BlobHostMsg_DecrementRefCount(uuid.utf8()));
108 }
109 
registerPublicBlobURL(const WebURL & url,const WebString & uuid)110 void WebBlobRegistryImpl::registerPublicBlobURL(
111     const WebURL& url, const WebString& uuid) {
112   sender_->Send(new BlobHostMsg_RegisterPublicURL(url, uuid.utf8()));
113 }
114 
revokePublicBlobURL(const WebURL & url)115 void WebBlobRegistryImpl::revokePublicBlobURL(const WebURL& url) {
116   sender_->Send(new BlobHostMsg_RevokePublicURL(url));
117 }
118 
SendDataForBlob(const std::string & uuid_str,const WebThreadSafeData & data)119 void WebBlobRegistryImpl::SendDataForBlob(const std::string& uuid_str,
120                                           const WebThreadSafeData& data) {
121 
122   if (data.size() == 0)
123     return;
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));
128   } else {
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,
135                                           sender_.get()));
136     CHECK(shared_memory.get());
137 
138     size_t data_size = data.size();
139     const char* data_ptr = data.data();
140     while (data_size) {
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;
147     }
148   }
149 }
150 
151 // ------ streams stuff -----
152 
registerStreamURL(const WebURL & url,const WebString & content_type)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()));
157 }
158 
registerStreamURL(const WebURL & url,const WebURL & src_url)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));
163 }
164 
addDataToStream(const WebURL & url,WebThreadSafeData & data)165 void WebBlobRegistryImpl::addDataToStream(const WebURL& url,
166                                           WebThreadSafeData& data) {
167   DCHECK(ChildThread::current());
168   if (data.size() == 0)
169     return;
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));
174   } else {
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,
181                                           sender_.get()));
182     CHECK(shared_memory.get());
183 
184     size_t data_size = data.size();
185     const char* data_ptr = data.data();
186     while (data_size) {
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;
193     }
194   }
195 }
196 
finalizeStream(const WebURL & url)197 void WebBlobRegistryImpl::finalizeStream(const WebURL& url) {
198   DCHECK(ChildThread::current());
199   sender_->Send(new StreamHostMsg_FinishBuilding(url));
200 }
201 
abortStream(const WebURL & url)202 void WebBlobRegistryImpl::abortStream(const WebURL& url) {
203   DCHECK(ChildThread::current());
204   sender_->Send(new StreamHostMsg_AbortBuilding(url));
205 }
206 
unregisterStreamURL(const WebURL & url)207 void WebBlobRegistryImpl::unregisterStreamURL(const WebURL& url) {
208   DCHECK(ChildThread::current());
209   sender_->Send(new StreamHostMsg_Remove(url));
210 }
211 
212 }  // namespace content
213