Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / remoting / test / app_remoting_test_driver_environment.cc
blob11ac9913cf89aee8851f152292904c4dc746cc01
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) {
33 AppRemotingTestDriverEnvironment::EnvironmentOptions::~EnvironmentOptions() {
36 AppRemotingTestDriverEnvironment::AppRemotingTestDriverEnvironment(
37 const EnvironmentOptions& options)
38 : user_name_(options.user_name),
39 service_environment_(options.service_environment),
40 release_hosts_when_done_(options.release_hosts_when_done),
41 refresh_token_file_path_(options.refresh_token_file_path),
42 test_access_token_fetcher_(nullptr),
43 test_app_remoting_report_issue_request_(nullptr),
44 test_refresh_token_store_(nullptr),
45 test_remote_host_info_fetcher_(nullptr) {
46 DCHECK(!user_name_.empty());
47 DCHECK(service_environment_ < kUnknownEnvironment);
49 PopulateApplicationNames();
50 PopulateApplicationDetailsMap();
53 AppRemotingTestDriverEnvironment::~AppRemotingTestDriverEnvironment() {
56 bool AppRemotingTestDriverEnvironment::Initialize(
57 const std::string& auth_code) {
58 if (!access_token_.empty()) {
59 return true;
62 if (!base::MessageLoop::current()) {
63 message_loop_.reset(new base::MessageLoopForIO);
66 // If a unit test has set |test_refresh_token_store_| then we should use it
67 // below. Note that we do not want to destroy the test object.
68 scoped_ptr<RefreshTokenStore> temporary_refresh_token_store;
69 RefreshTokenStore* refresh_token_store = test_refresh_token_store_;
70 if (!refresh_token_store) {
71 temporary_refresh_token_store =
72 RefreshTokenStore::OnDisk(user_name_, refresh_token_file_path_);
73 refresh_token_store = temporary_refresh_token_store.get();
76 // Check to see if we have a refresh token stored for this user.
77 refresh_token_ = refresh_token_store->FetchRefreshToken();
78 if (refresh_token_.empty()) {
79 // This isn't necessarily an error as this might be a first run scenario.
80 VLOG(2) << "No refresh token stored for " << user_name_;
82 if (auth_code.empty()) {
83 // No token and no Auth code means no service connectivity, bail!
84 LOG(ERROR) << "Cannot retrieve an access token without a stored refresh"
85 << " token on disk or an auth_code passed into the tool";
86 return false;
90 if (!RetrieveAccessToken(auth_code)) {
91 // If we cannot retrieve an access token, then nothing is going to work and
92 // we should let the caller know that our object is not ready to be used.
93 return false;
96 return true;
99 bool AppRemotingTestDriverEnvironment::RefreshAccessToken() {
100 DCHECK(!refresh_token_.empty());
102 // Empty auth code is used when refreshing.
103 return RetrieveAccessToken(std::string());
106 bool AppRemotingTestDriverEnvironment::GetRemoteHostInfoForApplicationId(
107 const std::string& application_id,
108 RemoteHostInfo* remote_host_info) {
109 DCHECK(!application_id.empty());
110 DCHECK(remote_host_info);
112 if (access_token_.empty()) {
113 LOG(ERROR) << "RemoteHostInfo requested without a valid access token. "
114 << "Ensure the environment object has been initialized.";
115 return false;
118 base::RunLoop run_loop;
120 RemoteHostInfoCallback remote_host_info_fetch_callback = base::Bind(
121 &AppRemotingTestDriverEnvironment::OnRemoteHostInfoRetrieved,
122 base::Unretained(this), run_loop.QuitClosure(), remote_host_info);
124 // If a unit test has set |test_remote_host_info_fetcher_| then we should use
125 // it below. Note that we do not want to destroy the test object at the end
126 // of the function which is why we have the dance below.
127 scoped_ptr<RemoteHostInfoFetcher> temporary_remote_host_info_fetcher;
128 RemoteHostInfoFetcher* remote_host_info_fetcher =
129 test_remote_host_info_fetcher_;
130 if (!remote_host_info_fetcher) {
131 temporary_remote_host_info_fetcher.reset(new RemoteHostInfoFetcher());
132 remote_host_info_fetcher = temporary_remote_host_info_fetcher.get();
135 remote_host_info_fetcher->RetrieveRemoteHostInfo(
136 application_id, access_token_, service_environment_,
137 remote_host_info_fetch_callback);
139 run_loop.Run();
141 return remote_host_info->IsReadyForConnection();
144 void AppRemotingTestDriverEnvironment::AddHostToReleaseList(
145 const std::string& application_id,
146 const std::string& host_id) {
147 if (!release_hosts_when_done_) {
148 return;
151 auto map_iterator = host_ids_to_release_.find(application_id);
152 if (map_iterator == host_ids_to_release_.end()) {
153 std::vector<std::string> host_id_list(1, host_id);
154 host_ids_to_release_.insert(std::make_pair(application_id, host_id_list));
155 } else {
156 std::vector<std::string>* host_ids = &map_iterator->second;
157 if (std::find(host_ids->begin(), host_ids->end(), host_id) ==
158 host_ids->end()) {
159 host_ids->push_back(host_id);
164 void AppRemotingTestDriverEnvironment::ShowHostAvailability() {
165 const char kHostAvailabilityFormatString[] = "%-25s%-35s%-10s";
167 LOG(INFO) << base::StringPrintf(kHostAvailabilityFormatString,
168 "Application Name", "Application ID",
169 "Status");
171 for (const auto& application_name : application_names_) {
172 const RemoteApplicationDetails& application_details =
173 GetDetailsFromAppName(application_name);
175 RemoteHostInfo remote_host_info;
176 GetRemoteHostInfoForApplicationId(application_details.application_id,
177 &remote_host_info);
179 std::string status;
180 RemoteHostStatus remote_host_status = remote_host_info.remote_host_status;
181 if (remote_host_status == kRemoteHostStatusReady) {
182 status = "Ready :)";
183 } else if (remote_host_status == kRemoteHostStatusPending) {
184 status = "Pending :|";
185 } else {
186 status = "Unknown :(";
189 LOG(INFO) << base::StringPrintf(
190 kHostAvailabilityFormatString, application_name.c_str(),
191 application_details.application_id.c_str(), status.c_str());
195 const RemoteApplicationDetails&
196 AppRemotingTestDriverEnvironment::GetDetailsFromAppName(
197 const std::string& application_name) {
198 const auto map_pair_iterator =
199 application_details_map_.find(application_name);
200 DCHECK(map_pair_iterator != application_details_map_.end());
202 return map_pair_iterator->second;
205 void AppRemotingTestDriverEnvironment::SetAccessTokenFetcherForTest(
206 AccessTokenFetcher* access_token_fetcher) {
207 DCHECK(access_token_fetcher);
209 test_access_token_fetcher_ = access_token_fetcher;
212 void AppRemotingTestDriverEnvironment::SetAppRemotingReportIssueRequestForTest(
213 AppRemotingReportIssueRequest* app_remoting_report_issue_request) {
214 DCHECK(app_remoting_report_issue_request);
216 test_app_remoting_report_issue_request_ = app_remoting_report_issue_request;
219 void AppRemotingTestDriverEnvironment::SetRefreshTokenStoreForTest(
220 RefreshTokenStore* refresh_token_store) {
221 DCHECK(refresh_token_store);
223 test_refresh_token_store_ = refresh_token_store;
226 void AppRemotingTestDriverEnvironment::SetRemoteHostInfoFetcherForTest(
227 RemoteHostInfoFetcher* remote_host_info_fetcher) {
228 DCHECK(remote_host_info_fetcher);
230 test_remote_host_info_fetcher_ = remote_host_info_fetcher;
233 void AppRemotingTestDriverEnvironment::TearDown() {
234 // If a unit test has set |test_app_remoting_report_issue_request_| then we
235 // should use it below. Note that we do not want to destroy the test object
236 // at the end of the function which is why we have the dance below.
237 scoped_ptr<AppRemotingReportIssueRequest> temporary_report_issue_request;
238 AppRemotingReportIssueRequest* report_issue_request =
239 test_app_remoting_report_issue_request_;
240 if (!report_issue_request) {
241 temporary_report_issue_request.reset(new AppRemotingReportIssueRequest());
242 report_issue_request = temporary_report_issue_request.get();
245 for (const auto& kvp : host_ids_to_release_) {
246 std::string application_id = kvp.first;
247 VLOG(1) << "Releasing hosts for application: " << application_id;
249 for (const auto& host_id : kvp.second) {
250 base::RunLoop run_loop;
252 VLOG(1) << " Releasing host: " << host_id;
253 bool request_started = report_issue_request->Start(
254 application_id, host_id, access_token_, service_environment_, true,
255 run_loop.QuitClosure());
257 if (request_started) {
258 run_loop.Run();
259 } else {
260 LOG(ERROR) << "Failed to send ReportIssueRequest for: "
261 << application_id << ", " << host_id;
265 temporary_report_issue_request.reset();
267 // Letting the MessageLoop tear down during the test destructor results in
268 // errors after test completion, when the MessageLoop dtor touches the
269 // registered AtExitManager. The AtExitManager is torn down before the test
270 // destructor is executed, so we tear down the MessageLoop here, while it is
271 // still valid.
272 message_loop_.reset();
275 bool AppRemotingTestDriverEnvironment::RetrieveAccessToken(
276 const std::string& auth_code) {
277 base::RunLoop run_loop;
279 access_token_.clear();
281 AccessTokenCallback access_token_callback =
282 base::Bind(&AppRemotingTestDriverEnvironment::OnAccessTokenRetrieved,
283 base::Unretained(this), run_loop.QuitClosure());
285 // If a unit test has set |test_access_token_fetcher_| then we should use it
286 // below. Note that we do not want to destroy the test object at the end of
287 // the function which is why we have the dance below.
288 scoped_ptr<AccessTokenFetcher> temporary_access_token_fetcher;
289 AccessTokenFetcher* access_token_fetcher = test_access_token_fetcher_;
290 if (!access_token_fetcher) {
291 temporary_access_token_fetcher.reset(new AccessTokenFetcher());
292 access_token_fetcher = temporary_access_token_fetcher.get();
295 if (!auth_code.empty()) {
296 // If the user passed in an authcode, then use it to retrieve an
297 // updated access/refresh token.
298 access_token_fetcher->GetAccessTokenFromAuthCode(auth_code,
299 access_token_callback);
300 } else {
301 DCHECK(!refresh_token_.empty());
303 access_token_fetcher->GetAccessTokenFromRefreshToken(refresh_token_,
304 access_token_callback);
307 run_loop.Run();
309 // If we were using an auth_code and received a valid refresh token,
310 // then we want to store it locally. If we had an auth code and did not
311 // receive a refresh token, then we should let the user know and exit.
312 if (!auth_code.empty()) {
313 if (!refresh_token_.empty()) {
314 // If a unit test has set |test_refresh_token_store_| then we should use
315 // it below. Note that we do not want to destroy the test object.
316 scoped_ptr<RefreshTokenStore> temporary_refresh_token_store;
317 RefreshTokenStore* refresh_token_store = test_refresh_token_store_;
318 if (!refresh_token_store) {
319 temporary_refresh_token_store =
320 RefreshTokenStore::OnDisk(user_name_, refresh_token_file_path_);
321 refresh_token_store = temporary_refresh_token_store.get();
324 if (!refresh_token_store->StoreRefreshToken(refresh_token_)) {
325 // If we failed to persist the refresh token, then we should let the
326 // user sort out the issue before continuing.
327 return false;
329 } else {
330 LOG(ERROR) << "Failed to use AUTH CODE to retrieve a refresh token.\n"
331 << "Was the one-time use AUTH CODE used more than once?";
332 return false;
336 if (access_token_.empty()) {
337 LOG(ERROR) << "Failed to retrieve access token.";
338 return false;
341 return true;
344 void AppRemotingTestDriverEnvironment::OnAccessTokenRetrieved(
345 base::Closure done_closure,
346 const std::string& access_token,
347 const std::string& refresh_token) {
348 access_token_ = access_token;
349 refresh_token_ = refresh_token;
351 done_closure.Run();
354 void AppRemotingTestDriverEnvironment::OnRemoteHostInfoRetrieved(
355 base::Closure done_closure,
356 RemoteHostInfo* remote_host_info,
357 const RemoteHostInfo& retrieved_remote_host_info) {
358 DCHECK(remote_host_info);
360 *remote_host_info = retrieved_remote_host_info;
362 done_closure.Run();
365 } // namespace test
366 } // namespace remoting