Roll src/third_party/WebKit d9c6159:8139f33 (svn 201974:201975)
[chromium-blink-merge.git] / remoting / test / app_remoting_test_driver_environment.cc
blob9e8b2f59285bd3e41769b7a7d28a3cb253f6c2e3
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_test_driver_environment.h"
7 #include <map>
8 #include <string>
9 #include <vector>
11 #include "base/bind.h"
12 #include "base/callback_forward.h"
13 #include "base/logging.h"
14 #include "base/message_loop/message_loop.h"
15 #include "base/run_loop.h"
16 #include "base/strings/stringprintf.h"
17 #include "remoting/test/access_token_fetcher.h"
18 #include "remoting/test/app_remoting_report_issue_request.h"
19 #include "remoting/test/refresh_token_store.h"
20 #include "remoting/test/remote_host_info.h"
22 namespace remoting {
23 namespace test {
25 AppRemotingTestDriverEnvironment* AppRemotingSharedData;
27 AppRemotingTestDriverEnvironment::EnvironmentOptions::EnvironmentOptions()
28 : refresh_token_file_path(base::FilePath()),
29 service_environment(kUnknownEnvironment),
30 release_hosts_when_done(false) {}
32 AppRemotingTestDriverEnvironment::EnvironmentOptions::~EnvironmentOptions() {}
34 AppRemotingTestDriverEnvironment::AppRemotingTestDriverEnvironment(
35 const EnvironmentOptions& options)
36 : user_name_(options.user_name),
37 service_environment_(options.service_environment),
38 release_hosts_when_done_(options.release_hosts_when_done),
39 refresh_token_file_path_(options.refresh_token_file_path),
40 test_access_token_fetcher_(nullptr),
41 test_app_remoting_report_issue_request_(nullptr),
42 test_refresh_token_store_(nullptr),
43 test_remote_host_info_fetcher_(nullptr) {
44 DCHECK(!user_name_.empty());
45 DCHECK(service_environment_ < kUnknownEnvironment);
48 AppRemotingTestDriverEnvironment::~AppRemotingTestDriverEnvironment() {}
50 bool AppRemotingTestDriverEnvironment::Initialize(
51 const std::string& auth_code) {
52 if (!access_token_.empty()) {
53 return true;
56 if (!base::MessageLoop::current()) {
57 message_loop_.reset(new base::MessageLoopForIO);
60 // If a unit test has set |test_refresh_token_store_| then we should use it
61 // below. Note that we do not want to destroy the test object.
62 scoped_ptr<RefreshTokenStore> temporary_refresh_token_store;
63 RefreshTokenStore* refresh_token_store = test_refresh_token_store_;
64 if (!refresh_token_store) {
65 temporary_refresh_token_store =
66 RefreshTokenStore::OnDisk(user_name_, refresh_token_file_path_);
67 refresh_token_store = temporary_refresh_token_store.get();
70 // Check to see if we have a refresh token stored for this user.
71 refresh_token_ = refresh_token_store->FetchRefreshToken();
72 if (refresh_token_.empty()) {
73 // This isn't necessarily an error as this might be a first run scenario.
74 VLOG(2) << "No refresh token stored for " << user_name_;
76 if (auth_code.empty()) {
77 // No token and no Auth code means no service connectivity, bail!
78 LOG(ERROR) << "Cannot retrieve an access token without a stored refresh"
79 << " token on disk or an auth_code passed into the tool";
80 return false;
84 if (!RetrieveAccessToken(auth_code)) {
85 // If we cannot retrieve an access token, then nothing is going to work and
86 // we should let the caller know that our object is not ready to be used.
87 return false;
90 return true;
93 bool AppRemotingTestDriverEnvironment::RefreshAccessToken() {
94 DCHECK(!refresh_token_.empty());
96 // Empty auth code is used when refreshing.
97 return RetrieveAccessToken(std::string());
100 bool AppRemotingTestDriverEnvironment::GetRemoteHostInfoForApplicationId(
101 const std::string& application_id,
102 RemoteHostInfo* remote_host_info) {
103 DCHECK(!application_id.empty());
104 DCHECK(remote_host_info);
106 if (access_token_.empty()) {
107 LOG(ERROR) << "RemoteHostInfo requested without a valid access token. "
108 << "Ensure the environment object has been initialized.";
109 return false;
112 base::RunLoop run_loop;
114 RemoteHostInfoCallback remote_host_info_fetch_callback = base::Bind(
115 &AppRemotingTestDriverEnvironment::OnRemoteHostInfoRetrieved,
116 base::Unretained(this), run_loop.QuitClosure(), remote_host_info);
118 // If a unit test has set |test_remote_host_info_fetcher_| then we should use
119 // it below. Note that we do not want to destroy the test object at the end
120 // of the function which is why we have the dance below.
121 scoped_ptr<RemoteHostInfoFetcher> temporary_remote_host_info_fetcher;
122 RemoteHostInfoFetcher* remote_host_info_fetcher =
123 test_remote_host_info_fetcher_;
124 if (!remote_host_info_fetcher) {
125 temporary_remote_host_info_fetcher.reset(new RemoteHostInfoFetcher());
126 remote_host_info_fetcher = temporary_remote_host_info_fetcher.get();
129 remote_host_info_fetcher->RetrieveRemoteHostInfo(
130 application_id, access_token_, service_environment_,
131 remote_host_info_fetch_callback);
133 run_loop.Run();
135 return remote_host_info->IsReadyForConnection();
138 void AppRemotingTestDriverEnvironment::AddHostToReleaseList(
139 const std::string& application_id,
140 const std::string& host_id) {
141 if (!release_hosts_when_done_) {
142 return;
145 auto map_iterator = host_ids_to_release_.find(application_id);
146 if (map_iterator == host_ids_to_release_.end()) {
147 std::vector<std::string> host_id_list(1, host_id);
148 host_ids_to_release_.insert(std::make_pair(application_id, host_id_list));
149 } else {
150 std::vector<std::string>* host_ids = &map_iterator->second;
151 if (std::find(host_ids->begin(), host_ids->end(), host_id) ==
152 host_ids->end()) {
153 host_ids->push_back(host_id);
158 void AppRemotingTestDriverEnvironment::ShowHostAvailability() {
159 const char kHostAvailabilityFormatString[] = "%-25s%-35s%-10s";
161 LOG(INFO) << base::StringPrintf(kHostAvailabilityFormatString,
162 "Application Name", "Application ID",
163 "Status");
165 for (const auto& application_name : application_names_) {
166 const RemoteApplicationDetails& application_details =
167 GetDetailsFromAppName(application_name);
169 RemoteHostInfo remote_host_info;
170 GetRemoteHostInfoForApplicationId(application_details.application_id,
171 &remote_host_info);
173 std::string status;
174 RemoteHostStatus remote_host_status = remote_host_info.remote_host_status;
175 if (remote_host_status == kRemoteHostStatusReady) {
176 status = "Ready :)";
177 } else if (remote_host_status == kRemoteHostStatusPending) {
178 status = "Pending :|";
179 } else {
180 status = "Unknown :(";
183 LOG(INFO) << base::StringPrintf(
184 kHostAvailabilityFormatString, application_name.c_str(),
185 application_details.application_id.c_str(), status.c_str());
189 const RemoteApplicationDetails&
190 AppRemotingTestDriverEnvironment::GetDetailsFromAppName(
191 const std::string& application_name) {
192 const auto map_pair_iterator =
193 application_details_map_.find(application_name);
194 DCHECK(map_pair_iterator != application_details_map_.end());
196 return map_pair_iterator->second;
199 void AppRemotingTestDriverEnvironment::SetAccessTokenFetcherForTest(
200 AccessTokenFetcher* access_token_fetcher) {
201 DCHECK(access_token_fetcher);
203 test_access_token_fetcher_ = access_token_fetcher;
206 void AppRemotingTestDriverEnvironment::SetAppRemotingReportIssueRequestForTest(
207 AppRemotingReportIssueRequest* app_remoting_report_issue_request) {
208 DCHECK(app_remoting_report_issue_request);
210 test_app_remoting_report_issue_request_ = app_remoting_report_issue_request;
213 void AppRemotingTestDriverEnvironment::SetRefreshTokenStoreForTest(
214 RefreshTokenStore* refresh_token_store) {
215 DCHECK(refresh_token_store);
217 test_refresh_token_store_ = refresh_token_store;
220 void AppRemotingTestDriverEnvironment::SetRemoteHostInfoFetcherForTest(
221 RemoteHostInfoFetcher* remote_host_info_fetcher) {
222 DCHECK(remote_host_info_fetcher);
224 test_remote_host_info_fetcher_ = remote_host_info_fetcher;
227 void AppRemotingTestDriverEnvironment::TearDown() {
228 // If a unit test has set |test_app_remoting_report_issue_request_| then we
229 // should use it below. Note that we do not want to destroy the test object
230 // at the end of the function which is why we have the dance below.
231 scoped_ptr<AppRemotingReportIssueRequest> temporary_report_issue_request;
232 AppRemotingReportIssueRequest* report_issue_request =
233 test_app_remoting_report_issue_request_;
234 if (!report_issue_request) {
235 temporary_report_issue_request.reset(new AppRemotingReportIssueRequest());
236 report_issue_request = temporary_report_issue_request.get();
239 for (const auto& kvp : host_ids_to_release_) {
240 std::string application_id = kvp.first;
241 VLOG(1) << "Releasing hosts for application: " << application_id;
243 for (const auto& host_id : kvp.second) {
244 base::RunLoop run_loop;
246 VLOG(1) << " Releasing host: " << host_id;
247 bool request_started = report_issue_request->Start(
248 application_id, host_id, access_token_, service_environment_, true,
249 run_loop.QuitClosure());
251 if (request_started) {
252 run_loop.Run();
253 } else {
254 LOG(ERROR) << "Failed to send ReportIssueRequest for: "
255 << application_id << ", " << host_id;
259 temporary_report_issue_request.reset();
261 // Letting the MessageLoop tear down during the test destructor results in
262 // errors after test completion, when the MessageLoop dtor touches the
263 // registered AtExitManager. The AtExitManager is torn down before the test
264 // destructor is executed, so we tear down the MessageLoop here, while it is
265 // still valid.
266 message_loop_.reset();
269 bool AppRemotingTestDriverEnvironment::RetrieveAccessToken(
270 const std::string& auth_code) {
271 base::RunLoop run_loop;
273 access_token_.clear();
275 AccessTokenCallback access_token_callback =
276 base::Bind(&AppRemotingTestDriverEnvironment::OnAccessTokenRetrieved,
277 base::Unretained(this), run_loop.QuitClosure());
279 // If a unit test has set |test_access_token_fetcher_| then we should use it
280 // below. Note that we do not want to destroy the test object at the end of
281 // the function which is why we have the dance below.
282 scoped_ptr<AccessTokenFetcher> temporary_access_token_fetcher;
283 AccessTokenFetcher* access_token_fetcher = test_access_token_fetcher_;
284 if (!access_token_fetcher) {
285 temporary_access_token_fetcher.reset(new AccessTokenFetcher());
286 access_token_fetcher = temporary_access_token_fetcher.get();
289 if (!auth_code.empty()) {
290 // If the user passed in an authcode, then use it to retrieve an
291 // updated access/refresh token.
292 access_token_fetcher->GetAccessTokenFromAuthCode(auth_code,
293 access_token_callback);
294 } else {
295 DCHECK(!refresh_token_.empty());
297 access_token_fetcher->GetAccessTokenFromRefreshToken(refresh_token_,
298 access_token_callback);
301 run_loop.Run();
303 // If we were using an auth_code and received a valid refresh token,
304 // then we want to store it locally. If we had an auth code and did not
305 // receive a refresh token, then we should let the user know and exit.
306 if (!auth_code.empty()) {
307 if (!refresh_token_.empty()) {
308 // If a unit test has set |test_refresh_token_store_| then we should use
309 // it below. Note that we do not want to destroy the test object.
310 scoped_ptr<RefreshTokenStore> temporary_refresh_token_store;
311 RefreshTokenStore* refresh_token_store = test_refresh_token_store_;
312 if (!refresh_token_store) {
313 temporary_refresh_token_store =
314 RefreshTokenStore::OnDisk(user_name_, refresh_token_file_path_);
315 refresh_token_store = temporary_refresh_token_store.get();
318 if (!refresh_token_store->StoreRefreshToken(refresh_token_)) {
319 // If we failed to persist the refresh token, then we should let the
320 // user sort out the issue before continuing.
321 return false;
323 } else {
324 LOG(ERROR) << "Failed to use AUTH CODE to retrieve a refresh token.\n"
325 << "Was the one-time use AUTH CODE used more than once?";
326 return false;
330 if (access_token_.empty()) {
331 LOG(ERROR) << "Failed to retrieve access token.";
332 return false;
335 return true;
338 void AppRemotingTestDriverEnvironment::OnAccessTokenRetrieved(
339 base::Closure done_closure,
340 const std::string& access_token,
341 const std::string& refresh_token) {
342 access_token_ = access_token;
343 refresh_token_ = refresh_token;
345 done_closure.Run();
348 void AppRemotingTestDriverEnvironment::OnRemoteHostInfoRetrieved(
349 base::Closure done_closure,
350 RemoteHostInfo* remote_host_info,
351 const RemoteHostInfo& retrieved_remote_host_info) {
352 DCHECK(remote_host_info);
354 *remote_host_info = retrieved_remote_host_info;
356 done_closure.Run();
359 } // namespace test
360 } // namespace remoting