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 |