bluetooth_options_handler.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chromeos {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace options {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)BluetoothOptionsHandler::BluetoothOptionsHandler() : discovering_(false),
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                     weak_ptr_factory_(this) {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BluetoothOptionsHandler::~BluetoothOptionsHandler() {
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (discovering_) {
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    adapter_->StopDiscovering(
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&base::DoNothing),
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&base::DoNothing));
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    discovering_ = false;
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (adapter_.get())
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    adapter_->RemoveObserver(this);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::GetLocalizedValues(
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DictionaryValue* localized_strings) {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(localized_strings);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static OptionsStringResource resources[] = {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetooth", IDS_OPTIONS_SETTINGS_SECTION_TITLE_BLUETOOTH },
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "disableBluetooth", IDS_OPTIONS_SETTINGS_BLUETOOTH_DISABLE },
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "enableBluetooth", IDS_OPTIONS_SETTINGS_BLUETOOTH_ENABLE },
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "addBluetoothDevice", IDS_OPTIONS_SETTINGS_ADD_BLUETOOTH_DEVICE },
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothAddDeviceTitle",
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_ADD_DEVICE_TITLE },
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothOptionsPageTabTitle",
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_ADD_DEVICE_TITLE },
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "findBluetoothDevices", IDS_OPTIONS_SETTINGS_FIND_BLUETOOTH_DEVICES },
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothNoDevices", IDS_OPTIONS_SETTINGS_BLUETOOTH_NO_DEVICES },
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothNoDevicesFound",
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_NO_DEVICES_FOUND },
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"bluetoothScanning", IDS_OPTIONS_SETTINGS_BLUETOOTH_SCANNING },
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"bluetoothDeviceConnected", IDS_OPTIONS_SETTINGS_BLUETOOTH_CONNECTED },
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothDeviceNotConnected",
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_NOT_CONNECTED },
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothConnectDevice", IDS_OPTIONS_SETTINGS_BLUETOOTH_CONNECT },
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothDisconnectDevice", IDS_OPTIONS_SETTINGS_BLUETOOTH_DISCONNECT },
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothForgetDevice", IDS_OPTIONS_SETTINGS_BLUETOOTH_FORGET },
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothCancel", IDS_OPTIONS_SETTINGS_BLUETOOTH_CANCEL },
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothEnterKey", IDS_OPTIONS_SETTINGS_BLUETOOTH_ENTER_KEY },
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothDismissError", IDS_OPTIONS_SETTINGS_BLUETOOTH_DISMISS_ERROR },
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Device connecting and pairing.
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothStartConnecting",
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_START_CONNECTING },
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothAcceptPasskey",
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_ACCEPT_PASSKEY },
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothRejectPasskey",
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_REJECT_PASSKEY },
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothEnterPinCode",
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_ENTER_PIN_CODE_REQUEST },
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothEnterPasskey",
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_ENTER_PASSKEY_REQUEST },
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothRemotePinCode",
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_REMOTE_PIN_CODE_REQUEST },
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothRemotePasskey",
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_REMOTE_PASSKEY_REQUEST },
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothConfirmPasskey",
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_CONFIRM_PASSKEY_REQUEST },
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Error messages.
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothStartDiscoveryFailed",
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_START_DISCOVERY_FAILED },
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothStopDiscoveryFailed",
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_STOP_DISCOVERY_FAILED },
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothChangePowerFailed",
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_CHANGE_POWER_FAILED },
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    { "bluetoothConnectUnknownError",
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_CONNECT_UNKNOWN_ERROR },
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    { "bluetoothConnectInProgress",
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_CONNECT_IN_PROGRESS },
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothConnectFailed",
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_CONNECT_FAILED },
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    { "bluetoothConnectAuthFailed",
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_CONNECT_AUTH_FAILED },
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    { "bluetoothConnectAuthCanceled",
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_CONNECT_AUTH_CANCELED },
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    { "bluetoothConnectAuthRejected",
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_CONNECT_AUTH_REJECTED },
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    { "bluetoothConnectAuthTimeout",
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_CONNECT_AUTH_TIMEOUT },
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    { "bluetoothConnectUnsupportedDevice",
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_CONNECT_UNSUPPORTED_DEVICE },
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothDisconnectFailed",
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_DISCONNECT_FAILED },
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bluetoothForgetFailed",
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IDS_OPTIONS_SETTINGS_BLUETOOTH_FORGET_FAILED }};
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RegisterStrings(localized_strings, resources, arraysize(resources));
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(kevers): Reorder methods to match ordering in the header file.
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::AdapterPresentChanged(
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    device::BluetoothAdapter* adapter,
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool present) {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(adapter == adapter_.get());
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (present) {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    web_ui()->CallJavascriptFunction(
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "options.BrowserOptions.showBluetoothSettings");
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Update the checkbox and visibility based on the powered state of the
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // new adapter.
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AdapterPoweredChanged(adapter_.get(), adapter_->IsPowered());
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    web_ui()->CallJavascriptFunction(
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "options.BrowserOptions.hideBluetoothSettings");
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::AdapterPoweredChanged(
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    device::BluetoothAdapter* adapter,
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool powered) {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(adapter == adapter_.get());
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::FundamentalValue checked(powered);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->CallJavascriptFunction(
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "options.BrowserOptions.setBluetoothState", checked);
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::RegisterMessages() {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->RegisterMessageCallback("bluetoothEnableChange",
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&BluetoothOptionsHandler::EnableChangeCallback,
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)));
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->RegisterMessageCallback("findBluetoothDevices",
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&BluetoothOptionsHandler::FindDevicesCallback,
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)));
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->RegisterMessageCallback("updateBluetoothDevice",
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&BluetoothOptionsHandler::UpdateDeviceCallback,
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)));
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->RegisterMessageCallback("stopBluetoothDeviceDiscovery",
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&BluetoothOptionsHandler::StopDiscoveryCallback,
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)));
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->RegisterMessageCallback("getPairedBluetoothDevices",
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&BluetoothOptionsHandler::GetPairedDevicesCallback,
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)));
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::InitializeHandler() {
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  device::BluetoothAdapterFactory::GetAdapter(
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&BluetoothOptionsHandler::InitializeAdapter,
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr()));
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::InitializePage() {
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Show or hide the bluetooth settings and update the checkbox based
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // on the current present/powered state.
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AdapterPresentChanged(adapter_.get(), adapter_->IsPresent());
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Automatically start device discovery if the "Add Bluetooth Device"
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // overlay is visible.
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->CallJavascriptFunction(
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "options.BluetoothOptions.updateDiscovery");
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothOptionsHandler::InitializeAdapter(
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_refptr<device::BluetoothAdapter> adapter) {
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  adapter_ = adapter;
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK(adapter_);
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  adapter_->AddObserver(this);
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::EnableChangeCallback(
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ListValue* args) {
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool bluetooth_enabled;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  args->GetBoolean(0, &bluetooth_enabled);
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  adapter_->SetPowered(bluetooth_enabled,
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       base::Bind(&base::DoNothing),
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       base::Bind(&BluetoothOptionsHandler::EnableChangeError,
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  weak_ptr_factory_.GetWeakPtr()));
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::EnableChangeError() {
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VLOG(1) << "Failed to change power state.";
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportError("bluetoothChangePowerFailed", std::string());
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::FindDevicesCallback(
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ListValue* args) {
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!discovering_) {
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    discovering_ = true;
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    adapter_->StartDiscovering(
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&base::DoNothing),
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&BluetoothOptionsHandler::FindDevicesError,
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::FindDevicesError() {
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VLOG(1) << "Failed to start discovery.";
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportError("bluetoothStartDiscoveryFailed", std::string());
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::UpdateDeviceCallback(
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ListValue* args) {
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string address;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  args->GetString(kUpdateDeviceAddressIndex, &address);
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  device::BluetoothDevice* device = adapter_->GetDevice(address);
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!device)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string command;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  args->GetString(kUpdateDeviceCommandIndex, &command);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (command == kConnectCommand) {
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int size = args->GetSize();
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (size > kUpdateDeviceAuthTokenIndex) {
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // PIN code or Passkey entry during the pairing process.
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string auth_token;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      args->GetString(kUpdateDeviceAuthTokenIndex, &auth_token);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (device->ExpectingPinCode()) {
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        DeviceConnecting(device);
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // PIN Code is an array of 1 to 16 8-bit bytes, the usual
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // interpretation, and the one shared by BlueZ, is a UTF-8 string
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // of as many characters that will fit in that space, thus we
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // can use the auth token from JavaScript unmodified.
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        VLOG(1) << "PIN Code supplied: " << address << ": " << auth_token;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        device->SetPinCode(auth_token);
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (device->ExpectingPasskey()) {
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        DeviceConnecting(device);
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Passkey is a numeric in the range 0-999999, in this case the
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // JavaScript code should have ensured the auth token string only
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // contains digits so a simple conversion is sufficient. In the
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // failure case, just use 0 since that's the most likely Passkey
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // anyway, and if it's refused the device will request a new one.
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        unsigned passkey = 0;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::StringToUint(auth_token, &passkey);
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        VLOG(1) << "Passkey supplied: " << address << ": " << passkey;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        device->SetPasskey(passkey);
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(WARNING) << "Auth token supplied after pairing ended: " << address
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     << ": " << auth_token;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Connection request.
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      VLOG(1) << "Connect: " << address;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      device->Connect(
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          this,
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(&base::DoNothing),
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(&BluetoothOptionsHandler::ConnectError,
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr(),
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     device->address()));
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (command == kCancelCommand) {
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Cancel pairing.
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VLOG(1) << "Cancel pairing: " << address;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    device->CancelPairing();
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (command == kAcceptCommand) {
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Confirm displayed Passkey.
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VLOG(1) << "Confirm pairing: " << address;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    device->ConfirmPairing();
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (command == kRejectCommand) {
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Reject displayed Passkey.
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VLOG(1) << "Reject pairing: " << address;
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    device->RejectPairing();
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (command == kDisconnectCommand) {
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Disconnect from device.
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VLOG(1) << "Disconnect device: " << address;
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    device->Disconnect(
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&base::DoNothing),
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&BluetoothOptionsHandler::DisconnectError,
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr(),
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   device->address()));
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (command == kForgetCommand) {
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Disconnect from device and delete pairing information.
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VLOG(1) << "Forget device: " << address;
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    device->Forget(base::Bind(&BluetoothOptionsHandler::ForgetError,
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              weak_ptr_factory_.GetWeakPtr(),
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              device->address()));
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Unknown updateBluetoothDevice command: " << command;
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothOptionsHandler::ConnectError(
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& address,
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    device::BluetoothDevice::ConnectErrorCode error_code) {
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char* error_name = NULL;
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VLOG(1) << "Failed to connect to device: " << address;
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (error_code) {
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case device::BluetoothDevice::ERROR_UNKNOWN:
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      error_name = "bluetoothConnectUnknownError";
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case device::BluetoothDevice::ERROR_INPROGRESS:
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      error_name = "bluetoothConnectInProgress";
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case device::BluetoothDevice::ERROR_FAILED:
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      error_name = "bluetoothConnectFailed";
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case device::BluetoothDevice::ERROR_AUTH_FAILED:
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      error_name = "bluetoothConnectAuthFailed";
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case device::BluetoothDevice::ERROR_AUTH_CANCELED:
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      error_name = "bluetoothConnectAuthCanceled";
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case device::BluetoothDevice::ERROR_AUTH_REJECTED:
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      error_name = "bluetoothConnectAuthRejected";
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case device::BluetoothDevice::ERROR_AUTH_TIMEOUT:
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      error_name = "bluetoothConnectAuthTimeout";
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case device::BluetoothDevice::ERROR_UNSUPPORTED_DEVICE:
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      error_name = "bluetoothConnectUnsupportedDevice";
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Report an error only if there's an error to report.
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (error_name)
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ReportError(error_name, address);
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::DisconnectError(const std::string& address) {
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VLOG(1) << "Failed to disconnect from device: " << address;
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportError("bluetoothDisconnectFailed", address);
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::ForgetError(const std::string& address) {
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VLOG(1) << "Failed to disconnect and unpair device: " << address;
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportError("bluetoothForgetFailed", address);
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::StopDiscoveryCallback(
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ListValue* args) {
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (discovering_) {
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    adapter_->StopDiscovering(
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&base::DoNothing),
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&BluetoothOptionsHandler::StopDiscoveryError,
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    discovering_ = false;
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::StopDiscoveryError() {
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VLOG(1) << "Failed to stop discovery.";
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportError("bluetoothStopDiscoveryFailed", std::string());
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::GetPairedDevicesCallback(
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ListValue* args) {
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  device::BluetoothAdapter::DeviceList devices = adapter_->GetDevices();
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (device::BluetoothAdapter::DeviceList::iterator iter = devices.begin();
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != devices.end(); ++iter)
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SendDeviceNotification(*iter, NULL);
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::SendDeviceNotification(
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const device::BluetoothDevice* device,
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::DictionaryValue* params) {
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::DictionaryValue js_properties;
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  js_properties.SetString("name", device->GetName());
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  js_properties.SetString("address", device->address());
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  js_properties.SetBoolean("paired", device->IsPaired());
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  js_properties.SetBoolean("bonded", device->IsBonded());
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  js_properties.SetBoolean("connected", device->IsConnected());
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  js_properties.SetBoolean("connectable", device->IsConnectable());
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (params)
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    js_properties.MergeDictionary(params);
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->CallJavascriptFunction(
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "options.BrowserOptions.addBluetoothDevice",
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      js_properties);
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::RequestPinCode(device::BluetoothDevice* device) {
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DictionaryValue params;
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params.SetString("pairing", kEnterPinCode);
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendDeviceNotification(device, &params);
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::RequestPasskey(device::BluetoothDevice* device) {
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DictionaryValue params;
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params.SetString("pairing", kEnterPasskey);
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendDeviceNotification(device, &params);
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::DisplayPinCode(device::BluetoothDevice* device,
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             const std::string& pincode) {
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DictionaryValue params;
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params.SetString("pairing", kRemotePinCode);
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params.SetString("pincode", pincode);
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendDeviceNotification(device, &params);
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::DisplayPasskey(device::BluetoothDevice* device,
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             uint32 passkey) {
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DictionaryValue params;
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params.SetString("pairing", kRemotePasskey);
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params.SetInteger("passkey", passkey);
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendDeviceNotification(device, &params);
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::ConfirmPasskey(device::BluetoothDevice* device,
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             uint32 passkey) {
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DictionaryValue params;
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params.SetString("pairing", kConfirmPasskey);
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params.SetInteger("passkey", passkey);
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendDeviceNotification(device, &params);
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::DismissDisplayOrConfirm() {
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->CallJavascriptFunction(
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "options.BluetoothPairing.dismissDialog");
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::ReportError(
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& error,
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& address) {
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::DictionaryValue properties;
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  properties.SetString("label", error);
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  properties.SetString("address", address);
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->CallJavascriptFunction(
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "options.BluetoothPairing.showMessage",
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      properties);
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::DeviceAdded(device::BluetoothAdapter* adapter,
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          device::BluetoothDevice* device) {
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(adapter == adapter_.get());
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(device);
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendDeviceNotification(device, NULL);
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::DeviceChanged(device::BluetoothAdapter* adapter,
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            device::BluetoothDevice* device) {
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(adapter == adapter_.get());
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(device);
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendDeviceNotification(device, NULL);
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BluetoothOptionsHandler::DeviceRemoved(device::BluetoothAdapter* adapter,
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            device::BluetoothDevice* device) {
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(adapter == adapter_.get());
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(device);
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StringValue address(device->address());
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->CallJavascriptFunction(
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "options.BrowserOptions.removeBluetoothDevice",
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      address);
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothOptionsHandler::DeviceConnecting(
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    device::BluetoothDevice* device) {
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(device);
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DictionaryValue params;
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  params.SetString("pairing", kStartConnecting);
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SendDeviceNotification(device, &params);
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace options
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace chromeos
508