blob: 4375a4341a8def4776a410c54468975440c74d3e [file] [log] [blame]
tengs0fe21e22015-09-22 01:18:401// 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#include "components/proximity_auth/messenger_impl.h"
6
7#include "base/callback.h"
8#include "base/macros.h"
9#include "base/memory/scoped_ptr.h"
10#include "components/proximity_auth/connection.h"
tengs61a7c1022015-09-24 23:24:3711#include "components/proximity_auth/fake_connection.h"
tengs1d939ea2015-10-29 20:10:3312#include "components/proximity_auth/fake_secure_context.h"
tengs0fe21e22015-09-22 01:18:4013#include "components/proximity_auth/messenger_observer.h"
tengsae50e972015-10-02 04:00:4014#include "components/proximity_auth/proximity_auth_test_util.h"
tengs0fe21e22015-09-22 01:18:4015#include "components/proximity_auth/remote_device.h"
16#include "components/proximity_auth/remote_status_update.h"
tengs0fe21e22015-09-22 01:18:4017#include "components/proximity_auth/wire_message.h"
18#include "testing/gmock/include/gmock/gmock.h"
19#include "testing/gtest/include/gtest/gtest.h"
20
21using testing::_;
22using testing::AllOf;
tengs0fe21e22015-09-22 01:18:4023using testing::Eq;
24using testing::Field;
25using testing::NiceMock;
26using testing::Pointee;
27using testing::Return;
28using testing::StrictMock;
29
30namespace proximity_auth {
31namespace {
32
33const char kChallenge[] = "a most difficult challenge";
tengs0fe21e22015-09-22 01:18:4034
tengs0fe21e22015-09-22 01:18:4035class MockMessengerObserver : public MessengerObserver {
36 public:
37 explicit MockMessengerObserver(Messenger* messenger) : messenger_(messenger) {
38 messenger_->AddObserver(this);
39 }
40 virtual ~MockMessengerObserver() { messenger_->RemoveObserver(this); }
41
42 MOCK_METHOD1(OnUnlockEventSent, void(bool success));
43 MOCK_METHOD1(OnRemoteStatusUpdate,
44 void(const RemoteStatusUpdate& status_update));
45 MOCK_METHOD1(OnDecryptResponseProxy,
tengsa85897c22015-10-29 01:12:0046 void(const std::string& decrypted_bytes));
tengs0fe21e22015-09-22 01:18:4047 MOCK_METHOD1(OnUnlockResponse, void(bool success));
48 MOCK_METHOD0(OnDisconnected, void());
49
tengsa85897c22015-10-29 01:12:0050 virtual void OnDecryptResponse(const std::string& decrypted_bytes) {
51 OnDecryptResponseProxy(decrypted_bytes);
tengs0fe21e22015-09-22 01:18:4052 }
53
54 private:
55 // The messenger that |this| instance observes.
56 Messenger* const messenger_;
57
58 DISALLOW_COPY_AND_ASSIGN(MockMessengerObserver);
59};
60
61class TestMessenger : public MessengerImpl {
62 public:
63 TestMessenger()
tengsae50e972015-10-02 04:00:4064 : MessengerImpl(make_scoped_ptr(new FakeConnection(
65 CreateClassicRemoteDeviceForTest())),
tengs1d939ea2015-10-29 20:10:3366 make_scoped_ptr(new FakeSecureContext())) {}
tengs0fe21e22015-09-22 01:18:4067 ~TestMessenger() override {}
68
69 // Simple getters for the mock objects owned by |this| messenger.
70 FakeConnection* GetFakeConnection() {
71 return static_cast<FakeConnection*>(connection());
72 }
tengs1d939ea2015-10-29 20:10:3373 FakeSecureContext* GetFakeSecureContext() {
74 return static_cast<FakeSecureContext*>(GetSecureContext());
tengs0fe21e22015-09-22 01:18:4075 }
76
77 private:
78 DISALLOW_COPY_AND_ASSIGN(TestMessenger);
79};
80
81} // namespace
82
83TEST(ProximityAuthMessengerImplTest, SupportsSignIn_ProtocolVersionThreeZero) {
84 TestMessenger messenger;
tengs1d939ea2015-10-29 20:10:3385 messenger.GetFakeSecureContext()->set_protocol_version(
86 SecureContext::PROTOCOL_VERSION_THREE_ZERO);
tengs0fe21e22015-09-22 01:18:4087 EXPECT_FALSE(messenger.SupportsSignIn());
88}
89
90TEST(ProximityAuthMessengerImplTest, SupportsSignIn_ProtocolVersionThreeOne) {
91 TestMessenger messenger;
tengs1d939ea2015-10-29 20:10:3392 messenger.GetFakeSecureContext()->set_protocol_version(
93 SecureContext::PROTOCOL_VERSION_THREE_ONE);
tengs0fe21e22015-09-22 01:18:4094 EXPECT_TRUE(messenger.SupportsSignIn());
95}
96
97TEST(ProximityAuthMessengerImplTest,
98 OnConnectionStatusChanged_ConnectionDisconnects) {
99 TestMessenger messenger;
100 MockMessengerObserver observer(&messenger);
101
102 EXPECT_CALL(observer, OnDisconnected());
103 messenger.GetFakeConnection()->Disconnect();
104}
105
106TEST(ProximityAuthMessengerImplTest, DispatchUnlockEvent_SendsExpectedMessage) {
107 TestMessenger messenger;
108 messenger.DispatchUnlockEvent();
109
110 WireMessage* message = messenger.GetFakeConnection()->current_message();
111 ASSERT_TRUE(message);
112 EXPECT_EQ(std::string(), message->permit_id());
113 EXPECT_EQ(
114 "{"
115 "\"name\":\"easy_unlock\","
116 "\"type\":\"event\""
117 "}, but encoded",
118 message->payload());
119}
120
121TEST(ProximityAuthMessengerImplTest, DispatchUnlockEvent_SendMessageFails) {
122 TestMessenger messenger;
123 MockMessengerObserver observer(&messenger);
124 messenger.DispatchUnlockEvent();
125
126 EXPECT_CALL(observer, OnUnlockEventSent(false));
127 messenger.GetFakeConnection()->FinishSendingMessageWithSuccess(false);
128}
129
130TEST(ProximityAuthMessengerImplTest, DispatchUnlockEvent_SendMessageSucceeds) {
131 TestMessenger messenger;
132 MockMessengerObserver observer(&messenger);
133 messenger.DispatchUnlockEvent();
134
135 EXPECT_CALL(observer, OnUnlockEventSent(true));
136 messenger.GetFakeConnection()->FinishSendingMessageWithSuccess(true);
137}
138
139TEST(ProximityAuthMessengerImplTest,
140 RequestDecryption_SignInUnsupported_DoesntSendMessage) {
141 TestMessenger messenger;
tengs1d939ea2015-10-29 20:10:33142 messenger.GetFakeSecureContext()->set_protocol_version(
143 SecureContext::PROTOCOL_VERSION_THREE_ZERO);
tengs0fe21e22015-09-22 01:18:40144 messenger.RequestDecryption(kChallenge);
145 EXPECT_FALSE(messenger.GetFakeConnection()->current_message());
146}
147
148TEST(ProximityAuthMessengerImplTest, RequestDecryption_SendsExpectedMessage) {
149 TestMessenger messenger;
150 messenger.RequestDecryption(kChallenge);
151
152 WireMessage* message = messenger.GetFakeConnection()->current_message();
153 ASSERT_TRUE(message);
154 EXPECT_EQ(std::string(), message->permit_id());
155 EXPECT_EQ(
156 "{"
157 "\"encrypted_data\":\"YSBtb3N0IGRpZmZpY3VsdCBjaGFsbGVuZ2U=\","
158 "\"type\":\"decrypt_request\""
159 "}, but encoded",
160 message->payload());
161}
162
163TEST(ProximityAuthMessengerImplTest,
164 RequestDecryption_SendsExpectedMessage_UsingBase64UrlEncoding) {
165 TestMessenger messenger;
166 messenger.RequestDecryption("\xFF\xE6");
167
168 WireMessage* message = messenger.GetFakeConnection()->current_message();
169 ASSERT_TRUE(message);
170 EXPECT_EQ(std::string(), message->permit_id());
171 EXPECT_EQ(
172 "{"
173 "\"encrypted_data\":\"_-Y=\","
174 "\"type\":\"decrypt_request\""
175 "}, but encoded",
176 message->payload());
177}
178
179TEST(ProximityAuthMessengerImplTest, RequestDecryption_SendMessageFails) {
180 TestMessenger messenger;
181 MockMessengerObserver observer(&messenger);
182 messenger.RequestDecryption(kChallenge);
183
tengsa85897c22015-10-29 01:12:00184 EXPECT_CALL(observer, OnDecryptResponseProxy(std::string()));
tengs0fe21e22015-09-22 01:18:40185 messenger.GetFakeConnection()->FinishSendingMessageWithSuccess(false);
186}
187
188TEST(ProximityAuthMessengerImplTest,
189 RequestDecryption_SendSucceeds_WaitsForReply) {
190 TestMessenger messenger;
191 MockMessengerObserver observer(&messenger);
192 messenger.RequestDecryption(kChallenge);
193
194 EXPECT_CALL(observer, OnDecryptResponseProxy(_)).Times(0);
195 messenger.GetFakeConnection()->FinishSendingMessageWithSuccess(true);
196}
197
198TEST(ProximityAuthMessengerImplTest,
199 RequestDecryption_SendSucceeds_NotifiesObserversOnReply_NoData) {
200 TestMessenger messenger;
201 MockMessengerObserver observer(&messenger);
202 messenger.RequestDecryption(kChallenge);
203 messenger.GetFakeConnection()->FinishSendingMessageWithSuccess(true);
204
tengsa85897c22015-10-29 01:12:00205 EXPECT_CALL(observer, OnDecryptResponseProxy(std::string()));
tengs0fe21e22015-09-22 01:18:40206 messenger.GetFakeConnection()->ReceiveMessageWithPayload(
207 "{\"type\":\"decrypt_response\"}, but encoded");
208}
209
210TEST(ProximityAuthMessengerImplTest,
211 RequestDecryption_SendSucceeds_NotifiesObserversOnReply_InvalidData) {
212 TestMessenger messenger;
213 MockMessengerObserver observer(&messenger);
214 messenger.RequestDecryption(kChallenge);
215 messenger.GetFakeConnection()->FinishSendingMessageWithSuccess(true);
216
tengsa85897c22015-10-29 01:12:00217 EXPECT_CALL(observer, OnDecryptResponseProxy(std::string()));
tengs0fe21e22015-09-22 01:18:40218 messenger.GetFakeConnection()->ReceiveMessageWithPayload(
219 "{"
220 "\"type\":\"decrypt_response\","
221 "\"data\":\"not a base64-encoded string\""
222 "}, but encoded");
223}
224
225TEST(ProximityAuthMessengerImplTest,
226 RequestDecryption_SendSucceeds_NotifiesObserversOnReply_ValidData) {
227 TestMessenger messenger;
228 MockMessengerObserver observer(&messenger);
229 messenger.RequestDecryption(kChallenge);
230 messenger.GetFakeConnection()->FinishSendingMessageWithSuccess(true);
231
tengsa85897c22015-10-29 01:12:00232 EXPECT_CALL(observer, OnDecryptResponseProxy("a winner is you"));
tengs0fe21e22015-09-22 01:18:40233 messenger.GetFakeConnection()->ReceiveMessageWithPayload(
234 "{"
235 "\"type\":\"decrypt_response\","
236 "\"data\":\"YSB3aW5uZXIgaXMgeW91\"" // "a winner is you", base64-encoded
237 "}, but encoded");
238}
239
240// Verify that the messenger correctly parses base64url encoded data.
241TEST(ProximityAuthMessengerImplTest,
242 RequestDecryption_SendSucceeds_ParsesBase64UrlEncodingInReply) {
243 TestMessenger messenger;
244 MockMessengerObserver observer(&messenger);
245 messenger.RequestDecryption(kChallenge);
246 messenger.GetFakeConnection()->FinishSendingMessageWithSuccess(true);
247
tengsa85897c22015-10-29 01:12:00248 EXPECT_CALL(observer, OnDecryptResponseProxy("\xFF\xE6"));
tengs0fe21e22015-09-22 01:18:40249 messenger.GetFakeConnection()->ReceiveMessageWithPayload(
250 "{"
251 "\"type\":\"decrypt_response\","
252 "\"data\":\"_-Y=\"" // "\0xFF\0xE6", base64url-encoded.
253 "}, but encoded");
254}
255
256TEST(ProximityAuthMessengerImplTest,
257 RequestUnlock_SignInUnsupported_DoesntSendMessage) {
258 TestMessenger messenger;
tengs1d939ea2015-10-29 20:10:33259 messenger.GetFakeSecureContext()->set_protocol_version(
260 SecureContext::PROTOCOL_VERSION_THREE_ZERO);
tengs0fe21e22015-09-22 01:18:40261 messenger.RequestUnlock();
262 EXPECT_FALSE(messenger.GetFakeConnection()->current_message());
263}
264
265TEST(ProximityAuthMessengerImplTest, RequestUnlock_SendsExpectedMessage) {
266 TestMessenger messenger;
267 messenger.RequestUnlock();
268
269 WireMessage* message = messenger.GetFakeConnection()->current_message();
270 ASSERT_TRUE(message);
271 EXPECT_EQ(std::string(), message->permit_id());
272 EXPECT_EQ("{\"type\":\"unlock_request\"}, but encoded", message->payload());
273}
274
275TEST(ProximityAuthMessengerImplTest, RequestUnlock_SendMessageFails) {
276 TestMessenger messenger;
277 MockMessengerObserver observer(&messenger);
278 messenger.RequestUnlock();
279
280 EXPECT_CALL(observer, OnUnlockResponse(false));
281 messenger.GetFakeConnection()->FinishSendingMessageWithSuccess(false);
282}
283
284TEST(ProximityAuthMessengerImplTest, RequestUnlock_SendSucceeds_WaitsForReply) {
285 TestMessenger messenger;
286 MockMessengerObserver observer(&messenger);
287 messenger.RequestUnlock();
288
289 EXPECT_CALL(observer, OnUnlockResponse(_)).Times(0);
290 messenger.GetFakeConnection()->FinishSendingMessageWithSuccess(true);
291}
292
293TEST(ProximityAuthMessengerImplTest,
294 RequestUnlock_SendSucceeds_NotifiesObserversOnReply) {
295 TestMessenger messenger;
296 MockMessengerObserver observer(&messenger);
297 messenger.RequestUnlock();
298 messenger.GetFakeConnection()->FinishSendingMessageWithSuccess(true);
299
300 EXPECT_CALL(observer, OnUnlockResponse(true));
301 messenger.GetFakeConnection()->ReceiveMessageWithPayload(
302 "{\"type\":\"unlock_response\"}, but encoded");
303}
304
305TEST(ProximityAuthMessengerImplTest,
306 OnMessageReceived_RemoteStatusUpdate_Invalid) {
307 TestMessenger messenger;
308 MockMessengerObserver observer(&messenger);
309
310 // Receive a status update message that's missing all the data.
311 EXPECT_CALL(observer, OnRemoteStatusUpdate(_)).Times(0);
312 messenger.GetFakeConnection()->ReceiveMessageWithPayload(
313 "{\"type\":\"status_update\"}, but encoded");
314}
315
316TEST(ProximityAuthMessengerImplTest,
317 OnMessageReceived_RemoteStatusUpdate_Valid) {
318 TestMessenger messenger;
319 MockMessengerObserver observer(&messenger);
320
321 EXPECT_CALL(observer,
322 OnRemoteStatusUpdate(
323 AllOf(Field(&RemoteStatusUpdate::user_presence, USER_PRESENT),
324 Field(&RemoteStatusUpdate::secure_screen_lock_state,
325 SECURE_SCREEN_LOCK_ENABLED),
326 Field(&RemoteStatusUpdate::trust_agent_state,
327 TRUST_AGENT_UNSUPPORTED))));
328 messenger.GetFakeConnection()->ReceiveMessageWithPayload(
329 "{"
330 "\"type\":\"status_update\","
331 "\"user_presence\":\"present\","
332 "\"secure_screen_lock\":\"enabled\","
333 "\"trust_agent\":\"unsupported\""
334 "}, but encoded");
335}
336
337TEST(ProximityAuthMessengerImplTest, OnMessageReceived_InvalidJSON) {
338 TestMessenger messenger;
339 StrictMock<MockMessengerObserver> observer(&messenger);
340 messenger.RequestUnlock();
341 messenger.GetFakeConnection()->FinishSendingMessageWithSuccess(true);
342
343 // The StrictMock will verify that no observer methods are called.
344 messenger.GetFakeConnection()->ReceiveMessageWithPayload(
345 "Not JSON, but encoded");
346}
347
348TEST(ProximityAuthMessengerImplTest, OnMessageReceived_MissingTypeField) {
349 TestMessenger messenger;
350 StrictMock<MockMessengerObserver> observer(&messenger);
351 messenger.RequestUnlock();
352 messenger.GetFakeConnection()->FinishSendingMessageWithSuccess(true);
353
354 // The StrictMock will verify that no observer methods are called.
355 messenger.GetFakeConnection()->ReceiveMessageWithPayload(
356 "{\"some key that's not 'type'\":\"some value\"}, but encoded");
357}
358
359TEST(ProximityAuthMessengerImplTest, OnMessageReceived_UnexpectedReply) {
360 TestMessenger messenger;
361 StrictMock<MockMessengerObserver> observer(&messenger);
362
363 // The StrictMock will verify that no observer methods are called.
364 messenger.GetFakeConnection()->ReceiveMessageWithPayload(
365 "{\"type\":\"unlock_response\"}, but encoded");
366}
367
368TEST(ProximityAuthMessengerImplTest,
369 OnMessageReceived_MismatchedReply_UnlockInReplyToDecrypt) {
370 TestMessenger messenger;
371 StrictMock<MockMessengerObserver> observer(&messenger);
372
373 messenger.RequestDecryption(kChallenge);
374 messenger.GetFakeConnection()->FinishSendingMessageWithSuccess(true);
375
376 // The StrictMock will verify that no observer methods are called.
377 messenger.GetFakeConnection()->ReceiveMessageWithPayload(
378 "{\"type\":\"unlock_response\"}, but encoded");
379}
380
381TEST(ProximityAuthMessengerImplTest,
382 OnMessageReceived_MismatchedReply_DecryptInReplyToUnlock) {
383 TestMessenger messenger;
384 StrictMock<MockMessengerObserver> observer(&messenger);
385
386 messenger.RequestUnlock();
387 messenger.GetFakeConnection()->FinishSendingMessageWithSuccess(true);
388
389 // The StrictMock will verify that no observer methods are called.
390 messenger.GetFakeConnection()->ReceiveMessageWithPayload(
391 "{"
392 "\"type\":\"decrypt_response\","
393 "\"data\":\"YSB3aW5uZXIgaXMgeW91\""
394 "}, but encoded");
395}
396
397TEST(ProximityAuthMessengerImplTest, BuffersMessages_WhileSending) {
398 TestMessenger messenger;
399 MockMessengerObserver observer(&messenger);
400
401 // Initiate a decryption request, and then initiate an unlock request before
402 // the decryption request is even finished sending.
403 messenger.RequestDecryption(kChallenge);
404 messenger.RequestUnlock();
405
tengsa85897c22015-10-29 01:12:00406 EXPECT_CALL(observer, OnDecryptResponseProxy(std::string()));
tengs0fe21e22015-09-22 01:18:40407 messenger.GetFakeConnection()->FinishSendingMessageWithSuccess(false);
408
409 EXPECT_CALL(observer, OnUnlockResponse(false));
410 messenger.GetFakeConnection()->FinishSendingMessageWithSuccess(false);
411}
412
413TEST(ProximityAuthMessengerImplTest, BuffersMessages_WhileAwaitingReply) {
414 TestMessenger messenger;
415 MockMessengerObserver observer(&messenger);
416
417 // Initiate a decryption request, and allow the message to be sent.
418 messenger.RequestDecryption(kChallenge);
419 messenger.GetFakeConnection()->FinishSendingMessageWithSuccess(true);
420
421 // At this point, the messenger is awaiting a reply to the decryption message.
422 // While it's waiting, initiate an unlock request.
423 messenger.RequestUnlock();
424
425 // Now simulate a response arriving for the original decryption request.
tengsa85897c22015-10-29 01:12:00426 EXPECT_CALL(observer, OnDecryptResponseProxy("a winner is you"));
tengs0fe21e22015-09-22 01:18:40427 messenger.GetFakeConnection()->ReceiveMessageWithPayload(
428 "{"
429 "\"type\":\"decrypt_response\","
430 "\"data\":\"YSB3aW5uZXIgaXMgeW91\""
431 "}, but encoded");
432
433 // The unlock request should have remained buffered, and should only now be
434 // sent.
435 EXPECT_CALL(observer, OnUnlockResponse(false));
436 messenger.GetFakeConnection()->FinishSendingMessageWithSuccess(false);
437}
438
439} // namespace proximity_auth