OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/it2me_host_user_interface.h" | 5 #include "remoting/host/it2me_host_user_interface.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "remoting/host/chromoting_host.h" | 8 #include "remoting/host/chromoting_host.h" |
9 #include "remoting/host/chromoting_host_context.h" | 9 #include "remoting/host/chromoting_host_context.h" |
10 #include "remoting/host/continue_window.h" | 10 #include "remoting/host/continue_window.h" |
11 #include "remoting/host/disconnect_window.h" | 11 #include "remoting/host/disconnect_window.h" |
12 #include "remoting/host/local_input_monitor.h" | 12 #include "remoting/host/local_input_monitor.h" |
13 | 13 |
| 14 namespace { |
| 15 |
| 16 // Milliseconds before the continue window is shown. |
| 17 static const int kContinueWindowShowTimeoutMs = 10 * 60 * 1000; |
| 18 |
| 19 // Milliseconds before the continue window is automatically dismissed and |
| 20 // the connection is closed. |
| 21 static const int kContinueWindowHideTimeoutMs = 60 * 1000; |
| 22 |
| 23 } // namespace |
| 24 |
14 namespace remoting { | 25 namespace remoting { |
15 | 26 |
16 class It2MeHostUserInterface::TimerTask { | 27 class It2MeHostUserInterface::TimerTask { |
17 public: | 28 public: |
18 TimerTask(base::MessageLoopProxy* message_loop, | 29 TimerTask(base::MessageLoopProxy* message_loop, |
19 const base::Closure& task, | 30 const base::Closure& task, |
20 int delay_ms) | 31 int delay_ms) |
21 : thread_proxy_(message_loop) { | 32 : thread_proxy_(message_loop) { |
22 thread_proxy_.PostDelayedTask(FROM_HERE, task, delay_ms); | 33 thread_proxy_.PostDelayedTask(FROM_HERE, task, delay_ms); |
23 } | 34 } |
24 | 35 |
25 private: | 36 private: |
26 ScopedThreadProxy thread_proxy_; | 37 ScopedThreadProxy thread_proxy_; |
27 }; | 38 }; |
28 | 39 |
29 | 40 |
30 It2MeHostUserInterface::It2MeHostUserInterface(ChromotingHost* host, | 41 It2MeHostUserInterface::It2MeHostUserInterface(ChromotingHostContext* context) |
31 ChromotingHostContext* context) | 42 : HostUserInterface(context) { |
32 : host_(host), | |
33 context_(context), | |
34 is_monitoring_local_inputs_(false), | |
35 ui_thread_proxy_(context->ui_message_loop()) { | |
36 } | 43 } |
37 | 44 |
38 It2MeHostUserInterface::~It2MeHostUserInterface() { | 45 It2MeHostUserInterface::~It2MeHostUserInterface() { |
| 46 DCHECK(ui_message_loop()->BelongsToCurrentThread()); |
| 47 |
| 48 ShowContinueWindow(false); |
| 49 StartContinueWindowTimer(false); |
39 } | 50 } |
40 | 51 |
41 void It2MeHostUserInterface::Init() { | 52 void It2MeHostUserInterface::Start(ChromotingHost* host, |
42 InitFrom(DisconnectWindow::Create(), | 53 const base::Closure& disconnect_callback) { |
43 ContinueWindow::Create(), | 54 DCHECK(network_message_loop()->BelongsToCurrentThread()); |
44 LocalInputMonitor::Create()); | |
45 } | |
46 | 55 |
47 void It2MeHostUserInterface::InitFrom( | 56 HostUserInterface::Start(host, disconnect_callback); |
48 scoped_ptr<DisconnectWindow> disconnect_window, | 57 continue_window_ = ContinueWindow::Create(); |
49 scoped_ptr<ContinueWindow> continue_window, | |
50 scoped_ptr<LocalInputMonitor> monitor) { | |
51 disconnect_window_ = disconnect_window.Pass(); | |
52 continue_window_ = continue_window.Pass(); | |
53 local_input_monitor_ = monitor.Pass(); | |
54 host_->AddStatusObserver(this); | |
55 } | 58 } |
56 | 59 |
57 void It2MeHostUserInterface::OnClientAuthenticated(const std::string& jid) { | 60 void It2MeHostUserInterface::OnClientAuthenticated(const std::string& jid) { |
58 if (!authenticated_jid_.empty()) { | 61 if (!get_authenticated_jid().empty()) { |
59 // If we already authenticated another client then one of the | 62 // If we already authenticated another client then one of the |
60 // connections may be an attacker, so both are suspect and we have | 63 // connections may be an attacker, so both are suspect and we have |
61 // to reject the second connection and shutdown the host. | 64 // to reject the second connection and shutdown the host. |
62 host_->RejectAuthenticatingClient(); | 65 get_host()->RejectAuthenticatingClient(); |
63 context_->network_message_loop()->PostTask(FROM_HERE, base::Bind( | 66 network_message_loop()->PostTask(FROM_HERE, base::Bind( |
64 &ChromotingHost::Shutdown, host_, base::Closure())); | 67 &ChromotingHost::Shutdown, get_host(), base::Closure())); |
65 return; | 68 } else { |
| 69 HostUserInterface::OnClientAuthenticated(jid); |
66 } | 70 } |
67 | |
68 authenticated_jid_ = jid; | |
69 | |
70 std::string username = jid.substr(0, jid.find('/')); | |
71 ui_thread_proxy_.PostTask(FROM_HERE, base::Bind( | |
72 &It2MeHostUserInterface::ProcessOnClientAuthenticated, | |
73 base::Unretained(this), username)); | |
74 } | |
75 | |
76 void It2MeHostUserInterface::OnClientDisconnected(const std::string& jid) { | |
77 if (jid == authenticated_jid_) { | |
78 ui_thread_proxy_.PostTask(FROM_HERE, base::Bind( | |
79 &It2MeHostUserInterface::ProcessOnClientDisconnected, | |
80 base::Unretained(this))); | |
81 } | |
82 } | |
83 | |
84 void It2MeHostUserInterface::OnAccessDenied(const std::string& jid) { | |
85 } | |
86 | |
87 void It2MeHostUserInterface::OnShutdown() { | |
88 // Host status observers must be removed on the network thread, so | |
89 // it must happen here instead of in the destructor. | |
90 host_->RemoveStatusObserver(this); | |
91 } | |
92 | |
93 void It2MeHostUserInterface::Shutdown() { | |
94 DCHECK(context_->ui_message_loop()->BelongsToCurrentThread()); | |
95 | |
96 MonitorLocalInputs(false); | |
97 ShowDisconnectWindow(false, std::string()); | |
98 ShowContinueWindow(false); | |
99 StartContinueWindowTimer(false); | |
100 | |
101 ui_thread_proxy_.Detach(); | |
102 } | 71 } |
103 | 72 |
104 void It2MeHostUserInterface::ProcessOnClientAuthenticated( | 73 void It2MeHostUserInterface::ProcessOnClientAuthenticated( |
105 const std::string& username) { | 74 const std::string& username) { |
106 DCHECK(context_->ui_message_loop()->BelongsToCurrentThread()); | 75 DCHECK(ui_message_loop()->BelongsToCurrentThread()); |
107 | 76 |
108 MonitorLocalInputs(true); | 77 HostUserInterface::ProcessOnClientAuthenticated(username); |
109 ShowDisconnectWindow(true, username); | |
110 StartContinueWindowTimer(true); | 78 StartContinueWindowTimer(true); |
111 } | 79 } |
112 | 80 |
113 void It2MeHostUserInterface::ProcessOnClientDisconnected() { | 81 void It2MeHostUserInterface::ProcessOnClientDisconnected() { |
114 DCHECK(context_->ui_message_loop()->BelongsToCurrentThread()); | 82 DCHECK(ui_message_loop()->BelongsToCurrentThread()); |
115 | 83 |
116 MonitorLocalInputs(false); | 84 HostUserInterface::ProcessOnClientDisconnected(); |
117 ShowDisconnectWindow(false, std::string()); | |
118 ShowContinueWindow(false); | 85 ShowContinueWindow(false); |
119 StartContinueWindowTimer(false); | 86 StartContinueWindowTimer(false); |
120 } | 87 } |
121 | 88 |
122 void It2MeHostUserInterface::MonitorLocalInputs(bool enable) { | 89 void It2MeHostUserInterface::StartForTest( |
123 DCHECK(context_->ui_message_loop()->BelongsToCurrentThread()); | 90 ChromotingHost* host, |
124 | 91 const base::Closure& disconnect_callback, |
125 if (enable == is_monitoring_local_inputs_) | 92 scoped_ptr<DisconnectWindow> disconnect_window, |
126 return; | 93 scoped_ptr<ContinueWindow> continue_window, |
127 if (enable) { | 94 scoped_ptr<LocalInputMonitor> local_input_monitor) { |
128 local_input_monitor_->Start(host_); | 95 HostUserInterface::StartForTest(host, disconnect_callback, |
129 } else { | 96 disconnect_window.Pass(), |
130 local_input_monitor_->Stop(); | 97 local_input_monitor.Pass()); |
131 } | 98 continue_window_ = continue_window.Pass(); |
132 is_monitoring_local_inputs_ = enable; | |
133 } | 99 } |
134 | 100 |
135 void It2MeHostUserInterface::ShowDisconnectWindow(bool show, | 101 void It2MeHostUserInterface::ContinueSession(bool continue_session) { |
136 const std::string& username) { | 102 DCHECK(ui_message_loop()->BelongsToCurrentThread()); |
137 DCHECK(context_->ui_message_loop()->BelongsToCurrentThread()); | |
138 | 103 |
139 if (show) { | 104 if (continue_session) { |
140 disconnect_window_->Show(host_, username); | 105 get_host()->PauseSession(false); |
| 106 timer_task_.reset(); |
| 107 StartContinueWindowTimer(true); |
141 } else { | 108 } else { |
142 disconnect_window_->Hide(); | 109 DisconnectSession(); |
143 } | 110 } |
144 } | 111 } |
145 | 112 |
| 113 void It2MeHostUserInterface::OnContinueWindowTimer() { |
| 114 DCHECK(ui_message_loop()->BelongsToCurrentThread()); |
| 115 |
| 116 get_host()->PauseSession(true); |
| 117 ShowContinueWindow(true); |
| 118 |
| 119 timer_task_.reset(new TimerTask( |
| 120 ui_message_loop(), |
| 121 base::Bind(&It2MeHostUserInterface::OnShutdownHostTimer, |
| 122 base::Unretained(this)), |
| 123 kContinueWindowHideTimeoutMs)); |
| 124 } |
| 125 |
| 126 void It2MeHostUserInterface::OnShutdownHostTimer() { |
| 127 DCHECK(ui_message_loop()->BelongsToCurrentThread()); |
| 128 |
| 129 ShowContinueWindow(false); |
| 130 DisconnectSession(); |
| 131 } |
| 132 |
146 void It2MeHostUserInterface::ShowContinueWindow(bool show) { | 133 void It2MeHostUserInterface::ShowContinueWindow(bool show) { |
147 DCHECK(context_->ui_message_loop()->BelongsToCurrentThread()); | 134 DCHECK(ui_message_loop()->BelongsToCurrentThread()); |
148 | 135 |
149 if (show) { | 136 if (show) { |
150 continue_window_->Show(host_, base::Bind( | 137 continue_window_->Show(get_host(), base::Bind( |
151 &It2MeHostUserInterface::ContinueSession, base::Unretained(this))); | 138 &It2MeHostUserInterface::ContinueSession, base::Unretained(this))); |
152 } else { | 139 } else { |
153 continue_window_->Hide(); | 140 continue_window_->Hide(); |
154 } | 141 } |
155 } | 142 } |
156 | 143 |
157 void It2MeHostUserInterface::ContinueSession(bool continue_session) { | |
158 DCHECK(context_->ui_message_loop()->BelongsToCurrentThread()); | |
159 | |
160 if (continue_session) { | |
161 host_->PauseSession(false); | |
162 timer_task_.reset(); | |
163 StartContinueWindowTimer(true); | |
164 } else { | |
165 host_->Shutdown(base::Closure()); | |
166 } | |
167 } | |
168 | |
169 void It2MeHostUserInterface::StartContinueWindowTimer(bool start) { | 144 void It2MeHostUserInterface::StartContinueWindowTimer(bool start) { |
170 DCHECK(context_->ui_message_loop()->BelongsToCurrentThread()); | 145 DCHECK(ui_message_loop()->BelongsToCurrentThread()); |
171 | 146 |
172 if (start) { | 147 if (start) { |
173 timer_task_.reset(new TimerTask( | 148 timer_task_.reset(new TimerTask( |
174 context_->ui_message_loop(), | 149 ui_message_loop(), |
175 base::Bind(&It2MeHostUserInterface::OnContinueWindowTimer, | 150 base::Bind(&It2MeHostUserInterface::OnContinueWindowTimer, |
176 base::Unretained(this)), | 151 base::Unretained(this)), |
177 kContinueWindowShowTimeoutMs)); | 152 kContinueWindowShowTimeoutMs)); |
178 } else { | 153 } else { |
179 timer_task_.reset(); | 154 timer_task_.reset(); |
180 } | 155 } |
181 } | 156 } |
182 | 157 |
183 void It2MeHostUserInterface::OnContinueWindowTimer() { | |
184 DCHECK(context_->ui_message_loop()->BelongsToCurrentThread()); | |
185 | |
186 host_->PauseSession(true); | |
187 ShowContinueWindow(true); | |
188 | |
189 timer_task_.reset(new TimerTask( | |
190 context_->ui_message_loop(), | |
191 base::Bind(&It2MeHostUserInterface::OnShutdownHostTimer, | |
192 base::Unretained(this)), | |
193 kContinueWindowHideTimeoutMs)); | |
194 } | |
195 | |
196 void It2MeHostUserInterface::OnShutdownHostTimer() { | |
197 DCHECK(context_->ui_message_loop()->BelongsToCurrentThread()); | |
198 | |
199 ShowContinueWindow(false); | |
200 host_->Shutdown(base::Closure()); | |
201 } | |
202 | |
203 } // namespace remoting | 158 } // namespace remoting |
OLD | NEW |