| Index: chrome/browser/resources/bluetooth_internals/device_details_page.js
|
| diff --git a/chrome/browser/resources/bluetooth_internals/device_details_page.js b/chrome/browser/resources/bluetooth_internals/device_details_page.js
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..c50f65771fe0a40d81e9da428287a5aead87de62
|
| --- /dev/null
|
| +++ b/chrome/browser/resources/bluetooth_internals/device_details_page.js
|
| @@ -0,0 +1,223 @@
|
| +// Copyright 2017 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +/**
|
| + * Javascript for DeviceDetailsPage which displays all of the details of a
|
| + * device. The page is generated and managed dynamically in bluetooth_internals.
|
| + * served from chrome://bluetooth-internals/.
|
| + */
|
| +
|
| +cr.define('device_details_page', function() {
|
| + /** @const */ var Page = cr.ui.pageManager.Page;
|
| + /** @const */ var Snackbar = snackbar.Snackbar;
|
| + /** @const */ var SnackbarType = snackbar.SnackbarType;
|
| +
|
| + /**
|
| + * Property names that will be displayed in the ObjectFieldSet which contains
|
| + * the DeviceInfo object.
|
| + */
|
| + var PROPERTY_NAMES = {
|
| + name: 'Name',
|
| + address: 'Address',
|
| + is_gatt_connected: 'GATT Connected',
|
| + 'rssi.value': 'Latest RSSI',
|
| + 'services.length': 'Services',
|
| + };
|
| +
|
| + /**
|
| + * Page that displays all of the details of a device. This page is generated
|
| + * and managed dynamically in bluetooth_internals. This page is the owner of
|
| + * the DevicePtr when a connection is created. Therefore, it manages the
|
| + * connection to the Bluetooth device and performs all Device interface
|
| + * related actions.
|
| + * @constructor
|
| + * @param {string} id
|
| + * @param {!interfaces.BluetoothDevice.DeviceInfo} deviceInfo
|
| + * @extends {cr.ui.pageManager.Page}
|
| + */
|
| + function DeviceDetailsPage(id, deviceInfo) {
|
| + Page.call(this, id, deviceInfo.name_for_display, id);
|
| +
|
| + /** @type {interfaces.BluetoothDevice.DeviceInfo} */
|
| + this.deviceInfo = deviceInfo;
|
| +
|
| + /** @type {interfaces.BluetoothDevice.Device.ptrClass} */
|
| + this.devicePtr = null;
|
| +
|
| + /** @type {!object_fieldset.ObjectFieldSet} */
|
| + this.deviceFieldSet = new object_fieldset.ObjectFieldSet();
|
| + this.deviceFieldSet.setPropertyDisplayNames(PROPERTY_NAMES);
|
| +
|
| + /** @private {!device_collection.ConnectionStatus} */
|
| + this.status_ = device_collection.ConnectionStatus.DISCONNECTED;
|
| +
|
| + /** @private {?HTMLElement} */
|
| + this.connectBtn_ = null;
|
| +
|
| + this.pageDiv.appendChild(
|
| + document.importNode($('device-details-template').content,
|
| + true /* deep */));
|
| +
|
| + this.pageDiv.querySelector('.device-details').appendChild(
|
| + this.deviceFieldSet);
|
| +
|
| + this.pageDiv.querySelector('.forget').addEventListener(
|
| + 'click', function() {
|
| + this.disconnect();
|
| + this.pageDiv.dispatchEvent(new CustomEvent('forgetpressed', {
|
| + detail: {
|
| + address: this.deviceInfo.address,
|
| + },
|
| + }));
|
| + }.bind(this));
|
| +
|
| + this.connectBtn_ = this.pageDiv.querySelector('.disconnect');
|
| + this.connectBtn_.addEventListener('click', function() {
|
| + this.devicePtr !== null ? this.disconnect() : this.connect();
|
| + }.bind(this));
|
| +
|
| + this.redraw();
|
| + }
|
| +
|
| + DeviceDetailsPage.prototype = {
|
| + __proto__: Page.prototype,
|
| +
|
| + /** Creates a connection to the Bluetooth device. */
|
| + connect: function() {
|
| + if (this.status_ !== device_collection.ConnectionStatus.DISCONNECTED)
|
| + return;
|
| +
|
| + this.updateConnectionStatus_(
|
| + device_collection.ConnectionStatus.CONNECTING);
|
| +
|
| + adapter_broker.getAdapterBroker().then(function(adapterBroker) {
|
| + return adapterBroker.connectToDevice(this.deviceInfo.address);
|
| + }.bind(this)).then(function(devicePtr) {
|
| + this.devicePtr = devicePtr;
|
| +
|
| + this.updateConnectionStatus_(
|
| + device_collection.ConnectionStatus.CONNECTED);
|
| +
|
| + // Fetch services asynchronously.
|
| + return this.devicePtr.getServices();
|
| + }.bind(this)).then(function(response) {
|
| + this.deviceInfo.services = response.services;
|
| + this.redraw();
|
| + this.fireDeviceInfoChanged_();
|
| + }.bind(this)).catch(function(error) {
|
| + // If a connection error occurs while fetching the services, the
|
| + // devicePtr reference must be removed.
|
| + if (this.devicePtr) {
|
| + this.devicePtr.disconnect();
|
| + this.devicePtr = null;
|
| + }
|
| +
|
| + Snackbar.show(
|
| + this.deviceInfo.name_for_display + ': ' + error.message,
|
| + SnackbarType.DANGER, 'Retry', this.connect.bind(this));
|
| +
|
| + this.updateConnectionStatus_(
|
| + device_collection.ConnectionStatus.DISCONNECTED);
|
| + }.bind(this));
|
| + },
|
| +
|
| + /** Disconnects the page from the Bluetooth device. */
|
| + disconnect: function() {
|
| + if (!this.devicePtr) return;
|
| +
|
| + this.devicePtr.disconnect();
|
| + this.devicePtr = null;
|
| + this.updateConnectionStatus_(
|
| + device_collection.ConnectionStatus.DISCONNECTED);
|
| + },
|
| +
|
| + /** Redraws the contents of the page with the current |deviceInfo|. */
|
| + redraw: function() {
|
| + var isConnected = this.deviceInfo.is_gatt_connected;
|
| +
|
| + // Update status if connection was dropped.
|
| + if (!isConnected) this.disconnect();
|
| + var connectedText = isConnected ? 'Connected' : 'Not Connected';
|
| +
|
| + var rssi = this.deviceInfo.rssi || {};
|
| + var services = this.deviceInfo.services;
|
| +
|
| + var rssiValue = 'Unknown';
|
| + if (rssi.value != null && rssi.value <= 0)
|
| + rssiValue = rssi.value;
|
| +
|
| + var serviceCount = 'Unknown';
|
| + if (services != null && services.length >= 0)
|
| + serviceCount = services.length;
|
| +
|
| + var deviceViewObj = {
|
| + name: this.deviceInfo.name_for_display,
|
| + address: this.deviceInfo.address,
|
| + is_gatt_connected: connectedText,
|
| + 'rssi.value': rssiValue,
|
| + 'services.length': serviceCount,
|
| + };
|
| +
|
| + this.deviceFieldSet.setObject(deviceViewObj);
|
| + },
|
| +
|
| + /**
|
| + * Sets the page's device info and forces a redraw.
|
| + * @param {!interfaces.BluetoothDevice.DeviceInfo}
|
| + */
|
| + setDeviceInfo: function(info) {
|
| + this.deviceInfo = info;
|
| + this.redraw();
|
| + },
|
| +
|
| + /**
|
| + * Fires an 'infochanged' event with the current |deviceInfo|
|
| + * @private
|
| + */
|
| + fireDeviceInfoChanged_: function() {
|
| + this.pageDiv.dispatchEvent(new CustomEvent('infochanged', {
|
| + bubbles: true,
|
| + detail: {
|
| + info: this.deviceInfo,
|
| + },
|
| + }));
|
| + },
|
| +
|
| + /**
|
| + * Updates the current connection status. Caches the latest status, updates
|
| + * the connection button message, and fires a 'connectionchanged' event when
|
| + * finished.
|
| + * @param {!device_collection.ConnectionStatus} status
|
| + * @private
|
| + */
|
| + updateConnectionStatus_: function(status) {
|
| + if (this.status === status)
|
| + return;
|
| +
|
| + this.status_ = status;
|
| + if (status === device_collection.ConnectionStatus.DISCONNECTED) {
|
| + this.connectBtn_.textContent = 'Connect';
|
| + this.connectBtn_.disabled = false;
|
| + } else if (status === device_collection.ConnectionStatus.CONNECTING) {
|
| + this.connectBtn_.textContent = 'Connecting';
|
| + this.connectBtn_.disabled = true;
|
| + } else {
|
| + this.connectBtn_.textContent = 'Disconnect';
|
| + this.connectBtn_.disabled = false;
|
| + }
|
| +
|
| + this.pageDiv.dispatchEvent(new CustomEvent('connectionchanged', {
|
| + bubbles: true,
|
| + detail: {
|
| + address: this.deviceInfo.address,
|
| + status: status,
|
| + }
|
| + }));
|
| + },
|
| + };
|
| +
|
| + return {
|
| + DeviceDetailsPage: DeviceDetailsPage,
|
| + };
|
| +});
|
|
|