Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(35)

Side by Side Diff: chrome/browser/extensions/extension_service_unittest.cc

Issue 9817018: Cleaning Up Extensions When Local Content Removed (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Pulled garbage collection into its own class. Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/extension_service_unittest.h" 5 #include "chrome/browser/extensions/extension_service_unittest.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <set> 8 #include <set>
9 #include <vector> 9 #include <vector>
10 10
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 mutable int visit_count_; 239 mutable int visit_count_;
240 240
241 int creation_flags_; 241 int creation_flags_;
242 242
243 DISALLOW_COPY_AND_ASSIGN(MockExtensionProvider); 243 DISALLOW_COPY_AND_ASSIGN(MockExtensionProvider);
244 }; 244 };
245 245
246 class MockProviderVisitor 246 class MockProviderVisitor
247 : public ExternalExtensionProviderInterface::VisitorInterface { 247 : public ExternalExtensionProviderInterface::VisitorInterface {
248 public: 248 public:
249
250 // The provider will return |fake_base_path| from 249 // The provider will return |fake_base_path| from
251 // GetBaseCrxFilePath(). User can test the behavior with 250 // GetBaseCrxFilePath(). User can test the behavior with
252 // and without an empty path using this parameter. 251 // and without an empty path using this parameter.
253 explicit MockProviderVisitor(FilePath fake_base_path) 252 explicit MockProviderVisitor(FilePath fake_base_path)
254 : ids_found_(0), 253 : ids_found_(0),
255 fake_base_path_(fake_base_path) { 254 fake_base_path_(fake_base_path) {
256 } 255 }
257 256
258 int Visit(const std::string& json_data) { 257 int Visit(const std::string& json_data) {
259 // Give the test json file to the provider for parsing. 258 // Give the test json file to the provider for parsing.
(...skipping 747 matching lines...) Expand 10 before | Expand all | Expand 10 after
1007 ASSERT_TRUE(file_util::PathExists(private_key_path)); 1006 ASSERT_TRUE(file_util::PathExists(private_key_path));
1008 } 1007 }
1009 1008
1010 // The tests are designed so that we never expect to see a packing error. 1009 // The tests are designed so that we never expect to see a packing error.
1011 void PackExtensionTestClient::OnPackFailure(const std::string& error_message, 1010 void PackExtensionTestClient::OnPackFailure(const std::string& error_message,
1012 ExtensionCreator::ErrorType type) { 1011 ExtensionCreator::ErrorType type) {
1013 if (type == ExtensionCreator::kCRXExists) 1012 if (type == ExtensionCreator::kCRXExists)
1014 FAIL() << "Packing should not fail."; 1013 FAIL() << "Packing should not fail.";
1015 else 1014 else
1016 FAIL() << "Existing CRX should have been overwritten."; 1015 FAIL() << "Existing CRX should have been overwritten.";
1017
1018 } 1016 }
1019 1017
1020 // Test loading good extensions from the profile directory. 1018 // Test loading good extensions from the profile directory.
1021 TEST_F(ExtensionServiceTest, LoadAllExtensionsFromDirectorySuccess) { 1019 TEST_F(ExtensionServiceTest, LoadAllExtensionsFromDirectorySuccess) {
1022 PluginService::GetInstance()->Init(); 1020 PluginService::GetInstance()->Init();
1023 1021
1024 // Initialize the test dir with a good Preferences/extensions. 1022 // Initialize the test dir with a good Preferences/extensions.
1025 FilePath source_install_dir = data_dir_ 1023 FilePath source_install_dir = data_dir_
1026 .AppendASCII("good") 1024 .AppendASCII("good")
1027 .AppendASCII("Extensions"); 1025 .AppendASCII("Extensions");
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
1151 std::string("Could not load extension from '*'. ") + 1149 std::string("Could not load extension from '*'. ") +
1152 extension_manifest_errors::kMissingFile)) << 1150 extension_manifest_errors::kMissingFile)) <<
1153 UTF16ToUTF8(GetErrors()[2]); 1151 UTF16ToUTF8(GetErrors()[2]);
1154 1152
1155 EXPECT_TRUE(MatchPattern(UTF16ToUTF8(GetErrors()[3]), 1153 EXPECT_TRUE(MatchPattern(UTF16ToUTF8(GetErrors()[3]),
1156 std::string("Could not load extension from '*'. ") + 1154 std::string("Could not load extension from '*'. ") +
1157 extension_manifest_errors::kManifestUnreadable)) << 1155 extension_manifest_errors::kManifestUnreadable)) <<
1158 UTF16ToUTF8(GetErrors()[3]); 1156 UTF16ToUTF8(GetErrors()[3]);
1159 }; 1157 };
1160 1158
1161 // Test that partially deleted extensions are cleaned up during startup 1159 // Test that old versions of extensions are deleted during garbage collection.
1162 // Test loading bad extensions from the profile directory. 1160 TEST_F(ExtensionServiceTest, GarbageCollectOldVersions) {
1163 TEST_F(ExtensionServiceTest, CleanupOnStartup) {
1164 PluginService::GetInstance()->Init(); 1161 PluginService::GetInstance()->Init();
1165 1162
1166 FilePath source_install_dir = data_dir_ 1163 FilePath source_install_dir = data_dir_
1164 .AppendASCII("garbage_collection")
1165 .AppendASCII("Extensions");
1166
1167 FilePath pref_path = source_install_dir
1168 .DirName()
1169 .AppendASCII("Preferences");
1170
1171 InitializeInstalledExtensionService(pref_path, source_install_dir);
1172
1173 // Verify that there are two versions present initially.
1174 ASSERT_TRUE(file_util::PathExists(
1175 extensions_install_dir_.AppendASCII("fdoajpacpdeapbmhbblepcnilfkpmkff")
1176 .AppendASCII("1.0_0")));
1177 ASSERT_TRUE(file_util::PathExists(
1178 extensions_install_dir_.AppendASCII("fdoajpacpdeapbmhbblepcnilfkpmkff")
1179 .AppendASCII("1.1_0")));
1180 service_->Init();
1181 loop_.RunAllPending();
1182
1183 // Garbage collection should have deleted the old version.
1184 ASSERT_FALSE(file_util::PathExists(
1185 extensions_install_dir_.AppendASCII("fdoajpacpdeapbmhbblepcnilfkpmkff")
1186 .AppendASCII("1.0_0")));
1187 ASSERT_TRUE(file_util::PathExists(
1188 extensions_install_dir_.AppendASCII("fdoajpacpdeapbmhbblepcnilfkpmkff")
1189 .AppendASCII("1.1_0")));
1190 }
1191
1192 // Test that extensions which were deleted from the preferences are cleaned up
1193 // during startup.
1194 // Test loading bad extensions from the profile directory.
1195 TEST_F(ExtensionServiceTest, GarbageCollectOnStartup) {
1196 PluginService::GetInstance()->Init();
1197
1198 FilePath source_install_dir = data_dir_
1167 .AppendASCII("good") 1199 .AppendASCII("good")
1168 .AppendASCII("Extensions"); 1200 .AppendASCII("Extensions");
1169 FilePath pref_path = source_install_dir 1201 FilePath pref_path = source_install_dir
1170 .DirName() 1202 .DirName()
1171 .AppendASCII("Preferences"); 1203 .AppendASCII("Preferences");
1172 1204
1173 InitializeInstalledExtensionService(pref_path, source_install_dir); 1205 InitializeInstalledExtensionService(pref_path, source_install_dir);
1174 1206
1175 // Simulate that one of them got partially deleted by clearing its pref. 1207 // Simulate that one of them got partially deleted by clearing its pref.
1176 { 1208 {
1177 DictionaryPrefUpdate update(profile_->GetPrefs(), "extensions.settings"); 1209 DictionaryPrefUpdate update(profile_->GetPrefs(), "extensions.settings");
1178 DictionaryValue* dict = update.Get(); 1210 DictionaryValue* dict = update.Get();
1179 ASSERT_TRUE(dict != NULL); 1211 ASSERT_TRUE(dict);
1180 dict->Remove("behllobkkfkfnphdnhnkndlbkcpglgmj", NULL); 1212 dict->Remove("behllobkkfkfnphdnhnkndlbkcpglgmj", NULL);
1181 } 1213 }
1182 1214
1183 service_->Init(); 1215 service_->Init();
1184 // Wait for GarbageCollectExtensions task to complete. 1216 // Wait for GarbageCollectExtensions task to complete.
1185 loop_.RunAllPending(); 1217 loop_.RunAllPending();
1186 1218
1187 file_util::FileEnumerator dirs(extensions_install_dir_, false, 1219 file_util::FileEnumerator dirs(extensions_install_dir_, false,
1188 file_util::FileEnumerator::DIRECTORIES); 1220 file_util::FileEnumerator::DIRECTORIES);
1189 size_t count = 0; 1221 size_t count = 0;
1190 while (!dirs.Next().empty()) 1222 while (!dirs.Next().empty())
1191 count++; 1223 count++;
1192 1224
1193 // We should have only gotten two extensions now. 1225 // We should have only gotten two extensions now.
1194 EXPECT_EQ(2u, count); 1226 EXPECT_EQ(2u, count);
1195 1227
1196 // And extension1 dir should now be toast. 1228 // And extension1 dir should now be toast.
1197 FilePath extension_dir = extensions_install_dir_ 1229 FilePath extension_dir = extensions_install_dir_
1198 .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj"); 1230 .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj");
1199 ASSERT_FALSE(file_util::PathExists(extension_dir)); 1231 ASSERT_FALSE(file_util::PathExists(extension_dir));
1200 } 1232 }
1201 1233
1234 // Test that internal extensions which are referenced in the preferences but
1235 // had their content deleted are cleaned up during startup.
1236 TEST_F(ExtensionServiceTest, GarbageCollectInternalExtensionsMissingContent) {
1237 PluginService::GetInstance()->Init();
1238
1239 FilePath source_dir = data_dir_.AppendASCII("good").AppendASCII("Extensions");
1240 FilePath pref_path = source_dir.DirName().AppendASCII("Preferences");
1241
1242 InitializeInstalledExtensionService(pref_path, source_dir);
1243
1244 // Delete the extension's directory.
1245 FilePath extension_dir = extensions_install_dir_
1246 .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj");
1247 ASSERT_TRUE(file_util::Delete(extension_dir, true));
1248
1249 // Run GarbageCollectExtensions.
1250 service_->Init();
1251 loop_.RunAllPending();
1252
1253 file_util::FileEnumerator dirs(extensions_install_dir_, false,
1254 file_util::FileEnumerator::DIRECTORIES);
1255 size_t count = 0;
1256 while (!dirs.Next().empty())
1257 count++;
1258
1259 // We should have only gotten two extensions now.
1260 EXPECT_EQ(2u, count);
1261
1262 DictionaryPrefUpdate update(profile_->GetPrefs(), "extensions.settings");
1263 DictionaryValue* dictionary = update.Get();
1264 ASSERT_TRUE(dictionary);
1265 ASSERT_FALSE(dictionary->HasKey("behllobkkfkfnphdnhnkndlbkcpglgmj"));
1266 }
1267
1268 // Test that unpacked extensions which are referenced in the preferences but
1269 // had their content deleted are cleaned up during startup.
1270 TEST_F(ExtensionServiceTest, GarbageCollectUnpackedExtensionsMissingContent) {
1271 InitializeEmptyExtensionService();
1272
1273 ScopedTempDir temp;
1274 ASSERT_TRUE(temp.CreateUniqueTempDir());
1275
1276 // Write the manifest dynamically, since we have to delete the file anyway.
1277 FilePath extension_path = temp.path();
1278 FilePath manifest_path = extension_path.Append(Extension::kManifestFilename);
1279 ASSERT_FALSE(file_util::PathExists(manifest_path));
1280
1281 // Construct a simple manifest and install it.
1282 DictionaryValue manifest;
1283 manifest.SetString("version", "1.0");
1284 manifest.SetString("name", "Cleanup Unpacked Extensions Missing Content");
1285 manifest.SetInteger("manifest_version", 2);
1286
1287 JSONFileValueSerializer serializer(manifest_path);
1288 ASSERT_TRUE(serializer.Serialize(manifest));
1289
1290 extensions::UnpackedInstaller::Create(service_)->Load(extension_path);
1291 loop_.RunAllPending();
1292
1293 // Make sure it installed correctly.
1294 EXPECT_EQ(0u, GetErrors().size());
1295 ASSERT_EQ(1u, loaded_.size());
1296 EXPECT_EQ(Extension::LOAD, loaded_[0]->location());
1297 EXPECT_EQ(1u, service_->extensions()->size());
1298
1299 std::string extension_id = loaded_[0]->id();
1300
1301 // Make sure it is in the preferences at this point.
1302 DictionaryPrefUpdate initial_update(
1303 profile_->GetPrefs(), "extensions.settings");
1304 DictionaryValue* initial_dictionary = initial_update.Get();
1305 ASSERT_TRUE(initial_dictionary);
1306 ASSERT_TRUE(initial_dictionary->HasKey(extension_id));
1307
1308 // Delete local content, GarbageCollectExtensions, and test whether the key
1309 // is still in the preferences.
1310 ASSERT_TRUE(file_util::Delete(extension_path, true));
1311 service_->GarbageCollectExtensions();
1312 loop_.RunAllPending();
1313
1314 DictionaryPrefUpdate final_update(
1315 profile_->GetPrefs(), "extensions.settings");
1316 DictionaryValue* final_dictionary = final_update.Get();
1317 ASSERT_TRUE(final_dictionary);
1318 ASSERT_FALSE(final_dictionary->HasKey(extension_id));
1319 }
1320
1202 // Test installing extensions. This test tries to install few extensions using 1321 // Test installing extensions. This test tries to install few extensions using
1203 // crx files. If you need to change those crx files, feel free to repackage 1322 // crx files. If you need to change those crx files, feel free to repackage
1204 // them, throw away the key used and change the id's above. 1323 // them, throw away the key used and change the id's above.
1205 TEST_F(ExtensionServiceTest, InstallExtension) { 1324 TEST_F(ExtensionServiceTest, InstallExtension) {
1206 InitializeEmptyExtensionService(); 1325 InitializeEmptyExtensionService();
1207 1326
1208 // Extensions not enabled. 1327 // Extensions not enabled.
1209 set_extensions_enabled(false); 1328 set_extensions_enabled(false);
1210 FilePath path = data_dir_.AppendASCII("good.crx"); 1329 FilePath path = data_dir_.AppendASCII("good.crx");
1211 InstallCRX(path, INSTALL_FAILED); 1330 InstallCRX(path, INSTALL_FAILED);
(...skipping 3647 matching lines...) Expand 10 before | Expand all | Expand 10 after
4859 provider->UpdateOrAddExtension(hosted_app, "1.0.0.0", 4978 provider->UpdateOrAddExtension(hosted_app, "1.0.0.0",
4860 data_dir_.AppendASCII("hosted_app.crx")); 4979 data_dir_.AppendASCII("hosted_app.crx"));
4861 4980
4862 service_->CheckForExternalUpdates(); 4981 service_->CheckForExternalUpdates();
4863 loop_.RunAllPending(); 4982 loop_.RunAllPending();
4864 4983
4865 ASSERT_TRUE(service_->PopulateExtensionGlobalError( 4984 ASSERT_TRUE(service_->PopulateExtensionGlobalError(
4866 extension_global_error.get())); 4985 extension_global_error.get()));
4867 ASSERT_EQ(1u, extension_global_error->get_external_extension_ids()->size()); 4986 ASSERT_EQ(1u, extension_global_error->get_external_extension_ids()->size());
4868 } 4987 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698