diff options
Diffstat (limited to 'chrome/browser/extensions')
-rw-r--r-- | chrome/browser/extensions/extensions_service.cc | 47 | ||||
-rw-r--r-- | chrome/browser/extensions/extensions_service.h | 14 | ||||
-rw-r--r-- | chrome/browser/extensions/extensions_service_unittest.cc | 43 |
3 files changed, 101 insertions, 3 deletions
diff --git a/chrome/browser/extensions/extensions_service.cc b/chrome/browser/extensions/extensions_service.cc index 7ba0f42..4d1ce3b 100644 --- a/chrome/browser/extensions/extensions_service.cc +++ b/chrome/browser/extensions/extensions_service.cc @@ -4,6 +4,8 @@ #include "chrome/browser/extensions/extensions_service.h" +#include <algorithm> + #include "base/basictypes.h" #include "base/command_line.h" #include "base/file_util.h" @@ -85,9 +87,18 @@ void GetExplicitOriginsInExtent(Extension* extension, pattern != patterns.end(); ++pattern) { if (pattern->match_subdomains() || pattern->match_all_urls()) continue; - GURL origin = GURL(pattern->GetAsString()).GetOrigin(); - if (origin.is_valid()) - set.insert(origin); + // Wildcard URL schemes won't parse into a valid GURL, so explicit schemes + // must be used. + PatternList explicit_patterns = pattern->ConvertToExplicitSchemes(); + for (PatternList::const_iterator explicit_p = explicit_patterns.begin(); + explicit_p != explicit_patterns.end(); ++explicit_p) { + GURL origin = GURL(explicit_p->GetAsString()).GetOrigin(); + if (origin.is_valid()) { + set.insert(origin); + } else { + NOTREACHED(); + } + } } for (std::set<GURL>::const_iterator unique = set.begin(); @@ -700,6 +711,11 @@ void ExtensionsService::NotifyExtensionLoaded(Extension* extension) { // Check if this permission requires unlimited storage quota if (extension->HasApiPermission(Extension::kUnlimitedStoragePermission)) GrantUnlimitedStorage(extension); + + // If the extension is an app, protect its local storage from + // "Clear browsing data." + if (extension->is_app()) + GrantProtectedStorage(extension); } LOG(INFO) << "Sending EXTENSION_LOADED"; @@ -725,6 +741,31 @@ void ExtensionsService::NotifyExtensionUnloaded(Extension* extension) { // in-memory quota. if (extension->HasApiPermission(Extension::kUnlimitedStoragePermission)) RevokeUnlimitedStorage(extension); + + // If this is an app, then stop protecting its storage so it can be deleted. + if (extension->is_app()) + RevokeProtectedStorage(extension); + } +} + +void ExtensionsService::GrantProtectedStorage(Extension* extension) { + DCHECK(extension->is_app()) << "Only Apps are allowed protected storage."; + std::vector<GURL> origins; + GetExplicitOriginsInExtent(extension, &origins); + for (size_t i = 0; i < origins.size(); ++i) + ++protected_storage_map_[origins[i]]; +} + +void ExtensionsService::RevokeProtectedStorage(Extension* extension) { + DCHECK(extension->is_app()) << "Attempting to revoke protected storage from " + << " a non-app extension."; + std::vector<GURL> origins; + GetExplicitOriginsInExtent(extension, &origins); + for (size_t i = 0; i < origins.size(); ++i) { + const GURL& origin = origins[i]; + DCHECK(protected_storage_map_[origin] > 0); + if (--protected_storage_map_[origin] <= 0) + protected_storage_map_.erase(origin); } } diff --git a/chrome/browser/extensions/extensions_service.h b/chrome/browser/extensions/extensions_service.h index efdc17b..f158303 100644 --- a/chrome/browser/extensions/extensions_service.h +++ b/chrome/browser/extensions/extensions_service.h @@ -362,6 +362,10 @@ class ExtensionsService ExtensionMenuManager* menu_manager() { return &menu_manager_; } + const std::map<GURL, int>& protected_storage_map() const { + return protected_storage_map_; + } + // Notify the frontend that there was an error loading an extension. // This method is public because ExtensionsServiceBackend can post to here. void ReportExtensionLoadError(const FilePath& extension_path, @@ -412,6 +416,8 @@ class ExtensionsService void LoadInstalledExtension(const ExtensionInfo& info, bool write_to_prefs); // Helper methods to configure the storage services accordingly. + void GrantProtectedStorage(Extension* extension); + void RevokeProtectedStorage(Extension* extension); void GrantUnlimitedStorage(Extension* extension); void RevokeUnlimitedStorage(Extension* extension); @@ -489,10 +495,18 @@ class ExtensionsService typedef std::map<GURL, int> UnlimitedStorageMap; UnlimitedStorageMap unlimited_storage_map_; + // Collection of origins whose storage is protected by "Clear browsing data." + // A map from origin to the number of Apps currently installed and therefore + // intrinsically protected. + typedef std::map<GURL, int> ProtectedStorageMap; + ProtectedStorageMap protected_storage_map_; + FRIEND_TEST_ALL_PREFIXES(ExtensionsServiceTest, UpdatePendingExtensionAlreadyInstalled); FRIEND_TEST_ALL_PREFIXES(ExtensionsServiceTest, InstallAppsWithUnlimtedStorage); + FRIEND_TEST_ALL_PREFIXES(ExtensionsServiceTest, + InstallAppsAndCheckStorageProtection); DISALLOW_COPY_AND_ASSIGN(ExtensionsService); }; diff --git a/chrome/browser/extensions/extensions_service_unittest.cc b/chrome/browser/extensions/extensions_service_unittest.cc index 819a6a2..bd92b0c 100644 --- a/chrome/browser/extensions/extensions_service_unittest.cc +++ b/chrome/browser/extensions/extensions_service_unittest.cc @@ -1267,6 +1267,49 @@ TEST_F(ExtensionsServiceTest, InstallAppsWithUnlimtedStorage) { EXPECT_TRUE(service_->unlimited_storage_map_.empty()); } +TEST_F(ExtensionsServiceTest, InstallAppsAndCheckStorageProtection) { + InitializeEmptyExtensionsService(); + EXPECT_TRUE(service_->extensions()->empty()); + EXPECT_TRUE(service_->protected_storage_map_.empty()); + + FilePath extensions_path; + ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); + extensions_path = extensions_path.AppendASCII("extensions"); + int pref_count = 0; + + PackAndInstallExtension(extensions_path.AppendASCII("app1"), true); + ValidatePrefKeyCount(++pref_count); + ASSERT_EQ(1u, service_->extensions()->size()); + Extension* extension = service_->extensions()->at(0); + EXPECT_TRUE(extension->is_app()); + const std::string id1 = extension->id(); + EXPECT_FALSE(service_->protected_storage_map_.empty()); + const GURL origin1(extension->GetFullLaunchURL().GetOrigin()); + ASSERT_EQ(1, service_->protected_storage_map_[origin1]); + + // App 4 has a different origin (maps.google.com). + PackAndInstallExtension(extensions_path.AppendASCII("app4"), true); + ValidatePrefKeyCount(++pref_count); + ASSERT_EQ(2u, service_->extensions()->size()); + extension = service_->extensions()->at(1); + const std::string id2 = extension->id(); + EXPECT_FALSE(service_->protected_storage_map_.empty()); + const GURL origin2(extension->GetFullLaunchURL().GetOrigin()); + ASSERT_NE(origin1, origin2); + ASSERT_EQ(1, service_->protected_storage_map_[origin2]); + + service_->UninstallExtension(id1, false); + loop_.RunAllPending(); + EXPECT_EQ(1u, service_->extensions()->size()); + EXPECT_FALSE(service_->protected_storage_map_.empty()); + + service_->UninstallExtension(id2, false); + loop_.RunAllPending(); + + EXPECT_TRUE(service_->extensions()->empty()); + EXPECT_TRUE(service_->protected_storage_map_.empty()); +} + // Test that when an extension version is reinstalled, nothing happens. TEST_F(ExtensionsServiceTest, Reinstall) { InitializeEmptyExtensionsService(); |