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

Side by Side Diff: ash/system/chromeos/bluetooth/bluetooth_notification_controller.cc

Issue 183853010: Bluetooth: notify user of incoming pairing requests (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fit nits, add unit tests dep Created 6 years, 9 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 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.
4
5 #include "ash/system/chromeos/bluetooth/bluetooth_notification_controller.h"
6
7 #include "ash/system/system_notifier.h"
8 #include "base/bind.h"
9 #include "base/callback.h"
10 #include "base/logging.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "device/bluetooth/bluetooth_adapter_factory.h"
15 #include "device/bluetooth/bluetooth_device.h"
16 #include "grit/ash_resources.h"
17 #include "grit/ash_strings.h"
18 #include "ui/base/l10n/l10n_util.h"
19 #include "ui/base/resource/resource_bundle.h"
20 #include "ui/message_center/message_center.h"
21 #include "ui/message_center/notification.h"
22 #include "ui/message_center/notification_delegate.h"
23 #include "ui/message_center/notification_types.h"
24
25 using device::BluetoothAdapter;
26 using device::BluetoothAdapterFactory;
27 using device::BluetoothDevice;
28 using message_center::Notification;
29
30 namespace {
31
32 // Identifier for the pairing notification; the Bluetooth code ensures we
33 // only receive one pairing request at a time, so a single id is sufficient and
34 // means we "update" one notification if not handled rather than continually
35 // bugging the user.
36 const char kBluetoothDevicePairingNotificationId[] =
37 "chrome://settings/bluetooth/pairing";
38
39 // The BluetoothPairingNotificationDelegate handles user interaction with the
40 // pairing notification and sending the confirmation, rejection or cancellation
41 // back to the underlying device.
42 class BluetoothPairingNotificationDelegate
43 : public message_center::NotificationDelegate {
44 public:
45 BluetoothPairingNotificationDelegate(scoped_refptr<BluetoothAdapter> adapter,
46 const std::string& address);
47
48 protected:
49 virtual ~BluetoothPairingNotificationDelegate();
50
51 // message_center::NotificationDelegate overrides.
52 virtual void Display() OVERRIDE;
53 virtual void Error() OVERRIDE;
54 virtual void Close(bool by_user) OVERRIDE;
55 virtual bool HasClickedListener() OVERRIDE;
56 virtual void Click() OVERRIDE;
57 virtual void ButtonClick(int button_index) OVERRIDE;
58
59 private:
60 // Reference to the underlying Bluetooth Adapter, holding onto this
61 // reference ensures the adapter object doesn't go out of scope while we have
62 // a pending request and user interaction.
63 scoped_refptr<BluetoothAdapter> adapter_;
64
65 // Address of the device being paired.
66 std::string address_;
67
68 DISALLOW_COPY_AND_ASSIGN(BluetoothPairingNotificationDelegate);
69 };
70
71 BluetoothPairingNotificationDelegate::BluetoothPairingNotificationDelegate(
72 scoped_refptr<BluetoothAdapter> adapter,
73 const std::string& address)
74 : adapter_(adapter),
75 address_(address) {
76 }
77
78 BluetoothPairingNotificationDelegate::~BluetoothPairingNotificationDelegate() {
79 }
80
81 void BluetoothPairingNotificationDelegate::Display() {
82 }
83
84 void BluetoothPairingNotificationDelegate::Error() {
85 }
86
87 void BluetoothPairingNotificationDelegate::Close(bool by_user) {
88 VLOG(1) << "Pairing notification closed. by_user = " << by_user;
89 // Ignore notification closes generated as a result of pairing completion.
90 if (!by_user)
91 return;
92
93 // Cancel the pairing of the device, if the object still exists.
94 BluetoothDevice* device = adapter_->GetDevice(address_);
95 if (device)
96 device->CancelPairing();
97 }
98
99 bool BluetoothPairingNotificationDelegate::HasClickedListener() {
100 return false;
101 }
102
103 void BluetoothPairingNotificationDelegate::Click() {
104 }
105
106 void BluetoothPairingNotificationDelegate::ButtonClick(int button_index) {
107 VLOG(1) << "Pairing notification, button click: " << button_index;
108 // If the device object still exists, send the appropriate response either
109 // confirming or rejecting the pairing.
110 BluetoothDevice* device = adapter_->GetDevice(address_);
111 if (device) {
112 switch (button_index) {
113 case 0:
114 device->ConfirmPairing();
115 break;
116 case 1:
117 device->RejectPairing();
118 break;
119 }
120 }
121
122 // In any case, remove this pairing notification.
123 message_center::MessageCenter::Get()->RemoveNotification(
124 kBluetoothDevicePairingNotificationId, false /* by_user */);
125 }
126
127 } // namespace
128
129
130 namespace ash {
131 namespace internal {
132
133 BluetoothNotificationController::BluetoothNotificationController()
134 : weak_ptr_factory_(this) {
135 BluetoothAdapterFactory::GetAdapter(
136 base::Bind(&BluetoothNotificationController::OnGetAdapter,
137 weak_ptr_factory_.GetWeakPtr()));
138 }
139
140 BluetoothNotificationController::~BluetoothNotificationController() {
141 adapter_->RemoveObserver(this);
142 adapter_->RemovePairingDelegate(this);
143 }
144
145
146 void BluetoothNotificationController::DeviceAdded(BluetoothAdapter* adapter,
147 BluetoothDevice* device) {
148 if (device->IsPaired()) {
149 paired_devices_.insert(device->GetAddress());
150 NotifyPairedDevice(device);
151 }
152 }
153
154 void BluetoothNotificationController::DeviceChanged(BluetoothAdapter* adapter,
155 BluetoothDevice* device) {
156 if (paired_devices_.find(device->GetAddress()) != paired_devices_.end())
157 return;
158
159 if (device->IsPaired()) {
160 paired_devices_.insert(device->GetAddress());
jennyz 2014/02/28 23:24:36 Is the insert redundant? device->GetAddress alread
keybuk 2014/02/28 23:28:18 You have the condition above backwards ... that ma
jennyz 2014/02/28 23:31:19 My blindness, I read it oppositely. You are right.
161 NotifyPairedDevice(device);
162 }
163 }
164
165 void BluetoothNotificationController::DeviceRemoved(BluetoothAdapter* adapter,
166 BluetoothDevice* device) {
167 paired_devices_.erase(device->GetAddress());
168 }
169
170
171 void BluetoothNotificationController::RequestPinCode(BluetoothDevice* device) {
172 // Cannot provide keyboard entry in a notification; these devices (old car
173 // audio systems for the most part) will need pairing to be initated from
jennyz 2014/02/28 23:24:36 nit: initated -> initiated
keybuk 2014/02/28 23:28:18 Done.
174 // the Chromebook.
175 device->CancelPairing();
176 }
177
178 void BluetoothNotificationController::RequestPasskey(BluetoothDevice* device) {
179 // Cannot provide keyboard entry in a notification; fortunately the spec
180 // doesn't allow for this to be an option when we're receiving the pairing
181 // request anyway.
182 device->CancelPairing();
183 }
184
185 void BluetoothNotificationController::DisplayPinCode(
186 BluetoothDevice* device,
187 const std::string& pincode) {
188 base::string16 message = l10n_util::GetStringFUTF16(
189 IDS_ASH_STATUS_TRAY_BLUETOOTH_DISPLAY_PINCODE,
190 device->GetName(), base::UTF8ToUTF16(pincode));
191
192 NotifyPairing(device, message, false);
193 }
194
195 void BluetoothNotificationController::DisplayPasskey(BluetoothDevice* device,
196 uint32 passkey) {
197 base::string16 message = l10n_util::GetStringFUTF16(
198 IDS_ASH_STATUS_TRAY_BLUETOOTH_DISPLAY_PASSKEY,
199 device->GetName(), base::UTF8ToUTF16(
200 base::StringPrintf("%06i", passkey)));
201
202 NotifyPairing(device, message, false);
203 }
204
205 void BluetoothNotificationController::KeysEntered(BluetoothDevice* device,
206 uint32 entered) {
207 // Ignored since we don't have CSS in the notification to update.
208 }
209
210 void BluetoothNotificationController::ConfirmPasskey(BluetoothDevice* device,
211 uint32 passkey) {
212 base::string16 message = l10n_util::GetStringFUTF16(
213 IDS_ASH_STATUS_TRAY_BLUETOOTH_CONFIRM_PASSKEY,
214 device->GetName(), base::UTF8ToUTF16(
215 base::StringPrintf("%06i", passkey)));
216
217 NotifyPairing(device, message, true);
218 }
219
220 void BluetoothNotificationController::AuthorizePairing(
221 BluetoothDevice* device) {
222 base::string16 message = l10n_util::GetStringFUTF16(
223 IDS_ASH_STATUS_TRAY_BLUETOOTH_AUTHORIZE_PAIRING,
224 device->GetName());
225
226 NotifyPairing(device, message, true);
227 }
228
229
230 void BluetoothNotificationController::OnGetAdapter(
231 scoped_refptr<BluetoothAdapter> adapter) {
232 adapter_ = adapter;
233 adapter_->AddObserver(this);
234 adapter_->AddPairingDelegate(this,
235 BluetoothAdapter::PAIRING_DELEGATE_PRIORITY_LOW);
236
237 // Build a list of the currently paired devices; these don't receive
238 // notifications since it's assumed they were previously notified.
239 BluetoothAdapter::DeviceList devices = adapter_->GetDevices();
240 for (BluetoothAdapter::DeviceList::const_iterator iter = devices.begin();
241 iter != devices.end(); ++iter) {
242 const BluetoothDevice* device = *iter;
243 if (device->IsPaired())
244 paired_devices_.insert(device->GetAddress());
245 }
246 }
247
248
249 void BluetoothNotificationController::NotifyPairing(
250 BluetoothDevice* device,
251 const base::string16& message,
252 bool with_buttons) {
253 message_center::RichNotificationData optional;
254 if (with_buttons) {
255 optional.buttons.push_back(message_center::ButtonInfo(
256 l10n_util::GetStringUTF16(
257 IDS_ASH_STATUS_TRAY_BLUETOOTH_ACCEPT)));
258 optional.buttons.push_back(message_center::ButtonInfo(
259 l10n_util::GetStringUTF16(
260 IDS_ASH_STATUS_TRAY_BLUETOOTH_REJECT)));
261 }
262
263 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
264
265 scoped_ptr<Notification> notification(new Notification(
266 message_center::NOTIFICATION_TYPE_SIMPLE,
267 kBluetoothDevicePairingNotificationId,
268 base::string16() /* title */,
269 message,
270 bundle.GetImageNamed(IDR_AURA_UBER_TRAY_BLUETOOTH),
271 base::string16() /* display source */,
272 message_center::NotifierId(
273 message_center::NotifierId::SYSTEM_COMPONENT,
274 system_notifier::kNotifierBluetooth),
275 optional,
276 new BluetoothPairingNotificationDelegate(adapter_,
277 device->GetAddress())));
278 message_center::MessageCenter::Get()->AddNotification(notification.Pass());
279 }
280
281 void BluetoothNotificationController::NotifyPairedDevice(
282 BluetoothDevice* device) {
283 // Remove the currently presented pairing notification; since only one
284 // pairing request is queued at a time, this is guaranteed to be the device
285 // that just became paired.
286 message_center::MessageCenter::Get()->RemoveNotification(
287 kBluetoothDevicePairingNotificationId, false /* by_user */);
288 }
289
290 } // namespace internal
291 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698