diff options
author | michaeln@chromium.org <michaeln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-13 21:59:48 +0000 |
---|---|---|
committer | michaeln@chromium.org <michaeln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-13 21:59:48 +0000 |
commit | c2c263cd9f2ac658d6dc35ecbd4551ca0c5cb154 (patch) | |
tree | 519a7a765fd452637ca925f7a29794524e9cee32 | |
parent | 3f4512be44cac7c017d93d4beedd0d6b49bec737 (diff) | |
download | chromium_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.cc | 89 | ||||
-rw-r--r-- | chrome/browser/extensions/extensions_service.h | 13 | ||||
-rw-r--r-- | chrome/browser/extensions/extensions_service_unittest.cc | 76 | ||||
-rw-r--r-- | chrome/browser/extensions/extensions_service_unittest.h | 1 | ||||
-rw-r--r-- | chrome/test/data/extensions/app1/manifest.json | 1 | ||||
-rw-r--r-- | chrome/test/data/extensions/app2/manifest.json | 3 |
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" } } } |