Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(750)

Side by Side Diff: chrome/browser/resources/bluetooth_internals/device_table.js

Issue 2576603002: bluetooth: Add device details page with basic properties to internals page. (Closed)
Patch Set: Fix formatting, fix comments, fix test, change service/rssi display Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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 * Javascript for DeviceTable UI, served from chrome://bluetooth-internals/. 6 * Javascript for DeviceTable UI, served from chrome://bluetooth-internals/.
7 */ 7 */
8 8
9 cr.define('device_table', function() { 9 cr.define('device_table', function() {
10 var COLUMNS = { 10 var COLUMNS = {
11 NAME: 0, 11 NAME: 0,
12 ADDRESS: 1, 12 ADDRESS: 1,
13 RSSI: 2, 13 RSSI: 2,
14 SERVICES: 3, 14 SERVICES: 3,
15 CONNECTION_STATE: 4, 15 CONNECTION_STATE: 4,
16 INSPECT_LINK: 5, 16 LINKS: 5,
17 }; 17 };
18 18
19 /** 19 /**
20 * A table that lists the devices and responds to changes in the given 20 * A table that lists the devices and responds to changes in the given
21 * DeviceCollection. Fires events for inspection requests from listed 21 * DeviceCollection. Fires events for inspection requests from listed
22 * devices. 22 * devices.
23 * @constructor 23 * @constructor
24 * @extends {HTMLTableElement} 24 * @extends {HTMLTableElement}
25 */ 25 */
26 var DeviceTable = cr.ui.define(function() { 26 var DeviceTable = cr.ui.define(function() {
27 /** @private {?Array<device_collection.Device>} */ 27 /** @private {?Array<device_collection.Device>} */
28 this.devices_ = null; 28 this.devices_ = null;
29 29
30 return document.importNode($('table-template').content.children[0], 30 return document.importNode($('table-template').content.children[0],
31 true /* deep */); 31 true /* deep */);
32 }); 32 });
33 33
34 DeviceTable.prototype = { 34 DeviceTable.prototype = {
35 __proto__: HTMLTableElement.prototype, 35 __proto__: HTMLTableElement.prototype,
36 36
37 /** 37 /**
38 * Decorates an element as a UI element class. Caches references to the 38 * Decorates an element as a UI element class. Caches references to the
39 * table body and headers. 39 * table body and headers.
40 */ 40 */
41 decorate: function() { 41 decorate: function() {
42 /** @private */ 42 /** @private */
43 this.body_ = this.tBodies[0]; 43 this.body_ = this.tBodies[0];
44 /** @private */ 44 /** @private */
45 this.headers_ = this.tHead.rows[0].cells; 45 this.headers_ = this.tHead.rows[0].cells;
46 /** @private {!Map<!interfaces.BluetoothDevice.DeviceInfo, boolean>} */
47 this.inspectionMap_ = new Map();
46 }, 48 },
47 49
48 /** 50 /**
49 * Sets the tables device collection. 51 * Sets the tables device collection.
50 * @param {!device_collection.DeviceCollection} deviceCollection 52 * @param {!device_collection.DeviceCollection} deviceCollection
51 */ 53 */
52 setDevices: function(deviceCollection) { 54 setDevices: function(deviceCollection) {
53 assert(!this.devices_, 'Devices can only be set once.'); 55 assert(!this.devices_, 'Devices can only be set once.');
54 56
55 this.devices_ = deviceCollection; 57 this.devices_ = deviceCollection;
56 this.devices_.addEventListener('sorted', this.redraw_.bind(this)); 58 this.devices_.addEventListener('sorted', this.redraw_.bind(this));
57 this.devices_.addEventListener('change', this.handleChange_.bind(this)); 59 this.devices_.addEventListener('change', this.handleChange_.bind(this));
58 this.devices_.addEventListener('splice', this.handleSplice_.bind(this)); 60 this.devices_.addEventListener('splice', this.handleSplice_.bind(this));
59 61
60 this.redraw_(); 62 this.redraw_();
61 }, 63 },
62 64
63 /** 65 /**
66 * Updates the inspect status of the row matching the given |deviceInfo|.
67 * If |isInspecting| is true, the forget link is enabled otherwise it's
68 * disabled.
69 * @param {!interfaces.BluetoothDevice.DeviceInfo} deviceInfo
70 * @param {boolean} isInspecting
71 */
72 setInspecting: function(deviceInfo, isInspecting) {
73 this.inspectionMap_.set(deviceInfo, isInspecting);
74 this.updateRow_(deviceInfo, this.devices_.indexOf(deviceInfo));
75 },
76
77 /**
78 * Fires a forget pressed event for the row |index|.
79 * @param {number} index
80 * @private
81 */
82 handleForgetClick_: function(index) {
83 var event = new CustomEvent('forgetpressed', {
84 bubbles: true,
85 detail: {
86 address: this.devices_.item(index).address,
87 }
88 });
89 this.dispatchEvent(event);
90 },
91
92 /**
64 * Updates table row on change event of the device collection. 93 * Updates table row on change event of the device collection.
94 * @param {!Event} event
65 * @private 95 * @private
66 * @param {!Event} event
67 */ 96 */
68 handleChange_: function(event) { 97 handleChange_: function(event) {
69 this.updateRow_(this.devices_.item(event.index), event.index); 98 this.updateRow_(this.devices_.item(event.index), event.index);
70 }, 99 },
71 100
72 /** 101 /**
73 * Fires a inspect pressed event for the row |index|. 102 * Fires an inspect pressed event for the row |index|.
103 * @param {number} index
74 * @private 104 * @private
75 * @param {number} index
76 */ 105 */
77 handleInspectClick_: function(index) { 106 handleInspectClick_: function(index) {
78 var event = new CustomEvent('inspectpressed', { 107 var event = new CustomEvent('inspectpressed', {
79 bubbles: true, 108 bubbles: true,
80 detail: { 109 detail: {
81 address: this.devices_.item(index).address, 110 address: this.devices_.item(index).address,
82 } 111 }
83 }); 112 });
84 this.dispatchEvent(event); 113 this.dispatchEvent(event);
85 }, 114 },
86 115
87 /** 116 /**
88 * Updates table row on splice event of the device collection. 117 * Updates table row on splice event of the device collection.
118 * @param {!Event} event
89 * @private 119 * @private
90 * @param {!Event} event
91 */ 120 */
92 handleSplice_: function(event) { 121 handleSplice_: function(event) {
93 event.removed.forEach(function() { 122 event.removed.forEach(function() {
94 this.body_.deleteRow(event.index); 123 this.body_.deleteRow(event.index);
95 }, this); 124 }, this);
96 125
97 event.added.forEach(function(device, index) { 126 event.added.forEach(function(device, index) {
98 this.insertRow_(device, event.index + index); 127 this.insertRow_(device, event.index + index);
99 }, this); 128 }, this);
100 }, 129 },
101 130
102 /** 131 /**
103 * Inserts a new row at |index| and updates it with info from |device|. 132 * Inserts a new row at |index| and updates it with info from |device|.
104 * @private
105 * @param {!interfaces.BluetoothDevice.DeviceInfo} device 133 * @param {!interfaces.BluetoothDevice.DeviceInfo} device
106 * @param {?number} index 134 * @param {?number} index
135 * @private
107 */ 136 */
108 insertRow_: function(device, index) { 137 insertRow_: function(device, index) {
109 var row = this.body_.insertRow(index); 138 var row = this.body_.insertRow(index);
110 row.id = device.address; 139 row.id = device.address;
111 140
112 for (var i = 0; i < this.headers_.length; i++) { 141 for (var i = 0; i < this.headers_.length; i++) {
142 // Skip the LINKS column. It has no data-field attribute.
143 if (i === COLUMNS.LINKS) continue;
113 row.insertCell(); 144 row.insertCell();
114 } 145 }
115 146
116 // Make two extra cells for the inspect link and connect errors. 147 // Make two extra cells for the inspect link and connect errors.
117 var inspectCell = row.insertCell(); 148 var inspectCell = row.insertCell();
118 149
119 var inspectLink = document.createElement('a', 'action-link'); 150 var inspectLink = document.createElement('a', 'action-link');
151 inspectLink.textContent = 'Inspect';
120 inspectCell.appendChild(inspectLink); 152 inspectCell.appendChild(inspectLink);
121 inspectLink.addEventListener('click', function() { 153 inspectLink.addEventListener('click', function() {
122 this.handleInspectClick_(row.sectionRowIndex); 154 this.handleInspectClick_(row.sectionRowIndex);
123 }.bind(this)); 155 }.bind(this));
124 156
157 var forgetLink = document.createElement('a', 'action-link');
158 forgetLink.textContent = 'Forget';
159 inspectCell.appendChild(forgetLink);
160 forgetLink.addEventListener('click', function() {
161 this.handleForgetClick_(row.sectionRowIndex);
162 }.bind(this));
163
125 this.updateRow_(device, row.sectionRowIndex); 164 this.updateRow_(device, row.sectionRowIndex);
126 }, 165 },
127 166
128 /** 167 /**
129 * Deletes and recreates the table using the cached |devices_|. 168 * Deletes and recreates the table using the cached |devices_|.
130 * @private 169 * @private
131 */ 170 */
132 redraw_: function() { 171 redraw_: function() {
133 this.removeChild(this.body_); 172 this.removeChild(this.body_);
134 this.appendChild(document.createElement('tbody')); 173 this.appendChild(document.createElement('tbody'));
135 this.body_ = this.tBodies[0]; 174 this.body_ = this.tBodies[0];
136 this.body_.classList.add('table-body'); 175 this.body_.classList.add('table-body');
137 176
138 for (var i = 0; i < this.devices_.length; i++) { 177 for (var i = 0; i < this.devices_.length; i++) {
139 this.insertRow_(this.devices_.item(i)); 178 this.insertRow_(this.devices_.item(i));
140 } 179 }
141 }, 180 },
142 181
143 /** 182 /**
144 * Updates the row at |index| with the info from |device|. 183 * Updates the row at |index| with the info from |device|.
145 * @private
146 * @param {!interfaces.BluetoothDevice.DeviceInfo} device 184 * @param {!interfaces.BluetoothDevice.DeviceInfo} device
147 * @param {number} index 185 * @param {number} index
186 * @private
148 */ 187 */
149 updateRow_: function(device, index) { 188 updateRow_: function(device, index) {
150 var row = this.body_.rows[index]; 189 var row = this.body_.rows[index];
151 assert(row, 'Row ' + index + ' is not in the table.'); 190 assert(row, 'Row ' + index + ' is not in the table.');
152 191
153 row.classList.toggle('removed', device.removed); 192 row.classList.toggle('removed', device.removed);
154 193
155 var inspectLink = row.cells[COLUMNS.INSPECT_LINK].children[0]; 194 var forgetLink = row.cells[COLUMNS.LINKS].children[1];
156 inspectLink.disabled = false; 195
157 switch (device.connectionStatus) { 196 if (this.inspectionMap_.has(device))
158 case device_collection.ConnectionStatus.DISCONNECTED: 197 forgetLink.disabled = !this.inspectionMap_.get(device);
159 inspectLink.textContent = 'Inspect'; 198 else
160 break; 199 forgetLink.disabled = true;
161 case device_collection.ConnectionStatus.CONNECTED:
162 inspectLink.textContent = 'Forget';
163 break;
164 case device_collection.ConnectionStatus.CONNECTING:
165 inspectLink.disabled = true;
166 break;
167 default: assert('case not handled');
168 }
169 200
170 // Update the properties based on the header field path. 201 // Update the properties based on the header field path.
171 for (var i = 0; i < this.headers_.length; i++) { 202 for (var i = 0; i < this.headers_.length; i++) {
203 // Skip the LINKS column. It has no data-field attribute.
204 if (i === COLUMNS.LINKS) continue;
205
172 var header = this.headers_[i]; 206 var header = this.headers_[i];
173 var propName = header.dataset.field; 207 var propName = header.dataset.field;
174 208
175 var parts = propName.split('.'); 209 var parts = propName.split('.');
176 var obj = device; 210 var obj = device;
177 while (obj != null && parts.length > 0) { 211 while (obj != null && parts.length > 0) {
178 var part = parts.shift(); 212 var part = parts.shift();
179 obj = obj[part]; 213 obj = obj[part];
180 } 214 }
181 215
182 if (propName == 'is_gatt_connected') { 216 if (propName == 'is_gatt_connected') {
183 obj = obj ? 'Connected' : 'Not Connected'; 217 obj = obj ? 'Connected' : 'Not Connected';
184 } 218 }
185 219
186 var cell = row.cells[i]; 220 var cell = row.cells[i];
187 cell.textContent = obj == null ? 'Unknown' : obj; 221 cell.textContent = obj == null ? 'Unknown' : obj;
188 cell.dataset.label = header.textContent; 222 cell.dataset.label = header.textContent;
189 } 223 }
190 }, 224 },
191 }; 225 };
192 226
193 return { 227 return {
194 DeviceTable: DeviceTable, 228 DeviceTable: DeviceTable,
195 }; 229 };
196 }); 230 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698