Commit adab4463 authored by Kyle Horimoto's avatar Kyle Horimoto Committed by Commit Bot

[CrOS MultiDevice] Refactor PendingConnectionRequest.

The class has been split between a pure-virtual class, an implementation
class, and a test double. The test double will be used in a follow-up
CL.

Note: This CL also removes the is_active() function from the class. As
I was implementing contents for a future CL, I realized it was never
actually used.

Bug: 824568, 752273
Change-Id: I748b5400ee02f86d1978fa866febf85132acb153
Reviewed-on: https://chromium-review.googlesource.com/1050951
Commit-Queue: Kyle Horimoto <khorimoto@chromium.org>
Reviewed-by: default avatarRyan Hansberry <hansberry@chromium.org>
Cr-Commit-Position: refs/heads/master@{#557262}
parent 051fa275
...@@ -7,6 +7,7 @@ assert(is_chromeos, "Non-ChromeOS builds cannot depend on //chromeos") ...@@ -7,6 +7,7 @@ assert(is_chromeos, "Non-ChromeOS builds cannot depend on //chromeos")
static_library("secure_channel") { static_library("secure_channel") {
sources = [ sources = [
"pending_connection_request.h", "pending_connection_request.h",
"pending_connection_request_base.h",
"pending_connection_request_delegate.cc", "pending_connection_request_delegate.cc",
"pending_connection_request_delegate.h", "pending_connection_request_delegate.h",
] ]
...@@ -24,6 +25,8 @@ static_library("test_support") { ...@@ -24,6 +25,8 @@ static_library("test_support") {
sources = [ sources = [
"fake_connection_delegate.cc", "fake_connection_delegate.cc",
"fake_connection_delegate.h", "fake_connection_delegate.h",
"fake_pending_connection_request.cc",
"fake_pending_connection_request.h",
"fake_pending_connection_request_delegate.cc", "fake_pending_connection_request_delegate.cc",
"fake_pending_connection_request_delegate.h", "fake_pending_connection_request_delegate.h",
] ]
...@@ -39,7 +42,7 @@ source_set("unit_tests") { ...@@ -39,7 +42,7 @@ source_set("unit_tests") {
testonly = true testonly = true
sources = [ sources = [
"pending_connection_request_unittest.cc", "pending_connection_request_base_unittest.cc",
] ]
deps = [ deps = [
......
// Copyright 2018 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 "chromeos/services/secure_channel/fake_pending_connection_request.h"
namespace chromeos {
namespace secure_channel {
FakePendingConnectionRequest::FakePendingConnectionRequest(
PendingConnectionRequestDelegate* delegate)
: PendingConnectionRequest<std::string>(delegate) {}
FakePendingConnectionRequest::~FakePendingConnectionRequest() = default;
void FakePendingConnectionRequest::HandleConnectionFailure(
std::string failure_detail) {
handled_failure_details_.push_back(failure_detail);
}
} // namespace secure_channel
} // namespace chromeos
// Copyright 2018 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.
#ifndef CHROMEOS_SERVICES_SECURE_CHANNEL_FAKE_PENDING_CONNECTION_REQUEST_H_
#define CHROMEOS_SERVICES_SECURE_CHANNEL_FAKE_PENDING_CONNECTION_REQUEST_H_
#include <string>
#include <vector>
#include "base/macros.h"
#include "chromeos/services/secure_channel/pending_connection_request.h"
namespace chromeos {
namespace secure_channel {
class PendingConnectionRequestDelegate;
// Fake PendingConnectionRequest implementation, whose FailureDetailType is
// std::string.
class FakePendingConnectionRequest
: public PendingConnectionRequest<std::string> {
public:
FakePendingConnectionRequest(PendingConnectionRequestDelegate* delegate);
~FakePendingConnectionRequest() override;
const std::vector<std::string>& handled_failure_details() const {
return handled_failure_details_;
}
// Make NotifyRequestFinishedWithoutConnection() public for testing.
using PendingConnectionRequest<
std::string>::NotifyRequestFinishedWithoutConnection;
private:
// PendingConnectionRequest<std::string>:
void HandleConnectionFailure(std::string failure_detail) override;
std::vector<std::string> handled_failure_details_;
DISALLOW_COPY_AND_ASSIGN(FakePendingConnectionRequest);
};
} // namespace secure_channel
} // namespace chromeos
#endif // CHROMEOS_SERVICES_SECURE_CHANNEL_FAKE_PENDING_CONNECTION_REQUEST_H_
...@@ -7,25 +7,16 @@ ...@@ -7,25 +7,16 @@
#include "base/guid.h" #include "base/guid.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "chromeos/components/proximity_auth/logging/logging.h"
#include "chromeos/services/secure_channel/pending_connection_request_delegate.h" #include "chromeos/services/secure_channel/pending_connection_request_delegate.h"
#include "chromeos/services/secure_channel/public/mojom/secure_channel.mojom.h"
namespace chromeos { namespace chromeos {
namespace secure_channel { namespace secure_channel {
// Encapsulates metadata for a pending request for a connection to a remote // Encapsulates metadata for a pending request for a connection to a remote
// device. Every PendingConnectionRequest starts out active (i.e., there exists // device. PendingConnectionRequest is templatized so that each derived class
// an ongoing attempt to create a connection). The client of this class can // can specify its own error-handling for connection failures; for instance,
// cancel an active attempt by disconnecting the ConnectionDelegatePtr passed // some derived classes may choose to continue an ongoing connection attempt
// PendingConnectionRequest's constructor; likewise, a PendingConnectionRequest
// can become inactive due to connection failures.
//
// PendingConnectionRequest is templatized so that each derived class can
// specify its own error-handling for connection failures; for instance, some
// derived classes may choose to continue an ongoing connection attempt
// indefinitely, while others may choose to handle connection failures by giving // indefinitely, while others may choose to handle connection failures by giving
// up on the request entirely. // up on the request entirely.
template <typename FailureDetailType> template <typename FailureDetailType>
...@@ -37,8 +28,6 @@ class PendingConnectionRequest { ...@@ -37,8 +28,6 @@ class PendingConnectionRequest {
// trying to connect after some number of failures. // trying to connect after some number of failures.
virtual void HandleConnectionFailure(FailureDetailType failure_detail) = 0; virtual void HandleConnectionFailure(FailureDetailType failure_detail) = 0;
bool is_active() { return is_active_; }
// Note: Request ID is guaranteed to be unique among all requests. // Note: Request ID is guaranteed to be unique among all requests.
const std::string& GetRequestId() { const std::string& GetRequestId() {
static const std::string kRequestId = base::GenerateGUID(); static const std::string kRequestId = base::GenerateGUID();
...@@ -46,60 +35,18 @@ class PendingConnectionRequest { ...@@ -46,60 +35,18 @@ class PendingConnectionRequest {
} }
protected: protected:
PendingConnectionRequest(const std::string& feature, PendingConnectionRequest(PendingConnectionRequestDelegate* delegate)
const std::string& readable_request_type_for_logging, : delegate_(delegate) {
PendingConnectionRequestDelegate* delegate,
mojom::ConnectionDelegatePtr connection_delegate_ptr)
: feature_(feature),
readable_request_type_for_logging_(readable_request_type_for_logging),
delegate_(delegate),
connection_delegate_ptr_(std::move(connection_delegate_ptr)),
weak_ptr_factory_(this) {
DCHECK(!feature_.empty());
DCHECK(delegate_); DCHECK(delegate_);
DCHECK(connection_delegate_ptr_);
// If the client disconnects its delegate, the client is signaling that the
// connection request has been canceled.
connection_delegate_ptr_.set_connection_error_handler(
base::BindOnce(&PendingConnectionRequest::
SetInactiveAndNotifyRequestFinishedWithoutConnection,
weak_ptr_factory_.GetWeakPtr(),
PendingConnectionRequestDelegate::
FailedConnectionReason::kRequestCanceledByClient));
} }
// Derived classes should invoke this function if they would like to give up void NotifyRequestFinishedWithoutConnection(
// on the request due to connection failures.
void StopRequestDueToConnectionFailures() {
SetInactiveAndNotifyRequestFinishedWithoutConnection(
PendingConnectionRequestDelegate::FailedConnectionReason::
kRequestFailed);
}
private:
void SetInactiveAndNotifyRequestFinishedWithoutConnection(
PendingConnectionRequestDelegate::FailedConnectionReason reason) { PendingConnectionRequestDelegate::FailedConnectionReason reason) {
// If the request is already inactive, there is nothing else to do.
if (!is_active_)
return;
PA_LOG(INFO) << "Request finished without connection; notifying delegate. "
<< "Feature: \"" << feature_ << "\""
<< ", Reason: " << reason << ", Request type: \""
<< readable_request_type_for_logging_ << "\"";
is_active_ = false;
delegate_->OnRequestFinishedWithoutConnection(GetRequestId(), reason); delegate_->OnRequestFinishedWithoutConnection(GetRequestId(), reason);
} }
const std::string feature_; private:
const std::string readable_request_type_for_logging_;
PendingConnectionRequestDelegate* delegate_; PendingConnectionRequestDelegate* delegate_;
mojom::ConnectionDelegatePtr connection_delegate_ptr_;
bool is_active_ = true;
base::WeakPtrFactory<PendingConnectionRequest> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(PendingConnectionRequest); DISALLOW_COPY_AND_ASSIGN(PendingConnectionRequest);
}; };
......
// Copyright 2018 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.
#ifndef CHROMEOS_SERVICES_SECURE_CHANNEL_PENDING_CONNECTION_REQUEST_BASE_H_
#define CHROMEOS_SERVICES_SECURE_CHANNEL_PENDING_CONNECTION_REQUEST_BASE_H_
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "chromeos/components/proximity_auth/logging/logging.h"
#include "chromeos/services/secure_channel/pending_connection_request.h"
#include "chromeos/services/secure_channel/public/mojom/secure_channel.mojom.h"
namespace chromeos {
namespace secure_channel {
// Encapsulates metadata for a pending request for a connection to a remote
// device. Every PendingConnectionRequestBase starts out active (i.e., there
// exists an ongoing attempt to create a connection). The client of this class
// can cancel an active attempt by disconnecting the ConnectionDelegatePtr
// passed PendingConnectionRequestBase's constructor; likewise, a
// PendingConnectionRequestBase can become inactive due to connection failures.
//
// Each connection type should implement its own pending request class deriving
// from PendingConnectionRequestBase.
template <typename FailureDetailType>
class PendingConnectionRequestBase
: public PendingConnectionRequest<FailureDetailType> {
public:
~PendingConnectionRequestBase() override = default;
protected:
PendingConnectionRequestBase(
const std::string& feature,
const std::string& readable_request_type_for_logging,
PendingConnectionRequestDelegate* delegate,
mojom::ConnectionDelegatePtr connection_delegate_ptr)
: PendingConnectionRequest<FailureDetailType>(delegate),
feature_(feature),
readable_request_type_for_logging_(readable_request_type_for_logging),
connection_delegate_ptr_(std::move(connection_delegate_ptr)),
weak_ptr_factory_(this) {
DCHECK(!feature_.empty());
DCHECK(connection_delegate_ptr_);
// If the client disconnects its delegate, the client is signaling that the
// connection request has been canceled.
connection_delegate_ptr_.set_connection_error_handler(base::BindOnce(
&PendingConnectionRequestBase::OnFinishedWithoutConnection,
weak_ptr_factory_.GetWeakPtr(),
PendingConnectionRequestDelegate::FailedConnectionReason::
kRequestCanceledByClient));
}
// Derived classes should invoke this function if they would like to give up
// on the request due to connection failures.
void StopRequestDueToConnectionFailures() {
OnFinishedWithoutConnection(PendingConnectionRequestDelegate::
FailedConnectionReason::kRequestFailed);
}
private:
// Make NotifyRequestFinishedWithoutConnection() inaccessible to derived
// types, which should use StopRequestDueToConnectionFailures() instead.
using PendingConnectionRequest<
FailureDetailType>::NotifyRequestFinishedWithoutConnection;
void OnFinishedWithoutConnection(
PendingConnectionRequestDelegate::FailedConnectionReason reason) {
PA_LOG(INFO) << "Request finished without connection; notifying delegate. "
<< "Feature: \"" << feature_ << "\""
<< ", Reason: " << reason << ", Request type: \""
<< readable_request_type_for_logging_ << "\"";
NotifyRequestFinishedWithoutConnection(reason);
}
const std::string feature_;
const std::string readable_request_type_for_logging_;
mojom::ConnectionDelegatePtr connection_delegate_ptr_;
base::WeakPtrFactory<PendingConnectionRequestBase> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(PendingConnectionRequestBase);
};
} // namespace secure_channel
} // namespace chromeos
#endif // CHROMEOS_SERVICES_SECURE_CHANNEL_PENDING_CONNECTION_REQUEST_BASE_H_
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "chromeos/services/secure_channel/pending_connection_request.h" #include "chromeos/services/secure_channel/pending_connection_request_base.h"
#include <memory> #include <memory>
...@@ -26,23 +26,23 @@ enum class TestFailureDetail { ...@@ -26,23 +26,23 @@ enum class TestFailureDetail {
kReasonWhichDoesNotCauseRequestToBecomeInactive kReasonWhichDoesNotCauseRequestToBecomeInactive
}; };
// Since PendingConnectionRequest is templatized, a concrete implementation is // Since PendingConnectionRequestBase is templatized, a concrete implementation
// needed for its test. // is needed for its test.
class TestPendingConnectionRequest class TestPendingConnectionRequest
: public PendingConnectionRequest<TestFailureDetail> { : public PendingConnectionRequestBase<TestFailureDetail> {
public: public:
TestPendingConnectionRequest( TestPendingConnectionRequest(
const std::string& feature, const std::string& feature,
mojom::ConnectionDelegatePtr connection_delegate_ptr, mojom::ConnectionDelegatePtr connection_delegate_ptr,
PendingConnectionRequestDelegate* delegate) PendingConnectionRequestDelegate* delegate)
: PendingConnectionRequest<TestFailureDetail>( : PendingConnectionRequestBase<TestFailureDetail>(
feature, feature,
kTestReadableRequestTypeForLogging, kTestReadableRequestTypeForLogging,
delegate, delegate,
std::move(connection_delegate_ptr)) {} std::move(connection_delegate_ptr)) {}
~TestPendingConnectionRequest() override = default; ~TestPendingConnectionRequest() override = default;
// PendingConnectionRequest<TestFailureDetail>: // PendingConnectionRequestBase<TestFailureDetail>:
void HandleConnectionFailure(TestFailureDetail failure_detail) override { void HandleConnectionFailure(TestFailureDetail failure_detail) override {
switch (failure_detail) { switch (failure_detail) {
case TestFailureDetail::kReasonWhichCausesRequestToBecomeInactive: case TestFailureDetail::kReasonWhichCausesRequestToBecomeInactive:
...@@ -57,10 +57,10 @@ class TestPendingConnectionRequest ...@@ -57,10 +57,10 @@ class TestPendingConnectionRequest
} // namespace } // namespace
class SecureChannelPendingConnectionRequestTest : public testing::Test { class SecureChannelPendingConnectionRequestBaseTest : public testing::Test {
protected: protected:
SecureChannelPendingConnectionRequestTest() = default; SecureChannelPendingConnectionRequestBaseTest() = default;
~SecureChannelPendingConnectionRequestTest() override = default; ~SecureChannelPendingConnectionRequestBaseTest() override = default;
void SetUp() override { void SetUp() override {
fake_connection_delegate_ = std::make_unique<FakeConnectionDelegate>(); fake_connection_delegate_ = std::make_unique<FakeConnectionDelegate>();
...@@ -102,35 +102,32 @@ class SecureChannelPendingConnectionRequestTest : public testing::Test { ...@@ -102,35 +102,32 @@ class SecureChannelPendingConnectionRequestTest : public testing::Test {
std::unique_ptr<TestPendingConnectionRequest> std::unique_ptr<TestPendingConnectionRequest>
test_pending_connection_request_; test_pending_connection_request_;
DISALLOW_COPY_AND_ASSIGN(SecureChannelPendingConnectionRequestTest); DISALLOW_COPY_AND_ASSIGN(SecureChannelPendingConnectionRequestBaseTest);
}; };
TEST_F(SecureChannelPendingConnectionRequestTest, TEST_F(SecureChannelPendingConnectionRequestBaseTest,
HandleConnectionFailureWhichCausesRequestToBecomeInactive) { HandleConnectionFailureWhichCausesRequestToBecomeInactive) {
test_pending_connection_request()->HandleConnectionFailure( test_pending_connection_request()->HandleConnectionFailure(
TestFailureDetail::kReasonWhichCausesRequestToBecomeInactive); TestFailureDetail::kReasonWhichCausesRequestToBecomeInactive);
EXPECT_FALSE(test_pending_connection_request()->is_active());
EXPECT_EQ( EXPECT_EQ(
PendingConnectionRequestDelegate::FailedConnectionReason::kRequestFailed, PendingConnectionRequestDelegate::FailedConnectionReason::kRequestFailed,
*GetFailedConnectionReason()); *GetFailedConnectionReason());
} }
TEST_F(SecureChannelPendingConnectionRequestTest, TEST_F(SecureChannelPendingConnectionRequestBaseTest,
HandleConnectionFailureWhichDoesNotCauseRequestToBecomeInactive) { HandleConnectionFailureWhichDoesNotCauseRequestToBecomeInactive) {
// Repeat 5 connection failures, none of which should cause the request to // Repeat 5 connection failures, none of which should cause the request to
// become inactive. // become inactive.
for (int i = 0; i < 5; ++i) { for (int i = 0; i < 5; ++i) {
test_pending_connection_request()->HandleConnectionFailure( test_pending_connection_request()->HandleConnectionFailure(
TestFailureDetail::kReasonWhichDoesNotCauseRequestToBecomeInactive); TestFailureDetail::kReasonWhichDoesNotCauseRequestToBecomeInactive);
EXPECT_TRUE(test_pending_connection_request()->is_active());
EXPECT_FALSE(GetFailedConnectionReason()); EXPECT_FALSE(GetFailedConnectionReason());
} }
} }
TEST_F(SecureChannelPendingConnectionRequestTest, TEST_F(SecureChannelPendingConnectionRequestBaseTest,
ConnectionDelegateInvalidated) { ConnectionDelegateInvalidated) {
DisconnectConnectionDelegatePtr(); DisconnectConnectionDelegatePtr();
EXPECT_FALSE(test_pending_connection_request()->is_active());
EXPECT_EQ(PendingConnectionRequestDelegate::FailedConnectionReason:: EXPECT_EQ(PendingConnectionRequestDelegate::FailedConnectionReason::
kRequestCanceledByClient, kRequestCanceledByClient,
*GetFailedConnectionReason()); *GetFailedConnectionReason());
......
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