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