OLD | NEW |
---|---|
(Empty) | |
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/files/file_enumerator.h" | |
7 #include "base/files/file_path.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_unittest.h" | |
13 #include "chrome/browser/profiles/profile.h" | |
14 #include "chrome/common/chrome_constants.h" | |
15 #include "chrome/test/base/testing_profile.h" | |
16 #include "content/public/browser/browser_thread.h" | |
17 #include "content/public/browser/plugin_service.h" | |
18 #include "content/public/test/test_browser_thread_bundle.h" | |
19 | |
20 namespace extensions { | |
21 | |
22 class ExtensionGarbageCollectorUnitTest : public ExtensionServiceTestBase { | |
23 protected: | |
24 void InitPluginService() { | |
25 #if defined(ENABLE_PLUGINS) | |
26 content::PluginService::GetInstance()->Init(); | |
27 #endif | |
28 } | |
29 | |
30 // Garbage collection, in production, runs on multiple threads. This is | |
31 // important to test to make sure we don't violate thread safety. Use a real | |
32 // task runner for these tests. | |
33 // TODO (rdevlin.cronin): It's kind of hacky that we have to do these things | |
Devlin
2014/03/28 22:42:44
Difference 2: We now use multiple threads when we
| |
34 // since we're using ExtensionServiceTestBase. Instead, we should probably do | |
35 // something like use an options flag, and handle it all in the base class. | |
36 void InitFileTaskRunner() { | |
37 service_->SetFileTaskRunnerForTesting( | |
38 content::BrowserThread::GetBlockingPool() | |
39 ->GetSequencedTaskRunnerWithShutdownBehavior( | |
40 content::BrowserThread::GetBlockingPool() | |
41 ->GetNamedSequenceToken("ext_install-"), | |
42 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)); | |
43 | |
44 } | |
45 | |
46 // A delayed task to call GarbageCollectExtensions is posted by | |
47 // ExtensionGarbageCollector's constructor. But, as the test won't wait for | |
48 // the delayed task to be called, we have to call it manually instead. | |
49 void GarbageCollectExtensions() { | |
50 service_->garbage_collector()->GarbageCollectExtensionsForTest(); | |
51 // Wait for GarbageCollectExtensions task to complete. | |
52 content::BrowserThread::GetBlockingPool()->FlushForTesting(); | |
53 } | |
54 }; | |
55 | |
56 // Test that partially deleted extensions are cleaned up during startup | |
57 // Test loading bad extensions from the profile directory. | |
58 TEST_F(ExtensionGarbageCollectorUnitTest, CleanupOnStartup) { | |
59 const std::string kExtensionId = "behllobkkfkfnphdnhnkndlbkcpglgmj"; | |
60 | |
61 InitPluginService(); | |
62 InitializeGoodInstalledExtensionService(); | |
63 InitFileTaskRunner(); | |
64 | |
65 // Simulate that one of them got partially deleted by clearing its pref. | |
66 { | |
67 DictionaryPrefUpdate update(profile_->GetPrefs(), "extensions.settings"); | |
68 base::DictionaryValue* dict = update.Get(); | |
69 ASSERT_TRUE(dict != NULL); | |
70 dict->Remove(kExtensionId, NULL); | |
71 } | |
72 | |
73 service_->Init(); | |
74 GarbageCollectExtensions(); | |
75 | |
76 base::FileEnumerator dirs(extensions_install_dir_, | |
77 false, // not recursive | |
78 base::FileEnumerator::DIRECTORIES); | |
79 size_t count = 0; | |
80 while (!dirs.Next().empty()) | |
81 count++; | |
82 | |
83 // We should have only gotten two extensions now. | |
84 EXPECT_EQ(2u, count); | |
85 | |
86 // And extension1 dir should now be toast. | |
87 base::FilePath extension_dir = | |
88 extensions_install_dir_.AppendASCII(kExtensionId); | |
89 ASSERT_FALSE(base::PathExists(extension_dir)); | |
90 } | |
91 | |
92 // Test that GarbageCollectExtensions deletes the right versions of an | |
93 // extension. | |
94 TEST_F(ExtensionGarbageCollectorUnitTest, GarbageCollectWithPendingUpdates) { | |
95 InitPluginService(); | |
96 | |
97 base::FilePath source_install_dir = | |
98 data_dir_.AppendASCII("pending_updates").AppendASCII("Extensions"); | |
99 base::FilePath pref_path = | |
100 source_install_dir.DirName().Append(chrome::kPreferencesFilename); | |
101 | |
102 InitializeInstalledExtensionService(pref_path, source_install_dir); | |
103 InitFileTaskRunner(); | |
104 | |
105 // This is the directory that is going to be deleted, so make sure it actually | |
106 // is there before the garbage collection. | |
107 ASSERT_TRUE(base::PathExists(extensions_install_dir_.AppendASCII( | |
108 "hpiknbiabeeppbpihjehijgoemciehgk/3"))); | |
109 | |
110 GarbageCollectExtensions(); | |
111 | |
112 // Verify that the pending update for the first extension didn't get | |
113 // deleted. | |
114 EXPECT_TRUE(base::PathExists(extensions_install_dir_.AppendASCII( | |
115 "bjafgdebaacbbbecmhlhpofkepfkgcpa/1.0"))); | |
116 EXPECT_TRUE(base::PathExists(extensions_install_dir_.AppendASCII( | |
117 "bjafgdebaacbbbecmhlhpofkepfkgcpa/2.0"))); | |
118 EXPECT_TRUE(base::PathExists(extensions_install_dir_.AppendASCII( | |
119 "hpiknbiabeeppbpihjehijgoemciehgk/2"))); | |
120 EXPECT_FALSE(base::PathExists(extensions_install_dir_.AppendASCII( | |
121 "hpiknbiabeeppbpihjehijgoemciehgk/3"))); | |
122 } | |
123 | |
124 // Test that pending updates are properly handled on startup. | |
125 TEST_F(ExtensionGarbageCollectorUnitTest, UpdateOnStartup) { | |
126 InitPluginService(); | |
127 | |
128 base::FilePath source_install_dir = | |
129 data_dir_.AppendASCII("pending_updates").AppendASCII("Extensions"); | |
130 base::FilePath pref_path = | |
131 source_install_dir.DirName().Append(chrome::kPreferencesFilename); | |
132 | |
133 InitializeInstalledExtensionService(pref_path, source_install_dir); | |
134 InitFileTaskRunner(); | |
135 | |
136 // This is the directory that is going to be deleted, so make sure it actually | |
137 // is there before the garbage collection. | |
138 ASSERT_TRUE(base::PathExists(extensions_install_dir_.AppendASCII( | |
139 "hpiknbiabeeppbpihjehijgoemciehgk/3"))); | |
140 | |
141 service_->Init(); | |
142 GarbageCollectExtensions(); | |
143 | |
144 // Verify that the pending update for the first extension got installed. | |
145 EXPECT_FALSE(base::PathExists(extensions_install_dir_.AppendASCII( | |
146 "bjafgdebaacbbbecmhlhpofkepfkgcpa/1.0"))); | |
147 EXPECT_TRUE(base::PathExists(extensions_install_dir_.AppendASCII( | |
148 "bjafgdebaacbbbecmhlhpofkepfkgcpa/2.0"))); | |
149 EXPECT_TRUE(base::PathExists(extensions_install_dir_.AppendASCII( | |
150 "hpiknbiabeeppbpihjehijgoemciehgk/2"))); | |
151 EXPECT_FALSE(base::PathExists(extensions_install_dir_.AppendASCII( | |
152 "hpiknbiabeeppbpihjehijgoemciehgk/3"))); | |
153 | |
154 // Make sure update information got deleted. | |
155 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile_.get()); | |
156 EXPECT_FALSE( | |
157 prefs->GetDelayedInstallInfo("bjafgdebaacbbbecmhlhpofkepfkgcpa")); | |
158 } | |
159 | |
160 } // namespace extensions | |
OLD | NEW |