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