1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // Custom binding for the Bluetooth API.
7 var binding = require('binding').Binding.create('bluetooth');
9 var chrome = requireNative('chrome').GetChrome();
10 var Event = require('event_bindings').Event;
11 var lastError = require('lastError');
12 var sendRequest = require('sendRequest').sendRequest;
14 // Use custom binding to create an undocumented event listener that will
15 // receive events about device discovery and call the event listener that was
16 // provided with the request to begin discovery.
17 binding.registerCustomHook(function(api) {
18 var apiFunctions = api.apiFunctions;
22 function callCallbackIfPresent(name, args, error) {
23 var callback = args[args.length - 1];
24 if (typeof(callback) == 'function')
25 lastError.run(name, error, callback);
28 bluetooth.deviceDiscoveredHandler = null;
29 bluetooth.onDeviceDiscovered = new Event('bluetooth.onDeviceDiscovered');
30 function clearDeviceDiscoveredHandler() {
31 bluetooth.onDeviceDiscovered.removeListener(
32 bluetooth.deviceDiscoveredHandler);
33 bluetooth.deviceDiscoveredHandler = null;
35 apiFunctions.setHandleRequest('startDiscovery',
38 if (args.length > 0 && args[0] && args[0].deviceCallback) {
39 if (bluetooth.deviceDiscoveredHandler != null) {
40 callCallbackIfPresent('bluetooth.startDiscovery',
42 'Concurrent discovery is not allowed.');
46 bluetooth.deviceDiscoveredHandler = args[0].deviceCallback;
47 bluetooth.onDeviceDiscovered.addListener(
48 bluetooth.deviceDiscoveredHandler);
49 sendRequest(this.name,
51 this.definition.parameters,
52 {customCallback:this.customCallback});
54 callCallbackIfPresent(
55 'bluetooth.startDiscovery',
57 'deviceCallback is required in the options object');
61 apiFunctions.setCustomCallback('startDiscovery',
62 function(name, request, response) {
63 if (chrome.runtime.lastError) {
64 clearDeviceDiscoveredHandler();
68 apiFunctions.setHandleRequest('stopDiscovery',
70 clearDeviceDiscoveredHandler();
71 sendRequest(this.name, arguments, this.definition.parameters);
74 // An object to hold state during one call to getDevices.
75 bluetooth.getDevicesState = null;
77 // Hidden events used to deliver getDevices data to the client callbacks
78 bluetooth.onDeviceSearchResult = new Event('bluetooth.onDeviceSearchResult');
79 bluetooth.onDeviceSearchFinished =
80 new Event('bluetooth.onDeviceSearchFinished');
82 function deviceSearchResultHandler(device) {
83 bluetooth.getDevicesState.actualEvents++;
84 bluetooth.getDevicesState.deviceCallback(device);
85 maybeFinishDeviceSearch();
88 function deviceSearchFinishedHandler(info) {
89 bluetooth.getDevicesState.expectedEventCount = info.expectedEventCount;
90 maybeFinishDeviceSearch();
93 function addDeviceSearchListeners() {
94 bluetooth.onDeviceSearchResult.addListener(deviceSearchResultHandler);
95 bluetooth.onDeviceSearchFinished.addListener(deviceSearchFinishedHandler);
98 function removeDeviceSearchListeners() {
99 bluetooth.onDeviceSearchResult.removeListener(deviceSearchResultHandler);
100 bluetooth.onDeviceSearchFinished.removeListener(
101 deviceSearchFinishedHandler);
104 function maybeFinishDeviceSearch() {
105 var state = bluetooth.getDevicesState;
106 if (typeof(state.expectedEventCount) != 'undefined' &&
107 state.actualEvents >= state.expectedEventCount) {
108 finishDeviceSearch();
112 function finishDeviceSearch() {
113 var finalCallback = bluetooth.getDevicesState.finalCallback;
114 removeDeviceSearchListeners();
115 bluetooth.getDevicesState = null;
122 apiFunctions.setUpdateArgumentsPostValidate('getDevices',
124 var args = $Array.slice(arguments);
126 if (bluetooth.getDevicesState != null) {
127 throw new Error('Concurrent calls to getDevices are not allowed.');
130 var state = { actualEvents: 0 };
132 if (typeof(args[args.length - 1]) == 'function') {
133 state.finalCallback = args.pop();
136 if (chrome.runtime.lastError) {
137 finishDeviceSearch();
141 throw new Error('getDevices must have a final callback parameter.');
144 if (typeof(args[0].deviceCallback) == 'function') {
145 state.deviceCallback = args[0].deviceCallback;
147 throw new Error('getDevices must be passed options with a ' +
151 bluetooth.getDevicesState = state;
152 addDeviceSearchListeners();
158 exports.binding = binding.generate();