blob: aef68afc8d70d7f00a7a67c1ddebe40a85930f73 [file] [log] [blame]
Avi Drissman4e1b7bc32022-09-15 14:03:501// Copyright 2015 The Chromium Authors
nick5f3d76072015-06-09 00:24:002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <string>
6
John Abd-El-Malekb5f10a92017-11-01 14:50:337#include "base/bind.h"
danakjdb9ae7942020-11-11 16:01:358#include "base/callback_helpers.h"
nick5f3d76072015-06-09 00:24:009#include "base/command_line.h"
10#include "base/files/file_path.h"
Guido Urdanetaef4e91942020-11-09 15:06:2411#include "base/test/bind.h"
Devlin Cronin513398f2018-06-05 15:33:4912#include "base/test/metrics/histogram_tester.h"
Chris Fredricksonb4cf8402022-09-23 22:59:5913#include "base/test/scoped_feature_list.h"
nick462f92832015-12-04 18:47:4514#include "content/browser/bad_message.h"
danakjc492bf82020-09-09 20:02:4415#include "content/browser/renderer_host/frame_tree.h"
nick5f3d76072015-06-09 00:24:0016#include "content/browser/web_contents/web_contents_impl.h"
Maks Orlovich710d5e32019-07-09 20:16:4517#include "content/public/browser/browser_context.h"
Eric Seckler8652dcd52018-09-20 10:42:2818#include "content/public/browser/browser_task_traits.h"
Gabriel Charette790754c2018-03-16 21:32:5919#include "content/public/browser/browser_thread.h"
nick5f3d76072015-06-09 00:24:0020#include "content/public/browser/render_process_host.h"
Maks Orlovich710d5e32019-07-09 20:16:4521#include "content/public/browser/storage_partition.h"
Hans Wennborg5ffd1392019-10-16 11:00:0222#include "content/public/common/content_client.h"
nick5f3d76072015-06-09 00:24:0023#include "content/public/common/content_switches.h"
Peter Kasting919ce652020-05-07 10:22:3624#include "content/public/test/browser_test.h"
nick5f3d76072015-06-09 00:24:0025#include "content/public/test/browser_test_utils.h"
26#include "content/public/test/content_browser_test.h"
27#include "content/public/test/content_browser_test_utils.h"
carlosk15fb0f02015-07-29 17:07:5128#include "content/public/test/test_utils.h"
nick5f3d76072015-06-09 00:24:0029#include "content/shell/browser/shell.h"
30#include "content/test/content_browser_test_utils_internal.h"
31#include "ipc/ipc_security_test_util.h"
Chris Fredricksonb4cf8402022-09-23 22:59:5932#include "net/base/features.h"
Maks Orlovich710d5e32019-07-09 20:16:4533#include "net/cookies/canonical_cookie.h"
Ayu Ishiif3966ca2020-07-08 17:35:1234#include "net/cookies/cookie_access_result.h"
Lily Chenf068a762019-08-21 21:10:5035#include "net/cookies/cookie_util.h"
nick5f3d76072015-06-09 00:24:0036#include "net/dns/mock_host_resolver.h"
Aaron Tagliaboschi6ed3c0692022-02-27 18:54:0037#include "net/http/alternative_service.h"
nick5f3d76072015-06-09 00:24:0038#include "net/test/embedded_test_server/embedded_test_server.h"
Chris Fredricksonf9de3452022-09-12 21:46:5639#include "services/network/public/cpp/network_switches.h"
Maks Orlovich710d5e32019-07-09 20:16:4540#include "services/network/public/mojom/restricted_cookie_manager.mojom-test-utils.h"
41#include "services/network/public/mojom/restricted_cookie_manager.mojom.h"
42#include "services/service_manager/public/cpp/interface_provider.h"
nick462f92832015-12-04 18:47:4543#include "testing/gmock/include/gmock/gmock.h"
nick5f3d76072015-06-09 00:24:0044#include "testing/gtest/include/gtest/gtest.h"
Anton Bikineevf62d1bf2021-05-15 17:56:0745#include "third_party/abseil-cpp/absl/types/optional.h"
mkwstdf1821c62016-02-24 13:07:2046#include "url/gurl.h"
nick5f3d76072015-06-09 00:24:0047
48namespace content {
49
50namespace {
51
Maks Orlovich710d5e32019-07-09 20:16:4552void SetCookieFromJS(RenderFrameHost* frame, std::string cookie) {
53 EvalJsResult result = EvalJs(frame, "document.cookie = '" + cookie + "'");
54 EXPECT_TRUE(result.error.empty()) << result.error;
55}
56
nick5f3d76072015-06-09 00:24:0057std::string GetCookieFromJS(RenderFrameHost* frame) {
Avi Drissman49ecc702021-04-15 20:37:4158 return EvalJs(frame, "document.cookie;").ExtractString();
nick5f3d76072015-06-09 00:24:0059}
60
Maks Orlovich710d5e32019-07-09 20:16:4561void SetCookieDirect(WebContentsImpl* tab,
62 const GURL& url,
63 const std::string& cookie_line) {
Lily Chene1d272a52019-08-12 17:00:5664 net::CookieOptions options;
65 // Allow setting SameSite cookies.
66 options.set_same_site_cookie_context(
Steven Bingler8d76c2a42020-03-24 17:13:3267 net::CookieOptions::SameSiteCookieContext::MakeInclusive());
Lily Chene1d272a52019-08-12 17:00:5668
Maks Orlovich710d5e32019-07-09 20:16:4569 auto cookie_obj = net::CanonicalCookie::Create(
Dylan Cutlerf4a802b2021-08-03 16:38:5470 url, cookie_line, base::Time::Now(), absl::nullopt /* server_time */,
71 absl::nullopt /* cookie_partition_key */);
Maks Orlovich710d5e32019-07-09 20:16:4572
73 base::RunLoop run_loop;
Lukasz Anforowiczb9a969a2021-04-29 15:26:2574 tab->GetBrowserContext()
75 ->GetDefaultStoragePartition()
Maks Orlovich710d5e32019-07-09 20:16:4576 ->GetCookieManagerForBrowserProcess()
77 ->SetCanonicalCookie(
Lily Chen96f29a132020-04-15 17:59:3678 *cookie_obj, url, options,
Maks Orlovich710d5e32019-07-09 20:16:4579 base::BindLambdaForTesting(
Ayu Ishiif3966ca2020-07-08 17:35:1280 [&](net::CookieAccessResult status) { run_loop.Quit(); }));
Maks Orlovich710d5e32019-07-09 20:16:4581 run_loop.Run();
82}
83
84std::string GetCookiesDirect(WebContentsImpl* tab, const GURL& url) {
Lily Chene1d272a52019-08-12 17:00:5685 net::CookieOptions options;
86 // Allow setting SameSite cookies.
87 options.set_same_site_cookie_context(
Steven Bingler8d76c2a42020-03-24 17:13:3288 net::CookieOptions::SameSiteCookieContext::MakeInclusive());
Maks Orlovich710d5e32019-07-09 20:16:4589 net::CookieList result;
90 base::RunLoop run_loop;
Lukasz Anforowiczb9a969a2021-04-29 15:26:2591 tab->GetBrowserContext()
92 ->GetDefaultStoragePartition()
Maks Orlovich710d5e32019-07-09 20:16:4593 ->GetCookieManagerForBrowserProcess()
Ayu Ishiibc6fdb0a2020-06-08 22:59:1994 ->GetCookieList(
Aykut Bulut244341e2021-12-09 15:57:2595 url, options, net::CookiePartitionKeyCollection(),
Ayu Ishiibc6fdb0a2020-06-08 22:59:1996 base::BindLambdaForTesting(
97 [&](const net::CookieAccessResultList& cookie_list,
98 const net::CookieAccessResultList& excluded_cookies) {
99 result = net::cookie_util::StripAccessResults(cookie_list);
100 run_loop.Quit();
101 }));
Maks Orlovich710d5e32019-07-09 20:16:45102 run_loop.Run();
103 return net::CanonicalCookie::BuildCookieLine(result);
rockot6a2d66a2016-08-04 00:15:25104}
105
nick5f3d76072015-06-09 00:24:00106} // namespace
107
Thomas Phillips7c0c3a52020-11-19 02:01:23108class CookieBrowserTest : public ContentBrowserTest {
mkwstf71d0bd2016-03-21 14:15:24109 protected:
110 void SetUp() override {
111 base::CommandLine::ForCurrentProcess()->AppendSwitch(
112 switches::kEnableExperimentalWebPlatformFeatures);
mkwstf71d0bd2016-03-21 14:15:24113 ContentBrowserTest::SetUp();
114 }
jam8f34ea72017-04-26 17:48:55115
116 void SetUpOnMainThread() override {
117 // Support multiple sites on the test server.
118 host_resolver()->AddRule("*", "127.0.0.1");
119 }
mkwstf71d0bd2016-03-21 14:15:24120};
nick5f3d76072015-06-09 00:24:00121
122// Exercises basic cookie operations via javascript, including an http page
123// interacting with secure cookies.
Thomas Phillips7c0c3a52020-11-19 02:01:23124IN_PROC_BROWSER_TEST_F(CookieBrowserTest, Cookies) {
nick5f3d76072015-06-09 00:24:00125 SetupCrossSiteRedirector(embedded_test_server());
martijn12d2dad2016-11-11 10:59:27126 ASSERT_TRUE(embedded_test_server()->Start());
nick5f3d76072015-06-09 00:24:00127
svaldezc3a9a172015-11-03 22:01:33128 net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
Alan Cutterfb5689192019-03-28 08:39:19129 https_server.AddDefaultHandlers(GetTestDataFilePath());
Maks Orlovichbd04d782020-11-17 21:23:34130 https_server.SetSSLConfig(net::EmbeddedTestServer::CERT_TEST_NAMES);
nick5f3d76072015-06-09 00:24:00131 ASSERT_TRUE(https_server.Start());
132
Lily Chen15b3ff882021-05-21 01:27:41133 // The server sends a HttpOnly cookie. The RestrictedCookieManager should
nick462f92832015-12-04 18:47:45134 // never allow this to be sent to any renderer process.
Maks Orlovichbd04d782020-11-17 21:23:34135 GURL https_url =
136 https_server.GetURL("a.test", "/set-cookie?notforjs=1;HttpOnly");
137 GURL http_url =
138 embedded_test_server()->GetURL("a.test", "/frame_with_load_event.html");
nick5f3d76072015-06-09 00:24:00139
140 Shell* shell2 = CreateBrowser();
Alex Moshchukaa95adf52019-08-13 00:02:02141 EXPECT_TRUE(NavigateToURL(shell(), http_url));
142 EXPECT_TRUE(NavigateToURL(shell2, https_url));
nick5f3d76072015-06-09 00:24:00143
144 WebContentsImpl* web_contents_https =
145 static_cast<WebContentsImpl*>(shell2->web_contents());
146 WebContentsImpl* web_contents_http =
147 static_cast<WebContentsImpl*>(shell()->web_contents());
Aaron Colwelle953e562019-07-24 16:47:36148 if (AreDefaultSiteInstancesEnabled()) {
149 // Note: Both use the default SiteInstance because the URLs don't require
150 // a dedicated process, but these default SiteInstances are not the same
151 // object because they come from different BrowsingInstances.
152 EXPECT_TRUE(web_contents_http->GetSiteInstance()->IsDefaultSiteInstance());
153 EXPECT_TRUE(web_contents_https->GetSiteInstance()->IsDefaultSiteInstance());
154 EXPECT_NE(web_contents_http->GetSiteInstance(),
155 web_contents_https->GetSiteInstance());
156 EXPECT_FALSE(web_contents_http->GetSiteInstance()->IsRelatedSiteInstance(
157 web_contents_https->GetSiteInstance()));
158 } else {
Maks Orlovichbd04d782020-11-17 21:23:34159 EXPECT_EQ("http://a.test/",
Aaron Colwelle953e562019-07-24 16:47:36160 web_contents_http->GetSiteInstance()->GetSiteURL().spec());
Maks Orlovichbd04d782020-11-17 21:23:34161 EXPECT_EQ("https://a.test/",
Aaron Colwelle953e562019-07-24 16:47:36162 web_contents_https->GetSiteInstance()->GetSiteURL().spec());
163 }
nick5f3d76072015-06-09 00:24:00164
165 EXPECT_NE(web_contents_http->GetSiteInstance()->GetProcess(),
166 web_contents_https->GetSiteInstance()->GetProcess());
167
Dave Tapuska327c06c92022-06-13 20:31:51168 EXPECT_EQ("", GetCookieFromJS(web_contents_https->GetPrimaryMainFrame()));
169 EXPECT_EQ("", GetCookieFromJS(web_contents_http->GetPrimaryMainFrame()));
nick5f3d76072015-06-09 00:24:00170
171 // Non-TLS page writes secure cookie.
Dave Tapuska327c06c92022-06-13 20:31:51172 EXPECT_TRUE(ExecJs(web_contents_http->GetPrimaryMainFrame(),
Avi Drissman49ecc702021-04-15 20:37:41173 "document.cookie = 'A=1; secure;';"));
Dave Tapuska327c06c92022-06-13 20:31:51174 EXPECT_EQ("", GetCookieFromJS(web_contents_https->GetPrimaryMainFrame()));
175 EXPECT_EQ("", GetCookieFromJS(web_contents_http->GetPrimaryMainFrame()));
nick5f3d76072015-06-09 00:24:00176
Joshua Hoodf54ef852022-02-23 17:33:58177 // Non-TLS page writes not-secure cookie.
Dave Tapuska327c06c92022-06-13 20:31:51178 EXPECT_TRUE(ExecJs(web_contents_http->GetPrimaryMainFrame(),
179 "document.cookie = 'B=2';"));
180 EXPECT_EQ("B=2", GetCookieFromJS(web_contents_https->GetPrimaryMainFrame()));
181 EXPECT_EQ("B=2", GetCookieFromJS(web_contents_http->GetPrimaryMainFrame()));
nick5f3d76072015-06-09 00:24:00182
mkwstf71d0bd2016-03-21 14:15:24183 // TLS page writes secure cookie.
Dave Tapuska327c06c92022-06-13 20:31:51184 EXPECT_TRUE(ExecJs(web_contents_https->GetPrimaryMainFrame(),
Avi Drissman49ecc702021-04-15 20:37:41185 "document.cookie = 'C=3;secure;';"));
Dave Tapuska327c06c92022-06-13 20:31:51186 EXPECT_EQ("B=2; C=3",
187 GetCookieFromJS(web_contents_https->GetPrimaryMainFrame()));
188 EXPECT_EQ("B=2", GetCookieFromJS(web_contents_http->GetPrimaryMainFrame()));
nick5f3d76072015-06-09 00:24:00189
190 // TLS page writes not-secure cookie.
Dave Tapuska327c06c92022-06-13 20:31:51191 EXPECT_TRUE(ExecJs(web_contents_https->GetPrimaryMainFrame(),
192 "document.cookie = 'D=4';"));
mkwstf71d0bd2016-03-21 14:15:24193 EXPECT_EQ("B=2; C=3; D=4",
Dave Tapuska327c06c92022-06-13 20:31:51194 GetCookieFromJS(web_contents_https->GetPrimaryMainFrame()));
195 EXPECT_EQ("B=2; D=4",
196 GetCookieFromJS(web_contents_http->GetPrimaryMainFrame()));
nick5f3d76072015-06-09 00:24:00197}
198
Joshua Bell1d432be2018-06-27 19:59:48199// Ensure "priority" cookie option is settable via document.cookie.
Thomas Phillips7c0c3a52020-11-19 02:01:23200IN_PROC_BROWSER_TEST_F(CookieBrowserTest, CookiePriority) {
Joshua Bell1d432be2018-06-27 19:59:48201 ASSERT_TRUE(embedded_test_server()->Start());
202
203 struct {
204 std::string param;
205 net::CookiePriority priority;
206 } cases[] = {{"name=value", net::COOKIE_PRIORITY_DEFAULT},
207 {"name=value;priority=Low", net::COOKIE_PRIORITY_LOW},
208 {"name=value;priority=Medium", net::COOKIE_PRIORITY_MEDIUM},
209 {"name=value;priority=High", net::COOKIE_PRIORITY_HIGH}};
210
211 for (auto test_case : cases) {
212 GURL url = embedded_test_server()->GetURL("/set_document_cookie.html?" +
213 test_case.param);
Alex Moshchukaa95adf52019-08-13 00:02:02214 EXPECT_TRUE(NavigateToURL(shell(), url));
Joshua Bell1d432be2018-06-27 19:59:48215 std::vector<net::CanonicalCookie> cookies =
216 GetCanonicalCookies(shell()->web_contents()->GetBrowserContext(), url);
217
218 EXPECT_EQ(1u, cookies.size());
219 EXPECT_EQ("name", cookies[0].Name());
220 EXPECT_EQ("value", cookies[0].Value());
221 EXPECT_EQ(test_case.priority, cookies[0].Priority());
222 }
223}
224
mkwstdf1821c62016-02-24 13:07:20225// SameSite cookies (that aren't marked as http-only) should be available to
226// JavaScript.
Thomas Phillips7c0c3a52020-11-19 02:01:23227IN_PROC_BROWSER_TEST_F(CookieBrowserTest, SameSiteCookies) {
Lily Chene1d272a52019-08-12 17:00:56228 // Must use HTTPS because SameSite=None cookies must be Secure.
David Benjaminddf9671c32019-12-03 16:54:12229 net::EmbeddedTestServer server(net::EmbeddedTestServer::TYPE_HTTPS);
230 server.SetSSLConfig(net::EmbeddedTestServer::CERT_TEST_NAMES);
231 server.AddDefaultHandlers(GetTestDataFilePath());
232 SetupCrossSiteRedirector(&server);
233 ASSERT_TRUE(server.Start());
mkwstdf1821c62016-02-24 13:07:20234
David Benjaminddf9671c32019-12-03 16:54:12235 // The server sets eight cookies on 'a.test' and on 'b.test', then loads
236 // a page that frames both 'a.test' and 'b.test' under 'a.test'.
mkwstf71d0bd2016-03-21 14:15:24237 std::string cookies_to_set =
Lily Chene1d272a52019-08-12 17:00:56238 "/set-cookie?none=1;SameSite=None;Secure" // SameSite=None must be
239 // Secure.
240 "&none-insecure=1;SameSite=None"
mkwstf71d0bd2016-03-21 14:15:24241 "&strict=1;SameSite=Strict"
Lily Chene1d272a52019-08-12 17:00:56242 "&unspecified=1" // unspecified SameSite should be treated as Lax.
mkwstf71d0bd2016-03-21 14:15:24243 "&lax=1;SameSite=Lax"
Lily Chene1d272a52019-08-12 17:00:56244 "&none-http=1;SameSite=None;Secure;httponly"
mkwstf71d0bd2016-03-21 14:15:24245 "&strict-http=1;SameSite=Strict;httponly"
Lily Chene1d272a52019-08-12 17:00:56246 "&unspecified-http=1;httponly"
mkwstf71d0bd2016-03-21 14:15:24247 "&lax-http=1;SameSite=Lax;httponly";
248
David Benjaminddf9671c32019-12-03 16:54:12249 GURL url = server.GetURL("a.test", cookies_to_set);
Alex Moshchukaeb20fe32019-09-25 17:40:01250 EXPECT_TRUE(NavigateToURL(shell(), url));
David Benjaminddf9671c32019-12-03 16:54:12251 url = server.GetURL("b.test", cookies_to_set);
Alex Moshchukaeb20fe32019-09-25 17:40:01252 EXPECT_TRUE(NavigateToURL(shell(), url));
David Benjaminddf9671c32019-12-03 16:54:12253 url = server.GetURL(
254 "a.test", "/cross_site_iframe_factory.html?a.test(a.test(),b.test())");
Alex Moshchukaa95adf52019-08-13 00:02:02255 EXPECT_TRUE(NavigateToURL(shell(), url));
mkwstdf1821c62016-02-24 13:07:20256
257 WebContentsImpl* web_contents =
258 static_cast<WebContentsImpl*>(shell()->web_contents());
Dave Tapuska327c06c92022-06-13 20:31:51259 RenderFrameHost* main_frame = web_contents->GetPrimaryMainFrame();
Carlos Caballero15caeeb2021-10-27 09:57:55260 RenderFrameHost* a_iframe = web_contents->GetPrimaryFrameTree()
261 .root()
262 ->child_at(0)
263 ->current_frame_host();
264 RenderFrameHost* b_iframe = web_contents->GetPrimaryFrameTree()
265 .root()
266 ->child_at(1)
267 ->current_frame_host();
mkwstdf1821c62016-02-24 13:07:20268
Lily Chene1d272a52019-08-12 17:00:56269 // The top-level frame should get all same-site cookies.
270 EXPECT_EQ("none=1; strict=1; unspecified=1; lax=1",
271 GetCookieFromJS(main_frame));
mkwstf71d0bd2016-03-21 14:15:24272
273 // Same-site cookies will be delievered to the 'a.com' frame, as it is same-
274 // site with its ancestors.
Lily Chene1d272a52019-08-12 17:00:56275 EXPECT_EQ("none=1; strict=1; unspecified=1; lax=1",
276 GetCookieFromJS(a_iframe));
mkwstf71d0bd2016-03-21 14:15:24277
278 // Same-site cookies should not be delievered to the 'b.com' frame, as it
Lily Chene1d272a52019-08-12 17:00:56279 // isn't same-site with its ancestors. The SameSite=None but insecure cookie
280 // is rejected.
281 EXPECT_EQ("none=1", GetCookieFromJS(b_iframe));
mkwstdf1821c62016-02-24 13:07:20282}
283
Aaron Tagliaboschi6ed3c0692022-02-27 18:54:00284IN_PROC_BROWSER_TEST_F(CookieBrowserTest, CookieTruncatingChar) {
285 using std::string_literals::operator""s;
286
287 std::string cookie_string;
288 embedded_test_server()->RegisterRequestHandler(base::BindLambdaForTesting(
289 [&](const net::test_server::HttpRequest& request)
290 -> std::unique_ptr<net::test_server::HttpResponse> {
291 auto response = std::make_unique<net::test_server::BasicHttpResponse>();
292 response->AddCustomHeader("Set-Cookie", cookie_string);
293 return std::move(response);
294 }));
295
296 ASSERT_TRUE(embedded_test_server()->Start());
297
298 GURL http_url = embedded_test_server()->GetURL("/");
299 base::HistogramTester histogram;
300
301 // Test scenarios where a control char may appear at start, middle and end of
302 // a cookie line. Control char array with NULL (\x0), CR (\xD), and LF (xA)
303 char kTestChars[] = {'\x0', '\xD', '\xA'};
304
305 for (const auto& test : kTestChars) {
306 std::string ctl_string(1, test);
307
308 // ctrl char at start of string
309 cookie_string = ctl_string + "foo=bar"s;
310 EXPECT_TRUE(NavigateToURL(shell(), http_url));
311
312 // ctrl char at middle of string
313 cookie_string = "foo=bar;"s + ctl_string + "httponly"s;
314 EXPECT_TRUE(NavigateToURL(shell(), http_url));
315
316 // ctrl char at end of string
317 cookie_string = "foo=bar;"s + "httponly;"s + ctl_string;
318 EXPECT_TRUE(NavigateToURL(shell(), http_url));
319 }
320 // Test if there are multiple control characters that terminate.
321 cookie_string = "foo=bar;\xA\xDhttponly"s;
322 EXPECT_TRUE(NavigateToURL(shell(), http_url));
323
324 FetchHistogramsFromChildProcesses();
325 histogram.ExpectBucketCount(
326 "Cookie.TruncatingCharacterInCookieString",
327 net::TruncatingCharacterInCookieStringType::kTruncatingCharNull, 0);
328 histogram.ExpectBucketCount(
329 "Cookie.TruncatingCharacterInCookieString",
330 net::TruncatingCharacterInCookieStringType::kTruncatingCharNewline, 0);
331 histogram.ExpectBucketCount(
332 "Cookie.TruncatingCharacterInCookieString",
333 net::TruncatingCharacterInCookieStringType::kTruncatingCharLineFeed, 0);
334}
335
Maks Orlovich710d5e32019-07-09 20:16:45336class RestrictedCookieManagerInterceptor
337 : public network::mojom::RestrictedCookieManagerInterceptorForTesting {
338 public:
339 RestrictedCookieManagerInterceptor(
Julie Jeongeun Kimd20f64b2019-08-26 04:13:03340 mojo::PendingReceiver<network::mojom::RestrictedCookieManager> receiver,
Julie Jeongeun Kimf42b07c2019-08-27 15:38:36341 mojo::PendingRemote<network::mojom::RestrictedCookieManager> real_rcm)
Julie Jeongeun Kimd20f64b2019-08-26 04:13:03342 : receiver_(this, std::move(receiver)), real_rcm_(std::move(real_rcm)) {}
Maks Orlovich710d5e32019-07-09 20:16:45343
Anton Bikineevf62d1bf2021-05-15 17:56:07344 void set_override_url(absl::optional<std::string> maybe_url) {
Maks Orlovich710d5e32019-07-09 20:16:45345 override_url_ = std::move(maybe_url);
346 }
347
348 void SetCookieFromString(const GURL& url,
Maks Orlovichab27e242020-01-07 18:10:39349 const net::SiteForCookies& site_for_cookies,
Christian Dullweber10d62c12019-08-19 12:08:19350 const url::Origin& top_frame_origin,
Maks Orlovich710d5e32019-07-09 20:16:45351 const std::string& cookie,
Dylan Cutler49dc3922022-02-18 01:45:27352 bool partitioned_cookies_runtime_feature_enabled,
Maks Orlovich710d5e32019-07-09 20:16:45353 SetCookieFromStringCallback callback) override {
354 GetForwardingInterface()->SetCookieFromString(
Christian Dullweber10d62c12019-08-19 12:08:19355 URLToUse(url), site_for_cookies, top_frame_origin, std::move(cookie),
Dylan Cutler49dc3922022-02-18 01:45:27356 /*partitioned_cookies_runtime_feature_enabled=*/false,
Maks Orlovich710d5e32019-07-09 20:16:45357 std::move(callback));
358 }
359
360 void GetCookiesString(const GURL& url,
Maks Orlovichab27e242020-01-07 18:10:39361 const net::SiteForCookies& site_for_cookies,
Christian Dullweber10d62c12019-08-19 12:08:19362 const url::Origin& top_frame_origin,
Dylan Cutler49dc3922022-02-18 01:45:27363 bool partitioned_cookies_runtime_feature_enabled,
Maks Orlovich710d5e32019-07-09 20:16:45364 GetCookiesStringCallback callback) override {
365 GetForwardingInterface()->GetCookiesString(
Dylan Cutler49dc3922022-02-18 01:45:27366 URLToUse(url), site_for_cookies, top_frame_origin,
367 /*partitioned_cookies_runtime_feature_enabled=*/false,
368 std::move(callback));
Maks Orlovich710d5e32019-07-09 20:16:45369 }
370
371 private:
372 network::mojom::RestrictedCookieManager* GetForwardingInterface() override {
373 return real_rcm_.get();
374 }
375
376 GURL URLToUse(const GURL& url_in) {
377 return override_url_ ? GURL(override_url_.value()) : url_in;
378 }
379
Anton Bikineevf62d1bf2021-05-15 17:56:07380 absl::optional<std::string> override_url_;
Maks Orlovich710d5e32019-07-09 20:16:45381
Julie Jeongeun Kimd20f64b2019-08-26 04:13:03382 mojo::Receiver<network::mojom::RestrictedCookieManager> receiver_;
Julie Jeongeun Kimf42b07c2019-08-27 15:38:36383 mojo::Remote<network::mojom::RestrictedCookieManager> real_rcm_;
Maks Orlovich710d5e32019-07-09 20:16:45384};
385
386class CookieStoreContentBrowserClient : public ContentBrowserClient {
387 public:
Chris Fredrickson5d0cb4f2022-09-27 16:48:42388 ~CookieStoreContentBrowserClient() override = default;
Maks Orlovich710d5e32019-07-09 20:16:45389
390 bool WillCreateRestrictedCookieManager(
Maks Orloviche7db7a22019-07-25 01:47:46391 network::mojom::RestrictedCookieManagerRole role,
Maks Orlovich710d5e32019-07-09 20:16:45392 content::BrowserContext* browser_context,
Shuran Huangbd4d1692021-01-26 17:03:41393 const url::Origin& origin,
Shuran Huang92b415d72021-01-12 20:48:15394 const net::IsolationInfo& isolation_info,
Maks Orlovich710d5e32019-07-09 20:16:45395 bool is_service_worker,
396 int process_id,
397 int routing_id,
Julie Jeongeun Kimd20f64b2019-08-26 04:13:03398 mojo::PendingReceiver<network::mojom::RestrictedCookieManager>* receiver)
399 override {
400 mojo::PendingReceiver<network::mojom::RestrictedCookieManager>
401 orig_receiver = std::move(*receiver);
Maks Orlovich710d5e32019-07-09 20:16:45402
Julie Jeongeun Kimf42b07c2019-08-27 15:38:36403 mojo::PendingRemote<network::mojom::RestrictedCookieManager> real_rcm;
404 *receiver = real_rcm.InitWithNewPipeAndPassReceiver();
Maks Orlovich710d5e32019-07-09 20:16:45405
406 rcm_interceptor_ = std::make_unique<RestrictedCookieManagerInterceptor>(
Julie Jeongeun Kimd20f64b2019-08-26 04:13:03407 std::move(orig_receiver), std::move(real_rcm));
Maks Orlovich710d5e32019-07-09 20:16:45408 rcm_interceptor_->set_override_url(override_url_);
409
410 return false; // only made a proxy, still need the actual impl to be made.
411 }
412
Anton Bikineevf62d1bf2021-05-15 17:56:07413 void set_override_url(absl::optional<std::string> maybe_url) {
Maks Orlovich710d5e32019-07-09 20:16:45414 override_url_ = maybe_url;
415 if (rcm_interceptor_)
416 rcm_interceptor_->set_override_url(override_url_);
417 }
418
419 private:
Anton Bikineevf62d1bf2021-05-15 17:56:07420 absl::optional<std::string> override_url_;
Maks Orlovich710d5e32019-07-09 20:16:45421 std::unique_ptr<RestrictedCookieManagerInterceptor> rcm_interceptor_;
422};
423
424// Cookie access in loader is locked to a particular origin, so messages
425// for wrong URLs are rejected.
426// TODO(https://crbug.com/954603): This should actually result in renderer
427// kills.
Thomas Phillips7c0c3a52020-11-19 02:01:23428IN_PROC_BROWSER_TEST_F(CookieBrowserTest, CrossSiteCookieSecurityEnforcement) {
nick5f3d76072015-06-09 00:24:00429 // The code under test is only active under site isolation.
nickd30fd962015-07-27 21:51:08430 if (!AreAllSitesIsolatedForTesting()) {
nick5f3d76072015-06-09 00:24:00431 return;
432 }
433
nick5f3d76072015-06-09 00:24:00434 SetupCrossSiteRedirector(embedded_test_server());
martijn12d2dad2016-11-11 10:59:27435 ASSERT_TRUE(embedded_test_server()->Start());
Alex Moshchukaa95adf52019-08-13 00:02:02436 EXPECT_TRUE(NavigateToURL(
437 shell(), embedded_test_server()->GetURL("/frame_with_load_event.html")));
nick5f3d76072015-06-09 00:24:00438
439 WebContentsImpl* tab = static_cast<WebContentsImpl*>(shell()->web_contents());
440
441 // The iframe on the http page should get its own process.
442 FrameTreeVisualizer v;
443 EXPECT_EQ(
444 " Site A ------------ proxies for B\n"
445 " +--Site B ------- proxies for A\n"
446 "Where A = http://127.0.0.1/\n"
447 " B = http://baz.com/",
Carlos Caballero15caeeb2021-10-27 09:57:55448 v.DepictFrameTree(tab->GetPrimaryFrameTree().root()));
nick5f3d76072015-06-09 00:24:00449
Dave Tapuska327c06c92022-06-13 20:31:51450 RenderFrameHost* main_frame = tab->GetPrimaryMainFrame();
nick5f3d76072015-06-09 00:24:00451 RenderFrameHost* iframe =
Carlos Caballero15caeeb2021-10-27 09:57:55452 tab->GetPrimaryFrameTree().root()->child_at(0)->current_frame_host();
nick5f3d76072015-06-09 00:24:00453
454 EXPECT_NE(iframe->GetProcess(), main_frame->GetProcess());
455
Maks Orlovich710d5e32019-07-09 20:16:45456 SetCookieDirect(tab, GURL("http://127.0.0.1/"), "A_cookie = parent");
457 SetCookieDirect(tab, GURL("http://baz.com/"), "B_cookie = child");
458 EXPECT_EQ("A_cookie=parent",
459 GetCookiesDirect(tab, GURL("http://127.0.0.1/")));
460
461 EXPECT_EQ("B_cookie=child", GetCookiesDirect(tab, GURL("http://baz.com/")));
462
463 // Try to get cross-site cookies from the subframe's process.
Lukasz Anforowicz6f746282018-01-04 23:24:51464 {
Maks Orlovich710d5e32019-07-09 20:16:45465 CookieStoreContentBrowserClient browser_client;
466 content::ContentBrowserClient* old_browser_client =
467 content::SetBrowserClientForTesting(&browser_client);
468 browser_client.set_override_url("http://127.0.0.1/");
469 EXPECT_EQ("", GetCookieFromJS(iframe));
nick5f3d76072015-06-09 00:24:00470
Maks Orlovich710d5e32019-07-09 20:16:45471 content::SetBrowserClientForTesting(old_browser_client);
Lukasz Anforowicz6f746282018-01-04 23:24:51472 }
nick5f3d76072015-06-09 00:24:00473
474 EXPECT_EQ(
475 " Site A ------------ proxies for B\n"
476 " +--Site B ------- proxies for A\n"
477 "Where A = http://127.0.0.1/\n"
Maks Orlovich710d5e32019-07-09 20:16:45478 " B = http://baz.com/",
Carlos Caballero15caeeb2021-10-27 09:57:55479 v.DepictFrameTree(tab->GetPrimaryFrameTree().root()));
nick5f3d76072015-06-09 00:24:00480
Maks Orlovich710d5e32019-07-09 20:16:45481 // Now set a cross-site cookie from the main frame's process.
Lukasz Anforowicz6f746282018-01-04 23:24:51482 {
Maks Orlovich710d5e32019-07-09 20:16:45483 CookieStoreContentBrowserClient browser_client;
484 content::ContentBrowserClient* old_browser_client =
485 content::SetBrowserClientForTesting(&browser_client);
rockot1587e332016-07-27 17:44:14486
Maks Orlovich710d5e32019-07-09 20:16:45487 browser_client.set_override_url("https://baz.com/");
488 SetCookieFromJS(iframe, "pwn=ed");
nick5f3d76072015-06-09 00:24:00489
Maks Orlovich710d5e32019-07-09 20:16:45490 EXPECT_EQ("B_cookie=child", GetCookiesDirect(tab, GURL("http://baz.com/")));
491
492 content::SetBrowserClientForTesting(old_browser_client);
Lukasz Anforowicz6f746282018-01-04 23:24:51493 }
nick5f3d76072015-06-09 00:24:00494
495 EXPECT_EQ(
Maks Orlovich710d5e32019-07-09 20:16:45496 " Site A ------------ proxies for B\n"
497 " +--Site B ------- proxies for A\n"
498 "Where A = http://127.0.0.1/\n"
499 " B = http://baz.com/",
Carlos Caballero15caeeb2021-10-27 09:57:55500 v.DepictFrameTree(tab->GetPrimaryFrameTree().root()));
nick5f3d76072015-06-09 00:24:00501}
502
nick5f3d76072015-06-09 00:24:00503} // namespace content