summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/extensions/user_script_master.cc51
-rw-r--r--chrome/browser/extensions/user_script_master.h5
-rw-r--r--chrome/browser/extensions/user_script_master_unittest.cc49
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));
+}