OLD | NEW |
| (Empty) |
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. | |
4 | |
5 (function() { | |
6 | |
7 'use strict'; | |
8 | |
9 var testUsername = 'testUsername@gmail.com'; | |
10 var testToken = 'testToken'; | |
11 | |
12 /** @type {(sinon.Spy|function(string):void)} */ | |
13 var sendMessage_spy = function(msg) {}; | |
14 /** @type {function(string):void} */ | |
15 var sendMessage = function(msg) {}; | |
16 | |
17 /** @type {(sinon.Spy|function():void)} */ | |
18 var startTls_spy = function() {}; | |
19 /** @type {function():void} */ | |
20 var startTls = function() {}; | |
21 | |
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) {}; | |
26 | |
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) {}; | |
31 | |
32 /** @type {remoting.XmppLoginHandler} */ | |
33 var loginHandler = null; | |
34 | |
35 module('XmppLoginHandler', { | |
36 setup: 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(); | |
42 onHandshakeDone = | |
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); | |
47 | |
48 loginHandler = new remoting.XmppLoginHandler( | |
49 'google.com', testUsername, testToken, false, | |
50 sendMessage, startTls, onHandshakeDone, onError); | |
51 } | |
52 }); | |
53 | |
54 // Executes handshake base. | |
55 function handshakeBase() { | |
56 loginHandler.start(); | |
57 | |
58 sinon.assert.calledWith(startTls); | |
59 startTls_spy.reset(); | |
60 | |
61 loginHandler.onTlsStarted(); | |
62 var cookie = window.btoa("\0" + testUsername + "\0" + testToken); | |
63 sinon.assert.calledWith( | |
64 sendMessage, | |
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 + | |
72 '</auth>'); | |
73 sendMessage_spy.reset(); | |
74 | |
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">' + | |
79 '<stream:features>' + | |
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>' + | |
84 '</mechanisms>' + | |
85 '</stream:features>')); | |
86 } | |
87 | |
88 test('should authenticate', function() { | |
89 handshakeBase(); | |
90 | |
91 loginHandler.onDataReceived( | |
92 base.encodeUtf8('<success xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/>')); | |
93 sinon.assert.calledWith( | |
94 sendMessage, | |
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>' + | |
100 '</bind>' + | |
101 '</iq>' + | |
102 '<iq type="set" id="1">' + | |
103 '<session xmlns="urn:ietf:params:xml:ns:xmpp-session"/>' + | |
104 '</iq>'); | |
105 sendMessage_spy.reset(); | |
106 | |
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>' + | |
118 '</bind>' + | |
119 '</iq>' + | |
120 '<iq type="result" id="1"/>')); | |
121 | |
122 sinon.assert.calledWith(onHandshakeDone); | |
123 }); | |
124 | |
125 test('use <starttls> handshake', function() { | |
126 loginHandler = new remoting.XmppLoginHandler( | |
127 'google.com', testUsername, testToken, true, sendMessage, | |
128 startTls, onHandshakeDone, onError); | |
129 loginHandler.start(); | |
130 | |
131 sinon.assert.calledWith( | |
132 sendMessage, | |
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(); | |
137 | |
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">' + | |
144 '<required/>' + | |
145 '</starttls>' + | |
146 '<mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">' + | |
147 '<mechanism>X-OAUTH2</mechanism>' + | |
148 '<mechanism>X-GOOGLE-TOKEN</mechanism>' + | |
149 '</mechanisms>' + | |
150 '</stream:features>')); | |
151 | |
152 loginHandler.onDataReceived( | |
153 base.encodeUtf8('<proceed xmlns="urn:ietf:params:xml:ns:xmpp-tls"/>')); | |
154 | |
155 sinon.assert.calledWith(startTls); | |
156 }); | |
157 | |
158 test('should return AUTHENTICATION_FAILED error when failed to authenticate', | |
159 function() { | |
160 handshakeBase(); | |
161 | |
162 loginHandler.onDataReceived( | |
163 base.encodeUtf8('<failure xmlns="urn:ietf:params:xml:ns:xmpp-sasl">' + | |
164 '<not-authorized/></failure>')); | |
165 sinon.assert.calledWith(onError, remoting.Error.AUTHENTICATION_FAILED); | |
166 }); | |
167 | |
168 test('should return UNEXPECTED error when failed to parse stream', | |
169 function() { | |
170 handshakeBase(); | |
171 loginHandler.onDataReceived( | |
172 base.encodeUtf8('BAD DATA')); | |
173 sinon.assert.calledWith(onError, remoting.Error.UNEXPECTED); | |
174 }); | |
175 | |
176 })(); | |
OLD | NEW |