Commit 88f55637 authored by Lambros Lambrou's avatar Lambros Lambrou Committed by Commit Bot

Update remoting_start_host to use new Directory service.

This migrates the start_host tool to access the new Directory API
using gRPC.

Bug: 968326
Change-Id: Iac944cfe1d072b977f0d71feb7ad3e30f168e385
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1636671
Auto-Submit: Lambros Lambrou <lambroslambrou@chromium.org>
Commit-Queue: Joe Downing <joedow@chromium.org>
Reviewed-by: default avatarJoe Downing <joedow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#664645}
parent 97d3c908
......@@ -20,6 +20,7 @@ include_rules = [
"+services/device/public",
"+services/device/wake_lock/power_save_blocker",
"+services/network",
"+third_party/grpc",
"+third_party/jsoncpp",
"+third_party/skia",
"+third_party/webrtc",
......
......@@ -45,6 +45,7 @@ source_set("common") {
"//remoting/base:authorization",
"//remoting/host:common",
"//remoting/host/native_messaging",
"//remoting/proto/remoting/v1:directory_grpc_library",
"//services/network/public/cpp",
"//services/network/public/mojom",
]
......
......@@ -40,12 +40,11 @@ HostStarter::HostStarter(
HostStarter::~HostStarter() = default;
std::unique_ptr<HostStarter> HostStarter::Create(
const std::string& chromoting_hosts_url,
const std::string& remoting_server_endpoint,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
return base::WrapUnique(new HostStarter(
std::make_unique<gaia::GaiaOAuthClient>(url_loader_factory),
std::make_unique<remoting::ServiceClient>(chromoting_hosts_url,
url_loader_factory),
std::make_unique<remoting::ServiceClient>(remoting_server_endpoint),
remoting::DaemonController::Create()));
}
......
......@@ -39,7 +39,7 @@ class HostStarter : public gaia::GaiaOAuthClient::Delegate,
// Creates a HostStarter.
static std::unique_ptr<HostStarter> Create(
const std::string& chromoting_hosts_url,
const std::string& remoting_server_endpoint,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
// Registers a new host with the Chromoting service, and starts it.
......
......@@ -7,25 +7,105 @@
#include <memory>
#include "base/bind.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/values.h"
#include "net/http/http_status_code.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "url/gurl.h"
#include "base/macros.h"
#include "remoting/base/grpc_support/grpc_async_executor.h"
#include "remoting/base/grpc_support/grpc_async_unary_request.h"
#include "remoting/base/grpc_support/grpc_channel.h"
#include "remoting/proto/remoting/v1/directory_service.grpc.pb.h"
#include "third_party/grpc/src/include/grpcpp/security/credentials.h"
namespace remoting {
namespace {
// Class for making Directory Service requests via gRPC, used by
// ServiceClient::Core.
class DirectoryServiceClient {
public:
using RegisterHostCallback =
base::OnceCallback<void(const grpc::Status&,
const apis::v1::RegisterHostResponse&)>;
using DeleteHostCallback =
base::OnceCallback<void(const grpc::Status&,
const apis::v1::DeleteHostResponse&)>;
explicit DirectoryServiceClient(const std::string& remoting_server_endpoint);
~DirectoryServiceClient();
void RegisterHost(const std::string& host_id,
const std::string& host_name,
const std::string& public_key,
const std::string& host_client_id,
const std::string& oauth_access_token,
RegisterHostCallback callback);
void DeleteHost(const std::string& host_id,
const std::string& oauth_access_token,
DeleteHostCallback callback);
private:
using RemotingDirectoryService = apis::v1::RemotingDirectoryService;
GrpcAsyncExecutor grpc_executor_;
std::unique_ptr<apis::v1::RemotingDirectoryService::Stub> stub_;
DISALLOW_COPY_AND_ASSIGN(DirectoryServiceClient);
};
DirectoryServiceClient::DirectoryServiceClient(
const std::string& remoting_server_endpoint) {
GrpcChannelSharedPtr channel =
CreateSslChannelForEndpoint(remoting_server_endpoint);
stub_ = RemotingDirectoryService::NewStub(channel);
}
DirectoryServiceClient::~DirectoryServiceClient() = default;
void DirectoryServiceClient::RegisterHost(const std::string& host_id,
const std::string& host_name,
const std::string& public_key,
const std::string& host_client_id,
const std::string& oauth_access_token,
RegisterHostCallback callback) {
auto register_host_request = apis::v1::RegisterHostRequest();
register_host_request.set_host_id(host_id);
register_host_request.set_host_name(host_name);
register_host_request.set_public_key(public_key);
register_host_request.set_host_client_id(host_client_id);
auto async_request = CreateGrpcAsyncUnaryRequest(
base::BindOnce(&RemotingDirectoryService::Stub::AsyncRegisterHost,
base::Unretained(stub_.get())),
register_host_request, std::move(callback));
async_request->context()->set_credentials(
grpc::AccessTokenCredentials(oauth_access_token));
grpc_executor_.ExecuteRpc(std::move(async_request));
}
void DirectoryServiceClient::DeleteHost(const std::string& host_id,
const std::string& oauth_access_token,
DeleteHostCallback callback) {
auto delete_host_request = apis::v1::DeleteHostRequest();
delete_host_request.set_host_id(host_id);
auto async_request = CreateGrpcAsyncUnaryRequest(
base::BindOnce(&RemotingDirectoryService::Stub::AsyncDeleteHost,
base::Unretained(stub_.get())),
delete_host_request, std::move(callback));
async_request->context()->set_credentials(
grpc::AccessTokenCredentials(oauth_access_token));
grpc_executor_.ExecuteRpc(std::move(async_request));
}
} // namespace
class ServiceClient::Core
: public base::RefCountedThreadSafe<ServiceClient::Core> {
public:
Core(const std::string& chromoting_hosts_url,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
: url_loader_factory_(url_loader_factory),
delegate_(nullptr),
pending_request_type_(PENDING_REQUEST_NONE),
chromoting_hosts_url_(chromoting_hosts_url) {}
explicit Core(const std::string& remoting_server_endpoint)
: directory_service_client_(remoting_server_endpoint) {}
void RegisterHost(const std::string& host_id,
const std::string& host_name,
......@@ -34,11 +114,9 @@ class ServiceClient::Core
const std::string& oauth_access_token,
ServiceClient::Delegate* delegate);
void UnregisterHost(const std::string& host_id,
const std::string& oauth_access_token,
ServiceClient::Delegate* delegate);
void OnURLLoadComplete(std::unique_ptr<std::string> response_body);
void DeleteHost(const std::string& host_id,
const std::string& oauth_access_token,
ServiceClient::Delegate* delegate);
private:
friend class base::RefCountedThreadSafe<Core>;
......@@ -47,20 +125,20 @@ class ServiceClient::Core
enum PendingRequestType {
PENDING_REQUEST_NONE,
PENDING_REQUEST_REGISTER_HOST,
PENDING_REQUEST_UNREGISTER_HOST
PENDING_REQUEST_DELETE_HOST
};
void MakeChromotingRequest(const std::string& request_type,
const std::string& post_body,
const std::string& url_suffix,
const std::string& oauth_access_token,
ServiceClient::Delegate* delegate);
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
ServiceClient::Delegate* delegate_;
std::unique_ptr<network::SimpleURLLoader> url_loader_;
PendingRequestType pending_request_type_;
std::string chromoting_hosts_url_;
void OnRegisterHostResponse(const grpc::Status& status,
const apis::v1::RegisterHostResponse& response);
void OnDeleteHostResponse(const grpc::Status& status,
const apis::v1::DeleteHostResponse& response);
void NotifyError(const grpc::Status& status);
ServiceClient::Delegate* delegate_ = nullptr;
PendingRequestType pending_request_type_ = PENDING_REQUEST_NONE;
DirectoryServiceClient directory_service_client_;
};
void ServiceClient::Core::RegisterHost(
......@@ -72,128 +150,82 @@ void ServiceClient::Core::RegisterHost(
Delegate* delegate) {
DCHECK(pending_request_type_ == PENDING_REQUEST_NONE);
pending_request_type_ = PENDING_REQUEST_REGISTER_HOST;
base::DictionaryValue post_body;
post_body.SetString("data.hostId", host_id);
post_body.SetString("data.hostName", host_name);
post_body.SetString("data.publicKey", public_key);
std::string url_suffix;
if (!host_client_id.empty())
url_suffix = "?hostClientId=" + host_client_id;
std::string post_body_str;
base::JSONWriter::Write(post_body, &post_body_str);
MakeChromotingRequest("POST", url_suffix, post_body_str, oauth_access_token,
delegate);
delegate_ = delegate;
directory_service_client_.RegisterHost(
host_id, host_name, public_key, host_client_id, oauth_access_token,
base::Bind(&ServiceClient::Core::OnRegisterHostResponse,
base::Unretained(this)));
}
void ServiceClient::Core::UnregisterHost(
const std::string& host_id,
const std::string& oauth_access_token,
Delegate* delegate) {
void ServiceClient::Core::DeleteHost(const std::string& host_id,
const std::string& oauth_access_token,
Delegate* delegate) {
DCHECK(pending_request_type_ == PENDING_REQUEST_NONE);
pending_request_type_ = PENDING_REQUEST_UNREGISTER_HOST;
MakeChromotingRequest("DELETE", host_id, std::string(), oauth_access_token,
delegate);
}
pending_request_type_ = PENDING_REQUEST_DELETE_HOST;
void ServiceClient::Core::MakeChromotingRequest(
const std::string& request_type,
const std::string& url_suffix,
const std::string& request_body,
const std::string& oauth_access_token,
ServiceClient::Delegate* delegate) {
delegate_ = delegate;
auto resource_request = std::make_unique<network::ResourceRequest>();
resource_request->url = GURL(chromoting_hosts_url_ + url_suffix);
resource_request->method = request_type;
resource_request->headers.SetHeader(
"Authorization", std::string("OAuth ") + oauth_access_token);
net::NetworkTrafficAnnotationTag traffic_annotation =
net::DefineNetworkTrafficAnnotation("CRD_service_client",
R"(
semantics {
sender: "CRD Service Client"
description: "Client implementation for the chromoting service."
trigger:
"Manually triggered running <out>/remoting_start_host."
data: "No user data."
destination: OTHER
destination_other:
"The Chrome Remote Desktop client/host the user is connecting to."
}
policy {
cookies_allowed: NO
setting:
"This request cannot be stopped in settings, but will not be sent "
"if user does not use Chrome Remote Desktop."
policy_exception_justification:
"Not implemented."
})");
url_loader_ = network::SimpleURLLoader::Create(std::move(resource_request),
traffic_annotation);
url_loader_->AttachStringForUpload(request_body,
"application/json; charset=UTF-8");
url_loader_->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
url_loader_factory_.get(),
base::BindOnce(&ServiceClient::Core::OnURLLoadComplete,
base::Unretained(this)));
directory_service_client_.DeleteHost(
host_id, oauth_access_token,
base::Bind(&ServiceClient::Core::OnDeleteHostResponse,
base::Unretained(this)));
}
void ServiceClient::Core::OnURLLoadComplete(
std::unique_ptr<std::string> response_body) {
DCHECK(pending_request_type_ != PENDING_REQUEST_NONE);
PendingRequestType old_type = pending_request_type_;
void ServiceClient::Core::OnRegisterHostResponse(
const grpc::Status& status,
const apis::v1::RegisterHostResponse& response) {
DCHECK(pending_request_type_ == PENDING_REQUEST_REGISTER_HOST);
pending_request_type_ = PENDING_REQUEST_NONE;
int response_code = -1;
if (url_loader_->ResponseInfo() && url_loader_->ResponseInfo()->headers) {
response_code = url_loader_->ResponseInfo()->headers->response_code();
if (!status.ok()) {
NotifyError(status);
return;
}
url_loader_.reset();
if (response_code == net::HTTP_BAD_REQUEST) {
if (!response.has_auth_code()) {
LOG(ERROR) << "No auth_code in server response.";
delegate_->OnOAuthError();
return;
}
if (response_body) {
// Treat codes 2xx as successful; for example, HTTP_NO_CONTENT (204) can be
// returned from a DELETE_REQUEST.
DCHECK(response_code == -1 || (response_code / 100 == 2));
switch (old_type) {
case PENDING_REQUEST_NONE:
break;
case PENDING_REQUEST_REGISTER_HOST:
{
std::string data = *response_body;
std::unique_ptr<base::Value> message_value =
base::JSONReader::ReadDeprecated(data);
base::DictionaryValue* dict;
std::string code;
if (message_value.get() && message_value->is_dict() &&
message_value->GetAsDictionary(&dict) &&
dict->GetString("data.authorizationCode", &code)) {
delegate_->OnHostRegistered(code);
} else {
delegate_->OnHostRegistered(std::string());
}
}
break;
case PENDING_REQUEST_UNREGISTER_HOST:
delegate_->OnHostUnregistered();
break;
}
delegate_->OnHostRegistered(response.auth_code());
}
void ServiceClient::Core::OnDeleteHostResponse(
const grpc::Status& status,
const apis::v1::DeleteHostResponse& response) {
DCHECK(pending_request_type_ == PENDING_REQUEST_DELETE_HOST);
pending_request_type_ = PENDING_REQUEST_NONE;
if (!status.ok()) {
NotifyError(status);
return;
}
delegate_->OnNetworkError(response_code);
delegate_->OnHostUnregistered();
}
void ServiceClient::Core::NotifyError(const grpc::Status& status) {
grpc::StatusCode error_code = status.error_code();
LOG(ERROR) << "Received error code: " << error_code
<< ", message: " << status.error_message();
// TODO(crbug.com/968326): Update the Delegate interface and reporting to
// better reflect the errors that gRPC returns.
switch (error_code) {
case grpc::StatusCode::PERMISSION_DENIED:
case grpc::StatusCode::UNAUTHENTICATED:
delegate_->OnOAuthError();
return;
default:
delegate_->OnNetworkError(error_code);
}
}
ServiceClient::ServiceClient(
const std::string& chromoting_hosts_url,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
core_ = new Core(chromoting_hosts_url, url_loader_factory);
ServiceClient::ServiceClient(const std::string& remoting_server_endpoint) {
core_ = new Core(remoting_server_endpoint);
}
ServiceClient::~ServiceClient() = default;
......@@ -213,7 +245,7 @@ void ServiceClient::UnregisterHost(
const std::string& host_id,
const std::string& oauth_access_token,
Delegate* delegate) {
return core_->UnregisterHost(host_id, oauth_access_token, delegate);
return core_->DeleteHost(host_id, oauth_access_token, delegate);
}
} // namespace gaia
} // namespace remoting
......@@ -10,10 +10,6 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
namespace network {
class SharedURLLoaderFactory;
}
// A class that gives access to the Chromoting service.
namespace remoting {
......@@ -35,9 +31,8 @@ class ServiceClient {
protected:
virtual ~Delegate() {}
};
ServiceClient(
const std::string& chromoting_hosts_url,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
explicit ServiceClient(const std::string& remoting_server_endpoint);
~ServiceClient();
// Register a host.
......
......@@ -231,7 +231,7 @@ int StartHostMain(int argc, char** argv) {
// Start the host.
std::unique_ptr<HostStarter> host_starter(HostStarter::Create(
remoting::ServiceUrls::GetInstance()->directory_hosts_url(),
remoting::ServiceUrls::GetInstance()->remoting_server_endpoint(),
url_loader_factory_owner.GetURLLoaderFactory()));
host_starter->StartHost(host_name, host_pin,
/*consent_to_data_collection=*/true, auth_code,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment