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
3 // found in the LICENSE file.
6 * Custom bindings for the Serial API.
8 * The bindings are implemented by asynchronously delegating to the
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
14 var binding = require('binding').Binding.create('serial');
15 var context = requireNative('v8_context');
16 var eventBindings = require('event_bindings');
17 var utils = require('utils');
19 var serialServicePromise = function() {
20 // getBackgroundPage is not available in unit tests so fall back to the
21 // current page's serial_service module.
22 if (!chrome.runtime.getBackgroundPage)
23 return requireAsync('serial_service');
25 // Load the serial_service module from the background page if one exists. This
26 // is necessary for serial connections created in one window to be usable
27 // after that window is closed. This is necessary because the Mojo async
28 // waiter only functions while the v8 context remains.
29 return utils.promise(chrome.runtime.getBackgroundPage).then(function(bgPage) {
30 return context.GetModuleSystem(bgPage).requireAsync('serial_service');
32 return requireAsync('serial_service');
36 function forwardToConnection(methodName) {
37 return function(connectionId) {
38 var args = $Array.slice(arguments, 1);
39 return serialServicePromise.then(function(serialService) {
40 return serialService.getConnection(connectionId);
41 }).then(function(connection) {
42 return $Function.apply(connection[methodName], connection, args);
47 function addEventListeners(connection, id) {
48 connection.onData = function(data) {
49 eventBindings.dispatchEvent(
50 'serial.onReceive', [{connectionId: id, data: data}]);
52 connection.onError = function(error) {
53 eventBindings.dispatchEvent(
54 'serial.onReceiveError', [{connectionId: id, error: error}]);
58 serialServicePromise.then(function(serialService) {
59 return serialService.getConnections().then(function(connections) {
60 for (var entry of connections) {
61 var connection = entry[1];
62 addEventListeners(connection, entry[0]);
63 connection.resumeReceives();
68 binding.registerCustomHook(function(bindingsAPI) {
69 var apiFunctions = bindingsAPI.apiFunctions;
70 apiFunctions.setHandleRequestWithPromise('getDevices', function() {
71 return serialServicePromise.then(function(serialService) {
72 return serialService.getDevices();
76 apiFunctions.setHandleRequestWithPromise('connect', function(path, options) {
77 return serialServicePromise.then(function(serialService) {
78 return serialService.createConnection(path, options);
79 }).then(function(result) {
80 addEventListeners(result.connection, result.info.connectionId);
82 }).catch (function(e) {
83 throw new Error('Failed to connect to the port.');
87 apiFunctions.setHandleRequestWithPromise(
88 'disconnect', forwardToConnection('close'));
89 apiFunctions.setHandleRequestWithPromise(
90 'getInfo', forwardToConnection('getInfo'));
91 apiFunctions.setHandleRequestWithPromise(
92 'update', forwardToConnection('setOptions'));
93 apiFunctions.setHandleRequestWithPromise(
94 'getControlSignals', forwardToConnection('getControlSignals'));
95 apiFunctions.setHandleRequestWithPromise(
96 'setControlSignals', forwardToConnection('setControlSignals'));
97 apiFunctions.setHandleRequestWithPromise(
98 'flush', forwardToConnection('flush'));
99 apiFunctions.setHandleRequestWithPromise(
100 'setPaused', forwardToConnection('setPaused'));
101 apiFunctions.setHandleRequestWithPromise(
102 'send', forwardToConnection('send'));
104 apiFunctions.setHandleRequestWithPromise('getConnections', function() {
105 return serialServicePromise.then(function(serialService) {
106 return serialService.getConnections();
107 }).then(function(connections) {
109 for (var connection of connections.values()) {
110 promises.push(connection.getInfo());
112 return Promise.all(promises);
117 exports.binding = binding.generate();