123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245 |
- // Copyright 2019 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "components/url_rewrite/common/url_loader_throttle.h"
- #include <string>
- #include <utility>
- #include "base/strings/string_piece.h"
- #include "base/test/bind.h"
- #include "base/test/task_environment.h"
- #include "services/network/public/cpp/resource_request.h"
- #include "testing/gtest/include/gtest/gtest.h"
- #include "third_party/blink/public/common/loader/url_loader_throttle.h"
- namespace url_rewrite {
- namespace {
- constexpr char kMixedCaseCorsExemptHeader[] = "CoRs-ExEmPt";
- constexpr char kUpperCaseCorsExemptHeader[] = "CORS-EXEMPT";
- constexpr char kMixedCaseCorsExemptHeader2[] = "Another-CoRs-ExEmPt-2";
- constexpr char kUpperCaseCorsExemptHeader2[] = "ANOTHER-CORS-EXEMPT-2";
- constexpr char kRequiresCorsHeader[] = "requires-cors";
- } // namespace
- class URLLoaderThrottleTest : public testing::Test {
- public:
- URLLoaderThrottleTest()
- : task_environment_(base::test::TaskEnvironment::MainThreadType::IO) {}
- ~URLLoaderThrottleTest() override = default;
- URLLoaderThrottle::IsHeaderCorsExemptCallback CreateCorsExemptHeadersCallback(
- std::vector<std::string> cors_exempt_headers) {
- return base::BindLambdaForTesting(
- [cors_exempt_headers](base::StringPiece header) {
- LOG(INFO) << "HEADER: " << header;
- for (const auto& exempt_header : cors_exempt_headers) {
- if (base::EqualsCaseInsensitiveASCII(header, exempt_header)) {
- return true;
- }
- }
- return false;
- });
- }
- protected:
- base::test::SingleThreadTaskEnvironment task_environment_;
- };
- // Tests rules are properly applied when wildcard-filtering is used on hosts.
- TEST_F(URLLoaderThrottleTest, WildcardHosts) {
- mojom::UrlRequestRewriteAddHeadersPtr add_headers =
- mojom::UrlRequestRewriteAddHeaders::New();
- add_headers->headers.push_back(mojom::UrlHeader::New("Header", "Value"));
- mojom::UrlRequestActionPtr rewrite =
- mojom::UrlRequestAction::NewAddHeaders(std::move(add_headers));
- std::vector<mojom::UrlRequestActionPtr> actions;
- actions.push_back(std::move(rewrite));
- mojom::UrlRequestRulePtr rule = mojom::UrlRequestRule::New();
- rule->hosts_filter = absl::optional<std::vector<std::string>>({"*.test.net"});
- rule->actions = std::move(actions);
- mojom::UrlRequestRewriteRulesPtr rules = mojom::UrlRequestRewriteRules::New();
- rules->rules.push_back(std::move(rule));
- URLLoaderThrottle throttle(
- base::MakeRefCounted<UrlRequestRewriteRules>(std::move(rules)),
- CreateCorsExemptHeadersCallback({}));
- bool defer = false;
- network::ResourceRequest request1;
- request1.url = GURL("http://test.net");
- throttle.WillStartRequest(&request1, &defer);
- EXPECT_TRUE(request1.headers.HasHeader("Header"));
- network::ResourceRequest request2;
- request2.url = GURL("http://subdomain.test.net");
- throttle.WillStartRequest(&request2, &defer);
- EXPECT_TRUE(request2.headers.HasHeader("Header"));
- network::ResourceRequest request3;
- request3.url = GURL("http://domaintest.net");
- throttle.WillStartRequest(&request3, &defer);
- EXPECT_FALSE(request3.headers.HasHeader("Header"));
- network::ResourceRequest request4;
- request4.url = GURL("http://otherdomain.net");
- throttle.WillStartRequest(&request4, &defer);
- EXPECT_FALSE(request4.headers.HasHeader("Header"));
- }
- // Verifies that injected headers are correctly exempted from CORS checks if
- // their names are registered as CORS exempt.
- TEST_F(URLLoaderThrottleTest, CorsAwareHeaders) {
- mojom::UrlRequestRewriteAddHeadersPtr add_headers =
- mojom::UrlRequestRewriteAddHeaders::New();
- add_headers->headers.push_back(
- mojom::UrlHeader::New(kRequiresCorsHeader, "Value"));
- // Inject the uppercased form for CORS exempt header #1, and the mixed case
- // form of header #2.
- add_headers->headers.push_back(
- mojom::UrlHeader::New(kUpperCaseCorsExemptHeader, "Value"));
- add_headers->headers.push_back(
- mojom::UrlHeader::New(kMixedCaseCorsExemptHeader2, "Value"));
- mojom::UrlRequestActionPtr rewrite =
- mojom::UrlRequestAction::NewAddHeaders(std::move(add_headers));
- std::vector<mojom::UrlRequestActionPtr> actions;
- actions.push_back(std::move(rewrite));
- mojom::UrlRequestRulePtr rule = mojom::UrlRequestRule::New();
- rule->hosts_filter = absl::optional<std::vector<std::string>>({"*.test.net"});
- rule->actions = std::move(actions);
- mojom::UrlRequestRewriteRulesPtr rules = mojom::UrlRequestRewriteRules::New();
- rules->rules.push_back(std::move(rule));
- // Use the mixed case form for CORS exempt header #1, and the uppercased form
- // of header #2.
- URLLoaderThrottle throttle(
- base::MakeRefCounted<UrlRequestRewriteRules>(std::move(rules)),
- CreateCorsExemptHeadersCallback(
- {kMixedCaseCorsExemptHeader, kUpperCaseCorsExemptHeader2}));
- network::ResourceRequest request;
- request.url = GURL("http://test.net");
- bool defer = false;
- throttle.WillStartRequest(&request, &defer);
- EXPECT_FALSE(defer);
- // Verify that the cors-exempt and cors-required headers were partitioned into
- // the "cors_exempt_headers" and "headers" arrays, respectively.
- EXPECT_TRUE(
- request.cors_exempt_headers.HasHeader(kUpperCaseCorsExemptHeader));
- EXPECT_TRUE(
- request.cors_exempt_headers.HasHeader(kMixedCaseCorsExemptHeader2));
- EXPECT_TRUE(request.headers.HasHeader(kRequiresCorsHeader));
- // Verify that the headers were not also placed in the other array.
- EXPECT_FALSE(request.cors_exempt_headers.HasHeader(kRequiresCorsHeader));
- EXPECT_FALSE(request.headers.HasHeader(kUpperCaseCorsExemptHeader));
- EXPECT_FALSE(request.headers.HasHeader(kMixedCaseCorsExemptHeader2));
- }
- // Tests URL replacement rules that replace to a data URL do not append query or
- // ref from the original URL.
- TEST_F(URLLoaderThrottleTest, DataReplacementUrl) {
- const char kCssDataURI[] = "data:text/css,";
- mojom::UrlRequestRewriteReplaceUrlPtr replace_url =
- mojom::UrlRequestRewriteReplaceUrl::New();
- replace_url->url_ends_with = ".css";
- replace_url->new_url = GURL(kCssDataURI);
- mojom::UrlRequestActionPtr rewrite =
- mojom::UrlRequestAction::NewReplaceUrl(std::move(replace_url));
- std::vector<mojom::UrlRequestActionPtr> actions;
- actions.push_back(std::move(rewrite));
- mojom::UrlRequestRulePtr rule = mojom::UrlRequestRule::New();
- rule->hosts_filter = absl::optional<std::vector<std::string>>({"*.test.net"});
- rule->actions = std::move(actions);
- mojom::UrlRequestRewriteRulesPtr rules = mojom::UrlRequestRewriteRules::New();
- rules->rules.push_back(std::move(rule));
- URLLoaderThrottle throttle(
- base::MakeRefCounted<UrlRequestRewriteRules>(std::move(rules)),
- CreateCorsExemptHeadersCallback({}));
- bool defer = false;
- network::ResourceRequest request;
- request.url = GURL("http://test.net/style.css?query#ref");
- throttle.WillStartRequest(&request, &defer);
- EXPECT_EQ(request.url, base::StringPiece(kCssDataURI));
- }
- class TestThrottleDelegate : public blink::URLLoaderThrottle::Delegate {
- public:
- TestThrottleDelegate() = default;
- ~TestThrottleDelegate() override = default;
- bool canceled() const { return canceled_; }
- base::StringPiece cancel_reason() const { return cancel_reason_; }
- void Reset() {
- canceled_ = false;
- cancel_reason_.clear();
- }
- // URLLoaderThrottle::Delegate implementation.
- void CancelWithError(int error_code,
- base::StringPiece custom_reason) override {
- canceled_ = true;
- cancel_reason_ = std::string(custom_reason);
- }
- void Resume() override {}
- private:
- bool canceled_ = false;
- std::string cancel_reason_;
- };
- // Tests that resource loads can be allowed or blocked based on the
- // UrlRequestAction policy.
- TEST_F(URLLoaderThrottleTest, AllowAndDeny) {
- mojom::UrlRequestRewriteRulesPtr rules = mojom::UrlRequestRewriteRules::New();
- {
- mojom::UrlRequestRulePtr rule = mojom::UrlRequestRule::New();
- rule->hosts_filter = absl::optional<std::vector<std::string>>({"test.net"});
- rule->actions.push_back(mojom::UrlRequestAction::NewPolicy(
- mojom::UrlRequestAccessPolicy::kAllow));
- rules->rules.push_back(std::move(rule));
- }
- {
- mojom::UrlRequestRulePtr rule = mojom::UrlRequestRule::New();
- rule->actions.push_back(mojom::UrlRequestAction::NewPolicy(
- mojom::UrlRequestAccessPolicy::kDeny));
- rules->rules.push_back(std::move(rule));
- }
- URLLoaderThrottle throttle(
- base::MakeRefCounted<UrlRequestRewriteRules>(std::move(rules)),
- CreateCorsExemptHeadersCallback({}));
- bool defer = false;
- TestThrottleDelegate delegate;
- throttle.set_delegate(&delegate);
- network::ResourceRequest request1;
- request1.url = GURL("http://test.net");
- throttle.WillStartRequest(&request1, &defer);
- EXPECT_FALSE(delegate.canceled());
- delegate.Reset();
- network::ResourceRequest request2;
- request2.url = GURL("http://blocked.net");
- throttle.WillStartRequest(&request2, &defer);
- EXPECT_TRUE(delegate.canceled());
- EXPECT_EQ(delegate.cancel_reason(),
- "Resource load blocked by embedder policy.");
- }
- } // namespace url_rewrite
|