Make the ChromeOS chromecast system tray integration use a private API.
[chromium-blink-merge.git] / chrome / browser / extensions / extension_garbage_collector_unittest.cc
blobb35576396f1c4d75df2e8b85304c65210528f8b4
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.
5 #include "base/files/file_enumerator.h"
6 #include "base/files/file_path.h"
7 #include "base/files/file_util.h"
8 #include "base/prefs/scoped_user_pref_update.h"
9 #include "base/threading/sequenced_worker_pool.h"
10 #include "base/values.h"
11 #include "chrome/browser/extensions/extension_garbage_collector.h"
12 #include "chrome/browser/extensions/extension_service.h"
13 #include "chrome/browser/extensions/extension_service_test_base.h"
14 #include "chrome/browser/extensions/install_tracker.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/common/chrome_constants.h"
17 #include "chrome/test/base/testing_profile.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "content/public/browser/plugin_service.h"
20 #include "content/public/test/test_browser_thread_bundle.h"
21 #include "extensions/browser/extension_prefs.h"
23 namespace extensions {
25 class ExtensionGarbageCollectorUnitTest : public ExtensionServiceTestBase {
26 protected:
27 void InitPluginService() {
28 #if defined(ENABLE_PLUGINS)
29 content::PluginService::GetInstance()->Init();
30 #endif
33 // Garbage collection, in production, runs on multiple threads. This is
34 // important to test to make sure we don't violate thread safety. Use a real
35 // task runner for these tests.
36 // TODO (rdevlin.cronin): It's kind of hacky that we have to do these things
37 // since we're using ExtensionServiceTestBase. Instead, we should probably do
38 // something like use an options flag, and handle it all in the base class.
39 void InitFileTaskRunner() {
40 service_->SetFileTaskRunnerForTesting(
41 content::BrowserThread::GetBlockingPool()
42 ->GetSequencedTaskRunnerWithShutdownBehavior(
43 content::BrowserThread::GetBlockingPool()
44 ->GetNamedSequenceToken("ext_install-"),
45 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN));
49 // A delayed task to call GarbageCollectExtensions is posted by
50 // ExtensionGarbageCollector's constructor. But, as the test won't wait for
51 // the delayed task to be called, we have to call it manually instead.
52 void GarbageCollectExtensions() {
53 ExtensionGarbageCollector::Get(profile_.get())
54 ->GarbageCollectExtensionsForTest();
55 // Wait for GarbageCollectExtensions task to complete.
56 content::BrowserThread::GetBlockingPool()->FlushForTesting();
60 // Test that partially deleted extensions are cleaned up during startup.
61 TEST_F(ExtensionGarbageCollectorUnitTest, CleanupOnStartup) {
62 const std::string kExtensionId = "behllobkkfkfnphdnhnkndlbkcpglgmj";
64 InitPluginService();
65 InitializeGoodInstalledExtensionService();
66 InitFileTaskRunner();
68 // Simulate that one of them got partially deleted by clearing its pref.
70 DictionaryPrefUpdate update(profile_->GetPrefs(), "extensions.settings");
71 base::DictionaryValue* dict = update.Get();
72 ASSERT_TRUE(dict != NULL);
73 dict->Remove(kExtensionId, NULL);
76 service_->Init();
77 GarbageCollectExtensions();
79 base::FileEnumerator dirs(extensions_install_dir(),
80 false, // not recursive
81 base::FileEnumerator::DIRECTORIES);
82 size_t count = 0;
83 while (!dirs.Next().empty())
84 count++;
86 // We should have only gotten two extensions now.
87 EXPECT_EQ(2u, count);
89 // And extension1 dir should now be toast.
90 base::FilePath extension_dir =
91 extensions_install_dir().AppendASCII(kExtensionId);
92 ASSERT_FALSE(base::PathExists(extension_dir));
95 // Test that garbage collection doesn't delete anything while a crx is being
96 // installed.
97 TEST_F(ExtensionGarbageCollectorUnitTest, NoCleanupDuringInstall) {
98 const std::string kExtensionId = "behllobkkfkfnphdnhnkndlbkcpglgmj";
100 InitPluginService();
101 InitializeGoodInstalledExtensionService();
102 InitFileTaskRunner();
104 // Simulate that one of them got partially deleted by clearing its pref.
106 DictionaryPrefUpdate update(profile_->GetPrefs(), "extensions.settings");
107 base::DictionaryValue* dict = update.Get();
108 ASSERT_TRUE(dict != NULL);
109 dict->Remove(kExtensionId, NULL);
112 service_->Init();
114 // Simulate a CRX installation.
115 InstallTracker::Get(profile_.get())->OnBeginCrxInstall(kExtensionId);
117 GarbageCollectExtensions();
119 // extension1 dir should still exist.
120 base::FilePath extension_dir =
121 extensions_install_dir().AppendASCII(kExtensionId);
122 ASSERT_TRUE(base::PathExists(extension_dir));
124 // Finish CRX installation and re-run garbage collection.
125 InstallTracker::Get(profile_.get())->OnFinishCrxInstall(kExtensionId, false);
126 GarbageCollectExtensions();
128 // extension1 dir should be gone
129 ASSERT_FALSE(base::PathExists(extension_dir));
132 // Test that GarbageCollectExtensions deletes the right versions of an
133 // extension.
134 TEST_F(ExtensionGarbageCollectorUnitTest, GarbageCollectWithPendingUpdates) {
135 InitPluginService();
137 base::FilePath source_install_dir =
138 data_dir().AppendASCII("pending_updates").AppendASCII("Extensions");
139 base::FilePath pref_path =
140 source_install_dir.DirName().Append(chrome::kPreferencesFilename);
142 InitializeInstalledExtensionService(pref_path, source_install_dir);
143 InitFileTaskRunner();
145 // This is the directory that is going to be deleted, so make sure it actually
146 // is there before the garbage collection.
147 ASSERT_TRUE(base::PathExists(extensions_install_dir().AppendASCII(
148 "hpiknbiabeeppbpihjehijgoemciehgk/3")));
150 GarbageCollectExtensions();
152 // Verify that the pending update for the first extension didn't get
153 // deleted.
154 EXPECT_TRUE(base::PathExists(extensions_install_dir().AppendASCII(
155 "bjafgdebaacbbbecmhlhpofkepfkgcpa/1.0")));
156 EXPECT_TRUE(base::PathExists(extensions_install_dir().AppendASCII(
157 "bjafgdebaacbbbecmhlhpofkepfkgcpa/2.0")));
158 EXPECT_TRUE(base::PathExists(extensions_install_dir().AppendASCII(
159 "hpiknbiabeeppbpihjehijgoemciehgk/2")));
160 EXPECT_FALSE(base::PathExists(extensions_install_dir().AppendASCII(
161 "hpiknbiabeeppbpihjehijgoemciehgk/3")));
164 // Test that pending updates are properly handled on startup.
165 TEST_F(ExtensionGarbageCollectorUnitTest, UpdateOnStartup) {
166 InitPluginService();
168 base::FilePath source_install_dir =
169 data_dir().AppendASCII("pending_updates").AppendASCII("Extensions");
170 base::FilePath pref_path =
171 source_install_dir.DirName().Append(chrome::kPreferencesFilename);
173 InitializeInstalledExtensionService(pref_path, source_install_dir);
174 InitFileTaskRunner();
176 // This is the directory that is going to be deleted, so make sure it actually
177 // is there before the garbage collection.
178 ASSERT_TRUE(base::PathExists(extensions_install_dir().AppendASCII(
179 "hpiknbiabeeppbpihjehijgoemciehgk/3")));
181 service_->Init();
182 GarbageCollectExtensions();
184 // Verify that the pending update for the first extension got installed.
185 EXPECT_FALSE(base::PathExists(extensions_install_dir().AppendASCII(
186 "bjafgdebaacbbbecmhlhpofkepfkgcpa/1.0")));
187 EXPECT_TRUE(base::PathExists(extensions_install_dir().AppendASCII(
188 "bjafgdebaacbbbecmhlhpofkepfkgcpa/2.0")));
189 EXPECT_TRUE(base::PathExists(extensions_install_dir().AppendASCII(
190 "hpiknbiabeeppbpihjehijgoemciehgk/2")));
191 EXPECT_FALSE(base::PathExists(extensions_install_dir().AppendASCII(
192 "hpiknbiabeeppbpihjehijgoemciehgk/3")));
194 // Make sure update information got deleted.
195 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile_.get());
196 EXPECT_FALSE(
197 prefs->GetDelayedInstallInfo("bjafgdebaacbbbecmhlhpofkepfkgcpa"));
200 } // namespace extensions