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.
5 #include "net/ssl/default_channel_id_store.h"
11 #include "base/bind.h"
12 #include "base/compiler_specific.h"
13 #include "base/location.h"
14 #include "base/logging.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/message_loop/message_loop.h"
17 #include "base/single_thread_task_runner.h"
18 #include "base/thread_task_runner_handle.h"
19 #include "crypto/ec_private_key.h"
20 #include "net/base/net_errors.h"
21 #include "net/test/channel_id_test_util.h"
22 #include "testing/gtest/include/gtest/gtest.h"
28 void CallCounter(int* counter
) {
32 void GetChannelIDCallbackNotCalled(
34 const std::string
& server_identifier
,
35 scoped_ptr
<crypto::ECPrivateKey
> key_result
) {
36 ADD_FAILURE() << "Unexpected callback execution.";
39 class AsyncGetChannelIDHelper
{
41 AsyncGetChannelIDHelper() : called_(false) {}
43 void Callback(int err
,
44 const std::string
& server_identifier
,
45 scoped_ptr
<crypto::ECPrivateKey
> key_result
) {
47 server_identifier_
= server_identifier
;
48 key_
= key_result
.Pass();
53 std::string server_identifier_
;
54 scoped_ptr
<crypto::ECPrivateKey
> key_
;
59 ChannelIDStore::ChannelIDList
* dest
,
60 const ChannelIDStore::ChannelIDList
& result
) {
64 class MockPersistentStore
65 : public DefaultChannelIDStore::PersistentStore
{
67 MockPersistentStore();
69 // DefaultChannelIDStore::PersistentStore implementation.
70 void Load(const LoadedCallback
& loaded_callback
) override
;
72 const DefaultChannelIDStore::ChannelID
& channel_id
) override
;
74 const DefaultChannelIDStore::ChannelID
& channel_id
) override
;
75 void SetForceKeepSessionState() override
;
78 ~MockPersistentStore() override
;
81 typedef std::map
<std::string
, DefaultChannelIDStore::ChannelID
>
84 ChannelIDMap channel_ids_
;
87 MockPersistentStore::MockPersistentStore() {}
89 void MockPersistentStore::Load(const LoadedCallback
& loaded_callback
) {
90 scoped_ptr
<ScopedVector
<DefaultChannelIDStore::ChannelID
> >
91 channel_ids(new ScopedVector
<DefaultChannelIDStore::ChannelID
>());
92 ChannelIDMap::iterator it
;
94 for (it
= channel_ids_
.begin(); it
!= channel_ids_
.end(); ++it
) {
95 channel_ids
->push_back(
96 new DefaultChannelIDStore::ChannelID(it
->second
));
99 base::ThreadTaskRunnerHandle::Get()->PostTask(
100 FROM_HERE
, base::Bind(loaded_callback
, base::Passed(&channel_ids
)));
103 void MockPersistentStore::AddChannelID(
104 const DefaultChannelIDStore::ChannelID
& channel_id
) {
105 channel_ids_
[channel_id
.server_identifier()] = channel_id
;
108 void MockPersistentStore::DeleteChannelID(
109 const DefaultChannelIDStore::ChannelID
& channel_id
) {
110 channel_ids_
.erase(channel_id
.server_identifier());
113 void MockPersistentStore::SetForceKeepSessionState() {}
115 MockPersistentStore::~MockPersistentStore() {}
119 TEST(DefaultChannelIDStoreTest
, TestLoading
) {
120 scoped_refptr
<MockPersistentStore
> persistent_store(new MockPersistentStore
);
122 persistent_store
->AddChannelID(DefaultChannelIDStore::ChannelID(
123 "google.com", base::Time(),
124 make_scoped_ptr(crypto::ECPrivateKey::Create())));
125 persistent_store
->AddChannelID(DefaultChannelIDStore::ChannelID(
126 "verisign.com", base::Time(),
127 make_scoped_ptr(crypto::ECPrivateKey::Create())));
129 // Make sure channel_ids load properly.
130 DefaultChannelIDStore
store(persistent_store
.get());
131 // Load has not occurred yet.
132 EXPECT_EQ(0, store
.GetChannelIDCount());
133 store
.SetChannelID(make_scoped_ptr(new ChannelIDStore::ChannelID(
134 "verisign.com", base::Time(),
135 make_scoped_ptr(crypto::ECPrivateKey::Create()))));
136 // Wait for load & queued set task.
137 base::MessageLoop::current()->RunUntilIdle();
138 EXPECT_EQ(2, store
.GetChannelIDCount());
139 store
.SetChannelID(make_scoped_ptr(new ChannelIDStore::ChannelID(
140 "twitter.com", base::Time(),
141 make_scoped_ptr(crypto::ECPrivateKey::Create()))));
142 // Set should be synchronous now that load is done.
143 EXPECT_EQ(3, store
.GetChannelIDCount());
146 //TODO(mattm): add more tests of without a persistent store?
147 TEST(DefaultChannelIDStoreTest
, TestSettingAndGetting
) {
148 // No persistent store, all calls will be synchronous.
149 DefaultChannelIDStore
store(NULL
);
150 scoped_ptr
<crypto::ECPrivateKey
> expected_key(crypto::ECPrivateKey::Create());
152 scoped_ptr
<crypto::ECPrivateKey
> key
;
153 EXPECT_EQ(0, store
.GetChannelIDCount());
154 EXPECT_EQ(ERR_FILE_NOT_FOUND
,
155 store
.GetChannelID("verisign.com", &key
,
156 base::Bind(&GetChannelIDCallbackNotCalled
)));
158 store
.SetChannelID(make_scoped_ptr(new ChannelIDStore::ChannelID(
159 "verisign.com", base::Time::FromInternalValue(123),
160 make_scoped_ptr(expected_key
->Copy()))));
161 EXPECT_EQ(OK
, store
.GetChannelID("verisign.com", &key
,
162 base::Bind(&GetChannelIDCallbackNotCalled
)));
163 EXPECT_TRUE(KeysEqual(expected_key
.get(), key
.get()));
166 TEST(DefaultChannelIDStoreTest
, TestDuplicateChannelIds
) {
167 scoped_refptr
<MockPersistentStore
> persistent_store(new MockPersistentStore
);
168 DefaultChannelIDStore
store(persistent_store
.get());
169 scoped_ptr
<crypto::ECPrivateKey
> expected_key(crypto::ECPrivateKey::Create());
171 scoped_ptr
<crypto::ECPrivateKey
> key
;
172 EXPECT_EQ(0, store
.GetChannelIDCount());
173 store
.SetChannelID(make_scoped_ptr(new ChannelIDStore::ChannelID(
174 "verisign.com", base::Time::FromInternalValue(123),
175 make_scoped_ptr(crypto::ECPrivateKey::Create()))));
176 store
.SetChannelID(make_scoped_ptr(new ChannelIDStore::ChannelID(
177 "verisign.com", base::Time::FromInternalValue(456),
178 make_scoped_ptr(expected_key
->Copy()))));
180 // Wait for load & queued set tasks.
181 base::MessageLoop::current()->RunUntilIdle();
182 EXPECT_EQ(1, store
.GetChannelIDCount());
183 EXPECT_EQ(OK
, store
.GetChannelID("verisign.com", &key
,
184 base::Bind(&GetChannelIDCallbackNotCalled
)));
185 EXPECT_TRUE(KeysEqual(expected_key
.get(), key
.get()));
188 TEST(DefaultChannelIDStoreTest
, TestAsyncGet
) {
189 scoped_refptr
<MockPersistentStore
> persistent_store(new MockPersistentStore
);
190 scoped_ptr
<crypto::ECPrivateKey
> expected_key(crypto::ECPrivateKey::Create());
191 persistent_store
->AddChannelID(ChannelIDStore::ChannelID(
192 "verisign.com", base::Time::FromInternalValue(123),
193 make_scoped_ptr(expected_key
->Copy())));
195 DefaultChannelIDStore
store(persistent_store
.get());
196 AsyncGetChannelIDHelper helper
;
197 scoped_ptr
<crypto::ECPrivateKey
> key
;
198 EXPECT_EQ(0, store
.GetChannelIDCount());
199 EXPECT_EQ(ERR_IO_PENDING
,
200 store
.GetChannelID("verisign.com", &key
,
201 base::Bind(&AsyncGetChannelIDHelper::Callback
,
202 base::Unretained(&helper
))));
204 // Wait for load & queued get tasks.
205 base::MessageLoop::current()->RunUntilIdle();
206 EXPECT_EQ(1, store
.GetChannelIDCount());
208 EXPECT_TRUE(helper
.called_
);
209 EXPECT_EQ(OK
, helper
.err_
);
210 EXPECT_EQ("verisign.com", helper
.server_identifier_
);
211 EXPECT_TRUE(KeysEqual(expected_key
.get(), helper
.key_
.get()));
214 TEST(DefaultChannelIDStoreTest
, TestDeleteAll
) {
215 scoped_refptr
<MockPersistentStore
> persistent_store(new MockPersistentStore
);
216 DefaultChannelIDStore
store(persistent_store
.get());
218 store
.SetChannelID(make_scoped_ptr(new ChannelIDStore::ChannelID(
219 "verisign.com", base::Time(),
220 make_scoped_ptr(crypto::ECPrivateKey::Create()))));
221 store
.SetChannelID(make_scoped_ptr(new ChannelIDStore::ChannelID(
222 "google.com", base::Time(),
223 make_scoped_ptr(crypto::ECPrivateKey::Create()))));
224 store
.SetChannelID(make_scoped_ptr(new ChannelIDStore::ChannelID(
225 "harvard.com", base::Time(),
226 make_scoped_ptr(crypto::ECPrivateKey::Create()))));
227 // Wait for load & queued set tasks.
228 base::MessageLoop::current()->RunUntilIdle();
230 EXPECT_EQ(3, store
.GetChannelIDCount());
231 int delete_finished
= 0;
232 store
.DeleteAll(base::Bind(&CallCounter
, &delete_finished
));
233 ASSERT_EQ(1, delete_finished
);
234 EXPECT_EQ(0, store
.GetChannelIDCount());
237 TEST(DefaultChannelIDStoreTest
, TestAsyncGetAndDeleteAll
) {
238 scoped_refptr
<MockPersistentStore
> persistent_store(new MockPersistentStore
);
239 persistent_store
->AddChannelID(ChannelIDStore::ChannelID(
240 "verisign.com", base::Time(),
241 make_scoped_ptr(crypto::ECPrivateKey::Create())));
242 persistent_store
->AddChannelID(ChannelIDStore::ChannelID(
243 "google.com", base::Time(),
244 make_scoped_ptr(crypto::ECPrivateKey::Create())));
246 ChannelIDStore::ChannelIDList pre_channel_ids
;
247 ChannelIDStore::ChannelIDList post_channel_ids
;
248 int delete_finished
= 0;
249 DefaultChannelIDStore
store(persistent_store
.get());
251 store
.GetAllChannelIDs(base::Bind(GetAllCallback
, &pre_channel_ids
));
252 store
.DeleteAll(base::Bind(&CallCounter
, &delete_finished
));
253 store
.GetAllChannelIDs(base::Bind(GetAllCallback
, &post_channel_ids
));
254 // Tasks have not run yet.
255 EXPECT_EQ(0u, pre_channel_ids
.size());
256 // Wait for load & queued tasks.
257 base::MessageLoop::current()->RunUntilIdle();
258 EXPECT_EQ(0, store
.GetChannelIDCount());
259 EXPECT_EQ(2u, pre_channel_ids
.size());
260 EXPECT_EQ(0u, post_channel_ids
.size());
263 TEST(DefaultChannelIDStoreTest
, TestDelete
) {
264 scoped_refptr
<MockPersistentStore
> persistent_store(new MockPersistentStore
);
265 DefaultChannelIDStore
store(persistent_store
.get());
267 scoped_ptr
<crypto::ECPrivateKey
> key
;
268 EXPECT_EQ(0, store
.GetChannelIDCount());
269 store
.SetChannelID(make_scoped_ptr(new ChannelIDStore::ChannelID(
270 "verisign.com", base::Time(),
271 make_scoped_ptr(crypto::ECPrivateKey::Create()))));
272 // Wait for load & queued set task.
273 base::MessageLoop::current()->RunUntilIdle();
275 store
.SetChannelID(make_scoped_ptr(new ChannelIDStore::ChannelID(
276 "google.com", base::Time(),
277 make_scoped_ptr(crypto::ECPrivateKey::Create()))));
279 EXPECT_EQ(2, store
.GetChannelIDCount());
280 int delete_finished
= 0;
281 store
.DeleteChannelID("verisign.com",
282 base::Bind(&CallCounter
, &delete_finished
));
283 ASSERT_EQ(1, delete_finished
);
284 EXPECT_EQ(1, store
.GetChannelIDCount());
285 EXPECT_EQ(ERR_FILE_NOT_FOUND
,
286 store
.GetChannelID("verisign.com", &key
,
287 base::Bind(&GetChannelIDCallbackNotCalled
)));
288 EXPECT_EQ(OK
, store
.GetChannelID("google.com", &key
,
289 base::Bind(&GetChannelIDCallbackNotCalled
)));
290 int delete2_finished
= 0;
291 store
.DeleteChannelID("google.com",
292 base::Bind(&CallCounter
, &delete2_finished
));
293 ASSERT_EQ(1, delete2_finished
);
294 EXPECT_EQ(0, store
.GetChannelIDCount());
295 EXPECT_EQ(ERR_FILE_NOT_FOUND
,
296 store
.GetChannelID("google.com", &key
,
297 base::Bind(&GetChannelIDCallbackNotCalled
)));
300 TEST(DefaultChannelIDStoreTest
, TestAsyncDelete
) {
301 scoped_refptr
<MockPersistentStore
> persistent_store(new MockPersistentStore
);
302 scoped_ptr
<crypto::ECPrivateKey
> expected_key(crypto::ECPrivateKey::Create());
303 persistent_store
->AddChannelID(ChannelIDStore::ChannelID(
304 "a.com", base::Time::FromInternalValue(1),
305 make_scoped_ptr(crypto::ECPrivateKey::Create())));
306 persistent_store
->AddChannelID(
307 ChannelIDStore::ChannelID("b.com", base::Time::FromInternalValue(3),
308 make_scoped_ptr(expected_key
->Copy())));
309 DefaultChannelIDStore
store(persistent_store
.get());
310 int delete_finished
= 0;
311 store
.DeleteChannelID("a.com",
312 base::Bind(&CallCounter
, &delete_finished
));
314 AsyncGetChannelIDHelper a_helper
;
315 AsyncGetChannelIDHelper b_helper
;
316 scoped_ptr
<crypto::ECPrivateKey
> key
;
317 EXPECT_EQ(0, store
.GetChannelIDCount());
318 EXPECT_EQ(ERR_IO_PENDING
,
319 store
.GetChannelID("a.com", &key
,
320 base::Bind(&AsyncGetChannelIDHelper::Callback
,
321 base::Unretained(&a_helper
))));
322 EXPECT_EQ(ERR_IO_PENDING
,
323 store
.GetChannelID("b.com", &key
,
324 base::Bind(&AsyncGetChannelIDHelper::Callback
,
325 base::Unretained(&b_helper
))));
327 EXPECT_EQ(0, delete_finished
);
328 EXPECT_FALSE(a_helper
.called_
);
329 EXPECT_FALSE(b_helper
.called_
);
330 // Wait for load & queued tasks.
331 base::MessageLoop::current()->RunUntilIdle();
332 EXPECT_EQ(1, delete_finished
);
333 EXPECT_EQ(1, store
.GetChannelIDCount());
335 EXPECT_TRUE(a_helper
.called_
);
336 EXPECT_EQ(ERR_FILE_NOT_FOUND
, a_helper
.err_
);
337 EXPECT_EQ("a.com", a_helper
.server_identifier_
);
338 EXPECT_FALSE(a_helper
.key_
);
339 EXPECT_TRUE(b_helper
.called_
);
340 EXPECT_EQ(OK
, b_helper
.err_
);
341 EXPECT_EQ("b.com", b_helper
.server_identifier_
);
342 EXPECT_TRUE(KeysEqual(expected_key
.get(), b_helper
.key_
.get()));
345 TEST(DefaultChannelIDStoreTest
, TestGetAll
) {
346 scoped_refptr
<MockPersistentStore
> persistent_store(new MockPersistentStore
);
347 DefaultChannelIDStore
store(persistent_store
.get());
349 EXPECT_EQ(0, store
.GetChannelIDCount());
350 store
.SetChannelID(make_scoped_ptr(new ChannelIDStore::ChannelID(
351 "verisign.com", base::Time(),
352 make_scoped_ptr(crypto::ECPrivateKey::Create()))));
353 store
.SetChannelID(make_scoped_ptr(new ChannelIDStore::ChannelID(
354 "google.com", base::Time(),
355 make_scoped_ptr(crypto::ECPrivateKey::Create()))));
356 store
.SetChannelID(make_scoped_ptr(new ChannelIDStore::ChannelID(
357 "harvard.com", base::Time(),
358 make_scoped_ptr(crypto::ECPrivateKey::Create()))));
359 store
.SetChannelID(make_scoped_ptr(new ChannelIDStore::ChannelID(
360 "mit.com", base::Time(),
361 make_scoped_ptr(crypto::ECPrivateKey::Create()))));
362 // Wait for load & queued set tasks.
363 base::MessageLoop::current()->RunUntilIdle();
365 EXPECT_EQ(4, store
.GetChannelIDCount());
366 ChannelIDStore::ChannelIDList channel_ids
;
367 store
.GetAllChannelIDs(base::Bind(GetAllCallback
, &channel_ids
));
368 EXPECT_EQ(4u, channel_ids
.size());
371 TEST(DefaultChannelIDStoreTest
, TestInitializeFrom
) {
372 scoped_refptr
<MockPersistentStore
> persistent_store(new MockPersistentStore
);
373 DefaultChannelIDStore
store(persistent_store
.get());
374 scoped_ptr
<crypto::ECPrivateKey
> preexisting_key(
375 crypto::ECPrivateKey::Create());
376 scoped_ptr
<crypto::ECPrivateKey
> both_key(crypto::ECPrivateKey::Create());
377 scoped_ptr
<crypto::ECPrivateKey
> copied_key(crypto::ECPrivateKey::Create());
379 store
.SetChannelID(make_scoped_ptr(
380 new ChannelIDStore::ChannelID("preexisting.com", base::Time(),
381 make_scoped_ptr(preexisting_key
->Copy()))));
382 store
.SetChannelID(make_scoped_ptr(new ChannelIDStore::ChannelID(
383 "both.com", base::Time(),
384 make_scoped_ptr(crypto::ECPrivateKey::Create()))));
385 // Wait for load & queued set tasks.
386 base::MessageLoop::current()->RunUntilIdle();
387 EXPECT_EQ(2, store
.GetChannelIDCount());
389 ChannelIDStore::ChannelIDList source_channel_ids
;
390 source_channel_ids
.push_back(ChannelIDStore::ChannelID(
391 "both.com", base::Time(),
392 // Key differs from above to test that existing entries are overwritten.
393 make_scoped_ptr(both_key
->Copy())));
394 source_channel_ids
.push_back(ChannelIDStore::ChannelID(
395 "copied.com", base::Time(), make_scoped_ptr(copied_key
->Copy())));
396 store
.InitializeFrom(source_channel_ids
);
397 EXPECT_EQ(3, store
.GetChannelIDCount());
399 ChannelIDStore::ChannelIDList channel_ids
;
400 store
.GetAllChannelIDs(base::Bind(GetAllCallback
, &channel_ids
));
401 ASSERT_EQ(3u, channel_ids
.size());
403 ChannelIDStore::ChannelIDList::iterator channel_id
= channel_ids
.begin();
404 EXPECT_EQ("both.com", channel_id
->server_identifier());
405 EXPECT_TRUE(KeysEqual(both_key
.get(), channel_id
->key()));
408 EXPECT_EQ("copied.com", channel_id
->server_identifier());
409 EXPECT_TRUE(KeysEqual(copied_key
.get(), channel_id
->key()));
412 EXPECT_EQ("preexisting.com", channel_id
->server_identifier());
413 EXPECT_TRUE(KeysEqual(preexisting_key
.get(), channel_id
->key()));
416 TEST(DefaultChannelIDStoreTest
, TestAsyncInitializeFrom
) {
417 scoped_refptr
<MockPersistentStore
> persistent_store(new MockPersistentStore
);
418 scoped_ptr
<crypto::ECPrivateKey
> preexisting_key(
419 crypto::ECPrivateKey::Create());
420 scoped_ptr
<crypto::ECPrivateKey
> both_key(crypto::ECPrivateKey::Create());
421 scoped_ptr
<crypto::ECPrivateKey
> copied_key(crypto::ECPrivateKey::Create());
423 persistent_store
->AddChannelID(
424 ChannelIDStore::ChannelID("preexisting.com", base::Time(),
425 make_scoped_ptr(preexisting_key
->Copy())));
426 persistent_store
->AddChannelID(ChannelIDStore::ChannelID(
427 "both.com", base::Time(),
428 make_scoped_ptr(crypto::ECPrivateKey::Create())));
430 DefaultChannelIDStore
store(persistent_store
.get());
431 ChannelIDStore::ChannelIDList source_channel_ids
;
432 source_channel_ids
.push_back(ChannelIDStore::ChannelID(
433 "both.com", base::Time(),
434 // Key differs from above to test that existing entries are overwritten.
435 make_scoped_ptr(both_key
->Copy())));
436 source_channel_ids
.push_back(ChannelIDStore::ChannelID(
437 "copied.com", base::Time(), make_scoped_ptr(copied_key
->Copy())));
438 store
.InitializeFrom(source_channel_ids
);
439 EXPECT_EQ(0, store
.GetChannelIDCount());
440 // Wait for load & queued tasks.
441 base::MessageLoop::current()->RunUntilIdle();
442 EXPECT_EQ(3, store
.GetChannelIDCount());
444 ChannelIDStore::ChannelIDList channel_ids
;
445 store
.GetAllChannelIDs(base::Bind(GetAllCallback
, &channel_ids
));
446 ASSERT_EQ(3u, channel_ids
.size());
448 ChannelIDStore::ChannelIDList::iterator channel_id
= channel_ids
.begin();
449 EXPECT_EQ("both.com", channel_id
->server_identifier());
450 EXPECT_TRUE(KeysEqual(both_key
.get(), channel_id
->key()));
453 EXPECT_EQ("copied.com", channel_id
->server_identifier());
454 EXPECT_TRUE(KeysEqual(copied_key
.get(), channel_id
->key()));
457 EXPECT_EQ("preexisting.com", channel_id
->server_identifier());
458 EXPECT_TRUE(KeysEqual(preexisting_key
.get(), channel_id
->key()));