blob: df04fc91b8f2c8aa473934b8fe0b153672a4c0cd [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* Javascript for AdapterBroker, served from
* chrome://bluetooth-internals/.
*/
cr.define('adapter_broker', function() {
/** @typedef {bluetooth.mojom.Adapter.ptrClass} */
var AdapterPtr;
/** @typedef {bluetooth.mojom.Device.ptrClass} */
var DevicePtr;
/** @typedef {bluetooth.mojom.DiscoverySession.ptrClass} */
var DiscoverySessionPtr;
/**
* Enum of adapter property names. Used for adapterchanged events.
* @enum {string}
*/
var AdapterProperty = {
DISCOVERABLE: 'discoverable',
DISCOVERING: 'discovering',
POWERED: 'powered',
PRESENT: 'present',
};
/**
* 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 {!AdapterPtr} adapter
*/
var AdapterBroker = function(adapter) {
this.adapter_ = adapter;
this.adapterClient_ = new AdapterClient(this);
this.setClient(this.adapterClient_);
};
AdapterBroker.prototype = {
__proto__: cr.EventTarget.prototype,
/**
* Creates a GATT connection to the device with |address|.
* @param {string} address
* @return {!Promise<!DevicePtr>}
*/
connectToDevice: function(address) {
return this.adapter_.connectToDevice(address).then(function(response) {
if (response.result != bluetooth.mojom.ConnectResult.SUCCESS) {
// TODO(crbug.com/663394): Replace with more descriptive error
// messages.
var ConnectResult = bluetooth.mojom.ConnectResult;
var errorString = Object.keys(ConnectResult).find(function(key) {
return ConnectResult[key] === response.result;
});
throw new Error(errorString);
}
return response.device;
});
},
/**
* Gets an array of currently detectable devices from the Adapter service.
* @return {!Array<!bluetooth.mojom.DeviceInfo>}
*/
getDevices: function() {
return this.adapter_.getDevices();
},
/**
* Gets the current state of the Adapter.
* @return {!bluetooth.mojom.AdapterInfo}
*/
getInfo: function() {
return this.adapter_.getInfo();
},
/**
* Sets client of Adapter service.
* @param {!bluetooth.mojom.AdapterClient} adapterClient
*/
setClient: function(adapterClient) {
adapterClient.binding =
new mojo.Binding(bluetooth.mojom.AdapterClient, adapterClient);
this.adapter_.setClient(
adapterClient.binding.createInterfacePtrAndBind());
},
/**
* Requests the adapter to start a new discovery session.
* @return {!Promise<!DiscoverySessionPtr>}
*/
startDiscoverySession: function() {
return this.adapter_.startDiscoverySession().then(function(response) {
if (!response.session.ptr.isBound()) {
throw new Error('Discovery session failed to start');
}
return response.session;
});
},
};
/**
* The implementation of AdapterClient in
* device/bluetooth/public/interfaces/adapter.mojom. Dispatches events
* through AdapterBroker to notify client objects of changes to the Adapter
* service.
* @constructor
* @param {!AdapterBroker} adapterBroker Broker to dispatch events through.
*/
var AdapterClient = function(adapterBroker) {
this.adapterBroker_ = adapterBroker;
};
AdapterClient.prototype = {
/**
* Fires adapterchanged event with "present" property.
* @param {boolean} present
*/
presentChanged: function(present) {
var event = new CustomEvent('adapterchanged', {
detail: {
property: AdapterProperty.PRESENT,
value: present,
}
});
this.adapterBroker_.dispatchEvent(event);
},
/**
* Fires adapterchanged event with "powered" property changed.
* @param {boolean} powered
*/
poweredChanged: function(powered) {
var event = new CustomEvent('adapterchanged', {
detail: {
property: AdapterProperty.POWERED,
value: powered,
}
});
this.adapterBroker_.dispatchEvent(event);
},
/**
* Fires adapterchanged event with "discoverable" property changed.
* @param {boolean} discoverable
*/
discoverableChanged: function(discoverable) {
var event = new CustomEvent('adapterchanged', {
detail: {
property: AdapterProperty.DISCOVERABLE,
value: discoverable,
}
});
this.adapterBroker_.dispatchEvent(event);
},
/**
* Fires adapterchanged event with "discovering" property changed.
* @param {boolean} discovering
*/
discoveringChanged: function(discovering) {
var event = new CustomEvent('adapterchanged', {
detail: {
property: AdapterProperty.DISCOVERING,
value: discovering,
}
});
this.adapterBroker_.dispatchEvent(event);
},
/**
* Fires deviceadded event.
* @param {!bluetooth.mojom.DeviceInfo} deviceInfo
*/
deviceAdded: function(deviceInfo) {
var event =
new CustomEvent('deviceadded', {detail: {deviceInfo: deviceInfo}});
this.adapterBroker_.dispatchEvent(event);
},
/**
* Fires devicechanged event.
* @param {!bluetooth.mojom.DeviceInfo} deviceInfo
*/
deviceChanged: function(deviceInfo) {
var event =
new CustomEvent('devicechanged', {detail: {deviceInfo: deviceInfo}});
this.adapterBroker_.dispatchEvent(event);
},
/**
* Fires deviceremoved event.
* @param {!bluetooth.mojom.DeviceInfo} deviceInfo
*/
deviceRemoved: function(deviceInfo) {
var event =
new CustomEvent('deviceremoved', {detail: {deviceInfo: deviceInfo}});
this.adapterBroker_.dispatchEvent(event);
},
};
var adapterBroker = null;
/**
* Initializes an AdapterBroker if one doesn't exist.
* @return {!Promise<!AdapterBroker>} resolves with AdapterBroker,
* rejects if Bluetooth is not supported.
*/
function getAdapterBroker() {
if (adapterBroker)
return Promise.resolve(adapterBroker);
var adapterFactory = new bluetooth.mojom.AdapterFactoryPtr;
Mojo.bindInterface(
bluetooth.mojom.AdapterFactory.name,
mojo.makeRequest(adapterFactory).handle);
// Get an Adapter service.
return adapterFactory.getAdapter().then(function(response) {
if (!response.adapter.ptr.isBound()) {
throw new Error('Bluetooth Not Supported on this platform.');
}
adapterBroker = new AdapterBroker(response.adapter);
return adapterBroker;
});
}
return {
AdapterProperty: AdapterProperty,
getAdapterBroker: getAdapterBroker,
};
});