Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(372)

Side by Side Diff: remoting/webapp/xmpp_connection.js

Issue 530213004: Use XMPP in V2 webapp (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 'use strict'; 5 'use strict';
6 6
7 /** @suppress {duplicate} */ 7 /** @suppress {duplicate} */
8 var remoting = remoting || {}; 8 var remoting = remoting || {};
9 9
10 /** 10 /**
11 * A connection to an XMPP server. 11 * A connection to an XMPP server.
12 * 12 *
13 * TODO(sergeyu): Chrome provides two APIs for TCP sockets: chrome.socket and 13 * TODO(sergeyu): Chrome provides two APIs for TCP sockets: chrome.socket and
14 * chrome.sockets.tcp . chrome.socket is deprecated but it's still used here 14 * chrome.sockets.tcp . chrome.socket is deprecated but it's still used here
15 * because TLS support in chrome.sockets.tcp is currently broken, see 15 * because TLS support in chrome.sockets.tcp is currently broken, see
16 * crbug.com/403076 . 16 * crbug.com/403076 .
17 * 17 *
18 * @param {function(remoting.XmppConnection.State):void} onStateChangedCallback 18 * @param {function(remoting.SignalStrategy.State):void} onStateChangedCallback
19 * Callback to call on state change. 19 * Callback to call on state change.
20 * @param {function(Element):void} onIncomingStanzaCallback Callback to call to
21 * handle incoming messages.
22 * @constructor 20 * @constructor
23 * @implements {base.Disposable} 21 * @implements {remoting.SignalStrategy}
24 */ 22 */
25 remoting.XmppConnection = 23 remoting.XmppConnection = function(onStateChangedCallback) {
26 function(onStateChangedCallback, onIncomingStanzaCallback) {
27 /** @private */ 24 /** @private */
28 this.server_ = ''; 25 this.server_ = '';
29 /** @private */ 26 /** @private */
30 this.port_ = 0; 27 this.port_ = 0;
31 /** @private */ 28 /** @private */
32 this.onStateChangedCallback_ = onStateChangedCallback; 29 this.onStateChangedCallback_ = onStateChangedCallback;
33 /** @private */ 30 /** @type {?function(Element):void} @private */
34 this.onIncomingStanzaCallback_ = onIncomingStanzaCallback; 31 this.onIncomingStanzaCallback_ = null;
35 /** @private */ 32 /** @private */
36 this.socketId_ = -1; 33 this.socketId_ = -1;
37 /** @private */ 34 /** @private */
38 this.state_ = remoting.XmppConnection.State.NOT_CONNECTED; 35 this.state_ = remoting.SignalStrategy.State.NOT_CONNECTED;
39 /** @private */ 36 /** @private */
40 this.readPending_ = false; 37 this.readPending_ = false;
41 /** @private */ 38 /** @private */
42 this.sendPending_ = false; 39 this.sendPending_ = false;
43 /** @private */ 40 /** @private */
44 this.startTlsPending_ = false; 41 this.startTlsPending_ = false;
45 /** @type {Array.<ArrayBuffer>} @private */ 42 /** @type {Array.<ArrayBuffer>} @private */
46 this.sendQueue_ = []; 43 this.sendQueue_ = [];
47 /** @type {remoting.XmppLoginHandler} @private*/ 44 /** @type {remoting.XmppLoginHandler} @private*/
48 this.loginHandler_ = null; 45 this.loginHandler_ = null;
49 /** @type {remoting.XmppStreamParser} @private*/ 46 /** @type {remoting.XmppStreamParser} @private*/
50 this.streamParser_ = null; 47 this.streamParser_ = null;
51 /** @private */ 48 /** @private */
52 this.jid_ = ''; 49 this.jid_ = '';
53 /** @private */ 50 /** @private */
54 this.error_ = remoting.Error.NONE; 51 this.error_ = remoting.Error.NONE;
55 }; 52 };
56 53
57 /** 54 /**
58 * @enum {number} XmppConnection states. Possible state transitions: 55 * @param {?function(Element):void} onIncomingStanzaCallback Callback to call on
59 * NOT_CONNECTED -> CONNECTING (connect() called). 56 * incoming messages.
60 * CONNECTING -> HANDSHAKE (connected successfully).
61 * HANDSHAKE -> CONNECTED (authenticated successfully).
62 * CONNECTING -> FAILED (connection failed).
63 * HANDSHAKE -> FAILED (authentication failed).
64 * * -> CLOSED (dispose() called).
65 */ 57 */
66 remoting.XmppConnection.State = { 58 remoting.XmppConnection.prototype.setIncomingStanzaCallback =
67 NOT_CONNECTED: 0, 59 function(onIncomingStanzaCallback) {
68 CONNECTING: 1, 60 this.onIncomingStanzaCallback_ = onIncomingStanzaCallback;
69 HANDSHAKE: 2,
70 CONNECTED: 3,
71 FAILED: 4,
72 CLOSED: 5
73 }; 61 };
74 62
75 /** 63 /**
76 * @param {string} server 64 * @param {string} server
77 * @param {string} username 65 * @param {string} username
78 * @param {string} authToken 66 * @param {string} authToken
79 */ 67 */
80 remoting.XmppConnection.prototype.connect = 68 remoting.XmppConnection.prototype.connect =
81 function(server, username, authToken) { 69 function(server, username, authToken) {
82 base.debug.assert(this.state_ == remoting.XmppConnection.State.NOT_CONNECTED); 70 base.debug.assert(this.state_ == remoting.SignalStrategy.State.NOT_CONNECTED);
83 71
84 this.error_ = remoting.Error.NONE; 72 this.error_ = remoting.Error.NONE;
85 var hostnameAndPort = server.split(':', 2); 73 var hostnameAndPort = server.split(':', 2);
86 this.server_ = hostnameAndPort[0]; 74 this.server_ = hostnameAndPort[0];
87 this.port_ = 75 this.port_ =
88 (hostnameAndPort.length == 2) ? parseInt(hostnameAndPort[1], 10) : 5222; 76 (hostnameAndPort.length == 2) ? parseInt(hostnameAndPort[1], 10) : 5222;
89 77
90 // The server name is passed as to attribute in the <stream>. When connecting 78 // The server name is passed as to attribute in the <stream>. When connecting
91 // to talk.google.com it affects the certificate the server will use for TLS: 79 // to talk.google.com it affects the certificate the server will use for TLS:
92 // talk.google.com uses gmail certificate when specified server is gmail.com 80 // talk.google.com uses gmail certificate when specified server is gmail.com
93 // or googlemail.com and google.com cert otherwise. In the same time it 81 // or googlemail.com and google.com cert otherwise. In the same time it
94 // doesn't accept talk.google.com as target server. Here we use google.com 82 // doesn't accept talk.google.com as target server. Here we use google.com
95 // server name when authenticating to talk.google.com. This ensures that the 83 // server name when authenticating to talk.google.com. This ensures that the
96 // server will use google.com cert which will be accepted by the TLS 84 // server will use google.com cert which will be accepted by the TLS
97 // implementation in Chrome (TLS API doesn't allow specifying domain other 85 // implementation in Chrome (TLS API doesn't allow specifying domain other
98 // than the one that was passed to connect()). 86 // than the one that was passed to connect()).
99 var xmppServer = this.server_; 87 var xmppServer = this.server_;
100 if (xmppServer == 'talk.google.com') 88 if (xmppServer == 'talk.google.com')
101 xmppServer = 'google.com'; 89 xmppServer = 'google.com';
102 90
103 /** @type {remoting.XmppLoginHandler} */ 91 /** @type {remoting.XmppLoginHandler} */
104 this.loginHandler_ = 92 this.loginHandler_ =
105 new remoting.XmppLoginHandler(xmppServer, username, authToken, 93 new remoting.XmppLoginHandler(xmppServer, username, authToken,
106 this.sendInternal_.bind(this), 94 this.sendInternal_.bind(this),
107 this.startTls_.bind(this), 95 this.startTls_.bind(this),
108 this.onHandshakeDone_.bind(this), 96 this.onHandshakeDone_.bind(this),
109 this.onError_.bind(this)); 97 this.onError_.bind(this));
110 chrome.socket.create("tcp", {}, this.onSocketCreated_.bind(this)); 98 chrome.socket.create("tcp", {}, this.onSocketCreated_.bind(this));
111 this.setState_(remoting.XmppConnection.State.CONNECTING); 99 this.setState_(remoting.SignalStrategy.State.CONNECTING);
112 }; 100 };
113 101
114 /** @param {string} message */ 102 /** @param {string} message */
115 remoting.XmppConnection.prototype.sendMessage = function(message) { 103 remoting.XmppConnection.prototype.sendMessage = function(message) {
116 base.debug.assert(this.state_ == remoting.XmppConnection.State.CONNECTED); 104 base.debug.assert(this.state_ == remoting.SignalStrategy.State.CONNECTED);
117 this.sendInternal_(message); 105 this.sendInternal_(message);
118 }; 106 };
119 107
120 /** @return {remoting.XmppConnection.State} Current state */ 108 /** @return {remoting.SignalStrategy.State} Current state */
121 remoting.XmppConnection.prototype.getState = function() { 109 remoting.XmppConnection.prototype.getState = function() {
122 return this.state_; 110 return this.state_;
123 }; 111 };
124 112
125 /** @return {remoting.Error} Error when in FAILED state. */ 113 /** @return {remoting.Error} Error when in FAILED state. */
126 remoting.XmppConnection.prototype.getError = function() { 114 remoting.XmppConnection.prototype.getError = function() {
127 return this.error_; 115 return this.error_;
128 }; 116 };
129 117
130 /** @return {string} Current JID when in CONNECTED state. */ 118 /** @return {string} Current JID when in CONNECTED state. */
131 remoting.XmppConnection.prototype.getJid = function() { 119 remoting.XmppConnection.prototype.getJid = function() {
132 return this.jid_; 120 return this.jid_;
133 }; 121 };
134 122
135 remoting.XmppConnection.prototype.dispose = function() { 123 remoting.XmppConnection.prototype.dispose = function() {
136 this.closeSocket_(); 124 this.closeSocket_();
137 this.setState_(remoting.XmppConnection.State.CLOSED); 125 this.setState_(remoting.SignalStrategy.State.CLOSED);
138 }; 126 };
139 127
140 /** 128 /**
141 * @param {chrome.socket.CreateInfo} createInfo 129 * @param {chrome.socket.CreateInfo} createInfo
142 * @private 130 * @private
143 */ 131 */
144 remoting.XmppConnection.prototype.onSocketCreated_ = function(createInfo) { 132 remoting.XmppConnection.prototype.onSocketCreated_ = function(createInfo) {
145 // Check if connection was destroyed. 133 // Check if connection was destroyed.
146 if (this.state_ != remoting.XmppConnection.State.CONNECTING) { 134 if (this.state_ != remoting.SignalStrategy.State.CONNECTING) {
147 chrome.socket.destroy(createInfo.socketId); 135 chrome.socket.destroy(createInfo.socketId);
148 return; 136 return;
149 } 137 }
150 138
151 this.socketId_ = createInfo.socketId; 139 this.socketId_ = createInfo.socketId;
152 140
153 chrome.socket.connect(this.socketId_, 141 chrome.socket.connect(this.socketId_,
154 this.server_, 142 this.server_,
155 this.port_, 143 this.port_,
156 this.onSocketConnected_.bind(this)); 144 this.onSocketConnected_.bind(this));
157 }; 145 };
158 146
159 /** 147 /**
160 * @param {number} result 148 * @param {number} result
161 * @private 149 * @private
162 */ 150 */
163 remoting.XmppConnection.prototype.onSocketConnected_ = function(result) { 151 remoting.XmppConnection.prototype.onSocketConnected_ = function(result) {
164 // Check if connection was destroyed. 152 // Check if connection was destroyed.
165 if (this.state_ != remoting.XmppConnection.State.CONNECTING) { 153 if (this.state_ != remoting.SignalStrategy.State.CONNECTING) {
166 return; 154 return;
167 } 155 }
168 156
169 if (result != 0) { 157 if (result != 0) {
170 this.onError_(remoting.Error.NETWORK_FAILURE, 158 this.onError_(remoting.Error.NETWORK_FAILURE,
171 'Failed to connect to ' + this.server_ + ': ' + result); 159 'Failed to connect to ' + this.server_ + ': ' + result);
172 return; 160 return;
173 } 161 }
174 162
175 this.setState_(remoting.XmppConnection.State.HANDSHAKE); 163 this.setState_(remoting.SignalStrategy.State.HANDSHAKE);
176 164
177 this.tryRead_(); 165 this.tryRead_();
178 this.loginHandler_.start(); 166 this.loginHandler_.start();
179 }; 167 };
180 168
181 /** 169 /**
182 * @private 170 * @private
183 */ 171 */
184 remoting.XmppConnection.prototype.tryRead_ = function() { 172 remoting.XmppConnection.prototype.tryRead_ = function() {
185 base.debug.assert(!this.readPending_); 173 base.debug.assert(!this.readPending_);
186 base.debug.assert(this.state_ == remoting.XmppConnection.State.HANDSHAKE || 174 base.debug.assert(this.state_ == remoting.SignalStrategy.State.HANDSHAKE ||
187 this.state_ == remoting.XmppConnection.State.CONNECTED); 175 this.state_ == remoting.SignalStrategy.State.CONNECTED);
188 base.debug.assert(!this.startTlsPending_); 176 base.debug.assert(!this.startTlsPending_);
189 177
190 this.readPending_ = true; 178 this.readPending_ = true;
191 chrome.socket.read(this.socketId_, this.onRead_.bind(this)); 179 chrome.socket.read(this.socketId_, this.onRead_.bind(this));
192 }; 180 };
193 181
194 /** 182 /**
195 * @param {chrome.socket.ReadInfo} readInfo 183 * @param {chrome.socket.ReadInfo} readInfo
196 * @private 184 * @private
197 */ 185 */
198 remoting.XmppConnection.prototype.onRead_ = function(readInfo) { 186 remoting.XmppConnection.prototype.onRead_ = function(readInfo) {
199 base.debug.assert(this.readPending_); 187 base.debug.assert(this.readPending_);
200 this.readPending_ = false; 188 this.readPending_ = false;
201 189
202 // Check if the socket was closed while reading. 190 // Check if the socket was closed while reading.
203 if (this.state_ != remoting.XmppConnection.State.HANDSHAKE && 191 if (this.state_ != remoting.SignalStrategy.State.HANDSHAKE &&
204 this.state_ != remoting.XmppConnection.State.CONNECTED) { 192 this.state_ != remoting.SignalStrategy.State.CONNECTED) {
205 return; 193 return;
206 } 194 }
207 195
196
208 if (readInfo.resultCode < 0) { 197 if (readInfo.resultCode < 0) {
209 this.onError_(remoting.Error.NETWORK_FAILURE, 198 this.onError_(remoting.Error.NETWORK_FAILURE,
210 'Failed to receive from XMPP socket: ' + readInfo.resultCode); 199 'Failed to receive from XMPP socket: ' + readInfo.resultCode);
211 return; 200 return;
212 } 201 }
213 202
214 if (this.state_ == remoting.XmppConnection.State.HANDSHAKE) { 203 if (this.state_ == remoting.SignalStrategy.State.HANDSHAKE) {
215 this.loginHandler_.onDataReceived(readInfo.data); 204 this.loginHandler_.onDataReceived(readInfo.data);
216 } else if (this.state_ == remoting.XmppConnection.State.CONNECTED) { 205 } else if (this.state_ == remoting.SignalStrategy.State.CONNECTED) {
217 this.streamParser_.appendData(readInfo.data); 206 this.streamParser_.appendData(readInfo.data);
218 } 207 }
219 208
220 if (!this.startTlsPending_) { 209 if (!this.startTlsPending_) {
221 this.tryRead_(); 210 this.tryRead_();
222 } 211 }
223 }; 212 };
224 213
225 /** 214 /**
226 * @param {string} text 215 * @param {string} text
(...skipping 19 matching lines...) Expand all
246 235
247 /** 236 /**
248 * @param {chrome.socket.WriteInfo} writeInfo 237 * @param {chrome.socket.WriteInfo} writeInfo
249 * @private 238 * @private
250 */ 239 */
251 remoting.XmppConnection.prototype.onWrite_ = function(writeInfo) { 240 remoting.XmppConnection.prototype.onWrite_ = function(writeInfo) {
252 base.debug.assert(this.sendPending_); 241 base.debug.assert(this.sendPending_);
253 this.sendPending_ = false; 242 this.sendPending_ = false;
254 243
255 // Ignore write() result if the socket was closed. 244 // Ignore write() result if the socket was closed.
256 if (this.state_ != remoting.XmppConnection.State.HANDSHAKE && 245 if (this.state_ != remoting.SignalStrategy.State.HANDSHAKE &&
257 this.state_ != remoting.XmppConnection.State.CONNECTED) { 246 this.state_ != remoting.SignalStrategy.State.CONNECTED) {
258 return; 247 return;
259 } 248 }
260 249
261 if (writeInfo.bytesWritten < 0) { 250 if (writeInfo.bytesWritten < 0) {
262 this.onError_(remoting.Error.NETWORK_FAILURE, 251 this.onError_(remoting.Error.NETWORK_FAILURE,
263 'TCP write failed with error ' + writeInfo.bytesWritten); 252 'TCP write failed with error ' + writeInfo.bytesWritten);
264 return; 253 return;
265 } 254 }
266 255
267 base.debug.assert(this.sendQueue_.length > 0); 256 base.debug.assert(this.sendQueue_.length > 0);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
309 298
310 /** 299 /**
311 * @param {string} jid 300 * @param {string} jid
312 * @param {remoting.XmppStreamParser} streamParser 301 * @param {remoting.XmppStreamParser} streamParser
313 * @private 302 * @private
314 */ 303 */
315 remoting.XmppConnection.prototype.onHandshakeDone_ = 304 remoting.XmppConnection.prototype.onHandshakeDone_ =
316 function(jid, streamParser) { 305 function(jid, streamParser) {
317 this.jid_ = jid; 306 this.jid_ = jid;
318 this.streamParser_ = streamParser; 307 this.streamParser_ = streamParser;
319 this.streamParser_.setCallbacks(this.onIncomingStanzaCallback_, 308 this.streamParser_.setCallbacks(this.onIncomingStanza_.bind(this),
320 this.onParserError_.bind(this)); 309 this.onParserError_.bind(this));
321 this.setState_(remoting.XmppConnection.State.CONNECTED); 310 this.setState_(remoting.SignalStrategy.State.CONNECTED);
322 }; 311 };
323 312
324 /** 313 /**
314 * @param {Element} stanza
315 * @private
316 */
317 remoting.XmppConnection.prototype.onIncomingStanza_ = function(stanza) {
318 if (this.onIncomingStanzaCallback_) {
319 this.onIncomingStanzaCallback_(stanza);
320 }
321 };
322
323 /**
325 * @param {string} text 324 * @param {string} text
326 * @private 325 * @private
327 */ 326 */
328 remoting.XmppConnection.prototype.onParserError_ = function(text) { 327 remoting.XmppConnection.prototype.onParserError_ = function(text) {
329 this.onError_(remoting.Error.UNEXPECTED, text); 328 this.onError_(remoting.Error.UNEXPECTED, text);
330 } 329 }
331 330
332 /** 331 /**
333 * @param {remoting.Error} error 332 * @param {remoting.Error} error
334 * @param {string} text 333 * @param {string} text
335 * @private 334 * @private
336 */ 335 */
337 remoting.XmppConnection.prototype.onError_ = function(error, text) { 336 remoting.XmppConnection.prototype.onError_ = function(error, text) {
338 console.error(text); 337 console.error(text);
339 this.error_ = error; 338 this.error_ = error;
340 this.closeSocket_(); 339 this.closeSocket_();
341 this.setState_(remoting.XmppConnection.State.FAILED); 340 this.setState_(remoting.SignalStrategy.State.FAILED);
342 }; 341 };
343 342
344 /** 343 /**
345 * @private 344 * @private
346 */ 345 */
347 remoting.XmppConnection.prototype.closeSocket_ = function() { 346 remoting.XmppConnection.prototype.closeSocket_ = function() {
348 if (this.socketId_ != -1) { 347 if (this.socketId_ != -1) {
349 chrome.socket.destroy(this.socketId_); 348 chrome.socket.destroy(this.socketId_);
350 this.socketId_ = -1; 349 this.socketId_ = -1;
351 } 350 }
352 }; 351 };
353 352
354 /** 353 /**
355 * @param {remoting.XmppConnection.State} newState 354 * @param {remoting.SignalStrategy.State} newState
356 * @private 355 * @private
357 */ 356 */
358 remoting.XmppConnection.prototype.setState_ = function(newState) { 357 remoting.XmppConnection.prototype.setState_ = function(newState) {
359 if (this.state_ != newState) { 358 if (this.state_ != newState) {
360 this.state_ = newState; 359 this.state_ = newState;
361 this.onStateChangedCallback_(this.state_); 360 this.onStateChangedCallback_(this.state_);
362 } 361 }
363 }; 362 };
OLDNEW
« remoting/webapp/session_connector.js ('K') | « remoting/webapp/wcs_adapter.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698