summaryrefslogtreecommitdiffstats
path: root/chrome/browser/extensions
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/extensions')
-rw-r--r--chrome/browser/extensions/extensions_service.cc47
-rw-r--r--chrome/browser/extensions/extensions_service.h14
-rw-r--r--chrome/browser/extensions/extensions_service_unittest.cc43
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();