blob: 9f82ce79d39169b3befbf1dd57ebe2615f905fd9 [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "remoting/host/setup/corp_host_starter.h"
#include <memory>
#include <string>
#include <utility>
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/strings/string_util.h"
#include "remoting/base/corp_service_client.h"
#include "remoting/base/http_status.h"
#include "remoting/base/internal_headers.h"
#include "remoting/host/host_config.h"
#include "remoting/host/setup/buildflags.h"
#include "remoting/host/setup/host_starter.h"
#include "remoting/host/setup/host_starter_base.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
namespace remoting {
namespace {
// A helper class which provisions a corp machine for Chrome Remote Desktop.
class CorpHostStarter : public HostStarterBase {
public:
CorpHostStarter(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
std::unique_ptr<net::ClientCertStore> client_cert_store);
CorpHostStarter(const CorpHostStarter&) = delete;
CorpHostStarter& operator=(const CorpHostStarter&) = delete;
~CorpHostStarter() override;
// HostStarterBase implementation.
void RegisterNewHost(std::optional<std::string> access_token) override;
void RemoveOldHostFromDirectory(base::OnceClosure on_host_removed) override;
void ApplyConfigValues(base::Value::Dict& config) override;
void ReportError(const std::string& error_message,
base::OnceClosure on_error_reported) override;
// CorpServiceClient callback.
void OnProvisionCorpMachineResponse(
const HttpStatus& status,
std::unique_ptr<internal::ProvisionCorpMachineResponse> response);
private:
std::unique_ptr<CorpServiceClient> corp_service_client_;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<CorpHostStarter> weak_ptr_factory_{this};
};
CorpHostStarter::CorpHostStarter(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
std::unique_ptr<net::ClientCertStore> client_cert_store)
: HostStarterBase(url_loader_factory),
corp_service_client_(
std::make_unique<CorpServiceClient>(url_loader_factory,
std::move(client_cert_store))) {}
CorpHostStarter::~CorpHostStarter() = default;
void CorpHostStarter::RegisterNewHost(std::optional<std::string> access_token) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// We don't expect |access_token| to be populated for this flow.
DCHECK(!access_token.has_value());
corp_service_client_->ProvisionCorpMachine(
params().username, params().name, key_pair().GetPublicKey(),
existing_host_id(),
base::BindOnce(&CorpHostStarter::OnProvisionCorpMachineResponse,
weak_ptr_factory_.GetWeakPtr()));
}
void CorpHostStarter::OnProvisionCorpMachineResponse(
const HttpStatus& status,
std::unique_ptr<internal::ProvisionCorpMachineResponse> response) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!status.ok()) {
HandleHttpStatusError(status);
return;
}
OnNewHostRegistered(
base::ToLowerASCII(internal::GetHostId(*response)),
base::ToLowerASCII(internal::GetOwnerEmail(*response)),
base::ToLowerASCII(internal::GetServiceAccount(*response)),
internal::GetAuthorizationCode(*response));
}
void CorpHostStarter::RemoveOldHostFromDirectory(
base::OnceClosure on_host_removed) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// This workflow removes the existing host as part of the provisioning service
// call so we don't need to make an additional service request here.
std::move(on_host_removed).Run();
}
void CorpHostStarter::ApplyConfigValues(base::Value::Dict& config) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
config.Set(kRequireSessionAuthorizationPath, true);
config.Set(kHostTypeHintPath, kCorpHostTypeHint);
}
void CorpHostStarter::ReportError(const std::string& message,
base::OnceClosure on_error_reported) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
const std::string& host_id = params().id;
LOG(ERROR) << "\n Reporting provisioning error for host id `" << host_id
<< "`:\n " << message;
corp_service_client_->ReportProvisioningError(
host_id, message,
base::BindOnce(
[](base::OnceClosure on_error_reported, const HttpStatus& status,
std::unique_ptr<Empty>) {
if (!status.ok()) {
LOG(ERROR) << "Failed to report provisioning error: "
<< static_cast<int>(status.error_code());
}
std::move(on_error_reported).Run();
},
std::move(on_error_reported)));
}
} // namespace
std::unique_ptr<HostStarter> ProvisionCorpMachine(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
std::unique_ptr<net::ClientCertStore> client_cert_store) {
return std::make_unique<CorpHostStarter>(url_loader_factory,
std::move(client_cert_store));
}
} // namespace remoting