bluetooth_options_handler.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/webui/options/chromeos/bluetooth_options_handler.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/utf_string_conversions.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_ui.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "device/bluetooth/bluetooth_adapter.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "device/bluetooth/bluetooth_adapter_factory.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "device/bluetooth/bluetooth_device.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/chromium_strings.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/cros_system_api/dbus/service_constants.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |UpdateDeviceCallback| takes a variable length list as an argument. The
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// value stored in each list element is indicated by the following constants.
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kUpdateDeviceAddressIndex = 0;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kUpdateDeviceCommandIndex = 1;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kUpdateDeviceAuthTokenIndex = 2;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |UpdateDeviceCallback| provides a command value of one of the following
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// constants that indicates what update it is providing to us.
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kConnectCommand[] = "connect";
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kCancelCommand[] = "cancel";
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kAcceptCommand[] = "accept";
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kRejectCommand[] = "reject";
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kDisconnectCommand[] = "disconnect";
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kForgetCommand[] = "forget";
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |SendDeviceNotification| may include a pairing parameter whose value
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is one of the following constants instructing the UI to perform a certain
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// action.
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kStartConnecting[] = "bluetoothStartConnecting";
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kEnterPinCode[] = "bluetoothEnterPinCode";
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kEnterPasskey[] = "bluetoothEnterPasskey";
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kRemotePinCode[] = "bluetoothRemotePinCode";
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kRemotePasskey[] = "bluetoothRemotePasskey";
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kConfirmPasskey[] = "bluetoothConfirmPasskey";
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// An invalid |entered| value to represent the "undefined" value.
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int kInvalidEntered = 0xFFFF;
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chromeos {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace options {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)BluetoothOptionsHandler::BluetoothOptionsHandler() :
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    discovering_(false),
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    pairing_device_passkey_(1000000),
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    pairing_device_entered_(kInvalidEntered),
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    weak_ptr_factory_(this) {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BluetoothOptionsHandler::~BluetoothOptionsHandler() {
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (discovering_) {
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    adapter_->StopDiscovering(
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&base::DoNothing),
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&base::DoNothing));
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    discovering_ = false;
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (adapter_.get())
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    adapter_->RemoveObserver(this);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::GetLocalizedValues(
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DictionaryValue* localized_strings) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(localized_strings);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static OptionsStringResource resources[] = {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetooth", IDS_OPTIONS_SETTINGS_SECTION_TITLE_BLUETOOTH },
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "disableBluetooth", IDS_OPTIONS_SETTINGS_BLUETOOTH_DISABLE },
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "enableBluetooth", IDS_OPTIONS_SETTINGS_BLUETOOTH_ENABLE },
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "addBluetoothDevice", IDS_OPTIONS_SETTINGS_ADD_BLUETOOTH_DEVICE },
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothAddDeviceTitle",
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_ADD_DEVICE_TITLE },
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothOptionsPageTabTitle",
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_ADD_DEVICE_TITLE },
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "findBluetoothDevices", IDS_OPTIONS_SETTINGS_FIND_BLUETOOTH_DEVICES },
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothNoDevices", IDS_OPTIONS_SETTINGS_BLUETOOTH_NO_DEVICES },
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothNoDevicesFound",
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_NO_DEVICES_FOUND },
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    { "bluetoothScanning", IDS_OPTIONS_SETTINGS_BLUETOOTH_SCANNING },
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    { "bluetoothDeviceConnecting", IDS_OPTIONS_SETTINGS_BLUETOOTH_CONNECTING },
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothConnectDevice", IDS_OPTIONS_SETTINGS_BLUETOOTH_CONNECT },
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothDisconnectDevice", IDS_OPTIONS_SETTINGS_BLUETOOTH_DISCONNECT },
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothForgetDevice", IDS_OPTIONS_SETTINGS_BLUETOOTH_FORGET },
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothCancel", IDS_OPTIONS_SETTINGS_BLUETOOTH_CANCEL },
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothEnterKey", IDS_OPTIONS_SETTINGS_BLUETOOTH_ENTER_KEY },
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothDismissError", IDS_OPTIONS_SETTINGS_BLUETOOTH_DISMISS_ERROR },
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Device connecting and pairing.
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothStartConnecting",
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_START_CONNECTING },
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothAcceptPasskey",
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_ACCEPT_PASSKEY },
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothRejectPasskey",
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_REJECT_PASSKEY },
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothEnterPinCode",
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_ENTER_PIN_CODE_REQUEST },
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothEnterPasskey",
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_ENTER_PASSKEY_REQUEST },
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothRemotePinCode",
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_REMOTE_PIN_CODE_REQUEST },
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothRemotePasskey",
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_REMOTE_PASSKEY_REQUEST },
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothConfirmPasskey",
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_CONFIRM_PASSKEY_REQUEST },
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Error messages.
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothStartDiscoveryFailed",
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_START_DISCOVERY_FAILED },
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothStopDiscoveryFailed",
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_STOP_DISCOVERY_FAILED },
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothChangePowerFailed",
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_CHANGE_POWER_FAILED },
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    { "bluetoothConnectUnknownError",
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_CONNECT_UNKNOWN_ERROR },
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    { "bluetoothConnectInProgress",
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_CONNECT_IN_PROGRESS },
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothConnectFailed",
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_CONNECT_FAILED },
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    { "bluetoothConnectAuthFailed",
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_CONNECT_AUTH_FAILED },
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    { "bluetoothConnectAuthCanceled",
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_CONNECT_AUTH_CANCELED },
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    { "bluetoothConnectAuthRejected",
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_CONNECT_AUTH_REJECTED },
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    { "bluetoothConnectAuthTimeout",
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_CONNECT_AUTH_TIMEOUT },
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    { "bluetoothConnectUnsupportedDevice",
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_CONNECT_UNSUPPORTED_DEVICE },
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothDisconnectFailed",
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_DISCONNECT_FAILED },
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothForgetFailed",
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_FORGET_FAILED }};
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RegisterStrings(localized_strings, resources, arraysize(resources));
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(kevers): Reorder methods to match ordering in the header file.
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::AdapterPresentChanged(
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    device::BluetoothAdapter* adapter,
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool present) {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(adapter == adapter_.get());
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (present) {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    web_ui()->CallJavascriptFunction(
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "options.BrowserOptions.showBluetoothSettings");
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Update the checkbox and visibility based on the powered state of the
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // new adapter.
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AdapterPoweredChanged(adapter_.get(), adapter_->IsPowered());
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    web_ui()->CallJavascriptFunction(
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "options.BrowserOptions.hideBluetoothSettings");
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::AdapterPoweredChanged(
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    device::BluetoothAdapter* adapter,
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool powered) {
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(adapter == adapter_.get());
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::FundamentalValue checked(powered);
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->CallJavascriptFunction(
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "options.BrowserOptions.setBluetoothState", checked);
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::RegisterMessages() {
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->RegisterMessageCallback("bluetoothEnableChange",
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&BluetoothOptionsHandler::EnableChangeCallback,
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)));
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->RegisterMessageCallback("findBluetoothDevices",
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&BluetoothOptionsHandler::FindDevicesCallback,
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)));
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->RegisterMessageCallback("updateBluetoothDevice",
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&BluetoothOptionsHandler::UpdateDeviceCallback,
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)));
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->RegisterMessageCallback("stopBluetoothDeviceDiscovery",
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&BluetoothOptionsHandler::StopDiscoveryCallback,
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)));
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->RegisterMessageCallback("getPairedBluetoothDevices",
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&BluetoothOptionsHandler::GetPairedDevicesCallback,
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)));
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::InitializeHandler() {
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  device::BluetoothAdapterFactory::GetAdapter(
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&BluetoothOptionsHandler::InitializeAdapter,
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr()));
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::InitializePage() {
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Show or hide the bluetooth settings and update the checkbox based
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // on the current present/powered state.
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AdapterPresentChanged(adapter_.get(), adapter_->IsPresent());
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Automatically start device discovery if the "Add Bluetooth Device"
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // overlay is visible.
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->CallJavascriptFunction(
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "options.BluetoothOptions.updateDiscovery");
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothOptionsHandler::InitializeAdapter(
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_refptr<device::BluetoothAdapter> adapter) {
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  adapter_ = adapter;
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK(adapter_);
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  adapter_->AddObserver(this);
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::EnableChangeCallback(
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ListValue* args) {
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool bluetooth_enabled;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  args->GetBoolean(0, &bluetooth_enabled);
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  adapter_->SetPowered(bluetooth_enabled,
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       base::Bind(&base::DoNothing),
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       base::Bind(&BluetoothOptionsHandler::EnableChangeError,
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  weak_ptr_factory_.GetWeakPtr()));
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::EnableChangeError() {
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VLOG(1) << "Failed to change power state.";
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportError("bluetoothChangePowerFailed", std::string());
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::FindDevicesCallback(
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ListValue* args) {
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!discovering_) {
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    discovering_ = true;
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    adapter_->StartDiscovering(
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&base::DoNothing),
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&BluetoothOptionsHandler::FindDevicesError,
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::FindDevicesError() {
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VLOG(1) << "Failed to start discovery.";
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportError("bluetoothStartDiscoveryFailed", std::string());
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::UpdateDeviceCallback(
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ListValue* args) {
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string address;
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  args->GetString(kUpdateDeviceAddressIndex, &address);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  device::BluetoothDevice* device = adapter_->GetDevice(address);
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!device)
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string command;
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  args->GetString(kUpdateDeviceCommandIndex, &command);
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (command == kConnectCommand) {
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int size = args->GetSize();
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (size > kUpdateDeviceAuthTokenIndex) {
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // PIN code or Passkey entry during the pairing process.
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string auth_token;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      args->GetString(kUpdateDeviceAuthTokenIndex, &auth_token);
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (device->ExpectingPinCode()) {
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        DeviceConnecting(device);
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // PIN Code is an array of 1 to 16 8-bit bytes, the usual
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // interpretation, and the one shared by BlueZ, is a UTF-8 string
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // of as many characters that will fit in that space, thus we
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // can use the auth token from JavaScript unmodified.
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        VLOG(1) << "PIN Code supplied: " << address << ": " << auth_token;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        device->SetPinCode(auth_token);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (device->ExpectingPasskey()) {
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        DeviceConnecting(device);
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Passkey is a numeric in the range 0-999999, in this case the
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // JavaScript code should have ensured the auth token string only
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // contains digits so a simple conversion is sufficient. In the
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // failure case, just use 0 since that's the most likely Passkey
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // anyway, and if it's refused the device will request a new one.
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        unsigned passkey = 0;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::StringToUint(auth_token, &passkey);
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        VLOG(1) << "Passkey supplied: " << address << ": " << passkey;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        device->SetPasskey(passkey);
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(WARNING) << "Auth token supplied after pairing ended: " << address
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     << ": " << auth_token;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // Determine if the device supports pairing:
297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      PairingDelegate* delegate = NULL;
298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (device->IsPairable())
299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        delegate = this;
300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Connection request.
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      VLOG(1) << "Connect: " << address;
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      device->Connect(
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          delegate,
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          base::Bind(&BluetoothOptionsHandler::Connected,
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr()),
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(&BluetoothOptionsHandler::ConnectError,
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr(),
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     device->GetAddress()));
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (command == kCancelCommand) {
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Cancel pairing.
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VLOG(1) << "Cancel pairing: " << address;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    device->CancelPairing();
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (command == kAcceptCommand) {
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Confirm displayed Passkey.
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VLOG(1) << "Confirm pairing: " << address;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    device->ConfirmPairing();
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (command == kRejectCommand) {
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Reject displayed Passkey.
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VLOG(1) << "Reject pairing: " << address;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    device->RejectPairing();
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (command == kDisconnectCommand) {
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Disconnect from device.
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VLOG(1) << "Disconnect device: " << address;
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    device->Disconnect(
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&base::DoNothing),
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&BluetoothOptionsHandler::DisconnectError,
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr(),
330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   device->GetAddress()));
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (command == kForgetCommand) {
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Disconnect from device and delete pairing information.
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VLOG(1) << "Forget device: " << address;
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    device->Forget(base::Bind(&BluetoothOptionsHandler::ForgetError,
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              weak_ptr_factory_.GetWeakPtr(),
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                              device->GetAddress()));
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Unknown updateBluetoothDevice command: " << command;
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void BluetoothOptionsHandler::Connected() {
343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Invalidate the local cache.
344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  pairing_device_address_.clear();
345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  pairing_device_entered_ = kInvalidEntered;
346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  web_ui()->CallJavascriptFunction(
348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "options.BluetoothPairing.dismissDialog");
349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothOptionsHandler::ConnectError(
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& address,
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    device::BluetoothDevice::ConnectErrorCode error_code) {
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char* error_name = NULL;
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Invalidate the local cache.
357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  pairing_device_address_.clear();
358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  pairing_device_entered_ = kInvalidEntered;
359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VLOG(1) << "Failed to connect to device: " << address;
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (error_code) {
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case device::BluetoothDevice::ERROR_UNKNOWN:
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      error_name = "bluetoothConnectUnknownError";
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case device::BluetoothDevice::ERROR_INPROGRESS:
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      error_name = "bluetoothConnectInProgress";
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case device::BluetoothDevice::ERROR_FAILED:
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      error_name = "bluetoothConnectFailed";
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case device::BluetoothDevice::ERROR_AUTH_FAILED:
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      error_name = "bluetoothConnectAuthFailed";
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case device::BluetoothDevice::ERROR_AUTH_CANCELED:
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      error_name = "bluetoothConnectAuthCanceled";
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case device::BluetoothDevice::ERROR_AUTH_REJECTED:
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      error_name = "bluetoothConnectAuthRejected";
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case device::BluetoothDevice::ERROR_AUTH_TIMEOUT:
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      error_name = "bluetoothConnectAuthTimeout";
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case device::BluetoothDevice::ERROR_UNSUPPORTED_DEVICE:
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      error_name = "bluetoothConnectUnsupportedDevice";
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Report an error only if there's an error to report.
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (error_name)
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ReportError(error_name, address);
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::DisconnectError(const std::string& address) {
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VLOG(1) << "Failed to disconnect from device: " << address;
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportError("bluetoothDisconnectFailed", address);
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::ForgetError(const std::string& address) {
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VLOG(1) << "Failed to disconnect and unpair device: " << address;
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportError("bluetoothForgetFailed", address);
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::StopDiscoveryCallback(
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ListValue* args) {
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (discovering_) {
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    adapter_->StopDiscovering(
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&base::DoNothing),
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&BluetoothOptionsHandler::StopDiscoveryError,
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    discovering_ = false;
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::StopDiscoveryError() {
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VLOG(1) << "Failed to stop discovery.";
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportError("bluetoothStopDiscoveryFailed", std::string());
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::GetPairedDevicesCallback(
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ListValue* args) {
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  device::BluetoothAdapter::DeviceList devices = adapter_->GetDevices();
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (device::BluetoothAdapter::DeviceList::iterator iter = devices.begin();
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != devices.end(); ++iter)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SendDeviceNotification(*iter, NULL);
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::SendDeviceNotification(
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const device::BluetoothDevice* device,
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::DictionaryValue* params) {
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::DictionaryValue js_properties;
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  js_properties.SetString("name", device->GetName());
432c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  js_properties.SetString("address", device->GetAddress());
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  js_properties.SetBoolean("paired", device->IsPaired());
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  js_properties.SetBoolean("connected", device->IsConnected());
435c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  js_properties.SetBoolean("connecting", device->IsConnecting());
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  js_properties.SetBoolean("connectable", device->IsConnectable());
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (params)
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    js_properties.MergeDictionary(params);
439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
440c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Use the cached values to update js_property.
441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (device->GetAddress() == pairing_device_address_) {
442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::string pairing;
443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!js_properties.GetString("pairing", &pairing)) {
444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      pairing = pairing_device_pairing_;
445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      js_properties.SetString("pairing", pairing);
446c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
447c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (pairing == kRemotePinCode && !js_properties.HasKey("pincode"))
448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      js_properties.SetString("pincode", pairing_device_pincode_);
449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (pairing == kRemotePasskey && !js_properties.HasKey("passkey"))
450c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      js_properties.SetInteger("passkey", pairing_device_passkey_);
451c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if ((pairing == kRemotePinCode || pairing == kRemotePasskey) &&
452c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        !js_properties.HasKey("entered") &&
453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        pairing_device_entered_ != kInvalidEntered) {
454c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      js_properties.SetInteger("entered", pairing_device_entered_);
455c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
456c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
457c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
458c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Update the cache with the new information.
459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (js_properties.HasKey("pairing")) {
460c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    pairing_device_address_ = device->GetAddress();
461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    js_properties.GetString("pairing", &pairing_device_pairing_);
462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    js_properties.GetString("pincode", &pairing_device_pincode_);
463c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    js_properties.GetInteger("passkey", &pairing_device_passkey_);
464c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!js_properties.GetInteger("entered", &pairing_device_entered_))
465c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      pairing_device_entered_ = kInvalidEntered;
466c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
467c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->CallJavascriptFunction(
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "options.BrowserOptions.addBluetoothDevice",
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      js_properties);
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::RequestPinCode(device::BluetoothDevice* device) {
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DictionaryValue params;
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params.SetString("pairing", kEnterPinCode);
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendDeviceNotification(device, &params);
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::RequestPasskey(device::BluetoothDevice* device) {
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DictionaryValue params;
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params.SetString("pairing", kEnterPasskey);
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendDeviceNotification(device, &params);
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::DisplayPinCode(device::BluetoothDevice* device,
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             const std::string& pincode) {
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DictionaryValue params;
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params.SetString("pairing", kRemotePinCode);
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params.SetString("pincode", pincode);
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendDeviceNotification(device, &params);
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::DisplayPasskey(device::BluetoothDevice* device,
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             uint32 passkey) {
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DictionaryValue params;
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params.SetString("pairing", kRemotePasskey);
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params.SetInteger("passkey", passkey);
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendDeviceNotification(device, &params);
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
501c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void BluetoothOptionsHandler::KeysEntered(device::BluetoothDevice* device,
502c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          uint32 entered) {
503c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DictionaryValue params;
504c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  params.SetInteger("entered", entered);
505c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SendDeviceNotification(device, &params);
506c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
507c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::ConfirmPasskey(device::BluetoothDevice* device,
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             uint32 passkey) {
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DictionaryValue params;
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params.SetString("pairing", kConfirmPasskey);
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params.SetInteger("passkey", passkey);
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendDeviceNotification(device, &params);
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::DismissDisplayOrConfirm() {
517c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(adapter_);
518c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
519c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // We can receive this delegate call when we haven't been asked to display or
520c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // confirm anything; we can determine that by checking whether we've saved
521c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // pairing information for the device. This is also a handy way to get the
522c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // BluetoothDevice object we need.
523c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!pairing_device_address_.empty()) {
524c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    device::BluetoothDevice* device =
525c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        adapter_->GetDevice(pairing_device_address_);
526c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(device);
527c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DeviceConnecting(device);
528c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::ReportError(
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& error,
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& address) {
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::DictionaryValue properties;
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  properties.SetString("label", error);
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  properties.SetString("address", address);
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->CallJavascriptFunction(
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "options.BluetoothPairing.showMessage",
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      properties);
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::DeviceAdded(device::BluetoothAdapter* adapter,
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          device::BluetoothDevice* device) {
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(adapter == adapter_.get());
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(device);
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendDeviceNotification(device, NULL);
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::DeviceChanged(device::BluetoothAdapter* adapter,
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            device::BluetoothDevice* device) {
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(adapter == adapter_.get());
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(device);
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendDeviceNotification(device, NULL);
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::DeviceRemoved(device::BluetoothAdapter* adapter,
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            device::BluetoothDevice* device) {
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(adapter == adapter_.get());
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(device);
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
561c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Invalidate the local cache if the pairing device is removed.
562c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (pairing_device_address_ == device->GetAddress()) {
563c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    pairing_device_address_.clear();
564c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    pairing_device_entered_ = kInvalidEntered;
565c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
566c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
567c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::StringValue address(device->GetAddress());
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->CallJavascriptFunction(
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "options.BrowserOptions.removeBluetoothDevice",
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      address);
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothOptionsHandler::DeviceConnecting(
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    device::BluetoothDevice* device) {
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(device);
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DictionaryValue params;
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  params.SetString("pairing", kStartConnecting);
5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SendDeviceNotification(device, &params);
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace options
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace chromeos
583