| // Copyright 2013 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <stddef.h> |
| |
| #include "base/files/file_path.h" |
| #include "base/pickle.h" |
| #include "extensions/common/mojom/host_id.mojom.h" |
| #include "extensions/common/mojom/run_location.mojom-shared.h" |
| #include "extensions/common/user_script.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "url/gurl.h" |
| |
| namespace extensions { |
| |
| static const int kAllSchemes = |
| URLPattern::SCHEME_HTTP | |
| URLPattern::SCHEME_HTTPS | |
| URLPattern::SCHEME_FILE | |
| URLPattern::SCHEME_FTP | |
| URLPattern::SCHEME_CHROMEUI; |
| |
| inline constexpr char kStaticContentScript[] = "_mc_1"; |
| inline constexpr char kDynamicContentScript[] = "_dc_1"; |
| inline constexpr char kDynamicUserScript[] = "_du_1"; |
| |
| class UserScriptMatchesTest : public testing::Test, |
| public testing::WithParamInterface<std::string> { |
| public: |
| UserScriptMatchesTest() { |
| // Script source will be determined by the id prefix. |
| script_.set_id(GetParam()); |
| } |
| UserScriptMatchesTest(const UserScriptMatchesTest&) = delete; |
| const UserScriptMatchesTest& operator=(const UserScriptMatchesTest&) = delete; |
| ~UserScriptMatchesTest() override = default; |
| |
| UserScript* script() { return &script_; } |
| |
| private: |
| UserScript script_; |
| }; |
| |
| INSTANTIATE_TEST_SUITE_P(All, |
| UserScriptMatchesTest, |
| testing::Values(kStaticContentScript, |
| kDynamicContentScript, |
| kDynamicUserScript)); |
| |
| TEST_P(UserScriptMatchesTest, Glob_HostString) { |
| script()->add_glob("*mail.google.com*"); |
| script()->add_glob("*mail.yahoo.com*"); |
| script()->add_glob("*mail.msn.com*"); |
| |
| EXPECT_TRUE(script()->MatchesURL(GURL("http://mail.google.com"))); |
| EXPECT_TRUE(script()->MatchesURL(GURL("http://mail.google.com/foo"))); |
| EXPECT_TRUE(script()->MatchesURL(GURL("https://mail.google.com/foo"))); |
| EXPECT_TRUE(script()->MatchesURL(GURL("ftp://mail.google.com/foo"))); |
| EXPECT_TRUE(script()->MatchesURL(GURL("http://woo.mail.google.com/foo"))); |
| EXPECT_TRUE(script()->MatchesURL(GURL("http://mail.yahoo.com/bar"))); |
| EXPECT_TRUE(script()->MatchesURL(GURL("http://mail.msn.com/baz"))); |
| EXPECT_FALSE(script()->MatchesURL(GURL("http://www.hotmail.com"))); |
| |
| script()->add_exclude_glob("*foo*"); |
| EXPECT_TRUE(script()->MatchesURL(GURL("http://mail.google.com"))); |
| EXPECT_FALSE(script()->MatchesURL(GURL("http://mail.google.com/foo"))); |
| } |
| |
| TEST_P(UserScriptMatchesTest, Glob_TrailingSlash) { |
| script()->add_glob("*mail.google.com/"); |
| |
| // GURL normalizes the URL to have a trailing "/" |
| EXPECT_TRUE(script()->MatchesURL(GURL("http://mail.google.com"))); |
| EXPECT_TRUE(script()->MatchesURL(GURL("http://mail.google.com/"))); |
| EXPECT_FALSE(script()->MatchesURL(GURL("http://mail.google.com/foo"))); |
| } |
| |
| TEST_P(UserScriptMatchesTest, Glob_TrailingSlashStar) { |
| script()->add_glob("http://mail.google.com/*"); |
| |
| // GURL normalizes the URL to have a trailing "/" |
| EXPECT_TRUE(script()->MatchesURL(GURL("http://mail.google.com"))); |
| EXPECT_TRUE(script()->MatchesURL(GURL("http://mail.google.com/foo"))); |
| EXPECT_FALSE(script()->MatchesURL(GURL("https://mail.google.com/foo"))); |
| } |
| |
| TEST_P(UserScriptMatchesTest, Glob_Star) { |
| script()->add_glob("*"); |
| |
| EXPECT_TRUE(script()->MatchesURL(GURL("http://foo.com/bar"))); |
| EXPECT_TRUE(script()->MatchesURL(GURL("http://hot.com/dog"))); |
| EXPECT_TRUE(script()->MatchesURL(GURL("https://hot.com/dog"))); |
| EXPECT_TRUE(script()->MatchesURL(GURL("file:///foo/bar"))); |
| EXPECT_TRUE(script()->MatchesURL(GURL("file://localhost/foo/bar"))); |
| } |
| |
| TEST_P(UserScriptMatchesTest, Glob_StringAnywhere) { |
| script()->add_glob("*foo*"); |
| |
| EXPECT_TRUE(script()->MatchesURL(GURL("http://foo.com/bar"))); |
| EXPECT_TRUE(script()->MatchesURL(GURL("http://baz.org/foo/bar"))); |
| EXPECT_FALSE(script()->MatchesURL(GURL("http://baz.org"))); |
| } |
| |
| TEST_P(UserScriptMatchesTest, UrlPattern) { |
| URLPattern pattern(kAllSchemes); |
| ASSERT_EQ(URLPattern::ParseResult::kSuccess, pattern.Parse("http://*/foo*")); |
| |
| script()->add_url_pattern(pattern); |
| |
| EXPECT_TRUE(script()->MatchesURL(GURL("http://monkey.com/foobar"))); |
| EXPECT_FALSE(script()->MatchesURL(GURL("http://monkey.com/hotdog"))); |
| |
| // NOTE: URLPattern is tested more extensively in url_pattern_unittest.cc. |
| } |
| |
| TEST_P(UserScriptMatchesTest, ExcludeUrlPattern) { |
| URLPattern pattern(kAllSchemes); |
| ASSERT_EQ(URLPattern::ParseResult::kSuccess, |
| pattern.Parse("http://*.nytimes.com/*")); |
| script()->add_url_pattern(pattern); |
| |
| URLPattern exclude(kAllSchemes); |
| ASSERT_EQ(URLPattern::ParseResult::kSuccess, |
| exclude.Parse("*://*/*business*")); |
| script()->add_exclude_url_pattern(exclude); |
| |
| EXPECT_TRUE(script()->MatchesURL(GURL("http://www.nytimes.com/health"))); |
| EXPECT_FALSE(script()->MatchesURL(GURL("http://www.nytimes.com/business"))); |
| EXPECT_TRUE(script()->MatchesURL(GURL("http://business.nytimes.com"))); |
| } |
| |
| TEST_P(UserScriptMatchesTest, ExcludeUrlPatternWithTrailingDot) { |
| URLPattern pattern(kAllSchemes); |
| ASSERT_EQ(URLPattern::ParseResult::kSuccess, pattern.Parse("*://*/*")); |
| script()->add_url_pattern(pattern); |
| |
| URLPattern exclude(kAllSchemes); |
| ASSERT_EQ(URLPattern::ParseResult::kSuccess, |
| exclude.Parse("*://mail.nytimes.com/*")); |
| script()->add_exclude_url_pattern(exclude); |
| |
| EXPECT_TRUE(script()->MatchesURL(GURL("http://www.nytimes.com/health"))); |
| EXPECT_TRUE(script()->MatchesURL(GURL("http://business.nytimes.com"))); |
| EXPECT_FALSE(script()->MatchesURL(GURL("http://mail.nytimes.com"))); |
| EXPECT_FALSE(script()->MatchesURL(GURL("http://mail.nytimes.com."))); |
| EXPECT_FALSE(script()->MatchesURL(GURL("http://mail.nytimes.com/login"))); |
| EXPECT_FALSE(script()->MatchesURL(GURL("http://mail.nytimes.com./login"))); |
| } |
| |
| TEST_P(UserScriptMatchesTest, UrlPatternAndIncludeGlobs) { |
| URLPattern pattern(kAllSchemes); |
| ASSERT_EQ(URLPattern::ParseResult::kSuccess, |
| pattern.Parse("http://*.nytimes.com/*")); |
| script()->add_url_pattern(pattern); |
| script()->add_glob("*nytimes.com/???s/*"); |
| |
| // Match, because url matches both the url patterns and include globs. |
| EXPECT_TRUE(script()->MatchesURL(GURL("http://www.nytimes.com/arts/1.html"))); |
| EXPECT_TRUE(script()->MatchesURL(GURL("http://www.nytimes.com/jobs/1.html"))); |
| |
| if (script()->GetSource() == UserScript::Source::kDynamicUserScript) { |
| // Match, because user scripts only need to match url patterns OR include |
| // globs. |
| EXPECT_TRUE( |
| script()->MatchesURL(GURL("http://www.nytimes.com/sports/1.html"))); |
| } else { |
| // No match, because other scripts need to match url patterns AND include |
| // globs. |
| EXPECT_FALSE( |
| script()->MatchesURL(GURL("http://www.nytimes.com/sports/1.html"))); |
| } |
| } |
| |
| TEST_P(UserScriptMatchesTest, UrlPatternAndExcludeGlobs) { |
| URLPattern pattern(kAllSchemes); |
| ASSERT_EQ(URLPattern::ParseResult::kSuccess, |
| pattern.Parse("http://*.nytimes.com/*")); |
| script()->add_url_pattern(pattern); |
| |
| script()->add_exclude_glob("*science*"); |
| |
| EXPECT_TRUE(script()->MatchesURL(GURL("http://www.nytimes.com"))); |
| EXPECT_FALSE(script()->MatchesURL(GURL("http://science.nytimes.com"))); |
| EXPECT_FALSE(script()->MatchesURL(GURL("http://www.nytimes.com/science"))); |
| } |
| |
| TEST_P(UserScriptMatchesTest, UrlPatternGlobInteraction) { |
| URLPattern pattern(kAllSchemes); |
| ASSERT_EQ(URLPattern::ParseResult::kSuccess, |
| pattern.Parse("http://www.google.com/*")); |
| script()->add_url_pattern(pattern); |
| script()->add_glob("*bar*"); |
| |
| if (script()->GetSource() == UserScript::Source::kDynamicUserScript) { |
| // Match, because it matches the url pattern. User scripts only need to |
| // match url patterns OR include globs. |
| EXPECT_TRUE(script()->MatchesURL(GURL("http://www.google.com/foo"))); |
| |
| } else { |
| // No match, because it doesn't match the glob. Other scripts need to match |
| // url patterns AND include globs. |
| EXPECT_FALSE(script()->MatchesURL(GURL("http://www.google.com/foo"))); |
| } |
| |
| script()->add_exclude_glob("*baz*"); |
| |
| // No match, because it matches the exclude glob. |
| EXPECT_FALSE(script()->MatchesURL(GURL("http://www.google.com/baz"))); |
| |
| // Match, because it matches the glob, doesn't match the exclude glob. |
| EXPECT_TRUE(script()->MatchesURL(GURL("http://www.google.com/bar"))); |
| |
| // Try with just a single exclude glob. |
| script()->clear_globs(); |
| EXPECT_TRUE(script()->MatchesURL(GURL("http://www.google.com/foo"))); |
| |
| // Try with no globs or exclude globs. |
| script()->clear_exclude_globs(); |
| EXPECT_TRUE(script()->MatchesURL(GURL("http://www.google.com/foo"))); |
| } |
| |
| TEST(ExtensionUserScriptTest, Pickle) { |
| URLPattern pattern1(kAllSchemes); |
| URLPattern pattern2(kAllSchemes); |
| URLPattern exclude1(kAllSchemes); |
| URLPattern exclude2(kAllSchemes); |
| ASSERT_EQ(URLPattern::ParseResult::kSuccess, pattern1.Parse("http://*/foo*")); |
| ASSERT_EQ(URLPattern::ParseResult::kSuccess, |
| pattern2.Parse("http://bar/baz*")); |
| ASSERT_EQ(URLPattern::ParseResult::kSuccess, exclude1.Parse("*://*/*bar")); |
| ASSERT_EQ(URLPattern::ParseResult::kSuccess, exclude2.Parse("https://*/*")); |
| |
| UserScript script1; |
| script1.js_scripts().push_back(UserScript::Content::CreateFile( |
| base::FilePath(FILE_PATH_LITERAL("c:\\foo\\")), |
| base::FilePath(FILE_PATH_LITERAL("foo.user.js")), |
| GURL("chrome-extension://abc/foo.user.js"))); |
| script1.css_scripts().push_back(UserScript::Content::CreateFile( |
| base::FilePath(FILE_PATH_LITERAL("c:\\foo\\")), |
| base::FilePath(FILE_PATH_LITERAL("foo.user.css")), |
| GURL("chrome-extension://abc/foo.user.css"))); |
| script1.css_scripts().push_back(UserScript::Content::CreateFile( |
| base::FilePath(FILE_PATH_LITERAL("c:\\foo\\")), |
| base::FilePath(FILE_PATH_LITERAL("foo2.user.css")), |
| GURL("chrome-extension://abc/foo2.user.css"))); |
| script1.set_run_location(mojom::RunLocation::kDocumentStart); |
| |
| script1.add_url_pattern(pattern1); |
| script1.add_url_pattern(pattern2); |
| script1.add_exclude_url_pattern(exclude1); |
| script1.add_exclude_url_pattern(exclude2); |
| |
| const std::string kId = "_mc_12"; |
| script1.set_id(kId); |
| const std::string kExtensionId = "foo"; |
| mojom::HostID id(mojom::HostID::HostType::kExtensions, kExtensionId); |
| script1.set_host_id(id); |
| |
| base::Pickle pickle; |
| script1.Pickle(&pickle); |
| |
| base::PickleIterator iter(pickle); |
| UserScript script2; |
| script2.Unpickle(pickle, &iter); |
| |
| EXPECT_EQ(1U, script2.js_scripts().size()); |
| EXPECT_EQ(script1.js_scripts()[0]->url(), script2.js_scripts()[0]->url()); |
| |
| EXPECT_EQ(2U, script2.css_scripts().size()); |
| for (size_t i = 0; i < script2.js_scripts().size(); ++i) { |
| EXPECT_EQ(script1.css_scripts()[i]->url(), script2.css_scripts()[i]->url()); |
| } |
| |
| ASSERT_EQ(script1.globs().size(), script2.globs().size()); |
| for (size_t i = 0; i < script1.globs().size(); ++i) { |
| EXPECT_EQ(script1.globs()[i], script2.globs()[i]); |
| } |
| |
| ASSERT_EQ(script1.url_patterns(), script2.url_patterns()); |
| ASSERT_EQ(script1.exclude_url_patterns(), script2.exclude_url_patterns()); |
| |
| EXPECT_EQ(kExtensionId, script2.extension_id()); |
| EXPECT_EQ(kId, script2.id()); |
| } |
| |
| TEST(ExtensionUserScriptTest, Defaults) { |
| UserScript script; |
| ASSERT_EQ(mojom::RunLocation::kDocumentIdle, script.run_location()); |
| } |
| |
| // Verifies the correct source is returned for a script id with source prefix. |
| TEST(ExtensionUserScriptTest, GetSourceForScriptID) { |
| std::string manifest_script_id = "_mc_manifest_script"; |
| std::string content_script_id = "_dc_content_script"; |
| std::string user_script_id = "_du_user_script"; |
| |
| EXPECT_EQ(UserScript::GetSourceForScriptID(manifest_script_id), |
| UserScript::Source::kStaticContentScript); |
| EXPECT_EQ(UserScript::GetSourceForScriptID(content_script_id), |
| UserScript::Source::kDynamicContentScript); |
| EXPECT_EQ(UserScript::GetSourceForScriptID(user_script_id), |
| UserScript::Source::kDynamicUserScript); |
| } |
| |
| } // namespace extensions |