blob: 9b360fdfbe9f853bf419364c4658b76238ea73a1 [file] [log] [blame]
// Copyright 2021 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 "content/browser/back_forward_cache_browsertest.h"
#include "build/build_config.h"
#include "build/buildflag.h"
#include "build/chromecast_buildflags.h"
#include "content/browser/renderer_host/navigation_request.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/shell/browser/shell.h"
#include "net/test/embedded_test_server/controllable_http_response.h"
// This file contains back-/forward-cache tests for the
// `Cache-control: no-store` header. It was forked from
// https://source.chromium.org/chromium/chromium/src/+/main:content/browser/back_forward_cache_browsertest.cc;drc=b339487e39ad6ae93af30fa8fcb37dc61bd138ec
//
// When adding tests please also add WPTs. See
// third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/README.md
namespace content {
namespace {
const char kResponseWithNoCache[] =
"HTTP/1.1 200 OK\r\n"
"Content-Type: text/html; charset=utf-8\r\n"
"Cache-Control: no-store\r\n"
"\r\n"
"The server speaks HTTP!";
} // namespace
IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest,
MainFrameWithNoStoreNotCached) {
net::test_server::ControllableHttpResponse response(embedded_test_server(),
"/main_document");
ASSERT_TRUE(embedded_test_server()->Start());
GURL url_a(embedded_test_server()->GetURL("a.com", "/main_document"));
GURL url_b(embedded_test_server()->GetURL("b.com", "/title1.html"));
// 1. Load the document and specify no-store for the main resource.
TestNavigationObserver observer(web_contents());
shell()->LoadURL(url_a);
response.WaitForRequest();
response.Send(kResponseWithNoCache);
response.Done();
observer.Wait();
// 2. Navigate away and expect frame to be deleted.
RenderFrameDeletedObserver delete_observer_rfh_a(current_frame_host());
EXPECT_TRUE(NavigateToURL(shell(), url_b));
delete_observer_rfh_a.WaitUntilDeleted();
}
// Disabled for being flaky. See crbug.com/1116190.
IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest, SubframeWithNoStoreCached) {
// iframe will try to load title1.html.
net::test_server::ControllableHttpResponse response(embedded_test_server(),
"/title1.html");
ASSERT_TRUE(embedded_test_server()->Start());
GURL url_a(embedded_test_server()->GetURL("a.com", "/page_with_iframe.html"));
GURL url_b(embedded_test_server()->GetURL("b.com", "/title2.html"));
// 1) Load the document and specify no-store for the main resource.
TestNavigationObserver observer(web_contents());
shell()->LoadURL(url_a);
response.WaitForRequest();
response.Send(kResponseWithNoCache);
response.Done();
observer.Wait();
RenderFrameHostImpl* rfh_a = current_frame_host();
RenderFrameDeletedObserver delete_observer_rfh_a(current_frame_host());
// 2) Navigate away.
EXPECT_TRUE(NavigateToURL(shell(), url_b));
// 3) Navigate back and expect everything to be restored.
ASSERT_TRUE(HistoryGoBack(web_contents()));
EXPECT_FALSE(delete_observer_rfh_a.deleted());
EXPECT_EQ(rfh_a, current_frame_host());
}
namespace {
class BackForwardCacheBrowserTestAllowCacheControlNoStore
: public BackForwardCacheBrowserTest {
protected:
void SetUpCommandLine(base::CommandLine* command_line) override {
EnableFeatureAndSetParams(features::kBackForwardCache, "", "");
EnableFeatureAndSetParams(kCacheControlNoStoreEnterBackForwardCache,
"level", "store-and-evict");
BackForwardCacheBrowserTest::SetUpCommandLine(command_line);
}
};
} // namespace
// TODO(https://crbug.com/1231849): flaky on Cast Linux.
// Test that a page with cache-control:no-store enters bfcache with the flag on,
// but does not get restored and gets evicted.
// Turned off on cast for https://crbug.com/1281665 , along with others.
#if BUILDFLAG(IS_CHROMECAST)
#define MAYBE_PagesWithCacheControlNoStoreEnterBfcacheAndEvicted \
DISABLED_PagesWithCacheControlNoStoreEnterBfcacheAndEvicted
#else
#define MAYBE_PagesWithCacheControlNoStoreEnterBfcacheAndEvicted \
PagesWithCacheControlNoStoreEnterBfcacheAndEvicted
#endif
IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTestAllowCacheControlNoStore,
MAYBE_PagesWithCacheControlNoStoreEnterBfcacheAndEvicted) {
net::test_server::ControllableHttpResponse response(embedded_test_server(),
"/main_document");
net::test_server::ControllableHttpResponse response2(embedded_test_server(),
"/main_document");
ASSERT_TRUE(embedded_test_server()->Start());
GURL url_a(embedded_test_server()->GetURL("a.com", "/main_document"));
GURL url_b(embedded_test_server()->GetURL("b.com", "/title1.html"));
// 1) Load the document and specify no-store for the main resource.
TestNavigationObserver observer(web_contents());
shell()->LoadURL(url_a);
RenderFrameHostImplWrapper rfh_a(current_frame_host());
response.WaitForRequest();
response.Send(kResponseWithNoCache);
response.Done();
observer.Wait();
// 2) Navigate away. |rfh_a| should enter the bfcache.
EXPECT_TRUE(NavigateToURL(shell(), url_b));
EXPECT_TRUE(rfh_a->IsInBackForwardCache());
// 3) Go back. |rfh_a| should be evicted upon restoration.
TestNavigationObserver observer2(web_contents());
web_contents()->GetController().GoBack();
response2.WaitForRequest();
response2.Send(kResponseWithNoCache);
response2.Done();
observer2.Wait();
ExpectNotRestored(
{BackForwardCacheMetrics::NotRestoredReason::kCacheControlNoStore}, {},
{}, {}, {}, FROM_HERE);
}
// Test that a page with cache-control:no-store enters bfcache with the flag on,
// and if a cookie is modified while it is in bfcache via JavaScript, gets
// evicted with cookie modified marked.
// Turned off on cast for https://crbug.com/1281665 .
#if BUILDFLAG(IS_CHROMECAST)
#define MAYBE_PagesWithCacheControlNoStoreCookieModifiedThroughJavaScript \
DISABLED_PagesWithCacheControlNoStoreCookieModifiedThroughJavaScript
#else
#define MAYBE_PagesWithCacheControlNoStoreCookieModifiedThroughJavaScript \
PagesWithCacheControlNoStoreCookieModifiedThroughJavaScript
#endif
IN_PROC_BROWSER_TEST_F(
BackForwardCacheBrowserTestAllowCacheControlNoStore,
MAYBE_PagesWithCacheControlNoStoreCookieModifiedThroughJavaScript) {
net::test_server::ControllableHttpResponse response(embedded_test_server(),
"/main_document");
net::test_server::ControllableHttpResponse response2(embedded_test_server(),
"/main_document");
ASSERT_TRUE(embedded_test_server()->Start());
GURL url_a(embedded_test_server()->GetURL("a.com", "/main_document"));
GURL url_a_2(embedded_test_server()->GetURL("a.com", "/title1.html"));
GURL url_b(embedded_test_server()->GetURL("b.com", "/title1.html"));
Shell* tab_to_be_bfcached = shell();
Shell* tab_to_modify_cookie = CreateBrowser();
// 1) Load the document and specify no-store for the main resource.
TestNavigationObserver observer(tab_to_be_bfcached->web_contents());
tab_to_be_bfcached->LoadURL(url_a);
RenderFrameHostImplWrapper rfh_a(current_frame_host());
response.WaitForRequest();
response.Send(kResponseWithNoCache);
response.Done();
observer.Wait();
// 2) Set a normal cookie from JavaScript.
EXPECT_TRUE(ExecJs(tab_to_be_bfcached, "document.cookie='foo=bar'"));
EXPECT_EQ("foo=bar", EvalJs(tab_to_be_bfcached, "document.cookie"));
// 3) Navigate away. |rfh_a| should enter bfcache.
EXPECT_TRUE(NavigateToURL(tab_to_be_bfcached, url_b));
EXPECT_TRUE(rfh_a->IsInBackForwardCache());
// 4) Navigate to a.com in |tab_to_modify_cookie| and modify cookie from
// JavaScript.
EXPECT_TRUE(NavigateToURL(tab_to_modify_cookie, url_a_2));
EXPECT_EQ("foo=bar", EvalJs(tab_to_modify_cookie, "document.cookie"));
EXPECT_TRUE(ExecJs(tab_to_modify_cookie, "document.cookie='foo=baz'"));
EXPECT_EQ("foo=baz", EvalJs(tab_to_modify_cookie, "document.cookie"));
// 5) Go back. |rfh_a| should be evicted upon restoration.
TestNavigationObserver observer2(tab_to_be_bfcached->web_contents());
tab_to_be_bfcached->web_contents()->GetController().GoBack();
response2.WaitForRequest();
response2.Send(kResponseWithNoCache);
response2.Done();
observer2.Wait();
EXPECT_EQ("foo=baz", EvalJs(tab_to_be_bfcached, "document.cookie"));
ExpectNotRestored({BackForwardCacheMetrics::NotRestoredReason::
kCacheControlNoStoreCookieModified},
{}, {}, {}, {}, FROM_HERE);
}
// Disabled due to flakiness on Cast Audio Linux https://crbug.com/1229182
#if BUILDFLAG(IS_CHROMECAST)
#define MAYBE_PagesWithCacheControlNoStoreCookieModifiedBackTwice \
DISABLED_PagesWithCacheControlNoStoreCookieModifiedBackTwice
#else
#define MAYBE_PagesWithCacheControlNoStoreCookieModifiedBackTwice \
PagesWithCacheControlNoStoreCookieModifiedBackTwice
#endif
// Test that a page with cache-control:no-store enters bfcache with the flag on,
// and if a cookie is modified, it gets evicted with cookie changed, but if
// navigated away again and navigated back, it gets evicted without cookie
// change marked.
IN_PROC_BROWSER_TEST_F(
BackForwardCacheBrowserTestAllowCacheControlNoStore,
MAYBE_PagesWithCacheControlNoStoreCookieModifiedBackTwice) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url_a(embedded_test_server()->GetURL(
"a.com", "/set-header?Cache-Control: no-store"));
GURL url_a_2(embedded_test_server()->GetURL("a.com", "/title1.html"));
GURL url_b(embedded_test_server()->GetURL("b.com", "/title1.html"));
Shell* tab_to_be_bfcached = shell();
Shell* tab_to_modify_cookie = CreateBrowser();
// 1) Load the document and specify no-store for the main resource.
EXPECT_TRUE(NavigateToURL(tab_to_be_bfcached, url_a));
RenderFrameHostImplWrapper rfh_a(current_frame_host());
// 2) Set a normal cookie from JavaScript.
EXPECT_TRUE(ExecJs(tab_to_be_bfcached, "document.cookie='foo=bar'"));
EXPECT_EQ("foo=bar", EvalJs(tab_to_be_bfcached, "document.cookie"));
// 3) Navigate away. |rfh_a| should enter bfcache.
EXPECT_TRUE(NavigateToURL(tab_to_be_bfcached, url_b));
EXPECT_TRUE(rfh_a->IsInBackForwardCache());
// 4) Navigate to a.com in |tab_to_modify_cookie| and modify cookie from
// JavaScript.
EXPECT_TRUE(NavigateToURL(tab_to_modify_cookie, url_a_2));
EXPECT_EQ("foo=bar", EvalJs(tab_to_modify_cookie, "document.cookie"));
EXPECT_TRUE(ExecJs(tab_to_modify_cookie, "document.cookie='foo=baz'"));
EXPECT_EQ("foo=baz", EvalJs(tab_to_modify_cookie, "document.cookie"));
// 5) Go back. |rfh_a| should be evicted upon restoration.
ASSERT_TRUE(HistoryGoBack(tab_to_be_bfcached->web_contents()));
EXPECT_EQ("foo=baz", EvalJs(tab_to_be_bfcached, "document.cookie"));
ExpectNotRestored({BackForwardCacheMetrics::NotRestoredReason::
kCacheControlNoStoreCookieModified},
{}, {}, {}, {}, FROM_HERE);
RenderFrameHostImplWrapper rfh_a_2(current_frame_host());
// 6) Navigate away to b.com. |rfh_a_2| should enter bfcache again.
EXPECT_TRUE(NavigateToURL(tab_to_be_bfcached, url_b));
EXPECT_TRUE(rfh_a_2->IsInBackForwardCache());
// 7) Navigate back to a.com. This time the cookie change has to be reset and
// gets evicted with a different reason.
ASSERT_TRUE(HistoryGoBack(tab_to_be_bfcached->web_contents()));
ExpectNotRestored(
{BackForwardCacheMetrics::NotRestoredReason::kCacheControlNoStore}, {},
{}, {}, {}, FROM_HERE);
}
// Flaky on Cast Audio Linux https://crbug.com/1229182
// Test that a page with cache-control:no-store enters bfcache with the flag on,
// and even if a cookie is modified on a different domain than the entry, the
// entry is not marked as cookie modified.
// Turned off on cast for https://crbug.com/1281665 .
#if BUILDFLAG(IS_CHROMECAST)
#define MAYBE_PagesWithCacheControlNoStoreCookieModifiedThroughJavaScriptOnDifferentDomain \
DISABLED_PagesWithCacheControlNoStoreCookieModifiedThroughJavaScriptOnDifferentDomain
#else
#define MAYBE_PagesWithCacheControlNoStoreCookieModifiedThroughJavaScriptOnDifferentDomain \
PagesWithCacheControlNoStoreCookieModifiedThroughJavaScriptOnDifferentDomain
#endif
IN_PROC_BROWSER_TEST_F(
BackForwardCacheBrowserTestAllowCacheControlNoStore,
MAYBE_PagesWithCacheControlNoStoreCookieModifiedThroughJavaScriptOnDifferentDomain) {
net::test_server::ControllableHttpResponse response(embedded_test_server(),
"/main_document");
net::test_server::ControllableHttpResponse response2(embedded_test_server(),
"/main_document");
ASSERT_TRUE(embedded_test_server()->Start());
GURL url_a(embedded_test_server()->GetURL("a.com", "/main_document"));
GURL url_a_2(embedded_test_server()->GetURL("a.com", "/title1.html"));
GURL url_b(embedded_test_server()->GetURL("b.com", "/title1.html"));
Shell* tab_to_be_bfcached = shell();
Shell* tab_to_modify_cookie = CreateBrowser();
// 1) Load the document and specify no-store for the main resource.
TestNavigationObserver observer(tab_to_be_bfcached->web_contents());
tab_to_be_bfcached->LoadURL(url_a);
RenderFrameHostImplWrapper rfh_a(current_frame_host());
response.WaitForRequest();
response.Send(kResponseWithNoCache);
response.Done();
observer.Wait();
// 2) Set a normal cookie from JavaScript.
EXPECT_TRUE(ExecJs(tab_to_be_bfcached, "document.cookie='foo=bar'"));
EXPECT_EQ("foo=bar", EvalJs(tab_to_be_bfcached, "document.cookie"));
// 3) Navigate away. |rfh_a| should enter bfcache.
EXPECT_TRUE(NavigateToURL(tab_to_be_bfcached, url_b));
EXPECT_TRUE(rfh_a->IsInBackForwardCache());
// 4) Navigate to b.com in |tab_to_modify_cookie| and modify cookie from
// JavaScript.
EXPECT_TRUE(NavigateToURL(tab_to_modify_cookie, url_b));
EXPECT_TRUE(ExecJs(tab_to_modify_cookie, "document.cookie='foo=baz'"));
EXPECT_EQ("foo=baz", EvalJs(tab_to_modify_cookie, "document.cookie"));
// 5) Go back. |rfh_a| should be evicted upon restoration.
TestNavigationObserver observer2(tab_to_be_bfcached->web_contents());
tab_to_be_bfcached->web_contents()->GetController().GoBack();
response2.WaitForRequest();
response2.Send(kResponseWithNoCache);
response2.Done();
observer2.Wait();
EXPECT_EQ("foo=bar", EvalJs(tab_to_be_bfcached, "document.cookie"));
ExpectNotRestored(
{BackForwardCacheMetrics::NotRestoredReason::kCacheControlNoStore}, {},
{}, {}, {}, FROM_HERE);
}
// Test that a page with cache-control:no-store records other not restored
// reasons along with kCacheControlNoStore when eviction happens.
IN_PROC_BROWSER_TEST_F(
BackForwardCacheBrowserTestAllowCacheControlNoStore,
PagesWithCacheControlNoStoreRecordOtherReasonsWhenEvictionHappens) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url_a(embedded_test_server()->GetURL(
"a.com", "/set-header?Cache-Control: no-store"));
GURL url_b(embedded_test_server()->GetURL("b.com", "/title1.html"));
// 1) Load the document and specify no-store for the main resource.
EXPECT_TRUE(NavigateToURL(shell(), url_a));
RenderFrameHostImplWrapper rfh_a(current_frame_host());
// 2) Navigate away. At this point the page should be in bfcache.
EXPECT_TRUE(NavigateToURL(shell(), url_b));
EXPECT_TRUE(rfh_a->IsInBackForwardCache());
// 3) Execute JavaScript and evict the entry.
EvictByJavaScript(rfh_a.get());
// 4) Go back.
ASSERT_TRUE(HistoryGoBack(web_contents()));
ExpectNotRestored(
{BackForwardCacheMetrics::NotRestoredReason::kJavaScriptExecution,
BackForwardCacheMetrics::NotRestoredReason::kCacheControlNoStore},
{}, {}, {}, {}, FROM_HERE);
}
// Test that a page with cache-control:no-store records other not restored
// reasons along with kCacheControlNoStore when there are other blocking reasons
// upon entering bfcache.
IN_PROC_BROWSER_TEST_F(
BackForwardCacheBrowserTestAllowCacheControlNoStore,
PagesWithCacheControlNoStoreRecordOtherReasonsUponEntrance) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url_a(embedded_test_server()->GetURL(
"a.com", "/set-header?Cache-Control: no-store"));
GURL url_b(embedded_test_server()->GetURL("b.com", "/title1.html"));
// 1) Load the document and specify no-store for the main resource.
EXPECT_TRUE(NavigateToURL(shell(), url_a));
RenderFrameHostImplWrapper rfh_a(current_frame_host());
RenderFrameDeletedObserver delete_observer_rfh_a(rfh_a.get());
// Use blocklisted feature.
EXPECT_TRUE(ExecJs(rfh_a.get(), "window.foo = new BroadcastChannel('foo');"));
// 2) Navigate away. |rfh_a| should not enter bfcache.
EXPECT_TRUE(NavigateToURL(shell(), url_b));
delete_observer_rfh_a.WaitUntilDeleted();
// 3) Go back.
ASSERT_TRUE(HistoryGoBack(web_contents()));
ExpectNotRestored(
{BackForwardCacheMetrics::NotRestoredReason::kBlocklistedFeatures,
BackForwardCacheMetrics::NotRestoredReason::kCacheControlNoStore},
{blink::scheduler::WebSchedulerTrackedFeature::kBroadcastChannel}, {}, {},
{}, FROM_HERE);
}
namespace {
const char kResponseWithNoCacheWithCookie[] =
"HTTP/1.1 200 OK\r\n"
"Content-Type: text/html; charset=utf-8\r\n"
"Set-Cookie: foo=bar\r\n"
"Cache-Control: no-store\r\n"
"\r\n"
"The server speaks HTTP!";
const char kResponseWithNoCacheWithHTTPOnlyCookie[] =
"HTTP/1.1 200 OK\r\n"
"Content-Type: text/html; charset=utf-8\r\n"
"Set-Cookie: foo=bar; Secure; HttpOnly;\r\n"
"Cache-Control: no-store\r\n"
"\r\n"
"The server speaks HTTP!";
const char kResponseWithNoCacheWithHTTPOnlyCookie2[] =
"HTTP/1.1 200 OK\r\n"
"Content-Type: text/html; charset=utf-8\r\n"
"Set-Cookie: foo=baz; Secure; HttpOnly;\r\n"
"Cache-Control: no-store\r\n"
"\r\n"
"The server speaks HTTP!";
} // namespace
// Disabled due to flakiness on Cast Audio Linux https://crbug.com/1229182
#if BUILDFLAG(IS_CHROMECAST)
#define MAYBE_PagesWithCacheControlNoStoreSetFromResponseHeader \
DISABLED_PagesWithCacheControlNoStoreSetFromResponseHeader
#else
#define MAYBE_PagesWithCacheControlNoStoreSetFromResponseHeader \
PagesWithCacheControlNoStoreSetFromResponseHeader
#endif
// Test that a page with cache-control:no-store enters bfcache with the flag on,
// and if a cookie is modified while it is in bfcache via response header, gets
// evicted with cookie modified marked.
IN_PROC_BROWSER_TEST_F(
BackForwardCacheBrowserTestAllowCacheControlNoStore,
MAYBE_PagesWithCacheControlNoStoreSetFromResponseHeader) {
net::test_server::ControllableHttpResponse response(embedded_test_server(),
"/main_document");
net::test_server::ControllableHttpResponse response2(embedded_test_server(),
"/main_document");
ASSERT_TRUE(embedded_test_server()->Start());
GURL url_a(embedded_test_server()->GetURL("a.com", "/main_document"));
GURL url_a_2(embedded_test_server()->GetURL("a.com", "/title1.html"));
GURL url_b(embedded_test_server()->GetURL("b.com", "/title1.html"));
Shell* tab_to_be_bfcached = shell();
Shell* tab_to_modify_cookie = CreateBrowser();
// 1) Load the document and specify no-store for the main resource.
TestNavigationObserver observer(tab_to_be_bfcached->web_contents());
tab_to_be_bfcached->LoadURL(url_a);
RenderFrameHostImplWrapper rfh_a(current_frame_host());
response.WaitForRequest();
response.Send(kResponseWithNoCacheWithCookie);
response.Done();
observer.Wait();
EXPECT_EQ("foo=bar", EvalJs(tab_to_be_bfcached, "document.cookie"));
// 2) Navigate away. |rfh_a| should enter bfcache.
EXPECT_TRUE(NavigateToURL(tab_to_be_bfcached, url_b));
EXPECT_TRUE(rfh_a->IsInBackForwardCache());
// 3) Navigate to a.com in |tab_to_modify_cookie| and modify cookie from
// JavaScript.
EXPECT_TRUE(NavigateToURL(tab_to_modify_cookie, url_a_2));
EXPECT_EQ("foo=bar", EvalJs(tab_to_modify_cookie, "document.cookie"));
EXPECT_TRUE(ExecJs(tab_to_modify_cookie, "document.cookie='foo=baz'"));
EXPECT_EQ("foo=baz", EvalJs(tab_to_modify_cookie, "document.cookie"));
// 4) Go back. |rfh_a| should be evicted upon restoration.
TestNavigationObserver observer2(tab_to_be_bfcached->web_contents());
tab_to_be_bfcached->web_contents()->GetController().GoBack();
response2.WaitForRequest();
// Send the response without the cookie header to avoid overwriting the
// cookie.
response2.Send(kResponseWithNoCache);
response2.Done();
observer2.Wait();
EXPECT_EQ("foo=baz", EvalJs(tab_to_be_bfcached, "document.cookie"));
ExpectNotRestored({BackForwardCacheMetrics::NotRestoredReason::
kCacheControlNoStoreCookieModified},
{}, {}, {}, {}, FROM_HERE);
}
// Disabled due to flakiness on Cast Audio Linux https://crbug.com/1229182
#if BUILDFLAG(IS_CHROMECAST)
#define MAYBE_PagesWithCacheControlNoStoreSetFromResponseHeaderHTTPOnlyCookie \
DISABLED_PagesWithCacheControlNoStoreSetFromResponseHeaderHTTPOnlyCookie
#else
#define MAYBE_PagesWithCacheControlNoStoreSetFromResponseHeaderHTTPOnlyCookie \
PagesWithCacheControlNoStoreSetFromResponseHeaderHTTPOnlyCookie
#endif
// Test that a page with cache-control:no-store enters bfcache with the flag on,
// and if HTTPOnly cookie is modified while it is in bfcache, gets evicted with
// HTTPOnly cookie modified marked.
IN_PROC_BROWSER_TEST_F(
BackForwardCacheBrowserTestAllowCacheControlNoStore,
MAYBE_PagesWithCacheControlNoStoreSetFromResponseHeaderHTTPOnlyCookie) {
// HTTPOnly cookie can be only set over HTTPS.
CreateHttpsServer();
net::test_server::ControllableHttpResponse response(https_server(),
"/main_document");
net::test_server::ControllableHttpResponse response2(https_server(),
"/main_document2");
net::test_server::ControllableHttpResponse response3(https_server(),
"/main_document");
ASSERT_TRUE(https_server()->Start());
GURL url_a(https_server()->GetURL("a.com", "/main_document"));
GURL url_a_2(https_server()->GetURL("a.com", "/main_document2"));
GURL url_b(https_server()->GetURL("b.com", "/title1.html"));
Shell* tab_to_be_bfcached = shell();
Shell* tab_to_modify_cookie = CreateBrowser();
// 1) Load the document and specify no-store for the main resource.
TestNavigationObserver observer(tab_to_be_bfcached->web_contents());
tab_to_be_bfcached->LoadURL(url_a);
RenderFrameHostImplWrapper rfh_a(current_frame_host());
response.WaitForRequest();
response.Send(kResponseWithNoCacheWithHTTPOnlyCookie);
response.Done();
observer.Wait();
// HTTPOnly cookie should not be accessible from JavaScript.
EXPECT_EQ("", EvalJs(tab_to_be_bfcached, "document.cookie"));
// 2) Navigate away. |rfh_a| should enter bfcache.
EXPECT_TRUE(NavigateToURL(tab_to_be_bfcached, url_b));
EXPECT_TRUE(rfh_a->IsInBackForwardCache());
// 3) Navigate to a.com in |tab_to_modify_cookie| and modify HTTPOnly cookie
// from the response.
TestNavigationObserver observer2(tab_to_modify_cookie->web_contents());
tab_to_modify_cookie->LoadURL(url_a_2);
response2.WaitForRequest();
response2.Send(kResponseWithNoCacheWithHTTPOnlyCookie2);
response2.Done();
observer2.Wait();
// 4) Go back. |rfh_a| should be evicted upon restoration.
TestNavigationObserver observer3(tab_to_be_bfcached->web_contents());
tab_to_be_bfcached->web_contents()->GetController().GoBack();
response3.WaitForRequest();
response3.Send(kResponseWithNoCacheWithHTTPOnlyCookie);
response3.Done();
observer3.Wait();
ExpectNotRestored({BackForwardCacheMetrics::NotRestoredReason::
kCacheControlNoStoreHTTPOnlyCookieModified},
{}, {}, {}, {}, FROM_HERE);
}
// Disabled due to flakiness on Cast Audio Linux https://crbug.com/1229182
#if BUILDFLAG(IS_CHROMECAST)
#define MAYBE_PagesWithCacheControlNoStoreHTTPOnlyCookieModifiedBackTwice \
DISABLED_PagesWithCacheControlNoStoreHTTPOnlyCookieModifiedBackTwice
#else
#define MAYBE_PagesWithCacheControlNoStoreHTTPOnlyCookieModifiedBackTwice \
PagesWithCacheControlNoStoreHTTPOnlyCookieModifiedBackTwice
#endif
// Test that a page with cache-control:no-store enters bfcache with the flag on,
// and if a HTTPOnly cookie is modified, it gets evicted with cookie changed,
// but if navigated away again and navigated back, it gets evicted without
// HTTPOnly cookie change marked.
IN_PROC_BROWSER_TEST_F(
BackForwardCacheBrowserTestAllowCacheControlNoStore,
MAYBE_PagesWithCacheControlNoStoreHTTPOnlyCookieModifiedBackTwice) {
CreateHttpsServer();
net::test_server::ControllableHttpResponse response(https_server(),
"/main_document");
net::test_server::ControllableHttpResponse response2(https_server(),
"/main_document2");
net::test_server::ControllableHttpResponse response3(https_server(),
"/main_document");
net::test_server::ControllableHttpResponse response4(https_server(),
"/main_document");
ASSERT_TRUE(https_server()->Start());
GURL url_a(https_server()->GetURL("a.com", "/main_document"));
GURL url_a_2(https_server()->GetURL("a.com", "/main_document2"));
GURL url_b(https_server()->GetURL("b.com", "/title1.html"));
Shell* tab_to_be_bfcached = shell();
Shell* tab_to_modify_cookie = CreateBrowser();
// 1) Load the document and specify no-store for the main resource.
TestNavigationObserver observer(tab_to_be_bfcached->web_contents());
tab_to_be_bfcached->LoadURL(url_a);
RenderFrameHostImplWrapper rfh_a(current_frame_host());
response.WaitForRequest();
response.Send(kResponseWithNoCacheWithHTTPOnlyCookie);
response.Done();
observer.Wait();
// 2) Navigate away. |rfh_a| should enter bfcache.
EXPECT_TRUE(NavigateToURL(tab_to_be_bfcached, url_b));
EXPECT_TRUE(rfh_a->IsInBackForwardCache());
// 3) Navigate to a.com in |tab_to_modify_cookie| and modify cookie from
// response header.
TestNavigationObserver observer2(tab_to_modify_cookie->web_contents());
tab_to_modify_cookie->LoadURL(url_a_2);
response2.WaitForRequest();
response2.Send(kResponseWithNoCacheWithHTTPOnlyCookie2);
response2.Done();
observer2.Wait();
// 4) Go back. |rfh_a| should be evicted upon restoration.
TestNavigationObserver observer3(tab_to_be_bfcached->web_contents());
tab_to_be_bfcached->web_contents()->GetController().GoBack();
response3.WaitForRequest();
response3.Send(kResponseWithNoCache);
response3.Done();
observer3.Wait();
ExpectNotRestored({BackForwardCacheMetrics::NotRestoredReason::
kCacheControlNoStoreHTTPOnlyCookieModified},
{}, {}, {}, {}, FROM_HERE);
RenderFrameHostImplWrapper rfh_a_2(current_frame_host());
// 5) Navigate away to b.com. |rfh_a_2| should enter bfcache again.
EXPECT_TRUE(NavigateToURL(tab_to_be_bfcached, url_b));
EXPECT_TRUE(rfh_a_2->IsInBackForwardCache());
// 6) Navigate back to a.com. This time the cookie change has to be reset and
// gets evicted with a different reason.
TestNavigationObserver observer4(tab_to_be_bfcached->web_contents());
tab_to_be_bfcached->web_contents()->GetController().GoBack();
response4.WaitForRequest();
response4.Send(kResponseWithNoCache);
response4.Done();
observer4.Wait();
ExpectNotRestored(
{BackForwardCacheMetrics::NotRestoredReason::kCacheControlNoStore}, {},
{}, {}, {}, FROM_HERE);
}
class BackForwardCacheBrowserTestRestoreCacheControlNoStoreUnlessCookieChange
: public BackForwardCacheBrowserTest {
protected:
void SetUpCommandLine(base::CommandLine* command_line) override {
EnableFeatureAndSetParams(features::kBackForwardCache, "", "");
EnableFeatureAndSetParams(kCacheControlNoStoreEnterBackForwardCache,
"level", "restore-unless-cookie-change");
BackForwardCacheBrowserTest::SetUpCommandLine(command_line);
}
};
// TODO(https://crbug.com/1231849): flaky on Cast Linux.
// Test that a page with cache-control:no-store enters bfcache with the flag on,
// and gets restored if cookies do not change.
#if BUILDFLAG(IS_CHROMECAST)
#define MAYBE_PagesWithCacheControlNoStoreRestoreFromBackForwardCache \
DISABLED_PagesWithCacheControlNoStoreRestoreFromBackForwardCache
#else
#define MAYBE_PagesWithCacheControlNoStoreRestoreFromBackForwardCache \
PagesWithCacheControlNoStoreRestoreFromBackForwardCache
#endif
IN_PROC_BROWSER_TEST_F(
BackForwardCacheBrowserTestRestoreCacheControlNoStoreUnlessCookieChange,
MAYBE_PagesWithCacheControlNoStoreRestoreFromBackForwardCache) {
net::test_server::ControllableHttpResponse response(embedded_test_server(),
"/main_document");
net::test_server::ControllableHttpResponse response2(embedded_test_server(),
"/main_document");
ASSERT_TRUE(embedded_test_server()->Start());
GURL url_a(embedded_test_server()->GetURL("a.com", "/main_document"));
GURL url_b(embedded_test_server()->GetURL("b.com", "/title1.html"));
// 1) Load the document and specify no-store for the main resource.
TestNavigationObserver observer(web_contents());
shell()->LoadURL(url_a);
RenderFrameHostImplWrapper rfh_a(current_frame_host());
response.WaitForRequest();
response.Send(kResponseWithNoCache);
response.Done();
observer.Wait();
// 2) Navigate away. |rfh_a| should enter the bfcache.
EXPECT_TRUE(NavigateToURL(shell(), url_b));
EXPECT_TRUE(rfh_a->IsInBackForwardCache());
// 3) Go back. |rfh_a| should be restored.
ASSERT_TRUE(HistoryGoBack(web_contents()));
ExpectRestored(FROM_HERE);
}
// Flaky on Cast: crbug.com/1229182
// Test that a page with cache-control:no-store enters bfcache with the flag on,
// but gets evicted if cookies change.
// Turned off on cast for https://crbug.com/1281665 .
#if BUILDFLAG(IS_CHROMECAST)
#define MAYBE_PagesWithCacheControlNoStoreEvictedIfCookieChange \
DISABLED_PagesWithCacheControlNoStoreEvictedIfCookieChange
#else
#define MAYBE_PagesWithCacheControlNoStoreEvictedIfCookieChange \
PagesWithCacheControlNoStoreEvictedIfCookieChange
#endif
IN_PROC_BROWSER_TEST_F(
BackForwardCacheBrowserTestRestoreCacheControlNoStoreUnlessCookieChange,
MAYBE_PagesWithCacheControlNoStoreEvictedIfCookieChange) {
net::test_server::ControllableHttpResponse response(embedded_test_server(),
"/main_document");
net::test_server::ControllableHttpResponse response2(embedded_test_server(),
"/main_document");
ASSERT_TRUE(embedded_test_server()->Start());
GURL url_a(embedded_test_server()->GetURL("a.com", "/main_document"));
GURL url_a_2(embedded_test_server()->GetURL("a.com", "/title1.html"));
GURL url_b(embedded_test_server()->GetURL("b.com", "/title1.html"));
Shell* tab_to_be_bfcached = shell();
Shell* tab_to_modify_cookie = CreateBrowser();
// 1) Load the document and specify no-store for the main resource.
TestNavigationObserver observer(tab_to_be_bfcached->web_contents());
tab_to_be_bfcached->LoadURL(url_a);
RenderFrameHostImplWrapper rfh_a(current_frame_host());
response.WaitForRequest();
response.Send(kResponseWithNoCache);
response.Done();
observer.Wait();
// 2) Set a normal cookie from JavaScript.
EXPECT_TRUE(ExecJs(tab_to_be_bfcached, "document.cookie='foo=bar'"));
EXPECT_EQ("foo=bar", EvalJs(tab_to_be_bfcached, "document.cookie"));
// 3) Navigate away. |rfh_a| should enter bfcache.
EXPECT_TRUE(NavigateToURL(tab_to_be_bfcached, url_b));
EXPECT_TRUE(rfh_a->IsInBackForwardCache());
// 4) Navigate to a.com in |tab_to_modify_cookie| and modify cookie from
// JavaScript.
EXPECT_TRUE(NavigateToURL(tab_to_modify_cookie, url_a_2));
EXPECT_EQ("foo=bar", EvalJs(tab_to_modify_cookie, "document.cookie"));
EXPECT_TRUE(ExecJs(tab_to_modify_cookie, "document.cookie='foo=baz'"));
EXPECT_EQ("foo=baz", EvalJs(tab_to_modify_cookie, "document.cookie"));
// 5) Go back. |rfh_a| should be evicted upon restoration.
TestNavigationObserver observer2(tab_to_be_bfcached->web_contents());
tab_to_be_bfcached->web_contents()->GetController().GoBack();
response2.WaitForRequest();
response2.Send(kResponseWithNoCache);
response2.Done();
observer2.Wait();
EXPECT_EQ("foo=baz", EvalJs(tab_to_be_bfcached, "document.cookie"));
ExpectNotRestored({BackForwardCacheMetrics::NotRestoredReason::
kCacheControlNoStoreCookieModified},
{}, {}, {}, {}, FROM_HERE);
}
// TODO(https://crbug.com/1231849): flaky on Cast Linux.
#if BUILDFLAG(IS_LINUX)
#define MAYBE_PagesWithCacheControlNoStoreEvictedWithBothCookieReasons \
DISABLED_PagesWithCacheControlNoStoreEvictedWithBothCookieReasons
#else
#define MAYBE_PagesWithCacheControlNoStoreEvictedWithBothCookieReasons \
PagesWithCacheControlNoStoreEvictedWithBothCookieReasons
#endif
// Test that a page with cache-control:no-store enters bfcache with the flag on,
// and gets evicted with both JavaScript and HTTPOnly cookie changes. Only
// HTTPOnly cookie reason should be recorded.
IN_PROC_BROWSER_TEST_F(
BackForwardCacheBrowserTestRestoreCacheControlNoStoreUnlessCookieChange,
MAYBE_PagesWithCacheControlNoStoreEvictedWithBothCookieReasons) {
CreateHttpsServer();
net::test_server::ControllableHttpResponse response(https_server(),
"/main_document");
net::test_server::ControllableHttpResponse response2(https_server(),
"/main_document2");
net::test_server::ControllableHttpResponse response3(https_server(),
"/main_document");
ASSERT_TRUE(https_server()->Start());
GURL url_a(https_server()->GetURL("a.com", "/main_document"));
GURL url_a_2(https_server()->GetURL("a.com", "/main_document2"));
GURL url_b(https_server()->GetURL("b.com", "/title1.html"));
Shell* tab_to_be_bfcached = shell();
Shell* tab_to_modify_cookie = CreateBrowser();
// 1) Load the document and specify no-store for the main resource.
TestNavigationObserver observer(tab_to_be_bfcached->web_contents());
tab_to_be_bfcached->LoadURL(url_a);
RenderFrameHostImplWrapper rfh_a(current_frame_host());
response.WaitForRequest();
response.Send(kResponseWithNoCacheWithHTTPOnlyCookie);
response.Done();
observer.Wait();
// 2) Navigate away. |rfh_a| should enter bfcache.
EXPECT_TRUE(NavigateToURL(tab_to_be_bfcached, url_b));
EXPECT_TRUE(rfh_a->IsInBackForwardCache());
// Modify cookie from JavaScript as well.
EXPECT_TRUE(ExecJs(tab_to_be_bfcached, "document.cookie='foo=quz'"));
// 3) Navigate to a.com in |tab_to_modify_cookie| and modify HTTPOnly cookie
// from the response.
TestNavigationObserver observer2(tab_to_modify_cookie->web_contents());
tab_to_modify_cookie->LoadURL(url_a_2);
response2.WaitForRequest();
response2.Send(kResponseWithNoCacheWithHTTPOnlyCookie2);
response2.Done();
observer2.Wait();
// 4) Go back. |rfh_a| should be evicted upon restoration.
TestNavigationObserver observer3(tab_to_be_bfcached->web_contents());
tab_to_be_bfcached->web_contents()->GetController().GoBack();
response3.WaitForRequest();
response3.Send(kResponseWithNoCacheWithHTTPOnlyCookie);
response3.Done();
observer3.Wait();
ExpectNotRestored({BackForwardCacheMetrics::NotRestoredReason::
kCacheControlNoStoreHTTPOnlyCookieModified},
{}, {}, {}, {}, FROM_HERE);
}
class BackForwardCacheBrowserTestRestoreUnlessHTTPOnlyCookieChange
: public BackForwardCacheBrowserTest {
protected:
void SetUpCommandLine(base::CommandLine* command_line) override {
EnableFeatureAndSetParams(features::kBackForwardCache, "", "");
EnableFeatureAndSetParams(kCacheControlNoStoreEnterBackForwardCache,
"level",
"restore-unless-http-only-cookie-change");
BackForwardCacheBrowserTest::SetUpCommandLine(command_line);
}
};
// TODO(https://crbug.com/1231849): flaky on Cast Linux.
#if BUILDFLAG(IS_LINUX)
#define MAYBE_NoCacheControlNoStoreButHTTPOnlyCookieChange \
DISABLED_NoCacheControlNoStoreButHTTPOnlyCookieChange
#else
#define MAYBE_NoCacheControlNoStoreButHTTPOnlyCookieChange \
NoCacheControlNoStoreButHTTPOnlyCookieChange
#endif
// Test that a page without cache-control:no-store can enter BackForwardCache
// and gets restored if HTTPOnly Cookie changes.
IN_PROC_BROWSER_TEST_F(
BackForwardCacheBrowserTestRestoreUnlessHTTPOnlyCookieChange,
MAYBE_NoCacheControlNoStoreButHTTPOnlyCookieChange) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url_a(embedded_test_server()->GetURL(
"a.com", "/set-header?Set-Cookie: foo=bar; Secure; HttpOnly;"));
GURL url_a_2(embedded_test_server()->GetURL(
"a.com", "/set-header?Set-Cookie: foo=baz; Secure; HttpOnly;"));
GURL url_b(embedded_test_server()->GetURL("b.com", "/title1.html"));
Shell* tab_to_be_bfcached = shell();
Shell* tab_to_modify_cookie = CreateBrowser();
// 1) Load the document without cache-control:no-store.
EXPECT_TRUE(NavigateToURL(tab_to_be_bfcached, url_a));
RenderFrameHostImplWrapper rfh_a(current_frame_host());
// 2) Navigate away. |rfh_a| should enter bfcache.
EXPECT_TRUE(NavigateToURL(tab_to_be_bfcached, url_b));
EXPECT_TRUE(rfh_a->IsInBackForwardCache());
// 3) Navigate to a.com in |tab_to_modify_cookie| and modify HTTPOnly cookie
// from the header.
EXPECT_TRUE(NavigateToURL(tab_to_modify_cookie, url_a_2));
// 4) Go back. |rfh_a| should be restored from bfcache.
ASSERT_TRUE(HistoryGoBack(tab_to_be_bfcached->web_contents()));
ExpectRestored(FROM_HERE);
}
// TODO(https://crbug.com/1231849): flaky on Cast Linux.
#if BUILDFLAG(IS_LINUX)
#define MAYBE_PagesWithCacheControlNoStoreNotEvictedIfNormalCookieChange \
DISABLED_PagesWithCacheControlNoStoreNotEvictedIfNormalCookieChange
#else
#define MAYBE_PagesWithCacheControlNoStoreNotEvictedIfNormalCookieChange \
PagesWithCacheControlNoStoreNotEvictedIfNormalCookieChange
#endif
// Test that a page with cache-control:no-store enters bfcache with the flag on,
// and does not get evicted if normal cookies change.
IN_PROC_BROWSER_TEST_F(
BackForwardCacheBrowserTestRestoreUnlessHTTPOnlyCookieChange,
MAYBE_PagesWithCacheControlNoStoreNotEvictedIfNormalCookieChange) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url_a(embedded_test_server()->GetURL(
"a.com", "/set-header?Cache-Control: no-store"));
GURL url_b(embedded_test_server()->GetURL("b.com", "/title1.html"));
Shell* tab_to_be_bfcached = shell();
Shell* tab_to_modify_cookie = CreateBrowser();
// 1) Load the document and specify no-store for the main resource.
EXPECT_TRUE(NavigateToURL(tab_to_be_bfcached, url_a));
RenderFrameHostImplWrapper rfh_a(current_frame_host());
// 2) Set a normal cookie from JavaScript.
EXPECT_TRUE(ExecJs(tab_to_be_bfcached, "document.cookie='foo=bar'"));
EXPECT_EQ("foo=bar", EvalJs(tab_to_be_bfcached, "document.cookie"));
// 3) Navigate away. |rfh_a| should enter bfcache.
EXPECT_TRUE(NavigateToURL(tab_to_be_bfcached, url_b));
EXPECT_TRUE(rfh_a->IsInBackForwardCache());
// 4) Navigate to a.com in |tab_to_modify_cookie| and modify cookie from
// JavaScript.
EXPECT_TRUE(NavigateToURL(tab_to_modify_cookie, url_a));
EXPECT_EQ("foo=bar", EvalJs(tab_to_modify_cookie, "document.cookie"));
EXPECT_TRUE(ExecJs(tab_to_modify_cookie, "document.cookie='foo=baz'"));
EXPECT_EQ("foo=baz", EvalJs(tab_to_modify_cookie, "document.cookie"));
// 5) Go back. |rfh_a| should be restored from bfcache.
ASSERT_TRUE(HistoryGoBack(tab_to_be_bfcached->web_contents()));
EXPECT_EQ("foo=baz", EvalJs(tab_to_be_bfcached, "document.cookie"));
ExpectRestored(FROM_HERE);
}
// TODO(https://crbug.com/1231849): flaky on Cast Linux.
#if BUILDFLAG(IS_LINUX)
#define MAYBE_PagesWithCacheControlNoStoreEvictedIfHTTPOnlyCookieChange \
DISABLED_PagesWithCacheControlNoStoreEvictedIfHTTPOnlyCookieChange
#else
#define MAYBE_PagesWithCacheControlNoStoreEvictedIfHTTPOnlyCookieChange \
PagesWithCacheControlNoStoreEvictedIfHTTPOnlyCookieChange
#endif
// Test that a page with cache-control:no-store enters bfcache with the flag on,
// and gets evicted if HTTPOnly cookie changes.
IN_PROC_BROWSER_TEST_F(
BackForwardCacheBrowserTestRestoreCacheControlNoStoreUnlessCookieChange,
MAYBE_PagesWithCacheControlNoStoreEvictedIfHTTPOnlyCookieChange) {
CreateHttpsServer();
net::test_server::ControllableHttpResponse response(https_server(),
"/main_document");
net::test_server::ControllableHttpResponse response2(https_server(),
"/main_document2");
net::test_server::ControllableHttpResponse response3(https_server(),
"/main_document");
ASSERT_TRUE(https_server()->Start());
GURL url_a(https_server()->GetURL("a.com", "/main_document"));
GURL url_a_2(https_server()->GetURL("a.com", "/main_document2"));
GURL url_b(https_server()->GetURL("b.com", "/title1.html"));
Shell* tab_to_be_bfcached = shell();
Shell* tab_to_modify_cookie = CreateBrowser();
// 1) Load the document and specify no-store for the main resource.
TestNavigationObserver observer(tab_to_be_bfcached->web_contents());
tab_to_be_bfcached->LoadURL(url_a);
RenderFrameHostImplWrapper rfh_a(current_frame_host());
response.WaitForRequest();
response.Send(kResponseWithNoCacheWithHTTPOnlyCookie);
response.Done();
observer.Wait();
// 2) Navigate away. |rfh_a| should enter bfcache.
EXPECT_TRUE(NavigateToURL(tab_to_be_bfcached, url_b));
EXPECT_TRUE(rfh_a->IsInBackForwardCache());
// 3) Navigate to a.com in |tab_to_modify_cookie| and modify HTTPOnly cookie
// from the response.
TestNavigationObserver observer2(tab_to_modify_cookie->web_contents());
tab_to_modify_cookie->LoadURL(url_a_2);
response2.WaitForRequest();
response2.Send(kResponseWithNoCacheWithHTTPOnlyCookie2);
response2.Done();
observer2.Wait();
// 4) Go back. |rfh_a| should be evicted upon restoration.
TestNavigationObserver observer3(tab_to_be_bfcached->web_contents());
tab_to_be_bfcached->web_contents()->GetController().GoBack();
response3.WaitForRequest();
response3.Send(kResponseWithNoCacheWithHTTPOnlyCookie);
response3.Done();
observer3.Wait();
ExpectNotRestored({BackForwardCacheMetrics::NotRestoredReason::
kCacheControlNoStoreHTTPOnlyCookieModified},
{}, {}, {}, {}, FROM_HERE);
}
// TODO(https://crbug.com/1231849): flaky on Cast Linux.
#if BUILDFLAG(IS_LINUX)
#define MAYBE_PagesWithCacheControlNoStoreEvictedIfJSAndHTTPOnlyCookieChange \
DISABLED_PagesWithCacheControlNoStoreEvictedIfJSAndHTTPOnlyCookieChange
#else
#define MAYBE_PagesWithCacheControlNoStoreEvictedIfJSAndHTTPOnlyCookieChange \
PagesWithCacheControlNoStoreEvictedIfJSAndHTTPOnlyCookieChange
#endif
// Test that a page with cache-control:no-store enters bfcache with the flag on,
// and gets evicted if HTTPOnly cookie changes.
IN_PROC_BROWSER_TEST_F(
BackForwardCacheBrowserTestRestoreCacheControlNoStoreUnlessCookieChange,
MAYBE_PagesWithCacheControlNoStoreEvictedIfJSAndHTTPOnlyCookieChange) {
CreateHttpsServer();
net::test_server::ControllableHttpResponse response(https_server(),
"/main_document");
net::test_server::ControllableHttpResponse response2(https_server(),
"/main_document2");
net::test_server::ControllableHttpResponse response3(https_server(),
"/main_document");
ASSERT_TRUE(https_server()->Start());
GURL url_a(https_server()->GetURL("a.com", "/main_document"));
GURL url_a_2(https_server()->GetURL("a.com", "/main_document2"));
GURL url_b(https_server()->GetURL("b.com", "/title1.html"));
Shell* tab_to_be_bfcached = shell();
Shell* tab_to_modify_cookie = CreateBrowser();
// 1) Load the document and specify no-store for the main resource.
TestNavigationObserver observer(tab_to_be_bfcached->web_contents());
tab_to_be_bfcached->LoadURL(url_a);
RenderFrameHostImplWrapper rfh_a(current_frame_host());
response.WaitForRequest();
response.Send(kResponseWithNoCacheWithHTTPOnlyCookie);
response.Done();
observer.Wait();
// 2) Navigate away. |rfh_a| should enter bfcache.
EXPECT_TRUE(NavigateToURL(tab_to_be_bfcached, url_b));
EXPECT_TRUE(rfh_a->IsInBackForwardCache());
// Modify cookie from JavaScript as well.
EXPECT_TRUE(ExecJs(tab_to_be_bfcached, "document.cookie='foo=quz'"));
// 3) Navigate to a.com in |tab_to_modify_cookie| and modify HTTPOnly cookie
// from the response.
TestNavigationObserver observer2(tab_to_modify_cookie->web_contents());
tab_to_modify_cookie->LoadURL(url_a_2);
response2.WaitForRequest();
response2.Send(kResponseWithNoCacheWithHTTPOnlyCookie2);
response2.Done();
observer2.Wait();
// 4) Go back. |rfh_a| should be evicted upon restoration.
TestNavigationObserver observer3(tab_to_be_bfcached->web_contents());
tab_to_be_bfcached->web_contents()->GetController().GoBack();
response3.WaitForRequest();
response3.Send(kResponseWithNoCacheWithHTTPOnlyCookie);
response3.Done();
observer3.Wait();
ExpectNotRestored({BackForwardCacheMetrics::NotRestoredReason::
kCacheControlNoStoreHTTPOnlyCookieModified},
{}, {}, {}, {}, FROM_HERE);
}
} // namespace content