Commit eb033605 authored by mbrunson's avatar mbrunson Committed by Commit bot

bluetooth: Add device list UI for chrome://bluetooth-internals.

Adds mobile responsive device list to bluetooth internals page.
Lists device name, address, and latest RSSI.
Refreshes when devices are discovered, removed, or advertising packets are received.

Screenshots
Desktop: https://goo.gl/photos/bot7JsdTuf8P2A328
Mobile: https://goo.gl/photos/G9bb9s4ih5KT3PJw8

BUG=651282
CQ_INCLUDE_TRYBOTS=master.tryserver.chromium.linux:closure_compilation

Review-Url: https://codereview.chromium.org/2418343002
Cr-Commit-Position: refs/heads/master@{#427261}
parent 97df95a8
......@@ -13,11 +13,83 @@ body {
padding: 0;
}
/* Header bar */
header {
background-color: blue;
padding: 2px;
align-items: center;
background-color: rgb(33, 150, 243);
display: flex;
flex-direction: row;
font-size: 20pt;
height: 56px;
justify-content: flex-start;
padding: 0 16px;
}
header * {
.title {
color: white;
display: inline-block;
margin-left: 8px;
}
/* Device table */
table {
border: 1px solid #ccc;
border-collapse: collapse;
margin: 0;
padding: 0;
width: 100%;
}
table tr {
border: 1px solid #ddd;
padding: 5px;
}
table th,
table td {
padding: 10px;
text-align: center;
}
table th {
font-size: 14px;
letter-spacing: 1px;
text-transform: uppercase;
}
@media screen and (max-width: 600px) {
table {
border: 0;
}
table thead {
display: none;
}
table tr {
border-bottom: 2px solid #ddd;
display: block;
}
table td {
border-bottom: 1px dotted #ccc;
display: block;
font-size: 13px;
text-align: right;
}
table td:last-child {
border-bottom: 0;
}
table td::before {
content: attr(data-label);
float: left;
font-weight: bold;
text-transform: uppercase;
}
}
/* Device Row */
table .removed {
background-color: #BDBDBD;
}
\ No newline at end of file
<!DOCTYPE HTML>
<html>
<!-- TODO(crbug.com/658814): Localize strings. -->
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bluetooth Internals</title>
<link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
<link rel="stylesheet" href="bluetooth_internals.css">
<script src="chrome://resources/js/assert.js"></script>
<script src="chrome://resources/js/util.js"></script>
<script src="bluetooth_internals.js"></script>
</head>
<body>
<header>
<h1>Bluetooth Internals</h1>
<div class="title">
Bluetooth Internals
</div>
</header>
<table id="device-table">
<thead>
<tr>
<th>Name</th>
<th>Address</th>
<th>Latest RSSI</th>
</tr>
</thead>
<tbody id="device-list">
</tbody>
</table>
</body>
<template id="device-row-template">
<tr class="device-row">
<td class="device-name" data-label="Name"></td>
<td class="device-address" data-label="Address"></td>
<td class="device-rssi" data-label="Latest RSSI">Unknown</td>
</tr>
</template>
</html>
\ No newline at end of file
......@@ -10,6 +10,8 @@
(function() {
var adapter, adapterClient, bluetoothAdapter, bluetoothDevice, connection;
var REMOVED_CSS = 'removed';
/*
* Data model for a cached device.
* @constructor
......@@ -26,32 +28,56 @@
var AdapterClient = function() { this.devices_ = new Map(); };
AdapterClient.prototype = {
/**
* Logs added device to console and caches the device info.
* @param {!bluetoothDevice.DeviceInfo} device
* Caches the device info and updates the device list.
* @param {!bluetoothDevice.DeviceInfo} deviceInfo
*/
deviceAdded: function(deviceInfo) {
console.log('Device added', deviceInfo);
this.devices_.set(deviceInfo.address, new Device(deviceInfo));
if (this.devices_.has(deviceInfo.address)) {
var deviceElement = $(deviceInfo.address);
deviceElement.classList.remove(REMOVED_CSS);
} else {
this.devices_.set(deviceInfo.address, new Device(deviceInfo));
var deviceRowTemplate = $('device-row-template');
var deviceRow = document.importNode(
deviceRowTemplate.content.children[0], true /* deep */);
deviceRow.id = deviceInfo.address;
var deviceList = $('device-list');
deviceList.appendChild(deviceRow);
}
this.deviceChanged(deviceInfo);
},
/**
* Logs removed device to console and removes the cached device.
* @param {!bluetoothDevice.DeviceInfo} device
* Marks device as removed.
* @param {!bluetoothDevice.DeviceInfo} deviceInfo
*/
deviceRemoved: function(deviceInfo) {
console.log('Device removed', deviceInfo);
this.devices_.delete(deviceInfo.address);
$(deviceInfo.address).classList.add(REMOVED_CSS);
},
/**
* Logs changed device info to console and updates the cached device.
* Updates cached device and updates the device list.
* @param {!bluetoothDevice.DeviceInfo} deviceInfo
*/
deviceChanged: function(deviceInfo) {
console.log(new Date(), deviceInfo);
if (this.devices_.has(deviceInfo.address)) {
this.devices_.get(deviceInfo.address).info = deviceInfo;
}
assert(this.devices_.has(deviceInfo.address), 'Device does not exist.');
this.devices_.get(deviceInfo.address).info = deviceInfo;
var deviceRow = $(deviceInfo.address);
deviceRow.querySelector('.device-name').textContent =
deviceInfo.name_for_display;
deviceRow.querySelector('.device-address').textContent =
deviceInfo.address;
var rssi = (deviceInfo.rssi && deviceInfo.rssi.value) ||
deviceRow.querySelector('.device-rssi').textContent;
deviceRow.querySelector('.device-rssi').textContent = rssi;
}
};
......@@ -81,8 +107,6 @@
'device/bluetooth/public/interfaces/device.mojom',
'mojo/public/js/connection',
]).then(function([frameInterfaces, ...modules]) {
console.log('Loaded modules');
// Destructure here to assign global variables.
[bluetoothAdapter, bluetoothDevice, connection] = modules;
......@@ -117,11 +141,7 @@
.then(function(response) { console.log('adapter', response.info); })
.then(function() { return adapter.getDevices(); })
.then(function(response) {
console.log('devices', response.devices.length);
response.devices.forEach(function(deviceInfo) {
adapterClient.deviceAdded(deviceInfo);
});
response.devices.forEach(adapterClient.deviceAdded, adapterClient);
})
.catch(function(error) { console.error(error); });
});
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment