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