extension_garbage_collector_chromeos_unittest.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
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 27namespace { 28const char kExtensionId1[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; 29const char kExtensionId2[] = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"; 30} // namespace 31 32namespace extensions { 33 34class 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. 151TEST_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@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