| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 /** | 5 /** |
| 6 * @fileoverview | 6 * @fileoverview |
| 7 * 'settings-bluetooth-page' is the settings page for managing bluetooth | 7 * 'Settings page for managing bluetooth properties and devices. This page |
| 8 * properties and devices. | 8 * just provodes a summary and link to the subpage. |
| 9 * | |
| 10 * Example: | |
| 11 * <core-animated-pages> | |
| 12 * <settings-bluetooth-page> | |
| 13 * </settings-bluetooth-page> | |
| 14 * ... other pages ... | |
| 15 * </core-animated-pages> | |
| 16 */ | 9 */ |
| 17 | 10 |
| 18 var bluetoothPage = bluetoothPage || { | 11 var bluetoothApis = bluetoothApis || { |
| 19 /** | 12 /** |
| 20 * Set this to provide a fake implementation for testing. | 13 * Set this to provide a fake implementation for testing. |
| 21 * @type {Bluetooth} | 14 * @type {Bluetooth} |
| 22 */ | 15 */ |
| 23 bluetoothApiForTest: null, | 16 bluetoothApiForTest: null, |
| 24 | 17 |
| 25 /** | 18 /** |
| 26 * Set this to provide a fake implementation for testing. | 19 * Set this to provide a fake implementation for testing. |
| 27 * @type {BluetoothPrivate} | 20 * @type {BluetoothPrivate} |
| 28 */ | 21 */ |
| 29 bluetoothPrivateApiForTest: null, | 22 bluetoothPrivateApiForTest: null, |
| 30 }; | 23 }; |
| 31 | 24 |
| 32 Polymer({ | 25 Polymer({ |
| 33 is: 'settings-bluetooth-page', | 26 is: 'settings-bluetooth-page', |
| 34 | 27 |
| 35 behaviors: [I18nBehavior, CrScrollableBehavior], | 28 behaviors: [I18nBehavior], |
| 36 | 29 |
| 37 properties: { | 30 properties: { |
| 38 /** Preferences state. */ | 31 /** Preferences state. */ |
| 39 prefs: { | 32 prefs: { |
| 40 type: Object, | 33 type: Object, |
| 41 notify: true, | 34 notify: true, |
| 42 }, | 35 }, |
| 43 | 36 |
| 44 /** @private */ | 37 /** @private */ |
| 45 bluetoothEnabled_: { | 38 bluetoothEnabled_: { |
| 46 type: Boolean, | 39 type: Boolean, |
| 47 value: false, | |
| 48 observer: 'bluetoothEnabledChanged_', | 40 observer: 'bluetoothEnabledChanged_', |
| 41 notify: true, |
| 49 }, | 42 }, |
| 50 | 43 |
| 51 /** @private */ | 44 /** |
| 52 deviceListExpanded_: { | 45 * Set by bluetooth-subpage to controll spinner visibilit in the header. |
| 46 * @private |
| 47 */ |
| 48 showSpinner_: { |
| 53 type: Boolean, | 49 type: Boolean, |
| 50 notify: true, |
| 54 value: false, | 51 value: false, |
| 55 }, | 52 }, |
| 56 | 53 |
| 57 /** | 54 /** |
| 58 * The cached bluetooth adapter state. | 55 * The cached bluetooth adapter state. |
| 59 * @type {!chrome.bluetooth.AdapterState|undefined} | 56 * @type {!chrome.bluetooth.AdapterState|undefined} |
| 60 * @private | 57 * @private |
| 61 */ | 58 */ |
| 62 adapterState_: Object, | 59 adapterState_: { |
| 63 | 60 type: Object, |
| 64 /** | 61 notify: true, |
| 65 * Whether or not a bluetooth device is connected. | |
| 66 * @private | |
| 67 */ | |
| 68 deviceConnected_: Boolean, | |
| 69 | |
| 70 /** | |
| 71 * The ordered list of bluetooth devices. | |
| 72 * @type {!Array<!chrome.bluetooth.Device>} | |
| 73 * @private | |
| 74 */ | |
| 75 deviceList_: { | |
| 76 type: Array, | |
| 77 value: function() { | |
| 78 return []; | |
| 79 }, | |
| 80 }, | 62 }, |
| 81 | 63 |
| 82 /** | 64 /** |
| 83 * Reflects the iron-list selecteditem property. | |
| 84 * @type {!chrome.bluetooth.Device} | |
| 85 * @private | |
| 86 */ | |
| 87 selectedItem_: { | |
| 88 type: Object, | |
| 89 observer: 'selectedItemChanged_', | |
| 90 }, | |
| 91 | |
| 92 /** | |
| 93 * Set to the name of the dialog to show. This page uses a single | |
| 94 * paper-dialog to host one of three dialog elements, 'addDevice', | |
| 95 * 'pairDevice', or 'connectError'. This allows a seamless transition | |
| 96 * between dialogs. Note: This property should be set before opening the | |
| 97 * dialog and setting the property will not itself cause the dialog to open. | |
| 98 * @private | |
| 99 */ | |
| 100 dialogId_: String, | |
| 101 | |
| 102 /** | |
| 103 * Current Pairing device. | |
| 104 * @type {?chrome.bluetooth.Device|undefined} | |
| 105 * @private | |
| 106 */ | |
| 107 pairingDevice_: Object, | |
| 108 | |
| 109 /** | |
| 110 * Current Pairing event. | |
| 111 * @type {?chrome.bluetoothPrivate.PairingEvent|undefined} | |
| 112 * @private | |
| 113 */ | |
| 114 pairingEvent_: Object, | |
| 115 | |
| 116 /** | |
| 117 * The translated error message to show when a connect error occurs. | |
| 118 * @private | |
| 119 */ | |
| 120 errorMessage_: String, | |
| 121 | |
| 122 /** | |
| 123 * Interface for bluetooth calls. May be overriden by tests. | 65 * Interface for bluetooth calls. May be overriden by tests. |
| 124 * @type {Bluetooth} | 66 * @type {Bluetooth} |
| 125 * @private | 67 * @private |
| 126 */ | 68 */ |
| 127 bluetooth: { | 69 bluetooth: { |
| 128 type: Object, | 70 type: Object, |
| 129 value: chrome.bluetooth, | 71 value: chrome.bluetooth, |
| 130 }, | 72 }, |
| 131 | 73 |
| 132 /** | 74 /** |
| 133 * Interface for bluetoothPrivate calls. May be overriden by tests. | 75 * Interface for bluetoothPrivate calls. May be overriden by tests. |
| 134 * @type {BluetoothPrivate} | 76 * @type {BluetoothPrivate} |
| 135 * @private | 77 * @private |
| 136 */ | 78 */ |
| 137 bluetoothPrivate: { | 79 bluetoothPrivate: { |
| 138 type: Object, | 80 type: Object, |
| 139 value: chrome.bluetoothPrivate, | 81 value: chrome.bluetoothPrivate, |
| 140 }, | 82 }, |
| 141 }, | 83 }, |
| 142 | 84 |
| 143 observers: ['deviceListChanged_(deviceList_.*)'], | 85 observers: ['deviceListChanged_(deviceList_.*)'], |
| 144 | 86 |
| 145 /** | 87 /** |
| 146 * Listener for chrome.bluetooth.onAdapterStateChanged events. | 88 * Listener for chrome.bluetooth.onAdapterStateChanged events. |
| 147 * @type {function(!chrome.bluetooth.AdapterState)|undefined} | 89 * @type {function(!chrome.bluetooth.AdapterState)|undefined} |
| 148 * @private | 90 * @private |
| 149 */ | 91 */ |
| 150 bluetoothAdapterStateChangedListener_: undefined, | 92 bluetoothAdapterStateChangedListener_: undefined, |
| 151 | 93 |
| 152 /** | |
| 153 * Listener for chrome.bluetooth.onBluetoothDeviceAdded/Changed events. | |
| 154 * @type {function(!chrome.bluetooth.Device)|undefined} | |
| 155 * @private | |
| 156 */ | |
| 157 bluetoothDeviceUpdatedListener_: undefined, | |
| 158 | |
| 159 /** | |
| 160 * Listener for chrome.bluetooth.onBluetoothDeviceRemoved events. | |
| 161 * @type {function(!chrome.bluetooth.Device)|undefined} | |
| 162 * @private | |
| 163 */ | |
| 164 bluetoothDeviceRemovedListener_: undefined, | |
| 165 | |
| 166 /** | |
| 167 * Listener for chrome.bluetoothPrivate.onPairing events. | |
| 168 * @type {function(!chrome.bluetoothPrivate.PairingEvent)|undefined} | |
| 169 * @private | |
| 170 */ | |
| 171 bluetoothPrivateOnPairingListener_: undefined, | |
| 172 | |
| 173 /** @override */ | 94 /** @override */ |
| 174 ready: function() { | 95 ready: function() { |
| 175 if (bluetoothPage.bluetoothApiForTest) | 96 if (bluetoothApis.bluetoothApiForTest) |
| 176 this.bluetooth = bluetoothPage.bluetoothApiForTest; | 97 this.bluetooth = bluetoothApis.bluetoothApiForTest; |
| 177 if (bluetoothPage.bluetoothPrivateApiForTest) | 98 if (bluetoothApis.bluetoothPrivateApiForTest) |
| 178 this.bluetoothPrivate = bluetoothPage.bluetoothPrivateApiForTest; | 99 this.bluetoothPrivate = bluetoothApis.bluetoothPrivateApiForTest; |
| 179 }, | 100 }, |
| 180 | 101 |
| 181 /** @override */ | 102 /** @override */ |
| 182 attached: function() { | 103 attached: function() { |
| 183 this.bluetoothAdapterStateChangedListener_ = | 104 this.bluetoothAdapterStateChangedListener_ = |
| 184 this.onBluetoothAdapterStateChanged_.bind(this); | 105 this.onBluetoothAdapterStateChanged_.bind(this); |
| 185 this.bluetooth.onAdapterStateChanged.addListener( | 106 this.bluetooth.onAdapterStateChanged.addListener( |
| 186 this.bluetoothAdapterStateChangedListener_); | 107 this.bluetoothAdapterStateChangedListener_); |
| 187 | 108 |
| 188 this.bluetoothDeviceUpdatedListener_ = | |
| 189 this.onBluetoothDeviceUpdated_.bind(this); | |
| 190 this.bluetooth.onDeviceAdded.addListener( | |
| 191 this.bluetoothDeviceUpdatedListener_); | |
| 192 this.bluetooth.onDeviceChanged.addListener( | |
| 193 this.bluetoothDeviceUpdatedListener_); | |
| 194 | |
| 195 this.bluetoothDeviceRemovedListener_ = | |
| 196 this.onBluetoothDeviceRemoved_.bind(this); | |
| 197 this.bluetooth.onDeviceRemoved.addListener( | |
| 198 this.bluetoothDeviceRemovedListener_); | |
| 199 | |
| 200 // Request the inital adapter state. | 109 // Request the inital adapter state. |
| 201 this.bluetooth.getAdapterState(this.bluetoothAdapterStateChangedListener_); | 110 this.bluetooth.getAdapterState(this.bluetoothAdapterStateChangedListener_); |
| 202 }, | 111 }, |
| 203 | 112 |
| 204 /** @override */ | 113 /** @override */ |
| 205 detached: function() { | 114 detached: function() { |
| 206 if (this.bluetoothAdapterStateChangedListener_) { | 115 if (this.bluetoothAdapterStateChangedListener_) { |
| 207 this.bluetooth.onAdapterStateChanged.removeListener( | 116 this.bluetooth.onAdapterStateChanged.removeListener( |
| 208 this.bluetoothAdapterStateChangedListener_); | 117 this.bluetoothAdapterStateChangedListener_); |
| 209 } | 118 } |
| 210 if (this.bluetoothDeviceUpdatedListener_) { | |
| 211 this.bluetooth.onDeviceAdded.removeListener( | |
| 212 this.bluetoothDeviceUpdatedListener_); | |
| 213 this.bluetooth.onDeviceChanged.removeListener( | |
| 214 this.bluetoothDeviceUpdatedListener_); | |
| 215 } | |
| 216 if (this.bluetoothDeviceRemovedListener_) { | |
| 217 this.bluetooth.onDeviceRemoved.removeListener( | |
| 218 this.bluetoothDeviceRemovedListener_); | |
| 219 } | |
| 220 }, | |
| 221 | |
| 222 /** @private */ | |
| 223 bluetoothEnabledChanged_: function() { | |
| 224 // When bluetooth is enabled, auto-expand the device list. | |
| 225 if (this.bluetoothEnabled_) | |
| 226 this.deviceListExpanded_ = true; | |
| 227 }, | |
| 228 | |
| 229 /** @private */ | |
| 230 deviceListChanged_: function() { | |
| 231 for (var i = 0; i < this.deviceList_.length; ++i) { | |
| 232 if (this.deviceList_[i].connected) { | |
| 233 this.deviceConnected_ = true; | |
| 234 return; | |
| 235 } | |
| 236 } | |
| 237 this.deviceConnected_ = false; | |
| 238 }, | |
| 239 | |
| 240 /** @private */ | |
| 241 selectedItemChanged_: function() { | |
| 242 if (this.selectedItem_) | |
| 243 this.connectDevice_(this.selectedItem_); | |
| 244 }, | 119 }, |
| 245 | 120 |
| 246 /** | 121 /** |
| 247 * @return {string} | 122 * @return {string} |
| 248 * @private | 123 * @private |
| 249 */ | 124 */ |
| 250 getIcon_: function() { | 125 getIcon_: function() { |
| 251 if (!this.bluetoothEnabled_) | 126 if (!this.bluetoothEnabled_) |
| 252 return 'settings:bluetooth-disabled'; | 127 return 'settings:bluetooth-disabled'; |
| 253 if (this.deviceConnected_) | |
| 254 return 'settings:bluetooth-connected'; | |
| 255 return 'settings:bluetooth'; | 128 return 'settings:bluetooth'; |
| 256 }, | 129 }, |
| 257 | 130 |
| 258 /** | 131 /** |
| 259 * @return {string} | 132 * @return {string} |
| 260 * @private | 133 * @private |
| 261 */ | 134 */ |
| 262 getTitle_: function() { | 135 getTitle_: function() { |
| 263 return this.i18n( | 136 return this.i18n( |
| 264 this.bluetoothEnabled_ ? 'bluetoothEnabled' : 'bluetoothDisabled'); | 137 this.bluetoothEnabled_ ? 'bluetoothEnabled' : 'bluetoothDisabled'); |
| 265 }, | 138 }, |
| 266 | 139 |
| 267 /** @private */ | |
| 268 toggleDeviceListExpanded_: function() { | |
| 269 this.deviceListExpanded_ = !this.deviceListExpanded_; | |
| 270 }, | |
| 271 | |
| 272 /** | |
| 273 * @return {boolean} Whether the <iron-collapse> can be shown. | |
| 274 * @private | |
| 275 */ | |
| 276 canShowDeviceList_: function() { | |
| 277 return this.bluetoothEnabled_ && this.deviceListExpanded_; | |
| 278 }, | |
| 279 | |
| 280 /** | |
| 281 * If bluetooth is enabled, request the complete list of devices and update | |
| 282 * this.deviceList_. | |
| 283 * @private | |
| 284 */ | |
| 285 updateDeviceList_: function() { | |
| 286 if (!this.bluetoothEnabled_) { | |
| 287 this.deviceList_ = []; | |
| 288 return; | |
| 289 } | |
| 290 this.bluetooth.getDevices(function(devices) { | |
| 291 this.deviceList_ = devices; | |
| 292 this.updateScrollableContents(); | |
| 293 }.bind(this)); | |
| 294 }, | |
| 295 | |
| 296 /** | |
| 297 * Event called when a user action changes the bluetoothEnabled state. | |
| 298 * @private | |
| 299 */ | |
| 300 onBluetoothEnabledChange_: function() { | |
| 301 this.bluetoothPrivate.setAdapterState( | |
| 302 {powered: this.bluetoothEnabled_}, function() { | |
| 303 if (chrome.runtime.lastError) { | |
| 304 console.error( | |
| 305 'Error enabling bluetooth: ' + | |
| 306 chrome.runtime.lastError.message); | |
| 307 } | |
| 308 }); | |
| 309 }, | |
| 310 | |
| 311 /** | 140 /** |
| 312 * Process bluetooth.onAdapterStateChanged events. | 141 * Process bluetooth.onAdapterStateChanged events. |
| 313 * @param {!chrome.bluetooth.AdapterState} state | 142 * @param {!chrome.bluetooth.AdapterState} state |
| 314 * @private | 143 * @private |
| 315 */ | 144 */ |
| 316 onBluetoothAdapterStateChanged_: function(state) { | 145 onBluetoothAdapterStateChanged_: function(state) { |
| 317 this.adapterState_ = state; | 146 this.adapterState_ = state; |
| 318 this.bluetoothEnabled_ = state.powered; | 147 this.bluetoothEnabled_ = state.powered; |
| 319 this.updateDeviceList_(); | |
| 320 }, | |
| 321 | |
| 322 /** | |
| 323 * Process bluetooth.onDeviceAdded and onDeviceChanged events. | |
| 324 * @param {!chrome.bluetooth.Device} device | |
| 325 * @private | |
| 326 */ | |
| 327 onBluetoothDeviceUpdated_: function(device) { | |
| 328 var address = device.address; | |
| 329 if (this.dialogId_ && this.pairingDevice_ && | |
| 330 this.pairingDevice_.address == address) { | |
| 331 this.pairingDevice_ = device; | |
| 332 } | |
| 333 var index = this.getDeviceIndex_(address); | |
| 334 if (index >= 0) { | |
| 335 this.set('deviceList_.' + index, device); | |
| 336 return; | |
| 337 } | |
| 338 this.push('deviceList_', device); | |
| 339 }, | |
| 340 | |
| 341 /** | |
| 342 * Process bluetooth.onDeviceRemoved events. | |
| 343 * @param {!chrome.bluetooth.Device} device | |
| 344 * @private | |
| 345 */ | |
| 346 onBluetoothDeviceRemoved_: function(device) { | |
| 347 var address = device.address; | |
| 348 var index = this.getDeviceIndex_(address); | |
| 349 if (index < 0) | |
| 350 return; | |
| 351 this.splice('deviceList_', index, 1); | |
| 352 }, | 148 }, |
| 353 | 149 |
| 354 /** @private */ | 150 /** @private */ |
| 355 startDiscovery_: function() { | 151 onTap_: function() { |
| 356 if (!this.adapterState_ || this.adapterState_.discovering) | 152 if (this.adapterState_.available === false) |
| 357 return; | 153 return; |
| 358 | 154 if (!this.bluetoothEnabled_) |
| 359 if (!this.bluetoothPrivateOnPairingListener_) { | 155 this.bluetoothEnabled_ = true; |
| 360 this.bluetoothPrivateOnPairingListener_ = | |
| 361 this.onBluetoothPrivateOnPairing_.bind(this); | |
| 362 this.bluetoothPrivate.onPairing.addListener( | |
| 363 this.bluetoothPrivateOnPairingListener_); | |
| 364 } | |
| 365 | |
| 366 this.bluetooth.startDiscovery(function() { | |
| 367 if (chrome.runtime.lastError) { | |
| 368 if (chrome.runtime.lastError.message == 'Failed to stop discovery') { | |
| 369 // May happen if also started elsewhere; ignore. | |
| 370 return; | |
| 371 } | |
| 372 console.error( | |
| 373 'startDiscovery Error: ' + chrome.runtime.lastError.message); | |
| 374 } | |
| 375 }); | |
| 376 }, | |
| 377 | |
| 378 /** @private */ | |
| 379 stopDiscovery_: function() { | |
| 380 if (!this.get('adapterState_.discovering')) | |
| 381 return; | |
| 382 | |
| 383 if (this.bluetoothPrivateOnPairingListener_) { | |
| 384 this.bluetoothPrivate.onPairing.removeListener( | |
| 385 this.bluetoothPrivateOnPairingListener_); | |
| 386 this.bluetoothPrivateOnPairingListener_ = undefined; | |
| 387 } | |
| 388 | |
| 389 this.bluetooth.stopDiscovery(function() { | |
| 390 if (chrome.runtime.lastError) { | |
| 391 console.error( | |
| 392 'Error stopping bluetooth discovery: ' + | |
| 393 chrome.runtime.lastError.message); | |
| 394 } | |
| 395 }); | |
| 396 }, | |
| 397 | |
| 398 /** | |
| 399 * Process bluetoothPrivate.onPairing events. | |
| 400 * @param {!chrome.bluetoothPrivate.PairingEvent} e | |
| 401 * @private | |
| 402 */ | |
| 403 onBluetoothPrivateOnPairing_: function(e) { | |
| 404 if (!this.dialogId_ || !this.pairingDevice_ || | |
| 405 e.device.address != this.pairingDevice_.address) { | |
| 406 return; | |
| 407 } | |
| 408 if (e.pairing == chrome.bluetoothPrivate.PairingEventType.KEYS_ENTERED && | |
| 409 e.passkey === undefined && this.pairingEvent_) { | |
| 410 // 'keysEntered' event might not include the updated passkey so preserve | |
| 411 // the current one. | |
| 412 e.passkey = this.pairingEvent_.passkey; | |
| 413 } | |
| 414 this.pairingEvent_ = e; | |
| 415 }, | |
| 416 | |
| 417 /** | |
| 418 * @param {!Event} e | |
| 419 * @private | |
| 420 */ | |
| 421 onAddDeviceTap_: function(e) { | |
| 422 e.preventDefault(); | |
| 423 this.openDialog_('addDevice'); | |
| 424 }, | |
| 425 | |
| 426 /** | |
| 427 * @param {!{detail: {action: string, device: !chrome.bluetooth.Device}}} e | |
| 428 * @private | |
| 429 */ | |
| 430 onDeviceEvent_: function(e) { | |
| 431 var action = e.detail.action; | |
| 432 var device = e.detail.device; | |
| 433 if (action == 'connect') | |
| 434 this.connectDevice_(device); | |
| 435 else if (action == 'disconnect') | |
| 436 this.disconnectDevice_(device); | |
| 437 else if (action == 'remove') | |
| 438 this.forgetDevice_(device); | |
| 439 else | 156 else |
| 440 console.error('Unexected action: ' + action); | 157 this.openSubpage_(); |
| 441 }, | |
| 442 | |
| 443 /** | |
| 444 * Handle a response sent from the pairing dialog and pass it to the | |
| 445 * bluetoothPrivate API. | |
| 446 * @param {Event} e | |
| 447 * @private | |
| 448 */ | |
| 449 onResponse_: function(e) { | |
| 450 var options = | |
| 451 /** @type {!chrome.bluetoothPrivate.SetPairingResponseOptions} */ ( | |
| 452 e.detail); | |
| 453 this.bluetoothPrivate.setPairingResponse(options, function() { | |
| 454 if (chrome.runtime.lastError) { | |
| 455 // TODO(stevenjb): Show error. | |
| 456 console.error( | |
| 457 'Error setting pairing response: ' + options.device.name + | |
| 458 ': Response: ' + options.response + | |
| 459 ': Error: ' + chrome.runtime.lastError.message); | |
| 460 } | |
| 461 this.$$('#deviceDialog').close(); | |
| 462 }.bind(this)); | |
| 463 }, | |
| 464 | |
| 465 /** | |
| 466 * @param {string} address | |
| 467 * @return {number} The index of the device associated with |address| or -1. | |
| 468 * @private | |
| 469 */ | |
| 470 getDeviceIndex_: function(address) { | |
| 471 var len = this.deviceList_.length; | |
| 472 for (var i = 0; i < len; ++i) { | |
| 473 if (this.deviceList_[i].address == address) | |
| 474 return i; | |
| 475 } | |
| 476 return -1; | |
| 477 }, | |
| 478 | |
| 479 /** | |
| 480 * @param {!chrome.bluetooth.Device} device | |
| 481 * @return {string} The text to display for |device| in the device list. | |
| 482 * @private | |
| 483 */ | |
| 484 getDeviceName_: function(device) { | |
| 485 return device.name || device.address; | |
| 486 }, | |
| 487 | |
| 488 /** | |
| 489 * @return {!Array<!chrome.bluetooth.Device>} | |
| 490 * @private | |
| 491 */ | |
| 492 getPairedOrConnecting_: function() { | |
| 493 return this.deviceList_.filter(function(device) { | |
| 494 return !!device.paired || !!device.connecting; | |
| 495 }); | |
| 496 }, | |
| 497 | |
| 498 /** | |
| 499 * @return {boolean} True if deviceList contains any paired devices. | |
| 500 * @private | |
| 501 */ | |
| 502 haveDevices_: function() { | |
| 503 return this.deviceList_.findIndex(function(d) { | |
| 504 return !!d.paired; | |
| 505 }) != -1; | |
| 506 }, | |
| 507 | |
| 508 /** | |
| 509 * @param {!chrome.bluetooth.Device} device | |
| 510 * @private | |
| 511 */ | |
| 512 connectDevice_: function(device) { | |
| 513 // If the device is not paired, show the pairing dialog. | |
| 514 if (!device.paired) { | |
| 515 // Set the pairing device and clear any pairing event. | |
| 516 this.pairingDevice_ = device; | |
| 517 this.pairingEvent_ = null; | |
| 518 | |
| 519 this.openDialog_('pairDevice'); | |
| 520 } | |
| 521 | |
| 522 this.bluetoothPrivate.connect(device.address, function(result) { | |
| 523 var error; | |
| 524 if (chrome.runtime.lastError) { | |
| 525 error = chrome.runtime.lastError.message; | |
| 526 } else { | |
| 527 switch (result) { | |
| 528 case chrome.bluetoothPrivate.ConnectResultType.ALREADY_CONNECTED: | |
| 529 case chrome.bluetoothPrivate.ConnectResultType.AUTH_CANCELED: | |
| 530 case chrome.bluetoothPrivate.ConnectResultType.IN_PROGRESS: | |
| 531 case chrome.bluetoothPrivate.ConnectResultType.SUCCESS: | |
| 532 break; | |
| 533 default: | |
| 534 error = result; | |
| 535 } | |
| 536 } | |
| 537 | |
| 538 if (!error) { | |
| 539 this.$$('#deviceDialog').close(); | |
| 540 return; | |
| 541 } | |
| 542 | |
| 543 var name = this.getDeviceName_(device); | |
| 544 var id = 'bluetooth_connect_' + error; | |
| 545 if (this.i18nExists(id)) { | |
| 546 this.errorMessage_ = this.i18n(id, name); | |
| 547 } else { | |
| 548 this.errorMessage_ = error; | |
| 549 console.error('Unexpected error connecting to: ' + name + ': ' + error); | |
| 550 } | |
| 551 this.openDialog_('connectError'); | |
| 552 }.bind(this)); | |
| 553 }, | |
| 554 | |
| 555 /** | |
| 556 * @param {!chrome.bluetooth.Device} device | |
| 557 * @private | |
| 558 */ | |
| 559 disconnectDevice_: function(device) { | |
| 560 this.bluetoothPrivate.disconnectAll(device.address, function() { | |
| 561 if (chrome.runtime.lastError) { | |
| 562 console.error( | |
| 563 'Error disconnecting: ' + device.address + | |
| 564 chrome.runtime.lastError.message); | |
| 565 } | |
| 566 }); | |
| 567 }, | |
| 568 | |
| 569 /** | |
| 570 * @param {!chrome.bluetooth.Device} device | |
| 571 * @private | |
| 572 */ | |
| 573 forgetDevice_: function(device) { | |
| 574 this.bluetoothPrivate.forgetDevice(device.address, function() { | |
| 575 if (chrome.runtime.lastError) { | |
| 576 console.error( | |
| 577 'Error forgetting: ' + device.name + ': ' + | |
| 578 chrome.runtime.lastError.message); | |
| 579 } | |
| 580 this.updateDeviceList_(); | |
| 581 }.bind(this)); | |
| 582 }, | |
| 583 | |
| 584 /** | |
| 585 * @param {string} dialogId | |
| 586 * @param {string} dialogToShow The name of the dialog. | |
| 587 * @return {boolean} | |
| 588 * @private | |
| 589 */ | |
| 590 dialogIsVisible_: function(dialogId, dialogToShow) { | |
| 591 return dialogToShow == dialogId; | |
| 592 }, | |
| 593 | |
| 594 /** | |
| 595 * @param {string} dialogId | |
| 596 * @private | |
| 597 */ | |
| 598 openDialog_: function(dialogId) { | |
| 599 if (this.dialogId_) { | |
| 600 // Dialog already opened, just update the contents. | |
| 601 this.dialogId_ = dialogId; | |
| 602 return; | |
| 603 } | |
| 604 this.dialogId_ = dialogId; | |
| 605 // Call flush so that the dialog gets sized correctly before it is opened. | |
| 606 Polymer.dom.flush(); | |
| 607 var dialog = this.$$('#deviceDialog'); | |
| 608 dialog.open(); | |
| 609 this.startDiscovery_(); | |
| 610 }, | |
| 611 | |
| 612 /** @private */ | |
| 613 onDialogClosed_: function() { | |
| 614 this.stopDiscovery_(); | |
| 615 this.dialogId_ = ''; | |
| 616 this.pairingDevice_ = null; | |
| 617 this.pairingEvent_ = null; | |
| 618 }, | 158 }, |
| 619 | 159 |
| 620 /** | 160 /** |
| 621 * @param {Event} e | 161 * @param {Event} e |
| 622 * @private | 162 * @private |
| 623 */ | 163 */ |
| 624 stopTap_: function(e) { | 164 onSubpageArrowTap_: function(e) { |
| 165 this.openSubpage_(); |
| 625 e.stopPropagation(); | 166 e.stopPropagation(); |
| 626 }, | 167 }, |
| 168 |
| 169 /** @private */ |
| 170 bluetoothEnabledChanged_: function() { |
| 171 this.bluetoothPrivate.setAdapterState( |
| 172 {powered: this.bluetoothEnabled_}, function() { |
| 173 if (chrome.runtime.lastError) { |
| 174 console.error( |
| 175 'Error enabling bluetooth: ' + |
| 176 chrome.runtime.lastError.message); |
| 177 } |
| 178 }); |
| 179 }, |
| 180 |
| 181 /** @private */ |
| 182 openSubpage_: function() { |
| 183 settings.navigateTo(settings.Route.BLUETOOTH_DEVICES); |
| 184 } |
| 627 }); | 185 }); |
| OLD | NEW |