| Index: remoting/webapp/unittests/xmpp_login_handler_unittest.js
|
| diff --git a/remoting/webapp/unittests/xmpp_login_handler_unittest.js b/remoting/webapp/unittests/xmpp_login_handler_unittest.js
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..339ceba3cc78e7dcd69ebf41cd66b01afadae3ef
|
| --- /dev/null
|
| +++ b/remoting/webapp/unittests/xmpp_login_handler_unittest.js
|
| @@ -0,0 +1,142 @@
|
| +// Copyright 2014 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +(function() {
|
| +
|
| +'use strict';
|
| +
|
| +var testUsername = 'testUsername@gmail.com';
|
| +var testToken = 'testToken';
|
| +
|
| +var sendMessage = null;
|
| +var startTls = null;
|
| +var onHandshakeDone = null;
|
| +var onStanzaStr = null;
|
| +var onError = null;
|
| +var loginHandler = null;
|
| +
|
| +module('XmppLoginHandler', {
|
| + setup: function() {
|
| + sendMessage = sinon.spy();
|
| + startTls = sinon.spy();
|
| + onHandshakeDone = sinon.spy();
|
| + onStanzaStr = sinon.spy();
|
| + onError = sinon.spy();
|
| + function onStanza(stanza) {
|
| + onStanzaStr(new XMLSerializer().serializeToString(stanza));
|
| + }
|
| + loginHandler = new remoting.XmppLoginHandler(
|
| + 'google.com', testUsername, testToken, sendMessage, startTls,
|
| + onHandshakeDone, onError);
|
| + }
|
| +});
|
| +
|
| +// Executes handshake base.
|
| +function handshakeBase() {
|
| + loginHandler.start();
|
| + sinon.assert.calledWith(
|
| + sendMessage,
|
| + '<stream:stream to="google.com" version="1.0" xmlns="jabber:client" ' +
|
| + 'xmlns:stream="http://etherx.jabber.org/streams">');
|
| + sendMessage.reset();
|
| +
|
| + loginHandler.onDataReceived(base.encodeUtf8(
|
| + '<stream:stream from="google.com" id="78A87C70559EF28A" version="1.0" ' +
|
| + 'xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client">' +
|
| + '<stream:features><starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls">' +
|
| + '<required/></starttls><mechanisms ' +
|
| + 'xmlns="urn:ietf:params:xml:ns:xmpp-sasl">' +
|
| + '<mechanism>X-OAUTH2</mechanism><mechanism>X-GOOGLE-TOKEN</mechanism>' +
|
| + '</mechanisms></stream:features>'));
|
| + sinon.assert.calledWith(
|
| + sendMessage, '<starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"/>');
|
| + sendMessage.reset();
|
| +
|
| + loginHandler.onDataReceived(
|
| + base.encodeUtf8('<proceed xmlns="urn:ietf:params:xml:ns:xmpp-tls"/>'));
|
| + sinon.assert.calledWith(startTls);
|
| + startTls.reset();
|
| +
|
| + loginHandler.onTlsStarted();
|
| + sinon.assert.calledWith(
|
| + sendMessage,
|
| + '<stream:stream to="google.com" version="1.0" xmlns="jabber:client" ' +
|
| + 'xmlns:stream="http://etherx.jabber.org/streams">');
|
| + sendMessage.reset();
|
| +
|
| + loginHandler.onDataReceived(base.encodeUtf8(
|
| + '<stream:stream from="google.com" id="DCDDE5171CB2154A" version="1.0" ' +
|
| + 'xmlns:stream="http://etherx.jabber.org/streams" ' +
|
| + 'xmlns="jabber:client"><stream:features>' +
|
| + '<mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">' +
|
| + '<mechanism>X-OAUTH2</mechanism><mechanism>X-GOOGLE-TOKEN</mechanism>' +
|
| + '<mechanism>PLAIN</mechanism></mechanisms></stream:features>'));
|
| + var cookie = window.btoa("\0" + testUsername + "\0" + testToken);
|
| + sinon.assert.calledWith(
|
| + sendMessage,
|
| + '<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="X-OAUTH2" ' +
|
| + 'auth:service="oauth2" auth:allow-generated-jid="true" ' +
|
| + 'auth:client-uses-full-bind-result="true" ' +
|
| + 'auth:allow-non-google-login="true" ' +
|
| + 'xmlns:auth="http://www.google.com/talk/protocol/auth">' + cookie +
|
| + '</auth>');
|
| + sendMessage.reset();
|
| +}
|
| +
|
| +test('should authenticate', function() {
|
| + handshakeBase();
|
| +
|
| + loginHandler.onDataReceived(
|
| + base.encodeUtf8('<success xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/>'));
|
| + sinon.assert.calledWith(
|
| + sendMessage,
|
| + '<stream:stream to="google.com" version="1.0" xmlns="jabber:client" ' +
|
| + 'xmlns:stream="http://etherx.jabber.org/streams">');
|
| + sendMessage.reset();
|
| +
|
| + loginHandler.onDataReceived(base.encodeUtf8(
|
| + '<stream:stream from="google.com" id="104FA10576E2AA80" version="1.0" ' +
|
| + 'xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client">' +
|
| + '<stream:features><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/>' +
|
| + '<session xmlns="urn:ietf:params:xml:ns:xmpp-session"/>' +
|
| + '</stream:features>'));
|
| + sinon.assert.calledWith(
|
| + sendMessage,
|
| + '<iq type="set" id="0"><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">' +
|
| + '<resource>chromoting</resource></bind></iq>');
|
| + sendMessage.reset();
|
| +
|
| + loginHandler.onDataReceived(
|
| + base.encodeUtf8('<iq id="0" type="result">' +
|
| + '<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"><jid>' +
|
| + testUsername + '/chromoting52B4920E</jid></bind></iq>'));
|
| + sinon.assert.calledWith(
|
| + sendMessage,
|
| + '<iq type="set" id="1"><session ' +
|
| + 'xmlns="urn:ietf:params:xml:ns:xmpp-session"/></iq>');
|
| + sendMessage.reset();
|
| +
|
| + loginHandler.onDataReceived(base.encodeUtf8('<iq type="result" id="1"/>'));
|
| + sinon.assert.calledWith(onHandshakeDone);
|
| +});
|
| +
|
| +test('should return AUTHENTICATION_FAILED error when failed to authenticate',
|
| + function() {
|
| + handshakeBase();
|
| +
|
| + loginHandler.onDataReceived(
|
| + base.encodeUtf8('<failure xmlns="urn:ietf:params:xml:ns:xmpp-sasl">' +
|
| + '<not-authorized/></failure>'));
|
| + sinon.assert.calledWith(onError, remoting.Error.AUTHENTICATION_FAILED);
|
| +});
|
| +
|
| +test('should return UNEXPECTED error when failed to parse stream',
|
| + function() {
|
| + loginHandler.start();
|
| + loginHandler.onDataReceived(
|
| + base.encodeUtf8('BAD DATA'));
|
| + sinon.assert.calledWith(onError, remoting.Error.UNEXPECTED);
|
| +});
|
| +
|
| +})();
|
|
|