diff options
author | aa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-10 22:44:21 +0000 |
---|---|---|
committer | aa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-10 22:44:21 +0000 |
commit | a72f5f32c228dd262f7c57546b4cc39c95860c03 (patch) | |
tree | 1741a93170a48fcda4a252eb377a20b48f960f2f | |
parent | 6ebdd17b6b90b0bba9363098987712d7770e89ef (diff) | |
download | chromium_src-a72f5f32c228dd262f7c57546b4cc39c95860c03.zip chromium_src-a72f5f32c228dd262f7c57546b4cc39c95860c03.tar.gz chromium_src-a72f5f32c228dd262f7c57546b4cc39c95860c03.tar.bz2 |
Optionally support URLPatterns in standalone user
scripts via the @match declaration.
In the future, maybe @include will be deprecated
and result in a warning.
Review URL: http://codereview.chromium.org/20127
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@9526 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/extensions/user_script_master.cc | 51 | ||||
-rw-r--r-- | chrome/browser/extensions/user_script_master.h | 5 | ||||
-rw-r--r-- | chrome/browser/extensions/user_script_master_unittest.cc | 49 |
3 files changed, 86 insertions, 19 deletions
diff --git a/chrome/browser/extensions/user_script_master.cc b/chrome/browser/extensions/user_script_master.cc index 4ca10fb..7164dc1 100644 --- a/chrome/browser/extensions/user_script_master.cc +++ b/chrome/browser/extensions/user_script_master.cc @@ -21,7 +21,19 @@ extern const char kExtensionURLScheme[]; extern const char kUserScriptURLScheme[]; // static -void UserScriptMaster::ScriptReloader::ParseMetadataHeader( +bool GetDeclarationValue(const StringPiece& line, const StringPiece& prefix, + std::string* value) { + if (!line.starts_with(prefix)) + return false; + + std::string temp(line.data() + prefix.length(), + line.length() - prefix.length()); + TrimWhitespace(temp, TRIM_ALL, value); + return true; +} + +// static +bool UserScriptMaster::ScriptReloader::ParseMetadataHeader( const StringPiece& script_text, UserScript* script) { // http://wiki.greasespot.net/Metadata_block StringPiece line; @@ -32,6 +44,7 @@ void UserScriptMaster::ScriptReloader::ParseMetadataHeader( static const StringPiece kUserScriptBegin("// ==UserScript=="); static const StringPiece kUserScriptEng("// ==/UserScript=="); static const StringPiece kIncludeDeclaration("// @include "); + static const StringPiece kMatchDeclaration("// @match "); while (line_start < script_text.length()) { line_end = script_text.find('\n', line_start); @@ -52,17 +65,17 @@ void UserScriptMaster::ScriptReloader::ParseMetadataHeader( break; } - if (line.starts_with(kIncludeDeclaration)) { - std::string pattern(line.data() + kIncludeDeclaration.length(), - line.length() - kIncludeDeclaration.length()); - std::string pattern_trimmed; - TrimWhitespace(pattern, TRIM_ALL, &pattern_trimmed); - + std::string value; + if (GetDeclarationValue(line, kIncludeDeclaration, &value)) { // We escape some characters that MatchPattern() considers special. - ReplaceSubstringsAfterOffset(&pattern_trimmed, 0, "\\", "\\\\"); - ReplaceSubstringsAfterOffset(&pattern_trimmed, 0, "?", "\\?"); - - script->add_glob(pattern_trimmed); + ReplaceSubstringsAfterOffset(&value, 0, "\\", "\\\\"); + ReplaceSubstringsAfterOffset(&value, 0, "?", "\\?"); + script->add_glob(value); + } else if (GetDeclarationValue(line, kMatchDeclaration, &value)) { + URLPattern pattern; + if (!pattern.Parse(value)) + return false; + script->add_url_pattern(pattern); } // TODO(aa): Handle more types of metadata. @@ -71,11 +84,16 @@ void UserScriptMaster::ScriptReloader::ParseMetadataHeader( line_start = line_end + 1; } - // If no @include patterns were specified, default to @include *. - // This is what Greasemonkey does. - if (script->globs().size() == 0) { + // It is probably a mistake to declare both @include and @match rules. + if (script->globs().size() > 0 && script->url_patterns().size() > 0) + return false; + + // If no patterns were specified, default to @include *. This is what + // Greasemonkey does. + if (script->globs().size() == 0 && script->url_patterns().size() == 0) script->add_glob("*"); - } + + return true; } void UserScriptMaster::ScriptReloader::StartScan( @@ -153,7 +171,8 @@ base::SharedMemory* UserScriptMaster::ScriptReloader::GetNewScripts( if (iter->url_patterns().empty()) { // TODO(aa): Handle errors parsing header. - ParseMetadataHeader(contents, &(*iter)); + if (!ParseMetadataHeader(contents, &(*iter))) + return NULL; } iter->Pickle(&pickle); diff --git a/chrome/browser/extensions/user_script_master.h b/chrome/browser/extensions/user_script_master.h index 8969281..f156180 100644 --- a/chrome/browser/extensions/user_script_master.h +++ b/chrome/browser/extensions/user_script_master.h @@ -57,6 +57,9 @@ class UserScriptMaster : public base::RefCounted<UserScriptMaster>, FRIEND_TEST(UserScriptMasterTest, Parse1); FRIEND_TEST(UserScriptMasterTest, Parse2); FRIEND_TEST(UserScriptMasterTest, Parse3); + FRIEND_TEST(UserScriptMasterTest, Parse4); + FRIEND_TEST(UserScriptMasterTest, Parse5); + FRIEND_TEST(UserScriptMasterTest, Parse6); // We reload user scripts on the file thread to prevent blocking the UI. // ScriptReloader lives on the file thread and does the reload @@ -68,7 +71,7 @@ class UserScriptMaster : public base::RefCounted<UserScriptMaster>, : public base::RefCounted<UserScriptMaster::ScriptReloader> { public: // Parses the includes out of |script| and returns them in |includes|. - static void ParseMetadataHeader(const StringPiece& script_text, + static bool ParseMetadataHeader(const StringPiece& script_text, UserScript* script); ScriptReloader(UserScriptMaster* master) diff --git a/chrome/browser/extensions/user_script_master_unittest.cc b/chrome/browser/extensions/user_script_master_unittest.cc index 8ce2391..155fe47 100644 --- a/chrome/browser/extensions/user_script_master_unittest.cc +++ b/chrome/browser/extensions/user_script_master_unittest.cc @@ -140,7 +140,8 @@ TEST_F(UserScriptMasterTest, Parse1) { "alert('hoo!');\n"); UserScript script; - UserScriptMaster::ScriptReloader::ParseMetadataHeader(text, &script); + EXPECT_TRUE(UserScriptMaster::ScriptReloader::ParseMetadataHeader( + text, &script)); EXPECT_EQ(3U, script.globs().size()); EXPECT_EQ("*mail.google.com*", script.globs()[0]); EXPECT_EQ("*mail.yahoo.com*", script.globs()[1]); @@ -151,7 +152,8 @@ TEST_F(UserScriptMasterTest, Parse2) { const std::string text("default to @include *"); UserScript script; - UserScriptMaster::ScriptReloader::ParseMetadataHeader(text, &script); + EXPECT_TRUE(UserScriptMaster::ScriptReloader::ParseMetadataHeader( + text, &script)); EXPECT_EQ(1U, script.globs().size()); EXPECT_EQ("*", script.globs()[0]); } @@ -167,3 +169,46 @@ TEST_F(UserScriptMasterTest, Parse3) { EXPECT_EQ(1U, script.globs().size()); EXPECT_EQ("*foo*", script.globs()[0]); } + +TEST_F(UserScriptMasterTest, Parse4) { + const std::string text( + "// ==UserScript==\n" + "// @match http://*.mail.google.com/*\n" + "// @match \t http://mail.yahoo.com/*\n" + "// ==/UserScript==\n"); + + UserScript script; + EXPECT_TRUE(UserScriptMaster::ScriptReloader::ParseMetadataHeader( + text, &script)); + EXPECT_EQ(0U, script.globs().size()); + EXPECT_EQ(2U, script.url_patterns().size()); + EXPECT_EQ("http://*.mail.google.com/*", + script.url_patterns()[0].GetAsString()); + EXPECT_EQ("http://mail.yahoo.com/*", + script.url_patterns()[1].GetAsString()); +} + +TEST_F(UserScriptMasterTest, Parse5) { + const std::string text( + "// ==UserScript==\n" + "// @match http://*mail.google.com/*\n" + "// ==/UserScript==\n"); + + // Invalid @match value. + UserScript script; + EXPECT_FALSE(UserScriptMaster::ScriptReloader::ParseMetadataHeader( + text, &script)); +} + +TEST_F(UserScriptMasterTest, Parse6) { + const std::string text( + "// ==UserScript==\n" + "// @include http://*.mail.google.com/*\n" + "// @match \t http://mail.yahoo.com/*\n" + "// ==/UserScript==\n"); + + // Not allowed to mix @include and @value. + UserScript script; + EXPECT_FALSE(UserScriptMaster::ScriptReloader::ParseMetadataHeader( + text, &script)); +} |