Home | History | Annotate | Download | only in unittests
      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 (a] gmail.com';
     10 var testToken = 'testToken';
     11 
     12 var sendMessage = null;
     13 var startTls = null;
     14 var onHandshakeDone = null;
     15 var onStanzaStr = null;
     16 var onError = null;
     17 var loginHandler = null;
     18 
     19 module('XmppLoginHandler', {
     20   setup: function() {
     21     sendMessage = sinon.spy();
     22     startTls = sinon.spy();
     23     onHandshakeDone = sinon.spy();
     24     onStanzaStr = sinon.spy();
     25     onError = sinon.spy();
     26     function onStanza(stanza) {
     27       onStanzaStr(new XMLSerializer().serializeToString(stanza));
     28     }
     29     loginHandler = new remoting.XmppLoginHandler(
     30         'google.com', testUsername, testToken, sendMessage, startTls,
     31         onHandshakeDone, onError);
     32   }
     33 });
     34 
     35 // Executes handshake base.
     36 function handshakeBase() {
     37   loginHandler.start();
     38   sinon.assert.calledWith(
     39       sendMessage,
     40       '<stream:stream to="google.com" version="1.0" xmlns="jabber:client" ' +
     41           'xmlns:stream="http://etherx.jabber.org/streams">' +
     42           '<starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"/>');
     43   sendMessage.reset();
     44 
     45   loginHandler.onDataReceived(base.encodeUtf8(
     46       '<stream:stream from="google.com" id="78A87C70559EF28A" version="1.0" ' +
     47           'xmlns:stream="http://etherx.jabber.org/streams"' +
     48           'xmlns="jabber:client">' +
     49         '<stream:features>' +
     50           '<starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls">' +
     51             '<required/>' +
     52           '</starttls>' +
     53           '<mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">' +
     54             '<mechanism>X-OAUTH2</mechanism>' +
     55             '<mechanism>X-GOOGLE-TOKEN</mechanism>' +
     56           '</mechanisms>' +
     57         '</stream:features>'));
     58 
     59   loginHandler.onDataReceived(
     60       base.encodeUtf8('<proceed xmlns="urn:ietf:params:xml:ns:xmpp-tls"/>'));
     61   sinon.assert.calledWith(startTls);
     62   startTls.reset();
     63 
     64   loginHandler.onTlsStarted();
     65   var cookie = window.btoa("\0" + testUsername + "\0" + testToken);
     66   sinon.assert.calledWith(
     67       sendMessage,
     68       '<stream:stream to="google.com" version="1.0" xmlns="jabber:client" ' +
     69           'xmlns:stream="http://etherx.jabber.org/streams">' +
     70       '<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="X-OAUTH2" ' +
     71           'auth:service="oauth2" auth:allow-generated-jid="true" ' +
     72           'auth:client-uses-full-bind-result="true" ' +
     73           'auth:allow-non-google-login="true" ' +
     74           'xmlns:auth="http://www.google.com/talk/protocol/auth">' + cookie +
     75       '</auth>');
     76   sendMessage.reset();
     77 
     78   loginHandler.onDataReceived(base.encodeUtf8(
     79       '<stream:stream from="google.com" id="DCDDE5171CB2154A" version="1.0" ' +
     80           'xmlns:stream="http://etherx.jabber.org/streams" ' +
     81           'xmlns="jabber:client">' +
     82         '<stream:features>' +
     83           '<mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">' +
     84             '<mechanism>X-OAUTH2</mechanism>' +
     85             '<mechanism>X-GOOGLE-TOKEN</mechanism>' +
     86             '<mechanism>PLAIN</mechanism>' +
     87           '</mechanisms>' +
     88         '</stream:features>'));
     89 }
     90 
     91 test('should authenticate', function() {
     92   handshakeBase();
     93 
     94   loginHandler.onDataReceived(
     95       base.encodeUtf8('<success xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/>'));
     96   sinon.assert.calledWith(
     97       sendMessage,
     98       '<stream:stream to="google.com" version="1.0" xmlns="jabber:client" ' +
     99           'xmlns:stream="http://etherx.jabber.org/streams">' +
    100         '<iq type="set" id="0">' +
    101           '<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">' +
    102             '<resource>chromoting</resource>' +
    103           '</bind>' +
    104         '</iq>' +
    105         '<iq type="set" id="1">' +
    106           '<session xmlns="urn:ietf:params:xml:ns:xmpp-session"/>' +
    107         '</iq>');
    108   sendMessage.reset();
    109 
    110   loginHandler.onDataReceived(base.encodeUtf8(
    111       '<stream:stream from="google.com" id="104FA10576E2AA80" version="1.0" ' +
    112           'xmlns:stream="http://etherx.jabber.org/streams" ' +
    113           'xmlns="jabber:client">' +
    114         '<stream:features>' +
    115           '<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/>' +
    116           '<session xmlns="urn:ietf:params:xml:ns:xmpp-session"/>' +
    117         '</stream:features>' +
    118         '<iq id="0" type="result">' +
    119           '<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">' +
    120             '<jid>' + testUsername + '/chromoting52B4920E</jid>' +
    121           '</bind>' +
    122         '</iq>' +
    123         '<iq type="result" id="1"/>'));
    124 
    125   sinon.assert.calledWith(onHandshakeDone);
    126 });
    127 
    128 test('should return AUTHENTICATION_FAILED error when failed to authenticate',
    129      function() {
    130   handshakeBase();
    131 
    132   loginHandler.onDataReceived(
    133       base.encodeUtf8('<failure xmlns="urn:ietf:params:xml:ns:xmpp-sasl">' +
    134                       '<not-authorized/></failure>'));
    135   sinon.assert.calledWith(onError, remoting.Error.AUTHENTICATION_FAILED);
    136 });
    137 
    138 test('should return UNEXPECTED error when failed to parse stream',
    139      function() {
    140   loginHandler.start();
    141   loginHandler.onDataReceived(
    142       base.encodeUtf8('BAD DATA'));
    143   sinon.assert.calledWith(onError, remoting.Error.UNEXPECTED);
    144 });
    145 
    146 })();
    147