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
;
41 if (delete_login_handler_from_delegate_
)
42 login_handler_
.reset();
45 void StartTls() override
{
46 start_tls_called_
= true;
47 if (delete_login_handler_from_delegate_
)
48 login_handler_
.reset();
51 void OnHandshakeDone(const std::string
& jid
,
52 scoped_ptr
<XmppStreamParser
> parser
) override
{
54 parser_
= parser
.Pass();
55 if (delete_login_handler_from_delegate_
)
56 login_handler_
.reset();
59 void OnLoginHandlerError(SignalStrategy::Error error
) override
{
60 EXPECT_NE(error
, SignalStrategy::OK
);
62 if (delete_login_handler_from_delegate_
)
63 login_handler_
.reset();
69 base::MessageLoop message_loop_
;
71 scoped_ptr
<XmppLoginHandler
> login_handler_
;
72 std::string sent_data_
;
73 bool start_tls_called_
;
75 scoped_ptr
<XmppStreamParser
> parser_
;
76 SignalStrategy::Error error_
;
77 bool delete_login_handler_from_delegate_
= false;
80 void XmppLoginHandlerTest::HandshakeBase() {
82 new XmppLoginHandler("google.com", kTestUsername
, kTestToken
,
83 XmppLoginHandler::TlsMode::WITHOUT_HANDSHAKE
, this));
84 login_handler_
->Start();
85 EXPECT_TRUE(start_tls_called_
);
87 login_handler_
->OnTlsStarted();
90 std::string("\0", 1) + kTestUsername
+ std::string("\0", 1) + kTestToken
,
94 "<stream:stream to=\"google.com\" version=\"1.0\" "
95 "xmlns=\"jabber:client\" "
96 "xmlns:stream=\"http://etherx.jabber.org/streams\">"
97 "<auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" mechanism=\"X-OAUTH2\" "
98 "auth:service=\"oauth2\" auth:allow-generated-jid=\"true\" "
99 "auth:client-uses-full-bind-result=\"true\" "
100 "auth:allow-non-google-login=\"true\" "
101 "xmlns:auth=\"http://www.google.com/talk/protocol/auth\">" + cookie
+
105 login_handler_
->OnDataReceived(
106 "<stream:stream from=\"google.com\" id=\"DCDDE5171CB2154A\" "
108 "xmlns:stream=\"http://etherx.jabber.org/streams\" "
109 "xmlns=\"jabber:client\">"
111 "<mechanisms xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">"
112 "<mechanism>X-OAUTH2</mechanism>"
113 "<mechanism>X-GOOGLE-TOKEN</mechanism>"
114 "<mechanism>PLAIN</mechanism>"
116 "</stream:features>");
119 TEST_F(XmppLoginHandlerTest
, SuccessfulAuth
) {
122 login_handler_
->OnDataReceived(
123 "<success xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\"/>");
126 "<stream:stream to=\"google.com\" version=\"1.0\" "
127 "xmlns=\"jabber:client\" "
128 "xmlns:stream=\"http://etherx.jabber.org/streams\">"
129 "<iq type=\"set\" id=\"0\">"
130 "<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\">"
131 "<resource>chromoting</resource>"
134 "<iq type=\"set\" id=\"1\">"
135 "<session xmlns=\"urn:ietf:params:xml:ns:xmpp-session\"/>"
139 // |login_handler_| will call OnHandshakeDone() which will delete
141 delete_login_handler_from_delegate_
= true;
143 login_handler_
->OnDataReceived(
144 "<stream:stream from=\"google.com\" id=\"104FA10576E2AA80\" "
146 "xmlns:stream=\"http://etherx.jabber.org/streams\" "
147 "xmlns=\"jabber:client\">"
149 "<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\"/>"
150 "<session xmlns=\"urn:ietf:params:xml:ns:xmpp-session\"/>"
152 "<iq id=\"0\" type=\"result\">"
153 "<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\">"
154 "<jid>" + std::string(kTestUsername
) + "/chromoting52B4920E</jid>"
157 "<iq type=\"result\" id=\"1\"/>");
159 EXPECT_EQ(jid_
, std::string(kTestUsername
) + "/chromoting52B4920E");
160 EXPECT_TRUE(parser_
);
161 EXPECT_FALSE(login_handler_
);
164 TEST_F(XmppLoginHandlerTest
, StartTlsHandshake
) {
165 login_handler_
.reset(
166 new XmppLoginHandler("google.com", kTestUsername
, kTestToken
,
167 XmppLoginHandler::TlsMode::WITH_HANDSHAKE
, this));
168 login_handler_
->Start();
169 EXPECT_FALSE(start_tls_called_
);
171 EXPECT_EQ(sent_data_
,
172 "<stream:stream to=\"google.com\" version=\"1.0\" "
173 "xmlns=\"jabber:client\" "
174 "xmlns:stream=\"http://etherx.jabber.org/streams\">"
175 "<starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"/>");
178 login_handler_
->OnDataReceived(
179 "<stream:stream from=\"google.com\" id=\"78A87C70559EF28A\" "
181 "xmlns:stream=\"http://etherx.jabber.org/streams\" "
182 "xmlns=\"jabber:client\">"
184 "<starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\">"
187 "<mechanisms xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">"
188 "<mechanism>X-OAUTH2</mechanism>"
189 "<mechanism>X-GOOGLE-TOKEN</mechanism>"
191 "</stream:features>");
193 login_handler_
->OnDataReceived(
194 "<proceed xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"/>");
195 EXPECT_TRUE(start_tls_called_
);
198 TEST_F(XmppLoginHandlerTest
, AuthError
) {
201 login_handler_
->OnDataReceived(
202 "<failure xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">"
203 "<not-authorized/></failure>");
204 EXPECT_EQ(error_
, SignalStrategy::AUTHENTICATION_FAILED
);
207 TEST_F(XmppLoginHandlerTest
, NoTls
) {
208 login_handler_
.reset(
209 new XmppLoginHandler("google.com", kTestUsername
, kTestToken
,
210 XmppLoginHandler::TlsMode::NO_TLS
, this));
211 login_handler_
->Start();
213 EXPECT_FALSE(start_tls_called_
);
216 std::string("\0", 1) + kTestUsername
+ std::string("\0", 1) + kTestToken
,
220 "<stream:stream to=\"google.com\" version=\"1.0\" "
221 "xmlns=\"jabber:client\" "
222 "xmlns:stream=\"http://etherx.jabber.org/streams\">"
223 "<auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" mechanism=\"X-OAUTH2\" "
224 "auth:service=\"oauth2\" auth:allow-generated-jid=\"true\" "
225 "auth:client-uses-full-bind-result=\"true\" "
226 "auth:allow-non-google-login=\"true\" "
227 "xmlns:auth=\"http://www.google.com/talk/protocol/auth\">" + cookie
+
231 TEST_F(XmppLoginHandlerTest
, StreamParseError
) {
233 delete_login_handler_from_delegate_
= true;
234 login_handler_
->OnDataReceived("BAD DATA");
235 EXPECT_EQ(error_
, SignalStrategy::PROTOCOL_ERROR
);
238 // Verify that LoginHandler doesn't crash when destroyed from
239 // Delegate::SendMessage().
240 TEST_F(XmppLoginHandlerTest
, DeleteInSendMessage
) {
241 login_handler_
.reset(
242 new XmppLoginHandler("google.com", kTestUsername
, kTestToken
,
243 XmppLoginHandler::TlsMode::WITHOUT_HANDSHAKE
, this));
244 login_handler_
->Start();
245 EXPECT_TRUE(start_tls_called_
);
247 delete_login_handler_from_delegate_
= true;
248 login_handler_
->OnTlsStarted();
249 EXPECT_FALSE(login_handler_
);
252 // Verify that LoginHandler doesn't crash when destroyed from
253 // Delegate::StartTls().
254 TEST_F(XmppLoginHandlerTest
, DeleteInStartTls
) {
255 login_handler_
.reset(
256 new XmppLoginHandler("google.com", kTestUsername
, kTestToken
,
257 XmppLoginHandler::TlsMode::WITHOUT_HANDSHAKE
, this));
258 delete_login_handler_from_delegate_
= true;
259 login_handler_
->Start();
260 EXPECT_TRUE(start_tls_called_
);
261 EXPECT_FALSE(login_handler_
);
264 } // namespace remoting