Home | History | Annotate | Download | only in child
      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 "storage/common/blob/blob_data.h"
     16 #include "third_party/WebKit/public/platform/WebBlobData.h"
     17 #include "third_party/WebKit/public/platform/WebString.h"
     18 #include "third_party/WebKit/public/platform/WebThreadSafeData.h"
     19 #include "third_party/WebKit/public/platform/WebURL.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 
     35 WebBlobRegistryImpl::WebBlobRegistryImpl(ThreadSafeSender* sender)
     36     : sender_(sender) {
     37 }
     38 
     39 WebBlobRegistryImpl::~WebBlobRegistryImpl() {
     40 }
     41 
     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           storage::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           storage::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           storage::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 
    102 void WebBlobRegistryImpl::addBlobDataRef(const WebString& uuid) {
    103   sender_->Send(new BlobHostMsg_IncrementRefCount(uuid.utf8()));
    104 }
    105 
    106 void WebBlobRegistryImpl::removeBlobDataRef(const WebString& uuid) {
    107   sender_->Send(new BlobHostMsg_DecrementRefCount(uuid.utf8()));
    108 }
    109 
    110 void WebBlobRegistryImpl::registerPublicBlobURL(
    111     const WebURL& url, const WebString& uuid) {
    112   sender_->Send(new BlobHostMsg_RegisterPublicURL(url, uuid.utf8()));
    113 }
    114 
    115 void WebBlobRegistryImpl::revokePublicBlobURL(const WebURL& url) {
    116   sender_->Send(new BlobHostMsg_RevokePublicURL(url));
    117 }
    118 
    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     storage::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 
    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 
    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 
    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     storage::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 
    197 void WebBlobRegistryImpl::finalizeStream(const WebURL& url) {
    198   DCHECK(ChildThread::current());
    199   sender_->Send(new StreamHostMsg_FinishBuilding(url));
    200 }
    201 
    202 void WebBlobRegistryImpl::abortStream(const WebURL& url) {
    203   DCHECK(ChildThread::current());
    204   sender_->Send(new StreamHostMsg_AbortBuilding(url));
    205 }
    206 
    207 void WebBlobRegistryImpl::unregisterStreamURL(const WebURL& url) {
    208   DCHECK(ChildThread::current());
    209   sender_->Send(new StreamHostMsg_Remove(url));
    210 }
    211 
    212 }  // namespace content
    213