Roll src/third_party/WebKit 3529d49:06e8485 (svn 202554:202555)
[chromium-blink-merge.git] / remoting / webapp / base / js / tcp_socket.js
blobe4877a5d1bdb82052b1561f3c59816fe887573cf
1 // Copyright 2015 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 'use strict';
7 /** @suppress {duplicate} */
8 var remoting = remoting || {};
10 (function() {
12 /** @type {Object<number, remoting.TcpSocket>} */
13 var sockets = {};
14 var receiveListenersAdded = false;
16 function addReceiveListeners() {
17   if (receiveListenersAdded) {
18     return;
19   }
21   receiveListenersAdded = true;
23   chrome.sockets.tcp.onReceive.addListener(function(
24       /** chrome.sockets.tcp.ReceiveEventData */ info) {
25     var socket = sockets[info.socketId];
26     if (socket === undefined) {
27       console.warn("Received data for unknown socket " + info.socketId);
28       return;
29     }
30     if (socket.receiveCallback_ === null) {
31       console.warn("Received data when socket was paused.");
32       return;
33     }
34     socket.receiveCallback_(info.data);
35   });
37   chrome.sockets.tcp.onReceiveError.addListener(function(
38       /** chrome.sockets.tcp.ReceiveErrorEventData */ info) {
39     var socket = sockets[info.socketId];
40     if (socket === undefined) {
41       console.warn("Received error for unknown socket " + info.socketId);
42       return;
43     }
44     if (socket.receiveErrorCallback_ === null) {
45       console.warn("Recv() failed when socket was paused: " + info.resultCode);
46       return;
47     }
48     socket.receiveErrorCallback_(info.resultCode);
49   });
52 /**
53  * Wrapper for chrome.sockets.tcp API.
54  *
55  * @constructor
56  * @implements {base.Disposable}
57  */
58 remoting.TcpSocket = function() {
59   /** @private */
60   this.destroyed_ = false;
61   /** @private */
62   this.socketId_ = -1;
63   /** @private {?function(ArrayBuffer):void} */
64   this.receiveCallback_ = null;
65   /** @private {?function(number):void} */
66   this.receiveErrorCallback_ = null;
68   addReceiveListeners();
71 /**
72  * Connects the socket to the specified host and port.
73  *
74  * @returns {Promise} Promise that's resolved when the socket is connected.
75  */
76 remoting.TcpSocket.prototype.connect = function(/** string */ host,
77                                                 /** number */ port) {
78   var that = this;
80   return new Promise(function(resolve, reject) {
81     chrome.sockets.tcp.create({}, /** @type {function(Object)} */ (onCreated));
84     function onCreated(/** chrome.socket.CreateInfo */ createInfo) {
85       // Check if the socket was destroyed.
86       if (that.destroyed_) {
87         chrome.sockets.tcp.close(createInfo.socketId);
88         return;
89       }
91       that.socketId_ = createInfo.socketId;
92       sockets[that.socketId_] = that;
94       // Pause the socket so that we start receiving only after startReceiving()
95       // is called.
96       chrome.sockets.tcp.setPaused(that.socketId_, true);
98       chrome.sockets.tcp.connect(that.socketId_, host, port, onConnected);
99     }
101     function onConnected(/** number */ result) {
102       if (that.destroyed_) {
103         return;
104       }
106       if (result < 0) {
107         reject(result);
108       } else {
109         resolve(0);
110       }
111     }
112   });
115 remoting.TcpSocket.prototype.dispose = function() {
116   if (this.socketId_ != -1) {
117     chrome.sockets.tcp.close(this.socketId_);
118     delete sockets[this.socketId_];
119     this.socketId_ = -1;
120   }
121   this.destroyed_ = true;
122   this.receiveCallback_ = null;
126  * Starts receiving data on the socket. Calls receiveCallback when new data is
127  * received or receiveErrorCallback when recv() returns an error.
128  */
129 remoting.TcpSocket.prototype.startReceiving = function(
130     /** ?function(ArrayBuffer):void */ receiveCallback,
131     /** ?function(number):void */ receiveErrorCallback) {
132   console.assert(this.receiveCallback_ == null,
133                  'Duplicate startReceiving() invocation.');
134   this.receiveCallback_ = receiveCallback;
135   this.receiveErrorCallback_ = receiveErrorCallback;
136   chrome.sockets.tcp.setPaused(this.socketId_, false);
140  * Sends |data|.
142  * @returns {Promise}
143  */
144 remoting.TcpSocket.prototype.send = function(/** !ArrayBuffer */ data) {
145   var that = this;
147   return new Promise(function(resolve, reject) {
148     chrome.sockets.tcp.send(that.socketId_, data,
149         function(/** chrome.socket.SendInfo */ sendInfo) {
150       if (sendInfo.resultCode < 0) {
151         reject(sendInfo.resultCode);
152       } else {
153         resolve(sendInfo.bytesSent);
154       }
155     });
156   });
160  * Starts TLS on the socket. Once TLS is negotiated the caller will need to call
161  * startReceiving() to start receiving data, even if startReceiving() was called
162  * before.
164  * @returns {Promise}
165  */
166 remoting.TcpSocket.prototype.startTls = function() {
167   var that = this;
169   return new Promise(function(resolve, reject) {
170     function doStartTls() {
171       chrome.sockets.tcp.secure(that.socketId_, {}, function(result) {
172         if (result < 0) {
173           reject(result);
174         } else {
175           resolve(0);
176         }
177       });
178     }
180     if (!that.receiveCallback_) {
181       // Socket is already paused.
182       doStartTls();
183     } else {
184       // Socket must be paused before staring TLS. This won't work correctly
185       // until crbug.com/403076 is fixed. Log a warning and try anyway.
186       console.warn(
187           "remoting.TcpSocket.secure() was called after some data was " +
188           "received on the socket. This won't work properly until " +
189           "crbug.com/403076 is fixed.");
190       chrome.sockets.tcp.setPaused(that.socketId_, true, function() {
191         if (that.destroyed_) {
192           return;
193         }
194         that.receiveCallback_ = null;
195         that.receiveErrorCallback_ = null;
196         doStartTls();
197       });
198     }
199   });
202 })();