1 // Copyright (c) 2012 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 "chrome/browser/ui/webui/options/chromeos/bluetooth_options_handler.h"
6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/callback.h"
10 #include "base/command_line.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/values.h"
14 #include "content/public/browser/web_ui.h"
15 #include "device/bluetooth/bluetooth_adapter.h"
16 #include "device/bluetooth/bluetooth_adapter_factory.h"
17 #include "device/bluetooth/bluetooth_device.h"
18 #include "grit/chromium_strings.h"
19 #include "grit/generated_resources.h"
20 #include "third_party/cros_system_api/dbus/service_constants.h"
21 #include "ui/base/l10n/l10n_util.h"
22
23 namespace {
24
25 // |UpdateDeviceCallback| takes a variable length list as an argument. The
26 // value stored in each list element is indicated by the following constants.
27 const int kUpdateDeviceAddressIndex = 0;
28 const int kUpdateDeviceCommandIndex = 1;
29 const int kUpdateDeviceAuthTokenIndex = 2;
30
31 // |UpdateDeviceCallback| provides a command value of one of the following
32 // constants that indicates what update it is providing to us.
33 const char kConnectCommand[] = "connect";
34 const char kCancelCommand[] = "cancel";
35 const char kAcceptCommand[] = "accept";
36 const char kRejectCommand[] = "reject";
37 const char kDisconnectCommand[] = "disconnect";
38 const char kForgetCommand[] = "forget";
39
40 // |SendDeviceNotification| may include a pairing parameter whose value
41 // is one of the following constants instructing the UI to perform a certain
42 // action.
43 const char kStartConnecting[] = "bluetoothStartConnecting";
44 const char kEnterPinCode[] = "bluetoothEnterPinCode";
45 const char kEnterPasskey[] = "bluetoothEnterPasskey";
46 const char kRemotePinCode[] = "bluetoothRemotePinCode";
47 const char kRemotePasskey[] = "bluetoothRemotePasskey";
48 const char kConfirmPasskey[] = "bluetoothConfirmPasskey";
49
50 // An invalid |entered| value to represent the "undefined" value.
51 const int kInvalidEntered = 0xFFFF;
52
53 } // namespace
54
55 namespace chromeos {
56 namespace options {
57
BluetoothOptionsHandler()58 BluetoothOptionsHandler::BluetoothOptionsHandler() :
59 discovering_(false),
60 pairing_device_passkey_(1000000),
61 pairing_device_entered_(kInvalidEntered),
62 weak_ptr_factory_(this) {
63 }
64
~BluetoothOptionsHandler()65 BluetoothOptionsHandler::~BluetoothOptionsHandler() {
66 if (discovering_) {
67 adapter_->StopDiscovering(
68 base::Bind(&base::DoNothing),
69 base::Bind(&base::DoNothing));
70 discovering_ = false;
71 }
72 if (adapter_.get())
73 adapter_->RemoveObserver(this);
74 }
75
GetLocalizedValues(DictionaryValue * localized_strings)76 void BluetoothOptionsHandler::GetLocalizedValues(
77 DictionaryValue* localized_strings) {
78 DCHECK(localized_strings);
79
80 static OptionsStringResource resources[] = {
81 { "bluetooth", IDS_OPTIONS_SETTINGS_SECTION_TITLE_BLUETOOTH },
82 { "disableBluetooth", IDS_OPTIONS_SETTINGS_BLUETOOTH_DISABLE },
83 { "enableBluetooth", IDS_OPTIONS_SETTINGS_BLUETOOTH_ENABLE },
84 { "addBluetoothDevice", IDS_OPTIONS_SETTINGS_ADD_BLUETOOTH_DEVICE },
85 { "bluetoothAddDeviceTitle",
86 IDS_OPTIONS_SETTINGS_BLUETOOTH_ADD_DEVICE_TITLE },
87 { "bluetoothOptionsPageTabTitle",
88 IDS_OPTIONS_SETTINGS_BLUETOOTH_ADD_DEVICE_TITLE },
89 { "findBluetoothDevices", IDS_OPTIONS_SETTINGS_FIND_BLUETOOTH_DEVICES },
90 { "bluetoothNoDevices", IDS_OPTIONS_SETTINGS_BLUETOOTH_NO_DEVICES },
91 { "bluetoothNoDevicesFound",
92 IDS_OPTIONS_SETTINGS_BLUETOOTH_NO_DEVICES_FOUND },
93 { "bluetoothScanning", IDS_OPTIONS_SETTINGS_BLUETOOTH_SCANNING },
94 { "bluetoothDeviceConnecting", IDS_OPTIONS_SETTINGS_BLUETOOTH_CONNECTING },
95 { "bluetoothConnectDevice", IDS_OPTIONS_SETTINGS_BLUETOOTH_CONNECT },
96 { "bluetoothDisconnectDevice", IDS_OPTIONS_SETTINGS_BLUETOOTH_DISCONNECT },
97 { "bluetoothForgetDevice", IDS_OPTIONS_SETTINGS_BLUETOOTH_FORGET },
98 { "bluetoothCancel", IDS_OPTIONS_SETTINGS_BLUETOOTH_CANCEL },
99 { "bluetoothEnterKey", IDS_OPTIONS_SETTINGS_BLUETOOTH_ENTER_KEY },
100 { "bluetoothDismissError", IDS_OPTIONS_SETTINGS_BLUETOOTH_DISMISS_ERROR },
101
102 // Device connecting and pairing.
103 { "bluetoothStartConnecting",
104 IDS_OPTIONS_SETTINGS_BLUETOOTH_START_CONNECTING },
105 { "bluetoothAcceptPasskey",
106 IDS_OPTIONS_SETTINGS_BLUETOOTH_ACCEPT_PASSKEY },
107 { "bluetoothRejectPasskey",
108 IDS_OPTIONS_SETTINGS_BLUETOOTH_REJECT_PASSKEY },
109 { "bluetoothEnterPinCode",
110 IDS_OPTIONS_SETTINGS_BLUETOOTH_ENTER_PIN_CODE_REQUEST },
111 { "bluetoothEnterPasskey",
112 IDS_OPTIONS_SETTINGS_BLUETOOTH_ENTER_PASSKEY_REQUEST },
113 { "bluetoothRemotePinCode",
114 IDS_OPTIONS_SETTINGS_BLUETOOTH_REMOTE_PIN_CODE_REQUEST },
115 { "bluetoothRemotePasskey",
116 IDS_OPTIONS_SETTINGS_BLUETOOTH_REMOTE_PASSKEY_REQUEST },
117 { "bluetoothConfirmPasskey",
118 IDS_OPTIONS_SETTINGS_BLUETOOTH_CONFIRM_PASSKEY_REQUEST },
119
120 // Error messages.
121 { "bluetoothStartDiscoveryFailed",
122 IDS_OPTIONS_SETTINGS_BLUETOOTH_START_DISCOVERY_FAILED },
123 { "bluetoothStopDiscoveryFailed",
124 IDS_OPTIONS_SETTINGS_BLUETOOTH_STOP_DISCOVERY_FAILED },
125 { "bluetoothChangePowerFailed",
126 IDS_OPTIONS_SETTINGS_BLUETOOTH_CHANGE_POWER_FAILED },
127 { "bluetoothConnectUnknownError",
128 IDS_OPTIONS_SETTINGS_BLUETOOTH_CONNECT_UNKNOWN_ERROR },
129 { "bluetoothConnectInProgress",
130 IDS_OPTIONS_SETTINGS_BLUETOOTH_CONNECT_IN_PROGRESS },
131 { "bluetoothConnectFailed",
132 IDS_OPTIONS_SETTINGS_BLUETOOTH_CONNECT_FAILED },
133 { "bluetoothConnectAuthFailed",
134 IDS_OPTIONS_SETTINGS_BLUETOOTH_CONNECT_AUTH_FAILED },
135 { "bluetoothConnectAuthCanceled",
136 IDS_OPTIONS_SETTINGS_BLUETOOTH_CONNECT_AUTH_CANCELED },
137 { "bluetoothConnectAuthRejected",
138 IDS_OPTIONS_SETTINGS_BLUETOOTH_CONNECT_AUTH_REJECTED },
139 { "bluetoothConnectAuthTimeout",
140 IDS_OPTIONS_SETTINGS_BLUETOOTH_CONNECT_AUTH_TIMEOUT },
141 { "bluetoothConnectUnsupportedDevice",
142 IDS_OPTIONS_SETTINGS_BLUETOOTH_CONNECT_UNSUPPORTED_DEVICE },
143 { "bluetoothDisconnectFailed",
144 IDS_OPTIONS_SETTINGS_BLUETOOTH_DISCONNECT_FAILED },
145 { "bluetoothForgetFailed",
146 IDS_OPTIONS_SETTINGS_BLUETOOTH_FORGET_FAILED }};
147
148 RegisterStrings(localized_strings, resources, arraysize(resources));
149 }
150
151 // TODO(kevers): Reorder methods to match ordering in the header file.
152
AdapterPresentChanged(device::BluetoothAdapter * adapter,bool present)153 void BluetoothOptionsHandler::AdapterPresentChanged(
154 device::BluetoothAdapter* adapter,
155 bool present) {
156 DCHECK(adapter == adapter_.get());
157 if (present) {
158 web_ui()->CallJavascriptFunction(
159 "options.BrowserOptions.showBluetoothSettings");
160
161 // Update the checkbox and visibility based on the powered state of the
162 // new adapter.
163 AdapterPoweredChanged(adapter_.get(), adapter_->IsPowered());
164 } else {
165 web_ui()->CallJavascriptFunction(
166 "options.BrowserOptions.hideBluetoothSettings");
167 }
168 }
169
AdapterPoweredChanged(device::BluetoothAdapter * adapter,bool powered)170 void BluetoothOptionsHandler::AdapterPoweredChanged(
171 device::BluetoothAdapter* adapter,
172 bool powered) {
173 DCHECK(adapter == adapter_.get());
174 base::FundamentalValue checked(powered);
175 web_ui()->CallJavascriptFunction(
176 "options.BrowserOptions.setBluetoothState", checked);
177 }
178
RegisterMessages()179 void BluetoothOptionsHandler::RegisterMessages() {
180 web_ui()->RegisterMessageCallback("bluetoothEnableChange",
181 base::Bind(&BluetoothOptionsHandler::EnableChangeCallback,
182 base::Unretained(this)));
183 web_ui()->RegisterMessageCallback("findBluetoothDevices",
184 base::Bind(&BluetoothOptionsHandler::FindDevicesCallback,
185 base::Unretained(this)));
186 web_ui()->RegisterMessageCallback("updateBluetoothDevice",
187 base::Bind(&BluetoothOptionsHandler::UpdateDeviceCallback,
188 base::Unretained(this)));
189 web_ui()->RegisterMessageCallback("stopBluetoothDeviceDiscovery",
190 base::Bind(&BluetoothOptionsHandler::StopDiscoveryCallback,
191 base::Unretained(this)));
192 web_ui()->RegisterMessageCallback("getPairedBluetoothDevices",
193 base::Bind(&BluetoothOptionsHandler::GetPairedDevicesCallback,
194 base::Unretained(this)));
195 }
196
InitializeHandler()197 void BluetoothOptionsHandler::InitializeHandler() {
198 device::BluetoothAdapterFactory::GetAdapter(
199 base::Bind(&BluetoothOptionsHandler::InitializeAdapter,
200 weak_ptr_factory_.GetWeakPtr()));
201 }
202
InitializePage()203 void BluetoothOptionsHandler::InitializePage() {
204 // Show or hide the bluetooth settings and update the checkbox based
205 // on the current present/powered state.
206 AdapterPresentChanged(adapter_.get(), adapter_->IsPresent());
207 // Automatically start device discovery if the "Add Bluetooth Device"
208 // overlay is visible.
209 web_ui()->CallJavascriptFunction(
210 "options.BluetoothOptions.updateDiscovery");
211 }
212
InitializeAdapter(scoped_refptr<device::BluetoothAdapter> adapter)213 void BluetoothOptionsHandler::InitializeAdapter(
214 scoped_refptr<device::BluetoothAdapter> adapter) {
215 adapter_ = adapter;
216 CHECK(adapter_.get());
217 adapter_->AddObserver(this);
218 }
219
EnableChangeCallback(const ListValue * args)220 void BluetoothOptionsHandler::EnableChangeCallback(
221 const ListValue* args) {
222 bool bluetooth_enabled;
223 args->GetBoolean(0, &bluetooth_enabled);
224
225 adapter_->SetPowered(bluetooth_enabled,
226 base::Bind(&base::DoNothing),
227 base::Bind(&BluetoothOptionsHandler::EnableChangeError,
228 weak_ptr_factory_.GetWeakPtr()));
229 }
230
EnableChangeError()231 void BluetoothOptionsHandler::EnableChangeError() {
232 VLOG(1) << "Failed to change power state.";
233 ReportError("bluetoothChangePowerFailed", std::string());
234 }
235
FindDevicesCallback(const ListValue * args)236 void BluetoothOptionsHandler::FindDevicesCallback(
237 const ListValue* args) {
238 if (!discovering_) {
239 discovering_ = true;
240 adapter_->StartDiscovering(
241 base::Bind(&base::DoNothing),
242 base::Bind(&BluetoothOptionsHandler::FindDevicesError,
243 weak_ptr_factory_.GetWeakPtr()));
244 }
245 }
246
FindDevicesError()247 void BluetoothOptionsHandler::FindDevicesError() {
248 VLOG(1) << "Failed to start discovery.";
249 ReportError("bluetoothStartDiscoveryFailed", std::string());
250 }
251
UpdateDeviceCallback(const ListValue * args)252 void BluetoothOptionsHandler::UpdateDeviceCallback(
253 const ListValue* args) {
254 std::string address;
255 args->GetString(kUpdateDeviceAddressIndex, &address);
256
257 device::BluetoothDevice* device = adapter_->GetDevice(address);
258 if (!device)
259 return;
260
261 std::string command;
262 args->GetString(kUpdateDeviceCommandIndex, &command);
263
264 if (command == kConnectCommand) {
265 int size = args->GetSize();
266 if (size > kUpdateDeviceAuthTokenIndex) {
267 // PIN code or Passkey entry during the pairing process.
268 std::string auth_token;
269 args->GetString(kUpdateDeviceAuthTokenIndex, &auth_token);
270
271 if (device->ExpectingPinCode()) {
272 DeviceConnecting(device);
273 // PIN Code is an array of 1 to 16 8-bit bytes, the usual
274 // interpretation, and the one shared by BlueZ, is a UTF-8 string
275 // of as many characters that will fit in that space, thus we
276 // can use the auth token from JavaScript unmodified.
277 VLOG(1) << "PIN Code supplied: " << address << ": " << auth_token;
278 device->SetPinCode(auth_token);
279 } else if (device->ExpectingPasskey()) {
280 DeviceConnecting(device);
281 // Passkey is a numeric in the range 0-999999, in this case the
282 // JavaScript code should have ensured the auth token string only
283 // contains digits so a simple conversion is sufficient. In the
284 // failure case, just use 0 since that's the most likely Passkey
285 // anyway, and if it's refused the device will request a new one.
286 unsigned passkey = 0;
287 base::StringToUint(auth_token, &passkey);
288
289 VLOG(1) << "Passkey supplied: " << address << ": " << passkey;
290 device->SetPasskey(passkey);
291 } else {
292 LOG(WARNING) << "Auth token supplied after pairing ended: " << address
293 << ": " << auth_token;
294 }
295 } else {
296 // Determine if the device supports pairing:
297 PairingDelegate* delegate = NULL;
298 if (device->IsPairable())
299 delegate = this;
300
301 // Connection request.
302 VLOG(1) << "Connect: " << address;
303 device->Connect(
304 delegate,
305 base::Bind(&BluetoothOptionsHandler::Connected,
306 weak_ptr_factory_.GetWeakPtr()),
307 base::Bind(&BluetoothOptionsHandler::ConnectError,
308 weak_ptr_factory_.GetWeakPtr(),
309 device->GetAddress()));
310 }
311 } else if (command == kCancelCommand) {
312 // Cancel pairing.
313 VLOG(1) << "Cancel pairing: " << address;
314 device->CancelPairing();
315 } else if (command == kAcceptCommand) {
316 // Confirm displayed Passkey.
317 VLOG(1) << "Confirm pairing: " << address;
318 device->ConfirmPairing();
319 } else if (command == kRejectCommand) {
320 // Reject displayed Passkey.
321 VLOG(1) << "Reject pairing: " << address;
322 device->RejectPairing();
323 } else if (command == kDisconnectCommand) {
324 // Disconnect from device.
325 VLOG(1) << "Disconnect device: " << address;
326 device->Disconnect(
327 base::Bind(&base::DoNothing),
328 base::Bind(&BluetoothOptionsHandler::DisconnectError,
329 weak_ptr_factory_.GetWeakPtr(),
330 device->GetAddress()));
331 } else if (command == kForgetCommand) {
332 // Disconnect from device and delete pairing information.
333 VLOG(1) << "Forget device: " << address;
334 device->Forget(base::Bind(&BluetoothOptionsHandler::ForgetError,
335 weak_ptr_factory_.GetWeakPtr(),
336 device->GetAddress()));
337 } else {
338 LOG(WARNING) << "Unknown updateBluetoothDevice command: " << command;
339 }
340 }
341
Connected()342 void BluetoothOptionsHandler::Connected() {
343 // Invalidate the local cache.
344 pairing_device_address_.clear();
345 pairing_device_entered_ = kInvalidEntered;
346
347 web_ui()->CallJavascriptFunction(
348 "options.BluetoothPairing.dismissDialog");
349 }
350
ConnectError(const std::string & address,device::BluetoothDevice::ConnectErrorCode error_code)351 void BluetoothOptionsHandler::ConnectError(
352 const std::string& address,
353 device::BluetoothDevice::ConnectErrorCode error_code) {
354 const char* error_name = NULL;
355
356 // Invalidate the local cache.
357 pairing_device_address_.clear();
358 pairing_device_entered_ = kInvalidEntered;
359
360 VLOG(1) << "Failed to connect to device: " << address;
361 switch (error_code) {
362 case device::BluetoothDevice::ERROR_UNKNOWN:
363 error_name = "bluetoothConnectUnknownError";
364 break;
365 case device::BluetoothDevice::ERROR_INPROGRESS:
366 error_name = "bluetoothConnectInProgress";
367 break;
368 case device::BluetoothDevice::ERROR_FAILED:
369 error_name = "bluetoothConnectFailed";
370 break;
371 case device::BluetoothDevice::ERROR_AUTH_FAILED:
372 error_name = "bluetoothConnectAuthFailed";
373 break;
374 case device::BluetoothDevice::ERROR_AUTH_CANCELED:
375 error_name = "bluetoothConnectAuthCanceled";
376 break;
377 case device::BluetoothDevice::ERROR_AUTH_REJECTED:
378 error_name = "bluetoothConnectAuthRejected";
379 break;
380 case device::BluetoothDevice::ERROR_AUTH_TIMEOUT:
381 error_name = "bluetoothConnectAuthTimeout";
382 break;
383 case device::BluetoothDevice::ERROR_UNSUPPORTED_DEVICE:
384 error_name = "bluetoothConnectUnsupportedDevice";
385 break;
386 }
387 // Report an error only if there's an error to report.
388 if (error_name)
389 ReportError(error_name, address);
390 }
391
DisconnectError(const std::string & address)392 void BluetoothOptionsHandler::DisconnectError(const std::string& address) {
393 VLOG(1) << "Failed to disconnect from device: " << address;
394 ReportError("bluetoothDisconnectFailed", address);
395 }
396
ForgetError(const std::string & address)397 void BluetoothOptionsHandler::ForgetError(const std::string& address) {
398 VLOG(1) << "Failed to disconnect and unpair device: " << address;
399 ReportError("bluetoothForgetFailed", address);
400 }
401
StopDiscoveryCallback(const ListValue * args)402 void BluetoothOptionsHandler::StopDiscoveryCallback(
403 const ListValue* args) {
404 if (discovering_) {
405 adapter_->StopDiscovering(
406 base::Bind(&base::DoNothing),
407 base::Bind(&BluetoothOptionsHandler::StopDiscoveryError,
408 weak_ptr_factory_.GetWeakPtr()));
409 discovering_ = false;
410 }
411 }
412
StopDiscoveryError()413 void BluetoothOptionsHandler::StopDiscoveryError() {
414 VLOG(1) << "Failed to stop discovery.";
415 ReportError("bluetoothStopDiscoveryFailed", std::string());
416 }
417
GetPairedDevicesCallback(const ListValue * args)418 void BluetoothOptionsHandler::GetPairedDevicesCallback(
419 const ListValue* args) {
420 device::BluetoothAdapter::DeviceList devices = adapter_->GetDevices();
421
422 for (device::BluetoothAdapter::DeviceList::iterator iter = devices.begin();
423 iter != devices.end(); ++iter)
424 SendDeviceNotification(*iter, NULL);
425 }
426
SendDeviceNotification(const device::BluetoothDevice * device,base::DictionaryValue * params)427 void BluetoothOptionsHandler::SendDeviceNotification(
428 const device::BluetoothDevice* device,
429 base::DictionaryValue* params) {
430 base::DictionaryValue js_properties;
431 js_properties.SetString("name", device->GetName());
432 js_properties.SetString("address", device->GetAddress());
433 js_properties.SetBoolean("paired", device->IsPaired());
434 js_properties.SetBoolean("connected", device->IsConnected());
435 js_properties.SetBoolean("connecting", device->IsConnecting());
436 js_properties.SetBoolean("connectable", device->IsConnectable());
437 if (params)
438 js_properties.MergeDictionary(params);
439
440 // Use the cached values to update js_property.
441 if (device->GetAddress() == pairing_device_address_) {
442 std::string pairing;
443 if (!js_properties.GetString("pairing", &pairing)) {
444 pairing = pairing_device_pairing_;
445 js_properties.SetString("pairing", pairing);
446 }
447 if (pairing == kRemotePinCode && !js_properties.HasKey("pincode"))
448 js_properties.SetString("pincode", pairing_device_pincode_);
449 if (pairing == kRemotePasskey && !js_properties.HasKey("passkey"))
450 js_properties.SetInteger("passkey", pairing_device_passkey_);
451 if ((pairing == kRemotePinCode || pairing == kRemotePasskey) &&
452 !js_properties.HasKey("entered") &&
453 pairing_device_entered_ != kInvalidEntered) {
454 js_properties.SetInteger("entered", pairing_device_entered_);
455 }
456 }
457
458 // Update the cache with the new information.
459 if (js_properties.HasKey("pairing")) {
460 pairing_device_address_ = device->GetAddress();
461 js_properties.GetString("pairing", &pairing_device_pairing_);
462 js_properties.GetString("pincode", &pairing_device_pincode_);
463 js_properties.GetInteger("passkey", &pairing_device_passkey_);
464 if (!js_properties.GetInteger("entered", &pairing_device_entered_))
465 pairing_device_entered_ = kInvalidEntered;
466 }
467
468 web_ui()->CallJavascriptFunction(
469 "options.BrowserOptions.addBluetoothDevice",
470 js_properties);
471 }
472
RequestPinCode(device::BluetoothDevice * device)473 void BluetoothOptionsHandler::RequestPinCode(device::BluetoothDevice* device) {
474 DictionaryValue params;
475 params.SetString("pairing", kEnterPinCode);
476 SendDeviceNotification(device, ¶ms);
477 }
478
RequestPasskey(device::BluetoothDevice * device)479 void BluetoothOptionsHandler::RequestPasskey(device::BluetoothDevice* device) {
480 DictionaryValue params;
481 params.SetString("pairing", kEnterPasskey);
482 SendDeviceNotification(device, ¶ms);
483 }
484
DisplayPinCode(device::BluetoothDevice * device,const std::string & pincode)485 void BluetoothOptionsHandler::DisplayPinCode(device::BluetoothDevice* device,
486 const std::string& pincode) {
487 DictionaryValue params;
488 params.SetString("pairing", kRemotePinCode);
489 params.SetString("pincode", pincode);
490 SendDeviceNotification(device, ¶ms);
491 }
492
DisplayPasskey(device::BluetoothDevice * device,uint32 passkey)493 void BluetoothOptionsHandler::DisplayPasskey(device::BluetoothDevice* device,
494 uint32 passkey) {
495 DictionaryValue params;
496 params.SetString("pairing", kRemotePasskey);
497 params.SetInteger("passkey", passkey);
498 SendDeviceNotification(device, ¶ms);
499 }
500
KeysEntered(device::BluetoothDevice * device,uint32 entered)501 void BluetoothOptionsHandler::KeysEntered(device::BluetoothDevice* device,
502 uint32 entered) {
503 DictionaryValue params;
504 params.SetInteger("entered", entered);
505 SendDeviceNotification(device, ¶ms);
506 }
507
ConfirmPasskey(device::BluetoothDevice * device,uint32 passkey)508 void BluetoothOptionsHandler::ConfirmPasskey(device::BluetoothDevice* device,
509 uint32 passkey) {
510 DictionaryValue params;
511 params.SetString("pairing", kConfirmPasskey);
512 params.SetInteger("passkey", passkey);
513 SendDeviceNotification(device, ¶ms);
514 }
515
DismissDisplayOrConfirm()516 void BluetoothOptionsHandler::DismissDisplayOrConfirm() {
517 DCHECK(adapter_.get());
518
519 // We can receive this delegate call when we haven't been asked to display or
520 // confirm anything; we can determine that by checking whether we've saved
521 // pairing information for the device. This is also a handy way to get the
522 // BluetoothDevice object we need.
523 if (!pairing_device_address_.empty()) {
524 device::BluetoothDevice* device =
525 adapter_->GetDevice(pairing_device_address_);
526 DCHECK(device);
527 DeviceConnecting(device);
528 }
529 }
530
ReportError(const std::string & error,const std::string & address)531 void BluetoothOptionsHandler::ReportError(
532 const std::string& error,
533 const std::string& address) {
534 base::DictionaryValue properties;
535 properties.SetString("label", error);
536 properties.SetString("address", address);
537 web_ui()->CallJavascriptFunction(
538 "options.BluetoothPairing.showMessage",
539 properties);
540 }
541
DeviceAdded(device::BluetoothAdapter * adapter,device::BluetoothDevice * device)542 void BluetoothOptionsHandler::DeviceAdded(device::BluetoothAdapter* adapter,
543 device::BluetoothDevice* device) {
544 DCHECK(adapter == adapter_.get());
545 DCHECK(device);
546 SendDeviceNotification(device, NULL);
547 }
548
DeviceChanged(device::BluetoothAdapter * adapter,device::BluetoothDevice * device)549 void BluetoothOptionsHandler::DeviceChanged(device::BluetoothAdapter* adapter,
550 device::BluetoothDevice* device) {
551 DCHECK(adapter == adapter_.get());
552 DCHECK(device);
553 SendDeviceNotification(device, NULL);
554 }
555
DeviceRemoved(device::BluetoothAdapter * adapter,device::BluetoothDevice * device)556 void BluetoothOptionsHandler::DeviceRemoved(device::BluetoothAdapter* adapter,
557 device::BluetoothDevice* device) {
558 DCHECK(adapter == adapter_.get());
559 DCHECK(device);
560
561 // Invalidate the local cache if the pairing device is removed.
562 if (pairing_device_address_ == device->GetAddress()) {
563 pairing_device_address_.clear();
564 pairing_device_entered_ = kInvalidEntered;
565 }
566
567 base::StringValue address(device->GetAddress());
568 web_ui()->CallJavascriptFunction(
569 "options.BrowserOptions.removeBluetoothDevice",
570 address);
571 }
572
DeviceConnecting(device::BluetoothDevice * device)573 void BluetoothOptionsHandler::DeviceConnecting(
574 device::BluetoothDevice* device) {
575 DCHECK(device);
576 DictionaryValue params;
577 params.SetString("pairing", kStartConnecting);
578 SendDeviceNotification(device, ¶ms);
579 }
580
581 } // namespace options
582 } // namespace chromeos
583