| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "remoting/host/desktop_environment.h" | 5 #include "remoting/host/desktop_environment.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/compiler_specific.h" | 8 #include "base/compiler_specific.h" |
| 9 #include "remoting/host/capturer.h" | 9 #include "remoting/host/capturer.h" |
| 10 #include "remoting/host/chromoting_host.h" | 10 #include "remoting/host/chromoting_host.h" |
| 11 #include "remoting/host/chromoting_host_context.h" | 11 #include "remoting/host/chromoting_host_context.h" |
| 12 #include "remoting/host/continue_window.h" | 12 #include "remoting/host/continue_window.h" |
| 13 #include "remoting/host/curtain.h" | 13 #include "remoting/host/curtain.h" |
| 14 #include "remoting/host/disconnect_window.h" | 14 #include "remoting/host/disconnect_window.h" |
| 15 #include "remoting/host/event_executor.h" | 15 #include "remoting/host/event_executor.h" |
| 16 #include "remoting/host/local_input_monitor.h" | 16 #include "remoting/host/local_input_monitor.h" |
| 17 | 17 |
| 18 static const int kContinueWindowTimeoutMs = 10 * 60 * 1000; | 18 static const int kContinueWindowTimeoutMs = 10 * 60 * 1000; |
| 19 | 19 |
| 20 namespace remoting { | 20 namespace remoting { |
| 21 | 21 |
| 22 // UIThreadProxy proxies DesktopEnvironment method calls to the UI | 22 // UIThreadProxy proxies DesktopEnvironment method calls to the UI |
| 23 // thread. This is neccessary so that DesktopEnvironment can be | 23 // thread. This is neccessary so that DesktopEnvironment can be |
| 24 // deleted synchronously even while there are pending tasks on the | 24 // deleted synchronously even while there are pending tasks on the |
| 25 // message queue. | 25 // message queue. |
| 26 class UIThreadProxy : public base::RefCountedThreadSafe<UIThreadProxy> { | 26 class UIThreadProxy : public base::RefCountedThreadSafe<UIThreadProxy> { |
| 27 public: | 27 public: |
| 28 UIThreadProxy(ChromotingHostContext* context) | 28 UIThreadProxy(base::MessageLoopProxy* message_loop) |
| 29 : context_(context) { | 29 : message_loop_(message_loop) { |
| 30 } | 30 } |
| 31 | 31 |
| 32 void Detach() { | 32 void Detach() { |
| 33 DCHECK(context_->IsUIThread()); | 33 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 34 context_ = NULL; | 34 message_loop_ = NULL; |
| 35 } | 35 } |
| 36 | 36 |
| 37 void CallOnUIThread(const tracked_objects::Location& from_here, | 37 void CallOnUIThread(const tracked_objects::Location& from_here, |
| 38 const base::Closure& closure) { | 38 const base::Closure& closure) { |
| 39 if (context_) { | 39 scoped_refptr<base::MessageLoopProxy> message_loop = message_loop_; |
| 40 context_->PostTaskToUIThread(from_here, base::Bind( | 40 if (message_loop) { |
| 41 message_loop->PostTask(from_here, base::Bind( |
| 41 &UIThreadProxy::CallClosure, this, closure)); | 42 &UIThreadProxy::CallClosure, this, closure)); |
| 42 } | 43 } |
| 43 } | 44 } |
| 44 | 45 |
| 45 void CallOnUIThreadDelayed(const tracked_objects::Location& from_here, | 46 void CallOnUIThreadDelayed(const tracked_objects::Location& from_here, |
| 46 const base::Closure& closure, | 47 const base::Closure& closure, |
| 47 int delay_ms) { | 48 int delay_ms) { |
| 48 if (context_) { | 49 scoped_refptr<base::MessageLoopProxy> message_loop = message_loop_; |
| 49 context_->PostDelayedTaskToUIThread(from_here, base::Bind( | 50 if (message_loop) { |
| 51 message_loop->PostDelayedTask(from_here, base::Bind( |
| 50 &UIThreadProxy::CallClosure, this, closure), delay_ms); | 52 &UIThreadProxy::CallClosure, this, closure), delay_ms); |
| 51 } | 53 } |
| 52 } | 54 } |
| 53 | 55 |
| 54 private: | 56 private: |
| 55 friend class base::RefCountedThreadSafe<UIThreadProxy>; | 57 friend class base::RefCountedThreadSafe<UIThreadProxy>; |
| 56 | 58 |
| 57 virtual ~UIThreadProxy() { } | 59 virtual ~UIThreadProxy() { } |
| 58 | 60 |
| 59 void CallClosure(const base::Closure& closure) { | 61 void CallClosure(const base::Closure& closure) { |
| 60 if (context_) | 62 if (message_loop_) |
| 61 closure.Run(); | 63 closure.Run(); |
| 62 } | 64 } |
| 63 | 65 |
| 64 ChromotingHostContext* context_; | 66 scoped_refptr<base::MessageLoopProxy> message_loop_; |
| 65 | 67 |
| 66 DISALLOW_COPY_AND_ASSIGN(UIThreadProxy); | 68 DISALLOW_COPY_AND_ASSIGN(UIThreadProxy); |
| 67 }; | 69 }; |
| 68 | 70 |
| 69 // static | 71 // static |
| 70 DesktopEnvironment* DesktopEnvironment::Create(ChromotingHostContext* context) { | 72 DesktopEnvironment* DesktopEnvironment::Create(ChromotingHostContext* context) { |
| 71 Capturer* capturer = Capturer::Create(); | 73 Capturer* capturer = Capturer::Create(); |
| 72 EventExecutor* event_executor = | 74 EventExecutor* event_executor = |
| 73 EventExecutor::Create(context->desktop_message_loop(), capturer); | 75 EventExecutor::Create(context->desktop_message_loop(), capturer); |
| 74 Curtain* curtain = Curtain::Create(); | 76 Curtain* curtain = Curtain::Create(); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 91 : host_(NULL), | 93 : host_(NULL), |
| 92 context_(context), | 94 context_(context), |
| 93 capturer_(capturer), | 95 capturer_(capturer), |
| 94 event_executor_(event_executor), | 96 event_executor_(event_executor), |
| 95 curtain_(curtain), | 97 curtain_(curtain), |
| 96 disconnect_window_(disconnect_window), | 98 disconnect_window_(disconnect_window), |
| 97 continue_window_(continue_window), | 99 continue_window_(continue_window), |
| 98 local_input_monitor_(local_input_monitor), | 100 local_input_monitor_(local_input_monitor), |
| 99 is_monitoring_local_inputs_(false), | 101 is_monitoring_local_inputs_(false), |
| 100 continue_timer_started_(false), | 102 continue_timer_started_(false), |
| 101 proxy_(new UIThreadProxy(context)) { | 103 proxy_(new UIThreadProxy(context->ui_message_loop())) { |
| 102 } | 104 } |
| 103 | 105 |
| 104 DesktopEnvironment::~DesktopEnvironment() { | 106 DesktopEnvironment::~DesktopEnvironment() { |
| 105 } | 107 } |
| 106 | 108 |
| 107 void DesktopEnvironment::Shutdown() { | 109 void DesktopEnvironment::Shutdown() { |
| 108 DCHECK(context_->IsUIThread()); | 110 DCHECK(context_->ui_message_loop()->BelongsToCurrentThread()); |
| 109 | 111 |
| 110 MonitorLocalInputs(false); | 112 MonitorLocalInputs(false); |
| 111 ShowDisconnectWindow(false, std::string()); | 113 ShowDisconnectWindow(false, std::string()); |
| 112 ShowContinueWindow(false); | 114 ShowContinueWindow(false); |
| 113 StartContinueWindowTimer(false); | 115 StartContinueWindowTimer(false); |
| 114 | 116 |
| 115 proxy_->Detach(); | 117 proxy_->Detach(); |
| 116 } | 118 } |
| 117 | 119 |
| 118 void DesktopEnvironment::OnConnect(const std::string& username) { | 120 void DesktopEnvironment::OnConnect(const std::string& username) { |
| 119 proxy_->CallOnUIThread(FROM_HERE, base::Bind( | 121 proxy_->CallOnUIThread(FROM_HERE, base::Bind( |
| 120 &DesktopEnvironment::ProcessOnConnect, base::Unretained(this), username)); | 122 &DesktopEnvironment::ProcessOnConnect, base::Unretained(this), username)); |
| 121 } | 123 } |
| 122 | 124 |
| 123 void DesktopEnvironment::OnLastDisconnect() { | 125 void DesktopEnvironment::OnLastDisconnect() { |
| 124 proxy_->CallOnUIThread(FROM_HERE, base::Bind( | 126 proxy_->CallOnUIThread(FROM_HERE, base::Bind( |
| 125 &DesktopEnvironment::ProcessOnLastDisconnect, base::Unretained(this))); | 127 &DesktopEnvironment::ProcessOnLastDisconnect, base::Unretained(this))); |
| 126 } | 128 } |
| 127 | 129 |
| 128 void DesktopEnvironment::OnPause(bool pause) { | 130 void DesktopEnvironment::OnPause(bool pause) { |
| 129 proxy_->CallOnUIThread(FROM_HERE, base::Bind( | 131 proxy_->CallOnUIThread(FROM_HERE, base::Bind( |
| 130 &DesktopEnvironment::ProcessOnPause, base::Unretained(this), pause)); | 132 &DesktopEnvironment::ProcessOnPause, base::Unretained(this), pause)); |
| 131 } | 133 } |
| 132 | 134 |
| 133 void DesktopEnvironment::ProcessOnConnect(const std::string& username) { | 135 void DesktopEnvironment::ProcessOnConnect(const std::string& username) { |
| 134 DCHECK(context_->IsUIThread()); | 136 DCHECK(context_->ui_message_loop()->BelongsToCurrentThread()); |
| 135 | 137 |
| 136 MonitorLocalInputs(true); | 138 MonitorLocalInputs(true); |
| 137 ShowDisconnectWindow(true, username); | 139 ShowDisconnectWindow(true, username); |
| 138 StartContinueWindowTimer(true); | 140 StartContinueWindowTimer(true); |
| 139 } | 141 } |
| 140 | 142 |
| 141 void DesktopEnvironment::ProcessOnLastDisconnect() { | 143 void DesktopEnvironment::ProcessOnLastDisconnect() { |
| 142 DCHECK(context_->IsUIThread()); | 144 DCHECK(context_->ui_message_loop()->BelongsToCurrentThread()); |
| 143 | 145 |
| 144 MonitorLocalInputs(false); | 146 MonitorLocalInputs(false); |
| 145 ShowDisconnectWindow(false, std::string()); | 147 ShowDisconnectWindow(false, std::string()); |
| 146 ShowContinueWindow(false); | 148 ShowContinueWindow(false); |
| 147 StartContinueWindowTimer(false); | 149 StartContinueWindowTimer(false); |
| 148 } | 150 } |
| 149 | 151 |
| 150 void DesktopEnvironment::ProcessOnPause(bool pause) { | 152 void DesktopEnvironment::ProcessOnPause(bool pause) { |
| 151 StartContinueWindowTimer(!pause); | 153 StartContinueWindowTimer(!pause); |
| 152 } | 154 } |
| 153 | 155 |
| 154 void DesktopEnvironment::MonitorLocalInputs(bool enable) { | 156 void DesktopEnvironment::MonitorLocalInputs(bool enable) { |
| 155 DCHECK(context_->IsUIThread()); | 157 DCHECK(context_->ui_message_loop()->BelongsToCurrentThread()); |
| 156 | 158 |
| 157 if (enable == is_monitoring_local_inputs_) | 159 if (enable == is_monitoring_local_inputs_) |
| 158 return; | 160 return; |
| 159 if (enable) { | 161 if (enable) { |
| 160 local_input_monitor_->Start(host_); | 162 local_input_monitor_->Start(host_); |
| 161 } else { | 163 } else { |
| 162 local_input_monitor_->Stop(); | 164 local_input_monitor_->Stop(); |
| 163 } | 165 } |
| 164 is_monitoring_local_inputs_ = enable; | 166 is_monitoring_local_inputs_ = enable; |
| 165 } | 167 } |
| 166 | 168 |
| 167 void DesktopEnvironment::ShowDisconnectWindow(bool show, | 169 void DesktopEnvironment::ShowDisconnectWindow(bool show, |
| 168 const std::string& username) { | 170 const std::string& username) { |
| 169 DCHECK(context_->IsUIThread()); | 171 DCHECK(context_->ui_message_loop()->BelongsToCurrentThread()); |
| 170 | 172 |
| 171 if (show) { | 173 if (show) { |
| 172 disconnect_window_->Show(host_, username); | 174 disconnect_window_->Show(host_, username); |
| 173 } else { | 175 } else { |
| 174 disconnect_window_->Hide(); | 176 disconnect_window_->Hide(); |
| 175 } | 177 } |
| 176 } | 178 } |
| 177 | 179 |
| 178 void DesktopEnvironment::ShowContinueWindow(bool show) { | 180 void DesktopEnvironment::ShowContinueWindow(bool show) { |
| 179 DCHECK(context_->IsUIThread()); | 181 DCHECK(context_->ui_message_loop()->BelongsToCurrentThread()); |
| 180 | 182 |
| 181 if (show) { | 183 if (show) { |
| 182 continue_window_->Show(host_); | 184 continue_window_->Show(host_); |
| 183 } else { | 185 } else { |
| 184 continue_window_->Hide(); | 186 continue_window_->Hide(); |
| 185 } | 187 } |
| 186 } | 188 } |
| 187 | 189 |
| 188 void DesktopEnvironment::StartContinueWindowTimer(bool start) { | 190 void DesktopEnvironment::StartContinueWindowTimer(bool start) { |
| 189 DCHECK(context_->IsUIThread()); | 191 DCHECK(context_->ui_message_loop()->BelongsToCurrentThread()); |
| 190 | 192 |
| 191 if (start && ! continue_timer_started_) { | 193 if (start && ! continue_timer_started_) { |
| 192 continue_timer_target_time_ = base::Time::Now() + | 194 continue_timer_target_time_ = base::Time::Now() + |
| 193 base::TimeDelta::FromMilliseconds(kContinueWindowTimeoutMs); | 195 base::TimeDelta::FromMilliseconds(kContinueWindowTimeoutMs); |
| 194 proxy_->CallOnUIThreadDelayed( | 196 proxy_->CallOnUIThreadDelayed( |
| 195 FROM_HERE, base::Bind(&DesktopEnvironment::ContinueWindowTimerFunc, | 197 FROM_HERE, base::Bind(&DesktopEnvironment::ContinueWindowTimerFunc, |
| 196 base::Unretained(this)), | 198 base::Unretained(this)), |
| 197 kContinueWindowTimeoutMs); | 199 kContinueWindowTimeoutMs); |
| 198 } | 200 } |
| 199 | 201 |
| 200 continue_timer_started_ = start; | 202 continue_timer_started_ = start; |
| 201 } | 203 } |
| 202 | 204 |
| 203 void DesktopEnvironment::ContinueWindowTimerFunc() { | 205 void DesktopEnvironment::ContinueWindowTimerFunc() { |
| 204 DCHECK(context_->IsUIThread()); | 206 DCHECK(context_->ui_message_loop()->BelongsToCurrentThread()); |
| 205 | 207 |
| 206 // This function may be called prematurely if timer was stopped and | 208 // This function may be called prematurely if timer was stopped and |
| 207 // then started again. In that case we just ignore this call. | 209 // then started again. In that case we just ignore this call. |
| 208 if (continue_timer_target_time_ > base::Time::Now()) | 210 if (continue_timer_target_time_ > base::Time::Now()) |
| 209 return; | 211 return; |
| 210 | 212 |
| 211 host_->PauseSession(true); | 213 host_->PauseSession(true); |
| 212 ShowContinueWindow(true); | 214 ShowContinueWindow(true); |
| 213 } | 215 } |
| 214 | 216 |
| 215 | 217 |
| 216 } // namespace remoting | 218 } // namespace remoting |
| OLD | NEW |