| 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 // | |
| 27 // TODO(sergeyu): Merge this code with remoting::TaskThreadProxy. The | |
| 28 // problem solved by this class is very simular to the one solved by | |
| 29 // ScopedRunnableMethodFactory. The main difference is that this class | |
| 30 // is thread-safe. Change the interface to make it look more like | |
| 31 // ScopedRunnableMethodFactory and rename it to avoid confusion with | |
| 32 // MessageLoopProxy. | |
| 33 class UIThreadProxy : public base::RefCountedThreadSafe<UIThreadProxy> { | 26 class UIThreadProxy : public base::RefCountedThreadSafe<UIThreadProxy> { |
| 34 public: | 27 public: |
| 35 UIThreadProxy(base::MessageLoopProxy* message_loop) | 28 UIThreadProxy(ChromotingHostContext* context) |
| 36 : message_loop_(message_loop) { | 29 : context_(context) { |
| 37 } | 30 } |
| 38 | 31 |
| 39 // TODO(sergeyu): Rename this method. | |
| 40 void Detach() { | 32 void Detach() { |
| 41 DCHECK(message_loop_->BelongsToCurrentThread()); | 33 DCHECK(context_->IsUIThread()); |
| 42 message_loop_ = NULL; | 34 context_ = NULL; |
| 43 } | 35 } |
| 44 | 36 |
| 45 void CallOnUIThread(const tracked_objects::Location& from_here, | 37 void CallOnUIThread(const tracked_objects::Location& from_here, |
| 46 const base::Closure& closure) { | 38 const base::Closure& closure) { |
| 47 scoped_refptr<base::MessageLoopProxy> message_loop = message_loop_; | 39 if (context_) { |
| 48 if (message_loop) { | 40 context_->PostTaskToUIThread(from_here, base::Bind( |
| 49 message_loop->PostTask(from_here, base::Bind( | |
| 50 &UIThreadProxy::CallClosure, this, closure)); | 41 &UIThreadProxy::CallClosure, this, closure)); |
| 51 } | 42 } |
| 52 } | 43 } |
| 53 | 44 |
| 54 void CallOnUIThreadDelayed(const tracked_objects::Location& from_here, | 45 void CallOnUIThreadDelayed(const tracked_objects::Location& from_here, |
| 55 const base::Closure& closure, | 46 const base::Closure& closure, |
| 56 int delay_ms) { | 47 int delay_ms) { |
| 57 scoped_refptr<base::MessageLoopProxy> message_loop = message_loop_; | 48 if (context_) { |
| 58 if (message_loop) { | 49 context_->PostDelayedTaskToUIThread(from_here, base::Bind( |
| 59 message_loop->PostDelayedTask(from_here, base::Bind( | |
| 60 &UIThreadProxy::CallClosure, this, closure), delay_ms); | 50 &UIThreadProxy::CallClosure, this, closure), delay_ms); |
| 61 } | 51 } |
| 62 } | 52 } |
| 63 | 53 |
| 64 private: | 54 private: |
| 65 friend class base::RefCountedThreadSafe<UIThreadProxy>; | 55 friend class base::RefCountedThreadSafe<UIThreadProxy>; |
| 66 | 56 |
| 67 virtual ~UIThreadProxy() { } | 57 virtual ~UIThreadProxy() { } |
| 68 | 58 |
| 69 void CallClosure(const base::Closure& closure) { | 59 void CallClosure(const base::Closure& closure) { |
| 70 if (message_loop_) | 60 if (context_) |
| 71 closure.Run(); | 61 closure.Run(); |
| 72 } | 62 } |
| 73 | 63 |
| 74 scoped_refptr<base::MessageLoopProxy> message_loop_; | 64 ChromotingHostContext* context_; |
| 75 | 65 |
| 76 DISALLOW_COPY_AND_ASSIGN(UIThreadProxy); | 66 DISALLOW_COPY_AND_ASSIGN(UIThreadProxy); |
| 77 }; | 67 }; |
| 78 | 68 |
| 79 // static | 69 // static |
| 80 DesktopEnvironment* DesktopEnvironment::Create(ChromotingHostContext* context) { | 70 DesktopEnvironment* DesktopEnvironment::Create(ChromotingHostContext* context) { |
| 81 Capturer* capturer = Capturer::Create(); | 71 Capturer* capturer = Capturer::Create(); |
| 82 EventExecutor* event_executor = | 72 EventExecutor* event_executor = |
| 83 EventExecutor::Create(context->desktop_message_loop(), capturer); | 73 EventExecutor::Create(context->desktop_message_loop(), capturer); |
| 84 Curtain* curtain = Curtain::Create(); | 74 Curtain* curtain = Curtain::Create(); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 101 : host_(NULL), | 91 : host_(NULL), |
| 102 context_(context), | 92 context_(context), |
| 103 capturer_(capturer), | 93 capturer_(capturer), |
| 104 event_executor_(event_executor), | 94 event_executor_(event_executor), |
| 105 curtain_(curtain), | 95 curtain_(curtain), |
| 106 disconnect_window_(disconnect_window), | 96 disconnect_window_(disconnect_window), |
| 107 continue_window_(continue_window), | 97 continue_window_(continue_window), |
| 108 local_input_monitor_(local_input_monitor), | 98 local_input_monitor_(local_input_monitor), |
| 109 is_monitoring_local_inputs_(false), | 99 is_monitoring_local_inputs_(false), |
| 110 continue_timer_started_(false), | 100 continue_timer_started_(false), |
| 111 proxy_(new UIThreadProxy(context->ui_message_loop())) { | 101 proxy_(new UIThreadProxy(context)) { |
| 112 } | 102 } |
| 113 | 103 |
| 114 DesktopEnvironment::~DesktopEnvironment() { | 104 DesktopEnvironment::~DesktopEnvironment() { |
| 115 } | 105 } |
| 116 | 106 |
| 117 void DesktopEnvironment::Shutdown() { | 107 void DesktopEnvironment::Shutdown() { |
| 118 DCHECK(context_->ui_message_loop()->BelongsToCurrentThread()); | 108 DCHECK(context_->IsUIThread()); |
| 119 | 109 |
| 120 MonitorLocalInputs(false); | 110 MonitorLocalInputs(false); |
| 121 ShowDisconnectWindow(false, std::string()); | 111 ShowDisconnectWindow(false, std::string()); |
| 122 ShowContinueWindow(false); | 112 ShowContinueWindow(false); |
| 123 StartContinueWindowTimer(false); | 113 StartContinueWindowTimer(false); |
| 124 | 114 |
| 125 proxy_->Detach(); | 115 proxy_->Detach(); |
| 126 } | 116 } |
| 127 | 117 |
| 128 void DesktopEnvironment::OnConnect(const std::string& username) { | 118 void DesktopEnvironment::OnConnect(const std::string& username) { |
| 129 proxy_->CallOnUIThread(FROM_HERE, base::Bind( | 119 proxy_->CallOnUIThread(FROM_HERE, base::Bind( |
| 130 &DesktopEnvironment::ProcessOnConnect, base::Unretained(this), username)); | 120 &DesktopEnvironment::ProcessOnConnect, base::Unretained(this), username)); |
| 131 } | 121 } |
| 132 | 122 |
| 133 void DesktopEnvironment::OnLastDisconnect() { | 123 void DesktopEnvironment::OnLastDisconnect() { |
| 134 proxy_->CallOnUIThread(FROM_HERE, base::Bind( | 124 proxy_->CallOnUIThread(FROM_HERE, base::Bind( |
| 135 &DesktopEnvironment::ProcessOnLastDisconnect, base::Unretained(this))); | 125 &DesktopEnvironment::ProcessOnLastDisconnect, base::Unretained(this))); |
| 136 } | 126 } |
| 137 | 127 |
| 138 void DesktopEnvironment::OnPause(bool pause) { | 128 void DesktopEnvironment::OnPause(bool pause) { |
| 139 proxy_->CallOnUIThread(FROM_HERE, base::Bind( | 129 proxy_->CallOnUIThread(FROM_HERE, base::Bind( |
| 140 &DesktopEnvironment::ProcessOnPause, base::Unretained(this), pause)); | 130 &DesktopEnvironment::ProcessOnPause, base::Unretained(this), pause)); |
| 141 } | 131 } |
| 142 | 132 |
| 143 void DesktopEnvironment::ProcessOnConnect(const std::string& username) { | 133 void DesktopEnvironment::ProcessOnConnect(const std::string& username) { |
| 144 DCHECK(context_->ui_message_loop()->BelongsToCurrentThread()); | 134 DCHECK(context_->IsUIThread()); |
| 145 | 135 |
| 146 MonitorLocalInputs(true); | 136 MonitorLocalInputs(true); |
| 147 ShowDisconnectWindow(true, username); | 137 ShowDisconnectWindow(true, username); |
| 148 StartContinueWindowTimer(true); | 138 StartContinueWindowTimer(true); |
| 149 } | 139 } |
| 150 | 140 |
| 151 void DesktopEnvironment::ProcessOnLastDisconnect() { | 141 void DesktopEnvironment::ProcessOnLastDisconnect() { |
| 152 DCHECK(context_->ui_message_loop()->BelongsToCurrentThread()); | 142 DCHECK(context_->IsUIThread()); |
| 153 | 143 |
| 154 MonitorLocalInputs(false); | 144 MonitorLocalInputs(false); |
| 155 ShowDisconnectWindow(false, std::string()); | 145 ShowDisconnectWindow(false, std::string()); |
| 156 ShowContinueWindow(false); | 146 ShowContinueWindow(false); |
| 157 StartContinueWindowTimer(false); | 147 StartContinueWindowTimer(false); |
| 158 } | 148 } |
| 159 | 149 |
| 160 void DesktopEnvironment::ProcessOnPause(bool pause) { | 150 void DesktopEnvironment::ProcessOnPause(bool pause) { |
| 161 StartContinueWindowTimer(!pause); | 151 StartContinueWindowTimer(!pause); |
| 162 } | 152 } |
| 163 | 153 |
| 164 void DesktopEnvironment::MonitorLocalInputs(bool enable) { | 154 void DesktopEnvironment::MonitorLocalInputs(bool enable) { |
| 165 DCHECK(context_->ui_message_loop()->BelongsToCurrentThread()); | 155 DCHECK(context_->IsUIThread()); |
| 166 | 156 |
| 167 if (enable == is_monitoring_local_inputs_) | 157 if (enable == is_monitoring_local_inputs_) |
| 168 return; | 158 return; |
| 169 if (enable) { | 159 if (enable) { |
| 170 local_input_monitor_->Start(host_); | 160 local_input_monitor_->Start(host_); |
| 171 } else { | 161 } else { |
| 172 local_input_monitor_->Stop(); | 162 local_input_monitor_->Stop(); |
| 173 } | 163 } |
| 174 is_monitoring_local_inputs_ = enable; | 164 is_monitoring_local_inputs_ = enable; |
| 175 } | 165 } |
| 176 | 166 |
| 177 void DesktopEnvironment::ShowDisconnectWindow(bool show, | 167 void DesktopEnvironment::ShowDisconnectWindow(bool show, |
| 178 const std::string& username) { | 168 const std::string& username) { |
| 179 DCHECK(context_->ui_message_loop()->BelongsToCurrentThread()); | 169 DCHECK(context_->IsUIThread()); |
| 180 | 170 |
| 181 if (show) { | 171 if (show) { |
| 182 disconnect_window_->Show(host_, username); | 172 disconnect_window_->Show(host_, username); |
| 183 } else { | 173 } else { |
| 184 disconnect_window_->Hide(); | 174 disconnect_window_->Hide(); |
| 185 } | 175 } |
| 186 } | 176 } |
| 187 | 177 |
| 188 void DesktopEnvironment::ShowContinueWindow(bool show) { | 178 void DesktopEnvironment::ShowContinueWindow(bool show) { |
| 189 DCHECK(context_->ui_message_loop()->BelongsToCurrentThread()); | 179 DCHECK(context_->IsUIThread()); |
| 190 | 180 |
| 191 if (show) { | 181 if (show) { |
| 192 continue_window_->Show(host_); | 182 continue_window_->Show(host_); |
| 193 } else { | 183 } else { |
| 194 continue_window_->Hide(); | 184 continue_window_->Hide(); |
| 195 } | 185 } |
| 196 } | 186 } |
| 197 | 187 |
| 198 void DesktopEnvironment::StartContinueWindowTimer(bool start) { | 188 void DesktopEnvironment::StartContinueWindowTimer(bool start) { |
| 199 DCHECK(context_->ui_message_loop()->BelongsToCurrentThread()); | 189 DCHECK(context_->IsUIThread()); |
| 200 | 190 |
| 201 if (start && !continue_timer_started_) { | 191 if (start && !continue_timer_started_) { |
| 202 continue_timer_target_time_ = base::Time::Now() + | 192 continue_timer_target_time_ = base::Time::Now() + |
| 203 base::TimeDelta::FromMilliseconds(kContinueWindowTimeoutMs); | 193 base::TimeDelta::FromMilliseconds(kContinueWindowTimeoutMs); |
| 204 proxy_->CallOnUIThreadDelayed( | 194 proxy_->CallOnUIThreadDelayed( |
| 205 FROM_HERE, base::Bind(&DesktopEnvironment::ContinueWindowTimerFunc, | 195 FROM_HERE, base::Bind(&DesktopEnvironment::ContinueWindowTimerFunc, |
| 206 base::Unretained(this)), | 196 base::Unretained(this)), |
| 207 kContinueWindowTimeoutMs); | 197 kContinueWindowTimeoutMs); |
| 208 } | 198 } |
| 209 | 199 |
| 210 continue_timer_started_ = start; | 200 continue_timer_started_ = start; |
| 211 } | 201 } |
| 212 | 202 |
| 213 void DesktopEnvironment::ContinueWindowTimerFunc() { | 203 void DesktopEnvironment::ContinueWindowTimerFunc() { |
| 214 DCHECK(context_->ui_message_loop()->BelongsToCurrentThread()); | 204 DCHECK(context_->IsUIThread()); |
| 215 | 205 |
| 216 // This function may be called prematurely if timer was stopped and | 206 // This function may be called prematurely if timer was stopped and |
| 217 // then started again. In that case we just ignore this call. | 207 // then started again. In that case we just ignore this call. |
| 218 if (continue_timer_target_time_ > base::Time::Now()) | 208 if (continue_timer_target_time_ > base::Time::Now()) |
| 219 return; | 209 return; |
| 220 | 210 |
| 221 continue_timer_started_ = false; | 211 continue_timer_started_ = false; |
| 222 host_->PauseSession(true); | 212 host_->PauseSession(true); |
| 223 ShowContinueWindow(true); | 213 ShowContinueWindow(true); |
| 224 } | 214 } |
| 225 | 215 |
| 226 | 216 |
| 227 } // namespace remoting | 217 } // namespace remoting |
| OLD | NEW |