diff options
author | rafaelw@chromium.org <rafaelw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-03-23 05:05:49 +0000 |
---|---|---|
committer | rafaelw@chromium.org <rafaelw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-03-23 05:05:49 +0000 |
commit | 7197f4999afa5e767fa9ed76fdc7e67db080f9d2 (patch) | |
tree | 52eba2af9f010576998b0d71ac2e9dfa4f2581ca /chrome | |
parent | 648200ffe8c0d0fc89b577297e1ad5109b97fc5a (diff) | |
download | chromium_src-7197f4999afa5e767fa9ed76fdc7e67db080f9d2.zip chromium_src-7197f4999afa5e767fa9ed76fdc7e67db080f9d2.tar.gz chromium_src-7197f4999afa5e767fa9ed76fdc7e67db080f9d2.tar.bz2 |
Support for extensions permissions. This CL only contains, parsing, initializing values into Extension, outputting values to the extension_ui, and appropriate unit test changes
Review URL: http://codereview.chromium.org/42480
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@12273 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
10 files changed, 147 insertions, 10 deletions
diff --git a/chrome/browser/extensions/extension.cc b/chrome/browser/extensions/extension.cc index 794b943..57fbbbc 100644 --- a/chrome/browser/extensions/extension.cc +++ b/chrome/browser/extensions/extension.cc @@ -8,6 +8,7 @@ #include "base/logging.h" #include "base/string_util.h" #include "net/base/net_util.h" +#include "chrome/browser/extensions/extension_error_reporter.h" #include "chrome/common/extensions/user_script.h" #include "chrome/common/resource_bundle.h" #include "chrome/common/url_constants.h" @@ -15,19 +16,20 @@ const char Extension::kManifestFilename[] = "manifest.json"; const wchar_t* Extension::kContentScriptsKey = L"content_scripts"; +const wchar_t* Extension::kCssKey = L"css"; const wchar_t* Extension::kDescriptionKey = L"description"; const wchar_t* Extension::kFormatVersionKey = L"format_version"; const wchar_t* Extension::kIdKey = L"id"; const wchar_t* Extension::kJsKey = L"js"; -const wchar_t* Extension::kCssKey = L"css"; const wchar_t* Extension::kMatchesKey = L"matches"; const wchar_t* Extension::kNameKey = L"name"; -const wchar_t* Extension::kRunAtKey = L"run_at"; -const wchar_t* Extension::kVersionKey = L"version"; -const wchar_t* Extension::kZipHashKey = L"zip_hash"; +const wchar_t* Extension::kPermissionsKey = L"permissions"; const wchar_t* Extension::kPluginsDirKey = L"plugins_dir"; +const wchar_t* Extension::kRunAtKey = L"run_at"; const wchar_t* Extension::kThemeKey = L"theme"; const wchar_t* Extension::kToolstripsKey = L"toolstrips"; +const wchar_t* Extension::kVersionKey = L"version"; +const wchar_t* Extension::kZipHashKey = L"zip_hash"; const char* Extension::kRunAtDocumentStartValue = "document_start"; const char* Extension::kRunAtDocumentEndValue = "document_end"; @@ -65,6 +67,15 @@ const char* Extension::kInvalidMatchesError = "Required value 'content_scripts[*].matches' is missing or invalid."; const char* Extension::kInvalidNameError = "Required value 'name' is missing or invalid."; +const char* Extension::kInvalidPermissionsError = + "Required value 'permissions' is missing or invalid."; +const char* Extension::kInvalidPermissionCountWarning = + "Warning, 'permissions' key found, but array is empty."; +const char* Extension::kInvalidPermissionError = + "Invalid value for 'permissions[*]'."; +const char* Extension::kInvalidPermissionSchemeError = + "Invalid scheme for 'permissions[*]'. Only 'http' and 'https' are " + "allowed."; const char* Extension::kInvalidPluginsDirError = "Invalid value for 'plugins_dir'."; const char* Extension::kInvalidRunAtError = @@ -447,5 +458,45 @@ bool Extension::InitFromValue(const DictionaryValue& source, } } + // Initialize the permissions (optional). + if (source.HasKey(kPermissionsKey)) { + ListValue* hosts = NULL; + if (!source.GetList(kPermissionsKey, &hosts)) { + *error = FormatErrorMessage(kInvalidPermissionsError, ""); + return false; + } + + if (hosts->GetSize() == 0) { + ExtensionErrorReporter::GetInstance()->ReportError( + kInvalidPermissionCountWarning, false); + } + + for (size_t i = 0; i < hosts->GetSize(); ++i) { + std::string host_str; + if (!hosts->GetString(i, &host_str)) { + *error = FormatErrorMessage(kInvalidPermissionError, + IntToString(i)); + return false; + } + + URLPattern pattern; + if (!pattern.Parse(host_str)) { + *error = FormatErrorMessage(kInvalidPermissionError, + IntToString(i)); + return false; + } + + // Only accept http/https persmissions at the moment. + if ((pattern.scheme() != chrome::kHttpScheme) && + (pattern.scheme() != chrome::kHttpsScheme)) { + *error = FormatErrorMessage(kInvalidPermissionSchemeError, + IntToString(i)); + return false; + } + + permissions_.push_back(pattern); + } + } + return true; } diff --git a/chrome/browser/extensions/extension.h b/chrome/browser/extensions/extension.h index fadea2d..565c8b5 100644 --- a/chrome/browser/extensions/extension.h +++ b/chrome/browser/extensions/extension.h @@ -7,6 +7,7 @@ #include <string> #include <vector> +#include <map> #include "base/file_path.h" #include "base/scoped_ptr.h" @@ -14,6 +15,7 @@ #include "base/values.h" #include "base/version.h" #include "chrome/browser/extensions/user_script_master.h" +#include "chrome/common/extensions/url_pattern.h" #include "googleurl/src/gurl.h" // Represents a Chromium extension. @@ -31,19 +33,20 @@ class Extension { // Keys used in JSON representation of extensions. static const wchar_t* kContentScriptsKey; + static const wchar_t* kCssKey; static const wchar_t* kDescriptionKey; static const wchar_t* kFormatVersionKey; static const wchar_t* kIdKey; static const wchar_t* kJsKey; - static const wchar_t* kCssKey; static const wchar_t* kMatchesKey; static const wchar_t* kNameKey; - static const wchar_t* kRunAtKey; - static const wchar_t* kVersionKey; - static const wchar_t* kZipHashKey; + static const wchar_t* kPermissionsKey; static const wchar_t* kPluginsDirKey; + static const wchar_t* kRunAtKey; static const wchar_t* kThemeKey; static const wchar_t* kToolstripsKey; + static const wchar_t* kVersionKey; + static const wchar_t* kZipHashKey; // Some values expected in manifests. static const char* kRunAtDocumentStartValue; @@ -69,6 +72,10 @@ class Extension { static const char* kInvalidToolstripError; static const char* kInvalidToolstripsError; static const char* kInvalidVersionError; + static const char* kInvalidPermissionsError; + static const char* kInvalidPermissionCountWarning; + static const char* kInvalidPermissionError; + static const char* kInvalidPermissionSchemeError; static const char* kInvalidZipHashError; static const char* kMissingFileError; @@ -118,6 +125,8 @@ class Extension { const UserScriptList& content_scripts() const { return content_scripts_; } const FilePath& plugins_dir() const { return plugins_dir_; } const std::vector<std::string>& toolstrips() const { return toolstrips_; } + const std::vector<URLPattern>& permissions() const { + return permissions_; } private: // Helper method that loads a UserScript object from a @@ -167,6 +176,8 @@ class Extension { // A map of resource id's to relative file paths. std::map<const std::wstring, std::string> theme_paths_; + std::vector<URLPattern> permissions_; + // We implement copy, but not assign. void operator=(const Extension&); }; diff --git a/chrome/browser/extensions/extension_unittest.cc b/chrome/browser/extensions/extension_unittest.cc index e78e9d2..b11e2dd 100644 --- a/chrome/browser/extensions/extension_unittest.cc +++ b/chrome/browser/extensions/extension_unittest.cc @@ -5,6 +5,7 @@ #include "base/string_util.h" #include "base/path_service.h" #include "chrome/browser/extensions/extension.h" +#include "chrome/browser/extensions/extension_error_reporter.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/json_value_serializer.h" #include "testing/gtest/include/gtest/gtest.h" @@ -20,6 +21,7 @@ TEST(ExtensionTest, InitFromValueInvalid) { #endif Extension extension(path); std::string error; + ExtensionErrorReporter::Init(false); // Start with a valid extension manifest std::wstring extensions_dir; @@ -170,6 +172,43 @@ TEST(ExtensionTest, InitFromValueInvalid) { css_files->Set(0, Value::CreateIntegerValue(42)); EXPECT_FALSE(extension.InitFromValue(*input_value, &error)); EXPECT_TRUE(MatchPattern(error, Extension::kInvalidCssError)); + + // Test missing and invalid permissions array + input_value.reset(static_cast<DictionaryValue*>(valid_value->DeepCopy())); + EXPECT_TRUE(extension.InitFromValue(*input_value, &error)); + ListValue* permissions = NULL; + input_value->GetList(Extension::kPermissionsKey, &permissions); + ASSERT_FALSE(NULL == permissions); + + permissions = new ListValue; + input_value->Set(Extension::kPermissionsKey, permissions); + EXPECT_TRUE(extension.InitFromValue(*input_value, &error)); + const std::vector<std::string>* error_vector = + ExtensionErrorReporter::GetInstance()->GetErrors(); + const std::string log_error = error_vector->at(error_vector->size() - 1); + EXPECT_TRUE(MatchPattern(log_error, + Extension::kInvalidPermissionCountWarning)); + + input_value->Set(Extension::kPermissionsKey, Value::CreateIntegerValue(9)); + EXPECT_FALSE(extension.InitFromValue(*input_value, &error)); + EXPECT_TRUE(MatchPattern(error, Extension::kInvalidPermissionsError)); + + input_value.reset(static_cast<DictionaryValue*>(valid_value->DeepCopy())); + input_value->GetList(Extension::kPermissionsKey, &permissions); + permissions->Set(0, Value::CreateIntegerValue(24)); + EXPECT_FALSE(extension.InitFromValue(*input_value, &error)); + EXPECT_TRUE(MatchPattern(error, Extension::kInvalidPermissionError)); + + permissions->Set(0, Value::CreateStringValue("www.google.com")); + EXPECT_FALSE(extension.InitFromValue(*input_value, &error)); + EXPECT_TRUE(MatchPattern(error, Extension::kInvalidPermissionError)); + + // Test permissions scheme. + input_value.reset(static_cast<DictionaryValue*>(valid_value->DeepCopy())); + input_value->GetList(Extension::kPermissionsKey, &permissions); + permissions->Set(0, Value::CreateStringValue("file:///C:/foo.txt")); + EXPECT_FALSE(extension.InitFromValue(*input_value, &error)); + EXPECT_TRUE(MatchPattern(error, Extension::kInvalidPermissionSchemeError)); } TEST(ExtensionTest, InitFromValueValid) { diff --git a/chrome/browser/extensions/extensions_service_unittest.cc b/chrome/browser/extensions/extensions_service_unittest.cc index b3328d3..4d4b4f7 100644 --- a/chrome/browser/extensions/extensions_service_unittest.cc +++ b/chrome/browser/extensions/extensions_service_unittest.cc @@ -14,6 +14,7 @@ #include "chrome/browser/extensions/extension.h" #include "chrome/browser/extensions/extension_error_reporter.h" #include "chrome/browser/extensions/extensions_service.h" +#include "chrome/common/extensions/url_pattern.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/json_value_serializer.h" #include "testing/gtest/include/gtest/gtest.h" @@ -185,6 +186,10 @@ TEST_F(ExtensionsServiceTest, LoadAllExtensionsFromDirectorySuccess) { EXPECT_EQ("http://*.news.com/*", scripts[1].url_patterns()[0].GetAsString()); EXPECT_EQ(extension->path().AppendASCII("js_files").AppendASCII("script3.js") .value(), scripts[1].js_scripts()[0].path().value()); + const std::vector<URLPattern> permissions = extension->permissions(); + ASSERT_EQ(2u, permissions.size()); + EXPECT_EQ("http://*.google.com/*", permissions[0].GetAsString()); + EXPECT_EQ("https://*.google.com/*", permissions[1].GetAsString()); ASSERT_EQ(2u, toolstrips.size()); EXPECT_EQ("toolstrip1.html", toolstrips[0]); EXPECT_EQ("toolstrip2.html", toolstrips[1]); diff --git a/chrome/browser/extensions/extensions_ui.cc b/chrome/browser/extensions/extensions_ui.cc index ee273dc..236b92a 100644 --- a/chrome/browser/extensions/extensions_ui.cc +++ b/chrome/browser/extensions/extensions_ui.cc @@ -9,6 +9,7 @@ #include "chrome/browser/extensions/extensions_service.h" #include "chrome/browser/extensions/extension_error_reporter.h" #include "chrome/browser/profile.h" +#include "chrome/common/extensions/url_pattern.h" #include "chrome/common/jstemplate_builder.h" #include "chrome/common/l10n_util.h" #include "chrome/common/resource_bundle.h" @@ -148,6 +149,16 @@ DictionaryValue* ExtensionsDOMHandler::CreateExtensionDetailValue( } extension_data->Set(L"content_scripts", content_script_list); + // Add permissions + ListValue *permission_list = new ListValue; + std::vector<URLPattern> permissions = extension->permissions(); + for (std::vector<URLPattern>::iterator permission = permissions.begin(); + permission != permissions.end(); ++permission) { + permission_list->Append(Value::CreateStringValue( + permission->GetAsString())); + } + extension_data->Set(L"permissions", permission_list); + return extension_data; } diff --git a/chrome/browser/resources/extensions.html b/chrome/browser/resources/extensions.html index e719f91..55a21d8 100644 --- a/chrome/browser/resources/extensions.html +++ b/chrome/browser/resources/extensions.html @@ -14,6 +14,7 @@ var extensionDataFormat = { "name": "Extension Name", "description": "Extension long format description", "version": "1.0.231", + "permissions": ["http://*/*", "http://other.com/*"], "content_scripts": [ { "js": ["script1_file1.js", "script1_file2.js"], @@ -185,14 +186,29 @@ th.enabled { <div jsdisplay="extensions.length > 0"> <div class="extension" jsselect="extensions"> <div class="extension-name" jscontent="name"> - sExtension Name</div> + Extension Name + </div> <dl> <dd> <span jscontent="description">Extension Description</span> </dd> <dd>Version: <span jscontent="version">x.x.x.x</span></dd> </dl> - + <table> + <thead> + <tr><th colspan="2">Configuration</th></tr> + </thead> + <tbody> + <tr> + <td>Permissions</td> + <td> + <span jsselect="permissions" + jscontent="(($index > 0) ? ', ' : '') + $this"> + </span> + </td> + </tr> + </tbody> + </table> <table jsselect="content_scripts"> <thead> <tr><th colspan="2">Content Script</th></tr> diff --git a/chrome/test/data/extensions/good/extension1/1/manifest.json b/chrome/test/data/extensions/good/extension1/1/manifest.json index 63d9789..cc2104d 100644 --- a/chrome/test/data/extensions/good/extension1/1/manifest.json +++ b/chrome/test/data/extensions/good/extension1/1/manifest.json @@ -8,6 +8,7 @@ "toolstrip1.html", "toolstrip2.html" ], + "permissions": ["http://*.google.com/*", "https://*.google.com/*"], "content_scripts": [ { "matches": ["http://*.google.com/*", "https://*.google.com/*"], diff --git a/chrome/test/data/extensions/ui/create_extension_detail_value_expected_output/good-extension1.json b/chrome/test/data/extensions/ui/create_extension_detail_value_expected_output/good-extension1.json index 712ca55..11df2a1 100644 --- a/chrome/test/data/extensions/ui/create_extension_detail_value_expected_output/good-extension1.json +++ b/chrome/test/data/extensions/ui/create_extension_detail_value_expected_output/good-extension1.json @@ -2,6 +2,7 @@ "version": "1.0.0.0", "name": "My extension 1", "description": "The first extension that I made.", + "permissions": ["http://*.google.com/*", "https://*.google.com/*"], "content_scripts": [ { "matches": ["http://*.google.com/*", "https://*.google.com/*"], diff --git a/chrome/test/data/extensions/ui/create_extension_detail_value_expected_output/good-extension2.json b/chrome/test/data/extensions/ui/create_extension_detail_value_expected_output/good-extension2.json index ca8b399..eeb0fb2 100644 --- a/chrome/test/data/extensions/ui/create_extension_detail_value_expected_output/good-extension2.json +++ b/chrome/test/data/extensions/ui/create_extension_detail_value_expected_output/good-extension2.json @@ -2,5 +2,6 @@ "version": "1.0.0.0", "name": "My extension 2", "description": "", + "permissions": [], "content_scripts": [] } diff --git a/chrome/test/data/extensions/ui/create_extension_detail_value_expected_output/good-extension3.json b/chrome/test/data/extensions/ui/create_extension_detail_value_expected_output/good-extension3.json index 86aa1dd..18915a4 100644 --- a/chrome/test/data/extensions/ui/create_extension_detail_value_expected_output/good-extension3.json +++ b/chrome/test/data/extensions/ui/create_extension_detail_value_expected_output/good-extension3.json @@ -2,5 +2,6 @@ "version": "1.0", "name": "My extension 3", "description": "", + "permissions": [], "content_scripts": [] } |