ExtensionInstallDialogView: fix scrolling behavior on Views (Win,Linux)
[chromium-blink-merge.git] / remoting / test / app_remoting_connection_helper.cc
blob83b92caa7cc19a90bd0d7c3a22673393392c4f04
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_connection_helper.h"
7 #include "base/callback_helpers.h"
8 #include "base/json/json_reader.h"
9 #include "base/logging.h"
10 #include "base/run_loop.h"
11 #include "base/thread_task_runner_handle.h"
12 #include "base/timer/timer.h"
13 #include "base/values.h"
14 #include "remoting/protocol/host_stub.h"
15 #include "remoting/test/app_remoting_test_driver_environment.h"
16 #include "remoting/test/remote_application_details.h"
17 #include "remoting/test/test_chromoting_client.h"
19 namespace {
20 const int kDefaultDPI = 96;
21 const int kDefaultWidth = 1024;
22 const int kDefaultHeight = 768;
24 const char kHostProcessWindowTitle[] = "Host Process";
25 } // namespace
27 namespace remoting {
28 namespace test {
30 AppRemotingConnectionHelper::AppRemotingConnectionHelper(
31 const RemoteApplicationDetails& application_details)
32 : application_details_(application_details),
33 connection_is_ready_for_tests_(false),
34 timer_(new base::Timer(true, false)) {
37 AppRemotingConnectionHelper::~AppRemotingConnectionHelper() {
38 // |client_| destroys some of its members via DeleteSoon on the message loop's
39 // TaskRunner so we need to run the loop until it has no more work to do.
40 client_->RemoveRemoteConnectionObserver(this);
41 client_.reset();
43 base::RunLoop().RunUntilIdle();
46 void AppRemotingConnectionHelper::Initialize(
47 scoped_ptr<TestChromotingClient> test_chromoting_client) {
48 client_ = test_chromoting_client.Pass();
49 client_->AddRemoteConnectionObserver(this);
52 void AppRemotingConnectionHelper::SetHostMessageReceivedCallback(
53 HostMessageReceivedCallback host_message_received_callback) {
54 host_message_received_callback_ = host_message_received_callback;
57 bool AppRemotingConnectionHelper::StartConnection() {
58 DCHECK(thread_checker_.CalledOnValidThread());
59 DCHECK(client_);
61 RemoteHostInfo remote_host_info;
62 remoting::test::AppRemotingSharedData->GetRemoteHostInfoForApplicationId(
63 application_details_.application_id, &remote_host_info);
65 if (!remote_host_info.IsReadyForConnection()) {
66 return false;
68 remoting::test::AppRemotingSharedData->AddHostToReleaseList(
69 application_details_.application_id, remote_host_info.host_id);
71 DCHECK(!run_loop_ || !run_loop_->running());
72 run_loop_.reset(new base::RunLoop());
74 // We will wait up to 30 seconds to complete the remote connection and for the
75 // main application window to become visible.
76 DCHECK(!timer_->IsRunning());
77 timer_->Start(FROM_HERE, base::TimeDelta::FromSeconds(30),
78 run_loop_->QuitClosure());
80 client_->StartConnection(AppRemotingSharedData->user_name(),
81 AppRemotingSharedData->access_token(),
82 remote_host_info);
84 run_loop_->Run();
85 timer_->Stop();
87 if (connection_is_ready_for_tests_) {
88 return true;
89 } else {
90 client_->EndConnection();
91 return false;
95 protocol::ClipboardStub* AppRemotingConnectionHelper::clipboard_forwarder() {
96 return client_->clipboard_forwarder();
99 protocol::HostStub* AppRemotingConnectionHelper::host_stub() {
100 return client_->host_stub();
103 protocol::InputStub* AppRemotingConnectionHelper::input_stub() {
104 return client_->input_stub();
107 void AppRemotingConnectionHelper::ConnectionStateChanged(
108 protocol::ConnectionToHost::State state,
109 protocol::ErrorCode error_code) {
110 DCHECK(thread_checker_.CalledOnValidThread());
112 // If the connection is closed or failed then mark the connection as closed
113 // and quit the current RunLoop if it exists.
114 if (state == protocol::ConnectionToHost::CLOSED ||
115 state == protocol::ConnectionToHost::FAILED ||
116 error_code != protocol::OK) {
117 connection_is_ready_for_tests_ = false;
119 if (run_loop_) {
120 run_loop_->Quit();
125 void AppRemotingConnectionHelper::ConnectionReady(bool ready) {
126 DCHECK(thread_checker_.CalledOnValidThread());
128 if (ready) {
129 SendClientConnectionDetailsToHost();
130 } else {
131 // We will only get called here with a false value for |ready| if the video
132 // renderer encounters an error.
133 connection_is_ready_for_tests_ = false;
135 if (run_loop_) {
136 run_loop_->Quit();
141 void AppRemotingConnectionHelper::HostMessageReceived(
142 const protocol::ExtensionMessage& message) {
143 DCHECK(thread_checker_.CalledOnValidThread());
145 // If a callback is not registered, then the message is passed to a default
146 // handler for the class based on the message type.
147 if (!host_message_received_callback_.is_null()) {
148 base::ResetAndReturn(&host_message_received_callback_).Run(message);
149 } else if (message.type() == "onWindowAdded") {
150 HandleOnWindowAddedMessage(message);
151 } else {
152 VLOG(2) << "HostMessage not handled by HostMessageReceived().";
153 VLOG(2) << "type: " << message.type();
154 VLOG(2) << "data: " << message.data();
158 void AppRemotingConnectionHelper::SendClientConnectionDetailsToHost() {
159 // First send an access token which will be used for Google Drive access.
160 protocol::ExtensionMessage message;
161 message.set_type("accessToken");
162 message.set_data(AppRemotingSharedData->access_token());
164 VLOG(1) << "Sending access token to host";
165 client_->host_stub()->DeliverClientMessage(message);
167 // Next send the host a description of the client screen size.
168 protocol::ClientResolution client_resolution;
169 client_resolution.set_width(kDefaultWidth);
170 client_resolution.set_height(kDefaultHeight);
171 client_resolution.set_x_dpi(kDefaultDPI);
172 client_resolution.set_y_dpi(kDefaultDPI);
173 client_resolution.set_dips_width(kDefaultWidth);
174 client_resolution.set_dips_height(kDefaultHeight);
176 VLOG(1) << "Sending ClientResolution details to host";
177 client_->host_stub()->NotifyClientResolution(client_resolution);
179 // Finally send a message to start sending us video packets.
180 protocol::VideoControl video_control;
181 video_control.set_enable(true);
183 VLOG(1) << "Sending enable VideoControl message to host";
184 client_->host_stub()->ControlVideo(video_control);
187 void AppRemotingConnectionHelper::HandleOnWindowAddedMessage(
188 const remoting::protocol::ExtensionMessage& message) {
189 DCHECK_EQ(message.type(), "onWindowAdded");
191 const base::DictionaryValue* message_data = nullptr;
192 scoped_ptr<base::Value> host_message = base::JSONReader::Read(message.data());
193 if (!host_message.get() || !host_message->GetAsDictionary(&message_data)) {
194 LOG(ERROR) << "onWindowAdded message received was not valid JSON.";
195 if (run_loop_) {
196 run_loop_->Quit();
198 return;
201 std::string current_window_title;
202 message_data->GetString("title", &current_window_title);
203 if (current_window_title == kHostProcessWindowTitle) {
204 LOG(ERROR) << "Host Process Window is visible, this likely means that the "
205 << "underlying application is in a bad state, YMMV.";
208 std::string main_window_title = application_details_.main_window_title;
209 if (current_window_title.find_first_of(main_window_title) == 0) {
210 connection_is_ready_for_tests_ = true;
212 if (timer_->IsRunning()) {
213 timer_->Stop();
216 DCHECK(run_loop_);
217 // Now that the main window is visible, give the app some time to settle
218 // before signaling that it is ready to run tests.
219 timer_->Start(FROM_HERE, base::TimeDelta::FromSeconds(2),
220 run_loop_->QuitClosure());
224 } // namespace test
225 } // namespace remoting