diff options
author | michaeln@google.com <michaeln@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-17 01:29:29 +0000 |
---|---|---|
committer | michaeln@google.com <michaeln@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-17 01:29:29 +0000 |
commit | cca14717e2a53023829bae337d9f92d51c2fe7d5 (patch) | |
tree | 5aa800482ff0b2bc63fac530dc61c96e8939f27d /chrome/browser/extensions | |
parent | 50c851f30264d9a7ee512926e2b4b8c5b06dd892 (diff) | |
download | chromium_src-cca14717e2a53023829bae337d9f92d51c2fe7d5.zip chromium_src-cca14717e2a53023829bae337d9f92d51c2fe7d5.tar.gz chromium_src-cca14717e2a53023829bae337d9f92d51c2fe7d5.tar.bz2 |
Add the quota::SpecialStoragePolicy interface and an implementation that grants
'protected' and 'unlimited' storage rights to chrome extensions and applications.
BUG=52357
TEST=extension_special_storage_policy_unittest.cc
Review URL: http://codereview.chromium.org/6299012
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@75216 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/extensions')
3 files changed, 303 insertions, 0 deletions
diff --git a/chrome/browser/extensions/extension_special_storage_policy.cc b/chrome/browser/extensions/extension_special_storage_policy.cc new file mode 100644 index 0000000..1a840fc --- /dev/null +++ b/chrome/browser/extensions/extension_special_storage_policy.cc @@ -0,0 +1,93 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/extensions/extension_special_storage_policy.h" + +#include "base/logging.h" +#include "chrome/common/extensions/extension.h" +#include "chrome/common/url_constants.h" + +bool ExtensionSpecialStoragePolicy::IsStorageProtected(const GURL& origin) { + if (origin.SchemeIs(chrome::kExtensionScheme)) + return true; + base::AutoLock locker(lock_); + return protected_apps_.Contains(origin); +} + +bool ExtensionSpecialStoragePolicy::IsStorageUnlimited(const GURL& origin) { + base::AutoLock locker(lock_); + return unlimited_extensions_.Contains(origin); +} + +void ExtensionSpecialStoragePolicy::GrantRightsForExtension( + const Extension* extension) { + DCHECK(extension); + if (!extension->is_hosted_app() && + !extension->HasApiPermission(Extension::kUnlimitedStoragePermission)) { + return; + } + base::AutoLock locker(lock_); + if (extension->is_hosted_app()) + protected_apps_.Add(extension); + if (extension->HasApiPermission(Extension::kUnlimitedStoragePermission)) + unlimited_extensions_.Add(extension); +} + +void ExtensionSpecialStoragePolicy::RevokeRightsForExtension( + const Extension* extension) { + DCHECK(extension); + if (!extension->is_hosted_app() && + !extension->HasApiPermission(Extension::kUnlimitedStoragePermission)) { + return; + } + base::AutoLock locker(lock_); + if (extension->is_hosted_app()) + protected_apps_.Remove(extension); + if (extension->HasApiPermission(Extension::kUnlimitedStoragePermission)) + unlimited_extensions_.Remove(extension); +} + +void ExtensionSpecialStoragePolicy::RevokeRightsForAllExtensions() { + base::AutoLock locker(lock_); + protected_apps_.Clear(); + unlimited_extensions_.Clear(); +} + +//----------------------------------------------------------------------------- +// SpecialCollection helper class +//----------------------------------------------------------------------------- + +bool ExtensionSpecialStoragePolicy::SpecialCollection::Contains( + const GURL& origin) { + CachedResults::const_iterator found = cached_resuts_.find(origin); + if (found != cached_resuts_.end()) + return found->second; + + for (Extensions::const_iterator iter = extensions_.begin(); + iter != extensions_.end(); ++iter) { + if ((*iter)->OverlapsWithOrigin(origin)) { + cached_resuts_[origin] = true; + return true; + } + } + cached_resuts_[origin] = false; + return false; +} + +void ExtensionSpecialStoragePolicy::SpecialCollection::Add( + const Extension* extension) { + cached_resuts_.clear(); + extensions_.insert(extension); +} + +void ExtensionSpecialStoragePolicy::SpecialCollection::Remove( + const Extension* extension) { + cached_resuts_.clear(); + extensions_.erase(extension); +} + +void ExtensionSpecialStoragePolicy::SpecialCollection::Clear() { + cached_resuts_.clear(); + extensions_.clear(); +} diff --git a/chrome/browser/extensions/extension_special_storage_policy.h b/chrome/browser/extensions/extension_special_storage_policy.h new file mode 100644 index 0000000..72ab89b --- /dev/null +++ b/chrome/browser/extensions/extension_special_storage_policy.h @@ -0,0 +1,53 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_SPECIAL_STORAGE_POLICY_H_ +#define CHROME_BROWSER_EXTENSIONS_EXTENSION_SPECIAL_STORAGE_POLICY_H_ +#pragma once + +#include <map> +#include <set> + +#include "base/synchronization/lock.h" +#include "googleurl/src/gurl.h" +#include "webkit/quota/special_storage_policy.h" + +class Extension; + +// Special rights are granted to 'extensions' and 'applications'. The +// storage subsystems and the browsing data remover query this interface +// to determine which origins have these rights. +class ExtensionSpecialStoragePolicy : public quota::SpecialStoragePolicy { + public: + // SpecialStoragePolicy methods used by storage subsystems and the browsing + // data remover. These methods are safe to call on any thread. + virtual bool IsStorageProtected(const GURL& origin); + virtual bool IsStorageUnlimited(const GURL& origin); + + // Methods used by the ExtensionService to populate this class. + void GrantRightsForExtension(const Extension* extension); + void RevokeRightsForExtension(const Extension* extension); + void RevokeRightsForAllExtensions(); + + private: + class SpecialCollection { + public: + bool Contains(const GURL& origin); + void Add(const Extension* extension); + void Remove(const Extension* extension); + void Clear(); + + private: + typedef std::map<GURL, bool> CachedResults; + typedef std::set<const Extension*> Extensions; + Extensions extensions_; + CachedResults cached_resuts_; + }; + + base::Lock lock_; // Synchronize all access to the collections. + SpecialCollection protected_apps_; + SpecialCollection unlimited_extensions_; +}; + +#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_SPECIAL_STORAGE_POLICY_H_ diff --git a/chrome/browser/extensions/extension_special_storage_policy_unittest.cc b/chrome/browser/extensions/extension_special_storage_policy_unittest.cc new file mode 100644 index 0000000..9597fb8 --- /dev/null +++ b/chrome/browser/extensions/extension_special_storage_policy_unittest.cc @@ -0,0 +1,157 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/values.h" +#include "chrome/browser/extensions/extension_special_storage_policy.h" +#include "chrome/common/extensions/extension.h" +#include "chrome/common/extensions/extension_constants.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace keys = extension_manifest_keys; + +class ExtensionSpecialStoragePolicyTest : public testing::Test { + protected: + scoped_refptr<Extension> CreateProtectedApp() { +#if defined(OS_WIN) + FilePath path(FILE_PATH_LITERAL("c:\\foo")); +#elif defined(OS_POSIX) + FilePath path(FILE_PATH_LITERAL("/foo")); +#endif + DictionaryValue manifest; + manifest.SetString(keys::kName, "Protected"); + manifest.SetString(keys::kVersion, "1"); + manifest.SetString(keys::kLaunchWebURL, "http://explicit/protected/start"); + ListValue* list = new ListValue(); + list->Append(Value::CreateStringValue("http://explicit/protected")); + list->Append(Value::CreateStringValue("*://*.wildcards/protected")); + manifest.Set(keys::kWebURLs, list); + std::string error; + scoped_refptr<Extension> protected_app = Extension::Create( + path, Extension::INVALID, manifest, false, &error); + EXPECT_TRUE(protected_app.get()) << error; + return protected_app; + } + + scoped_refptr<Extension> CreateUnlimitedApp() { +#if defined(OS_WIN) + FilePath path(FILE_PATH_LITERAL("c:\\bar")); +#elif defined(OS_POSIX) + FilePath path(FILE_PATH_LITERAL("/bar")); +#endif + DictionaryValue manifest; + manifest.SetString(keys::kName, "Unlimited"); + manifest.SetString(keys::kVersion, "1"); + manifest.SetString(keys::kLaunchWebURL, "http://explicit/unlimited/start"); + ListValue* list = new ListValue(); + list->Append(Value::CreateStringValue("unlimitedStorage")); + manifest.Set(keys::kPermissions, list); + list = new ListValue(); + list->Append(Value::CreateStringValue("http://explicit/unlimited")); + list->Append(Value::CreateStringValue("*://*.wildcards/unlimited")); + manifest.Set(keys::kWebURLs, list); + std::string error; + scoped_refptr<Extension> unlimited_app = Extension::Create( + path, Extension::INVALID, manifest, false, &error); + EXPECT_TRUE(unlimited_app.get()) << error; + return unlimited_app; + } +}; + +TEST_F(ExtensionSpecialStoragePolicyTest, EmptyPolicy) { + const GURL kHttpUrl("http://foo"); + const GURL kExtensionUrl("chrome-extension://bar"); + + scoped_refptr<ExtensionSpecialStoragePolicy> policy( + new ExtensionSpecialStoragePolicy); + + ASSERT_FALSE(policy->IsStorageUnlimited(kHttpUrl)); + ASSERT_FALSE(policy->IsStorageUnlimited(kHttpUrl)); // test cached result + ASSERT_FALSE(policy->IsStorageUnlimited(kExtensionUrl)); + ASSERT_FALSE(policy->IsStorageProtected(kHttpUrl)); + + // This one is just based on the scheme. + ASSERT_TRUE(policy->IsStorageProtected(kExtensionUrl)); +} + + +TEST_F(ExtensionSpecialStoragePolicyTest, AppWithProtectedStorage) { + scoped_refptr<Extension> extension(CreateProtectedApp()); + scoped_refptr<ExtensionSpecialStoragePolicy> policy( + new ExtensionSpecialStoragePolicy); + policy->GrantRightsForExtension(extension); + EXPECT_FALSE(policy->IsStorageUnlimited(extension->url())); + EXPECT_FALSE(policy->IsStorageUnlimited(GURL("http://explicit/"))); + EXPECT_TRUE(policy->IsStorageProtected(GURL("http://explicit/"))); + EXPECT_TRUE(policy->IsStorageProtected(GURL("http://explicit:6000/"))); + EXPECT_TRUE(policy->IsStorageProtected(GURL("http://foo.wildcards/"))); + EXPECT_TRUE(policy->IsStorageProtected(GURL("https://bar.wildcards/"))); + EXPECT_FALSE(policy->IsStorageProtected(GURL("http://not_listed/"))); + + policy->RevokeRightsForExtension(extension); + EXPECT_FALSE(policy->IsStorageProtected(GURL("http://explicit/"))); + EXPECT_FALSE(policy->IsStorageProtected(GURL("http://foo.wildcards/"))); + EXPECT_FALSE(policy->IsStorageProtected(GURL("https://bar.wildcards/"))); +} + +TEST_F(ExtensionSpecialStoragePolicyTest, AppWithUnlimitedStorage) { + scoped_refptr<Extension> extension(CreateUnlimitedApp()); + scoped_refptr<ExtensionSpecialStoragePolicy> policy( + new ExtensionSpecialStoragePolicy); + policy->GrantRightsForExtension(extension); + EXPECT_TRUE(policy->IsStorageProtected(GURL("http://explicit/"))); + EXPECT_TRUE(policy->IsStorageProtected(GURL("http://explicit:6000/"))); + EXPECT_TRUE(policy->IsStorageProtected(GURL("https://foo.wildcards/"))); + EXPECT_TRUE(policy->IsStorageProtected(GURL("https://foo.wildcards/"))); + EXPECT_TRUE(policy->IsStorageProtected(GURL("http://bar.wildcards/"))); + EXPECT_FALSE(policy->IsStorageProtected(GURL("http://not_listed/"))); + EXPECT_TRUE(policy->IsStorageUnlimited(extension->url())); + EXPECT_TRUE(policy->IsStorageUnlimited(GURL("http://explicit/"))); + EXPECT_TRUE(policy->IsStorageUnlimited(GURL("http://explicit:6000/"))); + EXPECT_TRUE(policy->IsStorageUnlimited(GURL("https://foo.wildcards/"))); + EXPECT_TRUE(policy->IsStorageUnlimited(GURL("https://bar.wildcards/"))); + EXPECT_FALSE(policy->IsStorageUnlimited(GURL("http://not_listed/"))); + + policy->RevokeRightsForExtension(extension); + EXPECT_FALSE(policy->IsStorageProtected(GURL("http://explicit/"))); + EXPECT_FALSE(policy->IsStorageProtected(GURL("https://foo.wildcards/"))); + EXPECT_FALSE(policy->IsStorageProtected(GURL("https://foo.wildcards/"))); + EXPECT_FALSE(policy->IsStorageProtected(GURL("http://bar.wildcards/"))); + EXPECT_FALSE(policy->IsStorageUnlimited(GURL("http://explicit/"))); + EXPECT_FALSE(policy->IsStorageUnlimited(GURL("https://foo.wildcards/"))); + EXPECT_FALSE(policy->IsStorageUnlimited(GURL("https://bar.wildcards/"))); +} + +TEST_F(ExtensionSpecialStoragePolicyTest, OverlappingApps) { + scoped_refptr<Extension> protected_app(CreateProtectedApp()); + scoped_refptr<Extension> unlimited_app(CreateUnlimitedApp()); + scoped_refptr<ExtensionSpecialStoragePolicy> policy( + new ExtensionSpecialStoragePolicy); + policy->GrantRightsForExtension(protected_app); + policy->GrantRightsForExtension(unlimited_app); + + EXPECT_TRUE(policy->IsStorageProtected(GURL("http://explicit/"))); + EXPECT_TRUE(policy->IsStorageProtected(GURL("http://explicit:6000/"))); + EXPECT_TRUE(policy->IsStorageProtected(GURL("https://foo.wildcards/"))); + EXPECT_TRUE(policy->IsStorageProtected(GURL("https://foo.wildcards/"))); + EXPECT_TRUE(policy->IsStorageProtected(GURL("http://bar.wildcards/"))); + EXPECT_FALSE(policy->IsStorageProtected(GURL("http://not_listed/"))); + EXPECT_TRUE(policy->IsStorageUnlimited(GURL("http://explicit/"))); + EXPECT_TRUE(policy->IsStorageUnlimited(GURL("http://explicit:6000/"))); + EXPECT_TRUE(policy->IsStorageUnlimited(GURL("https://foo.wildcards/"))); + EXPECT_TRUE(policy->IsStorageUnlimited(GURL("https://bar.wildcards/"))); + EXPECT_FALSE(policy->IsStorageUnlimited(GURL("http://not_listed/"))); + + policy->RevokeRightsForExtension(unlimited_app); + EXPECT_FALSE(policy->IsStorageUnlimited(GURL("http://explicit/"))); + EXPECT_FALSE(policy->IsStorageUnlimited(GURL("https://foo.wildcards/"))); + EXPECT_FALSE(policy->IsStorageUnlimited(GURL("https://bar.wildcards/"))); + EXPECT_TRUE(policy->IsStorageProtected(GURL("http://explicit/"))); + EXPECT_TRUE(policy->IsStorageProtected(GURL("http://foo.wildcards/"))); + EXPECT_TRUE(policy->IsStorageProtected(GURL("https://bar.wildcards/"))); + + policy->RevokeRightsForExtension(protected_app); + EXPECT_FALSE(policy->IsStorageProtected(GURL("http://explicit/"))); + EXPECT_FALSE(policy->IsStorageProtected(GURL("http://foo.wildcards/"))); + EXPECT_FALSE(policy->IsStorageProtected(GURL("https://bar.wildcards/"))); +} |