| Index: remoting/test/chromoting_test_driver_environment.cc
|
| diff --git a/remoting/test/chromoting_test_driver_environment.cc b/remoting/test/chromoting_test_driver_environment.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..83c506cca46a7a948067cebcdbaef2230a9f249b
|
| --- /dev/null
|
| +++ b/remoting/test/chromoting_test_driver_environment.cc
|
| @@ -0,0 +1,269 @@
|
| +// Copyright 2015 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "remoting/test/chromoting_test_driver_environment.h"
|
| +
|
| +#include <string>
|
| +#include <vector>
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/logging.h"
|
| +#include "base/message_loop/message_loop.h"
|
| +#include "base/run_loop.h"
|
| +#include "base/strings/stringprintf.h"
|
| +#include "remoting/test/access_token_fetcher.h"
|
| +#include "remoting/test/host_info.h"
|
| +#include "remoting/test/host_list_fetcher.h"
|
| +#include "remoting/test/refresh_token_store.h"
|
| +
|
| +namespace remoting {
|
| +namespace test {
|
| +
|
| +ChromotingTestDriverEnvironment::EnvironmentOptions::EnvironmentOptions() {
|
| +}
|
| +
|
| +ChromotingTestDriverEnvironment::EnvironmentOptions::~EnvironmentOptions() {
|
| +}
|
| +
|
| +ChromotingTestDriverEnvironment::ChromotingTestDriverEnvironment(
|
| + const EnvironmentOptions& options)
|
| + : host_name_(options.host_name),
|
| + user_name_(options.user_name),
|
| + refresh_token_file_path_(options.refresh_token_file_path),
|
| + test_access_token_fetcher_(nullptr),
|
| + test_refresh_token_store_(nullptr),
|
| + test_host_list_fetcher_(nullptr) {
|
| + DCHECK(!user_name_.empty());
|
| + DCHECK(!host_name_.empty());
|
| +}
|
| +
|
| +ChromotingTestDriverEnvironment::~ChromotingTestDriverEnvironment() {
|
| +}
|
| +
|
| +bool ChromotingTestDriverEnvironment::Initialize(
|
| + const std::string& auth_code) {
|
| + if (!access_token_.empty()) {
|
| + return true;
|
| + }
|
| +
|
| + if (!base::MessageLoop::current()) {
|
| + message_loop_.reset(new base::MessageLoopForIO);
|
| + }
|
| +
|
| + // If a unit test has set |test_refresh_token_store_| then we should use it
|
| + // below. Note that we do not want to destroy the test object.
|
| + scoped_ptr<RefreshTokenStore> temporary_refresh_token_store;
|
| + RefreshTokenStore* refresh_token_store = test_refresh_token_store_;
|
| + if (!refresh_token_store) {
|
| + temporary_refresh_token_store =
|
| + RefreshTokenStore::OnDisk(user_name_, refresh_token_file_path_);
|
| + refresh_token_store = temporary_refresh_token_store.get();
|
| + }
|
| +
|
| + // Check to see if we have a refresh token stored for this user.
|
| + refresh_token_ = refresh_token_store->FetchRefreshToken();
|
| + if (refresh_token_.empty()) {
|
| + // This isn't necessarily an error as this might be a first run scenario.
|
| + VLOG(2) << "No refresh token stored for " << user_name_;
|
| +
|
| + if (auth_code.empty()) {
|
| + // No token and no Auth code means no service connectivity, bail!
|
| + LOG(ERROR) << "Cannot retrieve an access token without a stored refresh"
|
| + << " token on disk or an auth_code passed into the tool";
|
| + return false;
|
| + }
|
| + }
|
| +
|
| + if (!RetrieveAccessToken(auth_code) || !RetrieveHostList()) {
|
| + // If we cannot retrieve an access token or a host list, then nothing is
|
| + // going to work. We should let the caller know that our object is not ready
|
| + // to be used.
|
| + return false;
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +
|
| +void ChromotingTestDriverEnvironment::DisplayHostList() {
|
| + const char kHostAvailabilityFormatString[] = "%-45s%-15s%-35s";
|
| +
|
| + LOG(INFO) << base::StringPrintf(kHostAvailabilityFormatString,
|
| + "Host Name", "Host Status", "Host JID");
|
| + LOG(INFO) << base::StringPrintf(kHostAvailabilityFormatString,
|
| + "---------", "-----------", "--------");
|
| +
|
| + std::string status;
|
| + for (const HostInfo& host_info : host_list_) {
|
| + HostStatus host_status = host_info.status;
|
| + if (host_status == kHostStatusOnline) {
|
| + status = "ONLINE";
|
| + } else if (host_status == kHostStatusOffline) {
|
| + status = "OFFLINE";
|
| + } else {
|
| + status = "UNKNOWN";
|
| + }
|
| +
|
| + LOG(INFO) << base::StringPrintf(
|
| + kHostAvailabilityFormatString, host_info.host_name.c_str(),
|
| + status.c_str(), host_info.host_jid.c_str());
|
| + }
|
| +}
|
| +
|
| +void ChromotingTestDriverEnvironment::SetAccessTokenFetcherForTest(
|
| + AccessTokenFetcher* access_token_fetcher) {
|
| + DCHECK(access_token_fetcher);
|
| +
|
| + test_access_token_fetcher_ = access_token_fetcher;
|
| +}
|
| +
|
| +void ChromotingTestDriverEnvironment::SetRefreshTokenStoreForTest(
|
| + RefreshTokenStore* refresh_token_store) {
|
| + DCHECK(refresh_token_store);
|
| +
|
| + test_refresh_token_store_ = refresh_token_store;
|
| +}
|
| +
|
| +void ChromotingTestDriverEnvironment::SetHostListFetcherForTest(
|
| + HostListFetcher* host_list_fetcher) {
|
| + DCHECK(host_list_fetcher);
|
| +
|
| + test_host_list_fetcher_ = host_list_fetcher;
|
| +}
|
| +
|
| +void ChromotingTestDriverEnvironment::TearDown() {
|
| + // Letting the MessageLoop tear down during the test destructor results in
|
| + // errors after test completion, when the MessageLoop dtor touches the
|
| + // registered AtExitManager. The AtExitManager is torn down before the test
|
| + // destructor is executed, so we tear down the MessageLoop here, while it is
|
| + // still valid.
|
| + message_loop_.reset();
|
| +}
|
| +
|
| +bool ChromotingTestDriverEnvironment::RetrieveAccessToken(
|
| + const std::string& auth_code) {
|
| + base::RunLoop run_loop;
|
| +
|
| + access_token_.clear();
|
| +
|
| + AccessTokenCallback access_token_callback =
|
| + base::Bind(&ChromotingTestDriverEnvironment::OnAccessTokenRetrieved,
|
| + base::Unretained(this), run_loop.QuitClosure());
|
| +
|
| + // If a unit test has set |test_access_token_fetcher_| then we should use it
|
| + // below. Note that we do not want to destroy the test object at the end of
|
| + // the function which is why we have the dance below.
|
| + scoped_ptr<AccessTokenFetcher> temporary_access_token_fetcher;
|
| + AccessTokenFetcher* access_token_fetcher = test_access_token_fetcher_;
|
| + if (!access_token_fetcher) {
|
| + temporary_access_token_fetcher.reset(new AccessTokenFetcher());
|
| + access_token_fetcher = temporary_access_token_fetcher.get();
|
| + }
|
| +
|
| + if (!auth_code.empty()) {
|
| + // If the user passed in an authcode, then use it to retrieve an
|
| + // updated access/refresh token.
|
| + access_token_fetcher->GetAccessTokenFromAuthCode(auth_code,
|
| + access_token_callback);
|
| + } else {
|
| + DCHECK(!refresh_token_.empty());
|
| +
|
| + access_token_fetcher->GetAccessTokenFromRefreshToken(refresh_token_,
|
| + access_token_callback);
|
| + }
|
| +
|
| + run_loop.Run();
|
| +
|
| + // If we were using an auth_code and received a valid refresh token,
|
| + // then we want to store it locally. If we had an auth code and did not
|
| + // receive a refresh token, then we should let the user know and exit.
|
| + if (!auth_code.empty()) {
|
| + if (!refresh_token_.empty()) {
|
| + // If a unit test has set |test_refresh_token_store_| then we should use
|
| + // it below. Note that we do not want to destroy the test object.
|
| + scoped_ptr<RefreshTokenStore> temporary_refresh_token_store;
|
| + RefreshTokenStore* refresh_token_store = test_refresh_token_store_;
|
| + if (!refresh_token_store) {
|
| + temporary_refresh_token_store =
|
| + RefreshTokenStore::OnDisk(user_name_, refresh_token_file_path_);
|
| + refresh_token_store = temporary_refresh_token_store.get();
|
| + }
|
| +
|
| + if (!refresh_token_store->StoreRefreshToken(refresh_token_)) {
|
| + // If we failed to persist the refresh token, then we should let the
|
| + // user sort out the issue before continuing.
|
| + return false;
|
| + }
|
| + } else {
|
| + LOG(ERROR) << "Failed to use AUTH CODE to retrieve a refresh token.\n"
|
| + << "Was the one-time use AUTH CODE used more than once?";
|
| + return false;
|
| + }
|
| + }
|
| +
|
| + if (access_token_.empty()) {
|
| + LOG(ERROR) << "Failed to retrieve access token.";
|
| + return false;
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +
|
| +void ChromotingTestDriverEnvironment::OnAccessTokenRetrieved(
|
| + base::Closure done_closure,
|
| + const std::string& retrieved_access_token,
|
| + const std::string& retrieved_refresh_token) {
|
| + VLOG(1) << "OnAccessTokenRetrieved() Called";
|
| + VLOG(1) << "Access Token: " << retrieved_access_token;
|
| +
|
| + access_token_ = retrieved_access_token;
|
| + refresh_token_ = retrieved_refresh_token;
|
| +
|
| + done_closure.Run();
|
| +}
|
| +
|
| +bool ChromotingTestDriverEnvironment::RetrieveHostList() {
|
| + base::RunLoop run_loop;
|
| +
|
| + host_list_.clear();
|
| +
|
| + // If a unit test has set |test_host_list_fetcher_| then we should use it
|
| + // below. Note that we do not want to destroy the test object at the end of
|
| + // the function which is why we have the dance below.
|
| + scoped_ptr<HostListFetcher> temporary_host_list_fetcher;
|
| + HostListFetcher* host_list_fetcher = test_host_list_fetcher_;
|
| + if (!host_list_fetcher) {
|
| + temporary_host_list_fetcher.reset(new HostListFetcher());
|
| + host_list_fetcher = temporary_host_list_fetcher.get();
|
| + }
|
| +
|
| + remoting::test::HostListFetcher::HostlistCallback host_list_callback =
|
| + base::Bind(&ChromotingTestDriverEnvironment::OnHostListRetrieved,
|
| + base::Unretained(this), run_loop.QuitClosure());
|
| +
|
| + host_list_fetcher->RetrieveHostlist(access_token_, host_list_callback);
|
| +
|
| + run_loop.Run();
|
| +
|
| + if (host_list_.empty()) {
|
| + // Note: Access token may have expired, but it is unlikely.
|
| + LOG(ERROR) << "Retrieved host list is empty.\n"
|
| + << "Does the account have hosts set up?";
|
| + return false;
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +
|
| +void ChromotingTestDriverEnvironment::OnHostListRetrieved(
|
| + base::Closure done_closure,
|
| + const std::vector<HostInfo>& retrieved_host_list) {
|
| + VLOG(1) << "OnHostListRetrieved() Called";
|
| +
|
| + host_list_ = retrieved_host_list;
|
| +
|
| + done_closure.Run();
|
| +}
|
| +
|
| +} // namespace test
|
| +} // namespace remoting
|
|
|