summaryrefslogtreecommitdiffstats
path: root/chrome/common
diff options
context:
space:
mode:
authormpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-12 21:50:42 +0000
committermpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-12 21:50:42 +0000
commitabaccb2cb8cff8138e5ea9daf420645e5852c9eb (patch)
tree76e9828a7e39dabbc61153c8abdd11fd10794dab /chrome/common
parent5b3dd2d4c849d348cc6aa8bdeabcf4a9f82d815e (diff)
downloadchromium_src-abaccb2cb8cff8138e5ea9daf420645e5852c9eb.zip
chromium_src-abaccb2cb8cff8138e5ea9daf420645e5852c9eb.tar.gz
chromium_src-abaccb2cb8cff8138e5ea9daf420645e5852c9eb.tar.bz2
Add a method to classify what permission class an extension is in, with unit
tests. BUG=12140 Review URL: http://codereview.chromium.org/164335 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@23229 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/common')
-rw-r--r--chrome/common/extensions/extension.cc19
-rw-r--r--chrome/common/extensions/extension.h11
-rw-r--r--chrome/common/extensions/extension_unittest.cc80
3 files changed, 110 insertions, 0 deletions
diff --git a/chrome/common/extensions/extension.cc b/chrome/common/extensions/extension.cc
index 637be5e..0ed6bf5 100644
--- a/chrome/common/extensions/extension.cc
+++ b/chrome/common/extensions/extension.cc
@@ -952,6 +952,25 @@ std::set<FilePath> Extension::GetBrowserImages() {
return image_paths;
}
+Extension::PermissionClass Extension::GetPermissionClass() {
+ // Native code can do anything. Highest class.
+ if (!plugins_.empty())
+ return PERMISSION_CLASS_FULL;
+
+ // Access to other sites means the extension can steal cookies (login data)
+ // from those sites.
+ // TODO(mpcomplete): should we only classify for host access outside the
+ // extension's origin? how?
+ if (!host_permissions_.empty() || !content_scripts_.empty())
+ return PERMISSION_CLASS_HIGH;
+
+ // Extension can access history data, bookmarks, other personal info.
+ if (!api_permissions_.empty())
+ return PERMISSION_CLASS_MEDIUM;
+
+ return PERMISSION_CLASS_LOW;
+}
+
bool Extension::GetBackgroundPageReady() {
return background_page_ready_ || background_url().is_empty();
}
diff --git a/chrome/common/extensions/extension.h b/chrome/common/extensions/extension.h
index 7969e96..1452014 100644
--- a/chrome/common/extensions/extension.h
+++ b/chrome/common/extensions/extension.h
@@ -62,6 +62,15 @@ class Extension {
static const char* kPermissionNames[];
static const size_t kNumPermissions;
+ // A classification of how dangerous an extension can be, based on what it has
+ // access to.
+ enum PermissionClass {
+ PERMISSION_CLASS_LOW = 0, // green
+ PERMISSION_CLASS_MEDIUM, // yellow
+ PERMISSION_CLASS_HIGH, // orange
+ PERMISSION_CLASS_FULL, // red
+ };
+
// An NPAPI plugin included in the extension.
struct PluginInfo {
FilePath path; // Path to the plugin.
@@ -205,6 +214,8 @@ class Extension {
// the browser might load (like themes and page action icons).
std::set<FilePath> GetBrowserImages();
+ PermissionClass GetPermissionClass();
+
// Runtime data:
// Put dynamic data about the state of a running extension below.
diff --git a/chrome/common/extensions/extension_unittest.cc b/chrome/common/extensions/extension_unittest.cc
index 6eba35a..a0eed4e 100644
--- a/chrome/common/extensions/extension_unittest.cc
+++ b/chrome/common/extensions/extension_unittest.cc
@@ -21,6 +21,14 @@ namespace errors = extension_manifest_errors;
class ExtensionTest : public testing::Test {
};
+static Value* ValueFromJSON(const std::string& json_string) {
+ std::string error;
+ JSONStringValueSerializer content_scripts(json_string);
+ Value* result = content_scripts.Deserialize(&error);
+ DCHECK(result) << error;
+ return result;
+}
+
TEST(ExtensionTest, InitFromValueInvalid) {
#if defined(OS_WIN)
FilePath path(FILE_PATH_LITERAL("c:\\foo"));
@@ -455,3 +463,75 @@ TEST(ExtensionTest, MimeTypeSniffing) {
GURL("http://www.example.com/foo.crx"), "", &result));
EXPECT_EQ("application/octet-stream", result);
}
+
+TEST(ExtensionTest, PermissionClass) {
+#if defined(OS_WIN)
+ FilePath path(FILE_PATH_LITERAL("C:\\foo"));
+#elif defined(OS_POSIX)
+ FilePath path(FILE_PATH_LITERAL("/foo"));
+#endif
+ Extension::ResetGeneratedIdCounter();
+
+ Extension extension(path);
+ std::string error;
+ DictionaryValue bare_manifest;
+ scoped_ptr<DictionaryValue> manifest;
+
+ // Start with a minimalist extension.
+ bare_manifest.SetString(keys::kVersion, "1.0.0.0");
+ bare_manifest.SetString(keys::kName, "my extension");
+ EXPECT_TRUE(extension.InitFromValue(bare_manifest, false, &error));
+ EXPECT_EQ(Extension::PERMISSION_CLASS_LOW, extension.GetPermissionClass());
+
+ // Toolstrips don't affect the permission class.
+ manifest.reset(static_cast<DictionaryValue*>(bare_manifest.DeepCopy()));
+ manifest->Set(keys::kToolstrips, ValueFromJSON(
+ "[\"toolstrip.html\", \"toolstrip2.html\"]"));
+ EXPECT_TRUE(extension.InitFromValue(*manifest, false, &error));
+ EXPECT_EQ(Extension::PERMISSION_CLASS_LOW, extension.GetPermissionClass());
+
+ // Requesting API permissions bumps you to medium.
+ manifest.reset(static_cast<DictionaryValue*>(bare_manifest.DeepCopy()));
+ manifest->Set(keys::kPermissions, ValueFromJSON(
+ "[\"tabs\", \"bookmarks\"]"));
+ EXPECT_TRUE(extension.InitFromValue(*manifest, false, &error));
+ EXPECT_EQ(Extension::PERMISSION_CLASS_MEDIUM, extension.GetPermissionClass());
+
+ // Adding a content script bumps you to high.
+ manifest.reset(static_cast<DictionaryValue*>(bare_manifest.DeepCopy()));
+ manifest->Set(keys::kContentScripts, ValueFromJSON(
+ "[{"
+ " \"matches\": [\"http://*.google.com/*\"],"
+ " \"js\": [\"script.js\"]"
+ "}]"));
+ EXPECT_TRUE(extension.InitFromValue(*manifest, false, &error));
+ EXPECT_EQ(Extension::PERMISSION_CLASS_HIGH, extension.GetPermissionClass());
+
+ // ... or asking for a host permission.
+ manifest.reset(static_cast<DictionaryValue*>(bare_manifest.DeepCopy()));
+ manifest->Set(keys::kPermissions, ValueFromJSON(
+ "[\"tabs\", \"http://google.com/*\"]"));
+ EXPECT_TRUE(extension.InitFromValue(*manifest, false, &error));
+ EXPECT_EQ(Extension::PERMISSION_CLASS_HIGH, extension.GetPermissionClass());
+
+ // Using native code (NPAPI) is automatically the max class.
+ manifest.reset(static_cast<DictionaryValue*>(bare_manifest.DeepCopy()));
+ manifest->Set(keys::kPlugins, ValueFromJSON(
+ "[{\"path\": \"harddrive_exploder.dll\"}]"));
+ EXPECT_TRUE(extension.InitFromValue(*manifest, false, &error));
+ EXPECT_EQ(Extension::PERMISSION_CLASS_FULL, extension.GetPermissionClass());
+
+ // Using everything at once should obviously be the max class as well.
+ manifest.reset(static_cast<DictionaryValue*>(bare_manifest.DeepCopy()));
+ manifest->Set(keys::kPlugins, ValueFromJSON(
+ "[{\"path\": \"harddrive_exploder.dll\"}]"));
+ manifest->Set(keys::kPermissions, ValueFromJSON(
+ "[\"tabs\", \"http://google.com/*\"]"));
+ manifest->Set(keys::kContentScripts, ValueFromJSON(
+ "[{"
+ " \"matches\": [\"http://*.google.com/*\"],"
+ " \"js\": [\"script.js\"]"
+ "}]"));
+ EXPECT_TRUE(extension.InitFromValue(*manifest, false, &error));
+ EXPECT_EQ(Extension::PERMISSION_CLASS_FULL, extension.GetPermissionClass());
+}