Home | History | Annotate | Download | only in media_galleries
      1 // Copyright 2014 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 "chrome/utility/media_galleries/ipc_data_source.h"
      6 
      7 #include "base/message_loop/message_loop_proxy.h"
      8 #include "chrome/common/chrome_utility_messages.h"
      9 #include "content/public/utility/utility_thread.h"
     10 
     11 namespace metadata {
     12 
     13 IPCDataSource::IPCDataSource(int64 total_size)
     14     : total_size_(total_size),
     15       utility_task_runner_(base::MessageLoopProxy::current()),
     16       next_request_id_(0) {
     17   data_source_thread_checker_.DetachFromThread();
     18 }
     19 
     20 IPCDataSource::~IPCDataSource() {
     21   DCHECK(utility_thread_checker_.CalledOnValidThread());
     22 }
     23 
     24 void IPCDataSource::Stop(const base::Closure& callback) {
     25   DCHECK(data_source_thread_checker_.CalledOnValidThread());
     26   callback.Run();
     27 }
     28 
     29 void IPCDataSource::Read(int64 position, int size, uint8* data,
     30                          const DataSource::ReadCB& read_cb) {
     31   DCHECK(data_source_thread_checker_.CalledOnValidThread());
     32   utility_task_runner_->PostTask(
     33       FROM_HERE,
     34       base::Bind(&IPCDataSource::ReadOnUtilityThread, base::Unretained(this),
     35                  position, size, data, read_cb));
     36 }
     37 
     38 bool IPCDataSource::GetSize(int64* size_out) {
     39   DCHECK(data_source_thread_checker_.CalledOnValidThread());
     40   *size_out = total_size_;
     41   return true;
     42 }
     43 
     44 bool IPCDataSource::IsStreaming() {
     45   DCHECK(data_source_thread_checker_.CalledOnValidThread());
     46   return false;
     47 }
     48 
     49 void IPCDataSource::SetBitrate(int bitrate) {
     50   DCHECK(data_source_thread_checker_.CalledOnValidThread());
     51 }
     52 
     53 bool IPCDataSource::OnMessageReceived(const IPC::Message& message) {
     54   DCHECK(utility_thread_checker_.CalledOnValidThread());
     55   bool handled = true;
     56   IPC_BEGIN_MESSAGE_MAP(IPCDataSource, message)
     57     IPC_MESSAGE_HANDLER(ChromeUtilityMsg_RequestBlobBytes_Finished,
     58                         OnRequestBlobBytesFinished)
     59     IPC_MESSAGE_UNHANDLED(handled = false)
     60   IPC_END_MESSAGE_MAP()
     61   return handled;
     62 }
     63 
     64 IPCDataSource::Request::Request()
     65     : destination(NULL) {
     66 }
     67 
     68 IPCDataSource::Request::~Request() {
     69 }
     70 
     71 void IPCDataSource::ReadOnUtilityThread(int64 position, int size, uint8* data,
     72                                         const DataSource::ReadCB& read_cb) {
     73   DCHECK(utility_thread_checker_.CalledOnValidThread());
     74   CHECK_GE(total_size_, 0);
     75   CHECK_GE(position, 0);
     76   CHECK_GE(size, 0);
     77 
     78   // Cap position and size within bounds.
     79   position = std::min(position, total_size_);
     80   int64 clamped_size =
     81       std::min(static_cast<int64>(size), total_size_ - position);
     82 
     83   int64 request_id = ++next_request_id_;
     84 
     85   Request request;
     86   request.destination = data;
     87   request.callback = read_cb;
     88 
     89   pending_requests_[request_id] = request;
     90   content::UtilityThread::Get()->Send(new ChromeUtilityHostMsg_RequestBlobBytes(
     91       request_id, position, clamped_size));
     92 }
     93 
     94 void IPCDataSource::OnRequestBlobBytesFinished(int64 request_id,
     95                                                const std::string& bytes) {
     96   DCHECK(utility_thread_checker_.CalledOnValidThread());
     97   std::map<int64, Request>::iterator it = pending_requests_.find(request_id);
     98 
     99   if (it == pending_requests_.end())
    100     return;
    101 
    102   std::copy(bytes.begin(), bytes.end(), it->second.destination);
    103   it->second.callback.Run(bytes.size());
    104 
    105   pending_requests_.erase(it);
    106 }
    107 
    108 }  // namespace metadata
    109