summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorskerner@chromium.org <skerner@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-04 21:25:31 +0000
committerskerner@chromium.org <skerner@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-04 21:25:31 +0000
commit542258c2719723200e46a45fdd7dc571ed5b90cf (patch)
tree5a7754d98ef347c17328696e62ec93bde6738d89 /chrome
parent7b1c0376a17429471d2163c31ed4dbb05a9e819f (diff)
downloadchromium_src-542258c2719723200e46a45fdd7dc571ed5b90cf.zip
chromium_src-542258c2719723200e46a45fdd7dc571ed5b90cf.tar.gz
chromium_src-542258c2719723200e46a45fdd7dc571ed5b90cf.tar.bz2
Give a helpful warning message if a url patern contains a port.
BUG=32160 TEST=ExtensionURLPatternTest.Ports,ExtensionManifestTest.* Review URL: http://codereview.chromium.org/2835034 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@76967 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/background_application_list_model_unittest.cc2
-rw-r--r--chrome/browser/extensions/convert_user_script.cc7
-rw-r--r--chrome/browser/extensions/convert_web_app.cc7
-rw-r--r--chrome/browser/extensions/crx_installer.cc6
-rw-r--r--chrome/browser/extensions/extension_context_menu_api.cc5
-rw-r--r--chrome/browser/extensions/extension_creator.cc1
-rw-r--r--chrome/browser/extensions/extension_icon_manager_unittest.cc2
-rw-r--r--chrome/browser/extensions/extension_info_map_unittest.cc5
-rw-r--r--chrome/browser/extensions/extension_prefs.cc18
-rw-r--r--chrome/browser/extensions/extension_prefs_unittest.cc6
-rw-r--r--chrome/browser/extensions/extension_service.cc20
-rw-r--r--chrome/browser/extensions/extension_special_storage_policy_unittest.cc4
-rw-r--r--chrome/browser/extensions/extension_ui_unittest.cc2
-rw-r--r--chrome/browser/extensions/extension_webrequest_api.cc3
-rw-r--r--chrome/browser/extensions/image_loading_tracker_unittest.cc2
-rw-r--r--chrome/browser/extensions/sandboxed_extension_unpacker.cc7
-rw-r--r--chrome/browser/extensions/test_extension_prefs.cc2
-rw-r--r--chrome/browser/extensions/user_script_master.cc3
-rw-r--r--chrome/browser/sync/glue/extension_util_unittest.cc4
-rw-r--r--chrome/browser/sync/glue/theme_util_unittest.cc2
-rw-r--r--chrome/browser/sync/util/extensions_activity_monitor_unittest.cc6
-rw-r--r--chrome/browser/themes/browser_theme_pack_unittest.cc3
-rw-r--r--chrome/browser/ui/cocoa/extensions/extension_install_prompt_controller_unittest.mm2
-rw-r--r--chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller_unittest.mm2
-rw-r--r--chrome/common/extensions/extension.cc125
-rw-r--r--chrome/common/extensions/extension.h35
-rw-r--r--chrome/common/extensions/extension_constants.cc11
-rw-r--r--chrome/common/extensions/extension_constants.h4
-rw-r--r--chrome/common/extensions/extension_file_util.cc8
-rw-r--r--chrome/common/extensions/extension_file_util.h1
-rw-r--r--chrome/common/extensions/extension_file_util_unittest.cc10
-rw-r--r--chrome/common/extensions/extension_manifests_unittest.cc141
-rw-r--r--chrome/common/extensions/extension_set_unittest.cc3
-rw-r--r--chrome/common/extensions/extension_unittest.cc93
-rw-r--r--chrome/common/extensions/extension_unpacker.cc7
-rw-r--r--chrome/common/extensions/url_pattern.cc59
-rw-r--r--chrome/common/extensions/url_pattern.h25
-rw-r--r--chrome/common/extensions/url_pattern_unittest.cc81
-rw-r--r--chrome/common/extensions/user_script.cc3
-rw-r--r--chrome/common/extensions/user_script_unittest.cc12
-rw-r--r--chrome/common/render_messages.cc2
-rw-r--r--chrome/common/render_messages_params.cc7
-rw-r--r--chrome/test/data/extensions/manifest_tests/content_script_match_pattern_not_string.json9
-rw-r--r--chrome/test/data/extensions/manifest_tests/forbid_ports_in_content_scripts.json14
-rw-r--r--chrome/test/data/extensions/manifest_tests/forbid_ports_in_permissions.json8
-rw-r--r--chrome/test/data/extensions/manifest_tests/web_urls_invalid_5.json13
-rw-r--r--chrome/test/data/extensions/manifest_tests/web_urls_invalid_has_port.json16
-rw-r--r--chrome/test/live_sync/live_extensions_sync_test_base.cc2
48 files changed, 629 insertions, 181 deletions
diff --git a/chrome/browser/background_application_list_model_unittest.cc b/chrome/browser/background_application_list_model_unittest.cc
index 27e8514..4f4a249 100644
--- a/chrome/browser/background_application_list_model_unittest.cc
+++ b/chrome/browser/background_application_list_model_unittest.cc
@@ -90,7 +90,7 @@ static scoped_refptr<Extension> CreateExtension(const std::string& name,
std::string error;
scoped_refptr<Extension> extension = Extension::Create(
bogus_file_path().AppendASCII(name), Extension::INVALID, manifest, false,
- &error);
+ true, &error);
// Cannot ASSERT_* here because that attempts an illegitimate return.
// Cannot EXPECT_NE here because that assumes non-pointers unlike EXPECT_EQ
EXPECT_TRUE(extension.get() != NULL) << error;
diff --git a/chrome/browser/extensions/convert_user_script.cc b/chrome/browser/extensions/convert_user_script.cc
index 0b45da8..f0ec459 100644
--- a/chrome/browser/extensions/convert_user_script.cc
+++ b/chrome/browser/extensions/convert_user_script.cc
@@ -147,7 +147,12 @@ scoped_refptr<Extension> ConvertUserScriptToExtension(
}
scoped_refptr<Extension> extension = Extension::Create(
- temp_dir.path(), Extension::INTERNAL, *root, false, error);
+ temp_dir.path(),
+ Extension::INTERNAL,
+ *root,
+ false, // Do not require key
+ false, // Disable strict checks
+ error);
if (!extension) {
NOTREACHED() << "Could not init extension " << *error;
return NULL;
diff --git a/chrome/browser/extensions/convert_web_app.cc b/chrome/browser/extensions/convert_web_app.cc
index fe082d9..66e3e8f 100644
--- a/chrome/browser/extensions/convert_web_app.cc
+++ b/chrome/browser/extensions/convert_web_app.cc
@@ -168,7 +168,12 @@ scoped_refptr<Extension> ConvertWebAppToExtension(
// Finally, create the extension object to represent the unpacked directory.
std::string error;
scoped_refptr<Extension> extension = Extension::Create(
- temp_dir.path(), Extension::INTERNAL, *root, false, &error);
+ temp_dir.path(),
+ Extension::INTERNAL,
+ *root,
+ false, // Don't require a key.
+ true, // Enable strict error checks.
+ &error);
if (!extension) {
LOG(ERROR) << error;
return NULL;
diff --git a/chrome/browser/extensions/crx_installer.cc b/chrome/browser/extensions/crx_installer.cc
index 1f494b0..39365fd 100644
--- a/chrome/browser/extensions/crx_installer.cc
+++ b/chrome/browser/extensions/crx_installer.cc
@@ -374,7 +374,11 @@ void CrxInstaller::CompleteInstall() {
// lazily and based on the Extension's root path at that moment.
std::string error;
extension_ = extension_file_util::LoadExtension(
- version_dir, install_source_, true, &error);
+ version_dir,
+ install_source_,
+ true, // Require key
+ false, // Disable strict error checks
+ &error);
CHECK(error.empty()) << error;
ReportSuccessFromFileThread();
diff --git a/chrome/browser/extensions/extension_context_menu_api.cc b/chrome/browser/extensions/extension_context_menu_api.cc
index 78f4f03..d8e93f2 100644
--- a/chrome/browser/extensions/extension_context_menu_api.cc
+++ b/chrome/browser/extensions/extension_context_menu_api.cc
@@ -138,7 +138,10 @@ bool ExtensionContextMenuFunction::ParseURLPatterns(
return false;
URLPattern pattern(ExtensionMenuManager::kAllowedSchemes);
- if (URLPattern::PARSE_SUCCESS != pattern.Parse(tmp)) {
+ // TODO(skerner): Consider enabling strict pattern parsing
+ // if this extension's location indicates that it is under development.
+ if (URLPattern::PARSE_SUCCESS != pattern.Parse(tmp,
+ URLPattern::PARSE_LENIENT)) {
error_ = ExtensionErrorUtils::FormatErrorMessage(kInvalidURLPatternError,
tmp);
return false;
diff --git a/chrome/browser/extensions/extension_creator.cc b/chrome/browser/extensions/extension_creator.cc
index a211071..e21728f 100644
--- a/chrome/browser/extensions/extension_creator.cc
+++ b/chrome/browser/extensions/extension_creator.cc
@@ -60,6 +60,7 @@ bool ExtensionCreator::InitializeInput(
extension_file_util::LoadExtension(extension_dir,
Extension::INTERNAL,
false, // key not required
+ true, // enable strict error checks
&error_message_));
if (!extension.get())
return false; // LoadExtension already set error_message_.
diff --git a/chrome/browser/extensions/extension_icon_manager_unittest.cc b/chrome/browser/extensions/extension_icon_manager_unittest.cc
index 0a4189c..6bb2445 100644
--- a/chrome/browser/extensions/extension_icon_manager_unittest.cc
+++ b/chrome/browser/extensions/extension_icon_manager_unittest.cc
@@ -111,7 +111,7 @@ TEST_F(ExtensionIconManagerTest, LoadRemoveLoad) {
scoped_refptr<Extension> extension(Extension::Create(
manifest_path.DirName(), Extension::INVALID, *manifest.get(),
- false, NULL));
+ false, true, NULL));
ASSERT_TRUE(extension.get());
TestIconManager icon_manager(this);
diff --git a/chrome/browser/extensions/extension_info_map_unittest.cc b/chrome/browser/extensions/extension_info_map_unittest.cc
index ba5a0b2..7d82dd2 100644
--- a/chrome/browser/extensions/extension_info_map_unittest.cc
+++ b/chrome/browser/extensions/extension_info_map_unittest.cc
@@ -42,7 +42,8 @@ static scoped_refptr<Extension> CreateExtension(const std::string& name) {
std::string error;
scoped_refptr<Extension> extension = Extension::Create(
- path.AppendASCII(name), Extension::INVALID, manifest, false, &error);
+ path.AppendASCII(name), Extension::INVALID, manifest, false, true,
+ &error);
EXPECT_TRUE(extension) << error;
return extension;
@@ -64,7 +65,7 @@ static scoped_refptr<Extension> LoadManifest(const std::string& dir,
std::string error;
scoped_refptr<Extension> extension = Extension::Create(
path, Extension::INVALID, *static_cast<DictionaryValue*>(result.get()),
- false, &error);
+ false, true, &error);
EXPECT_TRUE(extension) << error;
return extension;
diff --git a/chrome/browser/extensions/extension_prefs.cc b/chrome/browser/extensions/extension_prefs.cc
index 2022c11..1aa8840 100644
--- a/chrome/browser/extensions/extension_prefs.cc
+++ b/chrome/browser/extensions/extension_prefs.cc
@@ -488,7 +488,6 @@ void ExtensionPrefs::SetLastPingDayImpl(const Time& time,
SavePrefsAndNotify();
}
-
bool ExtensionPrefs::GetGrantedPermissions(
const std::string& extension_id,
bool* full_access,
@@ -511,11 +510,20 @@ bool ExtensionPrefs::GetGrantedPermissions(
// "permissions" array and from the content script "matches" arrays,
// so the URLPattern needs to accept valid schemes from both types.
for (std::set<std::string>::iterator i = host_permissions.begin();
- i != host_permissions.end(); ++i)
- host_extent->AddPattern(URLPattern(
+ i != host_permissions.end(); ++i) {
+ URLPattern pattern(
Extension::kValidHostPermissionSchemes |
- UserScript::kValidUserScriptSchemes,
- *i));
+ UserScript::kValidUserScriptSchemes);
+
+ // Parse without strict checks, so that new strict checks do not
+ // fail on a pattern in an installed extension.
+ if (URLPattern::PARSE_SUCCESS != pattern.Parse(
+ *i, URLPattern::PARSE_LENIENT)) {
+ NOTREACHED(); // Corrupt prefs? Hand editing?
+ } else {
+ host_extent->AddPattern(pattern);
+ }
+ }
return true;
}
diff --git a/chrome/browser/extensions/extension_prefs_unittest.cc b/chrome/browser/extensions/extension_prefs_unittest.cc
index fd83f56..71b4bb1 100644
--- a/chrome/browser/extensions/extension_prefs_unittest.cc
+++ b/chrome/browser/extensions/extension_prefs_unittest.cc
@@ -619,13 +619,13 @@ class ExtensionPrefsPreferencesBase : public ExtensionPrefsTest {
ext1_scoped_ = Extension::Create(
prefs_.temp_dir().AppendASCII("ext1_"), Extension::EXTERNAL_PREF,
- simple_dict, false, &error);
+ simple_dict, false, true, &error);
ext2_scoped_ = Extension::Create(
prefs_.temp_dir().AppendASCII("ext2_"), Extension::EXTERNAL_PREF,
- simple_dict, false, &error);
+ simple_dict, false, true, &error);
ext3_scoped_ = Extension::Create(
prefs_.temp_dir().AppendASCII("ext3_"), Extension::EXTERNAL_PREF,
- simple_dict, false, &error);
+ simple_dict, false, true, &error);
ext1_ = ext1_scoped_.get();
ext2_ = ext2_scoped_.get();
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc
index 6116e99..7d6d5e10 100644
--- a/chrome/browser/extensions/extension_service.cc
+++ b/chrome/browser/extensions/extension_service.cc
@@ -201,6 +201,7 @@ void ExtensionServiceBackend::LoadSingleExtension(
extension_path,
Extension::LOAD,
false, // Don't require id
+ Extension::ShouldDoStrictErrorChecking(Extension::LOAD),
&error));
if (!extension) {
@@ -833,7 +834,8 @@ void ExtensionService::LoadComponentExtensions() {
it->root_directory,
Extension::COMPONENT,
*static_cast<DictionaryValue*>(manifest.get()),
- true, // require key
+ true, // Require key
+ Extension::ShouldDoStrictErrorChecking(Extension::COMPONENT),
&error));
if (!extension.get()) {
NOTREACHED() << error;
@@ -878,7 +880,11 @@ void ExtensionService::LoadAllExtensions() {
std::string error;
scoped_refptr<const Extension> extension(
extension_file_util::LoadExtension(
- info->extension_path, info->extension_location, false, &error));
+ info->extension_path,
+ info->extension_location,
+ false, // Don't require key
+ Extension::ShouldDoStrictErrorChecking(info->extension_location),
+ &error));
if (extension.get()) {
extensions_info->at(i)->extension_manifest.reset(
@@ -985,7 +991,7 @@ void ExtensionService::LoadAllExtensions() {
}
void ExtensionService::LoadInstalledExtension(const ExtensionInfo& info,
- bool write_to_prefs) {
+ bool write_to_prefs) {
std::string error;
scoped_refptr<const Extension> extension(NULL);
if (!extension_prefs_->IsExtensionAllowedByPolicy(info.extension_id)) {
@@ -993,8 +999,12 @@ void ExtensionService::LoadInstalledExtension(const ExtensionInfo& info,
} else if (info.extension_manifest.get()) {
bool require_key = info.extension_location != Extension::LOAD;
extension = Extension::Create(
- info.extension_path, info.extension_location, *info.extension_manifest,
- require_key, &error);
+ info.extension_path,
+ info.extension_location,
+ *info.extension_manifest,
+ require_key,
+ Extension::ShouldDoStrictErrorChecking(info.extension_location),
+ &error);
} else {
error = errors::kManifestUnreadable;
}
diff --git a/chrome/browser/extensions/extension_special_storage_policy_unittest.cc b/chrome/browser/extensions/extension_special_storage_policy_unittest.cc
index 9597fb8..3a77b25 100644
--- a/chrome/browser/extensions/extension_special_storage_policy_unittest.cc
+++ b/chrome/browser/extensions/extension_special_storage_policy_unittest.cc
@@ -28,7 +28,7 @@ class ExtensionSpecialStoragePolicyTest : public testing::Test {
manifest.Set(keys::kWebURLs, list);
std::string error;
scoped_refptr<Extension> protected_app = Extension::Create(
- path, Extension::INVALID, manifest, false, &error);
+ path, Extension::INVALID, manifest, false, true, &error);
EXPECT_TRUE(protected_app.get()) << error;
return protected_app;
}
@@ -52,7 +52,7 @@ class ExtensionSpecialStoragePolicyTest : public testing::Test {
manifest.Set(keys::kWebURLs, list);
std::string error;
scoped_refptr<Extension> unlimited_app = Extension::Create(
- path, Extension::INVALID, manifest, false, &error);
+ path, Extension::INVALID, manifest, false, true, &error);
EXPECT_TRUE(unlimited_app.get()) << error;
return unlimited_app;
}
diff --git a/chrome/browser/extensions/extension_ui_unittest.cc b/chrome/browser/extensions/extension_ui_unittest.cc
index 5980109..b2ae1c5 100644
--- a/chrome/browser/extensions/extension_ui_unittest.cc
+++ b/chrome/browser/extensions/extension_ui_unittest.cc
@@ -42,7 +42,7 @@ namespace {
EXPECT_EQ("", error);
scoped_refptr<Extension> extension(Extension::Create(
- path, Extension::INVALID, *extension_data, true, &error));
+ path, Extension::INVALID, *extension_data, true, true, &error));
EXPECT_TRUE(extension.get());
EXPECT_EQ("", error);
diff --git a/chrome/browser/extensions/extension_webrequest_api.cc b/chrome/browser/extensions/extension_webrequest_api.cc
index d2567a9..a68f2b3 100644
--- a/chrome/browser/extensions/extension_webrequest_api.cc
+++ b/chrome/browser/extensions/extension_webrequest_api.cc
@@ -131,7 +131,8 @@ bool ExtensionWebRequestEventRouter::RequestFilter::InitFromValue(
std::string url;
URLPattern pattern(URLPattern::SCHEME_ALL);
if (!urls_value->GetString(i, &url) ||
- pattern.Parse(url) != URLPattern::PARSE_SUCCESS)
+ pattern.Parse(url, URLPattern::PARSE_STRICT) !=
+ URLPattern::PARSE_SUCCESS)
return false;
urls.AddPattern(pattern);
}
diff --git a/chrome/browser/extensions/image_loading_tracker_unittest.cc b/chrome/browser/extensions/image_loading_tracker_unittest.cc
index 4e41d32..e43d8d5 100644
--- a/chrome/browser/extensions/image_loading_tracker_unittest.cc
+++ b/chrome/browser/extensions/image_loading_tracker_unittest.cc
@@ -75,7 +75,7 @@ class ImageLoadingTrackerTest : public testing::Test,
return NULL;
return Extension::Create(
- test_file, Extension::INVALID, *valid_value, false, &error);
+ test_file, Extension::INVALID, *valid_value, false, true, &error);
}
SkBitmap image_;
diff --git a/chrome/browser/extensions/sandboxed_extension_unpacker.cc b/chrome/browser/extensions/sandboxed_extension_unpacker.cc
index 008c2fc..d7a9b1b 100644
--- a/chrome/browser/extensions/sandboxed_extension_unpacker.cc
+++ b/chrome/browser/extensions/sandboxed_extension_unpacker.cc
@@ -181,7 +181,12 @@ void SandboxedExtensionUnpacker::OnUnpackExtensionSucceeded(
}
extension_ = Extension::Create(
- extension_root_, Extension::INTERNAL, *final_manifest, true, &error);
+ extension_root_,
+ Extension::INTERNAL,
+ *final_manifest,
+ true, // Require key
+ false, // Disable strict error checks
+ &error);
if (!extension_.get()) {
ReportFailure(
diff --git a/chrome/browser/extensions/test_extension_prefs.cc b/chrome/browser/extensions/test_extension_prefs.cc
index 0975f27..a8c8a66 100644
--- a/chrome/browser/extensions/test_extension_prefs.cc
+++ b/chrome/browser/extensions/test_extension_prefs.cc
@@ -98,7 +98,7 @@ scoped_refptr<Extension> TestExtensionPrefs::AddExtensionWithManifest(
FilePath path = extensions_dir_.AppendASCII(name);
std::string errors;
scoped_refptr<Extension> extension = Extension::Create(
- path, location, manifest, false, &errors);
+ path, location, manifest, false, true, &errors);
EXPECT_TRUE(extension);
if (!extension)
return NULL;
diff --git a/chrome/browser/extensions/user_script_master.cc b/chrome/browser/extensions/user_script_master.cc
index eae62b4..c62f452 100644
--- a/chrome/browser/extensions/user_script_master.cc
+++ b/chrome/browser/extensions/user_script_master.cc
@@ -107,7 +107,8 @@ bool UserScriptMaster::ScriptReloader::ParseMetadataHeader(
script->set_description(value);
} else if (GetDeclarationValue(line, kMatchDeclaration, &value)) {
URLPattern pattern(UserScript::kValidUserScriptSchemes);
- if (URLPattern::PARSE_SUCCESS != pattern.Parse(value))
+ if (URLPattern::PARSE_SUCCESS !=
+ pattern.Parse(value, URLPattern::PARSE_LENIENT))
return false;
script->add_url_pattern(pattern);
} else if (GetDeclarationValue(line, kRunAtDeclaration, &value)) {
diff --git a/chrome/browser/sync/glue/extension_util_unittest.cc b/chrome/browser/sync/glue/extension_util_unittest.cc
index 946ca5a..2ca92dd 100644
--- a/chrome/browser/sync/glue/extension_util_unittest.cc
+++ b/chrome/browser/sync/glue/extension_util_unittest.cc
@@ -71,7 +71,7 @@ scoped_refptr<Extension> MakeExtension(
std::string error;
scoped_refptr<Extension> extension = Extension::Create(
- extension_path, location, source, false, &error);
+ extension_path, location, source, false, true, &error);
#if defined(OS_CHROMEOS)
if (num_plugins > 0) { // plugins are illegal in extensions on chrome os.
EXPECT_FALSE(extension);
@@ -386,7 +386,7 @@ scoped_refptr<Extension> MakeSyncableExtension(
source.SetString(extension_manifest_keys::kName, name);
std::string error;
scoped_refptr<Extension> extension = Extension::Create(
- extension_path, Extension::INTERNAL, source, false, &error);
+ extension_path, Extension::INTERNAL, source, false, true, &error);
EXPECT_TRUE(extension);
EXPECT_EQ("", error);
return extension;
diff --git a/chrome/browser/sync/glue/theme_util_unittest.cc b/chrome/browser/sync/glue/theme_util_unittest.cc
index 575ae86..dfa3ea3 100644
--- a/chrome/browser/sync/glue/theme_util_unittest.cc
+++ b/chrome/browser/sync/glue/theme_util_unittest.cc
@@ -33,7 +33,7 @@ scoped_refptr<Extension> MakeThemeExtension(const FilePath& extension_path,
source.SetString(extension_manifest_keys::kVersion, "0.0.0.0");
std::string error;
scoped_refptr<Extension> extension = Extension::Create(
- extension_path, Extension::INTERNAL, source, false, &error);
+ extension_path, Extension::INTERNAL, source, false, true, &error);
EXPECT_TRUE(extension);
EXPECT_EQ("", error);
return extension;
diff --git a/chrome/browser/sync/util/extensions_activity_monitor_unittest.cc b/chrome/browser/sync/util/extensions_activity_monitor_unittest.cc
index ec661bf..ed51a36 100644
--- a/chrome/browser/sync/util/extensions_activity_monitor_unittest.cc
+++ b/chrome/browser/sync/util/extensions_activity_monitor_unittest.cc
@@ -73,7 +73,8 @@ class BookmarkAPIEventGenerator {
input.SetString(keys::kVersion, kTestExtensionVersion);
input.SetString(keys::kName, kTestExtensionName);
scoped_refptr<Extension> extension(Extension::Create(
- FilePath(extension_path), Extension::INVALID, input, false, &error));
+ FilePath(extension_path), Extension::INVALID, input, false, true,
+ &error));
bookmarks_function->set_name(T::function_name());
base::WaitableEvent done_event(false, false);
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
@@ -131,7 +132,8 @@ class ExtensionsActivityMonitorTest : public testing::Test {
input.SetString(keys::kVersion, kTestExtensionVersion);
input.SetString(keys::kName, kTestExtensionName);
scoped_refptr<Extension> extension(Extension::Create(
- FilePath(extension_path), Extension::INVALID, input, false, &error));
+ FilePath(extension_path), Extension::INVALID, input, false, true,
+ &error));
EXPECT_EQ("", error);
return extension->id();
}
diff --git a/chrome/browser/themes/browser_theme_pack_unittest.cc b/chrome/browser/themes/browser_theme_pack_unittest.cc
index d13945c..72219f0 100644
--- a/chrome/browser/themes/browser_theme_pack_unittest.cc
+++ b/chrome/browser/themes/browser_theme_pack_unittest.cc
@@ -406,7 +406,8 @@ TEST_F(BrowserThemePackTest, CanBuildAndReadPack) {
EXPECT_EQ("", error);
ASSERT_TRUE(valid_value.get());
scoped_refptr<Extension> extension(Extension::Create(
- star_gazing_path, Extension::INVALID, *valid_value, true, &error));
+ star_gazing_path, Extension::INVALID, *valid_value, true, true,
+ &error));
ASSERT_TRUE(extension.get());
ASSERT_EQ("", error);
diff --git a/chrome/browser/ui/cocoa/extensions/extension_install_prompt_controller_unittest.mm b/chrome/browser/ui/cocoa/extensions/extension_install_prompt_controller_unittest.mm
index fb393af..f11aeb4 100644
--- a/chrome/browser/ui/cocoa/extensions/extension_install_prompt_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/extensions/extension_install_prompt_controller_unittest.mm
@@ -61,7 +61,7 @@ public:
}
extension_ = Extension::Create(
- path.DirName(), Extension::INVALID, *value, false, &error);
+ path.DirName(), Extension::INVALID, *value, false, true, &error);
if (!extension_.get()) {
LOG(ERROR) << error;
return;
diff --git a/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller_unittest.mm b/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller_unittest.mm
index 1cafd26..5115d7d 100644
--- a/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller_unittest.mm
@@ -101,7 +101,7 @@ class ExtensionInstalledBubbleControllerTest : public CocoaTest {
std::string error;
return Extension::Create(
- path, Extension::INVALID, extension_input_value, false, &error);
+ path, Extension::INVALID, extension_input_value, false, true, &error);
}
// Allows us to create the window and browser for testing.
diff --git a/chrome/common/extensions/extension.cc b/chrome/common/extensions/extension.cc
index c979d24..ce77fa3 100644
--- a/chrome/common/extensions/extension.cc
+++ b/chrome/common/extensions/extension.cc
@@ -268,9 +268,11 @@ scoped_refptr<Extension> Extension::Create(const FilePath& path,
Location location,
const DictionaryValue& value,
bool require_key,
+ bool strict_error_checks,
std::string* error) {
scoped_refptr<Extension> extension = new Extension(path, location);
- if (!extension->InitFromValue(value, require_key, error))
+
+ if (!extension->InitFromValue(value, require_key, strict_error_checks, error))
return NULL;
return extension;
}
@@ -515,7 +517,9 @@ bool Extension::GenerateId(const std::string& input, std::string* output) {
// Helper method that loads a UserScript object from a dictionary in the
// content_script list of the manifest.
bool Extension::LoadUserScriptHelper(const DictionaryValue* content_script,
- int definition_index, std::string* error,
+ int definition_index,
+ URLPattern::ParseOption parse_strictness,
+ std::string* error,
UserScript* result) {
// run_at
if (content_script->HasKey(keys::kRunAt)) {
@@ -566,8 +570,11 @@ bool Extension::LoadUserScriptHelper(const DictionaryValue* content_script,
for (size_t j = 0; j < matches->GetSize(); ++j) {
std::string match_str;
if (!matches->GetString(j, &match_str)) {
- *error = ExtensionErrorUtils::FormatErrorMessage(errors::kInvalidMatch,
- base::IntToString(definition_index), base::IntToString(j));
+ *error = ExtensionErrorUtils::FormatErrorMessage(
+ errors::kInvalidMatch,
+ base::IntToString(definition_index),
+ base::IntToString(j),
+ errors::kExpectString);
return false;
}
@@ -575,9 +582,14 @@ bool Extension::LoadUserScriptHelper(const DictionaryValue* content_script,
if (CanExecuteScriptEverywhere())
pattern.set_valid_schemes(URLPattern::SCHEME_ALL);
- if (URLPattern::PARSE_SUCCESS != pattern.Parse(match_str)) {
- *error = ExtensionErrorUtils::FormatErrorMessage(errors::kInvalidMatch,
- base::IntToString(definition_index), base::IntToString(j));
+ URLPattern::ParseResult parse_result = pattern.Parse(match_str,
+ parse_strictness);
+ if (parse_result != URLPattern::PARSE_SUCCESS) {
+ *error = ExtensionErrorUtils::FormatErrorMessage(
+ errors::kInvalidMatch,
+ base::IntToString(definition_index),
+ base::IntToString(j),
+ URLPattern::GetParseResultString(parse_result));
return false;
}
@@ -878,6 +890,7 @@ bool Extension::LoadExtent(const DictionaryValue* manifest,
ExtensionExtent* extent,
const char* list_error,
const char* value_error,
+ URLPattern::ParseOption parse_strictness,
std::string* error) {
Value* temp = NULL;
if (!manifest->Get(key, &temp))
@@ -893,34 +906,52 @@ bool Extension::LoadExtent(const DictionaryValue* manifest,
std::string pattern_string;
if (!pattern_list->GetString(i, &pattern_string)) {
*error = ExtensionErrorUtils::FormatErrorMessage(value_error,
- base::UintToString(i));
+ base::UintToString(i),
+ errors::kExpectString);
return false;
}
URLPattern pattern(kValidWebExtentSchemes);
- URLPattern::ParseResult result = pattern.Parse(pattern_string);
- if (result == URLPattern::PARSE_ERROR_EMPTY_PATH) {
+ URLPattern::ParseResult parse_result = pattern.Parse(pattern_string,
+ parse_strictness);
+ if (parse_result == URLPattern::PARSE_ERROR_EMPTY_PATH) {
pattern_string += "/";
- result = pattern.Parse(pattern_string);
+ parse_result = pattern.Parse(pattern_string, parse_strictness);
}
- if (URLPattern::PARSE_SUCCESS != result) {
- *error = ExtensionErrorUtils::FormatErrorMessage(value_error,
- base::UintToString(i));
+
+ if (parse_result != URLPattern::PARSE_SUCCESS) {
+ *error = ExtensionErrorUtils::FormatErrorMessage(
+ value_error,
+ base::UintToString(i),
+ URLPattern::GetParseResultString(parse_result));
return false;
}
- // Do not allow authors to claim "<all_urls>" or "*" for host.
- if (pattern.match_all_urls() || pattern.host().empty()) {
- *error = ExtensionErrorUtils::FormatErrorMessage(value_error,
- base::UintToString(i));
+ // Do not allow authors to claim "<all_urls>".
+ if (pattern.match_all_urls()) {
+ *error = ExtensionErrorUtils::FormatErrorMessage(
+ value_error,
+ base::UintToString(i),
+ errors::kCannotClaimAllURLsInExtent);
+ return false;
+ }
+
+ // Do not allow authors to claim "*" for host.
+ if (pattern.host().empty()) {
+ *error = ExtensionErrorUtils::FormatErrorMessage(
+ value_error,
+ base::UintToString(i),
+ errors::kCannotClaimAllHostsInExtent);
return false;
}
// We do not allow authors to put wildcards in their paths. Instead, we
// imply one at the end.
if (pattern.path().find('*') != std::string::npos) {
- *error = ExtensionErrorUtils::FormatErrorMessage(value_error,
- base::UintToString(i));
+ *error = ExtensionErrorUtils::FormatErrorMessage(
+ value_error,
+ base::UintToString(i),
+ errors::kNoWildCardsInPaths);
return false;
}
pattern.SetPath(pattern.path() + '*');
@@ -993,15 +1024,32 @@ bool Extension::LoadLaunchURL(const DictionaryValue* manifest,
// process isolation, we must insert any provided value into the component
// app's launch url and web extent.
if (id() == extension_misc::kWebStoreAppId) {
- GURL gallery_url(CommandLine::ForCurrentProcess()->
- GetSwitchValueASCII(switches::kAppsGalleryURL));
- if (gallery_url.is_valid()) {
- launch_web_url_ = gallery_url.spec();
+ std::string gallery_url_str = CommandLine::ForCurrentProcess()->
+ GetSwitchValueASCII(switches::kAppsGalleryURL);
+
+ // Empty string means option was not used.
+ if (!gallery_url_str.empty()) {
+ GURL gallery_url(gallery_url_str);
+ if (!gallery_url.is_valid()) {
+ LOG(WARNING) << "Invalid url given in switch "
+ << switches::kAppsGalleryURL;
+ } else {
+ if (gallery_url.has_port()) {
+ LOG(WARNING) << "URLs passed to switch " << switches::kAppsGalleryURL
+ << " should not contain a port. Removing it.";
+
+ GURL::Replacements remove_port;
+ remove_port.ClearPort();
+ gallery_url = gallery_url.ReplaceComponents(remove_port);
+ }
+
+ launch_web_url_ = gallery_url.spec();
- URLPattern pattern(kValidWebExtentSchemes);
- pattern.Parse(gallery_url.spec());
- pattern.SetPath(pattern.path() + '*');
- extent_.AddPattern(pattern);
+ URLPattern pattern(kValidWebExtentSchemes);
+ pattern.Parse(gallery_url.spec(), URLPattern::PARSE_STRICT);
+ pattern.SetPath(pattern.path() + '*');
+ extent_.AddPattern(pattern);
+ }
}
}
@@ -1278,7 +1326,12 @@ GURL Extension::GetBaseURLFromExtensionId(const std::string& extension_id) {
}
bool Extension::InitFromValue(const DictionaryValue& source, bool require_key,
- std::string* error) {
+ bool strict_error_checks, std::string* error) {
+ // When strict error checks are enabled, make URL pattern parsing strict.
+ URLPattern::ParseOption parse_strictness =
+ (strict_error_checks ? URLPattern::PARSE_STRICT
+ : URLPattern::PARSE_LENIENT);
+
if (source.HasKey(keys::kPublicKey)) {
std::string public_key_bytes;
if (!source.GetString(keys::kPublicKey,
@@ -1646,7 +1699,8 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key,
}
UserScript script;
- if (!LoadUserScriptHelper(content_script, i, error, &script))
+ if (!LoadUserScriptHelper(content_script, i, parse_strictness, error,
+ &script))
return false; // Failed to parse script context definition.
script.set_extension_id(id());
if (converted_from_user_script_) {
@@ -1714,7 +1768,8 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key,
if (!LoadIsApp(manifest_value_.get(), error) ||
!LoadExtent(manifest_value_.get(), keys::kWebURLs,
&extent_,
- errors::kInvalidWebURLs, errors::kInvalidWebURL, error) ||
+ errors::kInvalidWebURLs, errors::kInvalidWebURL,
+ parse_strictness, error) ||
!EnsureNotHybridApp(manifest_value_.get(), error) ||
!LoadLaunchURL(manifest_value_.get(), error) ||
!LoadLaunchContainer(manifest_value_.get(), error)) {
@@ -1810,7 +1865,9 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key,
URLPattern pattern = URLPattern(CanExecuteScriptEverywhere() ?
URLPattern::SCHEME_ALL : kValidHostPermissionSchemes);
- if (URLPattern::PARSE_SUCCESS == pattern.Parse(permission_str)) {
+ URLPattern::ParseResult parse_result = pattern.Parse(permission_str,
+ parse_strictness);
+ if (parse_result == URLPattern::PARSE_SUCCESS) {
if (!CanSpecifyHostPermission(pattern)) {
*error = ExtensionErrorUtils::FormatErrorMessage(
errors::kInvalidPermissionScheme, base::IntToString(i));
@@ -1829,6 +1886,10 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key,
// backwards compatability (http://crbug.com/42742).
// TODO(jstritar): We can improve error messages by adding better
// validation of API permissions here.
+ // TODO(skerner): Consider showing the reason |permission_str| is not
+ // a valid URL pattern if it is almost valid. For example, if it has
+ // a valid scheme, and failed to parse because it has a port, show an
+ // error.
}
}
diff --git a/chrome/common/extensions/extension.h b/chrome/common/extensions/extension.h
index 772d72c..49850aa 100644
--- a/chrome/common/extensions/extension.h
+++ b/chrome/common/extensions/extension.h
@@ -114,10 +114,21 @@ class Extension : public base::RefCountedThreadSafe<Extension> {
const int message_id;
};
+ // |strict_error_checks| enables extra error checking, such as
+ // checks that URL patterns do not contain ports. This error
+ // checking may find an error that a previous version of
+ // chrome did not flag. To avoid errors in installed extensions
+ // when chrome is upgraded, strict error checking is only enabled
+ // when loading extensions as a developer would (such as loading
+ // an unpacked extension), or when loading an extension that is
+ // tied to a specific version of chrome (such as a component
+ // extension). Most callers will set |strict_error_checks| to
+ // Extension::ShouldDoStrictErrorChecking(location).
static scoped_refptr<Extension> Create(const FilePath& path,
Location location,
const DictionaryValue& value,
bool require_key,
+ bool strict_error_checks,
std::string* error);
// Return the update url used by gallery/webstore extensions.
@@ -236,6 +247,17 @@ class Extension : public base::RefCountedThreadSafe<Extension> {
IsExternalLocation(location);
}
+ // Whether extensions with |location| should be loaded with strict
+ // error checking. Strict error checks may flag errors older versions
+ // of chrome did not detect. To avoid breaking installed extensions,
+ // strict checks are disabled unless the location indicates that the
+ // developer is loading the extension, or the extension is a component
+ // of chrome.
+ static inline bool ShouldDoStrictErrorChecking(Location location) {
+ return location == Extension::LOAD ||
+ location == Extension::COMPONENT;
+ }
+
// See Type definition above.
Type GetType() const;
@@ -513,7 +535,7 @@ class Extension : public base::RefCountedThreadSafe<Extension> {
// its manifest, but if |require_key| is |false|, a temporary ID will be
// generated based on the path.
bool InitFromValue(const DictionaryValue& value, bool require_key,
- std::string* error);
+ bool strict_error_checks, std::string* error);
// Helper function for implementing HasCachedImage/GetCachedImage. A return
// value of NULL means there is no matching image cached (we allow caching an
@@ -525,6 +547,7 @@ class Extension : public base::RefCountedThreadSafe<Extension> {
// dictionary in the content_script list of the manifest.
bool LoadUserScriptHelper(const DictionaryValue* content_script,
int definition_index,
+ URLPattern::ParseOption parse_strictness,
std::string* error,
UserScript* result);
@@ -539,9 +562,13 @@ class Extension : public base::RefCountedThreadSafe<Extension> {
// Helpers to load various chunks of the manifest.
bool LoadIsApp(const DictionaryValue* manifest, std::string* error);
- bool LoadExtent(const DictionaryValue* manifest, const char* key,
- ExtensionExtent* extent, const char* list_error,
- const char* value_error, std::string* error);
+ bool LoadExtent(const DictionaryValue* manifest,
+ const char* key,
+ ExtensionExtent* extent,
+ const char* list_error,
+ const char* value_error,
+ URLPattern::ParseOption parse_strictness,
+ std::string* error);
bool LoadLaunchContainer(const DictionaryValue* manifest, std::string* error);
bool LoadLaunchURL(const DictionaryValue* manifest, std::string* error);
bool EnsureNotHybridApp(const DictionaryValue* manifest, std::string* error);
diff --git a/chrome/common/extensions/extension_constants.cc b/chrome/common/extensions/extension_constants.cc
index e30ff97..96fd349 100644
--- a/chrome/common/extensions/extension_constants.cc
+++ b/chrome/common/extensions/extension_constants.cc
@@ -100,6 +100,10 @@ const char* kAppsNotEnabled =
const char* kCannotAccessPage =
"Cannot access contents of url \"*\". "
"Extension manifest must request permission to access this host.";
+const char* kCannotClaimAllHostsInExtent =
+ "Cannot claim all hosts ('*') in an extent.";
+const char* kCannotClaimAllURLsInExtent =
+ "Cannot claim all URLs in an extent.";
const char* kCannotScriptGallery =
"The extensions gallery cannot be scripted.";
const char* kChromeVersionTooLow =
@@ -109,6 +113,7 @@ const char* kDisabledByPolicy =
const char* kDevToolsExperimental =
"You must request the 'experimental' permission in order to use the"
" DevTools API.";
+const char* kExpectString = "Expect string value.";
const char* kExperimentalFlagRequired =
"Loading extensions with 'experimental' permission requires"
" --enable-experimental-extension-apis command line flag.";
@@ -171,7 +176,7 @@ const char* kInvalidLaunchWidthContainer =
const char* kInvalidManifest =
"Manifest file is invalid.";
const char* kInvalidMatch =
- "Invalid value for 'content_scripts[*].matches[*]'.";
+ "Invalid value for 'content_scripts[*].matches[*]': *";
const char* kInvalidMatchCount =
"Invalid value for 'content_scripts[*].matches'. There must be at least"
"one match specified.";
@@ -269,7 +274,7 @@ const char* kInvalidVersion =
"Required value 'version' is missing or invalid. It must be between 1-4 "
"dot-separated integers each between 0 and 65536.";
const char* kInvalidWebURL =
- "Invalid value for 'app.urls[*]'.";
+ "Invalid value for 'app.urls[*]': *";
const char* kInvalidWebURLs =
"Invalid value for 'app.urls'.";
const char* kInvalidZipHash =
@@ -296,6 +301,8 @@ const char* kMissingFile =
"At least one js or css file is required for 'content_scripts[*]'.";
const char* kMultipleOverrides =
"An extension cannot override more than one page.";
+const char* kNoWildCardsInPaths =
+ "Wildcards are not allowed in extent URL pattern paths.";
const char* kOneUISurfaceOnly =
"Only one of 'browser_action', 'page_action', and 'app' can be specified.";
const char* kReservedMessageFound =
diff --git a/chrome/common/extensions/extension_constants.h b/chrome/common/extensions/extension_constants.h
index 756a888..bad2a5b 100644
--- a/chrome/common/extensions/extension_constants.h
+++ b/chrome/common/extensions/extension_constants.h
@@ -100,11 +100,14 @@ namespace extension_manifest_values {
namespace extension_manifest_errors {
extern const char* kAppsNotEnabled;
extern const char* kCannotAccessPage;
+ extern const char* kCannotClaimAllHostsInExtent;
+ extern const char* kCannotClaimAllURLsInExtent;
extern const char* kCannotScriptGallery;
extern const char* kChromeVersionTooLow;
extern const char* kDevToolsExperimental;
extern const char* kDisabledByPolicy;
extern const char* kExperimentalFlagRequired;
+ extern const char* kExpectString;
extern const char* kHostedAppsCannotIncludeExtensionFeatures;
extern const char* kInvalidAllFrames;
extern const char* kInvalidBackground;
@@ -197,6 +200,7 @@ namespace extension_manifest_errors {
extern const char* kManifestUnreadable;
extern const char* kMissingFile;
extern const char* kMultipleOverrides;
+ extern const char* kNoWildCardsInPaths;
extern const char* kOneUISurfaceOnly;
extern const char* kReservedMessageFound;
extern const char* kSidebarExperimental;
diff --git a/chrome/common/extensions/extension_file_util.cc b/chrome/common/extensions/extension_file_util.cc
index 0a8197a..6e9a4eb 100644
--- a/chrome/common/extensions/extension_file_util.cc
+++ b/chrome/common/extensions/extension_file_util.cc
@@ -89,6 +89,7 @@ void UninstallExtension(const FilePath& extensions_dir,
scoped_refptr<Extension> LoadExtension(const FilePath& extension_path,
Extension::Location location,
bool require_key,
+ bool strict_error_checks,
std::string* error) {
FilePath manifest_path =
extension_path.Append(Extension::kManifestFilename);
@@ -124,7 +125,12 @@ scoped_refptr<Extension> LoadExtension(const FilePath& extension_path,
return NULL;
scoped_refptr<Extension> extension(Extension::Create(
- extension_path, location, *manifest, require_key, error));
+ extension_path,
+ location,
+ *manifest,
+ require_key,
+ strict_error_checks,
+ error));
if (!extension.get())
return NULL;
diff --git a/chrome/common/extensions/extension_file_util.h b/chrome/common/extensions/extension_file_util.h
index 04de555..066ee80 100644
--- a/chrome/common/extensions/extension_file_util.h
+++ b/chrome/common/extensions/extension_file_util.h
@@ -40,6 +40,7 @@ void UninstallExtension(const FilePath& extensions_dir,
scoped_refptr<Extension> LoadExtension(const FilePath& extension_root,
Extension::Location location,
bool require_key,
+ bool strict_error_checks,
std::string* error);
// Returns true if the given extension object is valid and consistent.
diff --git a/chrome/common/extensions/extension_file_util_unittest.cc b/chrome/common/extensions/extension_file_util_unittest.cc
index 3f59da6..d3cabff 100644
--- a/chrome/common/extensions/extension_file_util_unittest.cc
+++ b/chrome/common/extensions/extension_file_util_unittest.cc
@@ -79,7 +79,7 @@ TEST(ExtensionFileUtil, LoadExtensionWithValidLocales) {
std::string error;
scoped_refptr<Extension> extension(extension_file_util::LoadExtension(
- install_dir, Extension::LOAD, false, &error));
+ install_dir, Extension::LOAD, false, true, &error));
ASSERT_TRUE(extension != NULL);
EXPECT_EQ("The first extension that I made.", extension->description());
}
@@ -95,7 +95,7 @@ TEST(ExtensionFileUtil, LoadExtensionWithoutLocalesFolder) {
std::string error;
scoped_refptr<Extension> extension(extension_file_util::LoadExtension(
- install_dir, Extension::LOAD, false, &error));
+ install_dir, Extension::LOAD, false, true, &error));
ASSERT_FALSE(extension == NULL);
EXPECT_TRUE(error.empty());
}
@@ -153,7 +153,7 @@ TEST(ExtensionFileUtil, LoadExtensionGivesHelpfullErrorOnMissingManifest) {
std::string error;
scoped_refptr<Extension> extension(extension_file_util::LoadExtension(
- install_dir, Extension::LOAD, false, &error));
+ install_dir, Extension::LOAD, false, true, &error));
ASSERT_TRUE(extension == NULL);
ASSERT_FALSE(error.empty());
ASSERT_STREQ("Manifest file is missing or unreadable.", error.c_str());
@@ -170,7 +170,7 @@ TEST(ExtensionFileUtil, LoadExtensionGivesHelpfullErrorOnBadManifest) {
std::string error;
scoped_refptr<Extension> extension(extension_file_util::LoadExtension(
- install_dir, Extension::LOAD, false, &error));
+ install_dir, Extension::LOAD, false, true, &error));
ASSERT_TRUE(extension == NULL);
ASSERT_FALSE(error.empty());
ASSERT_STREQ("Manifest is not valid JSON. "
@@ -186,7 +186,7 @@ TEST(ExtensionFileUtil, FailLoadingNonUTF8Scripts) {
std::string error;
scoped_refptr<Extension> extension(extension_file_util::LoadExtension(
- install_dir, Extension::LOAD, false, &error));
+ install_dir, Extension::LOAD, false, true, &error));
ASSERT_TRUE(extension == NULL);
ASSERT_STREQ("Could not load file 'bad_encoding.js' for content script. "
"It isn't UTF-8 encoded.", error.c_str());
diff --git a/chrome/common/extensions/extension_manifests_unittest.cc b/chrome/common/extensions/extension_manifests_unittest.cc
index a6bc71f..63172a9 100644
--- a/chrome/common/extensions/extension_manifests_unittest.cc
+++ b/chrome/common/extensions/extension_manifests_unittest.cc
@@ -7,6 +7,7 @@
#include "base/file_util.h"
#include "base/path_service.h"
#include "base/scoped_ptr.h"
+#include "base/string_number_conversions.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/common/chrome_paths.h"
@@ -42,31 +43,41 @@ class ExtensionManifestTest : public testing::Test {
scoped_refptr<Extension> LoadExtensionWithLocation(
DictionaryValue* value,
Extension::Location location,
+ bool strict_error_checks,
std::string* error) {
FilePath path;
PathService::Get(chrome::DIR_TEST_DATA, &path);
path = path.AppendASCII("extensions").AppendASCII("manifest_tests");
- return Extension::Create(path.DirName(), location, *value, false, error);
+ return Extension::Create(path.DirName(), location, *value, false,
+ strict_error_checks, error);
}
scoped_refptr<Extension> LoadExtension(const std::string& name,
std::string* error) {
- return LoadExtensionWithLocation(name, Extension::INTERNAL, error);
+ return LoadExtensionWithLocation(name, Extension::INTERNAL, false, error);
+ }
+
+ scoped_refptr<Extension> LoadExtensionStrict(const std::string& name,
+ std::string* error) {
+ return LoadExtensionWithLocation(name, Extension::INTERNAL, true, error);
}
scoped_refptr<Extension> LoadExtension(DictionaryValue* value,
std::string* error) {
- return LoadExtensionWithLocation(value, Extension::INTERNAL, error);
+ // Loading as an installed extension disables strict error checks.
+ return LoadExtensionWithLocation(value, Extension::INTERNAL, false, error);
}
scoped_refptr<Extension> LoadExtensionWithLocation(
const std::string& name,
Extension::Location location,
+ bool strict_error_checks,
std::string* error) {
scoped_ptr<DictionaryValue> value(LoadManifestFile(name, error));
if (!value.get())
return NULL;
- return LoadExtensionWithLocation(value.get(), location, error);
+ return LoadExtensionWithLocation(value.get(), location,
+ strict_error_checks, error);
}
scoped_refptr<Extension> LoadAndExpectSuccess(const std::string& name) {
@@ -77,6 +88,14 @@ class ExtensionManifestTest : public testing::Test {
return extension;
}
+ scoped_refptr<Extension> LoadStrictAndExpectSuccess(const std::string& name) {
+ std::string error;
+ scoped_refptr<Extension> extension = LoadExtensionStrict(name, &error);
+ EXPECT_TRUE(extension) << name;
+ EXPECT_EQ("", error) << name;
+ return extension;
+ }
+
scoped_refptr<Extension> LoadAndExpectSuccess(DictionaryValue* manifest,
const std::string& name) {
std::string error;
@@ -104,6 +123,13 @@ class ExtensionManifestTest : public testing::Test {
VerifyExpectedError(extension.get(), name, error, expected_error);
}
+ void LoadAndExpectErrorStrict(const std::string& name,
+ const std::string& expected_error) {
+ std::string error;
+ scoped_refptr<Extension> extension(LoadExtensionStrict(name, &error));
+ VerifyExpectedError(extension.get(), name, error, expected_error);
+ }
+
void LoadAndExpectError(DictionaryValue* manifest,
const std::string& name,
const std::string& expected_error) {
@@ -129,18 +155,52 @@ TEST_F(ExtensionManifestTest, ValidApp) {
TEST_F(ExtensionManifestTest, AppWebUrls) {
LoadAndExpectError("web_urls_wrong_type.json",
errors::kInvalidWebURLs);
- LoadAndExpectError("web_urls_invalid_1.json",
- ExtensionErrorUtils::FormatErrorMessage(
- errors::kInvalidWebURL, "0"));
- LoadAndExpectError("web_urls_invalid_2.json",
- ExtensionErrorUtils::FormatErrorMessage(
- errors::kInvalidWebURL, "0"));
- LoadAndExpectError("web_urls_invalid_3.json",
- ExtensionErrorUtils::FormatErrorMessage(
- errors::kInvalidWebURL, "0"));
- LoadAndExpectError("web_urls_invalid_4.json",
- ExtensionErrorUtils::FormatErrorMessage(
- errors::kInvalidWebURL, "0"));
+ LoadAndExpectError(
+ "web_urls_invalid_1.json",
+ ExtensionErrorUtils::FormatErrorMessage(
+ errors::kInvalidWebURL,
+ base::IntToString(0),
+ errors::kExpectString));
+
+ LoadAndExpectError(
+ "web_urls_invalid_2.json",
+ ExtensionErrorUtils::FormatErrorMessage(
+ errors::kInvalidWebURL,
+ base::IntToString(0),
+ URLPattern::GetParseResultString(
+ URLPattern::PARSE_ERROR_MISSING_SCHEME_SEPARATOR)));
+
+ LoadAndExpectError(
+ "web_urls_invalid_3.json",
+ ExtensionErrorUtils::FormatErrorMessage(
+ errors::kInvalidWebURL,
+ base::IntToString(0),
+ errors::kNoWildCardsInPaths));
+
+ LoadAndExpectError(
+ "web_urls_invalid_4.json",
+ ExtensionErrorUtils::FormatErrorMessage(
+ errors::kInvalidWebURL,
+ base::IntToString(0),
+ errors::kCannotClaimAllURLsInExtent));
+
+ LoadAndExpectError(
+ "web_urls_invalid_5.json",
+ ExtensionErrorUtils::FormatErrorMessage(
+ errors::kInvalidWebURL,
+ base::IntToString(1),
+ errors::kCannotClaimAllHostsInExtent));
+
+ // Ports in app.urls only raise an error when loading as a
+ // developer would.
+ LoadAndExpectSuccess("web_urls_invalid_has_port.json");
+ LoadAndExpectErrorStrict(
+ "web_urls_invalid_has_port.json",
+ ExtensionErrorUtils::FormatErrorMessage(
+ errors::kInvalidWebURL,
+ base::IntToString(1),
+ URLPattern::GetParseResultString(URLPattern::PARSE_ERROR_HAS_COLON)));
+
scoped_refptr<Extension> extension(
LoadAndExpectSuccess("web_urls_default.json"));
@@ -238,13 +298,45 @@ TEST_F(ExtensionManifestTest, ChromeResourcesPermissionValidOnlyForComponents) {
extension = LoadExtensionWithLocation(
"permission_chrome_resources_url.json",
Extension::COMPONENT,
+ true, // Strict error checking
&error);
EXPECT_EQ("", error);
}
-TEST_F(ExtensionManifestTest, ChromeURLContentScriptInvalid) {
- LoadAndExpectError("content_script_chrome_url_invalid.json",
- errors::kInvalidMatch);
+TEST_F(ExtensionManifestTest, InvalidContentScriptMatchPattern) {
+
+ // chrome:// urls are not allowed.
+ LoadAndExpectError(
+ "content_script_chrome_url_invalid.json",
+ ExtensionErrorUtils::FormatErrorMessage(
+ errors::kInvalidMatch,
+ base::IntToString(0),
+ base::IntToString(0),
+ URLPattern::GetParseResultString(
+ URLPattern::PARSE_ERROR_INVALID_SCHEME)));
+
+ // Match paterns must be strings.
+ LoadAndExpectError(
+ "content_script_match_pattern_not_string.json",
+ ExtensionErrorUtils::FormatErrorMessage(
+ errors::kInvalidMatch,
+ base::IntToString(0),
+ base::IntToString(0),
+ errors::kExpectString));
+
+ // Ports in match patterns cause an error, but only when loading
+ // in developer mode.
+ LoadAndExpectSuccess("forbid_ports_in_content_scripts.json");
+
+ // Loading as a developer would should give an error.
+ LoadAndExpectErrorStrict(
+ "forbid_ports_in_content_scripts.json",
+ ExtensionErrorUtils::FormatErrorMessage(
+ errors::kInvalidMatch,
+ base::IntToString(1),
+ base::IntToString(0),
+ URLPattern::GetParseResultString(
+ URLPattern::PARSE_ERROR_HAS_COLON)));
}
TEST_F(ExtensionManifestTest, ExperimentalPermission) {
@@ -444,3 +536,14 @@ TEST_F(ExtensionManifestTest, TtsProvider) {
EXPECT_EQ("en-US", extension->tts_voices()[0].locale);
EXPECT_EQ("female", extension->tts_voices()[0].gender);
}
+
+TEST_F(ExtensionManifestTest, ForbidPortsInPermissions) {
+ // Loading as a user would shoud not trigger an error.
+ LoadAndExpectSuccess("forbid_ports_in_permissions.json");
+
+ // Ideally, loading as a developer would give an error.
+ // To ensure that we do not error out on a valid permission
+ // in a future version of chrome, validation is to loose
+ // to flag this case.
+ LoadStrictAndExpectSuccess("forbid_ports_in_permissions.json");
+}
diff --git a/chrome/common/extensions/extension_set_unittest.cc b/chrome/common/extensions/extension_set_unittest.cc
index 1b85ac5..a68e1d7 100644
--- a/chrome/common/extensions/extension_set_unittest.cc
+++ b/chrome/common/extensions/extension_set_unittest.cc
@@ -37,10 +37,11 @@ scoped_refptr<Extension> CreateTestExtension(const std::string& name,
}
const bool kRequireKey = false;
+ const bool kStrictErrorChecks = true;
std::string error;
scoped_refptr<Extension> extension(
Extension::Create(path, Extension::INTERNAL, manifest, kRequireKey,
- &error));
+ kStrictErrorChecks, &error));
EXPECT_TRUE(extension.get()) << error;
return extension;
}
diff --git a/chrome/common/extensions/extension_unittest.cc b/chrome/common/extensions/extension_unittest.cc
index 92d60fd..ab3c3a2 100644
--- a/chrome/common/extensions/extension_unittest.cc
+++ b/chrome/common/extensions/extension_unittest.cc
@@ -105,7 +105,7 @@ TEST(ExtensionTest, InitFromValueInvalid) {
EXPECT_EQ("", error);
EXPECT_EQ(0, error_code);
ASSERT_TRUE(valid_value.get());
- ASSERT_TRUE(extension.InitFromValue(*valid_value, true, &error));
+ ASSERT_TRUE(extension.InitFromValue(*valid_value, true, false, &error));
ASSERT_EQ("", error);
EXPECT_EQ("en_US", extension.default_locale());
@@ -114,33 +114,33 @@ TEST(ExtensionTest, InitFromValueInvalid) {
// Test missing and invalid versions
input_value.reset(valid_value->DeepCopy());
input_value->Remove(keys::kVersion, NULL);
- EXPECT_FALSE(extension.InitFromValue(*input_value, true, &error));
+ EXPECT_FALSE(extension.InitFromValue(*input_value, true, false, &error));
EXPECT_EQ(errors::kInvalidVersion, error);
input_value->SetInteger(keys::kVersion, 42);
- EXPECT_FALSE(extension.InitFromValue(*input_value, true, &error));
+ EXPECT_FALSE(extension.InitFromValue(*input_value, true, false, &error));
EXPECT_EQ(errors::kInvalidVersion, error);
// Test missing and invalid names.
input_value.reset(valid_value->DeepCopy());
input_value->Remove(keys::kName, NULL);
- EXPECT_FALSE(extension.InitFromValue(*input_value, true, &error));
+ EXPECT_FALSE(extension.InitFromValue(*input_value, true, false, &error));
EXPECT_EQ(errors::kInvalidName, error);
input_value->SetInteger(keys::kName, 42);
- EXPECT_FALSE(extension.InitFromValue(*input_value, true, &error));
+ EXPECT_FALSE(extension.InitFromValue(*input_value, true, false, &error));
EXPECT_EQ(errors::kInvalidName, error);
// Test invalid description
input_value.reset(valid_value->DeepCopy());
input_value->SetInteger(keys::kDescription, 42);
- EXPECT_FALSE(extension.InitFromValue(*input_value, true, &error));
+ EXPECT_FALSE(extension.InitFromValue(*input_value, true, false, &error));
EXPECT_EQ(errors::kInvalidDescription, error);
// Test invalid icons
input_value.reset(valid_value->DeepCopy());
input_value->SetInteger(keys::kIcons, 42);
- EXPECT_FALSE(extension.InitFromValue(*input_value, true, &error));
+ EXPECT_FALSE(extension.InitFromValue(*input_value, true, false, &error));
EXPECT_EQ(errors::kInvalidIcons, error);
// Test invalid icon paths
@@ -149,13 +149,13 @@ TEST(ExtensionTest, InitFromValueInvalid) {
input_value->GetDictionary(keys::kIcons, &icons);
ASSERT_FALSE(NULL == icons);
icons->SetInteger(base::IntToString(128), 42);
- EXPECT_FALSE(extension.InitFromValue(*input_value, true, &error));
+ EXPECT_FALSE(extension.InitFromValue(*input_value, true, false, &error));
EXPECT_TRUE(MatchPattern(error, errors::kInvalidIconPath));
// Test invalid user scripts list
input_value.reset(valid_value->DeepCopy());
input_value->SetInteger(keys::kContentScripts, 42);
- EXPECT_FALSE(extension.InitFromValue(*input_value, true, &error));
+ EXPECT_FALSE(extension.InitFromValue(*input_value, true, false, &error));
EXPECT_EQ(errors::kInvalidContentScriptsList, error);
// Test invalid user script item
@@ -164,7 +164,7 @@ TEST(ExtensionTest, InitFromValueInvalid) {
input_value->GetList(keys::kContentScripts, &content_scripts);
ASSERT_FALSE(NULL == content_scripts);
content_scripts->Set(0, Value::CreateIntegerValue(42));
- EXPECT_FALSE(extension.InitFromValue(*input_value, true, &error));
+ EXPECT_FALSE(extension.InitFromValue(*input_value, true, false, &error));
EXPECT_TRUE(MatchPattern(error, errors::kInvalidContentScript));
// Test missing and invalid matches array
@@ -173,25 +173,25 @@ TEST(ExtensionTest, InitFromValueInvalid) {
DictionaryValue* user_script = NULL;
content_scripts->GetDictionary(0, &user_script);
user_script->Remove(keys::kMatches, NULL);
- EXPECT_FALSE(extension.InitFromValue(*input_value, true, &error));
+ EXPECT_FALSE(extension.InitFromValue(*input_value, true, false, &error));
EXPECT_TRUE(MatchPattern(error, errors::kInvalidMatches));
user_script->Set(keys::kMatches, Value::CreateIntegerValue(42));
- EXPECT_FALSE(extension.InitFromValue(*input_value, true, &error));
+ EXPECT_FALSE(extension.InitFromValue(*input_value, true, false, &error));
EXPECT_TRUE(MatchPattern(error, errors::kInvalidMatches));
ListValue* matches = new ListValue;
user_script->Set(keys::kMatches, matches);
- EXPECT_FALSE(extension.InitFromValue(*input_value, true, &error));
+ EXPECT_FALSE(extension.InitFromValue(*input_value, true, false, &error));
EXPECT_TRUE(MatchPattern(error, errors::kInvalidMatchCount));
// Test invalid match element
matches->Set(0, Value::CreateIntegerValue(42));
- EXPECT_FALSE(extension.InitFromValue(*input_value, true, &error));
+ EXPECT_FALSE(extension.InitFromValue(*input_value, true, false, &error));
EXPECT_TRUE(MatchPattern(error, errors::kInvalidMatch));
matches->Set(0, Value::CreateStringValue("chrome://*/*"));
- EXPECT_FALSE(extension.InitFromValue(*input_value, true, &error));
+ EXPECT_FALSE(extension.InitFromValue(*input_value, true, false, &error));
EXPECT_TRUE(MatchPattern(error, errors::kInvalidMatch));
// Test missing and invalid files array
@@ -200,67 +200,68 @@ TEST(ExtensionTest, InitFromValueInvalid) {
content_scripts->GetDictionary(0, &user_script);
user_script->Remove(keys::kJs, NULL);
user_script->Remove(keys::kCss, NULL);
- EXPECT_FALSE(extension.InitFromValue(*input_value, true, &error));
+ EXPECT_FALSE(extension.InitFromValue(*input_value, true, false, &error));
EXPECT_TRUE(MatchPattern(error, errors::kMissingFile));
user_script->Set(keys::kJs, Value::CreateIntegerValue(42));
- EXPECT_FALSE(extension.InitFromValue(*input_value, true, &error));
+ EXPECT_FALSE(extension.InitFromValue(*input_value, true, false, &error));
EXPECT_TRUE(MatchPattern(error, errors::kInvalidJsList));
user_script->Set(keys::kCss, new ListValue);
user_script->Set(keys::kJs, new ListValue);
- EXPECT_FALSE(extension.InitFromValue(*input_value, true, &error));
+ EXPECT_FALSE(extension.InitFromValue(*input_value, true, false, &error));
EXPECT_TRUE(MatchPattern(error, errors::kMissingFile));
user_script->Remove(keys::kCss, NULL);
ListValue* files = new ListValue;
user_script->Set(keys::kJs, files);
- EXPECT_FALSE(extension.InitFromValue(*input_value, true, &error));
+ EXPECT_FALSE(extension.InitFromValue(*input_value, true, false, &error));
EXPECT_TRUE(MatchPattern(error, errors::kMissingFile));
// Test invalid file element
files->Set(0, Value::CreateIntegerValue(42));
- EXPECT_FALSE(extension.InitFromValue(*input_value, true, &error));
+ EXPECT_FALSE(extension.InitFromValue(*input_value, true, false, &error));
EXPECT_TRUE(MatchPattern(error, errors::kInvalidJs));
user_script->Remove(keys::kJs, NULL);
// Test the css element
user_script->Set(keys::kCss, Value::CreateIntegerValue(42));
- EXPECT_FALSE(extension.InitFromValue(*input_value, true, &error));
+ EXPECT_FALSE(extension.InitFromValue(*input_value, true, false, &error));
EXPECT_TRUE(MatchPattern(error, errors::kInvalidCssList));
// Test invalid file element
ListValue* css_files = new ListValue;
user_script->Set(keys::kCss, css_files);
css_files->Set(0, Value::CreateIntegerValue(42));
- EXPECT_FALSE(extension.InitFromValue(*input_value, true, &error));
+ EXPECT_FALSE(extension.InitFromValue(*input_value, true, false, &error));
EXPECT_TRUE(MatchPattern(error, errors::kInvalidCss));
// Test missing and invalid permissions array
input_value.reset(valid_value->DeepCopy());
- EXPECT_TRUE(extension.InitFromValue(*input_value, true, &error));
+ EXPECT_TRUE(extension.InitFromValue(*input_value, true, false, &error));
+
ListValue* permissions = NULL;
input_value->GetList(keys::kPermissions, &permissions);
ASSERT_FALSE(NULL == permissions);
permissions = new ListValue;
input_value->Set(keys::kPermissions, permissions);
- EXPECT_TRUE(extension.InitFromValue(*input_value, true, &error));
+ EXPECT_TRUE(extension.InitFromValue(*input_value, true, false, &error));
input_value->Set(keys::kPermissions, Value::CreateIntegerValue(9));
- EXPECT_FALSE(extension.InitFromValue(*input_value, true, &error));
+ EXPECT_FALSE(extension.InitFromValue(*input_value, true, false, &error));
EXPECT_TRUE(MatchPattern(error, errors::kInvalidPermissions));
input_value.reset(valid_value->DeepCopy());
input_value->GetList(keys::kPermissions, &permissions);
permissions->Set(0, Value::CreateIntegerValue(24));
- EXPECT_FALSE(extension.InitFromValue(*input_value, true, &error));
+ EXPECT_FALSE(extension.InitFromValue(*input_value, true, false, &error));
EXPECT_TRUE(MatchPattern(error, errors::kInvalidPermission));
// We allow unknown API permissions, so this will be valid until we better
// distinguish between API and host permissions.
permissions->Set(0, Value::CreateStringValue("www.google.com"));
- EXPECT_TRUE(extension.InitFromValue(*input_value, true, &error));
+ EXPECT_TRUE(extension.InitFromValue(*input_value, true, false, &error));
// Multiple page actions are not allowed.
input_value.reset(valid_value->DeepCopy());
@@ -271,36 +272,36 @@ TEST(ExtensionTest, InitFromValueInvalid) {
action_list->Append(action->DeepCopy());
action_list->Append(action);
input_value->Set(keys::kPageActions, action_list);
- EXPECT_FALSE(extension.InitFromValue(*input_value, true, &error));
+ EXPECT_FALSE(extension.InitFromValue(*input_value, true, false, &error));
EXPECT_STREQ(errors::kInvalidPageActionsListSize, error.c_str());
// Test invalid options page url.
input_value.reset(valid_value->DeepCopy());
input_value->Set(keys::kOptionsPage, Value::CreateNullValue());
- EXPECT_FALSE(extension.InitFromValue(*input_value, true, &error));
+ EXPECT_FALSE(extension.InitFromValue(*input_value, true, false, &error));
EXPECT_TRUE(MatchPattern(error, errors::kInvalidOptionsPage));
// Test invalid/empty default locale.
input_value.reset(valid_value->DeepCopy());
input_value->Set(keys::kDefaultLocale, Value::CreateIntegerValue(5));
- EXPECT_FALSE(extension.InitFromValue(*input_value, true, &error));
+ EXPECT_FALSE(extension.InitFromValue(*input_value, true, false, &error));
EXPECT_TRUE(MatchPattern(error, errors::kInvalidDefaultLocale));
input_value->Set(keys::kDefaultLocale, Value::CreateStringValue(""));
- EXPECT_FALSE(extension.InitFromValue(*input_value, true, &error));
+ EXPECT_FALSE(extension.InitFromValue(*input_value, true, false, &error));
EXPECT_TRUE(MatchPattern(error, errors::kInvalidDefaultLocale));
// Test invalid minimum_chrome_version.
input_value.reset(valid_value->DeepCopy());
input_value->Set(keys::kMinimumChromeVersion, Value::CreateIntegerValue(42));
- EXPECT_FALSE(extension.InitFromValue(*input_value, true, &error));
+ EXPECT_FALSE(extension.InitFromValue(*input_value, true, false, &error));
EXPECT_TRUE(MatchPattern(error, errors::kInvalidMinimumChromeVersion));
#if !defined(OS_MACOSX)
// TODO(aa): The version isn't stamped into the unit test binary on mac.
input_value->Set(keys::kMinimumChromeVersion,
Value::CreateStringValue("88.8"));
- EXPECT_FALSE(extension.InitFromValue(*input_value, true, &error));
+ EXPECT_FALSE(extension.InitFromValue(*input_value, true, false, &error));
EXPECT_TRUE(MatchPattern(error, errors::kChromeVersionTooLow));
#endif
}
@@ -321,7 +322,7 @@ TEST(ExtensionTest, InitFromValueValid) {
input_value.SetString(keys::kVersion, "1.0.0.0");
input_value.SetString(keys::kName, "my extension");
- EXPECT_TRUE(extension.InitFromValue(input_value, false, &error));
+ EXPECT_TRUE(extension.InitFromValue(input_value, false, false, &error));
EXPECT_EQ("", error);
EXPECT_TRUE(Extension::IdIsValid(extension.id()));
EXPECT_EQ("1.0.0.0", extension.VersionString());
@@ -336,12 +337,12 @@ TEST(ExtensionTest, InitFromValueValid) {
// We allow unknown API permissions, so this will be valid until we better
// distinguish between API and host permissions.
- EXPECT_TRUE(extension.InitFromValue(input_value, false, &error));
+ EXPECT_TRUE(extension.InitFromValue(input_value, false, false, &error));
input_value.Remove(keys::kPermissions, NULL);
// Test with an options page.
input_value.SetString(keys::kOptionsPage, "options.html");
- EXPECT_TRUE(extension.InitFromValue(input_value, false, &error));
+ EXPECT_TRUE(extension.InitFromValue(input_value, false, false, &error));
EXPECT_EQ("", error);
EXPECT_EQ("chrome-extension", extension.options_url().scheme());
EXPECT_EQ("/options.html", extension.options_url().path());
@@ -350,14 +351,14 @@ TEST(ExtensionTest, InitFromValueValid) {
// from being loaded.
ListValue* empty_list = new ListValue;
input_value.Set(keys::kPageActions, empty_list);
- EXPECT_TRUE(extension.InitFromValue(input_value, false, &error));
+ EXPECT_TRUE(extension.InitFromValue(input_value, false, false, &error));
EXPECT_EQ("", error);
#if !defined(OS_MACOSX)
// TODO(aa): The version isn't stamped into the unit test binary on mac.
// Test with a minimum_chrome_version.
input_value.SetString(keys::kMinimumChromeVersion, "1.0");
- EXPECT_TRUE(extension.InitFromValue(input_value, false, &error));
+ EXPECT_TRUE(extension.InitFromValue(input_value, false, false, &error));
EXPECT_EQ("", error);
// The minimum chrome version is not stored in the Extension object.
#endif
@@ -387,7 +388,7 @@ TEST(ExtensionTest, InitFromValueValidNameInRTL) {
// No strong RTL characters in name.
std::wstring name(L"Dictionary (by Google)");
input_value.SetString(keys::kName, WideToUTF16Hack(name));
- EXPECT_TRUE(extension.InitFromValue(input_value, false, &error));
+ EXPECT_TRUE(extension.InitFromValue(input_value, false, false, &error));
EXPECT_EQ("", error);
std::wstring localized_name(name);
base::i18n::AdjustStringForLocaleDirection(&localized_name);
@@ -396,7 +397,7 @@ TEST(ExtensionTest, InitFromValueValidNameInRTL) {
// Strong RTL characters in name.
name = L"Dictionary (\x05D1\x05D2"L" Google)";
input_value.SetString(keys::kName, WideToUTF16Hack(name));
- EXPECT_TRUE(extension.InitFromValue(input_value, false, &error));
+ EXPECT_TRUE(extension.InitFromValue(input_value, false, false, &error));
EXPECT_EQ("", error);
localized_name = name;
base::i18n::AdjustStringForLocaleDirection(&localized_name);
@@ -420,7 +421,7 @@ TEST(ExtensionTest, GetResourceURLAndPath) {
input_value.SetString(keys::kVersion, "1.0.0.0");
input_value.SetString(keys::kName, "my extension");
scoped_refptr<Extension> extension(Extension::Create(
- path, Extension::INVALID, input_value, false, NULL));
+ path, Extension::INVALID, input_value, false, true, NULL));
EXPECT_TRUE(extension.get());
EXPECT_EQ(extension->url().spec() + "bar/baz.js",
@@ -679,7 +680,7 @@ TEST(ExtensionTest, UpdateUrls) {
input_value.SetString(keys::kUpdateURL, url.spec());
scoped_refptr<Extension> extension(Extension::Create(
- path, Extension::INVALID, input_value, false, &error));
+ path, Extension::INVALID, input_value, false, true, &error));
EXPECT_TRUE(extension.get()) << error;
}
@@ -703,7 +704,7 @@ TEST(ExtensionTest, UpdateUrls) {
input_value.SetString(keys::kUpdateURL, invalid[i]);
scoped_refptr<Extension> extension(Extension::Create(
- path, Extension::INVALID, input_value, false, &error));
+ path, Extension::INVALID, input_value, false, true, &error));
EXPECT_FALSE(extension.get());
EXPECT_TRUE(MatchPattern(error, errors::kInvalidUpdateURL));
}
@@ -751,7 +752,7 @@ static scoped_refptr<Extension> LoadManifest(const std::string& dir,
scoped_refptr<Extension> extension = Extension::Create(
path.DirName(), Extension::INVALID,
- *static_cast<DictionaryValue*>(result.get()), false, &error);
+ *static_cast<DictionaryValue*>(result.get()), false, true, &error);
EXPECT_TRUE(extension) << error;
return extension;
}
@@ -972,7 +973,7 @@ TEST(ExtensionTest, ImageCaching) {
values.SetString(keys::kName, "test");
values.SetString(keys::kVersion, "0.1");
scoped_refptr<Extension> extension(Extension::Create(
- path, Extension::INVALID, values, false, &errors));
+ path, Extension::INVALID, values, false, true, &errors));
ASSERT_TRUE(extension.get());
// Create an ExtensionResource pointing at an icon.
@@ -1056,7 +1057,7 @@ TEST(ExtensionTest, OldUnlimitedStoragePermission) {
// is present.
std::string errors;
scoped_refptr<Extension> extension(Extension::Create(
- extension_path, Extension::INVALID, dictionary, false, &errors));
+ extension_path, Extension::INVALID, dictionary, false, true, &errors));
EXPECT_TRUE(extension.get());
EXPECT_TRUE(extension->HasApiPermission(
Extension::kUnlimitedStoragePermission));
diff --git a/chrome/common/extensions/extension_unpacker.cc b/chrome/common/extensions/extension_unpacker.cc
index 25919cf..fee4b54 100644
--- a/chrome/common/extensions/extension_unpacker.cc
+++ b/chrome/common/extensions/extension_unpacker.cc
@@ -177,7 +177,12 @@ bool ExtensionUnpacker::Run() {
// EXTENSION.
std::string error;
scoped_refptr<Extension> extension(Extension::Create(
- temp_install_dir_, Extension::INVALID, *parsed_manifest_, false, &error));
+ temp_install_dir_,
+ Extension::INVALID,
+ *parsed_manifest_,
+ false, // Do not require a key
+ false, // Do not enable strict error checks
+ &error));
if (!extension.get()) {
SetError(error);
return false;
diff --git a/chrome/common/extensions/url_pattern.cc b/chrome/common/extensions/url_pattern.cc
index 6dc3578..5eb0beb 100644
--- a/chrome/common/extensions/url_pattern.cc
+++ b/chrome/common/extensions/url_pattern.cc
@@ -11,10 +11,14 @@
#include "googleurl/src/gurl.h"
#include "googleurl/src/url_util.h"
+const char URLPattern::kAllUrlsPattern[] = "<all_urls>";
+
+namespace {
+
// TODO(aa): Consider adding chrome-extension? What about more obscure ones
// like data: and javascript: ?
// Note: keep this array in sync with kValidSchemeMasks.
-static const char* kValidSchemes[] = {
+const char* kValidSchemes[] = {
chrome::kHttpScheme,
chrome::kHttpsScheme,
chrome::kFileScheme,
@@ -22,7 +26,7 @@ static const char* kValidSchemes[] = {
chrome::kChromeUIScheme,
};
-static const int kValidSchemeMasks[] = {
+const int kValidSchemeMasks[] = {
URLPattern::SCHEME_HTTP,
URLPattern::SCHEME_HTTPS,
URLPattern::SCHEME_FILE,
@@ -33,11 +37,34 @@ static const int kValidSchemeMasks[] = {
COMPILE_ASSERT(arraysize(kValidSchemes) == arraysize(kValidSchemeMasks),
must_keep_these_arrays_in_sync);
-static const char kPathSeparator[] = "/";
+const char* kParseSuccess = "Success.";
+const char* kParseErrorMissingSchemeSeparator = "Missing scheme separator.";
+const char* kParseErrorInvalidScheme = "Invalid scheme.";
+const char* kParseErrorWrongSchemeType = "Wrong scheme type.";
+const char* kParseErrorEmptyHost = "Host can not be empty.";
+const char* kParseErrorInvalidHostWildcard = "Invalid host wildcard.";
+const char* kParseErrorEmptyPath = "Empty path.";
+const char* kParseErrorHasColon =
+ "Ports are not supported in URL patterns. ':' may not be used in a host.";
+
+// Message explaining each URLPattern::ParseResult.
+const char* kParseResultMessages[] = {
+ kParseSuccess,
+ kParseErrorMissingSchemeSeparator,
+ kParseErrorInvalidScheme,
+ kParseErrorWrongSchemeType,
+ kParseErrorEmptyHost,
+ kParseErrorInvalidHostWildcard,
+ kParseErrorEmptyPath,
+ kParseErrorHasColon
+};
-const char URLPattern::kAllUrlsPattern[] = "<all_urls>";
+COMPILE_ASSERT(URLPattern::NUM_PARSE_RESULTS == arraysize(kParseResultMessages),
+ must_add_message_for_each_parse_result);
+
+const char kPathSeparator[] = "/";
-static bool IsStandardScheme(const std::string& scheme) {
+bool IsStandardScheme(const std::string& scheme) {
// "*" gets the same treatment as a standard scheme.
if (scheme == "*")
return true;
@@ -46,6 +73,8 @@ static bool IsStandardScheme(const std::string& scheme) {
url_parse::Component(0, static_cast<int>(scheme.length())));
}
+} // namespace
+
URLPattern::URLPattern()
: valid_schemes_(SCHEME_NONE),
match_all_urls_(false),
@@ -58,14 +87,21 @@ URLPattern::URLPattern(int valid_schemes)
URLPattern::URLPattern(int valid_schemes, const std::string& pattern)
: valid_schemes_(valid_schemes), match_all_urls_(false),
match_subdomains_(false) {
- if (PARSE_SUCCESS != Parse(pattern))
+
+ // Strict error checking is used, because this constructor is only
+ // appropriate when we know |pattern| is valid.
+ if (PARSE_SUCCESS != Parse(pattern, PARSE_STRICT))
NOTREACHED() << "URLPattern is invalid: " << pattern;
}
URLPattern::~URLPattern() {
}
-URLPattern::ParseResult URLPattern::Parse(const std::string& pattern) {
+URLPattern::ParseResult URLPattern::Parse(const std::string& pattern,
+ ParseOption strictness) {
+ CHECK(strictness == PARSE_LENIENT ||
+ strictness == PARSE_STRICT);
+
// Special case pattern to match every valid URL.
if (pattern == kAllUrlsPattern) {
match_all_urls_ = true;
@@ -142,6 +178,9 @@ URLPattern::ParseResult URLPattern::Parse(const std::string& pattern) {
SetPath(pattern.substr(path_start_pos));
+ if (strictness == PARSE_STRICT && host_.find(':') != std::string::npos)
+ return PARSE_ERROR_HAS_COLON;
+
return PARSE_SUCCESS;
}
@@ -310,3 +349,9 @@ std::vector<URLPattern> URLPattern::ConvertToExplicitSchemes() const {
return result;
}
+
+// static
+const char* URLPattern::GetParseResultString(
+ URLPattern::ParseResult parse_result) {
+ return kParseResultMessages[parse_result];
+}
diff --git a/chrome/common/extensions/url_pattern.h b/chrome/common/extensions/url_pattern.h
index 723dc2c..edd92d4 100644
--- a/chrome/common/extensions/url_pattern.h
+++ b/chrome/common/extensions/url_pattern.h
@@ -91,15 +91,23 @@ class URLPattern {
SCHEME_ALL = -1,
};
+ // Options for URLPattern::Parse().
+ enum ParseOption {
+ PARSE_LENIENT,
+ PARSE_STRICT
+ };
+
// Error codes returned from Parse().
enum ParseResult {
- PARSE_SUCCESS,
+ PARSE_SUCCESS = 0,
PARSE_ERROR_MISSING_SCHEME_SEPARATOR,
PARSE_ERROR_INVALID_SCHEME,
PARSE_ERROR_WRONG_SCHEME_SEPARATOR,
PARSE_ERROR_EMPTY_HOST,
PARSE_ERROR_INVALID_HOST_WILDCARD,
PARSE_ERROR_EMPTY_PATH,
+ PARSE_ERROR_HAS_COLON, // Only checked when strict checks are enabled.
+ NUM_PARSE_RESULTS
};
// The <all_urls> string pattern.
@@ -149,8 +157,16 @@ class URLPattern {
// Initializes this instance by parsing the provided string. Returns
// URLPattern::PARSE_SUCCESS on success, or an error code otherwise. On
// failure, this instance will have some intermediate values and is in an
- // invalid state.
- ParseResult Parse(const std::string& pattern_str);
+ // invalid state. Adding error checks to URLPattern::Parse() can cause
+ // patterns in installed extensions to fail. If an installed extension
+ // uses a pattern that was valid but fails a new error check, the
+ // extension will fail to load when chrome is auto-updated. To avoid
+ // this, new parse checks are enabled only when |strictness| is
+ // OPTION_STRICT. OPTION_STRICT should be used when loading in developer
+ // mode, or when an extension's patterns are controlled by chrome (such
+ // as component extensions).
+ ParseResult Parse(const std::string& pattern_str,
+ ParseOption strictness);
// Sets the scheme for pattern matches. This can be a single '*' if the
// pattern matches all valid schemes (as defined by the valid_schemes_
@@ -205,6 +221,9 @@ class URLPattern {
};
};
+ // Get an error string for a ParseResult.
+ static const char* GetParseResultString(URLPattern::ParseResult parse_result);
+
private:
#if !(defined(_MSC_VER) && _MSC_VER >= 1600)
friend class std::vector<URLPattern>;
diff --git a/chrome/common/extensions/url_pattern_unittest.cc b/chrome/common/extensions/url_pattern_unittest.cc
index 33bf8a0..cc9c605 100644
--- a/chrome/common/extensions/url_pattern_unittest.cc
+++ b/chrome/common/extensions/url_pattern_unittest.cc
@@ -29,6 +29,7 @@ TEST(ExtensionURLPatternTest, ParseInvalid) {
{ "http:///", URLPattern::PARSE_ERROR_EMPTY_HOST },
{ "http://*foo/bar", URLPattern::PARSE_ERROR_INVALID_HOST_WILDCARD },
{ "http://foo.*.bar/baz", URLPattern::PARSE_ERROR_INVALID_HOST_WILDCARD },
+ { "http://fo.*.ba:123/baz", URLPattern::PARSE_ERROR_INVALID_HOST_WILDCARD },
{ "http:/bar", URLPattern::PARSE_ERROR_WRONG_SCHEME_SEPARATOR },
{ "http://bar", URLPattern::PARSE_ERROR_EMPTY_PATH },
};
@@ -36,15 +37,55 @@ TEST(ExtensionURLPatternTest, ParseInvalid) {
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kInvalidPatterns); ++i) {
URLPattern pattern(URLPattern::SCHEME_ALL);
EXPECT_EQ(kInvalidPatterns[i].expected_result,
- pattern.Parse(kInvalidPatterns[i].pattern))
+ pattern.Parse(kInvalidPatterns[i].pattern,
+ URLPattern::PARSE_LENIENT))
<< kInvalidPatterns[i].pattern;
}
};
+TEST(ExtensionURLPatternTest, Colons) {
+ const struct {
+ const char* pattern;
+ URLPattern::ParseResult expected_result;
+ } kTestPatterns[] = {
+ { "http://foo:1234/", URLPattern::PARSE_ERROR_HAS_COLON },
+ { "http://foo:1234/bar", URLPattern::PARSE_ERROR_HAS_COLON },
+ { "http://*.foo:1234/", URLPattern::PARSE_ERROR_HAS_COLON },
+ { "http://*.foo:1234/bar", URLPattern::PARSE_ERROR_HAS_COLON },
+ { "http://:1234/", URLPattern::PARSE_ERROR_HAS_COLON },
+ { "http://foo:/", URLPattern::PARSE_ERROR_HAS_COLON },
+ { "http://*.foo:/", URLPattern::PARSE_ERROR_HAS_COLON },
+ { "http://foo:com/", URLPattern::PARSE_ERROR_HAS_COLON },
+
+ // Port-like strings in the path should not trigger a warning.
+ { "http://*/:1234", URLPattern::PARSE_SUCCESS },
+ { "http://*.foo/bar:1234", URLPattern::PARSE_SUCCESS },
+ { "http://foo/bar:1234/path", URLPattern::PARSE_SUCCESS },
+ };
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestPatterns); ++i) {
+ URLPattern pattern(URLPattern::SCHEME_ALL);
+
+ // Without |strict_error_checks|, expect success.
+ EXPECT_EQ(URLPattern::PARSE_SUCCESS,
+ pattern.Parse(kTestPatterns[i].pattern,
+ URLPattern::PARSE_LENIENT))
+ << "Got unexpected error for URL pattern: "
+ << kTestPatterns[i].pattern;
+
+ EXPECT_EQ(kTestPatterns[i].expected_result,
+ pattern.Parse(kTestPatterns[i].pattern,
+ URLPattern::PARSE_STRICT))
+ << "Got unexpected result for URL pattern: "
+ << kTestPatterns[i].pattern;
+ }
+};
+
// all pages for a given scheme
TEST(ExtensionURLPatternTest, Match1) {
URLPattern pattern(kAllSchemes);
- EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse("http://*/*"));
+ EXPECT_EQ(URLPattern::PARSE_SUCCESS,
+ pattern.Parse("http://*/*", URLPattern::PARSE_STRICT));
EXPECT_EQ("http", pattern.scheme());
EXPECT_EQ("", pattern.host());
EXPECT_TRUE(pattern.match_subdomains());
@@ -60,7 +101,8 @@ TEST(ExtensionURLPatternTest, Match1) {
// all domains
TEST(ExtensionURLPatternTest, Match2) {
URLPattern pattern(kAllSchemes);
- EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse("https://*/foo*"));
+ EXPECT_EQ(URLPattern::PARSE_SUCCESS,
+ pattern.Parse("https://*/foo*", URLPattern::PARSE_STRICT));
EXPECT_EQ("https", pattern.scheme());
EXPECT_EQ("", pattern.host());
EXPECT_TRUE(pattern.match_subdomains());
@@ -76,7 +118,8 @@ TEST(ExtensionURLPatternTest, Match2) {
TEST(URLPatternTest, Match3) {
URLPattern pattern(kAllSchemes);
EXPECT_EQ(URLPattern::PARSE_SUCCESS,
- pattern.Parse("http://*.google.com/foo*bar"));
+ pattern.Parse("http://*.google.com/foo*bar",
+ URLPattern::PARSE_STRICT));
EXPECT_EQ("http", pattern.scheme());
EXPECT_EQ("google.com", pattern.host());
EXPECT_TRUE(pattern.match_subdomains());
@@ -93,7 +136,7 @@ TEST(URLPatternTest, Match3) {
TEST(ExtensionURLPatternTest, Match5) {
URLPattern pattern(kAllSchemes);
EXPECT_EQ(URLPattern::PARSE_SUCCESS,
- pattern.Parse("file:///foo?bar\\*baz"));
+ pattern.Parse("file:///foo?bar\\*baz", URLPattern::PARSE_STRICT));
EXPECT_EQ("file", pattern.scheme());
EXPECT_EQ("", pattern.host());
EXPECT_FALSE(pattern.match_subdomains());
@@ -107,7 +150,7 @@ TEST(ExtensionURLPatternTest, Match5) {
TEST(ExtensionURLPatternTest, Match6) {
URLPattern pattern(kAllSchemes);
EXPECT_EQ(URLPattern::PARSE_SUCCESS,
- pattern.Parse("http://127.0.0.1/*"));
+ pattern.Parse("http://127.0.0.1/*", URLPattern::PARSE_STRICT));
EXPECT_EQ("http", pattern.scheme());
EXPECT_EQ("127.0.0.1", pattern.host());
EXPECT_FALSE(pattern.match_subdomains());
@@ -120,7 +163,8 @@ TEST(ExtensionURLPatternTest, Match6) {
TEST(ExtensionURLPatternTest, Match7) {
URLPattern pattern(kAllSchemes);
EXPECT_EQ(URLPattern::PARSE_SUCCESS,
- pattern.Parse("http://*.0.0.1/*")); // allowed, but useless
+ pattern.Parse("http://*.0.0.1/*",
+ URLPattern::PARSE_STRICT)); // allowed, but useless
EXPECT_EQ("http", pattern.scheme());
EXPECT_EQ("0.0.1", pattern.host());
EXPECT_TRUE(pattern.match_subdomains());
@@ -136,7 +180,8 @@ TEST(ExtensionURLPatternTest, Match8) {
// The below is the ASCII encoding of the following URL:
// http://*.\xe1\x80\xbf/a\xc2\x81\xe1*
EXPECT_EQ(URLPattern::PARSE_SUCCESS,
- pattern.Parse("http://*.xn--gkd/a%C2%81%E1*"));
+ pattern.Parse("http://*.xn--gkd/a%C2%81%E1*",
+ URLPattern::PARSE_STRICT));
EXPECT_EQ("http", pattern.scheme());
EXPECT_EQ("xn--gkd", pattern.host());
EXPECT_TRUE(pattern.match_subdomains());
@@ -152,7 +197,7 @@ TEST(ExtensionURLPatternTest, Match8) {
TEST(ExtensionURLPatternTest, Match9) {
URLPattern pattern(kAllSchemes);
EXPECT_EQ(URLPattern::PARSE_SUCCESS,
- pattern.Parse("chrome://favicon/*"));
+ pattern.Parse("chrome://favicon/*", URLPattern::PARSE_STRICT));
EXPECT_EQ("chrome", pattern.scheme());
EXPECT_EQ("favicon", pattern.host());
EXPECT_FALSE(pattern.match_subdomains());
@@ -166,7 +211,8 @@ TEST(ExtensionURLPatternTest, Match9) {
// *://
TEST(ExtensionURLPatternTest, Match10) {
URLPattern pattern(kAllSchemes);
- EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse("*://*/*"));
+ EXPECT_EQ(URLPattern::PARSE_SUCCESS,
+ pattern.Parse("*://*/*", URLPattern::PARSE_STRICT));
EXPECT_TRUE(pattern.MatchesScheme("http"));
EXPECT_TRUE(pattern.MatchesScheme("https"));
EXPECT_FALSE(pattern.MatchesScheme("chrome"));
@@ -183,7 +229,8 @@ TEST(ExtensionURLPatternTest, Match10) {
// <all_urls>
TEST(ExtensionURLPatternTest, Match11) {
URLPattern pattern(kAllSchemes);
- EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse("<all_urls>"));
+ EXPECT_EQ(URLPattern::PARSE_SUCCESS,
+ pattern.Parse("<all_urls>", URLPattern::PARSE_STRICT));
EXPECT_TRUE(pattern.MatchesScheme("chrome"));
EXPECT_TRUE(pattern.MatchesScheme("http"));
EXPECT_TRUE(pattern.MatchesScheme("https"));
@@ -199,7 +246,8 @@ TEST(ExtensionURLPatternTest, Match11) {
// SCHEME_ALL matches all schemes.
TEST(ExtensionURLPatternTest, Match12) {
URLPattern pattern(URLPattern::SCHEME_ALL);
- EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse("<all_urls>"));
+ EXPECT_EQ(URLPattern::PARSE_SUCCESS,
+ pattern.Parse("<all_urls>", URLPattern::PARSE_STRICT));
EXPECT_TRUE(pattern.MatchesScheme("chrome"));
EXPECT_TRUE(pattern.MatchesScheme("http"));
EXPECT_TRUE(pattern.MatchesScheme("https"));
@@ -238,7 +286,8 @@ TEST(ExtensionURLPatternTest, Match13) {
for (size_t i = 0; i < arraysize(kMatch13UrlPatternTestCases); ++i) {
URLPattern pattern(URLPattern::SCHEME_ALL);
EXPECT_EQ(URLPattern::PARSE_SUCCESS,
- pattern.Parse(kMatch13UrlPatternTestCases[i].pattern))
+ pattern.Parse(kMatch13UrlPatternTestCases[i].pattern,
+ URLPattern::PARSE_STRICT))
<< " while parsing " << kMatch13UrlPatternTestCases[i].pattern;
EXPECT_TRUE(pattern.MatchesUrl(
GURL(kMatch13UrlPatternTestCases[i].matches)))
@@ -247,7 +296,8 @@ TEST(ExtensionURLPatternTest, Match13) {
// Negative test.
URLPattern pattern(URLPattern::SCHEME_ALL);
- EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse("data:*"));
+ EXPECT_EQ(URLPattern::PARSE_SUCCESS,
+ pattern.Parse("data:*", URLPattern::PARSE_STRICT));
EXPECT_FALSE(pattern.MatchesUrl(GURL("about:blank")));
};
@@ -272,7 +322,8 @@ TEST(ExtensionURLPatternTest, GetAsString) {
for (size_t i = 0; i < arraysize(kGetAsStringTestCases); ++i) {
URLPattern pattern(URLPattern::SCHEME_ALL);
EXPECT_EQ(URLPattern::PARSE_SUCCESS,
- pattern.Parse(kGetAsStringTestCases[i].pattern));
+ pattern.Parse(kGetAsStringTestCases[i].pattern,
+ URLPattern::PARSE_STRICT));
EXPECT_STREQ(kGetAsStringTestCases[i].pattern,
pattern.GetAsString().c_str());
}
diff --git a/chrome/common/extensions/user_script.cc b/chrome/common/extensions/user_script.cc
index b66dee94..488922d 100644
--- a/chrome/common/extensions/user_script.cc
+++ b/chrome/common/extensions/user_script.cc
@@ -195,7 +195,8 @@ void UserScript::Unpickle(const ::Pickle& pickle, void** iter) {
std::string pattern_str;
URLPattern pattern(valid_schemes);
CHECK(pickle.ReadString(iter, &pattern_str));
- CHECK(URLPattern::PARSE_SUCCESS == pattern.Parse(pattern_str));
+ CHECK(URLPattern::PARSE_SUCCESS ==
+ pattern.Parse(pattern_str, URLPattern::PARSE_LENIENT));
url_patterns_.push_back(pattern);
}
diff --git a/chrome/common/extensions/user_script_unittest.cc b/chrome/common/extensions/user_script_unittest.cc
index 297de7b..bec6436 100644
--- a/chrome/common/extensions/user_script_unittest.cc
+++ b/chrome/common/extensions/user_script_unittest.cc
@@ -71,7 +71,8 @@ TEST(ExtensionUserScriptTest, Match5) {
TEST(ExtensionUserScriptTest, Match6) {
URLPattern pattern(kAllSchemes);
- ASSERT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse("http://*/foo*"));
+ ASSERT_EQ(URLPattern::PARSE_SUCCESS,
+ pattern.Parse("http://*/foo*", URLPattern::PARSE_STRICT));
UserScript script;
script.add_url_pattern(pattern);
@@ -87,7 +88,8 @@ TEST(ExtensionUserScriptTest, UrlPatternGlobInteraction) {
URLPattern pattern(kAllSchemes);
ASSERT_EQ(URLPattern::PARSE_SUCCESS,
- pattern.Parse("http://www.google.com/*"));
+ pattern.Parse("http://www.google.com/*",
+ URLPattern::PARSE_STRICT));
script.add_url_pattern(pattern);
script.add_glob("*bar*");
@@ -115,8 +117,10 @@ TEST(ExtensionUserScriptTest, UrlPatternGlobInteraction) {
TEST(ExtensionUserScriptTest, Pickle) {
URLPattern pattern1(kAllSchemes);
URLPattern pattern2(kAllSchemes);
- ASSERT_EQ(URLPattern::PARSE_SUCCESS, pattern1.Parse("http://*/foo*"));
- ASSERT_EQ(URLPattern::PARSE_SUCCESS, pattern2.Parse("http://bar/baz*"));
+ ASSERT_EQ(URLPattern::PARSE_SUCCESS,
+ pattern1.Parse("http://*/foo*", URLPattern::PARSE_STRICT));
+ ASSERT_EQ(URLPattern::PARSE_SUCCESS,
+ pattern2.Parse("http://bar/baz*", URLPattern::PARSE_STRICT));
UserScript script1;
script1.js_scripts().push_back(UserScript::File(
diff --git a/chrome/common/render_messages.cc b/chrome/common/render_messages.cc
index 3d1f767..8cdcf51 100644
--- a/chrome/common/render_messages.cc
+++ b/chrome/common/render_messages.cc
@@ -834,7 +834,7 @@ bool ParamTraits<URLPattern>::Read(const Message* m, void** iter,
return false;
p->set_valid_schemes(valid_schemes);
- return URLPattern::PARSE_SUCCESS == p->Parse(spec);
+ return URLPattern::PARSE_SUCCESS == p->Parse(spec, URLPattern::PARSE_LENIENT);
}
void ParamTraits<URLPattern>::Log(const param_type& p, std::string* l) {
diff --git a/chrome/common/render_messages_params.cc b/chrome/common/render_messages_params.cc
index fa0a38e..149e521 100644
--- a/chrome/common/render_messages_params.cc
+++ b/chrome/common/render_messages_params.cc
@@ -327,10 +327,15 @@ scoped_refptr<Extension>
ViewMsg_ExtensionLoaded_Params::ConvertToExtension() const {
// Extensions that are loaded unpacked won't have a key.
const bool kRequireKey = false;
+
+ // The extension may have been loaded in a way that does not require
+ // strict error checks to pass. Do not do strict checks here.
+ const bool kStrictErrorChecks = false;
std::string error;
scoped_refptr<Extension> extension(
- Extension::Create(path, location, *manifest, kRequireKey, &error));
+ Extension::Create(path, location, *manifest, kRequireKey,
+ kStrictErrorChecks, &error));
if (!extension.get())
LOG(ERROR) << "Error deserializing extension: " << error;
diff --git a/chrome/test/data/extensions/manifest_tests/content_script_match_pattern_not_string.json b/chrome/test/data/extensions/manifest_tests/content_script_match_pattern_not_string.json
new file mode 100644
index 0000000..830ca39
--- /dev/null
+++ b/chrome/test/data/extensions/manifest_tests/content_script_match_pattern_not_string.json
@@ -0,0 +1,9 @@
+{
+ "name": "test",
+ "version": "1",
+ "content_scripts": [
+ {
+ "matches": [12345]
+ }
+ ]
+}
diff --git a/chrome/test/data/extensions/manifest_tests/forbid_ports_in_content_scripts.json b/chrome/test/data/extensions/manifest_tests/forbid_ports_in_content_scripts.json
new file mode 100644
index 0000000..fdb6411
--- /dev/null
+++ b/chrome/test/data/extensions/manifest_tests/forbid_ports_in_content_scripts.json
@@ -0,0 +1,14 @@
+{
+ "name": "test",
+ "version": "1",
+ "content_scripts": [
+ {
+ "matches": ["http://*.no.port.okay/path/*"],
+ "js": ["javascript.js"]
+ },
+ {
+ "matches": ["http://*.has.port.error:12345/path/*"],
+ "js": ["javascript.js"]
+ }
+ ]
+}
diff --git a/chrome/test/data/extensions/manifest_tests/forbid_ports_in_permissions.json b/chrome/test/data/extensions/manifest_tests/forbid_ports_in_permissions.json
new file mode 100644
index 0000000..9c5b870
--- /dev/null
+++ b/chrome/test/data/extensions/manifest_tests/forbid_ports_in_permissions.json
@@ -0,0 +1,8 @@
+{
+ "name": "test",
+ "version": "1",
+ "permissions": [
+ "http://*.no.port.okay/path/*",
+ "http://*.has.port.error:12345/path/*"
+ ]
+}
diff --git a/chrome/test/data/extensions/manifest_tests/web_urls_invalid_5.json b/chrome/test/data/extensions/manifest_tests/web_urls_invalid_5.json
new file mode 100644
index 0000000..ca3e4fe
--- /dev/null
+++ b/chrome/test/data/extensions/manifest_tests/web_urls_invalid_5.json
@@ -0,0 +1,13 @@
+{
+ "name": "test",
+ "version": "1",
+ "app": {
+ "urls": [
+ "http://*.example.com/path",
+ "https://*/path"
+ ],
+ "launch": {
+ "web_url": "http://www.google.com/foo.html"
+ }
+ }
+}
diff --git a/chrome/test/data/extensions/manifest_tests/web_urls_invalid_has_port.json b/chrome/test/data/extensions/manifest_tests/web_urls_invalid_has_port.json
new file mode 100644
index 0000000..9ae851b
--- /dev/null
+++ b/chrome/test/data/extensions/manifest_tests/web_urls_invalid_has_port.json
@@ -0,0 +1,16 @@
+{
+ "name": "test",
+ "version": "1",
+ "app": {
+ "urls": [
+ "http://www.google.com/mail/",
+ "http://www.google.com:12345/foobar/"
+ ],
+ "launch": {
+ "web_url": "http://www.google.com/mail/"
+ }
+ },
+ "permissions": [
+ "notifications"
+ ]
+}
diff --git a/chrome/test/live_sync/live_extensions_sync_test_base.cc b/chrome/test/live_sync/live_extensions_sync_test_base.cc
index 1fb31c8..97e245a 100644
--- a/chrome/test/live_sync/live_extensions_sync_test_base.cc
+++ b/chrome/test/live_sync/live_extensions_sync_test_base.cc
@@ -48,7 +48,7 @@ scoped_refptr<Extension> CreateExtension(
std::string error;
scoped_refptr<Extension> extension =
Extension::Create(extension_dir,
- Extension::INTERNAL, source, false, &error);
+ Extension::INTERNAL, source, false, true, &error);
if (!error.empty()) {
LOG(WARNING) << error;
return NULL;