Only grant permissions to new extensions from sync if they have the expected version
[chromium-blink-merge.git] / components / proximity_auth / bluetooth_connection_finder.cc
blob5a2aa3a94e925c5754d080f7ec4c921bb9110fe5
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/proximity_auth/bluetooth_connection_finder.h"
7 #include "base/bind.h"
8 #include "base/location.h"
9 #include "base/logging.h"
10 #include "base/single_thread_task_runner.h"
11 #include "base/thread_task_runner_handle.h"
12 #include "components/proximity_auth/bluetooth_connection.h"
13 #include "components/proximity_auth/logging/logging.h"
14 #include "device/bluetooth/bluetooth_adapter_factory.h"
16 using device::BluetoothAdapter;
18 namespace proximity_auth {
20 BluetoothConnectionFinder::BluetoothConnectionFinder(
21 const RemoteDevice& remote_device,
22 const device::BluetoothUUID& uuid,
23 const base::TimeDelta& polling_interval)
24 : remote_device_(remote_device),
25 uuid_(uuid),
26 polling_interval_(polling_interval),
27 has_delayed_poll_scheduled_(false),
28 weak_ptr_factory_(this) {
31 BluetoothConnectionFinder::~BluetoothConnectionFinder() {
32 UnregisterAsObserver();
35 void BluetoothConnectionFinder::Find(
36 const ConnectionCallback& connection_callback) {
37 if (!device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable()) {
38 PA_LOG(WARNING) << "Bluetooth is unsupported on this platform. Aborting.";
39 return;
42 DCHECK(start_time_.is_null());
43 PA_LOG(WARNING) << "Finding Bluetooth connection...";
45 start_time_ = base::TimeTicks::Now();
46 connection_callback_ = connection_callback;
48 device::BluetoothAdapterFactory::GetAdapter(
49 base::Bind(&BluetoothConnectionFinder::OnAdapterInitialized,
50 weak_ptr_factory_.GetWeakPtr()));
53 scoped_ptr<Connection> BluetoothConnectionFinder::CreateConnection() {
54 return scoped_ptr<Connection>(new BluetoothConnection(remote_device_, uuid_));
57 void BluetoothConnectionFinder::SeekDeviceByAddress(
58 const std::string& bluetooth_address,
59 const base::Closure& callback,
60 const bluetooth_util::ErrorCallback& error_callback) {
61 bluetooth_util::SeekDeviceByAddress(
62 bluetooth_address, callback, error_callback,
63 base::ThreadTaskRunnerHandle::Get().get());
66 bool BluetoothConnectionFinder::IsReadyToPoll() {
67 bool is_adapter_available =
68 adapter_.get() && adapter_->IsPresent() && adapter_->IsPowered();
69 PA_LOG(INFO) << "Readiness: adapter="
70 << (is_adapter_available ? "available" : "unavailable");
71 return is_adapter_available;
74 void BluetoothConnectionFinder::PollIfReady() {
75 if (!IsReadyToPoll())
76 return;
78 // If there is a pending task to poll at a later time, the time requisite
79 // timeout has not yet elapsed since the previous polling attempt. In that
80 // case, keep waiting until the delayed task comes in.
81 if (has_delayed_poll_scheduled_)
82 return;
84 // If the |connection_| is pending, wait for it to connect or fail prior to
85 // polling again.
86 if (connection_ && connection_->status() != Connection::DISCONNECTED)
87 return;
89 // This SeekDeviceByAddress operation is needed to connect to a device if
90 // it is not already known to the adapter.
91 if (!adapter_->GetDevice(remote_device_.bluetooth_address)) {
92 PA_LOG(INFO) << "Remote device [" << remote_device_.bluetooth_address
93 << "] is not known. "
94 << "Seeking device directly by address...";
96 SeekDeviceByAddress(
97 remote_device_.bluetooth_address,
98 base::Bind(&BluetoothConnectionFinder::OnSeekedDeviceByAddress,
99 weak_ptr_factory_.GetWeakPtr()),
100 base::Bind(&BluetoothConnectionFinder::OnSeekedDeviceByAddressError,
101 weak_ptr_factory_.GetWeakPtr()));
102 } else {
103 PA_LOG(INFO) << "Remote device known, connecting...";
104 connection_ = CreateConnection();
105 connection_->AddObserver(this);
106 connection_->Connect();
110 void BluetoothConnectionFinder::PostDelayedPoll() {
111 if (has_delayed_poll_scheduled_) {
112 PA_LOG(WARNING) << "Delayed poll already scheduled, skipping.";
113 return;
116 PA_LOG(INFO) << "Posting delayed poll..";
117 has_delayed_poll_scheduled_ = true;
118 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
119 FROM_HERE, base::Bind(&BluetoothConnectionFinder::OnDelayedPoll,
120 weak_ptr_factory_.GetWeakPtr()),
121 polling_interval_);
124 void BluetoothConnectionFinder::OnDelayedPoll() {
125 // Note that there is no longer a pending task, and therefore polling is
126 // permitted.
127 has_delayed_poll_scheduled_ = false;
128 PollIfReady();
131 void BluetoothConnectionFinder::OnSeekedDeviceByAddress() {
132 // Sanity check that the remote device is now known by the adapter.
133 if (adapter_->GetDevice(remote_device_.bluetooth_address))
134 PollIfReady();
135 else
136 PostDelayedPoll();
139 void BluetoothConnectionFinder::OnSeekedDeviceByAddressError(
140 const std::string& error_message) {
141 PA_LOG(ERROR) << "Failed to seek device: " << error_message;
142 PostDelayedPoll();
145 void BluetoothConnectionFinder::UnregisterAsObserver() {
146 if (connection_) {
147 connection_->RemoveObserver(this);
148 // The connection is about to be released or destroyed, so no need to clear
149 // it explicitly here.
152 if (adapter_.get()) {
153 adapter_->RemoveObserver(this);
154 adapter_ = NULL;
158 void BluetoothConnectionFinder::OnAdapterInitialized(
159 scoped_refptr<BluetoothAdapter> adapter) {
160 adapter_ = adapter;
161 adapter_->AddObserver(this);
162 PollIfReady();
165 void BluetoothConnectionFinder::AdapterPresentChanged(BluetoothAdapter* adapter,
166 bool present) {
167 PollIfReady();
170 void BluetoothConnectionFinder::AdapterPoweredChanged(BluetoothAdapter* adapter,
171 bool powered) {
172 PollIfReady();
175 void BluetoothConnectionFinder::OnConnectionStatusChanged(
176 Connection* connection,
177 Connection::Status old_status,
178 Connection::Status new_status) {
179 DCHECK_EQ(connection, connection_.get());
181 if (connection_->IsConnected()) {
182 base::TimeDelta elapsed = base::TimeTicks::Now() - start_time_;
183 PA_LOG(WARNING) << "Connection found! Elapsed Time: "
184 << elapsed.InMilliseconds() << "ms.";
185 UnregisterAsObserver();
187 // If we invoke the callback now, the callback function may install its own
188 // observer to |connection_|. Because we are in the ConnectionObserver
189 // callstack, this new observer will receive this connection event.
190 // Therefore, we need to invoke the callback asynchronously.
191 base::ThreadTaskRunnerHandle::Get()->PostTask(
192 FROM_HERE, base::Bind(&BluetoothConnectionFinder::InvokeCallbackAsync,
193 weak_ptr_factory_.GetWeakPtr()));
194 } else if (old_status == Connection::IN_PROGRESS) {
195 PA_LOG(WARNING)
196 << "Connection failed! Scheduling another polling iteration.";
197 PostDelayedPoll();
201 void BluetoothConnectionFinder::InvokeCallbackAsync() {
202 connection_callback_.Run(connection_.Pass());
205 } // namespace proximity_auth