|  | // Copyright 2013 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "remoting/host/host_window_proxy.h" | 
|  |  | 
|  | #include "base/bind.h" | 
|  | #include "base/location.h" | 
|  | #include "base/logging.h" | 
|  | #include "base/single_thread_task_runner.h" | 
|  | #include "remoting/host/client_session_control.h" | 
|  | #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h" | 
|  |  | 
|  | namespace remoting { | 
|  |  | 
|  | // Runs an instance of |HostWindow| on the |ui_task_runner_| thread. | 
|  | class HostWindowProxy::Core | 
|  | : public base::RefCountedThreadSafe<Core>, | 
|  | public ClientSessionControl { | 
|  | public: | 
|  | Core(scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, | 
|  | scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, | 
|  | scoped_ptr<HostWindow> host_window); | 
|  |  | 
|  | // Starts |host_window_| on the |ui_task_runner_| thread. | 
|  | void Start(const base::WeakPtr<ClientSessionControl>& client_session_control); | 
|  |  | 
|  | // Destroys |host_window_| on the |ui_task_runner_| thread. | 
|  | void Stop(); | 
|  |  | 
|  | private: | 
|  | friend class base::RefCountedThreadSafe<Core>; | 
|  | virtual ~Core(); | 
|  |  | 
|  | // Start() and Stop() equivalents called on the |ui_task_runner_| thread. | 
|  | void StartOnUiThread(const std::string& client_jid); | 
|  | void StopOnUiThread(); | 
|  |  | 
|  | // ClientSessionControl interface. | 
|  | virtual const std::string& client_jid() const OVERRIDE; | 
|  | virtual void DisconnectSession() OVERRIDE; | 
|  | virtual void OnLocalMouseMoved( | 
|  | const webrtc::DesktopVector& position) OVERRIDE; | 
|  | virtual void SetDisableInputs(bool disable_inputs) OVERRIDE; | 
|  | virtual void ResetVideoPipeline() OVERRIDE; | 
|  |  | 
|  | // Task runner on which public methods of this class must be called. | 
|  | scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_; | 
|  |  | 
|  | // Task runner on which |host_window_| is running. | 
|  | scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; | 
|  |  | 
|  | // Stores the client's JID so it can be read on the |ui_task_runner_| thread. | 
|  | std::string client_jid_; | 
|  |  | 
|  | // Used to notify the caller about the local user's actions on | 
|  | // the |caller_task_runner| thread. | 
|  | base::WeakPtr<ClientSessionControl> client_session_control_; | 
|  |  | 
|  | // The wrapped |HostWindow| instance running on the |ui_task_runner_| thread. | 
|  | scoped_ptr<HostWindow> host_window_; | 
|  |  | 
|  | // Used to create the control pointer passed to |host_window_|. | 
|  | base::WeakPtrFactory<ClientSessionControl> weak_factory_; | 
|  |  | 
|  | DISALLOW_COPY_AND_ASSIGN(Core); | 
|  | }; | 
|  |  | 
|  | HostWindowProxy::HostWindowProxy( | 
|  | scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, | 
|  | scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, | 
|  | scoped_ptr<HostWindow> host_window) { | 
|  | DCHECK(caller_task_runner->BelongsToCurrentThread()); | 
|  |  | 
|  | // Detach |host_window| from the calling thread so that |Core| could run it on | 
|  | // the |ui_task_runner_| thread. | 
|  | host_window->DetachFromThread(); | 
|  | core_ = new Core(caller_task_runner, ui_task_runner, host_window.Pass()); | 
|  | } | 
|  |  | 
|  | HostWindowProxy::~HostWindowProxy() { | 
|  | DCHECK(CalledOnValidThread()); | 
|  |  | 
|  | core_->Stop(); | 
|  | } | 
|  |  | 
|  | void HostWindowProxy::Start( | 
|  | const base::WeakPtr<ClientSessionControl>& client_session_control) { | 
|  | DCHECK(CalledOnValidThread()); | 
|  |  | 
|  | core_->Start(client_session_control); | 
|  | } | 
|  |  | 
|  | HostWindowProxy::Core::Core( | 
|  | scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, | 
|  | scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, | 
|  | scoped_ptr<HostWindow> host_window) | 
|  | : caller_task_runner_(caller_task_runner), | 
|  | ui_task_runner_(ui_task_runner), | 
|  | host_window_(host_window.Pass()), | 
|  | weak_factory_(this) { | 
|  | DCHECK(caller_task_runner->BelongsToCurrentThread()); | 
|  | } | 
|  |  | 
|  | void HostWindowProxy::Core::Start( | 
|  | const base::WeakPtr<ClientSessionControl>& client_session_control) { | 
|  | DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 
|  | DCHECK(!client_session_control_.get()); | 
|  | DCHECK(client_session_control.get()); | 
|  |  | 
|  | client_session_control_ = client_session_control; | 
|  | ui_task_runner_->PostTask( | 
|  | FROM_HERE, base::Bind(&Core::StartOnUiThread, this, | 
|  | client_session_control->client_jid())); | 
|  | } | 
|  |  | 
|  | void HostWindowProxy::Core::Stop() { | 
|  | DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 
|  |  | 
|  | ui_task_runner_->PostTask(FROM_HERE, base::Bind(&Core::StopOnUiThread, this)); | 
|  | } | 
|  |  | 
|  | HostWindowProxy::Core::~Core() { | 
|  | DCHECK(!host_window_); | 
|  | } | 
|  |  | 
|  | void HostWindowProxy::Core::StartOnUiThread(const std::string& client_jid) { | 
|  | DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 
|  | DCHECK(client_jid_.empty()); | 
|  |  | 
|  | client_jid_ = client_jid; | 
|  | host_window_->Start(weak_factory_.GetWeakPtr()); | 
|  | } | 
|  |  | 
|  | void HostWindowProxy::Core::StopOnUiThread() { | 
|  | DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 
|  |  | 
|  | host_window_.reset(); | 
|  | } | 
|  |  | 
|  | const std::string& HostWindowProxy::Core::client_jid() const { | 
|  | DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 
|  |  | 
|  | return client_jid_; | 
|  | } | 
|  |  | 
|  | void HostWindowProxy::Core::DisconnectSession() { | 
|  | if (!caller_task_runner_->BelongsToCurrentThread()) { | 
|  | caller_task_runner_->PostTask(FROM_HERE, | 
|  | base::Bind(&Core::DisconnectSession, this)); | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (client_session_control_.get()) | 
|  | client_session_control_->DisconnectSession(); | 
|  | } | 
|  |  | 
|  | void HostWindowProxy::Core::OnLocalMouseMoved( | 
|  | const webrtc::DesktopVector& position) { | 
|  | if (!caller_task_runner_->BelongsToCurrentThread()) { | 
|  | caller_task_runner_->PostTask( | 
|  | FROM_HERE, base::Bind(&Core::OnLocalMouseMoved, this, position)); | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (client_session_control_.get()) | 
|  | client_session_control_->OnLocalMouseMoved(position); | 
|  | } | 
|  |  | 
|  | void HostWindowProxy::Core::SetDisableInputs(bool disable_inputs) { | 
|  | if (!caller_task_runner_->BelongsToCurrentThread()) { | 
|  | caller_task_runner_->PostTask( | 
|  | FROM_HERE, base::Bind(&Core::SetDisableInputs, this, disable_inputs)); | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (client_session_control_.get()) | 
|  | client_session_control_->SetDisableInputs(disable_inputs); | 
|  | } | 
|  |  | 
|  | void HostWindowProxy::Core::ResetVideoPipeline() { | 
|  | // ResetVideoPipeline is only used by HostExtensionSession implementations. | 
|  | NOTREACHED(); | 
|  | } | 
|  |  | 
|  | }  // namespace remoting |