blob: 9634514dee60a08f5c448432a4023421b8feee92 [file] [log] [blame]
// Copyright 2019 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/signaling/ftl_grpc_context.h"
#include <utility>
#include "base/bind.h"
#include "base/guid.h"
#include "build/build_config.h"
#include "google_apis/google_api_keys.h"
#include "third_party/grpc/src/include/grpcpp/grpcpp.h"
namespace remoting {
namespace {
constexpr char kChromotingAppIdentifier[] = "CRD";
// TODO(yuweih): We should target different service environments.
constexpr char kFtlServerEndpoint[] = "instantmessaging-pa.googleapis.com";
} // namespace
// static
std::string FtlGrpcContext::GetChromotingAppIdentifier() {
return kChromotingAppIdentifier;
}
FtlGrpcContext::FtlGrpcContext(OAuthTokenGetter* token_getter)
: weak_factory_(this) {
DCHECK(token_getter);
token_getter_ = token_getter;
auto channel_creds = grpc::SslCredentials(grpc::SslCredentialsOptions());
channel_ = grpc::CreateChannel(kFtlServerEndpoint, channel_creds);
}
FtlGrpcContext::~FtlGrpcContext() = default;
void FtlGrpcContext::SetAuthToken(const std::string& auth_token) {
DCHECK(!auth_token.empty());
auth_token_ = auth_token;
}
void FtlGrpcContext::SetChannelForTesting(
std::shared_ptr<grpc::ChannelInterface> channel) {
channel_ = channel;
}
void FtlGrpcContext::GetOAuthTokenAndExecuteRpc(
ExecuteRpcWithContextCallback execute_rpc_with_context) {
token_getter_->CallWithToken(base::BindOnce(
&FtlGrpcContext::ExecuteRpcWithFetchedOAuthToken,
weak_factory_.GetWeakPtr(), std::move(execute_rpc_with_context)));
}
void FtlGrpcContext::ExecuteRpcWithFetchedOAuthToken(
ExecuteRpcWithContextCallback execute_rpc_with_context,
OAuthTokenGetter::Status status,
const std::string& user_email,
const std::string& access_token) {
std::unique_ptr<grpc::ClientContext> context = CreateClientContext();
if (status != OAuthTokenGetter::Status::SUCCESS) {
LOG(ERROR) << "Failed to fetch access token. Status: " << status;
}
if (status == OAuthTokenGetter::Status::SUCCESS && !access_token.empty()) {
context->set_credentials(grpc::AccessTokenCredentials(access_token));
} else {
LOG(WARNING) << "Attempting to execute RPC without access token.";
}
std::move(execute_rpc_with_context).Run(std::move(context));
}
// static
std::unique_ptr<grpc::ClientContext> FtlGrpcContext::CreateClientContext() {
auto context = std::make_unique<grpc::ClientContext>();
context->AddMetadata("x-goog-api-key", google_apis::GetRemotingFtlAPIKey());
return context;
}
std::unique_ptr<ftl::RequestHeader> FtlGrpcContext::BuildRequestHeader() {
auto header = std::make_unique<ftl::RequestHeader>();
header->set_request_id(base::GenerateGUID());
header->set_app(kChromotingAppIdentifier);
if (!auth_token_.empty()) {
header->set_auth_token_payload(auth_token_);
}
ftl::ClientInfo* client_info = header->mutable_client_info();
client_info->set_api_version(ftl::ApiVersion_Value_V4);
client_info->set_version_major(VERSION_MAJOR);
// Chrome's version has four number components, and the VERSION_MINOR is
// always 0, like X.0.X.X. The FTL server requires three-component version
// number so we just skip the VERSION_MINOR here.
client_info->set_version_minor(VERSION_BUILD);
client_info->set_version_point(VERSION_PATCH);
ftl::Platform_Type platform_type;
#if defined(OS_ANDROID)
platform_type = ftl::Platform_Type_FTL_ANDROID;
#elif defined(OS_IOS)
platform_type = ftl::Platform_Type_FTL_IOS;
#else
platform_type = ftl::Platform_Type_FTL_DESKTOP;
#endif
client_info->set_platform_type(platform_type);
return header;
}
} // namespace remoting