OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 * Custom bindings for the Serial API. | 6 * Custom bindings for the Serial API. |
7 * | 7 * |
8 * The bindings are implemented by asynchronously delegating to the | 8 * The bindings are implemented by asynchronously delegating to the |
9 * serial_service module. The functions that apply to a particular connection | 9 * serial_service module. The functions that apply to a particular connection |
10 * are delegated to the appropriate method on the Connection object specified by | 10 * are delegated to the appropriate method on the Connection object specified by |
11 * the ID parameter. | 11 * the ID parameter. |
12 */ | 12 */ |
13 | 13 |
14 var binding = require('binding').Binding.create('serial'); | 14 var binding = require('binding').Binding.create('serial'); |
| 15 var context = requireNative('v8_context'); |
| 16 var utils = require('utils'); |
15 | 17 |
16 function createAsyncProxy(targetPromise, functionNames) { | 18 var serialServicePromise = function() { |
17 var functionProxies = {}; | 19 // getBackgroundPage is not available in unit tests so fall back to the |
18 $Array.forEach(functionNames, function(name) { | 20 // current page's serial_service module. |
19 functionProxies[name] = function() { | 21 if (!chrome.runtime.getBackgroundPage) |
20 var args = arguments; | 22 return requireAsync('serial_service'); |
21 return targetPromise.then(function(target) { | 23 |
22 return $Function.apply(target[name], target, args); | 24 // Load the serial_service module from the background page if one exists. This |
23 }); | 25 // is necessary for serial connections created in one window to be usable |
24 }; | 26 // after that window is closed. This is necessary because the Mojo async |
| 27 // waiter only functions while the v8 context remains. |
| 28 return utils.promise(chrome.runtime.getBackgroundPage).then(function(bgPage) { |
| 29 return context.GetModuleSystem(bgPage).requireAsync('serial_service'); |
| 30 }).catch(function() { |
| 31 return requireAsync('serial_service'); |
25 }); | 32 }); |
26 return functionProxies; | 33 }(); |
27 } | |
28 | |
29 var serialService = createAsyncProxy(requireAsync('serial_service'), [ | |
30 'getDevices', | |
31 'createConnection', | |
32 'getConnection', | |
33 'getConnections', | |
34 ]); | |
35 | 34 |
36 function forwardToConnection(methodName) { | 35 function forwardToConnection(methodName) { |
37 return function(connectionId) { | 36 return function(connectionId) { |
38 var args = $Array.slice(arguments, 1); | 37 var args = $Array.slice(arguments, 1); |
39 return serialService.getConnection(connectionId).then(function(connection) { | 38 return serialServicePromise.then(function(serialService) { |
| 39 return serialService.getConnection(connectionId); |
| 40 }).then(function(connection) { |
40 return $Function.apply(connection[methodName], connection, args); | 41 return $Function.apply(connection[methodName], connection, args); |
41 }); | 42 }); |
42 }; | 43 }; |
43 } | 44 } |
44 | 45 |
45 binding.registerCustomHook(function(bindingsAPI) { | 46 binding.registerCustomHook(function(bindingsAPI) { |
46 var apiFunctions = bindingsAPI.apiFunctions; | 47 var apiFunctions = bindingsAPI.apiFunctions; |
47 apiFunctions.setHandleRequestWithPromise('getDevices', | 48 apiFunctions.setHandleRequestWithPromise('getDevices', function() { |
48 serialService.getDevices); | 49 return serialServicePromise.then(function(serialService) { |
| 50 return serialService.getDevices(); |
| 51 }) |
| 52 }); |
49 | 53 |
50 apiFunctions.setHandleRequestWithPromise('connect', function(path, options) { | 54 apiFunctions.setHandleRequestWithPromise('connect', function(path, options) { |
51 return serialService.createConnection(path, options).then(function(result) { | 55 return serialServicePromise.then(function(serialService) { |
| 56 return serialService.createConnection(path, options); |
| 57 }).then(function(result) { |
52 return result.info; | 58 return result.info; |
53 }).catch (function(e) { | 59 }).catch (function(e) { |
54 throw new Error('Failed to connect to the port.'); | 60 throw new Error('Failed to connect to the port.'); |
55 }); | 61 }); |
56 }); | 62 }); |
57 | 63 |
58 apiFunctions.setHandleRequestWithPromise( | 64 apiFunctions.setHandleRequestWithPromise( |
59 'disconnect', forwardToConnection('close')); | 65 'disconnect', forwardToConnection('close')); |
60 apiFunctions.setHandleRequestWithPromise( | 66 apiFunctions.setHandleRequestWithPromise( |
61 'getInfo', forwardToConnection('getInfo')); | 67 'getInfo', forwardToConnection('getInfo')); |
62 apiFunctions.setHandleRequestWithPromise( | 68 apiFunctions.setHandleRequestWithPromise( |
63 'update', forwardToConnection('setOptions')); | 69 'update', forwardToConnection('setOptions')); |
64 apiFunctions.setHandleRequestWithPromise( | 70 apiFunctions.setHandleRequestWithPromise( |
65 'getControlSignals', forwardToConnection('getControlSignals')); | 71 'getControlSignals', forwardToConnection('getControlSignals')); |
66 apiFunctions.setHandleRequestWithPromise( | 72 apiFunctions.setHandleRequestWithPromise( |
67 'setControlSignals', forwardToConnection('setControlSignals')); | 73 'setControlSignals', forwardToConnection('setControlSignals')); |
68 apiFunctions.setHandleRequestWithPromise( | 74 apiFunctions.setHandleRequestWithPromise( |
69 'flush', forwardToConnection('flush')); | 75 'flush', forwardToConnection('flush')); |
70 apiFunctions.setHandleRequestWithPromise( | 76 apiFunctions.setHandleRequestWithPromise( |
71 'setPaused', forwardToConnection('setPaused')); | 77 'setPaused', forwardToConnection('setPaused')); |
72 | 78 |
73 apiFunctions.setHandleRequestWithPromise('getConnections', function() { | 79 apiFunctions.setHandleRequestWithPromise('getConnections', function() { |
74 return serialService.getConnections().then(function(connections) { | 80 return serialServicePromise.then(function(serialService) { |
| 81 return serialService.getConnections(); |
| 82 }).then(function(connections) { |
75 var promises = []; | 83 var promises = []; |
76 for (var id in connections) { | 84 for (var id in connections) { |
77 promises.push(connections[id].getInfo()); | 85 promises.push(connections[id].getInfo()); |
78 } | 86 } |
79 return Promise.all(promises); | 87 return Promise.all(promises); |
80 }); | 88 }); |
81 }); | 89 }); |
82 }); | 90 }); |
83 | 91 |
84 exports.binding = binding.generate(); | 92 exports.binding = binding.generate(); |
OLD | NEW |