Commit ac4df1c4 authored by isherman's avatar isherman Committed by Commit bot

[Easy Unlock] Port the BluetoothConnectionFinder class to native code.

A couple of pieces are left as TODOs for future CLs:
  * Porting the "seek device by Bluetooth address" feature.
  * Wiring up a screen lock state accessor.

BUG=420946
TEST=components_unittests
R=tengs@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#299415}
parent c00b05d4
...@@ -668,6 +668,7 @@ ...@@ -668,6 +668,7 @@
'copresence/rpc/rpc_handler_unittest.cc', 'copresence/rpc/rpc_handler_unittest.cc',
'copresence/timed_map_unittest.cc', 'copresence/timed_map_unittest.cc',
'proximity_auth/bluetooth_connection_unittest.cc', 'proximity_auth/bluetooth_connection_unittest.cc',
'proximity_auth/bluetooth_connection_finder_unittest.cc',
'proximity_auth/connection_unittest.cc', 'proximity_auth/connection_unittest.cc',
'proximity_auth/cryptauth/cryptauth_api_call_flow_unittest.cc', 'proximity_auth/cryptauth/cryptauth_api_call_flow_unittest.cc',
'proximity_auth/proximity_auth_system_unittest.cc', 'proximity_auth/proximity_auth_system_unittest.cc',
......
...@@ -18,11 +18,14 @@ ...@@ -18,11 +18,14 @@
'sources': [ 'sources': [
"proximity_auth/bluetooth_connection.cc", "proximity_auth/bluetooth_connection.cc",
"proximity_auth/bluetooth_connection.h", "proximity_auth/bluetooth_connection.h",
"proximity_auth/bluetooth_connection_finder.cc",
"proximity_auth/bluetooth_connection_finder.h",
"proximity_auth/bluetooth_util.cc", "proximity_auth/bluetooth_util.cc",
"proximity_auth/bluetooth_util_chromeos.cc", "proximity_auth/bluetooth_util_chromeos.cc",
"proximity_auth/bluetooth_util.h", "proximity_auth/bluetooth_util.h",
"proximity_auth/connection.cc", "proximity_auth/connection.cc",
"proximity_auth/connection.h", "proximity_auth/connection.h",
"proximity_auth/connection_finder.h",
"proximity_auth/connection_observer.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",
......
...@@ -6,11 +6,14 @@ source_set("proximity_auth") { ...@@ -6,11 +6,14 @@ source_set("proximity_auth") {
sources = [ sources = [
"bluetooth_connection.cc", "bluetooth_connection.cc",
"bluetooth_connection.h", "bluetooth_connection.h",
"bluetooth_connection_finder.cc",
"bluetooth_connection_finder.h",
"bluetooth_util.cc", "bluetooth_util.cc",
"bluetooth_util_chromeos.cc", "bluetooth_util_chromeos.cc",
"bluetooth_util.h", "bluetooth_util.h",
"connection.cc", "connection.cc",
"connection.h", "connection.h",
"connection_finder.h",
"connection_observer.h", "connection_observer.h",
"proximity_auth_system.cc", "proximity_auth_system.cc",
"proximity_auth_system.h", "proximity_auth_system.h",
...@@ -32,6 +35,7 @@ source_set("unit_tests") { ...@@ -32,6 +35,7 @@ source_set("unit_tests") {
testonly = true testonly = true
sources = [ sources = [
"bluetooth_connection_unittest.cc", "bluetooth_connection_unittest.cc",
"bluetooth_connection_finder_unittest.cc",
"connection_unittest.cc", "connection_unittest.cc",
"proximity_auth_system_unittest.cc", "proximity_auth_system_unittest.cc",
"remote_status_update_unittest.cc", "remote_status_update_unittest.cc",
...@@ -51,11 +55,6 @@ source_set("unit_tests") { ...@@ -51,11 +55,6 @@ source_set("unit_tests") {
# Note: This is a convenience target for ease of rapid iteration during # Note: This is a convenience target for ease of rapid iteration during
# development. It is not executed on any try or build bots. # development. It is not executed on any try or build bots.
test("proximity_auth_unittests") { test("proximity_auth_unittests") {
sources = [ sources = [ "run_all_unittests.cc" ]
"run_all_unittests.cc", deps = [ ":unit_tests" ]
]
deps = [
":unit_tests",
]
} }
...@@ -120,6 +120,8 @@ void BluetoothConnection::OnAdapterInitialized( ...@@ -120,6 +120,8 @@ void BluetoothConnection::OnAdapterInitialized(
if (!bluetooth_device) { if (!bluetooth_device) {
VLOG(1) << "[BC] Device with address " << address VLOG(1) << "[BC] Device with address " << address
<< " is not known to the system Bluetooth daemon."; << " is not known to the system Bluetooth daemon.";
// TOOD(isherman): Optimistically attempt to seek the device and connect
// anyway, as was previously implemented in BluetoothConnectionFinder.
Disconnect(); Disconnect();
return; return;
} }
......
// 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/bluetooth_connection_finder.h"
#include "base/bind.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/message_loop/message_loop_proxy.h"
#include "components/proximity_auth/bluetooth_connection.h"
#include "device/bluetooth/bluetooth_adapter_factory.h"
using device::BluetoothAdapter;
namespace proximity_auth {
BluetoothConnectionFinder::BluetoothConnectionFinder(
const RemoteDevice& remote_device,
const device::BluetoothUUID& uuid,
const base::TimeDelta& polling_interval)
: remote_device_(remote_device),
uuid_(uuid),
polling_interval_(polling_interval),
has_delayed_poll_scheduled_(false),
weak_ptr_factory_(this) {
}
BluetoothConnectionFinder::~BluetoothConnectionFinder() {
UnregisterAsObserver();
}
void BluetoothConnectionFinder::Find(
const ConnectionCallback& connection_callback) {
if (!device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable()) {
VLOG(1) << "[BCF] Bluetooth is unsupported on this platform. Aborting.";
return;
}
DCHECK(start_time_.is_null());
VLOG(1) << "[BCF] Finding Bluetooth connection...";
start_time_ = base::TimeTicks::Now();
connection_callback_ = connection_callback;
device::BluetoothAdapterFactory::GetAdapter(
base::Bind(&BluetoothConnectionFinder::OnAdapterInitialized,
weak_ptr_factory_.GetWeakPtr()));
}
scoped_ptr<Connection> BluetoothConnectionFinder::CreateConnection() {
return scoped_ptr<Connection>(new BluetoothConnection(remote_device_, uuid_));
}
bool BluetoothConnectionFinder::IsReadyToPoll() {
bool is_adapter_available =
adapter_.get() && adapter_->IsPresent() && adapter_->IsPowered();
VLOG(1) << "[BCF] Readiness: adapter="
<< (is_adapter_available ? "available" : "unavailable");
return is_adapter_available;
}
void BluetoothConnectionFinder::PollIfReady() {
if (!IsReadyToPoll())
return;
// If there is a pending task to poll at a later time, the time requisite
// timeout has not yet elapsed since the previous polling attempt. In that
// case, keep waiting until the delayed task comes in.
if (has_delayed_poll_scheduled_)
return;
// If the |connection_| exists, wait for it to connect or fail prior to
// polling again.
if (connection_)
return;
VLOG(1) << "[BCF] Polling for connection...";
connection_ = CreateConnection();
connection_->AddObserver(this);
connection_->Connect();
}
void BluetoothConnectionFinder::DelayedPollIfReady() {
// Note that there is no longer a pending task, and therefore polling is
// permitted.
has_delayed_poll_scheduled_ = false;
PollIfReady();
}
void BluetoothConnectionFinder::UnregisterAsObserver() {
if (connection_) {
connection_->RemoveObserver(this);
// The connection is about to be released or destroyed, so no need to clear
// it explicitly here.
}
if (adapter_.get()) {
adapter_->RemoveObserver(this);
adapter_ = NULL;
}
}
void BluetoothConnectionFinder::OnAdapterInitialized(
scoped_refptr<BluetoothAdapter> adapter) {
adapter_ = adapter;
adapter_->AddObserver(this);
PollIfReady();
}
void BluetoothConnectionFinder::AdapterPresentChanged(BluetoothAdapter* adapter,
bool present) {
PollIfReady();
}
void BluetoothConnectionFinder::AdapterPoweredChanged(BluetoothAdapter* adapter,
bool powered) {
PollIfReady();
}
void BluetoothConnectionFinder::OnConnectionStatusChanged(
const Connection& connection,
Connection::Status old_status,
Connection::Status new_status) {
DCHECK_EQ(&connection, connection_.get());
if (connection_->IsConnected()) {
base::TimeDelta elapsed = base::TimeTicks::Now() - start_time_;
VLOG(1) << "[BCF] Connection found! Elapsed Time: "
<< elapsed.InMilliseconds() << "ms.";
UnregisterAsObserver();
connection_callback_.Run(connection_.Pass());
} else if (old_status == Connection::IN_PROGRESS) {
VLOG(1) << "[BCF] Connection failed! Scheduling another polling iteration.";
connection_.reset();
has_delayed_poll_scheduled_ = true;
base::MessageLoopProxy::current()->PostDelayedTask(
FROM_HERE,
base::Bind(&BluetoothConnectionFinder::DelayedPollIfReady,
weak_ptr_factory_.GetWeakPtr()),
polling_interval_);
}
}
} // 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_BLUETOOTH_CONNECTION_FINDER_H
#define COMPONENTS_PROXIMITY_AUTH_BLUETOOTH_CONNECTION_FINDER_H
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "components/proximity_auth/connection_finder.h"
#include "components/proximity_auth/connection_observer.h"
#include "components/proximity_auth/remote_device.h"
#include "device/bluetooth/bluetooth_adapter.h"
#include "device/bluetooth/bluetooth_uuid.h"
namespace proximity_auth {
class BluetoothConnection;
// This ConnectionFinder implementation tries to find a Bluetooth connection to
// the remote device by polling at a fixed interval.
class BluetoothConnectionFinder : public ConnectionFinder,
public ConnectionObserver,
public device::BluetoothAdapter::Observer {
public:
BluetoothConnectionFinder(const RemoteDevice& remote_device,
const device::BluetoothUUID& uuid,
const base::TimeDelta& polling_interval);
virtual ~BluetoothConnectionFinder();
// ConnectionFinder:
virtual void Find(const ConnectionCallback& connection_callback) override;
protected:
// Exposed for mocking out the connection in tests.
virtual scoped_ptr<Connection> CreateConnection();
// BluetoothAdapter::Observer:
virtual void AdapterPresentChanged(device::BluetoothAdapter* adapter,
bool present) override;
virtual void AdapterPoweredChanged(device::BluetoothAdapter* adapter,
bool powered) override;
private:
// Returns true iff the Bluetooth adapter is ready to make connections.
bool IsReadyToPoll();
// Attempts to connect to the |remote_device_| if the system is ready for
// another iteration of polling.
void PollIfReady();
// Wrapper around |PollIfReady()| that can be posted as a delayed task.
void DelayedPollIfReady();
// Unregisters |this| instance as an observer from all objects that it might
// have registered with.
void UnregisterAsObserver();
// Callback to be called when the Bluetooth adapter is initialized.
void OnAdapterInitialized(scoped_refptr<device::BluetoothAdapter> adapter);
// ConnectionObserver:
virtual void OnConnectionStatusChanged(
const Connection& connection,
Connection::Status old_status,
Connection::Status new_status) override;
// The remote device to connect to.
const RemoteDevice remote_device_;
// The UUID of the service on the remote device.
const device::BluetoothUUID uuid_;
// The time to wait between polling attempts.
const base::TimeDelta polling_interval_;
// Records the time at which the finder began searching for connections.
base::TimeTicks start_time_;
// The callback that should be called upon a successful connection.
ConnectionCallback connection_callback_;
// The Bluetooth adapter over which the Bluetooth connection will be made.
scoped_refptr<device::BluetoothAdapter> adapter_;
// The Bluetooth connection that will be opened.
scoped_ptr<Connection> connection_;
// Whether there is currently a polling task scheduled.
bool has_delayed_poll_scheduled_;
// Used to schedule everything else.
base::WeakPtrFactory<BluetoothConnectionFinder> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(BluetoothConnectionFinder);
};
// TODO(isherman): Make sure to wire up the controller to listen for screen lock
// state change events, and create or destroy the connection finder as
// appropriate.
} // namespace proximity_auth
#endif // COMPONENTS_PROXIMITY_AUTH_BLUETOOTH_CONNECTION_FINDER_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_FINDER_H
#define COMPONENTS_PROXIMITY_AUTH_CONNECTION_FINDER_H
#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
namespace proximity_auth {
class Connection;
// Interface for finding a connection to a remote device.
class ConnectionFinder {
public:
ConnectionFinder() {}
virtual ~ConnectionFinder() {}
// Attempts to find a connection to a remote device. The finder will try to
// find the connection indefinitely until the finder is destroyed. Calls
// |connection_callback| with the open connection once the remote device is
// connected.
// TODO(isherman): Can this just be done as part of the constructor?
typedef base::Callback<void(scoped_ptr<Connection> connection)>
ConnectionCallback;
virtual void Find(const ConnectionCallback& connection_callback) = 0;
private:
DISALLOW_COPY_AND_ASSIGN(ConnectionFinder);
};
} // namespace proximity_auth
#endif // COMPONENTS_PROXIMITY_AUTH_CONNECTION_FINDER_H
...@@ -18,18 +18,18 @@ class ConnectionObserver { ...@@ -18,18 +18,18 @@ class ConnectionObserver {
// |new_status|. // |new_status|.
virtual void OnConnectionStatusChanged(const Connection& connection, virtual void OnConnectionStatusChanged(const Connection& connection,
Connection::Status old_status, Connection::Status old_status,
Connection::Status new_status) = 0; Connection::Status new_status) {}
// Called when a |message| is received from a remote device over the // Called when a |message| is received from a remote device over the
// |connection|. // |connection|.
virtual void OnMessageReceived(const Connection& connection, virtual void OnMessageReceived(const Connection& connection,
const WireMessage& message) = 0; const WireMessage& message) {}
// Called after a |message| is sent to the remote device over the // Called after a |message| is sent to the remote device over the
// |connection|. |success| is |true| iff the message is sent successfully. // |connection|. |success| is |true| iff the message is sent successfully.
virtual void OnSendCompleted(const Connection& connection, virtual void OnSendCompleted(const Connection& connection,
const WireMessage& message, const WireMessage& message,
bool success) = 0; bool success) {}
}; };
} // namespace proximity_auth } // namespace proximity_auth
......
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