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