Home | History | Annotate | Download | only in extensions
      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 "base/file_util.h"
      6 #include "base/prefs/scoped_user_pref_update.h"
      7 #include "base/prefs/testing_pref_service.h"
      8 #include "base/strings/string_util.h"
      9 #include "base/threading/sequenced_worker_pool.h"
     10 #include "base/values.h"
     11 #include "chrome/browser/chromeos/login/users/fake_user_manager.h"
     12 #include "chrome/browser/chromeos/login/users/user_manager.h"
     13 #include "chrome/browser/extensions/extension_assets_manager_chromeos.h"
     14 #include "chrome/browser/extensions/extension_garbage_collector_chromeos.h"
     15 #include "chrome/browser/extensions/extension_service.h"
     16 #include "chrome/browser/extensions/extension_service_test_base.h"
     17 #include "chrome/browser/prefs/browser_prefs.h"
     18 #include "chrome/browser/profiles/profile.h"
     19 #include "chrome/test/base/testing_browser_process.h"
     20 #include "chrome/test/base/testing_profile.h"
     21 #include "content/public/browser/browser_thread.h"
     22 #include "content/public/browser/plugin_service.h"
     23 #include "extensions/browser/extension_prefs.h"
     24 #include "extensions/browser/install_flag.h"
     25 #include "extensions/common/manifest_constants.h"
     26 
     27 namespace {
     28 const char kExtensionId1[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
     29 const char kExtensionId2[] = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
     30 }  // namespace
     31 
     32 namespace extensions {
     33 
     34 class ExtensionGarbageCollectorChromeOSUnitTest
     35     : public ExtensionServiceTestBase {
     36  protected:
     37   PrefService& local_state() { return local_state_; }
     38   const base::FilePath& cache_dir() { return cache_dir_.path(); }
     39 
     40   virtual void SetUp() OVERRIDE {
     41     TestingBrowserProcess::GetGlobal()->SetLocalState(&local_state_);
     42     chrome::RegisterLocalState(local_state_.registry());
     43 
     44 #if defined(ENABLE_PLUGINS)
     45     content::PluginService::GetInstance()->Init();
     46 #endif
     47     InitializeGoodInstalledExtensionService();
     48 
     49     // Need real IO thread.
     50     service_->SetFileTaskRunnerForTesting(
     51         content::BrowserThread::GetBlockingPool()
     52             ->GetSequencedTaskRunnerWithShutdownBehavior(
     53                 content::BrowserThread::GetBlockingPool()
     54                     ->GetNamedSequenceToken("ext_install-"),
     55                 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN));
     56 
     57     CHECK(cache_dir_.CreateUniqueTempDir());
     58     ExtensionAssetsManagerChromeOS::SetSharedInstallDirForTesting(cache_dir());
     59     ExtensionGarbageCollectorChromeOS::ClearGarbageCollectedForTesting();
     60 
     61     // Initialize the UserManager singleton to a fresh FakeUserManager instance.
     62     user_manager_enabler_.reset(
     63         new chromeos::ScopedUserManagerEnabler(new chromeos::FakeUserManager));
     64 
     65     GetFakeUserManager()->AddUser(chromeos::UserManager::kStubUser);
     66     GetFakeUserManager()->LoginUser(chromeos::UserManager::kStubUser);
     67     GetFakeUserManager()->SetProfileForUser(
     68         GetFakeUserManager()->GetActiveUser(), profile_.get());
     69   }
     70 
     71   virtual void TearDown() OVERRIDE {
     72     TestingBrowserProcess::GetGlobal()->SetLocalState(NULL);
     73   }
     74 
     75   void GarbageCollectExtensions() {
     76     ExtensionGarbageCollector::Get(profile_.get())
     77         ->GarbageCollectExtensionsForTest();
     78     // Wait for GarbageCollectExtensions task to complete.
     79     content::BrowserThread::GetBlockingPool()->FlushForTesting();
     80   }
     81 
     82   base::FilePath CreateSharedExtensionDir(const std::string& id,
     83                                           const std::string& version,
     84                                           const base::FilePath& shared_dir) {
     85     base::FilePath path = shared_dir.AppendASCII(id).AppendASCII(version);
     86     CreateDirectory(path);
     87     return path;
     88   }
     89 
     90   void CreateSharedExtensionPrefs(const std::string& id,
     91                                   const std::string& version,
     92                                   const std::string& users_string,
     93                                   const base::FilePath& path) {
     94     DictionaryPrefUpdate shared_extensions(&local_state_,
     95         ExtensionAssetsManagerChromeOS::kSharedExtensions);
     96 
     97     base::DictionaryValue* extension_info = NULL;
     98     if (!shared_extensions->GetDictionary(id, &extension_info)) {
     99       extension_info = new base::DictionaryValue;
    100       shared_extensions->Set(id, extension_info);
    101     }
    102 
    103     base::DictionaryValue* version_info = new base::DictionaryValue;
    104     extension_info->SetWithoutPathExpansion(version, version_info);
    105     version_info->SetString(
    106         ExtensionAssetsManagerChromeOS::kSharedExtensionPath, path.value());
    107 
    108     base::ListValue* users = new base::ListValue;
    109     version_info->Set(ExtensionAssetsManagerChromeOS::kSharedExtensionUsers,
    110                       users);
    111     std::vector<std::string> users_list;
    112     if (Tokenize(users_string, ",", &users_list)) {
    113       for (size_t i = 0; i < users_list.size(); i++) {
    114         users->AppendString(users_list[i]);
    115       }
    116     }
    117   }
    118 
    119   scoped_refptr<Extension> CreateExtension(const std::string& id,
    120                                            const std::string& version,
    121                                            const base::FilePath& path) {
    122     base::DictionaryValue manifest;
    123     manifest.SetString(manifest_keys::kName, "test");
    124     manifest.SetString(manifest_keys::kVersion, version);
    125 
    126     std::string error;
    127     scoped_refptr<Extension> extension = Extension::Create(
    128         path, Manifest::INTERNAL, manifest, Extension::NO_FLAGS, id, &error);
    129     CHECK(extension.get()) << error;
    130     CHECK_EQ(id, extension->id());
    131 
    132     return extension;
    133   }
    134 
    135   ExtensionPrefs* GetExtensionPrefs() {
    136     return ExtensionPrefs::Get(profile_.get());
    137   }
    138 
    139   chromeos::FakeUserManager* GetFakeUserManager() {
    140     return static_cast<chromeos::FakeUserManager*>(
    141         chromeos::UserManager::Get());
    142   }
    143 
    144  private:
    145   scoped_ptr<chromeos::ScopedUserManagerEnabler> user_manager_enabler_;
    146   TestingPrefServiceSimple local_state_;
    147   base::ScopedTempDir cache_dir_;
    148 };
    149 
    150 // Test shared extensions clean up.
    151 TEST_F(ExtensionGarbageCollectorChromeOSUnitTest, SharedExtensions) {
    152   // Version for non-existing user.
    153   base::FilePath path_id1_1 = CreateSharedExtensionDir(
    154       kExtensionId1, "1.0", cache_dir());
    155   CreateSharedExtensionPrefs(kExtensionId1, "1.0", "test (at) test.com", path_id1_1);
    156   EXPECT_TRUE(base::PathExists(path_id1_1));
    157 
    158   // Version for current user but the extension is not installed.
    159   base::FilePath path_id1_2 = CreateSharedExtensionDir(
    160       kExtensionId1, "2.0", cache_dir());
    161   CreateSharedExtensionPrefs(
    162       kExtensionId1, "2.0", chromeos::UserManager::kStubUser, path_id1_2);
    163   EXPECT_TRUE(base::PathExists(path_id1_2));
    164 
    165   // Version for current user that delayed install.
    166   base::FilePath path_id2_1 = CreateSharedExtensionDir(
    167       kExtensionId2, "1.0", cache_dir());
    168   CreateSharedExtensionPrefs(
    169       kExtensionId2, "1.0", chromeos::UserManager::kStubUser, path_id2_1);
    170   scoped_refptr<Extension> extension2 = CreateExtension(kExtensionId2, "1.0",
    171                                                         path_id2_1);
    172   GetExtensionPrefs()->SetDelayedInstallInfo(
    173       extension2.get(),
    174       Extension::ENABLED,
    175       kInstallFlagNone,
    176       ExtensionPrefs::DELAY_REASON_WAIT_FOR_IDLE,
    177       syncer::StringOrdinal(),
    178       std::string());
    179   EXPECT_TRUE(base::PathExists(path_id2_1));
    180 
    181   GarbageCollectExtensions();
    182 
    183   EXPECT_FALSE(base::PathExists(path_id1_1));
    184   EXPECT_FALSE(base::PathExists(path_id1_2));
    185   EXPECT_FALSE(base::PathExists(cache_dir().AppendASCII(kExtensionId1)));
    186 
    187   EXPECT_TRUE(base::PathExists(path_id2_1));
    188 
    189   const base::DictionaryValue* shared_extensions = local_state().GetDictionary(
    190       ExtensionAssetsManagerChromeOS::kSharedExtensions);
    191   ASSERT_TRUE(shared_extensions);
    192 
    193   EXPECT_FALSE(shared_extensions->HasKey(kExtensionId1));
    194   EXPECT_TRUE(shared_extensions->HasKey(kExtensionId2));
    195 }
    196 
    197 }  // namespace extensions
    198