Commit a74b62f5 authored by Yuwei Huang's avatar Yuwei Huang Committed by Commit Bot

[remoting] Migrate HeartbeatSender to Protobuf over HTTP

This CL makes HeartbeatSender send request via Protobuf over HTTP. This
is OK to be checked in now since unlike FTL, our backend is ready to
accept Protobuf/HTTP requests.

Bug: 1103416
Change-Id: Iefdbcb59602436e01dbf4475cab3f6db67004e2c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2311121
Commit-Queue: Yuwei Huang <yuweih@chromium.org>
Auto-Submit: Yuwei Huang <yuweih@chromium.org>
Reviewed-by: default avatarMartin Šrámek <msramek@chromium.org>
Reviewed-by: default avatarJoe Downing <joedow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#791025}
parent 3ddbb96e
This diff is collapsed.
...@@ -21,13 +21,14 @@ namespace base { ...@@ -21,13 +21,14 @@ namespace base {
class TimeDelta; class TimeDelta;
} // namespace base } // namespace base
namespace grpc { namespace network {
class Status; class SharedURLLoaderFactory;
} // namespace grpc } // namespace network
namespace remoting { namespace remoting {
class OAuthTokenGetter; class OAuthTokenGetter;
class ProtobufHttpStatus;
// HeartbeatSender periodically sends heartbeat to the directory service. See // HeartbeatSender periodically sends heartbeat to the directory service. See
// the HeartbeatRequest message in directory_messages.proto for more details. // the HeartbeatRequest message in directory_messages.proto for more details.
...@@ -71,11 +72,13 @@ class HeartbeatSender final : public SignalStrategy::Listener { ...@@ -71,11 +72,13 @@ class HeartbeatSender final : public SignalStrategy::Listener {
}; };
// All raw pointers must be non-null and outlive this object. // All raw pointers must be non-null and outlive this object.
HeartbeatSender(Delegate* delegate, HeartbeatSender(
const std::string& host_id, Delegate* delegate,
SignalStrategy* signal_strategy, const std::string& host_id,
OAuthTokenGetter* oauth_token_getter, SignalStrategy* signal_strategy,
bool is_googler); OAuthTokenGetter* oauth_token_getter,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
bool is_googler);
~HeartbeatSender() override; ~HeartbeatSender() override;
// Sets host offline reason for future heartbeat, and initiates sending a // Sets host offline reason for future heartbeat, and initiates sending a
...@@ -95,12 +98,12 @@ class HeartbeatSender final : public SignalStrategy::Listener { ...@@ -95,12 +98,12 @@ class HeartbeatSender final : public SignalStrategy::Listener {
class HeartbeatClient { class HeartbeatClient {
public: public:
using HeartbeatResponseCallback = using HeartbeatResponseCallback =
base::OnceCallback<void(const grpc::Status&, base::OnceCallback<void(const ProtobufHttpStatus&,
const apis::v1::HeartbeatResponse&)>; std::unique_ptr<apis::v1::HeartbeatResponse>)>;
virtual ~HeartbeatClient() = default; virtual ~HeartbeatClient() = default;
virtual void Heartbeat(const apis::v1::HeartbeatRequest& request, virtual void Heartbeat(std::unique_ptr<apis::v1::HeartbeatRequest> request,
HeartbeatResponseCallback callback) = 0; HeartbeatResponseCallback callback) = 0;
virtual void CancelPendingRequests() = 0; virtual void CancelPendingRequests() = 0;
}; };
...@@ -115,8 +118,8 @@ class HeartbeatSender final : public SignalStrategy::Listener { ...@@ -115,8 +118,8 @@ class HeartbeatSender final : public SignalStrategy::Listener {
const jingle_xmpp::XmlElement* stanza) override; const jingle_xmpp::XmlElement* stanza) override;
void SendHeartbeat(); void SendHeartbeat();
void OnResponse(const grpc::Status& status, void OnResponse(const ProtobufHttpStatus& status,
const apis::v1::HeartbeatResponse& response); std::unique_ptr<apis::v1::HeartbeatResponse> response);
// Handlers for host-offline-reason completion and timeout. // Handlers for host-offline-reason completion and timeout.
void OnHostOfflineReasonTimeout(); void OnHostOfflineReasonTimeout();
...@@ -126,7 +129,7 @@ class HeartbeatSender final : public SignalStrategy::Listener { ...@@ -126,7 +129,7 @@ class HeartbeatSender final : public SignalStrategy::Listener {
apis::v1::HeartbeatResponse::RemoteCommand remote_command); apis::v1::HeartbeatResponse::RemoteCommand remote_command);
// Helper methods used by DoSendStanza() to generate heartbeat stanzas. // Helper methods used by DoSendStanza() to generate heartbeat stanzas.
apis::v1::HeartbeatRequest CreateHeartbeatRequest(); std::unique_ptr<apis::v1::HeartbeatRequest> CreateHeartbeatRequest();
Delegate* delegate_; Delegate* delegate_;
std::string host_id_; std::string host_id_;
......
...@@ -19,11 +19,12 @@ ...@@ -19,11 +19,12 @@
#include "base/time/time.h" #include "base/time/time.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "remoting/base/fake_oauth_token_getter.h" #include "remoting/base/fake_oauth_token_getter.h"
#include "remoting/proto/remoting/v1/directory_service.grpc.pb.h" #include "remoting/base/protobuf_http_status.h"
#include "remoting/signaling/fake_signal_strategy.h" #include "remoting/signaling/fake_signal_strategy.h"
#include "remoting/signaling/mock_signaling_tracker.h" #include "remoting/signaling/mock_signaling_tracker.h"
#include "remoting/signaling/signal_strategy.h" #include "remoting/signaling/signal_strategy.h"
#include "remoting/signaling/signaling_address.h" #include "remoting/signaling/signaling_address.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -37,8 +38,8 @@ using testing::InSequence; ...@@ -37,8 +38,8 @@ using testing::InSequence;
using testing::Return; using testing::Return;
using HeartbeatResponseCallback = using HeartbeatResponseCallback =
base::OnceCallback<void(const grpc::Status&, base::OnceCallback<void(const ProtobufHttpStatus&,
const apis::v1::HeartbeatResponse&)>; std::unique_ptr<apis::v1::HeartbeatResponse>)>;
constexpr char kOAuthAccessToken[] = "fake_access_token"; constexpr char kOAuthAccessToken[] = "fake_access_token";
constexpr char kHostId[] = "fake_host_id"; constexpr char kHostId[] = "fake_host_id";
...@@ -55,31 +56,31 @@ constexpr base::TimeDelta kOfflineReasonTimeout = ...@@ -55,31 +56,31 @@ constexpr base::TimeDelta kOfflineReasonTimeout =
constexpr base::TimeDelta kTestHeartbeatDelay = constexpr base::TimeDelta kTestHeartbeatDelay =
base::TimeDelta::FromSeconds(350); base::TimeDelta::FromSeconds(350);
void ValidateHeartbeat(const apis::v1::HeartbeatRequest& request, void ValidateHeartbeat(std::unique_ptr<apis::v1::HeartbeatRequest> request,
bool expected_is_initial_heartbeat = false, bool expected_is_initial_heartbeat = false,
const std::string& expected_host_offline_reason = {}, const std::string& expected_host_offline_reason = {},
bool is_googler = false) { bool is_googler = false) {
ASSERT_TRUE(request.has_host_version()); ASSERT_TRUE(request->has_host_version());
if (expected_host_offline_reason.empty()) { if (expected_host_offline_reason.empty()) {
ASSERT_FALSE(request.has_host_offline_reason()); ASSERT_FALSE(request->has_host_offline_reason());
} else { } else {
ASSERT_EQ(expected_host_offline_reason, request.host_offline_reason()); ASSERT_EQ(expected_host_offline_reason, request->host_offline_reason());
} }
ASSERT_EQ(kHostId, request.host_id()); ASSERT_EQ(kHostId, request->host_id());
ASSERT_EQ(kFtlId, request.tachyon_id()); ASSERT_EQ(kFtlId, request->tachyon_id());
ASSERT_TRUE(request.has_host_version()); ASSERT_TRUE(request->has_host_version());
ASSERT_TRUE(request.has_host_os_version()); ASSERT_TRUE(request->has_host_os_version());
ASSERT_TRUE(request.has_host_os_name()); ASSERT_TRUE(request->has_host_os_name());
ASSERT_TRUE(request.has_host_cpu_type()); ASSERT_TRUE(request->has_host_cpu_type());
ASSERT_EQ(expected_is_initial_heartbeat, request.is_initial_heartbeat()); ASSERT_EQ(expected_is_initial_heartbeat, request->is_initial_heartbeat());
bool is_linux = false; bool is_linux = false;
#if defined(OS_LINUX) && !defined(OS_CHROMEOS) #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
is_linux = true; is_linux = true;
#endif #endif
if (is_googler && is_linux) { if (is_googler && is_linux) {
ASSERT_TRUE(request.has_hostname_hash()); ASSERT_TRUE(request->has_hostname_hash());
} else { } else {
ASSERT_FALSE(request.has_hostname_hash()); ASSERT_FALSE(request->has_hostname_hash());
} }
} }
...@@ -87,13 +88,13 @@ decltype(auto) DoValidateHeartbeatAndRespondOk( ...@@ -87,13 +88,13 @@ decltype(auto) DoValidateHeartbeatAndRespondOk(
bool expected_is_initial_heartbeat = false, bool expected_is_initial_heartbeat = false,
const std::string& expected_host_offline_reason = {}, const std::string& expected_host_offline_reason = {},
bool is_googler = false) { bool is_googler = false) {
return [=](const apis::v1::HeartbeatRequest& request, return [=](std::unique_ptr<apis::v1::HeartbeatRequest> request,
HeartbeatResponseCallback callback) { HeartbeatResponseCallback callback) {
ValidateHeartbeat(request, expected_is_initial_heartbeat, ValidateHeartbeat(std::move(request), expected_is_initial_heartbeat,
expected_host_offline_reason, is_googler); expected_host_offline_reason, is_googler);
apis::v1::HeartbeatResponse response; auto response = std::make_unique<apis::v1::HeartbeatResponse>();
response.set_set_interval_seconds(kGoodIntervalSeconds); response->set_set_interval_seconds(kGoodIntervalSeconds);
std::move(callback).Run(grpc::Status::OK, response); std::move(callback).Run(ProtobufHttpStatus::OK, std::move(response));
}; };
} }
...@@ -125,7 +126,7 @@ class HeartbeatSenderTest : public testing::Test { ...@@ -125,7 +126,7 @@ class HeartbeatSenderTest : public testing::Test {
heartbeat_sender_ = std::make_unique<HeartbeatSender>( heartbeat_sender_ = std::make_unique<HeartbeatSender>(
&mock_delegate_, kHostId, signal_strategy_.get(), &oauth_token_getter_, &mock_delegate_, kHostId, signal_strategy_.get(), &oauth_token_getter_,
false); nullptr, false);
auto heartbeat_client = std::make_unique<MockHeartbeatClient>(); auto heartbeat_client = std::make_unique<MockHeartbeatClient>();
mock_client_ = heartbeat_client.get(); mock_client_ = heartbeat_client.get();
heartbeat_sender_->client_ = std::move(heartbeat_client); heartbeat_sender_->client_ = std::move(heartbeat_client);
...@@ -141,7 +142,7 @@ class HeartbeatSenderTest : public testing::Test { ...@@ -141,7 +142,7 @@ class HeartbeatSenderTest : public testing::Test {
class MockHeartbeatClient : public HeartbeatSender::HeartbeatClient { class MockHeartbeatClient : public HeartbeatSender::HeartbeatClient {
public: public:
MOCK_METHOD2(Heartbeat, MOCK_METHOD2(Heartbeat,
void(const apis::v1::HeartbeatRequest&, void(std::unique_ptr<apis::v1::HeartbeatRequest>,
HeartbeatResponseCallback)); HeartbeatResponseCallback));
void CancelPendingRequests() override { void CancelPendingRequests() override {
...@@ -247,11 +248,13 @@ TEST_F(HeartbeatSenderTest, SetHostOfflineReason) { ...@@ -247,11 +248,13 @@ TEST_F(HeartbeatSenderTest, SetHostOfflineReason) {
TEST_F(HeartbeatSenderTest, UnknownHostId) { TEST_F(HeartbeatSenderTest, UnknownHostId) {
EXPECT_CALL(*mock_client_, Heartbeat(_, _)) EXPECT_CALL(*mock_client_, Heartbeat(_, _))
.WillRepeatedly([](const apis::v1::HeartbeatRequest& request, .WillRepeatedly([](std::unique_ptr<apis::v1::HeartbeatRequest> request,
HeartbeatResponseCallback callback) { HeartbeatResponseCallback callback) {
ValidateHeartbeat(request, true); ValidateHeartbeat(std::move(request), true);
std::move(callback).Run( std::move(callback).Run(
grpc::Status(grpc::StatusCode::NOT_FOUND, "not found"), {}); ProtobufHttpStatus(ProtobufHttpStatus::Code::NOT_FOUND,
"not found"),
nullptr);
}); });
EXPECT_CALL(mock_delegate_, OnHostNotFound()).Times(1); EXPECT_CALL(mock_delegate_, OnHostNotFound()).Times(1);
...@@ -267,11 +270,13 @@ TEST_F(HeartbeatSenderTest, FailedToHeartbeat_Backoff) { ...@@ -267,11 +270,13 @@ TEST_F(HeartbeatSenderTest, FailedToHeartbeat_Backoff) {
EXPECT_CALL(*mock_client_, Heartbeat(_, _)) EXPECT_CALL(*mock_client_, Heartbeat(_, _))
.Times(2) .Times(2)
.WillRepeatedly([&](const apis::v1::HeartbeatRequest& request, .WillRepeatedly([&](std::unique_ptr<apis::v1::HeartbeatRequest> request,
HeartbeatResponseCallback callback) { HeartbeatResponseCallback callback) {
ValidateHeartbeat(request, true); ValidateHeartbeat(std::move(request), true);
std::move(callback).Run( std::move(callback).Run(
grpc::Status(grpc::StatusCode::UNAVAILABLE, "unavailable"), {}); ProtobufHttpStatus(ProtobufHttpStatus::Code::UNAVAILABLE,
"unavailable"),
nullptr);
}); });
EXPECT_CALL(*mock_client_, Heartbeat(_, _)) EXPECT_CALL(*mock_client_, Heartbeat(_, _))
...@@ -290,13 +295,14 @@ TEST_F(HeartbeatSenderTest, FailedToHeartbeat_Backoff) { ...@@ -290,13 +295,14 @@ TEST_F(HeartbeatSenderTest, FailedToHeartbeat_Backoff) {
TEST_F(HeartbeatSenderTest, Unauthenticated) { TEST_F(HeartbeatSenderTest, Unauthenticated) {
int heartbeat_count = 0; int heartbeat_count = 0;
EXPECT_CALL(*mock_client_, Heartbeat(_, _)) EXPECT_CALL(*mock_client_, Heartbeat(_, _))
.WillRepeatedly([&](const apis::v1::HeartbeatRequest& request, .WillRepeatedly([&](std::unique_ptr<apis::v1::HeartbeatRequest> request,
HeartbeatResponseCallback callback) { HeartbeatResponseCallback callback) {
ValidateHeartbeat(request, true); ValidateHeartbeat(std::move(request), true);
heartbeat_count++; heartbeat_count++;
std::move(callback).Run( std::move(callback).Run(
grpc::Status(grpc::StatusCode::UNAUTHENTICATED, "unauthenticated"), ProtobufHttpStatus(ProtobufHttpStatus::Code::UNAUTHENTICATED,
{}); "unauthenticated"),
nullptr);
}); });
EXPECT_CALL(mock_delegate_, OnAuthFailed()).Times(1); EXPECT_CALL(mock_delegate_, OnAuthFailed()).Times(1);
...@@ -310,13 +316,13 @@ TEST_F(HeartbeatSenderTest, Unauthenticated) { ...@@ -310,13 +316,13 @@ TEST_F(HeartbeatSenderTest, Unauthenticated) {
TEST_F(HeartbeatSenderTest, RemoteCommand) { TEST_F(HeartbeatSenderTest, RemoteCommand) {
EXPECT_CALL(*mock_client_, Heartbeat(_, _)) EXPECT_CALL(*mock_client_, Heartbeat(_, _))
.WillOnce([](const apis::v1::HeartbeatRequest& request, .WillOnce([](std::unique_ptr<apis::v1::HeartbeatRequest> request,
HeartbeatResponseCallback callback) { HeartbeatResponseCallback callback) {
ValidateHeartbeat(request, true); ValidateHeartbeat(std::move(request), true);
apis::v1::HeartbeatResponse response; auto response = std::make_unique<apis::v1::HeartbeatResponse>();
response.set_set_interval_seconds(kGoodIntervalSeconds); response->set_set_interval_seconds(kGoodIntervalSeconds);
response.set_remote_command(apis::v1::HeartbeatResponse::RESTART_HOST); response->set_remote_command(apis::v1::HeartbeatResponse::RESTART_HOST);
std::move(callback).Run(grpc::Status::OK, response); std::move(callback).Run(ProtobufHttpStatus::OK, std::move(response));
}); });
EXPECT_CALL(mock_delegate_, OnFirstHeartbeatSuccessful()).Times(1); EXPECT_CALL(mock_delegate_, OnFirstHeartbeatSuccessful()).Times(1);
EXPECT_CALL(mock_delegate_, OnRemoteRestartHost()).Times(1); EXPECT_CALL(mock_delegate_, OnRemoteRestartHost()).Times(1);
......
...@@ -1414,7 +1414,7 @@ void HostProcess::InitializeSignaling() { ...@@ -1414,7 +1414,7 @@ void HostProcess::InitializeSignaling() {
heartbeat_sender_ = std::make_unique<HeartbeatSender>( heartbeat_sender_ = std::make_unique<HeartbeatSender>(
this, host_id_, ftl_signal_strategy.get(), oauth_token_getter_.get(), this, host_id_, ftl_signal_strategy.get(), oauth_token_getter_.get(),
is_googler); context_->url_loader_factory(), is_googler);
signal_strategy_ = std::move(ftl_signal_strategy); signal_strategy_ = std::move(ftl_signal_strategy);
} }
......
...@@ -136,6 +136,7 @@ Refer to README.md for content description and update process. ...@@ -136,6 +136,7 @@ Refer to README.md for content description and update process.
<item id="geo_language_provider" hash_code="52821843" type="1" second_id="96590038" content_hash_code="65327456" os_list="linux,windows" semantics_fields="1" policy_fields="3,4" file_path="components/language/content/browser/geo_language_provider.cc"/> <item id="geo_language_provider" hash_code="52821843" type="1" second_id="96590038" content_hash_code="65327456" os_list="linux,windows" semantics_fields="1" policy_fields="3,4" file_path="components/language/content/browser/geo_language_provider.cc"/>
<item id="google_url_tracker" hash_code="5492492" type="0" deprecated="2019-08-01" content_hash_code="54474899" file_path=""/> <item id="google_url_tracker" hash_code="5492492" type="0" deprecated="2019-08-01" content_hash_code="54474899" file_path=""/>
<item id="headless_url_request" hash_code="29865866" type="0" deprecated="2018-07-10" content_hash_code="76700151" file_path=""/> <item id="headless_url_request" hash_code="29865866" type="0" deprecated="2018-07-10" content_hash_code="76700151" file_path=""/>
<item id="heartbeat_sender" hash_code="4883150" type="0" content_hash_code="131927805" os_list="linux,windows" file_path="remoting/host/heartbeat_sender.cc"/>
<item id="hintsfetcher_gethintsrequest" hash_code="34557599" type="0" content_hash_code="57003380" os_list="linux,windows" file_path="components/optimization_guide/hints_fetcher.cc"/> <item id="hintsfetcher_gethintsrequest" hash_code="34557599" type="0" content_hash_code="57003380" os_list="linux,windows" file_path="components/optimization_guide/hints_fetcher.cc"/>
<item id="history_notice_utils_notice" hash_code="102595701" type="1" second_id="110307337" content_hash_code="130829410" os_list="linux,windows" semantics_fields="2,3,4" policy_fields="4" file_path="components/browsing_data/core/history_notice_utils.cc"/> <item id="history_notice_utils_notice" hash_code="102595701" type="1" second_id="110307337" content_hash_code="130829410" os_list="linux,windows" semantics_fields="2,3,4" policy_fields="4" file_path="components/browsing_data/core/history_notice_utils.cc"/>
<item id="history_notice_utils_popup" hash_code="80832574" type="1" second_id="110307337" content_hash_code="30618510" os_list="linux,windows" semantics_fields="2,3,4" policy_fields="4" file_path="components/browsing_data/core/history_notice_utils.cc"/> <item id="history_notice_utils_popup" hash_code="80832574" type="1" second_id="110307337" content_hash_code="30618510" os_list="linux,windows" semantics_fields="2,3,4" policy_fields="4" file_path="components/browsing_data/core/history_notice_utils.cc"/>
......
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