| 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 |