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.
9 var testUsername
= 'testUsername@gmail.com';
10 var testToken
= 'testToken';
12 /** @type {(sinon.Spy|function(string):void)} */
13 var sendMessage_spy = function(msg
) {};
14 /** @type {function(string):void} */
15 var sendMessage = function(msg
) {};
17 /** @type {(sinon.Spy|function():void)} */
18 var startTls_spy = function() {};
19 /** @type {function():void} */
20 var startTls = function() {};
22 /** @type {(sinon.Spy|function(string, remoting.XmppStreamParser):void)} */
23 var onHandshakeDone_spy = function(name
, parser
) {};
24 /** @type {function(string, remoting.XmppStreamParser):void} */
25 var onHandshakeDone = function(name
, parser
) {};
27 /** @type {(sinon.Spy|function(remoting.Error, string):void)} */
28 var onError_spy = function(error
, message
) {};
29 /** @type {function(remoting.Error, string):void} */
30 var onError = function(error
, message
) {};
32 /** @type {remoting.XmppLoginHandler} */
33 var loginHandler
= null;
35 QUnit
.module('XmppLoginHandler', {
36 beforeEach: function() {
37 sendMessage_spy
= sinon
.spy();
38 sendMessage
= /** @type {function(string):void} */ (sendMessage_spy
);
39 startTls_spy
= sinon
.spy();
40 startTls
= /** @type {function():void} */ (startTls_spy
);
41 onHandshakeDone_spy
= sinon
.spy();
43 /** @type {function(string, remoting.XmppStreamParser):void} */
44 (onHandshakeDone_spy
);
45 onError_spy
= sinon
.spy();
46 onError
= /** @type {function(remoting.Error, string):void} */(onError_spy
);
48 loginHandler
= new remoting
.XmppLoginHandler(
49 'google.com', testUsername
, testToken
, false,
50 sendMessage
, startTls
, onHandshakeDone
, onError
);
54 // Executes handshake base.
55 function handshakeBase() {
58 sinon
.assert
.calledWith(startTls
);
61 loginHandler
.onTlsStarted();
62 var cookie
= window
.btoa("\0" + testUsername
+ "\0" + testToken
);
63 sinon
.assert
.calledWith(
65 '<stream:stream to="google.com" version="1.0" xmlns="jabber:client" ' +
66 'xmlns:stream="http://etherx.jabber.org/streams">' +
67 '<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="X-OAUTH2" ' +
68 'auth:service="oauth2" auth:allow-generated-jid="true" ' +
69 'auth:client-uses-full-bind-result="true" ' +
70 'auth:allow-non-google-login="true" ' +
71 'xmlns:auth="http://www.google.com/talk/protocol/auth">' + cookie
+
73 sendMessage_spy
.reset();
75 loginHandler
.onDataReceived(base
.encodeUtf8(
76 '<stream:stream from="google.com" id="DCDDE5171CB2154A" version="1.0" ' +
77 'xmlns:stream="http://etherx.jabber.org/streams" ' +
78 'xmlns="jabber:client">' +
80 '<mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">' +
81 '<mechanism>X-OAUTH2</mechanism>' +
82 '<mechanism>X-GOOGLE-TOKEN</mechanism>' +
83 '<mechanism>PLAIN</mechanism>' +
85 '</stream:features>'));
88 QUnit
.test('should authenticate', function() {
91 loginHandler
.onDataReceived(
92 base
.encodeUtf8('<success xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/>'));
93 sinon
.assert
.calledWith(
95 '<stream:stream to="google.com" version="1.0" xmlns="jabber:client" ' +
96 'xmlns:stream="http://etherx.jabber.org/streams">' +
97 '<iq type="set" id="0">' +
98 '<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">' +
99 '<resource>chromoting</resource>' +
102 '<iq type="set" id="1">' +
103 '<session xmlns="urn:ietf:params:xml:ns:xmpp-session"/>' +
105 sendMessage_spy
.reset();
107 loginHandler
.onDataReceived(base
.encodeUtf8(
108 '<stream:stream from="google.com" id="104FA10576E2AA80" version="1.0" ' +
109 'xmlns:stream="http://etherx.jabber.org/streams" ' +
110 'xmlns="jabber:client">' +
111 '<stream:features>' +
112 '<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/>' +
113 '<session xmlns="urn:ietf:params:xml:ns:xmpp-session"/>' +
114 '</stream:features>' +
115 '<iq id="0" type="result">' +
116 '<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">' +
117 '<jid>' + testUsername
+ '/chromoting52B4920E</jid>' +
120 '<iq type="result" id="1"/>'));
122 sinon
.assert
.calledWith(onHandshakeDone
);
125 QUnit
.test('use <starttls> handshake', function() {
126 loginHandler
= new remoting
.XmppLoginHandler(
127 'google.com', testUsername
, testToken
, true, sendMessage
,
128 startTls
, onHandshakeDone
, onError
);
129 loginHandler
.start();
131 sinon
.assert
.calledWith(
133 '<stream:stream to="google.com" version="1.0" xmlns="jabber:client" ' +
134 'xmlns:stream="http://etherx.jabber.org/streams">' +
135 '<starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"/>');
136 sendMessage_spy
.reset();
138 loginHandler
.onDataReceived(base
.encodeUtf8(
139 '<stream:stream from="google.com" id="78A87C70559EF28A" version="1.0" ' +
140 'xmlns:stream="http://etherx.jabber.org/streams"' +
141 'xmlns="jabber:client">' +
142 '<stream:features>' +
143 '<starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls">' +
146 '<mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">' +
147 '<mechanism>X-OAUTH2</mechanism>' +
148 '<mechanism>X-GOOGLE-TOKEN</mechanism>' +
150 '</stream:features>'));
152 loginHandler
.onDataReceived(
153 base
.encodeUtf8('<proceed xmlns="urn:ietf:params:xml:ns:xmpp-tls"/>'));
155 sinon
.assert
.calledWith(startTls
);
159 'should return AUTHENTICATION_FAILED error when failed to authenticate',
163 loginHandler
.onDataReceived(
164 base
.encodeUtf8('<failure xmlns="urn:ietf:params:xml:ns:xmpp-sasl">' +
165 '<not-authorized/></failure>'));
166 sinon
.assert
.calledWith(onError
, new remoting
.Error(
167 remoting
.Error
.Tag
.AUTHENTICATION_FAILED
));
170 QUnit
.test('should return UNEXPECTED error when failed to parse stream',
173 loginHandler
.onDataReceived(
174 base
.encodeUtf8('BAD DATA'));
175 sinon
.assert
.calledWith(onError
, remoting
.Error
.unexpected());