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