1 // Copyright 2015 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.
5 #include "remoting/signaling/xmpp_login_handler.h"
7 #include "base/base64.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/run_loop.h"
10 #include "remoting/signaling/xmpp_stream_parser.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "third_party/webrtc/libjingle/xmllite/xmlelement.h"
24 char kTestUsername
[] = "testUsername@gmail.com";
25 char kTestToken
[] = "testToken";
27 class XmppLoginHandlerTest
: public testing::Test
,
28 public XmppLoginHandler::Delegate
{
30 XmppLoginHandlerTest()
31 : start_tls_called_(false), error_(SignalStrategy::OK
) {}
33 void TearDown() override
{
34 login_handler_
.reset();
36 base::RunLoop().RunUntilIdle();
39 void SendMessage(const std::string
& message
) override
{
40 sent_data_
+= message
;
43 void StartTls() override
{
44 start_tls_called_
= true;
47 void OnHandshakeDone(const std::string
& jid
,
48 scoped_ptr
<XmppStreamParser
> parser
) override
{
50 parser_
= parser
.Pass();
53 void OnLoginHandlerError(SignalStrategy::Error error
) override
{
54 EXPECT_NE(error
, SignalStrategy::OK
);
61 base::MessageLoop message_loop_
;
63 scoped_ptr
<XmppLoginHandler
> login_handler_
;
64 std::string sent_data_
;
65 bool start_tls_called_
;
67 scoped_ptr
<XmppStreamParser
> parser_
;
68 SignalStrategy::Error error_
;
71 void XmppLoginHandlerTest::HandshakeBase() {
73 new XmppLoginHandler("google.com", kTestUsername
, kTestToken
,
74 XmppLoginHandler::TlsMode::WITHOUT_HANDSHAKE
, this));
75 login_handler_
->Start();
76 EXPECT_TRUE(start_tls_called_
);
78 login_handler_
->OnTlsStarted();
81 std::string("\0", 1) + kTestUsername
+ std::string("\0", 1) + kTestToken
,
85 "<stream:stream to=\"google.com\" version=\"1.0\" "
86 "xmlns=\"jabber:client\" "
87 "xmlns:stream=\"http://etherx.jabber.org/streams\">"
88 "<auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" mechanism=\"X-OAUTH2\" "
89 "auth:service=\"oauth2\" auth:allow-generated-jid=\"true\" "
90 "auth:client-uses-full-bind-result=\"true\" "
91 "auth:allow-non-google-login=\"true\" "
92 "xmlns:auth=\"http://www.google.com/talk/protocol/auth\">" + cookie
+
96 login_handler_
->OnDataReceived(
97 "<stream:stream from=\"google.com\" id=\"DCDDE5171CB2154A\" "
99 "xmlns:stream=\"http://etherx.jabber.org/streams\" "
100 "xmlns=\"jabber:client\">"
102 "<mechanisms xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">"
103 "<mechanism>X-OAUTH2</mechanism>"
104 "<mechanism>X-GOOGLE-TOKEN</mechanism>"
105 "<mechanism>PLAIN</mechanism>"
107 "</stream:features>");
110 TEST_F(XmppLoginHandlerTest
, SuccessfulAuth
) {
113 login_handler_
->OnDataReceived(
114 "<success xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\"/>");
117 "<stream:stream to=\"google.com\" version=\"1.0\" "
118 "xmlns=\"jabber:client\" "
119 "xmlns:stream=\"http://etherx.jabber.org/streams\">"
120 "<iq type=\"set\" id=\"0\">"
121 "<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\">"
122 "<resource>chromoting</resource>"
125 "<iq type=\"set\" id=\"1\">"
126 "<session xmlns=\"urn:ietf:params:xml:ns:xmpp-session\"/>"
130 login_handler_
->OnDataReceived(
131 "<stream:stream from=\"google.com\" id=\"104FA10576E2AA80\" "
133 "xmlns:stream=\"http://etherx.jabber.org/streams\" "
134 "xmlns=\"jabber:client\">"
136 "<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\"/>"
137 "<session xmlns=\"urn:ietf:params:xml:ns:xmpp-session\"/>"
139 "<iq id=\"0\" type=\"result\">"
140 "<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\">"
141 "<jid>" + std::string(kTestUsername
) + "/chromoting52B4920E</jid>"
144 "<iq type=\"result\" id=\"1\"/>");
146 EXPECT_EQ(jid_
, std::string(kTestUsername
) + "/chromoting52B4920E");
147 EXPECT_TRUE(parser_
);
150 TEST_F(XmppLoginHandlerTest
, StartTlsHandshake
) {
151 login_handler_
.reset(
152 new XmppLoginHandler("google.com", kTestUsername
, kTestToken
,
153 XmppLoginHandler::TlsMode::WITH_HANDSHAKE
, this));
154 login_handler_
->Start();
155 EXPECT_FALSE(start_tls_called_
);
157 EXPECT_EQ(sent_data_
,
158 "<stream:stream to=\"google.com\" version=\"1.0\" "
159 "xmlns=\"jabber:client\" "
160 "xmlns:stream=\"http://etherx.jabber.org/streams\">"
161 "<starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"/>");
164 login_handler_
->OnDataReceived(
165 "<stream:stream from=\"google.com\" id=\"78A87C70559EF28A\" "
167 "xmlns:stream=\"http://etherx.jabber.org/streams\" "
168 "xmlns=\"jabber:client\">"
170 "<starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\">"
173 "<mechanisms xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">"
174 "<mechanism>X-OAUTH2</mechanism>"
175 "<mechanism>X-GOOGLE-TOKEN</mechanism>"
177 "</stream:features>");
179 login_handler_
->OnDataReceived(
180 "<proceed xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"/>");
181 EXPECT_TRUE(start_tls_called_
);
184 TEST_F(XmppLoginHandlerTest
, AuthError
) {
187 login_handler_
->OnDataReceived(
188 "<failure xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">"
189 "<not-authorized/></failure>");
190 EXPECT_EQ(error_
, SignalStrategy::AUTHENTICATION_FAILED
);
193 TEST_F(XmppLoginHandlerTest
, NoTls
) {
194 login_handler_
.reset(
195 new XmppLoginHandler("google.com", kTestUsername
, kTestToken
,
196 XmppLoginHandler::TlsMode::NO_TLS
, this));
197 login_handler_
->Start();
199 EXPECT_FALSE(start_tls_called_
);
202 std::string("\0", 1) + kTestUsername
+ std::string("\0", 1) + kTestToken
,
206 "<stream:stream to=\"google.com\" version=\"1.0\" "
207 "xmlns=\"jabber:client\" "
208 "xmlns:stream=\"http://etherx.jabber.org/streams\">"
209 "<auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" mechanism=\"X-OAUTH2\" "
210 "auth:service=\"oauth2\" auth:allow-generated-jid=\"true\" "
211 "auth:client-uses-full-bind-result=\"true\" "
212 "auth:allow-non-google-login=\"true\" "
213 "xmlns:auth=\"http://www.google.com/talk/protocol/auth\">" + cookie
+
217 TEST_F(XmppLoginHandlerTest
, StreamParseError
) {
219 login_handler_
->OnDataReceived("BAD DATA");
220 EXPECT_EQ(error_
, SignalStrategy::PROTOCOL_ERROR
);
223 } // namespace remoting