Home | History | Annotate | Download | only in updater
      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.
      4 
      5 #include "chrome/browser/extensions/updater/local_extension_cache.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/files/file_path.h"
      9 #include "base/files/file_util.h"
     10 #include "base/files/scoped_temp_dir.h"
     11 #include "base/run_loop.h"
     12 #include "base/test/sequenced_worker_pool_owner.h"
     13 #include "base/values.h"
     14 #include "chrome/common/extensions/extension_constants.h"
     15 #include "content/public/browser/browser_thread.h"
     16 #include "content/public/test/test_browser_thread_bundle.h"
     17 #include "content/public/test/test_utils.h"
     18 #include "testing/gtest/include/gtest/gtest.h"
     19 
     20 namespace {
     21 
     22 const char kTestExtensionId1[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
     23 const char kTestExtensionId2[] = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
     24 const char kTestExtensionId3[] = "cccccccccccccccccccccccccccccccc";
     25 
     26 }  // namespace
     27 
     28 namespace extensions {
     29 
     30 class LocalExtensionCacheTest : public testing::Test {
     31  public:
     32   LocalExtensionCacheTest() {}
     33   virtual ~LocalExtensionCacheTest() {}
     34 
     35   scoped_refptr<base::SequencedTaskRunner> background_task_runner() {
     36     return background_task_runner_;
     37   }
     38 
     39   // testing::Test overrides:
     40   virtual void SetUp() OVERRIDE {
     41     pool_owner_.reset(
     42         new base::SequencedWorkerPoolOwner(3, "Background Pool"));
     43     background_task_runner_ = pool_owner_->pool()->GetSequencedTaskRunner(
     44         pool_owner_->pool()->GetNamedSequenceToken("background"));
     45   }
     46 
     47   virtual void TearDown() OVERRIDE {
     48     pool_owner_->pool()->Shutdown();
     49     base::RunLoop().RunUntilIdle();
     50   }
     51 
     52   base::FilePath CreateCacheDir(bool initialized) {
     53     EXPECT_TRUE(cache_dir_.CreateUniqueTempDir());
     54     if (initialized)
     55       CreateFlagFile(cache_dir_.path());
     56     return cache_dir_.path();
     57   }
     58 
     59   base::FilePath CreateTempDir() {
     60     EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
     61     return temp_dir_.path();
     62   }
     63 
     64   void CreateFlagFile(const base::FilePath& dir) {
     65     CreateFile(dir.Append(
     66         extensions::LocalExtensionCache::kCacheReadyFlagFileName),
     67         0, base::Time::Now());
     68   }
     69 
     70   void CreateExtensionFile(const base::FilePath& dir,
     71                            const std::string& id,
     72                            const std::string& version,
     73                            size_t size,
     74                            const base::Time& timestamp) {
     75     CreateFile(GetExtensionFileName(dir, id, version), size, timestamp);
     76   }
     77 
     78   void CreateFile(const base::FilePath& file,
     79                   size_t size,
     80                   const base::Time& timestamp) {
     81     std::string data(size, 0);
     82     EXPECT_EQ(base::WriteFile(file, data.data(), data.size()), int(size));
     83     EXPECT_TRUE(base::TouchFile(file, timestamp, timestamp));
     84   }
     85 
     86   base::FilePath GetExtensionFileName(const base::FilePath& dir,
     87                                       const std::string& id,
     88                                       const std::string& version) {
     89     return dir.Append(id + "-" + version + ".crx");
     90   }
     91 
     92   void WaitForCompletion() {
     93     // In the worst case you need to repeat this up to 3 times to make sure that
     94     // all pending tasks we sent from UI thread to task runner and back to UI.
     95     for (int i = 0; i < 3; i++) {
     96       // Wait for background task completion that sends replay to UI thread.
     97       pool_owner_->pool()->FlushForTesting();
     98       // Wait for UI thread task completion.
     99       base::RunLoop().RunUntilIdle();
    100     }
    101   }
    102 
    103  private:
    104   content::TestBrowserThreadBundle thread_bundle_;
    105 
    106   scoped_ptr<base::SequencedWorkerPoolOwner> pool_owner_;
    107   scoped_refptr<base::SequencedTaskRunner> background_task_runner_;
    108 
    109   base::ScopedTempDir cache_dir_;
    110   base::ScopedTempDir temp_dir_;
    111 
    112   DISALLOW_COPY_AND_ASSIGN(LocalExtensionCacheTest);
    113 };
    114 
    115 static void SimpleCallback(bool* ptr) {
    116   *ptr = true;
    117 }
    118 
    119 TEST_F(LocalExtensionCacheTest, Basic) {
    120   base::FilePath cache_dir(CreateCacheDir(false));
    121 
    122   LocalExtensionCache cache(cache_dir,
    123                             1000,
    124                             base::TimeDelta::FromDays(30),
    125                             background_task_runner());
    126   cache.SetCacheStatusPollingDelayForTests(base::TimeDelta());
    127 
    128   bool initialized = false;
    129   cache.Init(true, base::Bind(&SimpleCallback, &initialized));
    130 
    131   WaitForCompletion();
    132   EXPECT_FALSE(initialized);
    133 
    134   CreateExtensionFile(cache_dir, kTestExtensionId1, "1.0", 100,
    135                       base::Time::Now() - base::TimeDelta::FromDays(1));
    136   CreateExtensionFile(cache_dir, kTestExtensionId1, "0.1", 100,
    137                       base::Time::Now() - base::TimeDelta::FromDays(10));
    138   CreateExtensionFile(cache_dir, kTestExtensionId2, "2.0", 100,
    139                       base::Time::Now() - base::TimeDelta::FromDays(40));
    140   CreateExtensionFile(cache_dir, kTestExtensionId3, "3.0", 900,
    141                       base::Time::Now() - base::TimeDelta::FromDays(41));
    142 
    143   CreateFlagFile(cache_dir);
    144 
    145   WaitForCompletion();
    146   ASSERT_TRUE(initialized);
    147 
    148   // Older version should be removed on cache initialization.
    149   EXPECT_FALSE(base::PathExists(
    150       GetExtensionFileName(cache_dir, kTestExtensionId1, "0.1")));
    151 
    152   // All extensions should be there because cleanup happens on shutdown to
    153   // support use case when device was not used to more than 30 days and cache
    154   // shouldn't be cleaned before someone will have a chance to use it.
    155   EXPECT_TRUE(cache.GetExtension(kTestExtensionId1, NULL, NULL));
    156   EXPECT_TRUE(cache.GetExtension(kTestExtensionId2, NULL, NULL));
    157   EXPECT_TRUE(cache.GetExtension(kTestExtensionId3, NULL, NULL));
    158 
    159   bool did_shutdown = false;
    160   cache.Shutdown(base::Bind(&SimpleCallback, &did_shutdown));
    161   WaitForCompletion();
    162   ASSERT_TRUE(did_shutdown);
    163 
    164   EXPECT_TRUE(base::PathExists(
    165       GetExtensionFileName(cache_dir, kTestExtensionId1, "1.0")));
    166   EXPECT_FALSE(base::PathExists(
    167       GetExtensionFileName(cache_dir, kTestExtensionId2, "2.0")));
    168   EXPECT_FALSE(base::PathExists(
    169       GetExtensionFileName(cache_dir, kTestExtensionId3, "3.0")));
    170 }
    171 
    172 }  // namespace extensions
    173