1 // Copyright 2013 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.
6 #include "base/files/scoped_temp_dir.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "base/test/sequenced_worker_pool_owner.h"
9 #include "content/browser/media/webrtc_identity_store.h"
10 #include "content/public/test/test_browser_thread_bundle.h"
11 #include "content/public/test/test_utils.h"
12 #include "net/base/net_errors.h"
13 #include "sql/connection.h"
14 #include "sql/test/test_helpers.h"
15 #include "testing/gtest/include/gtest/gtest.h"
20 static const char kFakeOrigin
[] = "http://foo.com";
21 static const char kFakeIdentityName1
[] = "name1";
22 static const char kFakeIdentityName2
[] = "name2";
23 static const char kFakeCommonName1
[] = "cname1";
24 static const char kFakeCommonName2
[] = "cname2";
26 static void OnRequestCompleted(bool* completed
,
27 std::string
* out_cert
,
30 const std::string
& certificate
,
31 const std::string
& private_key
) {
32 ASSERT_EQ(net::OK
, error
);
33 ASSERT_NE("", certificate
);
34 ASSERT_NE("", private_key
);
36 *out_cert
= certificate
;
37 *out_key
= private_key
;
40 class WebRtcIdentityStoreTest
: public testing::Test
{
42 WebRtcIdentityStoreTest()
43 : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP
|
44 TestBrowserThreadBundle::REAL_DB_THREAD
),
46 new base::SequencedWorkerPoolOwner(3, "WebRtcIdentityStoreTest")),
47 webrtc_identity_store_(
48 new WebRTCIdentityStore(base::FilePath(), NULL
)) {
49 webrtc_identity_store_
->SetTaskRunnerForTesting(pool_owner_
->pool());
52 ~WebRtcIdentityStoreTest() override
{ pool_owner_
->pool()->Shutdown(); }
54 void SetValidityPeriod(base::TimeDelta validity_period
) {
55 webrtc_identity_store_
->SetValidityPeriodForTesting(validity_period
);
59 RunAllPendingInMessageLoop(BrowserThread::DB
);
60 RunAllPendingInMessageLoop(BrowserThread::IO
);
61 pool_owner_
->pool()->FlushForTesting();
62 base::RunLoop().RunUntilIdle();
65 base::Closure
RequestIdentityAndRunUtilIdle(const std::string
& origin
,
66 const std::string
& identity_name
,
67 const std::string
& common_name
,
69 std::string
* certificate
,
70 std::string
* private_key
) {
71 base::Closure cancel_callback
= webrtc_identity_store_
->RequestIdentity(
72 GURL(origin
), identity_name
, common_name
,
73 base::Bind(&OnRequestCompleted
, completed
, certificate
, private_key
),
74 true /* enable_cache */);
75 EXPECT_FALSE(cancel_callback
.is_null());
77 return cancel_callback
;
80 void Restart(const base::FilePath
& path
) {
81 webrtc_identity_store_
= new WebRTCIdentityStore(path
, NULL
);
82 webrtc_identity_store_
->SetTaskRunnerForTesting(pool_owner_
->pool());
86 TestBrowserThreadBundle browser_thread_bundle_
;
87 scoped_ptr
<base::SequencedWorkerPoolOwner
> pool_owner_
;
88 scoped_refptr
<WebRTCIdentityStore
> webrtc_identity_store_
;
91 TEST_F(WebRtcIdentityStoreTest
, RequestIdentity
) {
92 bool completed
= false;
94 base::Closure cancel_callback
=
95 RequestIdentityAndRunUtilIdle(kFakeOrigin
,
101 EXPECT_TRUE(completed
);
104 TEST_F(WebRtcIdentityStoreTest
, CancelRequest
) {
105 bool completed
= false;
107 base::Closure cancel_callback
= webrtc_identity_store_
->RequestIdentity(
108 GURL(kFakeOrigin
), kFakeIdentityName1
, kFakeCommonName1
,
109 base::Bind(&OnRequestCompleted
, &completed
, &dummy
, &dummy
),
110 true /* enable_cache */);
111 ASSERT_FALSE(cancel_callback
.is_null());
112 cancel_callback
.Run();
115 EXPECT_FALSE(completed
);
118 TEST_F(WebRtcIdentityStoreTest
, ConcurrentUniqueRequests
) {
119 bool completed_1
= false;
120 bool completed_2
= false;
122 base::Closure cancel_callback_1
= webrtc_identity_store_
->RequestIdentity(
123 GURL(kFakeOrigin
), kFakeIdentityName1
, kFakeCommonName1
,
124 base::Bind(&OnRequestCompleted
, &completed_1
, &dummy
, &dummy
),
125 true /* enable_cache */);
126 ASSERT_FALSE(cancel_callback_1
.is_null());
128 base::Closure cancel_callback_2
= webrtc_identity_store_
->RequestIdentity(
129 GURL(kFakeOrigin
), kFakeIdentityName2
, kFakeCommonName1
,
130 base::Bind(&OnRequestCompleted
, &completed_2
, &dummy
, &dummy
),
131 true /* enable_cache */);
132 ASSERT_FALSE(cancel_callback_2
.is_null());
135 EXPECT_TRUE(completed_1
);
136 EXPECT_TRUE(completed_2
);
139 TEST_F(WebRtcIdentityStoreTest
, DifferentCommonNameReturnNewIdentity
) {
140 bool completed_1
= false;
141 bool completed_2
= false;
142 std::string cert_1
, cert_2
, key_1
, key_2
;
144 base::Closure cancel_callback_1
=
145 RequestIdentityAndRunUtilIdle(kFakeOrigin
,
152 base::Closure cancel_callback_2
=
153 RequestIdentityAndRunUtilIdle(kFakeOrigin
,
160 EXPECT_TRUE(completed_1
);
161 EXPECT_TRUE(completed_2
);
162 EXPECT_NE(cert_1
, cert_2
);
163 EXPECT_NE(key_1
, key_2
);
166 TEST_F(WebRtcIdentityStoreTest
, DisableCacheReturnNewIdentity
) {
167 bool completed_1
= false;
168 bool completed_2
= false;
169 std::string cert_1
, cert_2
, key_1
, key_2
;
171 base::Closure cancel_callback_1
= RequestIdentityAndRunUtilIdle(
172 kFakeOrigin
, kFakeIdentityName1
, kFakeCommonName1
, &completed_1
, &cert_1
,
175 base::Closure cancel_callback_2
= webrtc_identity_store_
->RequestIdentity(
176 GURL(kFakeOrigin
), kFakeIdentityName1
, kFakeCommonName1
,
177 base::Bind(&OnRequestCompleted
, &completed_2
, &cert_2
, &key_2
),
178 false /* enable_cache */);
179 EXPECT_FALSE(cancel_callback_2
.is_null());
182 EXPECT_TRUE(completed_1
);
183 EXPECT_TRUE(completed_2
);
184 EXPECT_NE(cert_1
, cert_2
);
185 EXPECT_NE(key_1
, key_2
);
188 TEST_F(WebRtcIdentityStoreTest
, SerialIdenticalRequests
) {
189 bool completed_1
= false;
190 bool completed_2
= false;
191 std::string cert_1
, cert_2
, key_1
, key_2
;
193 base::Closure cancel_callback_1
=
194 RequestIdentityAndRunUtilIdle(kFakeOrigin
,
201 base::Closure cancel_callback_2
=
202 RequestIdentityAndRunUtilIdle(kFakeOrigin
,
209 EXPECT_TRUE(completed_1
);
210 EXPECT_TRUE(completed_2
);
211 EXPECT_EQ(cert_1
, cert_2
);
212 EXPECT_EQ(key_1
, key_2
);
215 TEST_F(WebRtcIdentityStoreTest
, ConcurrentIdenticalRequestsJoined
) {
216 bool completed_1
= false;
217 bool completed_2
= false;
218 std::string cert_1
, cert_2
, key_1
, key_2
;
220 base::Closure cancel_callback_1
= webrtc_identity_store_
->RequestIdentity(
221 GURL(kFakeOrigin
), kFakeIdentityName1
, kFakeCommonName1
,
222 base::Bind(&OnRequestCompleted
, &completed_1
, &cert_1
, &key_1
),
223 true /* enable_cache */);
224 ASSERT_FALSE(cancel_callback_1
.is_null());
226 base::Closure cancel_callback_2
= webrtc_identity_store_
->RequestIdentity(
227 GURL(kFakeOrigin
), kFakeIdentityName1
, kFakeCommonName1
,
228 base::Bind(&OnRequestCompleted
, &completed_2
, &cert_2
, &key_2
),
229 true /* enable_cache */);
230 ASSERT_FALSE(cancel_callback_2
.is_null());
233 EXPECT_TRUE(completed_1
);
234 EXPECT_TRUE(completed_2
);
235 EXPECT_EQ(cert_1
, cert_2
);
236 EXPECT_EQ(key_1
, key_2
);
239 TEST_F(WebRtcIdentityStoreTest
, CancelOneOfIdenticalRequests
) {
240 bool completed_1
= false;
241 bool completed_2
= false;
242 std::string cert_1
, cert_2
, key_1
, key_2
;
244 base::Closure cancel_callback_1
= webrtc_identity_store_
->RequestIdentity(
245 GURL(kFakeOrigin
), kFakeIdentityName1
, kFakeCommonName1
,
246 base::Bind(&OnRequestCompleted
, &completed_1
, &cert_1
, &key_1
),
247 true /* enable_cache */);
248 ASSERT_FALSE(cancel_callback_1
.is_null());
250 base::Closure cancel_callback_2
= webrtc_identity_store_
->RequestIdentity(
251 GURL(kFakeOrigin
), kFakeIdentityName1
, kFakeCommonName1
,
252 base::Bind(&OnRequestCompleted
, &completed_2
, &cert_2
, &key_2
),
253 true /* enable_cache */);
254 ASSERT_FALSE(cancel_callback_2
.is_null());
256 cancel_callback_1
.Run();
259 EXPECT_FALSE(completed_1
);
260 EXPECT_TRUE(completed_2
);
263 TEST_F(WebRtcIdentityStoreTest
, DeleteDataAndGenerateNewIdentity
) {
264 bool completed_1
= false;
265 bool completed_2
= false;
266 std::string cert_1
, cert_2
, key_1
, key_2
;
268 // Generate the first identity.
269 base::Closure cancel_callback_1
=
270 RequestIdentityAndRunUtilIdle(kFakeOrigin
,
277 // Clear the data and the second request should return a new identity.
278 webrtc_identity_store_
->DeleteBetween(
279 base::Time(), base::Time::Now(), base::Bind(&base::DoNothing
));
282 base::Closure cancel_callback_2
=
283 RequestIdentityAndRunUtilIdle(kFakeOrigin
,
290 EXPECT_TRUE(completed_1
);
291 EXPECT_TRUE(completed_2
);
292 EXPECT_NE(cert_1
, cert_2
);
293 EXPECT_NE(key_1
, key_2
);
296 TEST_F(WebRtcIdentityStoreTest
, ExpiredIdentityDeleted
) {
297 // The identities will expire immediately after creation.
298 SetValidityPeriod(base::TimeDelta::FromMilliseconds(0));
300 bool completed_1
= false;
301 bool completed_2
= false;
302 std::string cert_1
, cert_2
, key_1
, key_2
;
304 base::Closure cancel_callback_1
=
305 RequestIdentityAndRunUtilIdle(kFakeOrigin
,
311 EXPECT_TRUE(completed_1
);
313 // Check that the old identity is not returned.
314 base::Closure cancel_callback_2
=
315 RequestIdentityAndRunUtilIdle(kFakeOrigin
,
321 EXPECT_TRUE(completed_2
);
322 EXPECT_NE(cert_1
, cert_2
);
323 EXPECT_NE(key_1
, key_2
);
326 TEST_F(WebRtcIdentityStoreTest
, IdentityPersistentAcrossRestart
) {
327 base::ScopedTempDir temp_dir
;
328 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
329 Restart(temp_dir
.path());
331 bool completed_1
= false;
332 bool completed_2
= false;
333 std::string cert_1
, cert_2
, key_1
, key_2
;
335 // Creates an identity.
336 base::Closure cancel_callback_1
=
337 RequestIdentityAndRunUtilIdle(kFakeOrigin
,
343 EXPECT_TRUE(completed_1
);
345 Restart(temp_dir
.path());
347 // Check that the same identity is returned after the restart.
348 base::Closure cancel_callback_2
=
349 RequestIdentityAndRunUtilIdle(kFakeOrigin
,
355 EXPECT_TRUE(completed_2
);
356 EXPECT_EQ(cert_1
, cert_2
);
357 EXPECT_EQ(key_1
, key_2
);
360 TEST_F(WebRtcIdentityStoreTest
, HandleDBErrors
) {
361 base::ScopedTempDir temp_dir
;
362 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
363 Restart(temp_dir
.path());
365 bool completed_1
= false;
366 std::string cert_1
, key_1
;
368 // Creates an identity.
369 RequestIdentityAndRunUtilIdle(kFakeOrigin
,
376 // Make the table corrupted.
377 base::FilePath db_path
=
378 temp_dir
.path().Append(FILE_PATH_LITERAL("WebRTCIdentityStore"));
379 EXPECT_TRUE(sql::test::CorruptSizeInHeader(db_path
));
381 // Reset to commit the DB changes, which should fail and not crash.
382 webrtc_identity_store_
= NULL
;
385 // Verifies the corrupted table was razed.
386 scoped_ptr
<sql::Connection
> db(new sql::Connection());
387 EXPECT_TRUE(db
->Open(db_path
));
388 EXPECT_EQ(0U, sql::test::CountSQLTables(db
.get()));
391 } // namespace content