Chromium Code Reviews| 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 define('serial_service', [ | 5 define('serial_service', [ |
| 6 'content/public/renderer/service_provider', | 6 'content/public/renderer/service_provider', |
| 7 'device/serial/serial.mojom', | 7 'device/serial/serial.mojom', |
| 8 'mojo/public/js/bindings/core', | |
| 8 'mojo/public/js/bindings/router', | 9 'mojo/public/js/bindings/router', |
| 9 ], function(serviceProvider, serialMojom, routerModule) { | 10 ], function(serviceProvider, serialMojom, core, routerModule) { |
| 10 | 11 |
| 11 function defineService(proxy, handle) { | 12 function defineService(proxy, handle) { |
| 12 if (!handle) | 13 if (!handle) |
| 13 handle = serviceProvider.connectToService(proxy.NAME_); | 14 handle = serviceProvider.connectToService(proxy.NAME_); |
| 14 var router = new routerModule.Router(handle); | 15 var router = new routerModule.Router(handle); |
| 15 var service = new proxy(router); | 16 var service = new proxy(router); |
| 16 return { | 17 return { |
| 17 service: service, | 18 service: service, |
| 18 router: router, | 19 router: router, |
| 19 }; | 20 }; |
| 20 } | 21 } |
| 21 | 22 |
| 22 var service = defineService(serialMojom.SerialServiceProxy).service; | 23 var service = defineService(serialMojom.SerialServiceProxy).service; |
| 23 | 24 |
| 24 function getDevices() { | 25 function getDevices() { |
| 25 return service.getDevices().then(function(response) { | 26 return service.getDevices().then(function(response) { |
| 26 return $Array.map(response.devices, function(device) { | 27 return $Array.map(response.devices, function(device) { |
| 27 var result = {path: device.path || ''}; | 28 var result = {path: device.path || ''}; |
| 28 if (device.has_vendor_id) | 29 if (device.has_vendor_id) |
| 29 result.vendorId = device.vendor_id; | 30 result.vendorId = device.vendor_id; |
| 30 if (device.has_product_id) | 31 if (device.has_product_id) |
| 31 result.productId = device.product_id; | 32 result.productId = device.product_id; |
| 32 if (device.display_name) | 33 if (device.display_name) |
| 33 result.displayName = device.display_name; | 34 result.displayName = device.display_name; |
| 34 return result; | 35 return result; |
| 35 }); | 36 }); |
| 36 }); | 37 }); |
| 37 } | 38 } |
| 38 | 39 |
| 40 var DEFAULT_CLIENT_OPTIONS = { | |
| 41 persistent: false, | |
| 42 name: '', | |
| 43 receiveTimeout: 0, | |
| 44 sendTimeout: 0, | |
| 45 bufferSize: 4096, | |
| 46 }; | |
| 47 | |
| 48 var DATA_BITS_TO_MOJO = { | |
| 49 undefined: serialMojom.DataBits.NONE, | |
| 50 'seven': serialMojom.DataBits.SEVEN, | |
| 51 'eight': serialMojom.DataBits.EIGHT, | |
| 52 }; | |
| 53 var STOP_BITS_TO_MOJO = { | |
| 54 undefined: serialMojom.StopBits.NONE, | |
| 55 'one': serialMojom.StopBits.ONE, | |
| 56 'two': serialMojom.StopBits.TWO, | |
| 57 }; | |
| 58 var PARITY_BIT_TO_MOJO = { | |
| 59 undefined: serialMojom.ParityBit.NONE, | |
| 60 'no': serialMojom.ParityBit.NO, | |
| 61 'odd': serialMojom.ParityBit.ODD, | |
| 62 'even': serialMojom.ParityBit.EVEN, | |
| 63 }; | |
| 64 | |
| 65 function invertMap(input) { | |
| 66 var output = {}; | |
| 67 for (var key in input) { | |
| 68 if (key == 'undefined') | |
| 69 output[input[key]] = undefined; | |
| 70 else | |
| 71 output[input[key]] = key; | |
| 72 } | |
| 73 return output; | |
| 74 } | |
| 75 var DATA_BITS_FROM_MOJO = invertMap(DATA_BITS_TO_MOJO); | |
| 76 var STOP_BITS_FROM_MOJO = invertMap(STOP_BITS_TO_MOJO); | |
| 77 var PARITY_BIT_FROM_MOJO = invertMap(PARITY_BIT_TO_MOJO); | |
| 78 | |
|
Ken Rockot(use gerrit already)
2014/07/31 16:28:33
I'm guessing this conversion stuff is some of the
| |
| 79 function getServiceOptions(options) { | |
| 80 var out = {}; | |
| 81 if (options.dataBits) | |
| 82 out.data_bits = DATA_BITS_TO_MOJO[options.dataBits]; | |
| 83 if (options.stopBits) | |
| 84 out.stop_bits = STOP_BITS_TO_MOJO[options.stopBits]; | |
| 85 if (options.parityBit) | |
| 86 out.parity_bit = PARITY_BIT_TO_MOJO[options.parityBit]; | |
| 87 if ('ctsFlowControl' in options) { | |
| 88 out.has_cts_flow_control = true; | |
| 89 out.cts_flow_control = options.ctsFlowControl; | |
| 90 } | |
| 91 if ('bitrate' in options) | |
| 92 out.bitrate = options.bitrate; | |
| 93 return out; | |
| 94 } | |
| 95 | |
| 96 function convertServiceInfo(result) { | |
| 97 if (!result.info) | |
| 98 throw new Error('Failed to get ConnectionInfo.'); | |
| 99 return { | |
| 100 ctsFlowControl: !!result.info.cts_flow_control, | |
| 101 bitrate: result.info.bitrate || undefined, | |
| 102 dataBits: DATA_BITS_FROM_MOJO[result.info.data_bits], | |
| 103 stopBits: STOP_BITS_FROM_MOJO[result.info.stop_bits], | |
| 104 parityBit: PARITY_BIT_FROM_MOJO[result.info.parity_bit], | |
| 105 }; | |
| 106 } | |
| 107 | |
| 108 function Connection(remoteConnection, router, id, options) { | |
| 109 this.remoteConnection_ = remoteConnection; | |
| 110 this.router_ = router; | |
| 111 this.id_ = id; | |
| 112 getConnections().then(function(connections) { | |
| 113 connections[this.id_] = this; | |
| 114 }.bind(this)); | |
| 115 this.paused_ = false; | |
| 116 this.options_ = {}; | |
| 117 for (var key in DEFAULT_CLIENT_OPTIONS) { | |
| 118 this.options_[key] = DEFAULT_CLIENT_OPTIONS[key]; | |
| 119 } | |
| 120 this.setClientOptions_(options); | |
| 121 } | |
| 122 | |
| 123 Connection.create = function(path, options) { | |
| 124 options = options || {}; | |
| 125 var serviceOptions = getServiceOptions(options); | |
| 126 var pipe = core.createMessagePipe(); | |
| 127 service.connect(path, serviceOptions, pipe.handle0); | |
| 128 var result = defineService(serialMojom.ConnectionProxy, pipe.handle1); | |
| 129 return result.service.getInfo().then(convertServiceInfo).then( | |
| 130 function(info) { | |
| 131 return Promise.all([info, allocateConnectionId()]); | |
| 132 }).catch(function(e) { | |
| 133 result.router.close(); | |
| 134 throw e; | |
| 135 }).then(function(results) { | |
| 136 var info = results[0]; | |
| 137 var id = results[1]; | |
| 138 var serialConnectionClient = new Connection( | |
| 139 result.service, result.router, id, options); | |
| 140 var clientInfo = serialConnectionClient.getClientInfo_(); | |
| 141 for (var key in clientInfo) { | |
| 142 info[key] = clientInfo[key]; | |
| 143 } | |
| 144 return { | |
| 145 connection: serialConnectionClient, | |
| 146 info: info, | |
| 147 }; | |
| 148 }); | |
| 149 }; | |
| 150 | |
| 151 Connection.prototype.close = function() { | |
| 152 this.router_.close(); | |
| 153 return getConnections().then(function(connections) { | |
| 154 delete connections[this.id_] | |
| 155 return true; | |
| 156 }.bind(this)); | |
| 157 }; | |
| 158 | |
| 159 Connection.prototype.getClientInfo_ = function() { | |
| 160 var info = { | |
| 161 connectionId: this.id_, | |
| 162 paused: this.paused_, | |
| 163 } | |
| 164 for (var key in this.options_) { | |
| 165 info[key] = this.options_[key]; | |
| 166 } | |
| 167 return info; | |
| 168 }; | |
| 169 | |
| 170 Connection.prototype.getInfo = function() { | |
| 171 var info = this.getClientInfo_(); | |
| 172 return this.remoteConnection_.getInfo().then(convertServiceInfo).then( | |
| 173 function(result) { | |
| 174 for (var key in result) { | |
| 175 info[key] = result[key]; | |
| 176 } | |
| 177 return info; | |
| 178 }).catch(function() { | |
| 179 return info; | |
| 180 }); | |
| 181 } | |
| 182 | |
| 183 Connection.prototype.setClientOptions_ = function(options) { | |
| 184 if ('name' in options) | |
| 185 this.options_.name = options.name; | |
| 186 if ('receiveTimeout' in options) | |
| 187 this.options_.receiveTimeout = options.receiveTimeout; | |
| 188 if ('sendTimeout' in options) | |
| 189 this.options_.sendTimeout = options.sendTimeout; | |
| 190 if ('bufferSize' in options) | |
| 191 this.options_.bufferSize = options.bufferSize; | |
| 192 }; | |
| 193 | |
| 194 Connection.prototype.setOptions = function(options) { | |
| 195 this.setClientOptions_(options); | |
| 196 var serviceOptions = getServiceOptions(options); | |
| 197 if ($Object.keys(serviceOptions).length == 0) | |
| 198 return true; | |
| 199 return this.remoteConnection_.setOptions(serviceOptions).then( | |
| 200 function(result) { | |
| 201 return !!result.success; | |
| 202 }).catch(function() { | |
| 203 return false; | |
| 204 }); | |
| 205 }; | |
| 206 | |
| 207 Connection.prototype.getControlSignals = function() { | |
| 208 return this.remoteConnection_.getControlSignals().then(function(result) { | |
| 209 if (!result.signals) | |
| 210 throw new Error('Failed to get control signals.'); | |
| 211 var signals = result.signals; | |
| 212 return { | |
| 213 dcd: !!signals.dcd, | |
| 214 cts: !!signals.cts, | |
| 215 ri: !!signals.ri, | |
| 216 dsr: !!signals.dsr, | |
| 217 }; | |
| 218 }); | |
| 219 }; | |
| 220 | |
| 221 Connection.prototype.setControlSignals = function(signals) { | |
| 222 var controlSignals = {}; | |
| 223 if ('dtr' in signals) { | |
| 224 controlSignals.has_dtr = true; | |
| 225 controlSignals.dtr = signals.dtr; | |
| 226 } | |
| 227 if ('rts' in signals) { | |
| 228 controlSignals.has_rts = true; | |
| 229 controlSignals.rts = signals.rts; | |
| 230 } | |
| 231 return this.remoteConnection_.setControlSignals(controlSignals).then( | |
| 232 function(result) { | |
| 233 return !!result.success; | |
| 234 }); | |
| 235 }; | |
| 236 | |
| 237 Connection.prototype.flush = function() { | |
| 238 return this.remoteConnection_.flush().then(function(result) { | |
| 239 return !!result.success; | |
| 240 }); | |
| 241 }; | |
| 242 | |
| 243 Connection.prototype.setPaused = function(paused) { | |
| 244 this.paused_ = paused; | |
| 245 }; | |
| 246 | |
| 247 var connections_ = {}; | |
| 248 var nextConnectionId_ = 0; | |
| 249 | |
| 250 // Wrap all access to |connections_| through getConnections to avoid adding | |
| 251 // any synchronous dependencies on it. This will likely be important when | |
| 252 // supporting persistent connections by stashing them. | |
| 253 function getConnections() { | |
| 254 return Promise.resolve(connections_); | |
| 255 } | |
| 256 | |
| 257 function getConnection(id) { | |
| 258 return getConnections().then(function(connections) { | |
| 259 if (!connections[id]) | |
| 260 throw new Error ('Serial connection not found.'); | |
| 261 return connections[id]; | |
| 262 }); | |
| 263 } | |
| 264 | |
| 265 function forwardToConnection(methodName) { | |
| 266 return function(connectionId) { | |
| 267 var args = $Array.slice(arguments, 1); | |
| 268 return getConnection(connectionId).then(function(connection) { | |
| 269 return $Function.apply(connection[methodName], connection, args); | |
| 270 }); | |
| 271 } | |
| 272 } | |
| 273 | |
| 274 function allocateConnectionId() { | |
| 275 return Promise.resolve(nextConnectionId_++); | |
| 276 } | |
| 277 | |
| 39 return { | 278 return { |
| 40 getDevices: getDevices, | 279 getDevices: getDevices, |
| 280 createConnection: Connection.create, | |
| 281 getConnection: getConnection, | |
| 282 getConnections: getConnections, | |
| 41 }; | 283 }; |
| 42 }); | 284 }); |
| OLD | NEW |