blob: 9332b364dc90e6659f93193f20ec5ff2ae26192f [file] [log] [blame]
Avi Drissman4e1b7bc32022-09-15 14:03:501// Copyright 2016 The Chromium Authors
toyoshime5aaf6a2016-05-18 08:07:482// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <memory>
toyoshima27638a2016-12-06 10:20:476#include <string>
7#include <vector>
toyoshime5aaf6a2016-05-18 08:07:488
Avi Drissmanadac21992023-01-11 23:46:399#include "base/functional/bind.h"
10#include "base/functional/callback_helpers.h"
Makoto Shimazufd875022018-11-26 08:10:0111#include "base/strings/utf_string_conversions.h"
toyoshima27638a2016-12-06 10:20:4712#include "base/synchronization/lock.h"
David Sandersee132412025-06-25 17:50:2913#include "content/public/browser/web_contents.h"
Peter Kasting919ce652020-05-07 10:22:3614#include "content/public/test/browser_test.h"
Makoto Shimazufd875022018-11-26 08:10:0115#include "content/public/test/browser_test_utils.h"
toyoshime5aaf6a2016-05-18 08:07:4816#include "content/public/test/content_browser_test.h"
17#include "content/public/test/content_browser_test_utils.h"
18#include "content/shell/browser/shell.h"
19#include "net/test/embedded_test_server/embedded_test_server.h"
20#include "net/test/embedded_test_server/http_request.h"
21#include "net/test/embedded_test_server/http_response.h"
22#include "testing/gtest/include/gtest/gtest.h"
23#include "url/gurl.h"
24
25namespace content {
26
27namespace {
28
29using net::test_server::HttpRequest;
30using net::test_server::HttpResponse;
31
toyoshim4562d4a2017-03-16 04:09:0232const char kReloadTestPath[] = "/loader/reload_test.html";
toyoshim4562d4a2017-03-16 04:09:0233// The test page should request resources as the content structure is described
34// below. Reload and the same page navigation will affect only the top frame
35// resource, reload_test.html. But bypassing reload will affect all resources.
36// +- reload_test.html
37// +- empty16x16.png
38// +- simple_frame.html
39// +- empty16x16.png
toyoshime5aaf6a2016-05-18 08:07:4840
41const char kNoCacheControl[] = "";
42const char kMaxAgeCacheControl[] = "max-age=0";
43const char kNoCacheCacheControl[] = "no-cache";
44
45struct RequestLog {
46 std::string relative_url;
47 std::string cache_control;
48};
49
Takashi Toyoshimabf698302017-05-31 13:23:0550struct ExpectedCacheControl {
51 const char* top_main;
52 const char* others;
53};
54
55const ExpectedCacheControl kExpectedCacheControlForNormalLoad = {
56 kNoCacheControl, kNoCacheControl};
57const ExpectedCacheControl kExpectedCacheControlForReload = {
58 kMaxAgeCacheControl, kNoCacheControl};
59const ExpectedCacheControl kExpectedCacheControlForBypassingReload = {
60 kNoCacheCacheControl, kNoCacheCacheControl};
61
toyoshima27638a2016-12-06 10:20:4762// Tests end to end behaviors between Blink and content around reload variants.
toyoshime5aaf6a2016-05-18 08:07:4863class ReloadCacheControlBrowserTest : public ContentBrowserTest {
Peter Boström9b036532021-10-28 23:37:2864 public:
65 ReloadCacheControlBrowserTest(const ReloadCacheControlBrowserTest&) = delete;
66 ReloadCacheControlBrowserTest& operator=(
67 const ReloadCacheControlBrowserTest&) = delete;
68
toyoshime5aaf6a2016-05-18 08:07:4869 protected:
toyoshim980f11702016-12-02 08:15:5370 ReloadCacheControlBrowserTest() {}
asvitkinef1c49402016-11-19 00:25:1371 ~ReloadCacheControlBrowserTest() override = default;
toyoshim7ae0fd52016-07-08 09:29:5072
asvitkinef1c49402016-11-19 00:25:1373 void SetUpOnMainThread() override {
toyoshim7ae0fd52016-07-08 09:29:5074 SetUpTestServerOnMainThread();
75 }
76
77 void SetUpTestServerOnMainThread() {
toyoshime5aaf6a2016-05-18 08:07:4878 // ContentBrowserTest creates embedded_test_server instance with
79 // a registered HandleFileRequest for "content/test/data".
80 // Because the handler is registered as the first handler, MonitorHandler
81 // is needed to capture all requests.
Makoto Shimazu833e1c72019-10-09 21:14:5082 embedded_test_server()->RegisterRequestMonitor(base::BindRepeating(
tzike04a1472016-08-02 21:00:3383 &ReloadCacheControlBrowserTest::MonitorRequestHandler,
84 base::Unretained(this)));
toyoshime5aaf6a2016-05-18 08:07:4885
86 ASSERT_TRUE(embedded_test_server()->Start());
87 }
88
89 protected:
Takashi Toyoshimabf698302017-05-31 13:23:0590 void CheckCacheControl(const ExpectedCacheControl& expectation) {
91 base::AutoLock lock(request_log_lock_);
92 EXPECT_EQ(4u, request_log_.size());
93 for (const auto& log : request_log_) {
Solomon Kinardab293bae2024-09-19 17:13:5194 if (log.relative_url == kReloadTestPath) {
Takashi Toyoshimabf698302017-05-31 13:23:0595 EXPECT_EQ(expectation.top_main, log.cache_control);
Solomon Kinardab293bae2024-09-19 17:13:5196 } else {
Takashi Toyoshimabf698302017-05-31 13:23:0597 EXPECT_EQ(expectation.others, log.cache_control);
Solomon Kinardab293bae2024-09-19 17:13:5198 }
Takashi Toyoshimabf698302017-05-31 13:23:0599 }
100 request_log_.clear();
101 }
102
toyoshime5aaf6a2016-05-18 08:07:48103 std::vector<RequestLog> request_log_;
toyoshima27638a2016-12-06 10:20:47104 base::Lock request_log_lock_;
toyoshime5aaf6a2016-05-18 08:07:48105
106 private:
107 void MonitorRequestHandler(const HttpRequest& request) {
108 RequestLog log;
109 log.relative_url = request.relative_url;
110 auto cache_control = request.headers.find("Cache-Control");
111 log.cache_control = cache_control == request.headers.end()
112 ? kNoCacheControl
113 : cache_control->second;
toyoshima27638a2016-12-06 10:20:47114 base::AutoLock lock(request_log_lock_);
toyoshime5aaf6a2016-05-18 08:07:48115 request_log_.push_back(log);
116 }
toyoshime5aaf6a2016-05-18 08:07:48117};
118
toyoshim4562d4a2017-03-16 04:09:02119// Test if reload issues requests with proper cache control flags.
toyoshime5aaf6a2016-05-18 08:07:48120IN_PROC_BROWSER_TEST_F(ReloadCacheControlBrowserTest, NormalReload) {
121 GURL url(embedded_test_server()->GetURL(kReloadTestPath));
122
123 EXPECT_TRUE(NavigateToURL(shell(), url));
Takashi Toyoshimabf698302017-05-31 13:23:05124 CheckCacheControl(kExpectedCacheControlForNormalLoad);
125
toyoshime5aaf6a2016-05-18 08:07:48126 ReloadBlockUntilNavigationsComplete(shell(), 1);
Takashi Toyoshimabf698302017-05-31 13:23:05127 CheckCacheControl(kExpectedCacheControlForReload);
toyoshima27638a2016-12-06 10:20:47128
129 shell()->ShowDevTools();
130 ReloadBlockUntilNavigationsComplete(shell(), 1);
Takashi Toyoshimabf698302017-05-31 13:23:05131 CheckCacheControl(kExpectedCacheControlForReload);
toyoshima27638a2016-12-06 10:20:47132
133 shell()->CloseDevTools();
134 ReloadBlockUntilNavigationsComplete(shell(), 1);
Takashi Toyoshimabf698302017-05-31 13:23:05135 CheckCacheControl(kExpectedCacheControlForReload);
toyoshime5aaf6a2016-05-18 08:07:48136}
137
toyoshim4562d4a2017-03-16 04:09:02138// Test if bypassing reload issues requests with proper cache control flags.
toyoshime5aaf6a2016-05-18 08:07:48139IN_PROC_BROWSER_TEST_F(ReloadCacheControlBrowserTest, BypassingReload) {
140 GURL url(embedded_test_server()->GetURL(kReloadTestPath));
141
arthursonzognie7a44562017-05-11 19:06:46142 NavigateToURLBlockUntilNavigationsComplete(shell(), url, 1);
Takashi Toyoshimabf698302017-05-31 13:23:05143 CheckCacheControl(kExpectedCacheControlForNormalLoad);
arthursonzognie7a44562017-05-11 19:06:46144
145 ReloadBypassingCacheBlockUntilNavigationsComplete(shell(), 1);
Takashi Toyoshimabf698302017-05-31 13:23:05146 CheckCacheControl(kExpectedCacheControlForBypassingReload);
toyoshima27638a2016-12-06 10:20:47147
148 shell()->ShowDevTools();
149 ReloadBypassingCacheBlockUntilNavigationsComplete(shell(), 1);
Takashi Toyoshimabf698302017-05-31 13:23:05150 CheckCacheControl(kExpectedCacheControlForBypassingReload);
toyoshima27638a2016-12-06 10:20:47151
152 shell()->CloseDevTools();
153 ReloadBypassingCacheBlockUntilNavigationsComplete(shell(), 1);
Takashi Toyoshimabf698302017-05-31 13:23:05154 CheckCacheControl(kExpectedCacheControlForBypassingReload);
toyoshime5aaf6a2016-05-18 08:07:48155}
156
toyoshim4562d4a2017-03-16 04:09:02157// Test if the same page navigation issues requests with proper cache control
158// flags.
toyoshima27638a2016-12-06 10:20:47159IN_PROC_BROWSER_TEST_F(ReloadCacheControlBrowserTest, NavigateToSame) {
160 GURL url(embedded_test_server()->GetURL(kReloadTestPath));
161
toyoshima27638a2016-12-06 10:20:47162 // The first navigation is just a normal load.
Takashi Toyoshimabf698302017-05-31 13:23:05163 EXPECT_TRUE(NavigateToURL(shell(), url));
164 CheckCacheControl(kExpectedCacheControlForNormalLoad);
toyoshima27638a2016-12-06 10:20:47165
Liang Zhao0351d762024-11-13 00:10:07166 // The second navigation is the same page navigation from address bar. This
167 // should be handled as a replacement navigation, with normal load cache
168 // protocols. See https://github.com/whatwg/html/issues/10597 for spec
169 // discussion.
Takashi Toyoshimabf698302017-05-31 13:23:05170 EXPECT_TRUE(NavigateToURL(shell(), url));
Liang Zhao0351d762024-11-13 00:10:07171 CheckCacheControl(kExpectedCacheControlForNormalLoad);
toyoshima27638a2016-12-06 10:20:47172
173 shell()->ShowDevTools();
174 EXPECT_TRUE(NavigateToURL(shell(), url));
Liang Zhao0351d762024-11-13 00:10:07175 CheckCacheControl(kExpectedCacheControlForNormalLoad);
toyoshima27638a2016-12-06 10:20:47176
177 shell()->CloseDevTools();
178 EXPECT_TRUE(NavigateToURL(shell(), url));
Liang Zhao0351d762024-11-13 00:10:07179 CheckCacheControl(kExpectedCacheControlForNormalLoad);
toyoshima27638a2016-12-06 10:20:47180}
toyoshim8a956ec2016-05-19 07:24:36181
Makoto Shimazufd875022018-11-26 08:10:01182// Reloading with ReloadType::NORMAL should respect service workers.
183IN_PROC_BROWSER_TEST_F(ReloadCacheControlBrowserTest,
184 NormalReload_ControlledByServiceWorker) {
185 // Prepare for a service worker.
186 EXPECT_TRUE(NavigateToURL(shell(),
187 embedded_test_server()->GetURL(
188 "/service_worker/create_service_worker.html")));
189 EXPECT_EQ("DONE", EvalJs(shell(), "register('fetch_event_blob.js');"));
190
191 // Open a page served by the service worker.
192 EXPECT_TRUE(NavigateToURL(
193 shell(), embedded_test_server()->GetURL("/service_worker/empty.html")));
Jan Wilken Dörrie2c470ea2021-03-22 22:26:24194 EXPECT_EQ(u"Title", shell()->web_contents()->GetTitle());
Makoto Shimazufd875022018-11-26 08:10:01195
196 // Reload from the browser. The page is still controlled by the service
197 // worker.
198 ReloadBlockUntilNavigationsComplete(shell(), 1);
199 EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
Jan Wilken Dörrie2c470ea2021-03-22 22:26:24200 EXPECT_EQ(u"Title", shell()->web_contents()->GetTitle());
Makoto Shimazufd875022018-11-26 08:10:01201}
202
203// Reloading with ReloadType::BYPASSING_CACHE should bypass service workers.
204IN_PROC_BROWSER_TEST_F(ReloadCacheControlBrowserTest,
205 BypassingReload_ControlledByServiceWorker) {
206 // Prepare for a service worker.
207 EXPECT_TRUE(NavigateToURL(shell(),
208 embedded_test_server()->GetURL(
209 "/service_worker/create_service_worker.html")));
210 EXPECT_EQ("DONE", EvalJs(shell(), "register('fetch_event_blob.js');"));
211
212 // Open a page served by the service worker.
213 EXPECT_TRUE(NavigateToURL(
214 shell(), embedded_test_server()->GetURL("/service_worker/empty.html")));
Jan Wilken Dörrie2c470ea2021-03-22 22:26:24215 EXPECT_EQ(u"Title", shell()->web_contents()->GetTitle());
Makoto Shimazufd875022018-11-26 08:10:01216
217 // Reload from the browser with pressing shift key. It bypasses the service
218 // worker.
219 ReloadBypassingCacheBlockUntilNavigationsComplete(shell(), 1);
Jan Wilken Dörrie2c470ea2021-03-22 22:26:24220 EXPECT_EQ(u"ServiceWorker test - empty page",
Makoto Shimazufd875022018-11-26 08:10:01221 shell()->web_contents()->GetTitle());
222}
223
toyoshime5aaf6a2016-05-18 08:07:48224} // namespace
225
226} // namespace content