summaryrefslogtreecommitdiffstats
path: root/chrome/browser/extensions
diff options
context:
space:
mode:
authormichaeln@google.com <michaeln@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-17 01:29:29 +0000
committermichaeln@google.com <michaeln@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-17 01:29:29 +0000
commitcca14717e2a53023829bae337d9f92d51c2fe7d5 (patch)
tree5aa800482ff0b2bc63fac530dc61c96e8939f27d /chrome/browser/extensions
parent50c851f30264d9a7ee512926e2b4b8c5b06dd892 (diff)
downloadchromium_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')
-rw-r--r--chrome/browser/extensions/extension_special_storage_policy.cc93
-rw-r--r--chrome/browser/extensions/extension_special_storage_policy.h53
-rw-r--r--chrome/browser/extensions/extension_special_storage_policy_unittest.cc157
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/")));
+}