NaCl: Update revision in DEPS, r12770 -> r12773
[chromium-blink-merge.git] / chrome / renderer / resources / extensions / bluetooth_custom_bindings.js
bloba125877a76d4e23bc26dda5c7869fc92c917aa71
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;
20   var bluetooth = {};
22   function callCallbackIfPresent(name, args, error) {
23     var callback = args[args.length - 1];
24     if (typeof(callback) == 'function')
25       lastError.run(name, error, callback);
26   }
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;
34   }
35   apiFunctions.setHandleRequest('startDiscovery',
36       function() {
37         var args = arguments;
38         if (args.length > 0 && args[0] && args[0].deviceCallback) {
39           if (bluetooth.deviceDiscoveredHandler != null) {
40             callCallbackIfPresent('bluetooth.startDiscovery',
41                                   args,
42                                   'Concurrent discovery is not allowed.');
43             return;
44           }
46           bluetooth.deviceDiscoveredHandler = args[0].deviceCallback;
47           bluetooth.onDeviceDiscovered.addListener(
48               bluetooth.deviceDiscoveredHandler);
49           sendRequest(this.name,
50                       args,
51                       this.definition.parameters,
52                       {customCallback:this.customCallback});
53         } else {
54           callCallbackIfPresent(
55             'bluetooth.startDiscovery',
56             args,
57             'deviceCallback is required in the options object');
58           return;
59         }
60       });
61   apiFunctions.setCustomCallback('startDiscovery',
62       function(name, request, response) {
63         if (chrome.runtime.lastError) {
64           clearDeviceDiscoveredHandler();
65           return;
66         }
67       });
68   apiFunctions.setHandleRequest('stopDiscovery',
69       function() {
70         clearDeviceDiscoveredHandler();
71         sendRequest(this.name, arguments, this.definition.parameters);
72       });
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();
86   }
88   function deviceSearchFinishedHandler(info) {
89     bluetooth.getDevicesState.expectedEventCount = info.expectedEventCount;
90     maybeFinishDeviceSearch();
91   }
93   function addDeviceSearchListeners() {
94     bluetooth.onDeviceSearchResult.addListener(deviceSearchResultHandler);
95     bluetooth.onDeviceSearchFinished.addListener(deviceSearchFinishedHandler);
96   }
98   function removeDeviceSearchListeners() {
99     bluetooth.onDeviceSearchResult.removeListener(deviceSearchResultHandler);
100     bluetooth.onDeviceSearchFinished.removeListener(
101         deviceSearchFinishedHandler);
102   }
104   function maybeFinishDeviceSearch() {
105     var state = bluetooth.getDevicesState;
106     if (typeof(state.expectedEventCount) != 'undefined' &&
107         state.actualEvents >= state.expectedEventCount) {
108       finishDeviceSearch();
109     }
110   }
112   function finishDeviceSearch() {
113     var finalCallback = bluetooth.getDevicesState.finalCallback;
114     removeDeviceSearchListeners();
115     bluetooth.getDevicesState = null;
117     if (finalCallback) {
118       finalCallback();
119     }
120   }
122   apiFunctions.setUpdateArgumentsPostValidate('getDevices',
123       function() {
124         var args = $Array.slice(arguments);
126         if (bluetooth.getDevicesState != null) {
127           throw new Error('Concurrent calls to getDevices are not allowed.');
128         }
130         var state = { actualEvents: 0 };
132         if (typeof(args[args.length - 1]) == 'function') {
133           state.finalCallback = args.pop();
134           $Array.push(args,
135               function() {
136                 if (chrome.runtime.lastError) {
137                   finishDeviceSearch();
138                 }
139               });
140         } else {
141           throw new Error('getDevices must have a final callback parameter.');
142         }
144         if (typeof(args[0].deviceCallback) == 'function') {
145           state.deviceCallback = args[0].deviceCallback;
146         } else {
147           throw new Error('getDevices must be passed options with a ' +
148               'deviceCallback.');
149         }
151         bluetooth.getDevicesState = state;
152         addDeviceSearchListeners();
154         return args;
155       });
158 exports.binding = binding.generate();