Commit 06c6a9a7 authored by isherman's avatar isherman Committed by Commit bot

[EasyUnlock] Port Connection class to native code.

BUG=410639
TEST=components_unittests
R=tengs@chromium.org, cbentzel@chromium.org

Review URL: https://codereview.chromium.org/538843002

Cr-Commit-Position: refs/heads/master@{#294114}
parent 3c4d6ceb
...@@ -174,6 +174,7 @@ ...@@ -174,6 +174,7 @@
'precache/core/precache_database_unittest.cc', 'precache/core/precache_database_unittest.cc',
'precache/core/precache_fetcher_unittest.cc', 'precache/core/precache_fetcher_unittest.cc',
'precache/core/precache_url_table_unittest.cc', 'precache/core/precache_url_table_unittest.cc',
'proximity_auth/connection_unittest.cc',
'proximity_auth/proximity_auth_system_unittest.cc', 'proximity_auth/proximity_auth_system_unittest.cc',
'query_parser/query_parser_unittest.cc', 'query_parser/query_parser_unittest.cc',
'query_parser/snippet_unittest.cc', 'query_parser/snippet_unittest.cc',
......
...@@ -14,9 +14,14 @@ ...@@ -14,9 +14,14 @@
'../base/base.gyp:base', '../base/base.gyp:base',
], ],
'sources': [ 'sources': [
"proximity_auth/connection.cc",
"proximity_auth/connection.h",
"proximity_auth/connection_observer.h",
"proximity_auth/proximity_auth_system.cc", "proximity_auth/proximity_auth_system.cc",
"proximity_auth/proximity_auth_system.h", "proximity_auth/proximity_auth_system.h",
"proximity_auth/remote_device.h", "proximity_auth/remote_device.h",
"proximity_auth/wire_message.cc",
"proximity_auth/wire_message.h",
], ],
}, },
], ],
......
...@@ -4,9 +4,14 @@ ...@@ -4,9 +4,14 @@
static_library("proximity_auth") { static_library("proximity_auth") {
sources = [ sources = [
"connection.cc",
"connection.h",
"connection_observer.h",
"proximity_auth_system.cc", "proximity_auth_system.cc",
"proximity_auth_system.h", "proximity_auth_system.h",
"remote_device.h", "remote_device.h",
"wire_message.cc",
"wire_message.h",
] ]
deps = [ deps = [
...@@ -17,12 +22,14 @@ static_library("proximity_auth") { ...@@ -17,12 +22,14 @@ static_library("proximity_auth") {
source_set("unit_tests") { source_set("unit_tests") {
testonly = true testonly = true
sources = [ sources = [
"connection_unittest.cc",
"proximity_auth_system_unittest.cc", "proximity_auth_system_unittest.cc",
] ]
deps = [ deps = [
":proximity_auth", ":proximity_auth",
"//base/test:test_support", "//base/test:test_support",
"//testing/gmock",
"//testing/gtest", "//testing/gtest",
] ]
} }
include_rules = [ include_rules = [
"+net",
] ]
// Copyright 2014 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 "components/proximity_auth/connection.h"
#include "base/logging.h"
#include "components/proximity_auth/connection_observer.h"
#include "components/proximity_auth/wire_message.h"
namespace proximity_auth {
Connection::Connection(const RemoteDevice& remote_device)
: remote_device_(remote_device),
status_(DISCONNECTED),
is_sending_message_(false) {
}
Connection::~Connection() {
}
bool Connection::IsConnected() const {
return status_ == CONNECTED;
}
void Connection::SendMessage(scoped_ptr<WireMessage> message) {
if (!IsConnected()) {
VLOG(1) << "Cannot send message when disconnected.";
return;
}
if (is_sending_message_) {
VLOG(1) << "Another message is currently in progress.";
return;
}
is_sending_message_ = true;
SendMessageImpl(message.Pass());
}
void Connection::AddObserver(ConnectionObserver* observer) {
observers_.AddObserver(observer);
}
void Connection::RemoveObserver(ConnectionObserver* observer) {
observers_.RemoveObserver(observer);
}
void Connection::SetStatus(Status status) {
if (status_ == status)
return;
received_bytes_.clear();
Status old_status = status_;
status_ = status;
FOR_EACH_OBSERVER(ConnectionObserver,
observers_,
OnConnectionStatusChanged(*this, old_status, status_));
}
void Connection::OnDidSendMessage(const WireMessage& message, bool success) {
if (!is_sending_message_) {
VLOG(1) << "Send completed, but no message in progress.";
return;
}
is_sending_message_ = false;
FOR_EACH_OBSERVER(
ConnectionObserver, observers_, OnSendCompleted(*this, message, success));
}
void Connection::OnBytesReceived(const std::string& bytes) {
if (!IsConnected()) {
VLOG(1) << "Received bytes, but not connected.";
return;
}
received_bytes_ += bytes;
if (HasReceivedCompleteMessage()) {
scoped_ptr<WireMessage> message = DeserializeWireMessage();
if (message) {
FOR_EACH_OBSERVER(
ConnectionObserver, observers_, OnMessageReceived(*this, *message));
}
// Whether the message was parsed successfully or not, clear the
// |received_bytes_| buffer.
received_bytes_.clear();
}
}
bool Connection::HasReceivedCompleteMessage() {
return WireMessage::IsCompleteMessage(received_bytes_);
}
scoped_ptr<WireMessage> Connection::DeserializeWireMessage() {
return WireMessage::Deserialize(received_bytes_);
}
} // namespace proximity_auth
// Copyright 2014 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 COMPONENTS_PROXIMITY_AUTH_CONNECTION_H
#define COMPONENTS_PROXIMITY_AUTH_CONNECTION_H
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/observer_list.h"
#include "components/proximity_auth/remote_device.h"
namespace proximity_auth {
class ConnectionObserver;
class WireMessage;
// Base class representing a connection with a remote device, which is a
// persistent bidirectional channel for sending and receiving wire messages.
class Connection {
public:
enum Status {
DISCONNECTED,
IN_PROGRESS,
CONNECTED,
};
// Constructs a connection to the given |remote_device|.
explicit Connection(const RemoteDevice& remote_device);
~Connection();
// Returns true iff the connection's status is CONNECTED.
bool IsConnected() const;
// Sends a message to the remote device.
// |OnSendCompleted()| will be called for all observers upon completion with
// either success or failure.
void SendMessage(scoped_ptr<WireMessage> message);
void AddObserver(ConnectionObserver* observer);
void RemoveObserver(ConnectionObserver* observer);
const RemoteDevice& remote_device() const { return remote_device_; }
// Abstract methods that subclasses should implement:
// Pauses or unpauses the handling of incoming messages. Pausing allows the
// user of the connection to add or remove observers without missing messages.
virtual void SetPaused(bool paused) = 0;
// Attempts to connect to the remote device if not already connected.
virtual void Connect() = 0;
// Disconnects from the remote device.
virtual void Disconnect() = 0;
protected:
// Sets the connection's status to |status|. If this is different from the
// previous status, notifies observers of the change in status.
void SetStatus(Status status);
Status status() const { return status_; }
// Called after attempting to send bytes over the connection, whether the
// message was successfully sent or not.
void OnDidSendMessage(const WireMessage& message, bool success);
// Called when bytes are read from the connection. There should not be a send
// in progress when this function is called.
void OnBytesReceived(const std::string& bytes);
// Sends bytes over the connection. The implementing class should call
// OnSendCompleted() once the send succeeds or fails. At most one send will be
// in progress.
virtual void SendMessageImpl(scoped_ptr<WireMessage> message) = 0;
// Returns |true| iff the |received_bytes_| are long enough to contain a
// complete wire message. Exposed for testing.
virtual bool HasReceivedCompleteMessage();
// Deserializes the |recieved_bytes_| and returns the resulting WireMessage,
// or NULL if the message is malformed. Exposed for testing.
virtual scoped_ptr<WireMessage> DeserializeWireMessage();
private:
// The remote device corresponding to this connection.
const RemoteDevice remote_device_;
// The current status of the connection.
Status status_;
// The registered observers of the connection.
ObserverList<ConnectionObserver> observers_;
// A temporary buffer storing bytes received before a received message can be
// fully constructed.
std::string received_bytes_;
// Whether a message is currently in the process of being sent.
bool is_sending_message_;
DISALLOW_COPY_AND_ASSIGN(Connection);
};
} // namespace proximity_auth
#endif // COMPONENTS_PROXIMITY_AUTH_CONNECTION_H
// Copyright 2014 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 COMPONENTS_PROXIMITY_AUTH_CONNECTION_OBSERVER_H
#define COMPONENTS_PROXIMITY_AUTH_CONNECTION_OBSERVER_H
#include "components/proximity_auth/connection.h"
namespace proximity_auth {
class WireMessage;
// An interface for observing events that happen on a Connection.
class ConnectionObserver {
public:
// Called when the |connection|'s status changes from |old_status| to
// |new_status|.
virtual void OnConnectionStatusChanged(const Connection& connection,
Connection::Status old_status,
Connection::Status new_status) = 0;
// Called when a |message| is received from a remote device over the
// |connection|.
virtual void OnMessageReceived(const Connection& connection,
const WireMessage& message) = 0;
// Called after a |message| is sent to the remote device over the
// |connection|. |success| is |true| iff the message is sent successfully.
virtual void OnSendCompleted(const Connection& connection,
const WireMessage& message,
bool success) = 0;
};
} // namespace proximity_auth
#endif // COMPONENTS_PROXIMITY_AUTH_CONNECTION_OBSERVER_H
// Copyright 2014 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 "components/proximity_auth/connection.h"
#include "components/proximity_auth/connection_observer.h"
#include "components/proximity_auth/wire_message.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using testing::_;
using testing::NiceMock;
using testing::Return;
using testing::StrictMock;
namespace proximity_auth {
namespace {
class MockConnection : public Connection {
public:
MockConnection() : Connection(RemoteDevice()) {}
~MockConnection() {}
MOCK_METHOD1(SetPaused, void(bool paused));
MOCK_METHOD0(Connect, void());
MOCK_METHOD0(Disconnect, void());
MOCK_METHOD0(CancelConnectionAttempt, void());
MOCK_METHOD1(SendMessageImplProxy, void(WireMessage* message));
MOCK_METHOD0(HasReceivedCompleteMessage, bool());
MOCK_METHOD0(DeserializeWireMessageProxy, WireMessage*());
// Gmock only supports copyable types, so create simple wrapper methods for
// ease of mocking.
virtual void SendMessageImpl(scoped_ptr<WireMessage> message) OVERRIDE {
SendMessageImplProxy(message.get());
}
virtual scoped_ptr<WireMessage> DeserializeWireMessage() OVERRIDE {
return make_scoped_ptr(DeserializeWireMessageProxy());
}
using Connection::status;
using Connection::SetStatus;
using Connection::OnDidSendMessage;
using Connection::OnBytesReceived;
private:
DISALLOW_COPY_AND_ASSIGN(MockConnection);
};
class MockConnectionObserver : public ConnectionObserver {
public:
MockConnectionObserver() {}
virtual ~MockConnectionObserver() {}
MOCK_METHOD3(OnConnectionStatusChanged,
void(const Connection& connection,
Connection::Status old_status,
Connection::Status new_status));
MOCK_METHOD2(OnMessageReceived,
void(const Connection& connection, const WireMessage& message));
MOCK_METHOD3(OnSendCompleted,
void(const Connection& connection,
const WireMessage& message,
bool success));
private:
DISALLOW_COPY_AND_ASSIGN(MockConnectionObserver);
};
// Unlike WireMessage, offers a public constructor.
class TestWireMessage : public WireMessage {
public:
TestWireMessage() {}
virtual ~TestWireMessage() {}
private:
DISALLOW_COPY_AND_ASSIGN(TestWireMessage);
};
} // namespace
TEST(ProximityAuthConnectionTest, IsConnected) {
StrictMock<MockConnection> connection;
EXPECT_FALSE(connection.IsConnected());
connection.SetStatus(Connection::CONNECTED);
EXPECT_TRUE(connection.IsConnected());
connection.SetStatus(Connection::DISCONNECTED);
EXPECT_FALSE(connection.IsConnected());
connection.SetStatus(Connection::IN_PROGRESS);
EXPECT_FALSE(connection.IsConnected());
}
TEST(ProximityAuthConnectionTest, SendMessage_FailsWhenNotConnected) {
StrictMock<MockConnection> connection;
connection.SetStatus(Connection::IN_PROGRESS);
EXPECT_CALL(connection, SendMessageImplProxy(_)).Times(0);
connection.SendMessage(scoped_ptr<WireMessage>());
}
TEST(ProximityAuthConnectionTest,
SendMessage_FailsWhenAnotherMessageSendIsInProgress) {
NiceMock<MockConnection> connection;
connection.SetStatus(Connection::CONNECTED);
connection.SendMessage(scoped_ptr<WireMessage>());
EXPECT_CALL(connection, SendMessageImplProxy(_)).Times(0);
connection.SendMessage(scoped_ptr<WireMessage>());
}
TEST(ProximityAuthConnectionTest, SendMessage_SucceedsWhenConnected) {
StrictMock<MockConnection> connection;
connection.SetStatus(Connection::CONNECTED);
EXPECT_CALL(connection, SendMessageImplProxy(_));
connection.SendMessage(scoped_ptr<WireMessage>());
}
TEST(ProximityAuthConnectionTest,
SendMessage_SucceedsAfterPreviousMessageSendCompletes) {
NiceMock<MockConnection> connection;
connection.SetStatus(Connection::CONNECTED);
connection.SendMessage(scoped_ptr<WireMessage>());
connection.OnDidSendMessage(TestWireMessage(), true /* success */);
EXPECT_CALL(connection, SendMessageImplProxy(_));
connection.SendMessage(scoped_ptr<WireMessage>());
}
TEST(ProximityAuthConnectionTest, SetStatus_NotifiesObserversOfStatusChange) {
StrictMock<MockConnection> connection;
EXPECT_EQ(Connection::DISCONNECTED, connection.status());
StrictMock<MockConnectionObserver> observer;
connection.AddObserver(&observer);
EXPECT_CALL(
observer,
OnConnectionStatusChanged(
Ref(connection), Connection::DISCONNECTED, Connection::CONNECTED));
connection.SetStatus(Connection::CONNECTED);
}
TEST(ProximityAuthConnectionTest,
SetStatus_DoesntNotifyObserversIfStatusUnchanged) {
StrictMock<MockConnection> connection;
EXPECT_EQ(Connection::DISCONNECTED, connection.status());
StrictMock<MockConnectionObserver> observer;
connection.AddObserver(&observer);
EXPECT_CALL(observer, OnConnectionStatusChanged(_, _, _)).Times(0);
connection.SetStatus(Connection::DISCONNECTED);
}
TEST(ProximityAuthConnectionTest,
OnDidSendMessage_NotifiesObserversIfMessageSendInProgress) {
NiceMock<MockConnection> connection;
connection.SetStatus(Connection::CONNECTED);
connection.SendMessage(scoped_ptr<WireMessage>());
StrictMock<MockConnectionObserver> observer;
connection.AddObserver(&observer);
EXPECT_CALL(observer, OnSendCompleted(Ref(connection), _, true));
connection.OnDidSendMessage(TestWireMessage(), true /* success */);
}
TEST(ProximityAuthConnectionTest,
OnDidSendMessage_DoesntNotifyObserversIfNoMessageSendInProgress) {
NiceMock<MockConnection> connection;
connection.SetStatus(Connection::CONNECTED);
StrictMock<MockConnectionObserver> observer;
connection.AddObserver(&observer);
EXPECT_CALL(observer, OnSendCompleted(_, _, _)).Times(0);
connection.OnDidSendMessage(TestWireMessage(), true /* success */);
}
TEST(ProximityAuthConnectionTest,
OnBytesReceived_NotifiesObserversOnValidMessage) {
NiceMock<MockConnection> connection;
connection.SetStatus(Connection::CONNECTED);
StrictMock<MockConnectionObserver> observer;
connection.AddObserver(&observer);
ON_CALL(connection, HasReceivedCompleteMessage()).WillByDefault(Return(true));
ON_CALL(connection, DeserializeWireMessageProxy())
.WillByDefault(Return(new TestWireMessage));
EXPECT_CALL(observer, OnMessageReceived(Ref(connection), _));
connection.OnBytesReceived(std::string());
}
TEST(ProximityAuthConnectionTest,
OnBytesReceived_DoesntNotifyObserversIfNotConnected) {
StrictMock<MockConnection> connection;
connection.SetStatus(Connection::IN_PROGRESS);
StrictMock<MockConnectionObserver> observer;
connection.AddObserver(&observer);
EXPECT_CALL(observer, OnMessageReceived(_, _)).Times(0);
connection.OnBytesReceived(std::string());
}
TEST(ProximityAuthConnectionTest,
OnBytesReceived_DoesntNotifyObserversIfMessageIsIncomplete) {
NiceMock<MockConnection> connection;
connection.SetStatus(Connection::CONNECTED);
StrictMock<MockConnectionObserver> observer;
connection.AddObserver(&observer);
ON_CALL(connection, HasReceivedCompleteMessage())
.WillByDefault(Return(false));
EXPECT_CALL(observer, OnMessageReceived(_, _)).Times(0);
connection.OnBytesReceived(std::string());
}
TEST(ProximityAuthConnectionTest,
OnBytesReceived_DoesntNotifyObserversIfMessageIsInvalid) {
NiceMock<MockConnection> connection;
connection.SetStatus(Connection::CONNECTED);
StrictMock<MockConnectionObserver> observer;
connection.AddObserver(&observer);
ON_CALL(connection, HasReceivedCompleteMessage()).WillByDefault(Return(true));
ON_CALL(connection, DeserializeWireMessageProxy())
.WillByDefault(Return(static_cast<WireMessage*>(NULL)));
EXPECT_CALL(observer, OnMessageReceived(_, _)).Times(0);
connection.OnBytesReceived(std::string());
}
} // namespace proximity_auth
// Copyright 2014 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 "components/proximity_auth/wire_message.h"
namespace proximity_auth {
WireMessage::~WireMessage() {
}
// static
bool WireMessage::IsCompleteMessage(const std::string& serialized_message) {
// TODO(isherman): Implement.
return false;
}
// static
scoped_ptr<WireMessage> WireMessage::Deserialize(
const std::string& serialized_message) {
// TODO(isherman): Implement.
return scoped_ptr<WireMessage>();
}
WireMessage::WireMessage() {
// TODO(isherman): Implement.
}
} // namespace proximity_auth
// Copyright 2014 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 COMPONENTS_PROXIMITY_AUTH_WIRE_MESSAGE_H
#define COMPONENTS_PROXIMITY_AUTH_WIRE_MESSAGE_H
#include <string>
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
namespace proximity_auth {
class WireMessage {
public:
virtual ~WireMessage();
// Returns |true| iff the size of |message_bytes| is at least equal to the
// message length encoded in the message header. Returns false if the message
// header is not available.
static bool IsCompleteMessage(const std::string& message_bytes);
// Returns the deserialized message from |serialized_message|, or NULL if the
// message is malformed.
static scoped_ptr<WireMessage> Deserialize(
const std::string& serialized_message);
protected:
// Visible for tests.
WireMessage();
private:
DISALLOW_COPY_AND_ASSIGN(WireMessage);
};
} // namespace proximity_auth
#endif // COMPONENTS_PROXIMITY_AUTH_WIRE_MESSAGE_H
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