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 "remoting/host/host_window_proxy.h" 6 7#include "base/bind.h" 8#include "base/location.h" 9#include "base/logging.h" 10#include "base/single_thread_task_runner.h" 11#include "remoting/host/client_session_control.h" 12#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h" 13 14namespace remoting { 15 16// Runs an instance of |HostWindow| on the |ui_task_runner_| thread. 17class HostWindowProxy::Core 18 : public base::RefCountedThreadSafe<Core>, 19 public ClientSessionControl { 20 public: 21 Core(scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, 22 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, 23 scoped_ptr<HostWindow> host_window); 24 25 // Starts |host_window_| on the |ui_task_runner_| thread. 26 void Start(const base::WeakPtr<ClientSessionControl>& client_session_control); 27 28 // Destroys |host_window_| on the |ui_task_runner_| thread. 29 void Stop(); 30 31 private: 32 friend class base::RefCountedThreadSafe<Core>; 33 virtual ~Core(); 34 35 // Start() and Stop() equivalents called on the |ui_task_runner_| thread. 36 void StartOnUiThread(const std::string& client_jid); 37 void StopOnUiThread(); 38 39 // ClientSessionControl interface. 40 virtual const std::string& client_jid() const OVERRIDE; 41 virtual void DisconnectSession() OVERRIDE; 42 virtual void OnLocalMouseMoved( 43 const webrtc::DesktopVector& position) OVERRIDE; 44 virtual void SetDisableInputs(bool disable_inputs) OVERRIDE; 45 46 // Task runner on which public methods of this class must be called. 47 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_; 48 49 // Task runner on which |host_window_| is running. 50 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; 51 52 // Stores the client's JID so it can be read on the |ui_task_runner_| thread. 53 std::string client_jid_; 54 55 // Used to notify the caller about the local user's actions on 56 // the |caller_task_runner| thread. 57 base::WeakPtr<ClientSessionControl> client_session_control_; 58 59 // The wrapped |HostWindow| instance running on the |ui_task_runner_| thread. 60 scoped_ptr<HostWindow> host_window_; 61 62 // Used to create the control pointer passed to |host_window_|. 63 base::WeakPtrFactory<ClientSessionControl> weak_factory_; 64 65 DISALLOW_COPY_AND_ASSIGN(Core); 66}; 67 68HostWindowProxy::HostWindowProxy( 69 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, 70 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, 71 scoped_ptr<HostWindow> host_window) { 72 DCHECK(caller_task_runner->BelongsToCurrentThread()); 73 74 // Detach |host_window| from the calling thread so that |Core| could run it on 75 // the |ui_task_runner_| thread. 76 host_window->DetachFromThread(); 77 core_ = new Core(caller_task_runner, ui_task_runner, host_window.Pass()); 78} 79 80HostWindowProxy::~HostWindowProxy() { 81 DCHECK(CalledOnValidThread()); 82 83 core_->Stop(); 84} 85 86void HostWindowProxy::Start( 87 const base::WeakPtr<ClientSessionControl>& client_session_control) { 88 DCHECK(CalledOnValidThread()); 89 90 core_->Start(client_session_control); 91} 92 93HostWindowProxy::Core::Core( 94 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, 95 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, 96 scoped_ptr<HostWindow> host_window) 97 : caller_task_runner_(caller_task_runner), 98 ui_task_runner_(ui_task_runner), 99 host_window_(host_window.Pass()), 100 weak_factory_(this) { 101 DCHECK(caller_task_runner->BelongsToCurrentThread()); 102} 103 104void HostWindowProxy::Core::Start( 105 const base::WeakPtr<ClientSessionControl>& client_session_control) { 106 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 107 DCHECK(!client_session_control_.get()); 108 DCHECK(client_session_control.get()); 109 110 client_session_control_ = client_session_control; 111 ui_task_runner_->PostTask( 112 FROM_HERE, base::Bind(&Core::StartOnUiThread, this, 113 client_session_control->client_jid())); 114} 115 116void HostWindowProxy::Core::Stop() { 117 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 118 119 ui_task_runner_->PostTask(FROM_HERE, base::Bind(&Core::StopOnUiThread, this)); 120} 121 122HostWindowProxy::Core::~Core() { 123 DCHECK(!host_window_); 124} 125 126void HostWindowProxy::Core::StartOnUiThread(const std::string& client_jid) { 127 DCHECK(ui_task_runner_->BelongsToCurrentThread()); 128 DCHECK(client_jid_.empty()); 129 130 client_jid_ = client_jid; 131 host_window_->Start(weak_factory_.GetWeakPtr()); 132} 133 134void HostWindowProxy::Core::StopOnUiThread() { 135 DCHECK(ui_task_runner_->BelongsToCurrentThread()); 136 137 host_window_.reset(); 138} 139 140const std::string& HostWindowProxy::Core::client_jid() const { 141 DCHECK(ui_task_runner_->BelongsToCurrentThread()); 142 143 return client_jid_; 144} 145 146void HostWindowProxy::Core::DisconnectSession() { 147 if (!caller_task_runner_->BelongsToCurrentThread()) { 148 caller_task_runner_->PostTask(FROM_HERE, 149 base::Bind(&Core::DisconnectSession, this)); 150 return; 151 } 152 153 if (client_session_control_.get()) 154 client_session_control_->DisconnectSession(); 155} 156 157void HostWindowProxy::Core::OnLocalMouseMoved( 158 const webrtc::DesktopVector& position) { 159 if (!caller_task_runner_->BelongsToCurrentThread()) { 160 caller_task_runner_->PostTask( 161 FROM_HERE, base::Bind(&Core::OnLocalMouseMoved, this, position)); 162 return; 163 } 164 165 if (client_session_control_.get()) 166 client_session_control_->OnLocalMouseMoved(position); 167} 168 169void HostWindowProxy::Core::SetDisableInputs(bool disable_inputs) { 170 if (!caller_task_runner_->BelongsToCurrentThread()) { 171 caller_task_runner_->PostTask( 172 FROM_HERE, base::Bind(&Core::SetDisableInputs, this, disable_inputs)); 173 return; 174 } 175 176 if (client_session_control_.get()) 177 client_session_control_->SetDisableInputs(disable_inputs); 178} 179 180} // namespace remoting 181