Chromium Code Reviews| Index: chrome/browser/resources/bluetooth_internals/bluetooth_internals.js | 
| diff --git a/chrome/browser/resources/bluetooth_internals/bluetooth_internals.js b/chrome/browser/resources/bluetooth_internals/bluetooth_internals.js | 
| index 93a73935c52d3cabcc24309e489e4b00cc7de649..270f6e7fc2bc534a139e7408c56389070ecfa9cb 100644 | 
| --- a/chrome/browser/resources/bluetooth_internals/bluetooth_internals.js | 
| +++ b/chrome/browser/resources/bluetooth_internals/bluetooth_internals.js | 
| @@ -7,128 +7,138 @@ | 
| * chrome://bluetooth-internals/. | 
| */ | 
| -(function() { | 
| - var adapter, adapterClient, bluetoothAdapter, bluetoothDevice, connection; | 
| - | 
| - var REMOVED_CSS = 'removed'; | 
| - | 
| - /* | 
| - * Data model for a cached device. | 
| - * @constructor | 
| - * @param {!bluetoothDevice.DeviceInfo} info | 
| - */ | 
| - var Device = function(info) { this.info = info; }; | 
| - | 
| +cr.define('bluetooth_internals', function() { | 
| /** | 
| * The implementation of AdapterClient in | 
| * device/bluetooth/public/interfaces/adapter.mojom. This also manages the | 
| * client-side collection of devices. | 
| * @constructor | 
| + * @param {!AdapterBroker} adapterBroker Broker to dispatch events through. | 
| */ | 
| - var AdapterClient = function() { this.devices_ = new Map(); }; | 
| + var AdapterClient = function(adapterBroker) { | 
| + this.adapterBroker_ = adapterBroker; | 
| + }; | 
| + | 
| AdapterClient.prototype = { | 
| /** | 
| - * Caches the device info and updates the device list. | 
| - * @param {!bluetoothDevice.DeviceInfo} deviceInfo | 
| + * Fires deviceadded event. | 
| + * @param {!interfaces.BluetoothDevice.DeviceInfo} deviceInfo | 
| */ | 
| deviceAdded: function(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); | 
| + var event = new Event('deviceadded'); | 
| + event.deviceInfo = deviceInfo; | 
| + this.adapterBroker_.dispatchEvent(event); | 
| }, | 
| /** | 
| - * Marks device as removed. | 
| - * @param {!bluetoothDevice.DeviceInfo} deviceInfo | 
| + * Fires deviceremoved event. | 
| + * @param {!interfaces.BluetoothDevice.DeviceInfo} deviceInfo | 
| */ | 
| deviceRemoved: function(deviceInfo) { | 
| - $(deviceInfo.address).classList.add(REMOVED_CSS); | 
| + var event = new Event('deviceremoved'); | 
| + event.deviceInfo = deviceInfo; | 
| + this.adapterBroker_.dispatchEvent(event); | 
| }, | 
| /** | 
| - * Updates cached device and updates the device list. | 
| - * @param {!bluetoothDevice.DeviceInfo} deviceInfo | 
| + * Fires devicechanged event. | 
| + * @param {!interfaces.BluetoothDevice.DeviceInfo} deviceInfo | 
| */ | 
| deviceChanged: function(deviceInfo) { | 
| console.log(new Date(), deviceInfo); | 
| - assert(this.devices_.has(deviceInfo.address), 'Device does not exist.'); | 
| + var event = new Event('devicechanged'); | 
| + event.deviceInfo = deviceInfo; | 
| + this.adapterBroker_.dispatchEvent(event); | 
| + } | 
| + }; | 
| - this.devices_.get(deviceInfo.address).info = deviceInfo; | 
| + /** | 
| + * The proxy class of an adapter and router of adapter events. | 
| + * Exposes an EventTarget interface that allows other object to subscribe to | 
| + * to specific AdapterClient events. | 
| + * Provides proxy access to Adapter functions. Converts parameters to Mojo | 
| + * handles and back when necessary. | 
| + * @constructor | 
| + * @extends {cr.EventTarget} | 
| + * @param {!interfaces.BluetoothAdapter.Adapter.proxyClass} adapter | 
| + */ | 
| + var AdapterBroker = function(adapter) { | 
| + this.adapter_ = adapter; | 
| + this.adapterClient_ = new AdapterClient(this); | 
| + this.setClient(this.adapterClient_); | 
| + }; | 
| - var deviceRow = $(deviceInfo.address); | 
| - deviceRow.querySelector('.device-name').textContent = | 
| - deviceInfo.name_for_display; | 
| - deviceRow.querySelector('.device-address').textContent = | 
| - deviceInfo.address; | 
| + AdapterBroker.prototype = { | 
| + __proto__: cr.EventTarget.prototype, | 
| + | 
| + /** | 
| + * Sets client of Adapter service. | 
| + * @param {interfaces.BluetoothAdapter.AdapterClient} adapterClient | 
| + */ | 
| + setClient: function(adapterClient) { | 
| + this.adapter_.setClient(interfaces.Connection.bindStubDerivedImpl( | 
| + adapterClient)); | 
| + }, | 
| - var rssi = (deviceInfo.rssi && deviceInfo.rssi.value) || | 
| - deviceRow.querySelector('.device-rssi').textContent; | 
| - deviceRow.querySelector('.device-rssi').textContent = rssi; | 
| + /** | 
| + * Gets an array of currently detectable devices from the Adapter service. | 
| + * @return {Array<interfaces.BluetoothDevice.DeviceInfo>} | 
| + */ | 
| + getDevices: function() { | 
| + return this.adapter_.getDevices(); | 
| + }, | 
| + | 
| + /** | 
| + * Gets the current state of the Adapter. | 
| + * @return {interfaces.BluetoothAdapter.AdapterInfo} | 
| + */ | 
| + getInfo: function() { | 
| + return this.adapter_.getInfo(); | 
| } | 
| }; | 
| - /** | 
| - * Initializes Mojo proxies for page and Bluetooth services. | 
| - * @return {!Promise} resolves if adapter is acquired, rejects if Bluetooth | 
| - * is not supported. | 
| - */ | 
| - function initializeProxies() { | 
| - return importModules([ | 
| - 'content/public/renderer/frame_interfaces', | 
| - 'device/bluetooth/public/interfaces/adapter.mojom', | 
| - 'device/bluetooth/public/interfaces/device.mojom', | 
| - 'mojo/public/js/connection', | 
| - ]).then(function([frameInterfaces, ...modules]) { | 
| - // Destructure here to assign global variables. | 
| - [bluetoothAdapter, bluetoothDevice, connection] = modules; | 
| - | 
| - // Hook up the instance properties. | 
| - AdapterClient.prototype.__proto__ = | 
| - bluetoothAdapter.AdapterClient.stubClass.prototype; | 
| - | 
| - var adapterFactory = connection.bindHandleToProxy( | 
| - frameInterfaces.getInterface(bluetoothAdapter.AdapterFactory.name), | 
| - bluetoothAdapter.AdapterFactory); | 
| - | 
| - // Get an Adapter service. | 
| - return adapterFactory.getAdapter(); | 
| - }).then(function(response) { | 
| - if (!response.adapter) { | 
| - throw new Error('Bluetooth Not Supported on this platform.'); | 
| - } | 
| - | 
| - adapter = connection.bindHandleToProxy(response.adapter, | 
| - bluetoothAdapter.Adapter); | 
| - | 
| - // Create a message pipe and bind one end to client | 
| - // implementation and the other to the Adapter service. | 
| - adapterClient = new AdapterClient(); | 
| - adapter.setClient(connection.bindStubDerivedImpl(adapterClient)); | 
| - }); | 
| - } | 
| + var adapterBroker = null; | 
| + | 
| + function initialize() { | 
| + interfaces.initialize() | 
| + .then(function(adapter) { | 
| + // Hook up the instance properties. | 
| + AdapterClient.prototype.__proto__ = | 
| + interfaces.BluetoothAdapter.AdapterClient.stubClass.prototype; | 
| - document.addEventListener('DOMContentLoaded', function() { | 
| - initializeProxies() | 
| - .then(function() { return adapter.getInfo(); }) | 
| + adapterBroker = new AdapterBroker(adapter); | 
| 
 
ortuno
2016/11/03 04:58:21
Would it make sense to:
1. Put AdapterBroker in i
 
mbrunson
2016/11/03 18:07:28
I can do 1 and 2 relatively easily.
Not sure abou
 
 | 
| + }) | 
| + .then(function() { return adapterBroker.getInfo(); }) | 
| .then(function(response) { console.log('adapter', response.info); }) | 
| - .then(function() { return adapter.getDevices(); }) | 
| + .then(function() { return adapterBroker.getDevices(); }) | 
| .then(function(response) { | 
| - response.devices.forEach(adapterClient.deviceAdded, adapterClient); | 
| + // Hook up device collection events. | 
| + var devices = new device_collection.DeviceCollection([]); | 
| + adapterBroker.addEventListener('deviceadded', function(event) { | 
| + devices.addOrUpdate(event.deviceInfo); | 
| + }); | 
| + adapterBroker.addEventListener('devicechanged', function(event) { | 
| + devices.addOrUpdate(event.deviceInfo); | 
| + }); | 
| + adapterBroker.addEventListener('deviceremoved', function(event) { | 
| + devices.remove(event.deviceInfo); | 
| + }); | 
| + | 
| + response.devices.forEach(devices.addOrUpdate, | 
| + devices /** this */); | 
| 
 
ortuno
2016/11/03 04:58:21
nit: /** => /*
 
mbrunson
2016/11/03 18:07:28
Done.
 
 | 
| + | 
| + var deviceTable = new device_table.DeviceTable(); | 
| + deviceTable.setDevices(devices); | 
| + document.body.appendChild(deviceTable); | 
| }) | 
| .catch(function(error) { console.error(error); }); | 
| - }); | 
| -})(); | 
| + } | 
| + | 
| + return { | 
| + initialize: initialize | 
| + }; | 
| + | 
| +}); | 
| + | 
| +document.addEventListener('DOMContentLoaded', bluetooth_internals.initialize); |