OLD | NEW |
---|---|
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 (function() { | 10 (function() { |
11 var adapter, adapterClient, bluetoothAdapter, bluetoothDevice, connection; | 11 var adapter, adapterClient, bluetoothAdapter, bluetoothDevice, connection; |
12 | 12 |
13 // Dictionary for address->Device cache. | 13 // Dictionary for address->Device cache. |
14 var devices = {}; | 14 var devices = {}; |
15 | 15 |
16 // Data model for a cached device. | 16 // Data model for a cached device. |
17 function Device() {}; | 17 function Device() {}; |
18 Device.prototype = { info: null }; | 18 Device.prototype = { info: null }; |
19 | 19 |
20 /** | 20 /** |
21 * The implementation of AdapterClient in | 21 * The implementation of AdapterClient in |
22 * device/bluetooth/public/interfaces/adapter.mojom. | 22 * device/bluetooth/public/interfaces/adapter.mojom. |
23 */ | 23 */ |
24 var AdapterClient = function() {}; | 24 var AdapterClient = function() {}; |
25 AdapterClient.prototype = { | 25 AdapterClient.prototype = { |
26 /** | 26 /** |
27 * Logs added device to console and caches the device info. | 27 * Caches the device info and updates the device list. |
28 * @param {!bluetoothDevice.DeviceInfo} device | 28 * @param {!bluetoothDevice.DeviceInfo} deviceInfo |
29 */ | 29 */ |
30 deviceAdded: function(deviceInfo) { | 30 deviceAdded: function(deviceInfo) { |
31 console.log('Device added', deviceInfo); | 31 addDevice(deviceInfo); |
32 devices[deviceInfo.address] = new Device(); | |
33 devices[deviceInfo.address].info = deviceInfo; | |
34 }, | 32 }, |
35 | 33 |
36 /** | 34 /** |
37 * Logs removed device to console and removes the cached device. | 35 * Removes the cached device and updates the device list. |
38 * @param {!bluetoothDevice.DeviceInfo} device | 36 * @param {!bluetoothDevice.DeviceInfo} deviceInfo |
39 */ | 37 */ |
40 deviceRemoved: function(deviceInfo) { | 38 deviceRemoved: function(deviceInfo) { |
41 console.log('Device removed', deviceInfo); | 39 removeDevice(deviceInfo); |
42 delete devices[deviceInfo.address]; | |
43 }, | 40 }, |
44 | 41 |
45 /** | 42 /** |
46 * Logs changed device info to console and updates the cached device. | 43 * Caches the last valid RSSI and refreshes the device list. |
47 * @param {!bluetoothDevice.DeviceInfo} deviceInfo | 44 * @param {!bluetoothDevice.DeviceInfo} deviceInfo |
48 */ | 45 */ |
49 deviceChanged: function(deviceInfo) { | 46 deviceChanged: function(deviceInfo) { |
50 console.log(new Date(), deviceInfo); | 47 updateDevice(deviceInfo); |
51 devices[deviceInfo.address].info = deviceInfo; | |
52 } | 48 } |
53 }; | 49 }; |
54 | 50 |
55 /** | 51 /** |
56 * TODO(crbug.com/652361): Move to shared location. | 52 * TODO(crbug.com/652361): Move to shared location. |
57 * Helper to convert callback-based define() API to a promise-based API. | 53 * Helper to convert callback-based define() API to a promise-based API. |
58 * @param {!Array<string>} moduleNames | 54 * @param {!Array<string>} moduleNames |
59 * @return {!Promise} | 55 * @return {!Promise} |
60 */ | 56 */ |
61 function importModules(moduleNames) { | 57 function importModules(moduleNames) { |
62 return new Promise(function(resolve, reject) { | 58 return new Promise(function(resolve, reject) { |
63 define(moduleNames, function(var_args) { | 59 define(moduleNames, function(var_args) { |
64 resolve(Array.prototype.slice.call(arguments, 0)); | 60 resolve(Array.prototype.slice.call(arguments, 0)); |
65 }); | 61 }); |
66 }); | 62 }); |
67 } | 63 } |
68 | 64 |
69 /** | 65 /** |
70 * Initializes Mojo proxies for page and Bluetooth services. | 66 * Initializes Mojo proxies for page and Bluetooth services. |
71 * @return {!Promise} resolves if adapter is acquired, rejects if Bluetooth | 67 * @return {!Promise} resolves if adapter is acquired, rejects if Bluetooth |
72 * is not supported. | 68 * is not supported. |
73 */ | 69 */ |
74 function initializeProxies() { | 70 function initializeProxies() { |
75 return importModules([ | 71 return importModules([ |
76 'content/public/renderer/frame_interfaces', | 72 'content/public/renderer/frame_interfaces', |
77 'device/bluetooth/public/interfaces/adapter.mojom', | 73 'device/bluetooth/public/interfaces/adapter.mojom', |
78 'device/bluetooth/public/interfaces/device.mojom', | 74 'device/bluetooth/public/interfaces/device.mojom', |
79 'mojo/public/js/connection', | 75 'mojo/public/js/connection', |
80 ]).then(function([frameInterfaces, ...modules]) { | 76 ]).then(function([frameInterfaces, ...modules]) { |
81 console.log('Loaded modules'); | |
82 | |
83 // Destructure here to assign global variables. | 77 // Destructure here to assign global variables. |
84 [bluetoothAdapter, bluetoothDevice, connection] = modules; | 78 [bluetoothAdapter, bluetoothDevice, connection] = modules; |
85 | 79 |
86 // Hook up the instance properties. | 80 // Hook up the instance properties. |
87 AdapterClient.prototype.__proto__ = | 81 AdapterClient.prototype.__proto__ = |
88 bluetoothAdapter.AdapterClient.stubClass.prototype; | 82 bluetoothAdapter.AdapterClient.stubClass.prototype; |
89 | 83 |
90 var adapterFactory = connection.bindHandleToProxy( | 84 var adapterFactory = connection.bindHandleToProxy( |
91 frameInterfaces.getInterface(bluetoothAdapter.AdapterFactory.name), | 85 frameInterfaces.getInterface(bluetoothAdapter.AdapterFactory.name), |
92 bluetoothAdapter.AdapterFactory); | 86 bluetoothAdapter.AdapterFactory); |
93 | 87 |
94 // Get an Adapter service. | 88 // Get an Adapter service. |
95 return adapterFactory.getAdapter(); | 89 return adapterFactory.getAdapter(); |
96 }).then(function(response) { | 90 }).then(function(response) { |
97 if (!response.adapter) { | 91 if (!response.adapter) { |
98 throw new Error('Bluetooth Not Supported on this platform.'); | 92 throw new Error('Bluetooth Not Supported on this platform.'); |
99 } | 93 } |
100 | 94 |
101 adapter = connection.bindHandleToProxy(response.adapter, | 95 adapter = connection.bindHandleToProxy(response.adapter, |
102 bluetoothAdapter.Adapter); | 96 bluetoothAdapter.Adapter); |
103 | 97 |
104 // Create a message pipe and bind one end to client | 98 // Create a message pipe and bind one end to client |
105 // implementation and the other to the Adapter service. | 99 // implementation and the other to the Adapter service. |
106 adapterClient = new AdapterClient(); | 100 adapterClient = new AdapterClient(); |
107 adapter.setClient(connection.bindStubDerivedImpl(adapterClient)); | 101 adapter.setClient(connection.bindStubDerivedImpl(adapterClient)); |
108 }); | 102 }); |
109 } | 103 } |
110 | 104 |
105 /** | |
106 * Adds a device to the device list and caches the values in the device | |
107 * dictionary. | |
108 * @param {!bluetoothDevice.DeviceInfo} deviceInfo | |
109 */ | |
110 function addDevice(deviceInfo) { | |
111 devices[deviceInfo.address] = new Device(); | |
112 devices[deviceInfo.address].info = deviceInfo; | |
113 | |
114 var deviceRowTemplate = $('device-row-template'); | |
115 var deviceList = $('device-list'); | |
ortuno
2016/10/21 00:56:36
nit: Move this down to where it's used.
mbrunson
2016/10/21 02:09:34
Done.
| |
116 | |
117 var deviceRow = deviceRowTemplate.content.children[0].cloneNode(true); | |
ortuno
2016/10/21 00:56:36
nit: cloneNode(true /* deep */);
mbrunson
2016/10/21 02:09:33
Done.
| |
118 deviceRow.id = deviceInfo.address; | |
119 deviceList.appendChild(deviceRow); | |
120 | |
121 updateDevice(deviceInfo); | |
122 } | |
123 | |
124 /** | |
125 * Removes a device from the device list and device dictionary with the | |
126 * matching address in the given |deviceInfo|. | |
127 * @param {!bluetoothDevice.DeviceInfo} deviceInfo | |
128 */ | |
129 function removeDevice(deviceInfo) { | |
130 delete devices[deviceInfo.address]; | |
131 var deviceElement = $(deviceInfo.address); | |
132 | |
133 if (deviceElement) { | |
134 var deviceList = $('device-list'); | |
135 deviceList.removeChild(deviceElement); | |
ortuno
2016/10/21 00:56:36
I don't think we want to completely remove element
mbrunson
2016/10/21 02:09:33
Done.
| |
136 } | |
137 } | |
138 | |
139 /** | |
140 * Updates a device in the device list and device dictionary with the given | |
141 * |deviceInfo|. | |
142 * @param {!bluetoothDevice.DeviceInfo} deviceInfo | |
143 */ | |
144 function updateDevice(deviceInfo) { | |
145 var deviceRow = $(deviceInfo.address); | |
146 if (deviceRow) { | |
ortuno
2016/10/21 00:56:36
When would you receive a DeviceChanged for a devic
mbrunson
2016/10/21 02:09:33
Isn't the order of messages in Mojo not guaranteed
ortuno
2016/10/21 02:16:55
The order is not guaranteed between pipes e.g. the
mbrunson
2016/10/21 18:16:28
Ah ok. I'll just throw an exception here for that.
| |
147 deviceRow.querySelector('.device-name').innerText = | |
148 deviceInfo.name_for_display; | |
149 deviceRow.querySelector('.device-address').innerText = deviceInfo.address; | |
150 | |
151 var rssi = (deviceInfo.rssi && deviceInfo.rssi.value) || | |
152 deviceRow.querySelector('.device-rssi').innerText; | |
153 deviceRow.querySelector('.device-rssi').innerText = rssi; | |
154 } | |
155 } | |
156 | |
111 document.addEventListener('DOMContentLoaded', function() { | 157 document.addEventListener('DOMContentLoaded', function() { |
112 initializeProxies() | 158 initializeProxies() |
113 .then(function() { return adapter.getInfo(); }) | 159 .then(function() { return adapter.getInfo(); }) |
114 .then(function(response) { console.log('adapter', response.info); }) | 160 .then(function(response) { console.log('adapter', response.info); }) |
115 .then(function() { return adapter.getDevices(); }) | 161 .then(function() { return adapter.getDevices(); }) |
116 .then(function(response) { | 162 .then(function(response) { response.devices.forEach(addDevice); }) |
117 console.log('devices', response.devices.length); | |
118 | |
119 response.devices.forEach(function(deviceInfo) { | |
120 devices[deviceInfo.address] = new Device(); | |
121 devices[deviceInfo.address].info = deviceInfo; | |
122 console.log(deviceInfo.name_for_display, deviceInfo); | |
123 }); | |
124 }) | |
125 .catch(function(error) { console.error(error); }); | 163 .catch(function(error) { console.error(error); }); |
126 }); | 164 }); |
127 })(); | 165 })(); |
OLD | NEW |