123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476 |
- // Copyright 2017 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 "net/url_request/redirect_info.h"
- #include "base/memory/ref_counted.h"
- #include "base/strings/string_number_conversions.h"
- #include "net/http/http_response_headers.h"
- #include "net/http/http_util.h"
- #include "net/url_request/redirect_util.h"
- #include "net/url_request/referrer_policy.h"
- #include "testing/gtest/include/gtest/gtest.h"
- #include "url/gurl.h"
- namespace net {
- namespace {
- TEST(RedirectInfoTest, MethodForRedirect) {
- struct TestCase {
- const char* original_method;
- int http_status_code;
- const char* expected_new_method;
- };
- const TestCase kTests[] = {
- {"GET", 301, "GET"}, {"GET", 302, "GET"}, {"GET", 303, "GET"},
- {"GET", 307, "GET"}, {"GET", 308, "GET"}, {"HEAD", 301, "HEAD"},
- {"HEAD", 302, "HEAD"}, {"HEAD", 303, "HEAD"}, {"HEAD", 307, "HEAD"},
- {"HEAD", 308, "HEAD"}, {"POST", 301, "GET"}, {"POST", 302, "GET"},
- {"POST", 303, "GET"}, {"POST", 307, "POST"}, {"POST", 308, "POST"},
- {"PUT", 301, "PUT"}, {"PUT", 302, "PUT"}, {"PUT", 303, "GET"},
- {"PUT", 307, "PUT"}, {"PUT", 308, "PUT"},
- };
- const GURL kOriginalUrl = GURL("https://foo.test/original");
- const SiteForCookies kOriginalSiteForCookies =
- SiteForCookies::FromUrl(GURL("https://foo.test/"));
- const url::Origin kOriginalTopFrameOrigin = url::Origin::Create(kOriginalUrl);
- const RedirectInfo::FirstPartyURLPolicy kOriginalFirstPartyUrlPolicy =
- RedirectInfo::FirstPartyURLPolicy::NEVER_CHANGE_URL;
- const ReferrerPolicy kOriginalReferrerPolicy = ReferrerPolicy::NEVER_CLEAR;
- const std::string kOriginalReferrer = "";
- const GURL kNewLocation = GURL("https://foo.test/redirected");
- const bool kInsecureSchemeWasUpgraded = false;
- const bool kCopyFragment = true;
- for (const auto& test : kTests) {
- SCOPED_TRACE(::testing::Message()
- << "original_method: " << test.original_method
- << " http_status_code: " << test.http_status_code);
- RedirectInfo redirect_info = RedirectInfo::ComputeRedirectInfo(
- test.original_method, kOriginalUrl, kOriginalSiteForCookies,
- kOriginalFirstPartyUrlPolicy, kOriginalReferrerPolicy,
- kOriginalReferrer, test.http_status_code, kNewLocation,
- absl::nullopt /* referrer_policy_header */, kInsecureSchemeWasUpgraded,
- kCopyFragment);
- EXPECT_EQ(test.expected_new_method, redirect_info.new_method);
- EXPECT_EQ(test.http_status_code, redirect_info.status_code);
- EXPECT_EQ(kNewLocation, redirect_info.new_url);
- }
- }
- TEST(RedirectInfoTest, CopyFragment) {
- struct TestCase {
- bool copy_fragment;
- const char* original_url;
- const char* new_location;
- const char* expected_new_url;
- };
- const TestCase kTests[] = {
- {true, "http://foo.test/original", "http://foo.test/redirected",
- "http://foo.test/redirected"},
- {true, "http://foo.test/original#1", "http://foo.test/redirected",
- "http://foo.test/redirected#1"},
- {true, "http://foo.test/original#1", "http://foo.test/redirected#2",
- "http://foo.test/redirected#2"},
- {false, "http://foo.test/original", "http://foo.test/redirected",
- "http://foo.test/redirected"},
- {false, "http://foo.test/original#1", "http://foo.test/redirected",
- "http://foo.test/redirected"},
- {false, "http://foo.test/original#1", "http://foo.test/redirected#2",
- "http://foo.test/redirected#2"},
- };
- const std::string kOriginalMethod = "GET";
- const SiteForCookies kOriginalSiteForCookies =
- SiteForCookies::FromUrl(GURL("https://foo.test/"));
- const RedirectInfo::FirstPartyURLPolicy kOriginalFirstPartyUrlPolicy =
- RedirectInfo::FirstPartyURLPolicy::NEVER_CHANGE_URL;
- const ReferrerPolicy kOriginalReferrerPolicy = ReferrerPolicy::NEVER_CLEAR;
- const std::string kOriginalReferrer = "";
- const int kHttpStatusCode = 301;
- const bool kInsecureSchemeWasUpgraded = false;
- for (const auto& test : kTests) {
- SCOPED_TRACE(::testing::Message()
- << "copy_fragment: " << test.copy_fragment
- << " original_url: " << test.original_url
- << " new_location: " << test.new_location);
- RedirectInfo redirect_info = RedirectInfo::ComputeRedirectInfo(
- kOriginalMethod, GURL(test.original_url), kOriginalSiteForCookies,
- kOriginalFirstPartyUrlPolicy, kOriginalReferrerPolicy,
- kOriginalReferrer, kHttpStatusCode, GURL(test.new_location),
- absl::nullopt /* referrer_policy_header */, kInsecureSchemeWasUpgraded,
- test.copy_fragment);
- EXPECT_EQ(GURL(test.expected_new_url), redirect_info.new_url);
- }
- }
- TEST(RedirectInfoTest, FirstPartyURLPolicy) {
- struct TestCase {
- RedirectInfo::FirstPartyURLPolicy original_first_party_url_policy;
- const char* expected_new_site_for_cookies;
- };
- const TestCase kTests[] = {
- {RedirectInfo::FirstPartyURLPolicy::NEVER_CHANGE_URL,
- "https://foo.test/"},
- {RedirectInfo::FirstPartyURLPolicy::UPDATE_URL_ON_REDIRECT,
- "https://foo.test/redirected"},
- };
- const std::string kOriginalMethod = "GET";
- const GURL kOriginalUrl = GURL("https://foo.test/");
- const SiteForCookies kOriginalSiteForCookies =
- SiteForCookies::FromUrl(GURL("https://foo.test/"));
- const ReferrerPolicy kOriginalReferrerPolicy = ReferrerPolicy::NEVER_CLEAR;
- const std::string kOriginalReferrer = "";
- const GURL kNewLocation = GURL("https://foo.test/redirected");
- const bool kInsecureSchemeWasUpgraded = false;
- const int kHttpStatusCode = 301;
- const bool kCopyFragment = true;
- for (const auto& test : kTests) {
- SCOPED_TRACE(::testing::Message()
- << "original_first_party_url_policy: "
- << static_cast<int>(test.original_first_party_url_policy));
- RedirectInfo redirect_info = RedirectInfo::ComputeRedirectInfo(
- kOriginalMethod, kOriginalUrl, kOriginalSiteForCookies,
- test.original_first_party_url_policy, kOriginalReferrerPolicy,
- kOriginalReferrer, kHttpStatusCode, kNewLocation,
- absl::nullopt /* referrer_policy_header */, kInsecureSchemeWasUpgraded,
- kCopyFragment);
- EXPECT_TRUE(redirect_info.new_site_for_cookies.IsEquivalent(
- SiteForCookies::FromUrl(GURL(test.expected_new_site_for_cookies))));
- }
- }
- TEST(RedirectInfoTest, ReferrerPolicy) {
- struct TestCase {
- const char* original_url;
- const char* original_referrer;
- const char* response_headers;
- ReferrerPolicy original_referrer_policy;
- ReferrerPolicy expected_new_referrer_policy;
- const char* expected_referrer;
- };
- const TestCase kTests[] = {
- // If a redirect serves 'Referrer-Policy: no-referrer', then the referrer
- // should be cleared.
- {"http://foo.test/one" /* original url */,
- "http://foo.test/one" /* original referrer */,
- "Location: http://foo.test/test\n"
- "Referrer-Policy: no-referrer\n",
- // original policy
- ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
- ReferrerPolicy::NO_REFERRER /* expected new policy */,
- "" /* expected new referrer */},
- // Same as above but for the legacy keyword 'never', which should not be
- // supported.
- {"http://foo.test/one" /* original url */,
- "http://foo.test/one" /* original referrer */,
- "Location: http://foo.test/test\nReferrer-Policy: never\n",
- // original policy
- ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
- // expected new policy
- ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
- "http://foo.test/one" /* expected new referrer */},
- // If a redirect serves 'Referrer-Policy: no-referrer-when-downgrade',
- // then the referrer should be cleared on downgrade, even if the original
- // request's policy specified that the referrer should never be cleared.
- {"https://foo.test/one" /* original url */,
- "https://foo.test/one" /* original referrer */,
- "Location: http://foo.test\n"
- "Referrer-Policy: no-referrer-when-downgrade\n",
- ReferrerPolicy::NEVER_CLEAR /* original policy */,
- // expected new policy
- ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
- "" /* expected new referrer */},
- // Same as above but for the legacy keyword 'default', which should not be
- // supported.
- {"https://foo.test/one" /* original url */,
- "https://foo.test/one" /* original referrer */,
- "Location: http://foo.test\n"
- "Referrer-Policy: default\n",
- ReferrerPolicy::NEVER_CLEAR /* original policy */,
- // expected new policy
- ReferrerPolicy::NEVER_CLEAR,
- "https://foo.test/one" /* expected new referrer */},
- // If a redirect serves 'Referrer-Policy: no-referrer-when-downgrade',
- // the referrer should not be cleared for a non-downgrading redirect. But
- // the policy should be updated.
- {"https://foo.test/one" /* original url */,
- "https://foo.test/one" /* original referrer */,
- "Location: https://foo.test\n"
- "Referrer-Policy: no-referrer-when-downgrade\n",
- ReferrerPolicy::NEVER_CLEAR /* original policy */,
- // expected new policy
- ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
- "https://foo.test/one" /* expected new referrer */},
- // If a redirect serves 'Referrer-Policy: origin', then the referrer
- // should be stripped to its origin, even if the original request's policy
- // specified that the referrer should never be cleared.
- {"https://foo.test/one" /* original url */,
- "https://foo.test/one" /* original referrer */,
- "Location: https://foo.test/two\n"
- "Referrer-Policy: origin\n",
- ReferrerPolicy::NEVER_CLEAR /* original policy */,
- ReferrerPolicy::ORIGIN /* expected new policy */,
- "https://foo.test/" /* expected new referrer */},
- // If a redirect serves 'Referrer-Policy: origin-when-cross-origin', then
- // the referrer should be untouched for a same-origin redirect...
- {"https://foo.test/one" /* original url */,
- "https://foo.test/referrer" /* original referrer */,
- "Location: https://foo.test/two\n"
- "Referrer-Policy: origin-when-cross-origin\n",
- ReferrerPolicy::NEVER_CLEAR /* original policy */,
- ReferrerPolicy::
- ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* expected new policy */,
- "https://foo.test/referrer" /* expected new referrer */},
- // ... but should be stripped to the origin for a cross-origin redirect.
- {"https://foo.test/one" /* original url */,
- "https://foo.test/one" /* original referrer */,
- "Location: https://bar.test/two\n"
- "Referrer-Policy: origin-when-cross-origin\n",
- ReferrerPolicy::NEVER_CLEAR /* original policy */,
- ReferrerPolicy::
- ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* expected new policy */,
- "https://foo.test/" /* expected new referrer */},
- // If a redirect serves 'Referrer-Policy: same-origin', then the referrer
- // should be untouched for a same-origin redirect,
- {"https://foo.test/one" /* original url */,
- "https://foo.test/referrer" /* original referrer */,
- "Location: https://foo.test/two\n"
- "Referrer-Policy: same-origin\n",
- ReferrerPolicy::NEVER_CLEAR /* original policy */,
- ReferrerPolicy::CLEAR_ON_TRANSITION_CROSS_ORIGIN /* new policy */
- ,
- "https://foo.test/referrer" /* expected new referrer */},
- // ... but should be cleared for a cross-origin redirect.
- {"https://foo.test/one" /* original url */,
- "https://foo.test/referrer" /* original referrer */,
- "Location: https://bar.test/two\n"
- "Referrer-Policy: same-origin\n",
- ReferrerPolicy::NEVER_CLEAR /* original policy */,
- ReferrerPolicy::CLEAR_ON_TRANSITION_CROSS_ORIGIN,
- "" /* expected new referrer */},
- // If a redirect serves 'Referrer-Policy: strict-origin', then the
- // referrer should be the origin only for a cross-origin non-downgrading
- // redirect,
- {"https://foo.test/one" /* original url */,
- "https://foo.test/referrer" /* original referrer */,
- "Location: https://bar.test/two\n"
- "Referrer-Policy: strict-origin\n",
- ReferrerPolicy::NEVER_CLEAR /* original policy */,
- ReferrerPolicy::ORIGIN_CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
- "https://foo.test/" /* expected new referrer */},
- {"http://foo.test/one" /* original url */,
- "http://foo.test/referrer" /* original referrer */,
- "Location: http://bar.test/two\n"
- "Referrer-Policy: strict-origin\n",
- ReferrerPolicy::NEVER_CLEAR /* original policy */,
- ReferrerPolicy::ORIGIN_CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
- "http://foo.test/" /* expected new referrer */},
- // ... but should be cleared for a downgrading redirect.
- {"https://foo.test/one" /* original url */,
- "https://foo.test/referrer" /* original referrer */,
- "Location: http://foo.test/two\n"
- "Referrer-Policy: strict-origin\n",
- ReferrerPolicy::NEVER_CLEAR /* original policy */,
- ReferrerPolicy::ORIGIN_CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
- "" /* expected new referrer */},
- // If a redirect serves 'Referrer-Policy:
- // strict-origin-when-cross-origin', then the referrer should be preserved
- // for a same-origin redirect,
- {"https://foo.test/one" /* original url */,
- "https://foo.test/referrer" /* original referrer */,
- "Location: https://foo.test/two\n"
- "Referrer-Policy: strict-origin-when-cross-origin\n",
- ReferrerPolicy::NEVER_CLEAR /* original policy */,
- ReferrerPolicy::REDUCE_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN,
- "https://foo.test/referrer" /* expected new referrer */},
- {"http://foo.test/one" /* original url */,
- "http://foo.test/referrer" /* original referrer */,
- "Location: http://foo.test/two\n"
- "Referrer-Policy: strict-origin-when-cross-origin\n",
- ReferrerPolicy::NEVER_CLEAR /* original policy */,
- ReferrerPolicy::REDUCE_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN,
- "http://foo.test/referrer" /* expected new referrer */},
- // ... but should be stripped to the origin for a cross-origin
- // non-downgrading redirect,
- {"https://foo.test/one" /* original url */,
- "https://foo.test/referrer" /* original referrer */,
- "Location: https://bar.test/two\n"
- "Referrer-Policy: strict-origin-when-cross-origin\n",
- ReferrerPolicy::NEVER_CLEAR /* original policy */,
- ReferrerPolicy::REDUCE_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN,
- "https://foo.test/" /* expected new referrer */},
- {"http://foo.test/one" /* original url */,
- "http://foo.test/referrer" /* original referrer */,
- "Location: http://bar.test/two\n"
- "Referrer-Policy: strict-origin-when-cross-origin\n",
- ReferrerPolicy::NEVER_CLEAR /* original policy */,
- ReferrerPolicy::REDUCE_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN,
- "http://foo.test/" /* expected new referrer */},
- // ... and should be cleared for a downgrading redirect.
- {"https://foo.test/one" /* original url */,
- "https://foo.test/referrer" /* original referrer */,
- "Location: http://foo.test/two\n"
- "Referrer-Policy: strict-origin-when-cross-origin\n",
- ReferrerPolicy::NEVER_CLEAR /* original policy */,
- ReferrerPolicy::REDUCE_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN,
- "" /* expected new referrer */},
- // If a redirect serves 'Referrer-Policy: unsafe-url', then the referrer
- // should remain, even if originally set to clear on downgrade.
- {"https://foo.test/one" /* original url */,
- "https://foo.test/one" /* original referrer */,
- "Location: http://bar.test/two\n"
- "Referrer-Policy: unsafe-url\n",
- ReferrerPolicy::
- ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* original policy */,
- ReferrerPolicy::NEVER_CLEAR /* expected new policy */,
- "https://foo.test/one" /* expected new referrer */},
- // Same as above but for the legacy keyword 'always', which should not be
- // supported.
- {"https://foo.test/one" /* original url */,
- "https://foo.test/one" /* original referrer */,
- "Location: http://bar.test/two\n"
- "Referrer-Policy: always\n",
- ReferrerPolicy::
- ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* original policy */,
- ReferrerPolicy::
- ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* expected new policy */,
- "https://foo.test/" /* expected new referrer */},
- // An invalid keyword should leave the policy untouched.
- {"https://foo.test/one" /* original url */,
- "https://foo.test/one" /* original referrer */,
- "Location: https://bar.test/two\n"
- "Referrer-Policy: not-a-valid-policy\n",
- ReferrerPolicy::
- ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* original policy */,
- ReferrerPolicy::
- ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* expected new policy */,
- "https://foo.test/" /* expected new referrer */},
- {"https://foo.test/one" /* original url */,
- "https://foo.test/one" /* original referrer */,
- "Location: http://bar.test/two\n"
- "Referrer-Policy: not-a-valid-policy\n",
- // original policy
- ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
- // expected new policy
- ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
- "" /* expected new referrer */},
- // The last valid keyword should take precedence.
- {"https://foo.test/one" /* original url */,
- "https://foo.test/one" /* original referrer */,
- "Location: https://bar.test/two\n"
- "Referrer-Policy: unsafe-url\n"
- "Referrer-Policy: not-a-valid-policy\n",
- ReferrerPolicy::
- ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* original policy */,
- ReferrerPolicy::NEVER_CLEAR /* expected new policy */,
- "https://foo.test/one" /* expected new referrer */},
- {"https://foo.test/one" /* original url */,
- "https://foo.test/one" /* original referrer */,
- "Location: https://bar.test/two\n"
- "Referrer-Policy: unsafe-url\n"
- "Referrer-Policy: origin\n",
- ReferrerPolicy::
- ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* original policy */,
- ReferrerPolicy::ORIGIN /* expected new policy */,
- "https://foo.test/" /* expected new referrer */},
- // An empty header should not affect the request.
- {"https://foo.test/one" /* original url */,
- "https://foo.test/one" /* original referrer */,
- "Location: https://bar.test/two\n"
- "Referrer-Policy: \n",
- ReferrerPolicy::
- ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* original policy */,
- ReferrerPolicy::
- ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* expected new policy */,
- "https://foo.test/" /* expected new referrer */},
- // A redirect response without Referrer-Policy header should not affect
- // the policy and the referrer.
- {"http://foo.test/one" /* original url */,
- "http://foo.test/one" /* original referrer */,
- "Location: http://foo.test/test\n",
- // original policy
- ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
- // expected new policy
- ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
- "http://foo.test/one" /* expected new referrer */},
- };
- const std::string kOriginalMethod = "GET";
- const SiteForCookies kOriginalSiteForCookies =
- SiteForCookies::FromUrl(GURL("https://foo.test/"));
- const RedirectInfo::FirstPartyURLPolicy kOriginalFirstPartyUrlPolicy =
- RedirectInfo::FirstPartyURLPolicy::NEVER_CHANGE_URL;
- const bool kInsecureSchemeWasUpgraded = false;
- const bool kCopyFragment = true;
- for (const auto& test : kTests) {
- SCOPED_TRACE(::testing::Message()
- << "original_url: " << test.original_url
- << " original_referrer: " << test.original_referrer
- << " response_headers: " << test.response_headers
- << " original_referrer_policy: "
- << static_cast<int>(test.original_referrer_policy));
- std::string response_header_text =
- "HTTP/1.1 302 Redirect\n" + std::string(test.response_headers);
- std::string raw_headers =
- HttpUtil::AssembleRawHeaders(response_header_text);
- auto response_headers =
- base::MakeRefCounted<HttpResponseHeaders>(raw_headers);
- EXPECT_EQ(302, response_headers->response_code());
- std::string location_string;
- EXPECT_TRUE(response_headers->IsRedirect(&location_string));
- const GURL original_url = GURL(test.original_url);
- const GURL new_location = original_url.Resolve(location_string);
- RedirectInfo redirect_info = RedirectInfo::ComputeRedirectInfo(
- kOriginalMethod, original_url, kOriginalSiteForCookies,
- kOriginalFirstPartyUrlPolicy, test.original_referrer_policy,
- test.original_referrer, response_headers->response_code(), new_location,
- RedirectUtil::GetReferrerPolicyHeader(response_headers.get()),
- kInsecureSchemeWasUpgraded, kCopyFragment);
- EXPECT_EQ(test.expected_new_referrer_policy,
- redirect_info.new_referrer_policy);
- EXPECT_EQ(test.expected_referrer, redirect_info.new_referrer);
- }
- }
- } // namespace
- } // namespace net
|