blob: e15d870b9e4af0b51130072fbb2db381ce692b71 [file] [log] [blame]
// 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 ServiceList and ServiceListItem, served from
* chrome://bluetooth-internals/.
*/
cr.define('service_list', function() {
/** @const */ var ArrayDataModel = cr.ui.ArrayDataModel;
/** @const */ var ExpandableList = expandable_list.ExpandableList;
/** @const */ var ExpandableListItem = expandable_list.ExpandableListItem;
/** @const */ var Snackbar = snackbar.Snackbar;
/** @const */ var SnackbarType = snackbar.SnackbarType;
/**
* Property names that will be displayed in the ObjectFieldSet which contains
* the ServiceInfo object.
*/
var PROPERTY_NAMES = {
id: 'ID',
'uuid.uuid': 'UUID',
isPrimary: 'Type',
};
/**
* A list item that displays the data in a ServiceInfo object. The brief
* section contains the UUID of the given |serviceInfo|. The expanded section
* contains an ObjectFieldSet that displays all of the properties in the
* given |serviceInfo|. Data is not loaded until the ServiceListItem is
* expanded for the first time.
* @param {!bluetooth.mojom.ServiceInfo} serviceInfo
* @param {string} deviceAddress
* @extends {expandable_list.ExpandableListItem}
* @constructor
*/
function ServiceListItem(serviceInfo, deviceAddress) {
var listItem = new ExpandableListItem();
listItem.__proto__ = ServiceListItem.prototype;
/** @type {!bluetooth.mojom.ServiceInfo} */
listItem.info = serviceInfo;
/** @private {string} */
listItem.deviceAddress_ = deviceAddress;
listItem.decorate();
return listItem;
}
ServiceListItem.prototype = {
__proto__: ExpandableListItem.prototype,
/**
* Decorates the element as a service list item. Creates layout and caches
* references to the created header and fieldset.
* @override
*/
decorate: function() {
this.classList.add('service-list-item');
/** @private {!object_fieldset.ObjectFieldSet} */
this.serviceFieldSet_ = new object_fieldset.ObjectFieldSet();
this.serviceFieldSet_.setPropertyDisplayNames(PROPERTY_NAMES);
this.serviceFieldSet_.setObject({
id: this.info.id,
'uuid.uuid': this.info.uuid.uuid,
isPrimary: this.info.isPrimary ? 'Primary' : 'Secondary',
});
// Create content for display in brief content container.
var serviceHeaderText = document.createElement('div');
serviceHeaderText.textContent = 'Service:';
var serviceHeaderValue = document.createElement('div');
serviceHeaderValue.textContent = this.info.uuid.uuid;
var serviceHeader = document.createElement('div');
serviceHeader.appendChild(serviceHeaderText);
serviceHeader.appendChild(serviceHeaderValue);
this.briefContent_.appendChild(serviceHeader);
// Create content for display in expanded content container.
var serviceInfoHeader = document.createElement('h4');
serviceInfoHeader.textContent = 'Service Info';
var serviceDiv = document.createElement('div');
serviceDiv.classList.add('flex');
serviceDiv.appendChild(this.serviceFieldSet_);
var characteristicsListHeader = document.createElement('h4');
characteristicsListHeader.textContent = 'Characteristics';
this.characteristicList_ = new characteristic_list.CharacteristicList();
var infoDiv = document.createElement('div');
infoDiv.classList.add('info-container');
infoDiv.appendChild(serviceInfoHeader);
infoDiv.appendChild(serviceDiv);
infoDiv.appendChild(characteristicsListHeader);
infoDiv.appendChild(this.characteristicList_);
this.expandedContent_.appendChild(infoDiv);
},
/** @override */
onExpandInternal: function(expanded) {
this.characteristicList_.load(this.deviceAddress_, this.info.id);
},
};
/**
* A list that displays ServiceListItems.
* @constructor
* @extends {expandable_list.ExpandableList}
*/
var ServiceList = cr.ui.define('list');
ServiceList.prototype = {
__proto__: ExpandableList.prototype,
/** @override */
decorate: function() {
ExpandableList.prototype.decorate.call(this);
/** @private {?string} */
this.deviceAddress_ = null;
/** @private {boolean} */
this.servicesRequested_ = false;
this.classList.add('service-list');
this.setEmptyMessage('No Services Found');
},
/** @override */
createItem: function(data) {
return new ServiceListItem(data, assert(this.deviceAddress_));
},
/**
* Loads the service list with an array of ServiceInfo from the
* device with |deviceAddress|. If no active connection to the device
* exists, one is created.
* @param {string} deviceAddress
*/
load: function(deviceAddress) {
if (this.servicesRequested_ || !this.isSpinnerShowing()) {
return;
}
this.deviceAddress_ = deviceAddress;
this.servicesRequested_ = true;
device_broker.connectToDevice(this.deviceAddress_)
.then(function(device) {
return device.getServices();
}.bind(this))
.then(function(response) {
this.setData(new ArrayDataModel(response.services));
this.setSpinnerShowing(false);
this.servicesRequested_ = false;
}.bind(this))
.catch(function(error) {
this.servicesRequested_ = false;
Snackbar.show(
deviceAddress + ': ' + error.message, SnackbarType.ERROR,
'Retry', function() {
this.load(deviceAddress);
}.bind(this));
}.bind(this));
},
};
return {
ServiceList: ServiceList,
ServiceListItem: ServiceListItem,
};
});