OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "remoting/test/app_remoting_connected_client_tests.h" | |
6 | |
7 #include "base/json/json_reader.h" | |
8 #include "base/logging.h" | |
9 #include "base/run_loop.h" | |
10 #include "base/thread_task_runner_handle.h" | |
11 #include "base/values.h" | |
12 #include "remoting/protocol/host_stub.h" | |
13 #include "remoting/test/app_remoting_test_driver_environment.h" | |
14 #include "remoting/test/remote_application_data.h" | |
15 #include "remoting/test/test_chromoting_client.h" | |
16 #include "testing/gtest/include/gtest/gtest.h" | |
17 | |
18 namespace { | |
19 const int kDefaultDPI = 96; | |
20 const int kDefaultWidth = 1024; | |
21 const int kDefaultHeight = 768; | |
22 | |
23 void SimpleHostMessageReceivedHandler( | |
24 const std::string& target_message_type, | |
25 const std::string& target_message_data, | |
26 const base::Closure& done_closure, | |
27 bool* message_received, | |
28 const remoting::protocol::ExtensionMessage& message) { | |
29 if (message.type() == target_message_type && | |
30 message.data() == target_message_data) { | |
31 *message_received = true; | |
32 done_closure.Run(); | |
33 } | |
34 } | |
35 } | |
Wez
2015/03/16 22:19:08
nit: This is a non-trivial namespace declaration,
joedow
2015/03/18 20:13:08
Done.
| |
36 | |
37 namespace remoting { | |
38 namespace test { | |
39 | |
40 scoped_ptr<base::MessageLoopForIO> | |
41 AppRemotingConnectedClientTests::message_loop_; | |
Wez
2015/03/16 22:19:08
Does this line really need wrapping?
joedow
2015/03/18 20:13:08
It does :(
| |
42 scoped_ptr<TestChromotingClient> AppRemotingConnectedClientTests::client_; | |
43 bool AppRemotingConnectedClientTests::connection_is_ready_for_tests_; | |
44 | |
45 AppRemotingConnectedClientTests::AppRemotingConnectedClientTests() | |
46 : application_info_(GetRemoteApplicationInfoMap().at(GetParam())) { | |
47 } | |
48 | |
49 AppRemotingConnectedClientTests::~AppRemotingConnectedClientTests() { | |
50 } | |
51 | |
52 void AppRemotingConnectedClientTests::SetUp() { | |
53 // NOTE: Code here will be called immediately after the constructor (right | |
54 // before each test). | |
Wez
2015/03/16 22:19:09
Which of these properties is the important one to
joedow
2015/03/18 20:13:08
Done. Removed since I got rid of the static metho
| |
55 DCHECK(client_); | |
Wez
2015/03/16 22:19:09
No point DCHECKing a pointer immediately before de
joedow
2015/03/18 20:13:08
Done.
| |
56 client_->AddRemoteConnectionObserver(this); | |
57 | |
58 // If the client has not attempted to create a connection in the past, then | |
59 // start one now. | |
60 if (client_->connection_to_host_state() == | |
61 protocol::ConnectionToHost::INITIALIZING && | |
62 client_->connection_error_code() == protocol::OK) { | |
63 StartConnection(); | |
64 } | |
65 | |
66 if (!connection_is_ready_for_tests_) { | |
67 FAIL() << "Remote host connection could not be completed."; | |
68 client_->EndConnection(); | |
69 } | |
70 } | |
71 | |
72 void AppRemotingConnectedClientTests::TearDown() { | |
73 // NOTE: Code here will be called immediately after each test (right | |
74 // before the destructor). | |
75 DCHECK(client_); | |
Wez
2015/03/16 22:19:09
See above re DCHECK
joedow
2015/03/18 20:13:08
Done.
| |
76 client_->RemoveRemoteConnectionObserver(this); | |
77 } | |
78 | |
79 void AppRemotingConnectedClientTests::SetUpTestCase() { | |
80 // NOTE: Code here will be called before any instance constructors are called. | |
81 DCHECK(!message_loop_); | |
82 message_loop_.reset(new base::MessageLoopForIO); | |
83 | |
84 DCHECK(!client_); | |
85 client_.reset(new TestChromotingClient()); | |
86 } | |
87 | |
88 void AppRemotingConnectedClientTests::TearDownTestCase() { | |
89 // NOTE: Code here will be called immediately after all tests are done. | |
90 connection_is_ready_for_tests_ = false; | |
91 | |
92 // The client must be destroyed before the message loop as some of its | |
93 // members are destroyed via DeleteSoon on the message loop's TaskRunner. | |
Wez
2015/03/16 22:19:09
Unless you actually run the message-loop after des
joedow
2015/03/18 20:13:08
I had thought this was happening in the D'Tor for
| |
94 client_.reset(); | |
95 message_loop_.reset(); | |
96 } | |
97 | |
98 bool AppRemotingConnectedClientTests::VerifyResponseForSimpleHostMessage( | |
99 const std::string& message_request_title, | |
100 const std::string& message_response_title, | |
101 const std::string& message_payload, | |
102 const base::TimeDelta& max_wait_time) { | |
103 base::RunLoop run_loop; | |
104 bool message_received = false; | |
105 | |
106 done_closure_ = run_loop.QuitClosure(); | |
Wez
2015/03/16 22:19:08
Why are you saving the QuitClosure() for a RunLoop
joedow
2015/03/18 20:13:09
Done.
| |
107 host_message_received_callback_ = | |
108 base::Bind(&SimpleHostMessageReceivedHandler, message_response_title, | |
109 message_payload, done_closure_, &message_received); | |
110 | |
111 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(FROM_HERE, done_closure_, | |
112 max_wait_time); | |
Wez
2015/03/16 22:19:09
Cleaner to use a base::Timer for this?
joedow
2015/03/18 20:13:08
Done.
| |
113 | |
114 protocol::ExtensionMessage message; | |
115 message.set_type(message_request_title); | |
116 message.set_data(message_payload); | |
117 client_->host_stub()->DeliverClientMessage(message); | |
118 | |
119 run_loop.Run(); | |
120 host_message_received_callback_.Reset(); | |
121 | |
122 return message_received; | |
123 } | |
124 | |
125 void AppRemotingConnectedClientTests::StartConnection() { | |
126 DCHECK(client_); | |
127 | |
128 RemoteHostInfo remote_host_info; | |
129 remoting::test::AppRemotingSharedData->GetRemoteHostInfoForApplicationId( | |
130 application_info_.application_id, &remote_host_info); | |
131 | |
132 if (!remote_host_info.IsReadyForConnection()) { | |
133 LOG(ERROR) << "Remote Host is unavailable for connections."; | |
134 return; | |
135 } | |
136 | |
137 base::RunLoop run_loop; | |
138 | |
139 done_closure_ = run_loop.QuitClosure(); | |
Wez
2015/03/16 22:19:09
See above, re why this needs saving.
joedow
2015/03/18 20:13:08
Done.
| |
140 host_message_received_callback_ = | |
141 base::Bind(&AppRemotingConnectedClientTests::AddWindowMessageHandler, | |
142 base::Unretained(this), application_info_.main_window_name); | |
143 | |
144 // We will wait up to 30 seconds to complete the remote connection and for the | |
145 // main application window to become visible. | |
146 base::TimeDelta wait_time = base::TimeDelta::FromSeconds(30); | |
147 | |
148 // Post the QuitClosure with a max timeout to ensure we don't run forever. | |
149 // The QuitClosure will NOP if the connection was created before the timeout. | |
150 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(FROM_HERE, done_closure_, | |
151 wait_time); | |
Wez
2015/03/16 22:19:09
See above re base::Timer
joedow
2015/03/18 20:13:08
Done.
| |
152 | |
153 client_->StartConnection(AppRemotingSharedData->user_name(), | |
154 AppRemotingSharedData->access_token(), | |
155 remote_host_info); | |
156 | |
157 run_loop.Run(); | |
158 host_message_received_callback_.Reset(); | |
159 } | |
160 | |
161 void AppRemotingConnectedClientTests::ConnectionStateChanged( | |
Wez
2015/03/16 22:19:08
The RemoteConnectionObserver APIs are called by th
joedow
2015/03/18 20:13:08
Done.
| |
162 protocol::ConnectionToHost::State state, | |
163 protocol::ErrorCode error_code) { | |
164 if (state != protocol::ConnectionToHost::CONNECTED || | |
165 error_code != protocol::OK) { | |
166 connection_is_ready_for_tests_ = false; | |
167 } | |
168 | |
169 if (!done_closure_.is_null() && | |
170 (state == protocol::ConnectionToHost::CLOSED || | |
171 state == protocol::ConnectionToHost::FAILED || | |
172 error_code != protocol::OK)) { | |
Wez
2015/03/16 22:19:08
Why are these two connection-state checks differen
joedow
2015/03/18 20:13:08
Done.
| |
173 done_closure_.Run(); | |
174 } | |
175 } | |
176 | |
177 void AppRemotingConnectedClientTests::ConnectionReady(bool ready) { | |
Wez
2015/03/16 22:19:09
Under what circumstances will we receive this call
joedow
2015/03/18 20:13:08
Done.
| |
178 if (ready) { | |
179 SendClientConnectionDetailsToHost(); | |
180 } | |
181 } | |
182 | |
183 void AppRemotingConnectedClientTests::HostMessageReceived( | |
184 const protocol::ExtensionMessage& message) { | |
185 if (!host_message_received_callback_.is_null()) { | |
Wez
2015/03/16 22:19:09
Do we really want to ignore host messages received
joedow
2015/03/18 20:13:08
I've updated this method so that we can add defaul
| |
186 host_message_received_callback_.Run(message); | |
187 } | |
188 } | |
189 | |
190 void AppRemotingConnectedClientTests::SendClientConnectionDetailsToHost() { | |
191 // First send an access token which will be used for GDrive access. | |
192 protocol::ExtensionMessage message; | |
193 message.set_type("accessToken"); | |
194 message.set_data(AppRemotingSharedData->access_token()); | |
195 | |
196 DVLOG(1) << "Sending access token to host"; | |
197 client_->host_stub()->DeliverClientMessage(message); | |
198 | |
199 // next send the host a description of the client screen size. | |
Wez
2015/03/16 22:19:09
nit: Capitalization
joedow
2015/03/18 20:13:08
Done.
| |
200 protocol::ClientResolution client_resolution; | |
201 client_resolution.set_width(kDefaultWidth); | |
202 client_resolution.set_height(kDefaultHeight); | |
203 client_resolution.set_x_dpi(kDefaultDPI); | |
204 client_resolution.set_y_dpi(kDefaultDPI); | |
205 client_resolution.set_dips_width(kDefaultWidth); | |
206 client_resolution.set_dips_height(kDefaultHeight); | |
207 | |
208 DVLOG(1) << "Sending ClientResolution details to host"; | |
209 client_->host_stub()->NotifyClientResolution(client_resolution); | |
210 | |
211 // Finally send a message to start sending us video packets. | |
212 protocol::VideoControl video_control; | |
213 video_control.set_enable(true); | |
214 | |
Wez
2015/03/16 22:19:08
nit: No need for this blank line.
joedow
2015/03/18 20:13:08
Done.
| |
215 video_control.set_lossless_encode(true); | |
216 video_control.set_lossless_color(true); | |
Wez
2015/03/16 22:19:08
By default these are currently off (false).
joedow
2015/03/18 20:13:09
Done.
| |
217 | |
218 DVLOG(1) << "Sending enable VideoControl message to host"; | |
219 client_->host_stub()->ControlVideo(video_control); | |
220 } | |
221 | |
222 void AppRemotingConnectedClientTests::AddWindowMessageHandler( | |
223 const std::string& main_window_name, | |
Wez
2015/03/16 22:19:08
It seems strange to pass main_window_name in as a
joedow
2015/03/18 20:13:08
This is an artifact of some refactoring I did, you
| |
224 const remoting::protocol::ExtensionMessage& message) { | |
225 if (message.type() == "onWindowAdded") { | |
226 const base::DictionaryValue* message_data = nullptr; | |
227 scoped_ptr<base::Value> host_message( | |
228 base::JSONReader::Read(message.data())); | |
229 if (!host_message.get() || !host_message->GetAsDictionary(&message_data)) { | |
230 LOG(ERROR) << "Message received was not valid JSON."; | |
Wez
2015/03/16 22:19:08
Should we terminate the test (e.g. via |done_callb
joedow
2015/03/18 20:13:08
Done.
| |
231 return; | |
232 } | |
233 | |
234 std::string current_window_title; | |
235 message_data->GetString("title", ¤t_window_title); | |
236 | |
237 if (current_window_title == kHostProcessWindowTitle) { | |
238 LOG(WARNING) << "Host Process Window is visible, this may mean that the " | |
239 << "underlying application is in a bad state, YMMV."; | |
Wez
2015/03/16 22:19:08
I'm surprised that this is ever a state we get int
joedow
2015/03/18 20:13:08
I saw this last year when we had created a snapsho
| |
240 } | |
241 | |
242 std::string main_window_title = main_window_name; | |
243 if (current_window_title.find_first_of(main_window_title) == 0) { | |
244 connection_is_ready_for_tests_ = true; | |
245 | |
246 // Now that the main window is visible, give the app some time to settle | |
247 // before signaling that it is ready to run tests. | |
248 base::TimeDelta wait_time = base::TimeDelta::FromSeconds(5); | |
249 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
250 FROM_HERE, done_closure_, wait_time); | |
Wez
2015/03/16 22:19:08
Consider replacing this with a base::Timer member
joedow
2015/03/18 20:13:08
Done.
| |
251 } | |
252 } | |
Wez
2015/03/16 22:19:08
Do we want to completely ignore all other window m
joedow
2015/03/18 20:13:08
I'd like to keep this method simple for now, we ca
| |
253 } | |
254 | |
255 } // namespace test | |
256 } // namespace remoting | |
OLD | NEW |