diff options
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/common/extensions/url_pattern.cc | 36 | ||||
-rw-r--r-- | chrome/common/extensions/url_pattern.h | 11 | ||||
-rw-r--r-- | chrome/common/extensions/url_pattern_unittest.cc | 40 | ||||
-rw-r--r-- | chrome/renderer/user_script_slave.cc | 55 |
4 files changed, 125 insertions, 17 deletions
diff --git a/chrome/common/extensions/url_pattern.cc b/chrome/common/extensions/url_pattern.cc index 979d14b..70240b4 100644 --- a/chrome/common/extensions/url_pattern.cc +++ b/chrome/common/extensions/url_pattern.cc @@ -76,7 +76,7 @@ bool URLPattern::Parse(const std::string& pattern) { // File URLs are special because they have no host. There are other schemes // with the same structure, but we don't support them (yet). - if (scheme_ == "file") { + if (scheme_ == chrome::kFileScheme) { path_start_pos = host_start_pos; } else { size_t host_end_pos = pattern.find(kPathSeparator, host_start_pos); @@ -206,15 +206,17 @@ std::string URLPattern::GetAsString() const { std::string spec = scheme_ + chrome::kStandardSchemeSeparator; - if (match_subdomains_) { - spec += "*"; + if (scheme_ != chrome::kFileScheme) { + if (match_subdomains_) { + spec += "*"; + if (!host_.empty()) + spec += "."; + } + if (!host_.empty()) - spec += "."; + spec += host_; } - if (!host_.empty()) - spec += host_; - if (!path_.empty()) spec += path_; @@ -242,3 +244,23 @@ bool URLPattern::OverlapsWith(const URLPattern& other) const { return true; } + +std::vector<URLPattern> URLPattern::ConvertToExplicitSchemes() const { + std::vector<URLPattern> result; + + if (scheme_ != "*" && !match_all_urls_) { + result.push_back(*this); + return result; + } + + for (size_t i = 0; i < arraysize(kValidSchemes); ++i) { + if (MatchesScheme(kValidSchemes[i])) { + URLPattern temp = *this; + temp.SetScheme(kValidSchemes[i]); + temp.set_match_all_urls(false); + result.push_back(temp); + } + } + + return result; +} diff --git a/chrome/common/extensions/url_pattern.h b/chrome/common/extensions/url_pattern.h index ba4bdea..9d7f72f 100644 --- a/chrome/common/extensions/url_pattern.h +++ b/chrome/common/extensions/url_pattern.h @@ -5,6 +5,7 @@ #define CHROME_COMMON_EXTENSIONS_URL_PATTERN_H_ #include <string> +#include <vector> #include "googleurl/src/gurl.h" @@ -118,6 +119,10 @@ class URLPattern { path_escaped_ = ""; } + // Returns true if this pattern matches all urls. + bool match_all_urls() const { return match_all_urls_; } + void set_match_all_urls(bool val) { match_all_urls_ = val; } + // Initializes this instance by parsing the provided string. On failure, the // instance will have some intermediate values and is in an invalid state. bool Parse(const std::string& pattern_str); @@ -155,6 +160,12 @@ class URLPattern { // would result in the same answer. bool OverlapsWith(const URLPattern& other) const; + // Conver this URLPattern into an equivalent set of URLPatterns that don't use + // a wildcard in the scheme component. If this URLPattern doesn't use a + // wildcard scheme, then the returned set will contain one element that is + // equivalent to this instance. + std::vector<URLPattern> ConvertToExplicitSchemes() const; + private: // A bitmask containing the schemes which are considered valid for this // pattern. Parse() uses this to decide whether a pattern contains a valid diff --git a/chrome/common/extensions/url_pattern_unittest.cc b/chrome/common/extensions/url_pattern_unittest.cc index 3887602..f25052f 100644 --- a/chrome/common/extensions/url_pattern_unittest.cc +++ b/chrome/common/extensions/url_pattern_unittest.cc @@ -33,6 +33,7 @@ TEST(URLPatternTest, Match1) { EXPECT_EQ("http", pattern.scheme()); EXPECT_EQ("", pattern.host()); EXPECT_TRUE(pattern.match_subdomains()); + EXPECT_FALSE(pattern.match_all_urls()); EXPECT_EQ("/*", pattern.path()); EXPECT_TRUE(pattern.MatchesUrl(GURL("http://google.com"))); EXPECT_TRUE(pattern.MatchesUrl(GURL("http://yahoo.com"))); @@ -48,6 +49,7 @@ TEST(URLPatternTest, Match2) { EXPECT_EQ("https", pattern.scheme()); EXPECT_EQ("", pattern.host()); EXPECT_TRUE(pattern.match_subdomains()); + EXPECT_FALSE(pattern.match_all_urls()); EXPECT_EQ("/foo*", pattern.path()); EXPECT_TRUE(pattern.MatchesUrl(GURL("https://www.google.com/foo"))); EXPECT_TRUE(pattern.MatchesUrl(GURL("https://www.google.com/foobar"))); @@ -62,6 +64,7 @@ TEST(URLPatternTest, Match3) { EXPECT_EQ("http", pattern.scheme()); EXPECT_EQ("google.com", pattern.host()); EXPECT_TRUE(pattern.match_subdomains()); + EXPECT_FALSE(pattern.match_all_urls()); EXPECT_EQ("/foo*bar", pattern.path()); EXPECT_TRUE(pattern.MatchesUrl(GURL("http://google.com/foobar"))); EXPECT_TRUE(pattern.MatchesUrl(GURL("http://www.google.com/foo?bar"))); @@ -77,6 +80,7 @@ TEST(URLPatternTest, Match5) { EXPECT_EQ("file", pattern.scheme()); EXPECT_EQ("", pattern.host()); EXPECT_FALSE(pattern.match_subdomains()); + EXPECT_FALSE(pattern.match_all_urls()); EXPECT_EQ("/foo?bar\\*baz", pattern.path()); EXPECT_TRUE(pattern.MatchesUrl(GURL("file:///foo?bar\\hellobaz"))); EXPECT_FALSE(pattern.MatchesUrl(GURL("file:///fooXbar\\hellobaz"))); @@ -89,6 +93,7 @@ TEST(URLPatternTest, Match6) { EXPECT_EQ("http", pattern.scheme()); EXPECT_EQ("127.0.0.1", pattern.host()); EXPECT_FALSE(pattern.match_subdomains()); + EXPECT_FALSE(pattern.match_all_urls()); EXPECT_EQ("/*", pattern.path()); EXPECT_TRUE(pattern.MatchesUrl(GURL("http://127.0.0.1"))); } @@ -100,6 +105,7 @@ TEST(URLPatternTest, Match7) { EXPECT_EQ("http", pattern.scheme()); EXPECT_EQ("0.0.1", pattern.host()); EXPECT_TRUE(pattern.match_subdomains()); + EXPECT_FALSE(pattern.match_all_urls()); EXPECT_EQ("/*", pattern.path()); // Subdomain matching is never done if the argument has an IP address host. EXPECT_FALSE(pattern.MatchesUrl(GURL("http://127.0.0.1"))); @@ -114,6 +120,7 @@ TEST(URLPatternTest, Match8) { EXPECT_EQ("http", pattern.scheme()); EXPECT_EQ("xn--gkd", pattern.host()); EXPECT_TRUE(pattern.match_subdomains()); + EXPECT_FALSE(pattern.match_all_urls()); EXPECT_EQ("/a%C2%81%E1*", pattern.path()); EXPECT_TRUE(pattern.MatchesUrl( GURL("http://abc.\xe1\x80\xbf/a\xc2\x81\xe1xyz"))); @@ -128,6 +135,7 @@ TEST(URLPatternTest, Match9) { EXPECT_EQ("chrome", pattern.scheme()); EXPECT_EQ("favicon", pattern.host()); EXPECT_FALSE(pattern.match_subdomains()); + EXPECT_FALSE(pattern.match_all_urls()); EXPECT_EQ("/*", pattern.path()); EXPECT_TRUE(pattern.MatchesUrl(GURL("chrome://favicon/http://google.com"))); EXPECT_TRUE(pattern.MatchesUrl(GURL("chrome://favicon/https://google.com"))); @@ -144,6 +152,7 @@ TEST(URLPatternTest, Match10) { EXPECT_FALSE(pattern.MatchesScheme("file")); EXPECT_FALSE(pattern.MatchesScheme("ftp")); EXPECT_TRUE(pattern.match_subdomains()); + EXPECT_FALSE(pattern.match_all_urls()); EXPECT_EQ("/*", pattern.path()); EXPECT_TRUE(pattern.MatchesUrl(GURL("http://127.0.0.1"))); EXPECT_FALSE(pattern.MatchesUrl(GURL("chrome://favicon/http://google.com"))); @@ -159,6 +168,7 @@ TEST(URLPatternTest, Match11) { EXPECT_TRUE(pattern.MatchesScheme("https")); EXPECT_TRUE(pattern.MatchesScheme("file")); EXPECT_TRUE(pattern.match_subdomains()); + EXPECT_TRUE(pattern.match_all_urls()); EXPECT_EQ("/*", pattern.path()); EXPECT_TRUE(pattern.MatchesUrl(GURL("chrome://favicon/http://google.com"))); EXPECT_TRUE(pattern.MatchesUrl(GURL("http://127.0.0.1"))); @@ -203,3 +213,33 @@ TEST(URLPatternTest, OverlapsWith) { TestPatternOverlap(pattern7, pattern8, false); TestPatternOverlap(pattern7, pattern10, true); } + +TEST(URLPatternTest, ConvertToExplicitSchemes) { + std::vector<URLPattern> all_urls(URLPattern( + URLPattern::SCHEMES_ALL, + "<all_urls>").ConvertToExplicitSchemes()); + + std::vector<URLPattern> all_schemes(URLPattern( + URLPattern::SCHEMES_ALL, + "*://google.com/foo").ConvertToExplicitSchemes()); + + std::vector<URLPattern> monkey(URLPattern( + URLPattern::SCHEME_HTTP | URLPattern::SCHEME_HTTPS | + URLPattern::SCHEME_FTP, + "http://google.com/monkey").ConvertToExplicitSchemes()); + + ASSERT_EQ(5u, all_urls.size()); + ASSERT_EQ(2u, all_schemes.size()); + ASSERT_EQ(1u, monkey.size()); + + EXPECT_EQ("http://*/*", all_urls[0].GetAsString()); + EXPECT_EQ("https://*/*", all_urls[1].GetAsString()); + EXPECT_EQ("file:///*", all_urls[2].GetAsString()); + EXPECT_EQ("ftp://*/*", all_urls[3].GetAsString()); + EXPECT_EQ("chrome://*/*", all_urls[4].GetAsString()); + + EXPECT_EQ("http://google.com/foo", all_schemes[0].GetAsString()); + EXPECT_EQ("https://google.com/foo", all_schemes[1].GetAsString()); + + EXPECT_EQ("http://google.com/monkey", monkey[0].GetAsString()); +} diff --git a/chrome/renderer/user_script_slave.cc b/chrome/renderer/user_script_slave.cc index e064093..7a2f521 100644 --- a/chrome/renderer/user_script_slave.cc +++ b/chrome/renderer/user_script_slave.cc @@ -14,15 +14,20 @@ #include "base/string_util.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/extension.h" +#include "chrome/common/url_constants.h" #include "chrome/renderer/extension_groups.h" #include "chrome/renderer/render_thread.h" #include "googleurl/src/gurl.h" #include "third_party/WebKit/WebKit/chromium/public/WebFrame.h" +#include "third_party/WebKit/WebKit/chromium/public/WebVector.h" +#include "third_party/WebKit/WebKit/chromium/public/WebView.h" #include "grit/renderer_resources.h" using WebKit::WebFrame; using WebKit::WebString; +using WebKit::WebVector; +using WebKit::WebView; // These two strings are injected before and after the Greasemonkey API and // user script to wrap it in an anonymous scope. @@ -128,6 +133,42 @@ bool UserScriptSlave::UpdateScripts(base::SharedMemoryHandle shared_memory) { } } + // Push user styles down into WebCore + WebView::removeAllUserContent(); + for (size_t i = 0; i < scripts_.size(); ++i) { + UserScript* script = scripts_[i]; + if (script->css_scripts().empty()) + continue; + + WebVector<WebString> patterns; + std::vector<WebString> temp_patterns; + for (size_t k = 0; k < script->url_patterns().size(); ++k) { + std::vector<URLPattern> explicit_patterns = + script->url_patterns()[k].ConvertToExplicitSchemes(); + for (size_t m = 0; m < explicit_patterns.size(); ++m) { + // Only include file schemes if the user has opted into that. + if (!explicit_patterns[m].MatchesScheme(chrome::kFileScheme) || + script->allow_file_access()) { + temp_patterns.push_back(WebString::fromUTF8( + explicit_patterns[m].GetAsString())); + } + } + } + patterns.assign(temp_patterns); + + for (size_t j = 0; j < script->css_scripts().size(); ++j) { + const UserScript::File& file = scripts_[i]->css_scripts()[j]; + std::string content = file.GetContent().as_string(); + + WebView::addUserStyleSheet( + WebString::fromUTF8(content), + patterns, + script->match_all_frames() ? + WebView::UserContentInjectInAllFrames : + WebView::UserContentInjectInTopFrameOnly); + } + } + return true; } @@ -174,17 +215,11 @@ void UserScriptSlave::InjectScripts(WebFrame* frame, if (frame_url.SchemeIsFile() && !script->allow_file_access()) continue; // This script isn't allowed to run on file URLs. - // CSS files are always injected on document start before js scripts. - if (location == UserScript::DOCUMENT_START) { + // We rely on WebCore for CSS injection, but it's still useful to know how + // many css files there are. + if (location == UserScript::DOCUMENT_START) num_css += script->css_scripts().size(); - for (size_t j = 0; j < script->css_scripts().size(); ++j) { - PerfTimer insert_timer; - UserScript::File& file = script->css_scripts()[j]; - frame->insertStyleText( - WebString::fromUTF8(file.GetContent().as_string()), WebString()); - UMA_HISTOGRAM_TIMES("Extensions.InjectCssTime", insert_timer.Elapsed()); - } - } + if (script->run_location() == location) { num_scripts += script->js_scripts().size(); for (size_t j = 0; j < script->js_scripts().size(); ++j) { |