Home | History | Annotate | Download | only in host
      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 
     14 namespace remoting {
     15 
     16 // Runs an instance of |HostWindow| on the |ui_task_runner_| thread.
     17 class 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 
     68 HostWindowProxy::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 
     80 HostWindowProxy::~HostWindowProxy() {
     81   DCHECK(CalledOnValidThread());
     82 
     83   core_->Stop();
     84 }
     85 
     86 void HostWindowProxy::Start(
     87     const base::WeakPtr<ClientSessionControl>& client_session_control) {
     88   DCHECK(CalledOnValidThread());
     89 
     90   core_->Start(client_session_control);
     91 }
     92 
     93 HostWindowProxy::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 
    104 void 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 
    116 void HostWindowProxy::Core::Stop() {
    117   DCHECK(caller_task_runner_->BelongsToCurrentThread());
    118 
    119   ui_task_runner_->PostTask(FROM_HERE, base::Bind(&Core::StopOnUiThread, this));
    120 }
    121 
    122 HostWindowProxy::Core::~Core() {
    123   DCHECK(!host_window_);
    124 }
    125 
    126 void 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 
    134 void HostWindowProxy::Core::StopOnUiThread() {
    135   DCHECK(ui_task_runner_->BelongsToCurrentThread());
    136 
    137   host_window_.reset();
    138 }
    139 
    140 const std::string& HostWindowProxy::Core::client_jid() const {
    141   DCHECK(ui_task_runner_->BelongsToCurrentThread());
    142 
    143   return client_jid_;
    144 }
    145 
    146 void 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 
    157 void 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 
    169 void 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