Don't preload rarely seen large images
[chromium-blink-merge.git] / components / proximity_auth / ble / proximity_auth_ble_system.cc
blob1a399b4a8366ab2aba8d208445555269b7940d4b
1 // Copyright 2015 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/ble/proximity_auth_ble_system.h"
7 #include "base/bind.h"
8 #include "base/location.h"
9 #include "base/logging.h"
10 #include "base/thread_task_runner_handle.h"
11 #include "components/proximity_auth/ble/bluetooth_low_energy_connection.h"
12 #include "components/proximity_auth/ble/bluetooth_low_energy_connection_finder.h"
13 #include "components/proximity_auth/ble/fake_wire_message.h"
14 #include "components/proximity_auth/connection.h"
15 #include "components/proximity_auth/cryptauth/base64url.h"
16 #include "components/proximity_auth/cryptauth/cryptauth_client.h"
17 #include "components/proximity_auth/cryptauth/proto/cryptauth_api.pb.h"
18 #include "components/proximity_auth/logging/logging.h"
19 #include "components/proximity_auth/proximity_auth_client.h"
20 #include "components/proximity_auth/remote_device.h"
21 #include "device/bluetooth/bluetooth_device.h"
22 #include "device/bluetooth/bluetooth_gatt_connection.h"
24 namespace proximity_auth {
26 namespace {
28 // The UUID of the Bluetooth Low Energy service.
29 const char kSmartLockServiceUUID[] = "b3b7e28e-a000-3e17-bd86-6e97b9e28c11";
31 // The UUID of the characteristic used to send data to the peripheral.
32 const char kToPeripheralCharUUID[] = "977c6674-1239-4e72-993b-502369b8bb5a";
34 // The UUID of the characteristic used to receive data from the peripheral.
35 const char kFromPeripheralCharUUID[] = "f4b904a2-a030-43b3-98a8-221c536c03cb";
37 // Polling interval in seconds.
38 const int kPollingIntervalSeconds = 5;
40 // String received when the remote device's screen is unlocked.
41 const char kScreenUnlocked[] = "Screen Unlocked";
43 // String send to poll the remote device screen state.
44 const char kPollScreenState[] = "PollScreenState";
46 // BluetoothLowEnergyConnection parameter, number of attempts to send a write
47 // request before failing.
48 const int kMaxNumberOfTries = 2;
50 } // namespace
52 ProximityAuthBleSystem::ScreenlockBridgeAdapter::ScreenlockBridgeAdapter(
53 ScreenlockBridge* screenlock_bridge)
54 : screenlock_bridge_(screenlock_bridge) {
57 ProximityAuthBleSystem::ScreenlockBridgeAdapter::ScreenlockBridgeAdapter() {
60 ProximityAuthBleSystem::ScreenlockBridgeAdapter::~ScreenlockBridgeAdapter() {
63 void ProximityAuthBleSystem::ScreenlockBridgeAdapter::AddObserver(
64 ScreenlockBridge::Observer* observer) {
65 screenlock_bridge_->AddObserver(observer);
68 void ProximityAuthBleSystem::ScreenlockBridgeAdapter::RemoveObserver(
69 ScreenlockBridge::Observer* observer) {
70 screenlock_bridge_->RemoveObserver(observer);
73 void ProximityAuthBleSystem::ScreenlockBridgeAdapter::Unlock(
74 ProximityAuthClient* client) {
75 screenlock_bridge_->Unlock(client->GetAuthenticatedUsername());
78 ProximityAuthBleSystem::ProximityAuthBleSystem(
79 ScreenlockBridge* screenlock_bridge,
80 ProximityAuthClient* proximity_auth_client,
81 scoped_ptr<CryptAuthClientFactory> cryptauth_client_factory)
82 : screenlock_bridge_(new ProximityAuthBleSystem::ScreenlockBridgeAdapter(
83 screenlock_bridge)),
84 proximity_auth_client_(proximity_auth_client),
85 cryptauth_client_factory_(cryptauth_client_factory.Pass()),
86 is_polling_screen_state_(false),
87 weak_ptr_factory_(this) {
88 PA_LOG(INFO) << "Starting Proximity Auth over Bluetooth Low Energy.";
89 screenlock_bridge_->AddObserver(this);
92 ProximityAuthBleSystem::ProximityAuthBleSystem(
93 scoped_ptr<ScreenlockBridgeAdapter> screenlock_bridge,
94 ProximityAuthClient* proximity_auth_client)
95 : screenlock_bridge_(screenlock_bridge.Pass()),
96 proximity_auth_client_(proximity_auth_client),
97 is_polling_screen_state_(false),
98 weak_ptr_factory_(this) {
99 PA_LOG(INFO) << "Starting Proximity Auth over Bluetooth Low Energy.";
100 screenlock_bridge_->AddObserver(this);
103 ProximityAuthBleSystem::~ProximityAuthBleSystem() {
104 PA_LOG(INFO) << "Stopping Proximity over Bluetooth Low Energy.";
105 screenlock_bridge_->RemoveObserver(this);
106 if (connection_)
107 connection_->RemoveObserver(this);
110 void ProximityAuthBleSystem::OnGetMyDevices(
111 const cryptauth::GetMyDevicesResponse& response) {
112 PA_LOG(INFO) << "Found " << response.devices_size()
113 << " devices on CryptAuth.";
114 unlock_keys_.clear();
115 for (const auto& device : response.devices()) {
116 // Cache BLE devices (|bluetooth_address().empty() == true|) that are
117 // keys (|unlock_key() == 1|).
118 if (device.unlock_key() && device.bluetooth_address().empty()) {
119 std::string base64_public_key;
120 Base64UrlEncode(device.public_key(), &base64_public_key);
121 unlock_keys_[base64_public_key] = device.friendly_device_name();
123 PA_LOG(INFO) << "friendly_name = " << device.friendly_device_name();
124 PA_LOG(INFO) << "public_key = " << base64_public_key;
127 PA_LOG(INFO) << "Found " << unlock_keys_.size() << " unlock keys.";
130 void ProximityAuthBleSystem::OnGetMyDevicesError(const std::string& error) {
131 PA_LOG(INFO) << "GetMyDevices failed: " << error;
134 // This should be called exclusively after the user has logged in. For instance,
135 // calling |GetUnlockKeys| from the constructor cause |GetMyDevices| to always
136 // return an error.
137 void ProximityAuthBleSystem::GetUnlockKeys() {
138 if (cryptauth_client_factory_) {
139 cryptauth_client_ = cryptauth_client_factory_->CreateInstance();
140 cryptauth::GetMyDevicesRequest request;
141 cryptauth_client_->GetMyDevices(
142 request, base::Bind(&ProximityAuthBleSystem::OnGetMyDevices,
143 weak_ptr_factory_.GetWeakPtr()),
144 base::Bind(&ProximityAuthBleSystem::OnGetMyDevicesError,
145 weak_ptr_factory_.GetWeakPtr()));
149 void ProximityAuthBleSystem::OnScreenDidLock(
150 ScreenlockBridge::LockHandler::ScreenType screen_type) {
151 PA_LOG(INFO) << "OnScreenDidLock: " << screen_type;
152 switch (screen_type) {
153 case ScreenlockBridge::LockHandler::SIGNIN_SCREEN:
154 connection_finder_.reset();
155 break;
156 case ScreenlockBridge::LockHandler::LOCK_SCREEN:
157 DCHECK(!connection_finder_);
158 connection_finder_.reset(CreateConnectionFinder());
159 connection_finder_->Find(
160 base::Bind(&ProximityAuthBleSystem::OnConnectionFound,
161 weak_ptr_factory_.GetWeakPtr()));
162 break;
163 case ScreenlockBridge::LockHandler::OTHER_SCREEN:
164 connection_finder_.reset();
165 break;
169 ConnectionFinder* ProximityAuthBleSystem::CreateConnectionFinder() {
170 return new BluetoothLowEnergyConnectionFinder(
171 kSmartLockServiceUUID, kToPeripheralCharUUID, kFromPeripheralCharUUID,
172 kMaxNumberOfTries);
175 void ProximityAuthBleSystem::OnScreenDidUnlock(
176 ScreenlockBridge::LockHandler::ScreenType screen_type) {
177 PA_LOG(INFO) << "OnScreenDidUnlock: " << screen_type;
179 // Fetch the unlock keys when the user signs in.
180 // TODO(sacomoto): refetch the keys periodically, in case a new device was
181 // added.
182 if (screen_type == ScreenlockBridge::LockHandler::SIGNIN_SCREEN)
183 GetUnlockKeys();
185 if (connection_) {
186 // Note: it's important to remove the observer before calling
187 // |Disconnect()|, otherwise |OnConnectedStatusChanged()| will be called
188 // from |connection_| and a new instance for |connection_finder_| will be
189 // created.
190 connection_->RemoveObserver(this);
191 connection_->Disconnect();
194 connection_.reset();
195 connection_finder_.reset();
198 void ProximityAuthBleSystem::OnFocusedUserChanged(const std::string& user_id) {
199 PA_LOG(INFO) << "OnFocusedUserChanged: " << user_id;
202 void ProximityAuthBleSystem::OnMessageReceived(const Connection& connection,
203 const WireMessage& message) {
204 // TODO(sacomoto): change this when WireMessage is fully implemented.
205 PA_LOG(INFO) << "Message received: " << message.payload();
207 // Unlock the screen when the remote device sends an unlock signal.
209 // Note that this magically unlocks Chrome (no user interaction is needed).
210 // This user experience for this operation will be greately improved once
211 // the Proximity Auth Unlock Manager migration to C++ is done.
212 if (message.payload() == kScreenUnlocked) {
213 PA_LOG(INFO) << "Device unlocked. Unlock.";
214 screenlock_bridge_->Unlock(proximity_auth_client_);
218 void ProximityAuthBleSystem::OnConnectionFound(
219 scoped_ptr<Connection> connection) {
220 PA_LOG(INFO) << "Connection found.";
222 connection_ = connection.Pass();
223 if (connection_) {
224 connection_->AddObserver(this);
226 if (!is_polling_screen_state_) {
227 is_polling_screen_state_ = true;
228 StartPollingScreenState();
233 void ProximityAuthBleSystem::OnConnectionStatusChanged(
234 Connection* connection,
235 Connection::Status old_status,
236 Connection::Status new_status) {
237 if (old_status == Connection::CONNECTED &&
238 new_status == Connection::DISCONNECTED) {
239 StopPollingScreenState();
241 connection_->RemoveObserver(this);
242 connection_.reset();
244 connection_finder_.reset(CreateConnectionFinder());
245 connection_finder_->Find(
246 base::Bind(&ProximityAuthBleSystem::OnConnectionFound,
247 weak_ptr_factory_.GetWeakPtr()));
251 void ProximityAuthBleSystem::StartPollingScreenState() {
252 if (is_polling_screen_state_) {
253 if (!connection_ || !connection_->IsConnected()) {
254 PA_LOG(INFO) << "Polling stopped.";
255 is_polling_screen_state_ = false;
256 return;
259 // Sends message requesting screen state.
260 connection_->SendMessage(
261 make_scoped_ptr(new FakeWireMessage(kPollScreenState)));
263 // Schedules the next message in |kPollingIntervalSeconds| ms.
264 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
265 FROM_HERE, base::Bind(&ProximityAuthBleSystem::StartPollingScreenState,
266 weak_ptr_factory_.GetWeakPtr()),
267 base::TimeDelta::FromSeconds(kPollingIntervalSeconds));
271 void ProximityAuthBleSystem::StopPollingScreenState() {
272 is_polling_screen_state_ = false;
275 } // namespace proximity_auth