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

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: add dependency to hopefully fix linux_chromeos build failure 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 // Buttons that appear in notifications.
61 enum Button {
62 BUTTON_ACCEPT,
63 BUTTON_REJECT
64 };
65
66 // Reference to the underlying Bluetooth Adapter, holding onto this
67 // reference ensures the adapter object doesn't go out of scope while we have
68 // a pending request and user interaction.
69 scoped_refptr<BluetoothAdapter> adapter_;
70
71 // Address of the device being paired.
72 const std::string address_;
73
74 DISALLOW_COPY_AND_ASSIGN(BluetoothPairingNotificationDelegate);
75 };
76
77 BluetoothPairingNotificationDelegate::BluetoothPairingNotificationDelegate(
78 scoped_refptr<BluetoothAdapter> adapter,
79 const std::string& address)
80 : adapter_(adapter),
81 address_(address) {
82 }
83
84 BluetoothPairingNotificationDelegate::~BluetoothPairingNotificationDelegate() {
85 }
86
87 void BluetoothPairingNotificationDelegate::Display() {
88 }
89
90 void BluetoothPairingNotificationDelegate::Error() {
91 }
92
93 void BluetoothPairingNotificationDelegate::Close(bool by_user) {
94 VLOG(1) << "Pairing notification closed. by_user = " << by_user;
95 // Ignore notification closes generated as a result of pairing completion.
96 if (!by_user)
97 return;
98
99 // Cancel the pairing of the device, if the object still exists.
100 BluetoothDevice* device = adapter_->GetDevice(address_);
101 if (device)
102 device->CancelPairing();
103 }
104
105 bool BluetoothPairingNotificationDelegate::HasClickedListener() {
106 return false;
107 }
108
109 void BluetoothPairingNotificationDelegate::Click() {
110 }
111
112 void BluetoothPairingNotificationDelegate::ButtonClick(int button_index) {
113 VLOG(1) << "Pairing notification, button click: " << button_index;
114 // If the device object still exists, send the appropriate response either
115 // confirming or rejecting the pairing.
116 BluetoothDevice* device = adapter_->GetDevice(address_);
117 if (device) {
118 switch (button_index) {
119 case BUTTON_ACCEPT:
120 device->ConfirmPairing();
121 break;
122 case BUTTON_REJECT:
123 device->RejectPairing();
124 break;
125 }
126 }
127
128 // In any case, remove this pairing notification.
129 message_center::MessageCenter::Get()->RemoveNotification(
130 kBluetoothDevicePairingNotificationId, false /* by_user */);
131 }
132
133 } // namespace
134
135
136 namespace ash {
137 namespace internal {
138
139 BluetoothNotificationController::BluetoothNotificationController()
140 : weak_ptr_factory_(this) {
141 BluetoothAdapterFactory::GetAdapter(
142 base::Bind(&BluetoothNotificationController::OnGetAdapter,
143 weak_ptr_factory_.GetWeakPtr()));
144 }
145
146 BluetoothNotificationController::~BluetoothNotificationController() {
147 if (adapter_.get()) {
148 adapter_->RemoveObserver(this);
149 adapter_->RemovePairingDelegate(this);
150 adapter_ = NULL;
151 }
152 }
153
154
155 void BluetoothNotificationController::DeviceAdded(BluetoothAdapter* adapter,
156 BluetoothDevice* device) {
157 if (device->IsPaired()) {
158 paired_devices_.insert(device->GetAddress());
159 NotifyPairedDevice(device);
160 }
161 }
162
163 void BluetoothNotificationController::DeviceChanged(BluetoothAdapter* adapter,
164 BluetoothDevice* device) {
165 if (paired_devices_.find(device->GetAddress()) != paired_devices_.end())
166 return;
167
168 if (device->IsPaired()) {
169 paired_devices_.insert(device->GetAddress());
170 NotifyPairedDevice(device);
171 }
172 }
173
174 void BluetoothNotificationController::DeviceRemoved(BluetoothAdapter* adapter,
175 BluetoothDevice* device) {
176 paired_devices_.erase(device->GetAddress());
177 }
178
179
180 void BluetoothNotificationController::RequestPinCode(BluetoothDevice* device) {
181 // Cannot provide keyboard entry in a notification; these devices (old car
182 // audio systems for the most part) will need pairing to be initiated from
183 // the Chromebook.
184 device->CancelPairing();
185 }
186
187 void BluetoothNotificationController::RequestPasskey(BluetoothDevice* device) {
188 // Cannot provide keyboard entry in a notification; fortunately the spec
189 // doesn't allow for this to be an option when we're receiving the pairing
190 // request anyway.
191 device->CancelPairing();
192 }
193
194 void BluetoothNotificationController::DisplayPinCode(
195 BluetoothDevice* device,
196 const std::string& pincode) {
197 base::string16 message = l10n_util::GetStringFUTF16(
198 IDS_ASH_STATUS_TRAY_BLUETOOTH_DISPLAY_PINCODE,
199 device->GetName(), base::UTF8ToUTF16(pincode));
200
201 NotifyPairing(device, message, false);
202 }
203
204 void BluetoothNotificationController::DisplayPasskey(BluetoothDevice* device,
205 uint32 passkey) {
206 base::string16 message = l10n_util::GetStringFUTF16(
207 IDS_ASH_STATUS_TRAY_BLUETOOTH_DISPLAY_PASSKEY,
208 device->GetName(), base::UTF8ToUTF16(
209 base::StringPrintf("%06i", passkey)));
210
211 NotifyPairing(device, message, false);
212 }
213
214 void BluetoothNotificationController::KeysEntered(BluetoothDevice* device,
215 uint32 entered) {
216 // Ignored since we don't have CSS in the notification to update.
217 }
218
219 void BluetoothNotificationController::ConfirmPasskey(BluetoothDevice* device,
220 uint32 passkey) {
221 base::string16 message = l10n_util::GetStringFUTF16(
222 IDS_ASH_STATUS_TRAY_BLUETOOTH_CONFIRM_PASSKEY,
223 device->GetName(), base::UTF8ToUTF16(
224 base::StringPrintf("%06i", passkey)));
225
226 NotifyPairing(device, message, true);
227 }
228
229 void BluetoothNotificationController::AuthorizePairing(
230 BluetoothDevice* device) {
231 base::string16 message = l10n_util::GetStringFUTF16(
232 IDS_ASH_STATUS_TRAY_BLUETOOTH_AUTHORIZE_PAIRING,
233 device->GetName());
234
235 NotifyPairing(device, message, true);
236 }
237
238
239 void BluetoothNotificationController::OnGetAdapter(
240 scoped_refptr<BluetoothAdapter> adapter) {
241 DCHECK(!adapter_.get());
242 adapter_ = adapter;
243 adapter_->AddObserver(this);
244 adapter_->AddPairingDelegate(this,
245 BluetoothAdapter::PAIRING_DELEGATE_PRIORITY_LOW);
246
247 // Build a list of the currently paired devices; these don't receive
248 // notifications since it's assumed they were previously notified.
249 BluetoothAdapter::DeviceList devices = adapter_->GetDevices();
250 for (BluetoothAdapter::DeviceList::const_iterator iter = devices.begin();
251 iter != devices.end(); ++iter) {
252 const BluetoothDevice* device = *iter;
253 if (device->IsPaired())
254 paired_devices_.insert(device->GetAddress());
255 }
256 }
257
258
259 void BluetoothNotificationController::NotifyPairing(
260 BluetoothDevice* device,
261 const base::string16& message,
262 bool with_buttons) {
263 message_center::RichNotificationData optional;
264 if (with_buttons) {
265 optional.buttons.push_back(message_center::ButtonInfo(
266 l10n_util::GetStringUTF16(
267 IDS_ASH_STATUS_TRAY_BLUETOOTH_ACCEPT)));
268 optional.buttons.push_back(message_center::ButtonInfo(
269 l10n_util::GetStringUTF16(
270 IDS_ASH_STATUS_TRAY_BLUETOOTH_REJECT)));
271 }
272
273 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
274
275 scoped_ptr<Notification> notification(new Notification(
276 message_center::NOTIFICATION_TYPE_SIMPLE,
277 kBluetoothDevicePairingNotificationId,
278 base::string16() /* title */,
279 message,
280 bundle.GetImageNamed(IDR_AURA_UBER_TRAY_BLUETOOTH),
281 base::string16() /* display source */,
282 message_center::NotifierId(
283 message_center::NotifierId::SYSTEM_COMPONENT,
284 system_notifier::kNotifierBluetooth),
285 optional,
286 new BluetoothPairingNotificationDelegate(adapter_,
287 device->GetAddress())));
288 message_center::MessageCenter::Get()->AddNotification(notification.Pass());
289 }
290
291 void BluetoothNotificationController::NotifyPairedDevice(
292 BluetoothDevice* device) {
293 // Remove the currently presented pairing notification; since only one
294 // pairing request is queued at a time, this is guaranteed to be the device
295 // that just became paired.
296 message_center::MessageCenter::Get()->RemoveNotification(
297 kBluetoothDevicePairingNotificationId, false /* by_user */);
298 }
299
300 } // namespace internal
301 } // namespace ash
OLDNEW
« no previous file with comments | « ash/system/chromeos/bluetooth/bluetooth_notification_controller.h ('k') | ash/system/system_notifier.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698