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.
4
5#include "base/bind.h"
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 "testing/gtest/include/gtest/gtest.h"
14#include "url/gurl.h"
15
16namespace content {
17
18static const char* kFakeOrigin = "http://foo.com";
19static const char* kFakeIdentityName1 = "name1";
20static const char* kFakeIdentityName2 = "name2";
21static const char* kFakeCommonName1 = "cname1";
22static const char* kFakeCommonName2 = "cname2";
23
24static void OnRequestCompleted(bool* completed,
25                               std::string* out_cert,
26                               std::string* out_key,
27                               int error,
28                               const std::string& certificate,
29                               const std::string& private_key) {
30  ASSERT_EQ(net::OK, error);
31  ASSERT_NE("", certificate);
32  ASSERT_NE("", private_key);
33  *completed = true;
34  *out_cert = certificate;
35  *out_key = private_key;
36}
37
38class WebRTCIdentityStoreTest : public testing::Test {
39 public:
40  WebRTCIdentityStoreTest()
41      : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP |
42                               TestBrowserThreadBundle::REAL_DB_THREAD),
43        pool_owner_(
44            new base::SequencedWorkerPoolOwner(3, "WebRTCIdentityStoreTest")),
45        webrtc_identity_store_(
46            new WebRTCIdentityStore(base::FilePath(), NULL)) {
47    webrtc_identity_store_->SetTaskRunnerForTesting(pool_owner_->pool());
48  }
49
50  virtual ~WebRTCIdentityStoreTest() {
51    pool_owner_->pool()->Shutdown();
52  }
53
54  void SetValidityPeriod(base::TimeDelta validity_period) {
55    webrtc_identity_store_->SetValidityPeriodForTesting(validity_period);
56  }
57
58  void RunUntilIdle() {
59    RunAllPendingInMessageLoop(BrowserThread::DB);
60    RunAllPendingInMessageLoop(BrowserThread::IO);
61    pool_owner_->pool()->FlushForTesting();
62    base::RunLoop().RunUntilIdle();
63  }
64
65  base::Closure RequestIdentityAndRunUtilIdle(const std::string& origin,
66                                              const std::string& identity_name,
67                                              const std::string& common_name,
68                                              bool* completed,
69                                              std::string* certificate,
70                                              std::string* private_key) {
71    base::Closure cancel_callback = webrtc_identity_store_->RequestIdentity(
72        GURL(origin),
73        identity_name,
74        common_name,
75        base::Bind(&OnRequestCompleted, completed, certificate, private_key));
76    EXPECT_FALSE(cancel_callback.is_null());
77    RunUntilIdle();
78    return cancel_callback;
79  }
80
81  void Restart(const base::FilePath& path) {
82    webrtc_identity_store_ = new WebRTCIdentityStore(path, NULL);
83    webrtc_identity_store_->SetTaskRunnerForTesting(pool_owner_->pool());
84  }
85
86 protected:
87  TestBrowserThreadBundle browser_thread_bundle_;
88  scoped_ptr<base::SequencedWorkerPoolOwner> pool_owner_;
89  scoped_refptr<WebRTCIdentityStore> webrtc_identity_store_;
90};
91
92TEST_F(WebRTCIdentityStoreTest, RequestIdentity) {
93  bool completed = false;
94  std::string dummy;
95  base::Closure cancel_callback =
96      RequestIdentityAndRunUtilIdle(kFakeOrigin,
97                                    kFakeIdentityName1,
98                                    kFakeCommonName1,
99                                    &completed,
100                                    &dummy,
101                                    &dummy);
102  EXPECT_TRUE(completed);
103}
104
105TEST_F(WebRTCIdentityStoreTest, CancelRequest) {
106  bool completed = false;
107  std::string dummy;
108  base::Closure cancel_callback = webrtc_identity_store_->RequestIdentity(
109      GURL(kFakeOrigin),
110      kFakeIdentityName1,
111      kFakeCommonName1,
112      base::Bind(&OnRequestCompleted, &completed, &dummy, &dummy));
113  ASSERT_FALSE(cancel_callback.is_null());
114  cancel_callback.Run();
115
116  RunUntilIdle();
117  EXPECT_FALSE(completed);
118}
119
120TEST_F(WebRTCIdentityStoreTest, ConcurrentUniqueRequests) {
121  bool completed_1 = false;
122  bool completed_2 = false;
123  std::string dummy;
124  base::Closure cancel_callback_1 = webrtc_identity_store_->RequestIdentity(
125      GURL(kFakeOrigin),
126      kFakeIdentityName1,
127      kFakeCommonName1,
128      base::Bind(&OnRequestCompleted, &completed_1, &dummy, &dummy));
129  ASSERT_FALSE(cancel_callback_1.is_null());
130
131  base::Closure cancel_callback_2 = webrtc_identity_store_->RequestIdentity(
132      GURL(kFakeOrigin),
133      kFakeIdentityName2,
134      kFakeCommonName1,
135      base::Bind(&OnRequestCompleted, &completed_2, &dummy, &dummy));
136  ASSERT_FALSE(cancel_callback_2.is_null());
137
138  RunUntilIdle();
139  EXPECT_TRUE(completed_1);
140  EXPECT_TRUE(completed_2);
141}
142
143TEST_F(WebRTCIdentityStoreTest, DifferentCommonNameReturnNewIdentity) {
144  bool completed_1 = false;
145  bool completed_2 = false;
146  std::string cert_1, cert_2, key_1, key_2;
147
148  base::Closure cancel_callback_1 =
149      RequestIdentityAndRunUtilIdle(kFakeOrigin,
150                                    kFakeIdentityName1,
151                                    kFakeCommonName1,
152                                    &completed_1,
153                                    &cert_1,
154                                    &key_1);
155
156  base::Closure cancel_callback_2 =
157      RequestIdentityAndRunUtilIdle(kFakeOrigin,
158                                    kFakeIdentityName1,
159                                    kFakeCommonName2,
160                                    &completed_2,
161                                    &cert_2,
162                                    &key_2);
163
164  EXPECT_TRUE(completed_1);
165  EXPECT_TRUE(completed_2);
166  EXPECT_NE(cert_1, cert_2);
167  EXPECT_NE(key_1, key_2);
168}
169
170TEST_F(WebRTCIdentityStoreTest, SerialIdenticalRequests) {
171  bool completed_1 = false;
172  bool completed_2 = false;
173  std::string cert_1, cert_2, key_1, key_2;
174
175  base::Closure cancel_callback_1 =
176      RequestIdentityAndRunUtilIdle(kFakeOrigin,
177                                    kFakeIdentityName1,
178                                    kFakeCommonName1,
179                                    &completed_1,
180                                    &cert_1,
181                                    &key_1);
182
183  base::Closure cancel_callback_2 =
184      RequestIdentityAndRunUtilIdle(kFakeOrigin,
185                                    kFakeIdentityName1,
186                                    kFakeCommonName1,
187                                    &completed_2,
188                                    &cert_2,
189                                    &key_2);
190
191  EXPECT_TRUE(completed_1);
192  EXPECT_TRUE(completed_2);
193  EXPECT_EQ(cert_1, cert_2);
194  EXPECT_EQ(key_1, key_2);
195}
196
197TEST_F(WebRTCIdentityStoreTest, ConcurrentIdenticalRequestsJoined) {
198  bool completed_1 = false;
199  bool completed_2 = false;
200  std::string cert_1, cert_2, key_1, key_2;
201
202  base::Closure cancel_callback_1 = webrtc_identity_store_->RequestIdentity(
203      GURL(kFakeOrigin),
204      kFakeIdentityName1,
205      kFakeCommonName1,
206      base::Bind(&OnRequestCompleted, &completed_1, &cert_1, &key_1));
207  ASSERT_FALSE(cancel_callback_1.is_null());
208
209  base::Closure cancel_callback_2 = webrtc_identity_store_->RequestIdentity(
210      GURL(kFakeOrigin),
211      kFakeIdentityName1,
212      kFakeCommonName1,
213      base::Bind(&OnRequestCompleted, &completed_2, &cert_2, &key_2));
214  ASSERT_FALSE(cancel_callback_2.is_null());
215
216  RunUntilIdle();
217  EXPECT_TRUE(completed_1);
218  EXPECT_TRUE(completed_2);
219  EXPECT_EQ(cert_1, cert_2);
220  EXPECT_EQ(key_1, key_2);
221}
222
223TEST_F(WebRTCIdentityStoreTest, CancelOneOfIdenticalRequests) {
224  bool completed_1 = false;
225  bool completed_2 = false;
226  std::string cert_1, cert_2, key_1, key_2;
227
228  base::Closure cancel_callback_1 = webrtc_identity_store_->RequestIdentity(
229      GURL(kFakeOrigin),
230      kFakeIdentityName1,
231      kFakeCommonName1,
232      base::Bind(&OnRequestCompleted, &completed_1, &cert_1, &key_1));
233  ASSERT_FALSE(cancel_callback_1.is_null());
234
235  base::Closure cancel_callback_2 = webrtc_identity_store_->RequestIdentity(
236      GURL(kFakeOrigin),
237      kFakeIdentityName1,
238      kFakeCommonName1,
239      base::Bind(&OnRequestCompleted, &completed_2, &cert_2, &key_2));
240  ASSERT_FALSE(cancel_callback_2.is_null());
241
242  cancel_callback_1.Run();
243
244  RunUntilIdle();
245  EXPECT_FALSE(completed_1);
246  EXPECT_TRUE(completed_2);
247}
248
249TEST_F(WebRTCIdentityStoreTest, DeleteDataAndGenerateNewIdentity) {
250  bool completed_1 = false;
251  bool completed_2 = false;
252  std::string cert_1, cert_2, key_1, key_2;
253
254  // Generate the first identity.
255  base::Closure cancel_callback_1 =
256      RequestIdentityAndRunUtilIdle(kFakeOrigin,
257                                    kFakeIdentityName1,
258                                    kFakeCommonName1,
259                                    &completed_1,
260                                    &cert_1,
261                                    &key_1);
262
263  // Clear the data and the second request should return a new identity.
264  webrtc_identity_store_->DeleteBetween(
265      base::Time(), base::Time::Now(), base::Bind(&base::DoNothing));
266  RunUntilIdle();
267
268  base::Closure cancel_callback_2 =
269      RequestIdentityAndRunUtilIdle(kFakeOrigin,
270                                    kFakeIdentityName1,
271                                    kFakeCommonName1,
272                                    &completed_2,
273                                    &cert_2,
274                                    &key_2);
275
276  EXPECT_TRUE(completed_1);
277  EXPECT_TRUE(completed_2);
278  EXPECT_NE(cert_1, cert_2);
279  EXPECT_NE(key_1, key_2);
280}
281
282TEST_F(WebRTCIdentityStoreTest, ExpiredIdentityDeleted) {
283  // The identities will expire immediately after creation.
284  SetValidityPeriod(base::TimeDelta::FromMilliseconds(0));
285
286  bool completed_1 = false;
287  bool completed_2 = false;
288  std::string cert_1, cert_2, key_1, key_2;
289
290  base::Closure cancel_callback_1 =
291      RequestIdentityAndRunUtilIdle(kFakeOrigin,
292                                    kFakeIdentityName1,
293                                    kFakeCommonName1,
294                                    &completed_1,
295                                    &cert_1,
296                                    &key_1);
297  EXPECT_TRUE(completed_1);
298
299  // Check that the old identity is not returned.
300  base::Closure cancel_callback_2 =
301      RequestIdentityAndRunUtilIdle(kFakeOrigin,
302                                    kFakeIdentityName1,
303                                    kFakeCommonName1,
304                                    &completed_2,
305                                    &cert_2,
306                                    &key_2);
307  EXPECT_TRUE(completed_2);
308  EXPECT_NE(cert_1, cert_2);
309  EXPECT_NE(key_1, key_2);
310}
311
312TEST_F(WebRTCIdentityStoreTest, IdentityPersistentAcrossRestart) {
313  base::ScopedTempDir temp_dir;
314  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
315  Restart(temp_dir.path());
316
317  bool completed_1 = false;
318  bool completed_2 = false;
319  std::string cert_1, cert_2, key_1, key_2;
320
321  // Creates an identity.
322  base::Closure cancel_callback_1 =
323      RequestIdentityAndRunUtilIdle(kFakeOrigin,
324                                    kFakeIdentityName1,
325                                    kFakeCommonName1,
326                                    &completed_1,
327                                    &cert_1,
328                                    &key_1);
329  EXPECT_TRUE(completed_1);
330
331  Restart(temp_dir.path());
332
333  // Check that the same identity is returned after the restart.
334  base::Closure cancel_callback_2 =
335      RequestIdentityAndRunUtilIdle(kFakeOrigin,
336                                    kFakeIdentityName1,
337                                    kFakeCommonName1,
338                                    &completed_2,
339                                    &cert_2,
340                                    &key_2);
341  EXPECT_TRUE(completed_2);
342  EXPECT_EQ(cert_1, cert_2);
343  EXPECT_EQ(key_1, key_2);
344}
345
346}  // namespace content
347