diff --git a/android_webview/browser/network_service/aw_proxying_restricted_cookie_manager_unittest.cc b/android_webview/browser/network_service/aw_proxying_restricted_cookie_manager_unittest.cc index 14fa8ef572403..0beaffe47298d 100644 --- a/android_webview/browser/network_service/aw_proxying_restricted_cookie_manager_unittest.cc +++ b/android_webview/browser/network_service/aw_proxying_restricted_cookie_manager_unittest.cc @@ -98,6 +98,8 @@ class MockRestrictedCookieManager bool force_disable_third_party_cookies, GetCookiesStringCallback callback) override { last_get_cookies_shared_memory_param_ = get_version_shared_memory; + last_get_cookies_site_for_cookies_ = site_for_cookies; + last_get_cookies_force_disable_3pcs_ = force_disable_third_party_cookies; std::move(callback).Run(network::mojom::kInvalidCookieVersion, base::ReadOnlySharedMemoryRegion(), ""); } @@ -116,8 +118,18 @@ class MockRestrictedCookieManager return last_get_cookies_shared_memory_param_; } + const net::SiteForCookies& last_get_cookies_site_for_cookies() const { + return last_get_cookies_site_for_cookies_; + } + + bool last_get_cookies_force_disable_3pcs() const { + return last_get_cookies_force_disable_3pcs_; + } + private: bool last_get_cookies_shared_memory_param_ = false; + net::SiteForCookies last_get_cookies_site_for_cookies_; + bool last_get_cookies_force_disable_3pcs_ = false; }; class AwProxyingRestrictedCookieManagerTest : public testing::Test { @@ -332,5 +344,73 @@ TEST_F(AwProxyingRestrictedCookieManagerTest, EXPECT_FALSE(mock_rcm.last_get_cookies_shared_memory_param()); } +// Test: The third-party cookie policy is evaluated against the SiteForCookies +// supplied at bind time, not the per-call value supplied over Mojo. +TEST_F(AwProxyingRestrictedCookieManagerTest, + ThirdPartyPolicyUsesBoundSiteForCookies) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(features::kWebViewLatchedCookiePolicy); + + cookie_access_policy_.SetShouldAcceptCookies(true); + + const GURL kTopLevelUrl("https://top.example/"); + const GURL kEmbeddedUrl("https://embedded.example/"); + const net::SiteForCookies kBoundSiteForCookies = + net::SiteForCookies::FromUrl(kTopLevelUrl); + + MockRestrictedCookieManager mock_rcm; + mojo::Receiver mock_receiver( + &mock_rcm); + + mojo::Remote proxy_remote; + + // Bind the proxy with the top-level SiteForCookies. With no associated + // frame, the per-WebView third-party setting latches to disabled. + CreateProxyOnIOThread(mock_receiver.BindNewPipeAndPassRemote(), + proxy_remote.BindNewPipeAndPassReceiver(), + kBoundSiteForCookies); + + ASSERT_TRUE( + base::test::RunUntil([&]() { return proxy_remote.is_connected(); })); + + // Issue a cross-site request whose per-call SiteForCookies claims to be + // same-site with the request URL. + base::RunLoop get_loop; + proxy_remote->GetCookiesString( + kEmbeddedUrl, net::SiteForCookies::FromUrl(kEmbeddedUrl), + url::Origin::Create(kEmbeddedUrl), net::StorageAccessApiStatus::kNone, + /*get_version_shared_memory=*/false, + /*is_ad_tagged=*/false, + /*apply_devtools_overrides=*/false, + /*force_disable_third_party_cookies=*/false, + base::BindOnce([](base::RunLoop* run_loop, uint64_t version, + base::ReadOnlySharedMemoryRegion region, + const std::string& str) { run_loop->Quit(); }, + &get_loop)); + get_loop.Run(); + + // The proxy must classify the request as third-party using the bound value + // and forward that bound value to the underlying RCM. + EXPECT_TRUE(mock_rcm.last_get_cookies_force_disable_3pcs()); + EXPECT_TRUE(mock_rcm.last_get_cookies_site_for_cookies().IsEquivalent( + kBoundSiteForCookies)); + + // CookiesEnabledFor must likewise report the request as third-party. + base::RunLoop enabled_loop; + bool enabled_result = true; + proxy_remote->CookiesEnabledFor( + kEmbeddedUrl, net::SiteForCookies::FromUrl(kEmbeddedUrl), + url::Origin::Create(kEmbeddedUrl), net::StorageAccessApiStatus::kNone, + /*apply_devtools_overrides=*/false, + base::BindOnce( + [](base::RunLoop* run_loop, bool* out, bool enabled) { + *out = enabled; + run_loop->Quit(); + }, + &enabled_loop, &enabled_result)); + enabled_loop.Run(); + EXPECT_FALSE(enabled_result); +} + } // namespace } // namespace android_webview