summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormichaeln@chromium.org <michaeln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-13 21:59:48 +0000
committermichaeln@chromium.org <michaeln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-13 21:59:48 +0000
commitc2c263cd9f2ac658d6dc35ecbd4551ca0c5cb154 (patch)
tree519a7a765fd452637ca925f7a29794524e9cee32
parent3f4512be44cac7c017d93d4beedd0d6b49bec737 (diff)
downloadchromium_src-c2c263cd9f2ac658d6dc35ecbd4551ca0c5cb154.zip
chromium_src-c2c263cd9f2ac658d6dc35ecbd4551ca0c5cb154.tar.gz
chromium_src-c2c263cd9f2ac658d6dc35ecbd4551ca0c5cb154.tar.bz2
Grant ChromeApplications unlimited appcache and database storage if requested.
BUG=49227,49993 TEST=ExtensionsServiceTest.InstallAppsWithUnlimtedStorage Review URL: http://codereview.chromium.org/3053048 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@56099 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/extensions/extensions_service.cc89
-rw-r--r--chrome/browser/extensions/extensions_service.h13
-rw-r--r--chrome/browser/extensions/extensions_service_unittest.cc76
-rw-r--r--chrome/browser/extensions/extensions_service_unittest.h1
-rw-r--r--chrome/test/data/extensions/app1/manifest.json1
-rw-r--r--chrome/test/data/extensions/app2/manifest.json3
6 files changed, 167 insertions, 16 deletions
diff --git a/chrome/browser/extensions/extensions_service.cc b/chrome/browser/extensions/extensions_service.cc
index c9df30f..849eb2e 100644
--- a/chrome/browser/extensions/extensions_service.cc
+++ b/chrome/browser/extensions/extensions_service.cc
@@ -65,7 +65,7 @@ namespace errors = extension_manifest_errors;
namespace {
-static bool ShouldReloadExtensionManifest(const ExtensionInfo& info) {
+bool ShouldReloadExtensionManifest(const ExtensionInfo& info) {
// Always reload LOAD extension manifests, because they can change on disk
// independent of the manifest in our prefs.
if (info.extension_location == Extension::LOAD)
@@ -75,6 +75,26 @@ static bool ShouldReloadExtensionManifest(const ExtensionInfo& info) {
return extension_l10n_util::ShouldRelocalizeManifest(info);
}
+void GetExplicitOriginsInExtent(Extension* extension,
+ std::vector<GURL>* origins) {
+ typedef std::vector<URLPattern> PatternList;
+ std::set<GURL> set;
+ const PatternList& patterns = extension->web_extent().patterns();
+ for (PatternList::const_iterator pattern = patterns.begin();
+ 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);
+ }
+
+ for (std::set<GURL>::const_iterator unique = set.begin();
+ unique != set.end(); ++unique) {
+ origins->push_back(*unique);
+ }
+}
+
} // namespace
PendingExtensionInfo::PendingExtensionInfo(const GURL& update_url,
@@ -618,17 +638,8 @@ void ExtensionsService::NotifyExtensionLoaded(Extension* extension) {
profile_->RegisterExtensionWithRequestContexts(extension);
// Check if this permission requires unlimited storage quota
- if (extension->HasApiPermission(Extension::kUnlimitedStoragePermission)) {
- string16 origin_identifier =
- webkit_database::DatabaseUtil::GetOriginIdentifier(extension->url());
- ChromeThread::PostTask(
- ChromeThread::FILE, FROM_HERE,
- NewRunnableMethod(
- profile_->GetDatabaseTracker(),
- &webkit_database::DatabaseTracker::SetOriginQuotaInMemory,
- origin_identifier,
- kint64max));
- }
+ if (extension->HasApiPermission(Extension::kUnlimitedStoragePermission))
+ GrantUnlimitedStorage(extension);
}
LOG(INFO) << "Sending EXTENSION_LOADED";
@@ -652,15 +663,65 @@ void ExtensionsService::NotifyExtensionUnloaded(Extension* extension) {
// Check if this permission required unlimited storage quota, reset its
// in-memory quota.
- if (extension->HasApiPermission(Extension::kUnlimitedStoragePermission)) {
+ if (extension->HasApiPermission(Extension::kUnlimitedStoragePermission))
+ RevokeUnlimitedStorage(extension);
+ }
+}
+
+void ExtensionsService::GrantUnlimitedStorage(Extension* extension) {
+ DCHECK(extension->HasApiPermission(Extension::kUnlimitedStoragePermission));
+ std::vector<GURL> origins;
+ GetExplicitOriginsInExtent(extension, &origins);
+ origins.push_back(extension->url());
+
+ for (size_t i = 0; i < origins.size(); ++i) {
+ const GURL& origin = origins[i];
+ if (++unlimited_storage_map_[origin] == 1) {
+ string16 origin_identifier =
+ webkit_database::DatabaseUtil::GetOriginIdentifier(origin);
+ ChromeThread::PostTask(
+ ChromeThread::FILE, FROM_HERE,
+ NewRunnableMethod(
+ profile_->GetDatabaseTracker(),
+ &webkit_database::DatabaseTracker::SetOriginQuotaInMemory,
+ origin_identifier,
+ kint64max));
+ ChromeThread::PostTask(
+ ChromeThread::IO, FROM_HERE,
+ NewRunnableMethod(
+ profile_->GetAppCacheService(),
+ &ChromeAppCacheService::SetOriginQuotaInMemory,
+ origin,
+ kint64max));
+ }
+ }
+}
+
+void ExtensionsService::RevokeUnlimitedStorage(Extension* extension) {
+ DCHECK(extension->HasApiPermission(Extension::kUnlimitedStoragePermission));
+ std::vector<GURL> origins;
+ GetExplicitOriginsInExtent(extension, &origins);
+ origins.push_back(extension->url());
+
+ for (size_t i = 0; i < origins.size(); ++i) {
+ const GURL& origin = origins[i];
+ DCHECK(unlimited_storage_map_[origin] > 0);
+ if (--unlimited_storage_map_[origin] == 0) {
+ unlimited_storage_map_.erase(origin);
string16 origin_identifier =
- webkit_database::DatabaseUtil::GetOriginIdentifier(extension->url());
+ webkit_database::DatabaseUtil::GetOriginIdentifier(origin);
ChromeThread::PostTask(
ChromeThread::FILE, FROM_HERE,
NewRunnableMethod(
profile_->GetDatabaseTracker(),
&webkit_database::DatabaseTracker::ResetOriginQuotaInMemory,
origin_identifier));
+ ChromeThread::PostTask(
+ ChromeThread::IO, FROM_HERE,
+ NewRunnableMethod(
+ profile_->GetAppCacheService(),
+ &ChromeAppCacheService::ResetOriginQuotaInMemory,
+ origin));
}
}
}
diff --git a/chrome/browser/extensions/extensions_service.h b/chrome/browser/extensions/extensions_service.h
index 4290f2e..0506299 100644
--- a/chrome/browser/extensions/extensions_service.h
+++ b/chrome/browser/extensions/extensions_service.h
@@ -384,6 +384,10 @@ class ExtensionsService
// Helper method. Loads extension from prefs.
void LoadInstalledExtension(const ExtensionInfo& info, bool relocalize);
+ // Helper methods to configure the storage services accordingly.
+ void GrantUnlimitedStorage(Extension* extension);
+ void RevokeUnlimitedStorage(Extension* extension);
+
// The profile this ExtensionsService is part of.
Profile* profile_;
@@ -446,9 +450,16 @@ class ExtensionsService
typedef std::vector<ComponentExtensionInfo> RegisteredComponentExtensions;
RegisteredComponentExtensions component_extension_manifests_;
+ // Collection of origins we've granted unlimited storage to. This is a
+ // map from origin to the number of extensions requiring unlimited
+ // storage within that origin.
+ typedef std::map<GURL, int> UnlimitedStorageMap;
+ UnlimitedStorageMap unlimited_storage_map_;
+
FRIEND_TEST_ALL_PREFIXES(ExtensionsServiceTest,
UpdatePendingExtensionAlreadyInstalled);
-
+ FRIEND_TEST_ALL_PREFIXES(ExtensionsServiceTest,
+ InstallAppsWithUnlimtedStorage);
DISALLOW_COPY_AND_ASSIGN(ExtensionsService);
};
diff --git a/chrome/browser/extensions/extensions_service_unittest.cc b/chrome/browser/extensions/extensions_service_unittest.cc
index 7efac33..1319da9 100644
--- a/chrome/browser/extensions/extensions_service_unittest.cc
+++ b/chrome/browser/extensions/extensions_service_unittest.cc
@@ -23,6 +23,7 @@
#include "base/version.h"
#include "chrome/browser/browser_prefs.h"
#include "chrome/browser/chrome_thread.h"
+#include "chrome/browser/appcache/chrome_appcache_service.h"
#include "chrome/browser/extensions/crx_installer.h"
#include "chrome/browser/extensions/extension_creator.h"
#include "chrome/browser/extensions/extension_error_reporter.h"
@@ -227,8 +228,22 @@ class ExtensionTestingProfile : public TestingProfile {
}
virtual ExtensionsService* GetExtensionsService() { return service_; }
+ virtual ChromeAppCacheService* GetAppCacheService() {
+ if (!appcache_service_) {
+ appcache_service_ = new ChromeAppCacheService;
+ ChromeThread::PostTask(
+ ChromeThread::IO, FROM_HERE,
+ NewRunnableMethod(appcache_service_.get(),
+ &ChromeAppCacheService::InitializeOnIOThread,
+ GetPath(), IsOffTheRecord(),
+ make_scoped_refptr(GetHostContentSettingsMap())));
+ }
+ return appcache_service_;
+ }
+
private:
ExtensionsService* service_;
+ scoped_refptr<ChromeAppCacheService> appcache_service_;
};
// Our message loop may be used in tests which require it to be an IO loop.
@@ -236,6 +251,7 @@ ExtensionsServiceTestBase::ExtensionsServiceTestBase()
: total_successes_(0),
loop_(MessageLoop::TYPE_IO),
ui_thread_(ChromeThread::UI, &loop_),
+ db_thread_(ChromeThread::DB, &loop_),
webkit_thread_(ChromeThread::WEBKIT, &loop_),
file_thread_(ChromeThread::FILE, &loop_),
io_thread_(ChromeThread::IO, &loop_) {
@@ -1166,6 +1182,66 @@ TEST_F(ExtensionsServiceTest, InstallApps) {
// ValidatePrefKeyCount(pref_count);
}
+TEST_F(ExtensionsServiceTest, InstallAppsWithUnlimtedStorage) {
+ InitializeEmptyExtensionsService();
+ EXPECT_TRUE(service_->extensions()->empty());
+ EXPECT_TRUE(service_->unlimited_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;
+ ChromeAppCacheService* appcache_service = profile_->GetAppCacheService();
+
+ // Install app1 with unlimited storage.
+ PackAndInstallExtension(extensions_path.AppendASCII("app1"), true);
+ ValidatePrefKeyCount(++pref_count);
+ ASSERT_EQ(1u, service_->extensions()->size());
+ Extension* extension = service_->extensions()->at(0);
+ const std::string id1 = extension->id();
+ EXPECT_TRUE(extension->HasApiPermission(
+ Extension::kUnlimitedStoragePermission));
+ EXPECT_TRUE(extension->web_extent().ContainsURL(
+ extension->GetFullLaunchURL()));
+ const GURL origin1(extension->GetFullLaunchURL().GetOrigin());
+ EXPECT_EQ(kint64max,
+ appcache_service->storage()->GetOriginQuotaInMemory(origin1));
+ EXPECT_FALSE(service_->unlimited_storage_map_.empty());
+
+ // Install app2 from the same origin with unlimited storage.
+ PackAndInstallExtension(extensions_path.AppendASCII("app2"), true);
+ ValidatePrefKeyCount(++pref_count);
+ ASSERT_EQ(2u, service_->extensions()->size());
+ extension = service_->extensions()->at(1);
+ const std::string id2 = extension->id();
+ EXPECT_TRUE(extension->HasApiPermission(
+ Extension::kUnlimitedStoragePermission));
+ EXPECT_TRUE(extension->web_extent().ContainsURL(
+ extension->GetFullLaunchURL()));
+ const GURL origin2(extension->GetFullLaunchURL().GetOrigin());
+ EXPECT_EQ(origin1, origin2);
+ EXPECT_EQ(kint64max,
+ appcache_service->storage()->GetOriginQuotaInMemory(origin2));
+ EXPECT_FALSE(service_->unlimited_storage_map_.empty());
+
+ // Uninstall one of them, unlimited storage should still be granted
+ // to the origin.
+ service_->UninstallExtension(id1, false);
+ loop_.RunAllPending();
+ EXPECT_EQ(1u, service_->extensions()->size());
+ EXPECT_EQ(kint64max,
+ appcache_service->storage()->GetOriginQuotaInMemory(origin1));
+ EXPECT_FALSE(service_->unlimited_storage_map_.empty());
+
+ // Uninstall the other, unlimited storage should be revoked.
+ service_->UninstallExtension(id2, false);
+ loop_.RunAllPending();
+ EXPECT_EQ(0u, service_->extensions()->size());
+ EXPECT_EQ(-1L,
+ appcache_service->storage()->GetOriginQuotaInMemory(origin2));
+ EXPECT_TRUE(service_->unlimited_storage_map_.empty());
+}
+
// Test that when an extension version is reinstalled, nothing happens.
TEST_F(ExtensionsServiceTest, Reinstall) {
InitializeEmptyExtensionsService();
diff --git a/chrome/browser/extensions/extensions_service_unittest.h b/chrome/browser/extensions/extensions_service_unittest.h
index aaa4b54..62f6a95 100644
--- a/chrome/browser/extensions/extensions_service_unittest.h
+++ b/chrome/browser/extensions/extensions_service_unittest.h
@@ -45,6 +45,7 @@ class ExtensionsServiceTestBase : public testing::Test {
size_t total_successes_;
MessageLoop loop_;
ChromeThread ui_thread_;
+ ChromeThread db_thread_;
ChromeThread webkit_thread_;
ChromeThread file_thread_;
ChromeThread io_thread_;
diff --git a/chrome/test/data/extensions/app1/manifest.json b/chrome/test/data/extensions/app1/manifest.json
index c3e1eee..cb6ce98 100644
--- a/chrome/test/data/extensions/app1/manifest.json
+++ b/chrome/test/data/extensions/app1/manifest.json
@@ -1,6 +1,7 @@
{
"name": "Test App 1",
"version": "1",
+ "permissions": ["unlimited_storage"],
"app": {
"urls": [
"http://www.example.com/path1",
diff --git a/chrome/test/data/extensions/app2/manifest.json b/chrome/test/data/extensions/app2/manifest.json
index 195e21d..29c940a 100644
--- a/chrome/test/data/extensions/app2/manifest.json
+++ b/chrome/test/data/extensions/app2/manifest.json
@@ -1,13 +1,14 @@
{
"name": "Test App 2",
"version": "1",
+ "permissions": ["unlimited_storage"],
"app": {
"urls": [
"http://www.example.com/path3",
"http://www.example.com/path4"
],
"launch": {
- "web_url": "http://www.examle.com/path4/foo.html"
+ "web_url": "http://www.example.com/path4/foo.html"
}
}
}