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