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