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