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