Fix broken path in extensions/common/PRESUBMIT.py
[chromium-blink-merge.git] / remoting / test / app_remoting_connected_client_fixture.cc
blob090c22112f5549dffcd7c0912d0f01fbde4bd10b
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.
5 #include "remoting/test/app_remoting_connected_client_fixture.h"
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/timer/timer.h"
12 #include "base/values.h"
13 #include "remoting/protocol/host_stub.h"
14 #include "remoting/test/app_remoting_test_driver_environment.h"
15 #include "remoting/test/remote_application_details.h"
16 #include "remoting/test/test_chromoting_client.h"
18 namespace {
19 const int kDefaultDPI = 96;
20 const int kDefaultWidth = 1024;
21 const int kDefaultHeight = 768;
23 const char kHostProcessWindowTitle[] = "Host Process";
25 void SimpleHostMessageHandler(
26 const std::string& target_message_type,
27 const std::string& target_message_data,
28 const base::Closure& done_closure,
29 bool* message_received,
30 const remoting::protocol::ExtensionMessage& message) {
31 if (message.type() == target_message_type &&
32 message.data() == target_message_data) {
33 *message_received = true;
34 done_closure.Run();
37 } // namespace
39 namespace remoting {
40 namespace test {
42 AppRemotingConnectedClientFixture::AppRemotingConnectedClientFixture()
43 : application_details_(
44 AppRemotingSharedData->GetDetailsFromAppName(GetParam())),
45 connection_is_ready_for_tests_(false),
46 timer_(new base::Timer(true, false)) {
49 AppRemotingConnectedClientFixture::~AppRemotingConnectedClientFixture() {
52 void AppRemotingConnectedClientFixture::SetUp() {
53 client_.reset(new TestChromotingClient());
54 client_->AddRemoteConnectionObserver(this);
56 StartConnection();
58 if (!connection_is_ready_for_tests_) {
59 FAIL() << "Remote host connection could not be established.";
60 client_->EndConnection();
64 void AppRemotingConnectedClientFixture::TearDown() {
65 // |client_| destroys some of its members via DeleteSoon on the message loop's
66 // TaskRunner so we need to run the loop until it has no more work to do.
67 client_->RemoveRemoteConnectionObserver(this);
68 client_.reset();
70 base::RunLoop().RunUntilIdle();
73 bool AppRemotingConnectedClientFixture::VerifyResponseForSimpleHostMessage(
74 const std::string& message_request_title,
75 const std::string& message_response_title,
76 const std::string& message_payload,
77 const base::TimeDelta& max_wait_time) {
78 DCHECK(thread_checker_.CalledOnValidThread());
80 bool message_received = false;
82 DCHECK(!run_loop_ || !run_loop_->running());
83 run_loop_.reset(new base::RunLoop());
85 host_message_received_callback_ =
86 base::Bind(&SimpleHostMessageHandler, message_response_title,
87 message_payload, run_loop_->QuitClosure(), &message_received);
89 protocol::ExtensionMessage message;
90 message.set_type(message_request_title);
91 message.set_data(message_payload);
92 client_->host_stub()->DeliverClientMessage(message);
94 DCHECK(!timer_->IsRunning());
95 timer_->Start(FROM_HERE, max_wait_time, run_loop_->QuitClosure());
97 run_loop_->Run();
98 timer_->Stop();
100 host_message_received_callback_.Reset();
102 return message_received;
105 void AppRemotingConnectedClientFixture::StartConnection() {
106 DCHECK(thread_checker_.CalledOnValidThread());
108 RemoteHostInfo remote_host_info;
109 remoting::test::AppRemotingSharedData->GetRemoteHostInfoForApplicationId(
110 application_details_.application_id, &remote_host_info);
112 if (!remote_host_info.IsReadyForConnection()) {
113 LOG(ERROR) << "Remote Host is unavailable for connections.";
114 return;
117 DCHECK(!run_loop_ || !run_loop_->running());
118 run_loop_.reset(new base::RunLoop());
120 // We will wait up to 30 seconds to complete the remote connection and for the
121 // main application window to become visible.
122 DCHECK(!timer_->IsRunning());
123 timer_->Start(FROM_HERE, base::TimeDelta::FromSeconds(30),
124 run_loop_->QuitClosure());
126 client_->StartConnection(AppRemotingSharedData->user_name(),
127 AppRemotingSharedData->access_token(),
128 remote_host_info);
130 run_loop_->Run();
131 timer_->Stop();
134 void AppRemotingConnectedClientFixture::ConnectionStateChanged(
135 protocol::ConnectionToHost::State state,
136 protocol::ErrorCode error_code) {
137 DCHECK(thread_checker_.CalledOnValidThread());
139 // If the connection is closed or failed then mark the connection as closed
140 // and quit the current RunLoop if it exists.
141 if (state == protocol::ConnectionToHost::CLOSED ||
142 state == protocol::ConnectionToHost::FAILED ||
143 error_code != protocol::OK) {
144 connection_is_ready_for_tests_ = false;
146 if (run_loop_) {
147 run_loop_->Quit();
152 void AppRemotingConnectedClientFixture::ConnectionReady(bool ready) {
153 DCHECK(thread_checker_.CalledOnValidThread());
155 if (ready) {
156 SendClientConnectionDetailsToHost();
157 } else {
158 // We will only get called here with a false value for |ready| if the video
159 // renderer encounters an error.
160 connection_is_ready_for_tests_ = false;
162 if (run_loop_) {
163 run_loop_->Quit();
168 void AppRemotingConnectedClientFixture::HostMessageReceived(
169 const protocol::ExtensionMessage& message) {
170 DCHECK(thread_checker_.CalledOnValidThread());
172 // If a callback is not registered, then the message is passed to a default
173 // handler for the class based on the message type.
174 if (!host_message_received_callback_.is_null()) {
175 host_message_received_callback_.Run(message);
176 } else if (message.type() == "onWindowAdded") {
177 HandleOnWindowAddedMessage(message);
178 } else {
179 DVLOG(2) << "HostMessage not handled by HostMessageReceived().";
180 DVLOG(2) << "type: " << message.type();
181 DVLOG(2) << "data: " << message.data();
185 void AppRemotingConnectedClientFixture::SendClientConnectionDetailsToHost() {
186 // First send an access token which will be used for Google Drive access.
187 protocol::ExtensionMessage message;
188 message.set_type("accessToken");
189 message.set_data(AppRemotingSharedData->access_token());
191 DVLOG(1) << "Sending access token to host";
192 client_->host_stub()->DeliverClientMessage(message);
194 // Next send the host a description of the client screen size.
195 protocol::ClientResolution client_resolution;
196 client_resolution.set_width(kDefaultWidth);
197 client_resolution.set_height(kDefaultHeight);
198 client_resolution.set_x_dpi(kDefaultDPI);
199 client_resolution.set_y_dpi(kDefaultDPI);
200 client_resolution.set_dips_width(kDefaultWidth);
201 client_resolution.set_dips_height(kDefaultHeight);
203 DVLOG(1) << "Sending ClientResolution details to host";
204 client_->host_stub()->NotifyClientResolution(client_resolution);
206 // Finally send a message to start sending us video packets.
207 protocol::VideoControl video_control;
208 video_control.set_enable(true);
210 DVLOG(1) << "Sending enable VideoControl message to host";
211 client_->host_stub()->ControlVideo(video_control);
214 void AppRemotingConnectedClientFixture::HandleOnWindowAddedMessage(
215 const remoting::protocol::ExtensionMessage& message) {
216 DCHECK_EQ(message.type(), "onWindowAdded");
218 const base::DictionaryValue* message_data = nullptr;
219 scoped_ptr<base::Value> host_message(base::JSONReader::Read(message.data()));
220 if (!host_message.get() || !host_message->GetAsDictionary(&message_data)) {
221 LOG(ERROR) << "onWindowAdded message received was not valid JSON.";
222 if (run_loop_) {
223 run_loop_->Quit();
225 return;
228 std::string current_window_title;
229 message_data->GetString("title", &current_window_title);
230 if (current_window_title == kHostProcessWindowTitle) {
231 LOG(ERROR) << "Host Process Window is visible, this likely means that the "
232 << "underlying application is in a bad state, YMMV.";
235 std::string main_window_title = application_details_.main_window_title;
236 if (current_window_title.find_first_of(main_window_title) == 0) {
237 connection_is_ready_for_tests_ = true;
239 if (timer_->IsRunning()) {
240 timer_->Stop();
243 DCHECK(run_loop_);
244 // Now that the main window is visible, give the app some time to settle
245 // before signaling that it is ready to run tests.
246 timer_->Start(FROM_HERE, base::TimeDelta::FromSeconds(2),
247 run_loop_->QuitClosure());
251 } // namespace test
252 } // namespace remoting