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/memory/ref_counted.h"
      9 #include "base/memory/shared_memory.h"
     10 #include "base/message_loop/message_loop.h"
     11 #include "content/child/child_thread.h"
     12 #include "content/child/thread_safe_sender.h"
     13 #include "content/common/fileapi/webblob_messages.h"
     14 #include "third_party/WebKit/public/platform/WebBlobData.h"
     15 #include "third_party/WebKit/public/platform/WebString.h"
     16 #include "third_party/WebKit/public/platform/WebThreadSafeData.h"
     17 #include "third_party/WebKit/public/platform/WebURL.h"
     18 #include "webkit/common/blob/blob_data.h"
     19 
     20 using WebKit::WebBlobData;
     21 using WebKit::WebString;
     22 using WebKit::WebThreadSafeData;
     23 using WebKit::WebURL;
     24 
     25 namespace content {
     26 
     27 namespace {
     28 
     29 const size_t kLargeThresholdBytes = 250 * 1024;
     30 const size_t kMaxSharedMemoryBytes = 10 * 1024 * 1024;
     31 
     32 }  // namespace
     33 
     34 WebBlobRegistryImpl::WebBlobRegistryImpl(ThreadSafeSender* sender)
     35     : sender_(sender) {
     36 }
     37 
     38 WebBlobRegistryImpl::~WebBlobRegistryImpl() {
     39 }
     40 
     41 void WebBlobRegistryImpl::SendDataForBlob(const WebURL& url,
     42                                           const WebThreadSafeData& data) {
     43 
     44   if (data.size() == 0)
     45     return;
     46   if (data.size() < kLargeThresholdBytes) {
     47     webkit_blob::BlobData::Item item;
     48     item.SetToBytes(data.data(), data.size());
     49     sender_->Send(new BlobHostMsg_AppendBlobDataItem(url, item));
     50   } else {
     51     // We handle larger amounts of data via SharedMemory instead of
     52     // writing it directly to the IPC channel.
     53     size_t shared_memory_size = std::min(
     54         data.size(), kMaxSharedMemoryBytes);
     55     scoped_ptr<base::SharedMemory> shared_memory(
     56         ChildThread::AllocateSharedMemory(shared_memory_size,
     57                                           sender_.get()));
     58     CHECK(shared_memory.get());
     59 
     60     size_t data_size = data.size();
     61     const char* data_ptr = data.data();
     62     while (data_size) {
     63       size_t chunk_size = std::min(data_size, shared_memory_size);
     64       memcpy(shared_memory->memory(), data_ptr, chunk_size);
     65       sender_->Send(new BlobHostMsg_SyncAppendSharedMemory(
     66           url, shared_memory->handle(), chunk_size));
     67       data_size -= chunk_size;
     68       data_ptr += chunk_size;
     69     }
     70   }
     71 }
     72 
     73 void WebBlobRegistryImpl::registerBlobURL(
     74     const WebURL& url, WebBlobData& data) {
     75   DCHECK(ChildThread::current());
     76   sender_->Send(new BlobHostMsg_StartBuilding(url));
     77   size_t i = 0;
     78   WebBlobData::Item data_item;
     79   while (data.itemAt(i++, data_item)) {
     80     switch (data_item.type) {
     81       case WebBlobData::Item::TypeData: {
     82         // WebBlobData does not allow partial data items.
     83         DCHECK(!data_item.offset && data_item.length == -1);
     84         SendDataForBlob(url, data_item.data);
     85         break;
     86       }
     87       case WebBlobData::Item::TypeFile:
     88         if (data_item.length) {
     89           webkit_blob::BlobData::Item item;
     90           item.SetToFilePathRange(
     91               base::FilePath::FromUTF16Unsafe(data_item.filePath),
     92               static_cast<uint64>(data_item.offset),
     93               static_cast<uint64>(data_item.length),
     94               base::Time::FromDoubleT(data_item.expectedModificationTime));
     95           sender_->Send(
     96               new BlobHostMsg_AppendBlobDataItem(url, item));
     97         }
     98         break;
     99       case WebBlobData::Item::TypeBlob:
    100         if (data_item.length) {
    101           webkit_blob::BlobData::Item item;
    102           item.SetToBlobUrlRange(
    103               data_item.blobURL,
    104               static_cast<uint64>(data_item.offset),
    105               static_cast<uint64>(data_item.length));
    106           sender_->Send(
    107               new BlobHostMsg_AppendBlobDataItem(url, item));
    108         }
    109         break;
    110       case WebBlobData::Item::TypeURL:
    111         if (data_item.length) {
    112           // We only support filesystem URL as of now.
    113           DCHECK(GURL(data_item.url).SchemeIsFileSystem());
    114           webkit_blob::BlobData::Item item;
    115           item.SetToFileSystemUrlRange(
    116               data_item.url,
    117               static_cast<uint64>(data_item.offset),
    118               static_cast<uint64>(data_item.length),
    119               base::Time::FromDoubleT(data_item.expectedModificationTime));
    120           sender_->Send(
    121               new BlobHostMsg_AppendBlobDataItem(url, item));
    122         }
    123         break;
    124       default:
    125         NOTREACHED();
    126     }
    127   }
    128   sender_->Send(new BlobHostMsg_FinishBuilding(
    129       url, data.contentType().utf8().data()));
    130 }
    131 
    132 void WebBlobRegistryImpl::registerBlobURL(
    133     const WebURL& url, const WebURL& src_url) {
    134   DCHECK(ChildThread::current());
    135   sender_->Send(new BlobHostMsg_Clone(url, src_url));
    136 }
    137 
    138 void WebBlobRegistryImpl::unregisterBlobURL(const WebURL& url) {
    139   DCHECK(ChildThread::current());
    140   sender_->Send(new BlobHostMsg_Remove(url));
    141 }
    142 
    143 void WebBlobRegistryImpl::registerStreamURL(
    144     const WebURL& url, const WebString& content_type) {
    145   DCHECK(ChildThread::current());
    146   sender_->Send(new StreamHostMsg_StartBuilding(url, content_type.utf8()));
    147 }
    148 
    149 void WebBlobRegistryImpl::registerStreamURL(
    150     const WebURL& url, const WebURL& src_url) {
    151   DCHECK(ChildThread::current());
    152   sender_->Send(new StreamHostMsg_Clone(url, src_url));
    153 }
    154 
    155 void WebBlobRegistryImpl::addDataToStream(const WebURL& url,
    156                                           WebThreadSafeData& data) {
    157   DCHECK(ChildThread::current());
    158   if (data.size() == 0)
    159     return;
    160   if (data.size() < kLargeThresholdBytes) {
    161     webkit_blob::BlobData::Item item;
    162     item.SetToBytes(data.data(), data.size());
    163     sender_->Send(new StreamHostMsg_AppendBlobDataItem(url, item));
    164   } else {
    165     // We handle larger amounts of data via SharedMemory instead of
    166     // writing it directly to the IPC channel.
    167     size_t shared_memory_size = std::min(
    168         data.size(), kMaxSharedMemoryBytes);
    169     scoped_ptr<base::SharedMemory> shared_memory(
    170         ChildThread::AllocateSharedMemory(shared_memory_size,
    171                                           sender_.get()));
    172     CHECK(shared_memory.get());
    173 
    174     size_t data_size = data.size();
    175     const char* data_ptr = data.data();
    176     while (data_size) {
    177       size_t chunk_size = std::min(data_size, shared_memory_size);
    178       memcpy(shared_memory->memory(), data_ptr, chunk_size);
    179       sender_->Send(new StreamHostMsg_SyncAppendSharedMemory(
    180           url, shared_memory->handle(), chunk_size));
    181       data_size -= chunk_size;
    182       data_ptr += chunk_size;
    183     }
    184   }
    185 }
    186 
    187 void WebBlobRegistryImpl::finalizeStream(const WebURL& url) {
    188   DCHECK(ChildThread::current());
    189   sender_->Send(new StreamHostMsg_FinishBuilding(url));
    190 }
    191 
    192 void WebBlobRegistryImpl::unregisterStreamURL(const WebURL& url) {
    193   DCHECK(ChildThread::current());
    194   sender_->Send(new StreamHostMsg_Remove(url));
    195 }
    196 
    197 }  // namespace content
    198