diff options
author | mpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-12 21:50:42 +0000 |
---|---|---|
committer | mpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-12 21:50:42 +0000 |
commit | abaccb2cb8cff8138e5ea9daf420645e5852c9eb (patch) | |
tree | 76e9828a7e39dabbc61153c8abdd11fd10794dab /chrome/common | |
parent | 5b3dd2d4c849d348cc6aa8bdeabcf4a9f82d815e (diff) | |
download | chromium_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.cc | 19 | ||||
-rw-r--r-- | chrome/common/extensions/extension.h | 11 | ||||
-rw-r--r-- | chrome/common/extensions/extension_unittest.cc | 80 |
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()); +} |