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

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

Issue 2576603002: bluetooth: Add device details page with basic properties to internals page. (Closed)
Patch Set: Add CSS for handling long device names 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 bluetooth_internals.html, served from 6 * Javascript for bluetooth_internals.html, served from
7 * chrome://bluetooth-internals/. 7 * chrome://bluetooth-internals/.
8 */ 8 */
9 9
10 // Expose for testing. 10 // Expose for testing.
11 /** @type {adapter_broker.AdapterBroker} */
11 var adapterBroker = null; 12 var adapterBroker = null;
13 /** @type {device_collection.DeviceCollection} */
12 var devices = null; 14 var devices = null;
15 /** @type {sidebar.Sidebar} */
13 var sidebarObj = null; 16 var sidebarObj = null;
14 17
15 cr.define('bluetooth_internals', function() { 18 cr.define('bluetooth_internals', function() {
16 /** @const */ var AdapterPage = adapter_page.AdapterPage; 19 /** @const */ var AdapterPage = adapter_page.AdapterPage;
20 /** @const */ var DeviceDetailsPage = device_details_page.DeviceDetailsPage;
17 /** @const */ var DevicesPage = devices_page.DevicesPage; 21 /** @const */ var DevicesPage = devices_page.DevicesPage;
18 /** @const */ var PageManager = cr.ui.pageManager.PageManager; 22 /** @const */ var PageManager = cr.ui.pageManager.PageManager;
19 /** @const */ var Snackbar = snackbar.Snackbar; 23 /** @const */ var Snackbar = snackbar.Snackbar;
20 /** @const */ var SnackbarType = snackbar.SnackbarType; 24 /** @const */ var SnackbarType = snackbar.SnackbarType;
21 25
26 devices = new device_collection.DeviceCollection([]);
27
28 /** @type {adapter_page.AdapterPage} */
29 var adapterPage = null;
30 /** @type {devices_page.DevicesPage} */
31 var devicesPage = null;
32
33 /** @type {interfaces.BluetoothAdapter.DiscoverySession.ptrClass} */
34 var discoverySession = null;
35
36 /** @type {boolean} */
37 var userRequestedScanStop = false;
38
22 /** 39 /**
23 * Observer for page changes. Used to update page title header. 40 * Observer for page changes. Used to update page title header.
24 * @extends {cr.ui.pageManager.PageManager.Observer} 41 * @extends {cr.ui.pageManager.PageManager.Observer}
25 */ 42 */
26 var PageObserver = function() {}; 43 var PageObserver = function() {};
27 44
28 PageObserver.prototype = { 45 PageObserver.prototype = {
29 __proto__: PageManager.Observer.prototype, 46 __proto__: PageManager.Observer.prototype,
30 47
31 updateHistory: function(path) { 48 updateHistory: function(path) {
32 window.location.hash = '#' + path; 49 window.location.hash = '#' + path;
33 }, 50 },
34 51
35 /** 52 /**
36 * Sets the page title. Called by PageManager. 53 * Sets the page title. Called by PageManager.
37 * @override 54 * @override
38 * @param {string} title 55 * @param {string} title
39 */ 56 */
40 updateTitle: function(title) { 57 updateTitle: function(title) {
41 document.querySelector('.page-title').textContent = title; 58 document.querySelector('.page-title').textContent = title;
42 }, 59 },
43 }; 60 };
44 61
45 /** @type {!Map<string, !interfaces.BluetoothDevice.DevicePtr>} */ 62 /**
46 var deviceAddressToProxy = new Map(); 63 * Removes DeviceDetailsPage with matching device |address|. The associated
64 * sidebar item is also removed.
65 * @param {string} address
66 */
67 function removeDeviceDetailsPage(address) {
68 var id = 'devices/' + address.toLowerCase();
69 sidebarObj.removeItem(id);
47 70
48 /** @type {!device_collection.DeviceCollection} */ 71 var deviceDetailsPage = PageManager.registeredPages[id];
49 devices = new device_collection.DeviceCollection([]); 72 assert(deviceDetailsPage, 'Device Details page must exist');
50 73
51 /** @type {adapter_page.AdapterPage} */ 74 deviceDetailsPage.disconnect();
52 var adapterPage = null; 75 deviceDetailsPage.pageDiv.parentNode.removeChild(deviceDetailsPage.pageDiv);
53 /** @type {devices_page.DevicesPage} */ 76 deviceDetailsPage.deviceInfo.inspecting = false;
54 var devicesPage = null; 77 devices.addOrUpdate(deviceDetailsPage.deviceInfo);
scheib 2017/01/11 02:16:14 comment why the addOrUpdate here and below, or ren
mbrunson 2017/01/11 21:22:59 Now that I'm looking at this again, this is a bad
78 PageManager.unregister(deviceDetailsPage);
79 }
55 80
56 /** @type {interfaces.BluetoothAdapter.DiscoverySession.ptrClass} */ 81 /**
57 var discoverySession = null; 82 * Creates a DeviceDetailsPage with the given |deviceInfo|, appends it to
83 * '#page-container', and adds a sidebar item to show the new page. If a
84 * page exists that matches |deviceInfo.address|, nothing is created and the
85 * existing page is returned.
86 * @param {!interfaces.BluetoothDevice.Device} deviceInfo
87 * @return {!device_details_page.DeviceDetailsPage}
88 */
89 function makeDeviceDetailsPage(deviceInfo) {
90 var deviceDetailsPageId = 'devices/' + deviceInfo.address.toLowerCase();
91 var deviceDetailsPage = PageManager.registeredPages[deviceDetailsPageId];
92 if (deviceDetailsPage) return deviceDetailsPage;
58 93
59 /** @type {boolean} */ 94 var pageSection = document.createElement('section');
60 var userRequestedScanStop = false; 95 pageSection.hidden = true;
96 pageSection.id = deviceDetailsPageId;
97 $('page-container').appendChild(pageSection);
61 98
62 function handleInspect(event) { 99 deviceDetailsPage = new DeviceDetailsPage(deviceDetailsPageId, deviceInfo);
63 // TODO(crbug.com/663470): Move connection logic to DeviceDetailsView 100 deviceDetailsPage.pageDiv.addEventListener('connectionchanged',
64 // when it's added in chrome://bluetooth-internals. 101 function(event) {
65 var address = event.detail.address; 102 devices.updateConnectionStatus(
66 var proxy = deviceAddressToProxy.get(address); 103 event.detail.address, event.detail.status);
104 });
67 105
68 if (proxy) { 106 deviceDetailsPage.pageDiv.addEventListener('infochanged', function(event) {
69 // Device is already connected, so disconnect. 107 devices.addOrUpdate(event.detail.info);
70 proxy.disconnect(); 108 });
71 deviceAddressToProxy.delete(address);
72 devices.updateConnectionStatus(
73 address, device_collection.ConnectionStatus.DISCONNECTED);
74 return;
75 }
76 109
77 devices.updateConnectionStatus( 110 deviceDetailsPage.pageDiv.addEventListener('forgetpressed',
78 address, device_collection.ConnectionStatus.CONNECTING); 111 function(event) {
112 PageManager.showPageByName(devicesPage.name);
113 removeDeviceDetailsPage(event.detail.address);
114 });
79 115
80 adapterBroker.connectToDevice(address).then(function(deviceProxy) { 116 deviceInfo.inspecting = true;
81 var deviceInfo = devices.getByAddress(address); 117 devices.addOrUpdate(deviceInfo);
82 if (!deviceInfo) { 118 PageManager.register(deviceDetailsPage);
83 // Device no longer in list, so drop the connection.
84 deviceProxy.disconnect();
85 return;
86 }
87 119
88 deviceAddressToProxy.set(address, deviceProxy); 120 sidebarObj.addItem({
89 devices.updateConnectionStatus( 121 pageName: deviceDetailsPageId,
90 address, device_collection.ConnectionStatus.CONNECTED); 122 text: deviceInfo.name_for_display,
91 Snackbar.show(deviceInfo.name_for_display + ': Connected', 123 });
92 SnackbarType.SUCCESS);
93 124
94 // Fetch services asynchronously. 125 deviceDetailsPage.connect();
95 return deviceProxy.getServices(); 126 return deviceDetailsPage;
96 }).then(function(response) { 127 }
97 if (!response) return;
98 128
99 var deviceInfo = devices.getByAddress(address); 129 /**
100 deviceInfo.services = response.services; 130 * Updates the DeviceDetailsPage with the matching device |address| and
101 devices.addOrUpdate(deviceInfo); 131 * redraws it.
102 }).catch(function(error) { 132 * @param {string} address
103 // If a connection error occurs while fetching the services, the proxy 133 */
104 // reference must be removed. 134 function updateDeviceDetailsPage(address) {
105 var proxy = deviceAddressToProxy.get(address); 135 var detailPageId = 'devices/' + address.toLowerCase();
106 if (proxy) { 136 var page = PageManager.registeredPages[detailPageId];
107 proxy.disconnect(); 137 if (page) page.redraw();
108 deviceAddressToProxy.delete(address);
109 }
110
111 devices.updateConnectionStatus(
112 address, device_collection.ConnectionStatus.DISCONNECTED);
113
114 var deviceInfo = devices.getByAddress(address);
115 Snackbar.show(deviceInfo.name_for_display + ': ' + error.message,
116 SnackbarType.ERROR, 'Retry', function() { handleInspect(event); });
117 });
118 } 138 }
119 139
120 function updateStoppedDiscoverySession() { 140 function updateStoppedDiscoverySession() {
121 devicesPage.setScanStatus(devices_page.ScanStatus.OFF); 141 devicesPage.setScanStatus(devices_page.ScanStatus.OFF);
122 discoverySession.ptr.reset(); 142 discoverySession.ptr.reset();
123 discoverySession = null; 143 discoverySession = null;
124 } 144 }
125 145
126 function setupAdapterSystem(response) { 146 function setupAdapterSystem(response) {
127 adapterBroker.addEventListener('adapterchanged', function(event) { 147 adapterBroker.addEventListener('adapterchanged', function(event) {
(...skipping 15 matching lines...) Expand all
143 adapterBroker.getInfo().then(function(response) { 163 adapterBroker.getInfo().then(function(response) {
144 adapterPage.setAdapterInfo(response.info); 164 adapterPage.setAdapterInfo(response.info);
145 }); 165 });
146 }); 166 });
147 } 167 }
148 168
149 function setupDeviceSystem(response) { 169 function setupDeviceSystem(response) {
150 // Hook up device collection events. 170 // Hook up device collection events.
151 adapterBroker.addEventListener('deviceadded', function(event) { 171 adapterBroker.addEventListener('deviceadded', function(event) {
152 devices.addOrUpdate(event.detail.deviceInfo); 172 devices.addOrUpdate(event.detail.deviceInfo);
173 updateDeviceDetailsPage(event.detail.deviceInfo.address);
153 }); 174 });
154 adapterBroker.addEventListener('devicechanged', function(event) { 175 adapterBroker.addEventListener('devicechanged', function(event) {
155 devices.addOrUpdate(event.detail.deviceInfo); 176 devices.addOrUpdate(event.detail.deviceInfo);
177 updateDeviceDetailsPage(event.detail.deviceInfo.address);
156 }); 178 });
157 adapterBroker.addEventListener('deviceremoved', function(event) { 179 adapterBroker.addEventListener('deviceremoved', function(event) {
158 devices.remove(event.detail.deviceInfo); 180 devices.remove(event.detail.deviceInfo);
181 updateDeviceDetailsPage(event.detail.deviceInfo.address);
159 }); 182 });
160 183
161 response.devices.forEach(devices.addOrUpdate, devices /* this */); 184 response.devices.forEach(devices.addOrUpdate, devices /* this */);
162 185
163 devicesPage.setDevices(devices); 186 devicesPage.setDevices(devices);
164 devicesPage.pageDiv.addEventListener('inspectpressed', handleInspect); 187
188 devicesPage.pageDiv.addEventListener('inspectpressed', function(event) {
189 var detailsPage = makeDeviceDetailsPage(
190 devices.getByAddress(event.detail.address));
191 PageManager.showPageByName(detailsPage.name);
192 });
193
194 devicesPage.pageDiv.addEventListener('forgetpressed', function(event) {
195 PageManager.showPageByName(devicesPage.name);
196 removeDeviceDetailsPage(event.detail.address);
197 });
165 198
166 devicesPage.pageDiv.addEventListener('scanpressed', function(event) { 199 devicesPage.pageDiv.addEventListener('scanpressed', function(event) {
167 if (discoverySession && discoverySession.ptr.isBound()) { 200 if (discoverySession && discoverySession.ptr.isBound()) {
168 userRequestedScanStop = true; 201 userRequestedScanStop = true;
169 devicesPage.setScanStatus(devices_page.ScanStatus.STOPPING); 202 devicesPage.setScanStatus(devices_page.ScanStatus.STOPPING);
170 203
171 discoverySession.stop().then(function(response) { 204 discoverySession.stop().then(function(response) {
172 if (response.success) { 205 if (response.success) {
173 updateStoppedDiscoverySession(); 206 updateStoppedDiscoverySession();
174 userRequestedScanStop = false; 207 userRequestedScanStop = false;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
208 PageManager.addObserver(sidebarObj); 241 PageManager.addObserver(sidebarObj);
209 PageManager.addObserver(new PageObserver()); 242 PageManager.addObserver(new PageObserver());
210 243
211 devicesPage = new DevicesPage(); 244 devicesPage = new DevicesPage();
212 PageManager.register(devicesPage); 245 PageManager.register(devicesPage);
213 adapterPage = new AdapterPage(); 246 adapterPage = new AdapterPage();
214 PageManager.register(adapterPage); 247 PageManager.register(adapterPage);
215 248
216 // Set up hash-based navigation. 249 // Set up hash-based navigation.
217 window.addEventListener('hashchange', function() { 250 window.addEventListener('hashchange', function() {
218 PageManager.showPageByName(window.location.hash.substr(1)); 251 // If a user navigates and the page doesn't exist, do nothing.
252 var pageName = window.location.hash.substr(1);
253 if ($(pageName))
254 PageManager.showPageByName(pageName);
219 }); 255 });
220 256
221 if (!window.location.hash) { 257 if (!window.location.hash) {
222 PageManager.showPageByName(adapterPage.name); 258 PageManager.showPageByName(adapterPage.name);
223 return; 259 return;
224 } 260 }
225 261
226 PageManager.showPageByName(window.location.hash.substr(1)); 262 // Only the root pages are available on page load.
263 PageManager.showPageByName(window.location.hash.split('/')[0].substr(1));
227 } 264 }
228 265
229 function initializeViews() { 266 function initializeViews() {
230 setupPages(); 267 setupPages();
231 268
232 adapter_broker.getAdapterBroker() 269 adapter_broker.getAdapterBroker()
233 .then(function(broker) { adapterBroker = broker; }) 270 .then(function(broker) { adapterBroker = broker; })
234 .then(function() { return adapterBroker.getInfo(); }) 271 .then(function() { return adapterBroker.getInfo(); })
235 .then(setupAdapterSystem) 272 .then(setupAdapterSystem)
236 .then(function() { return adapterBroker.getDevices(); }) 273 .then(function() { return adapterBroker.getDevices(); })
237 .then(setupDeviceSystem) 274 .then(setupDeviceSystem)
238 .catch(function(error) { 275 .catch(function(error) {
239 Snackbar.show(error.message, SnackbarType.ERROR); 276 Snackbar.show(error.message, SnackbarType.ERROR);
240 console.error(error); 277 console.error(error);
241 }); 278 });
242 } 279 }
243 280
244 return { 281 return {
245 initializeViews: initializeViews 282 initializeViews: initializeViews,
246 }; 283 };
247 }); 284 });
248 285
249 document.addEventListener( 286 document.addEventListener(
250 'DOMContentLoaded', bluetooth_internals.initializeViews); 287 'DOMContentLoaded', bluetooth_internals.initializeViews);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698