Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(624)

Unified Diff: components/proximity_auth/bluetooth_connection_finder.cc

Issue 1277483007: Implement finding BLE connections in chrome://proximity-auth. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: refactor unit test Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: components/proximity_auth/bluetooth_connection_finder.cc
diff --git a/components/proximity_auth/bluetooth_connection_finder.cc b/components/proximity_auth/bluetooth_connection_finder.cc
index 7596a11c04f49bd9aa4d9c1df65a1ead3badd37d..00b51462e767262cab80600e2ca2b9423c0fdac5 100644
--- a/components/proximity_auth/bluetooth_connection_finder.cc
+++ b/components/proximity_auth/bluetooth_connection_finder.cc
@@ -54,6 +54,15 @@ scoped_ptr<Connection> BluetoothConnectionFinder::CreateConnection() {
return scoped_ptr<Connection>(new BluetoothConnection(remote_device_, uuid_));
}
+void BluetoothConnectionFinder::SeekDeviceByAddress(
+ const std::string& bluetooth_address,
+ const base::Closure& callback,
+ const bluetooth_util::ErrorCallback& error_callback) {
+ bluetooth_util::SeekDeviceByAddress(
+ bluetooth_address, callback, error_callback,
+ base::ThreadTaskRunnerHandle::Get().get());
+}
+
bool BluetoothConnectionFinder::IsReadyToPoll() {
bool is_adapter_available =
adapter_.get() && adapter_->IsPresent() && adapter_->IsPowered();
@@ -77,19 +86,62 @@ void BluetoothConnectionFinder::PollIfReady() {
if (connection_)
return;
- PA_LOG(INFO) << "Polling for connection...";
- connection_ = CreateConnection();
- connection_->AddObserver(this);
- connection_->Connect();
+ // This SeekDeviceByAddress operation is needed to connect to a device if
+ // it is not already known to the adapter.
+ if (!adapter_->GetDevice(remote_device_.bluetooth_address)) {
+ PA_LOG(INFO) << "Remote device [" << remote_device_.bluetooth_address
+ << "] is not known. "
+ << "Seeking device directly by address...";
+
+ SeekDeviceByAddress(
+ remote_device_.bluetooth_address,
+ base::Bind(&BluetoothConnectionFinder::OnSeekedDeviceByAddress,
+ weak_ptr_factory_.GetWeakPtr()),
+ base::Bind(&BluetoothConnectionFinder::OnSeekedDeviceByAddressError,
+ weak_ptr_factory_.GetWeakPtr()));
+ } else {
+ PA_LOG(INFO) << "Remote device known, connecting...";
+ connection_ = CreateConnection();
+ connection_->AddObserver(this);
+ connection_->Connect();
+ }
+}
+
+void BluetoothConnectionFinder::PostDelayedPoll() {
+ if (has_delayed_poll_scheduled_) {
+ PA_LOG(WARNING) << "Delayed poll already scheduled, skipping.";
+ return;
+ }
+
+ PA_LOG(INFO) << "Posting delayed poll..";
+ has_delayed_poll_scheduled_ = true;
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, base::Bind(&BluetoothConnectionFinder::OnDelayedPoll,
+ weak_ptr_factory_.GetWeakPtr()),
+ polling_interval_);
}
-void BluetoothConnectionFinder::DelayedPollIfReady() {
+void BluetoothConnectionFinder::OnDelayedPoll() {
// Note that there is no longer a pending task, and therefore polling is
// permitted.
has_delayed_poll_scheduled_ = false;
PollIfReady();
}
+void BluetoothConnectionFinder::OnSeekedDeviceByAddress() {
+ // Sanity check that the remote device is now known by the adapter.
+ if (adapter_->GetDevice(remote_device_.bluetooth_address))
+ PollIfReady();
+ else
+ PostDelayedPoll();
+}
+
+void BluetoothConnectionFinder::OnSeekedDeviceByAddressError(
+ const std::string& error_message) {
+ PA_LOG(ERROR) << "Failed to seek device: " << error_message;
+ PostDelayedPoll();
+}
+
void BluetoothConnectionFinder::UnregisterAsObserver() {
if (connection_) {
connection_->RemoveObserver(this);
@@ -131,17 +183,24 @@ void BluetoothConnectionFinder::OnConnectionStatusChanged(
PA_LOG(WARNING) << "Connection found! Elapsed Time: "
<< elapsed.InMilliseconds() << "ms.";
UnregisterAsObserver();
- connection_callback_.Run(connection_.Pass());
+
+ // If we invoke the callback now, the callback function may install its own
+ // observer to |connection_|. Because we are in the ConnectionObserver
+ // callstack, this new observer will receive this connection event.
+ // Therefore, we need to invoke the callback asynchronously.
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(&BluetoothConnectionFinder::InvokeCallbackAsync,
+ weak_ptr_factory_.GetWeakPtr()));
} else if (old_status == Connection::IN_PROGRESS) {
PA_LOG(WARNING)
<< "Connection failed! Scheduling another polling iteration.";
connection_.reset();
- has_delayed_poll_scheduled_ = true;
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::Bind(&BluetoothConnectionFinder::DelayedPollIfReady,
- weak_ptr_factory_.GetWeakPtr()),
- polling_interval_);
+ PostDelayedPoll();
}
}
+void BluetoothConnectionFinder::InvokeCallbackAsync() {
+ connection_callback_.Run(connection_.Pass());
+}
+
} // namespace proximity_auth

Powered by Google App Engine
This is Rietveld 408576698