background_command_transceiver.cc revision 80c739e10fd606b24e2656cad6e566c66bb218d4
1// Copyright 2015 The Chromium OS 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 "trunks/background_command_transceiver.h" 6 7#include <base/bind.h> 8#include <base/callback.h> 9#include <base/location.h> 10#include <base/logging.h> 11#include <base/message_loop/message_loop_proxy.h> 12#include <base/synchronization/waitable_event.h> 13 14namespace { 15 16// A simple callback useful when waiting for an asynchronous call. 17void AssignAndSignal(std::string* destination, 18 base::WaitableEvent* event, 19 const std::string& source) { 20 *destination = source; 21 event->Signal(); 22} 23 24// A callback which posts another |callback| to a given |message_loop|. 25void PostCallbackToMessageLoop( 26 const trunks::CommandTransceiver::ResponseCallback& callback, 27 scoped_refptr<base::MessageLoopProxy> message_loop, 28 const std::string& response) { 29 base::Closure task = base::Bind(callback, response); 30 message_loop->PostTask(FROM_HERE, task); 31} 32 33} // namespace 34 35namespace trunks { 36 37BackgroundCommandTransceiver::BackgroundCommandTransceiver( 38 CommandTransceiver* next_transceiver, 39 const scoped_refptr<base::SequencedTaskRunner>& task_runner) 40 : next_transceiver_(next_transceiver), 41 task_runner_(task_runner), 42 weak_factory_(this) {} 43 44BackgroundCommandTransceiver::~BackgroundCommandTransceiver() {} 45 46void BackgroundCommandTransceiver::SendCommand( 47 const std::string& command, 48 const ResponseCallback& callback) { 49 if (task_runner_.get()) { 50 ResponseCallback background_callback = base::Bind( 51 PostCallbackToMessageLoop, 52 callback, 53 base::MessageLoopProxy::current()); 54 // Use SendCommandTask instead of binding to next_transceiver_ directly to 55 // leverage weak pointer semantics. 56 base::Closure task = base::Bind( 57 &BackgroundCommandTransceiver::SendCommandTask, 58 GetWeakPtr(), 59 command, 60 background_callback); 61 task_runner_->PostNonNestableTask(FROM_HERE, task); 62 } else { 63 next_transceiver_->SendCommand(command, callback); 64 } 65} 66 67std::string BackgroundCommandTransceiver::SendCommandAndWait( 68 const std::string& command) { 69 if (task_runner_.get()) { 70 std::string response; 71 base::WaitableEvent response_ready(true, // manual_reset 72 false); // initially_signaled 73 ResponseCallback callback = 74 base::Bind(&AssignAndSignal, &response, &response_ready); 75 // Use SendCommandTask instead of binding to next_transceiver_ directly to 76 // leverage weak pointer semantics. 77 base::Closure task = base::Bind( 78 &BackgroundCommandTransceiver::SendCommandTask, 79 GetWeakPtr(), 80 command, 81 callback); 82 task_runner_->PostNonNestableTask(FROM_HERE, task); 83 response_ready.Wait(); 84 return response; 85 } else { 86 return next_transceiver_->SendCommandAndWait(command); 87 } 88} 89 90void BackgroundCommandTransceiver::SendCommandTask( 91 const std::string& command, 92 const ResponseCallback& callback) { 93 next_transceiver_->SendCommand(command, callback); 94} 95 96} // namespace trunks 97