blob: fab8ad1662bde9e9eeaf1274813984236ff65acc [file] [log] [blame]
// 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