Avi Drissman | 4e1b7bc3 | 2022-09-15 14:03:50 | [diff] [blame] | 1 | // Copyright 2020 The Chromium Authors |
Hiroki Nakagawa | 968139e2 | 2020-10-22 15:03:56 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
Sreeja Kamishetty | c227f7a | 2022-07-08 22:33:15 | [diff] [blame] | 5 | #include "content/browser/preloading/prerender/prerender_host.h" |
kenoss | 3bd73b8 | 2024-10-10 20:33:49 | [diff] [blame] | 6 | |
Miina Koyama | d0e41f3 | 2023-11-13 06:50:09 | [diff] [blame] | 7 | #include <memory> |
Hiroki Nakagawa | 968139e2 | 2020-10-22 15:03:56 | [diff] [blame] | 8 | |
Lingqi Chi | 8098c5e9 | 2022-09-21 13:24:50 | [diff] [blame] | 9 | #include "base/functional/bind.h" |
Sean Maher | 52fa5a7 | 2022-11-14 15:53:25 | [diff] [blame] | 10 | #include "base/task/sequenced_task_runner.h" |
Lingqi Chi | 8098c5e9 | 2022-09-21 13:24:50 | [diff] [blame] | 11 | #include "base/test/bind.h" |
Miina Koyama | d0e41f3 | 2023-11-13 06:50:09 | [diff] [blame] | 12 | #include "base/test/gmock_expected_support.h" |
Robert Lin | 1ae4056 | 2021-09-17 02:48:01 | [diff] [blame] | 13 | #include "build/build_config.h" |
Asami Doi | 2dfb267 | 2022-02-21 10:45:52 | [diff] [blame] | 14 | #include "components/ukm/test_ukm_recorder.h" |
kenoss | c3f9a2c | 2025-03-06 15:35:51 | [diff] [blame] | 15 | #include "content/browser/preloading/preload_pipeline_info_impl.h" |
Lingqi Chi | 8098c5e9 | 2022-09-21 13:24:50 | [diff] [blame] | 16 | #include "content/browser/preloading/preloading.h" |
Sreeja Kamishetty | c227f7a | 2022-07-08 22:33:15 | [diff] [blame] | 17 | #include "content/browser/preloading/prerender/prerender_attributes.h" |
Yoshiki Tanioka | 49b4cfb | 2022-10-20 09:25:31 | [diff] [blame] | 18 | #include "content/browser/preloading/prerender/prerender_final_status.h" |
Miina Koyama | d0e41f3 | 2023-11-13 06:50:09 | [diff] [blame] | 19 | #include "content/browser/preloading/prerender/prerender_host.h" |
Sreeja Kamishetty | c227f7a | 2022-07-08 22:33:15 | [diff] [blame] | 20 | #include "content/browser/preloading/prerender/prerender_host_registry.h" |
Miina Koyama | d0e41f3 | 2023-11-13 06:50:09 | [diff] [blame] | 21 | #include "content/browser/preloading/prerender/prerender_metrics.h" |
kenoss | c3f9a2c | 2025-03-06 15:35:51 | [diff] [blame] | 22 | #include "content/public/browser/preload_pipeline_info.h" |
Lingqi Chi | 8098c5e9 | 2022-09-21 13:24:50 | [diff] [blame] | 23 | #include "content/public/browser/preloading.h" |
| 24 | #include "content/public/browser/preloading_data.h" |
Sreeja Kamishetty | 0be3b1b | 2021-08-12 17:04:15 | [diff] [blame] | 25 | #include "content/public/test/mock_web_contents_observer.h" |
Matt Falkenhagen | 37d91a916 | 2021-01-08 08:13:28 | [diff] [blame] | 26 | #include "content/public/test/navigation_simulator.h" |
Sreeja Kamishetty | 26e40d2 | 2022-10-17 17:54:35 | [diff] [blame] | 27 | #include "content/public/test/preloading_test_util.h" |
Takashi Toyoshima | 9c8b08c | 2022-05-17 10:11:33 | [diff] [blame] | 28 | #include "content/public/test/prerender_test_util.h" |
Hiroki Nakagawa | 6c5f39bd | 2021-07-13 00:22:36 | [diff] [blame] | 29 | #include "content/test/mock_commit_deferring_condition.h" |
Harkiran Bolaria | 59290d6 | 2021-03-17 01:53:01 | [diff] [blame] | 30 | #include "content/test/navigation_simulator_impl.h" |
Lingqi Chi | 82efa95e | 2020-12-29 05:31:19 | [diff] [blame] | 31 | #include "content/test/test_render_frame_host.h" |
Hiroki Nakagawa | 968139e2 | 2020-10-22 15:03:56 | [diff] [blame] | 32 | #include "content/test/test_render_view_host.h" |
| 33 | #include "content/test/test_web_contents.h" |
Miina Koyama | d0e41f3 | 2023-11-13 06:50:09 | [diff] [blame] | 34 | #include "net/http/http_request_headers.h" |
Asami Doi | 2dfb267 | 2022-02-21 10:45:52 | [diff] [blame] | 35 | #include "services/metrics/public/cpp/ukm_builders.h" |
Sreeja Kamishetty | 0be3b1b | 2021-08-12 17:04:15 | [diff] [blame] | 36 | #include "third_party/blink/public/common/loader/loader_constants.h" |
Taiyo Mizuhashi | a19f037d | 2023-07-28 06:39:43 | [diff] [blame] | 37 | #include "third_party/blink/public/mojom/speculation_rules/speculation_rules.mojom-shared.h" |
Hiroki Nakagawa | 968139e2 | 2020-10-22 15:03:56 | [diff] [blame] | 38 | |
| 39 | namespace content { |
| 40 | namespace { |
| 41 | |
Sreeja Kamishetty | 0be3b1b | 2021-08-12 17:04:15 | [diff] [blame] | 42 | using ::testing::_; |
lingqi | 5e583f1f | 2023-05-14 06:16:40 | [diff] [blame] | 43 | |
| 44 | TEST(IsActivationHeaderMatchTest, OrderInsensitive) { |
Miina Koyama | d0e41f3 | 2023-11-13 06:50:09 | [diff] [blame] | 45 | PrerenderCancellationReason reason = PrerenderCancellationReason( |
| 46 | PrerenderFinalStatus::kActivationNavigationParameterMismatch); |
lingqi | 5e583f1f | 2023-05-14 06:16:40 | [diff] [blame] | 47 | net::HttpRequestHeaders prerender_headers; |
Doug Turner | b204399e | 2025-07-30 16:51:16 | [diff] [blame] | 48 | prerender_headers.SetHeader("name1", "value1"); |
| 49 | prerender_headers.SetHeader("name2", "value2"); |
| 50 | prerender_headers.SetHeader("name3", "value3"); |
lingqi | 5e583f1f | 2023-05-14 06:16:40 | [diff] [blame] | 51 | net::HttpRequestHeaders potential_activation_headers; |
Doug Turner | b204399e | 2025-07-30 16:51:16 | [diff] [blame] | 52 | potential_activation_headers.SetHeader("name2", "value2"); |
| 53 | potential_activation_headers.SetHeader("name3", "value3"); |
| 54 | potential_activation_headers.SetHeader("name1", "value1"); |
lingqi | 5e583f1f | 2023-05-14 06:16:40 | [diff] [blame] | 55 | EXPECT_TRUE(PrerenderHost::IsActivationHeaderMatch( |
Miina Koyama | d0e41f3 | 2023-11-13 06:50:09 | [diff] [blame] | 56 | potential_activation_headers, prerender_headers, reason)); |
lingqi | 5e583f1f | 2023-05-14 06:16:40 | [diff] [blame] | 57 | } |
| 58 | |
| 59 | TEST(IsActivationHeaderMatchTest, KeyCaseInsensitive) { |
Miina Koyama | d0e41f3 | 2023-11-13 06:50:09 | [diff] [blame] | 60 | PrerenderCancellationReason reason = PrerenderCancellationReason( |
| 61 | PrerenderFinalStatus::kActivationNavigationParameterMismatch); |
lingqi | 5e583f1f | 2023-05-14 06:16:40 | [diff] [blame] | 62 | net::HttpRequestHeaders prerender_headers; |
Doug Turner | b204399e | 2025-07-30 16:51:16 | [diff] [blame] | 63 | prerender_headers.SetHeader("NAME1", "value1"); |
| 64 | prerender_headers.SetHeader("name2", "value2"); |
| 65 | prerender_headers.SetHeader("name3", "value3"); |
lingqi | 5e583f1f | 2023-05-14 06:16:40 | [diff] [blame] | 66 | net::HttpRequestHeaders potential_activation_headers; |
Doug Turner | b204399e | 2025-07-30 16:51:16 | [diff] [blame] | 67 | potential_activation_headers.SetHeader("name1", "value1"); |
| 68 | potential_activation_headers.SetHeader("name2", "value2"); |
| 69 | potential_activation_headers.SetHeader("name3", "value3"); |
lingqi | 5e583f1f | 2023-05-14 06:16:40 | [diff] [blame] | 70 | EXPECT_TRUE(PrerenderHost::IsActivationHeaderMatch( |
Miina Koyama | d0e41f3 | 2023-11-13 06:50:09 | [diff] [blame] | 71 | potential_activation_headers, prerender_headers, reason)); |
lingqi | 5e583f1f | 2023-05-14 06:16:40 | [diff] [blame] | 72 | } |
| 73 | |
| 74 | TEST(IsActivationHeaderMatchTest, ValueCaseInsensitive) { |
Miina Koyama | d0e41f3 | 2023-11-13 06:50:09 | [diff] [blame] | 75 | PrerenderCancellationReason reason = PrerenderCancellationReason( |
| 76 | PrerenderFinalStatus::kActivationNavigationParameterMismatch); |
lingqi | 5e583f1f | 2023-05-14 06:16:40 | [diff] [blame] | 77 | net::HttpRequestHeaders prerender_headers; |
Doug Turner | b204399e | 2025-07-30 16:51:16 | [diff] [blame] | 78 | prerender_headers.SetHeader("name1", "value1"); |
| 79 | prerender_headers.SetHeader("name2", "value2"); |
| 80 | prerender_headers.SetHeader("name3", "value3"); |
lingqi | 5e583f1f | 2023-05-14 06:16:40 | [diff] [blame] | 81 | net::HttpRequestHeaders potential_activation_headers; |
Doug Turner | b204399e | 2025-07-30 16:51:16 | [diff] [blame] | 82 | potential_activation_headers.SetHeader("name1", "value1"); |
| 83 | potential_activation_headers.SetHeader("name2", "VALUE2"); |
| 84 | potential_activation_headers.SetHeader("name3", "value3"); |
lingqi | 5e583f1f | 2023-05-14 06:16:40 | [diff] [blame] | 85 | EXPECT_TRUE(PrerenderHost::IsActivationHeaderMatch( |
Miina Koyama | d0e41f3 | 2023-11-13 06:50:09 | [diff] [blame] | 86 | potential_activation_headers, prerender_headers, reason)); |
| 87 | } |
| 88 | |
| 89 | TEST(IsActivationHeaderMatchTest, CalculateMismatchedHeaders) { |
| 90 | auto same_key_value = [](const PrerenderMismatchedHeaders& a, |
| 91 | const PrerenderMismatchedHeaders& b) { |
| 92 | return a.header_name == b.header_name && |
| 93 | a.initial_value == b.initial_value && |
| 94 | a.activation_value == b.activation_value; |
| 95 | }; |
| 96 | { |
| 97 | PrerenderCancellationReason reason = PrerenderCancellationReason( |
| 98 | PrerenderFinalStatus::kActivationNavigationParameterMismatch); |
| 99 | net::HttpRequestHeaders prerender_headers; |
Doug Turner | b204399e | 2025-07-30 16:51:16 | [diff] [blame] | 100 | prerender_headers.SetHeader("name1", "value1"); |
| 101 | prerender_headers.SetHeader("name2", "value2"); |
| 102 | prerender_headers.SetHeader("name3", "value3"); |
Miina Koyama | d0e41f3 | 2023-11-13 06:50:09 | [diff] [blame] | 103 | net::HttpRequestHeaders potential_headers; |
Doug Turner | b204399e | 2025-07-30 16:51:16 | [diff] [blame] | 104 | potential_headers.SetHeader("name1", "value1"); |
| 105 | potential_headers.SetHeader("name2", "value2"); |
| 106 | potential_headers.SetHeader("name3", "value3"); |
Miina Koyama | d0e41f3 | 2023-11-13 06:50:09 | [diff] [blame] | 107 | EXPECT_TRUE(PrerenderHost::IsActivationHeaderMatch( |
| 108 | potential_headers, prerender_headers, reason)); |
| 109 | EXPECT_FALSE(reason.GetPrerenderMismatchedHeaders()); |
| 110 | } |
| 111 | { |
| 112 | PrerenderCancellationReason reason = PrerenderCancellationReason( |
| 113 | PrerenderFinalStatus::kActivationNavigationParameterMismatch); |
| 114 | net::HttpRequestHeaders prerender_headers; |
Miina Koyama | d0e41f3 | 2023-11-13 06:50:09 | [diff] [blame] | 115 | net::HttpRequestHeaders potential_headers; |
Miina Koyama | d0e41f3 | 2023-11-13 06:50:09 | [diff] [blame] | 116 | EXPECT_TRUE(PrerenderHost::IsActivationHeaderMatch( |
| 117 | potential_headers, prerender_headers, reason)); |
| 118 | EXPECT_FALSE(reason.GetPrerenderMismatchedHeaders()); |
| 119 | } |
| 120 | { |
| 121 | PrerenderCancellationReason reason = PrerenderCancellationReason( |
| 122 | PrerenderFinalStatus::kActivationNavigationParameterMismatch); |
| 123 | net::HttpRequestHeaders prerender_headers; |
Doug Turner | b204399e | 2025-07-30 16:51:16 | [diff] [blame] | 124 | prerender_headers.SetHeader("name1", "value1"); |
| 125 | prerender_headers.SetHeader("name2", "value2"); |
| 126 | prerender_headers.SetHeader("name3", "value3"); |
| 127 | prerender_headers.SetHeader("name5", "value3"); |
Miina Koyama | d0e41f3 | 2023-11-13 06:50:09 | [diff] [blame] | 128 | net::HttpRequestHeaders potential_headers; |
Doug Turner | b204399e | 2025-07-30 16:51:16 | [diff] [blame] | 129 | potential_headers.SetHeader("name1", "value1"); |
| 130 | potential_headers.SetHeader("name3", "value2"); |
| 131 | potential_headers.SetHeader("name4", "value4"); |
| 132 | potential_headers.SetHeader("name5", "value3"); |
Miina Koyama | d0e41f3 | 2023-11-13 06:50:09 | [diff] [blame] | 133 | EXPECT_FALSE(PrerenderHost::IsActivationHeaderMatch( |
| 134 | potential_headers, prerender_headers, reason)); |
| 135 | std::vector<PrerenderMismatchedHeaders> mismatched_headers_expected; |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 136 | mismatched_headers_expected.emplace_back("name2", "value2", std::nullopt); |
Miina Koyama | d0e41f3 | 2023-11-13 06:50:09 | [diff] [blame] | 137 | mismatched_headers_expected.emplace_back("name3", "value3", "value2"); |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 138 | mismatched_headers_expected.emplace_back("name4", std::nullopt, "value4"); |
Miina Koyama | d0e41f3 | 2023-11-13 06:50:09 | [diff] [blame] | 139 | |
| 140 | EXPECT_TRUE(std::equal(reason.GetPrerenderMismatchedHeaders()->begin(), |
| 141 | reason.GetPrerenderMismatchedHeaders()->end(), |
| 142 | mismatched_headers_expected.begin(), |
| 143 | mismatched_headers_expected.end(), same_key_value)); |
| 144 | } |
| 145 | { |
| 146 | PrerenderCancellationReason reason = PrerenderCancellationReason( |
| 147 | PrerenderFinalStatus::kActivationNavigationParameterMismatch); |
| 148 | net::HttpRequestHeaders prerender_headers; |
Doug Turner | b204399e | 2025-07-30 16:51:16 | [diff] [blame] | 149 | prerender_headers.SetHeader("name5", "value1"); |
| 150 | prerender_headers.SetHeader("name6", "value2"); |
| 151 | prerender_headers.SetHeader("name7", "value3"); |
Miina Koyama | d0e41f3 | 2023-11-13 06:50:09 | [diff] [blame] | 152 | net::HttpRequestHeaders potential_headers; |
Doug Turner | b204399e | 2025-07-30 16:51:16 | [diff] [blame] | 153 | potential_headers.SetHeader("name2", "value1"); |
Miina Koyama | d0e41f3 | 2023-11-13 06:50:09 | [diff] [blame] | 154 | EXPECT_FALSE(PrerenderHost::IsActivationHeaderMatch( |
| 155 | potential_headers, prerender_headers, reason)); |
| 156 | std::vector<PrerenderMismatchedHeaders> mismatched_headers_expected; |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 157 | mismatched_headers_expected.emplace_back("name2", std::nullopt, "value1"); |
| 158 | mismatched_headers_expected.emplace_back("name5", "value1", std::nullopt); |
| 159 | mismatched_headers_expected.emplace_back("name6", "value2", std::nullopt); |
| 160 | mismatched_headers_expected.emplace_back("name7", "value3", std::nullopt); |
Miina Koyama | d0e41f3 | 2023-11-13 06:50:09 | [diff] [blame] | 161 | |
| 162 | EXPECT_TRUE(std::equal(reason.GetPrerenderMismatchedHeaders()->begin(), |
| 163 | reason.GetPrerenderMismatchedHeaders()->end(), |
| 164 | mismatched_headers_expected.begin(), |
| 165 | mismatched_headers_expected.end(), same_key_value)); |
| 166 | } |
| 167 | { |
| 168 | PrerenderCancellationReason reason = PrerenderCancellationReason( |
| 169 | PrerenderFinalStatus::kActivationNavigationParameterMismatch); |
| 170 | net::HttpRequestHeaders prerender_headers; |
Doug Turner | b204399e | 2025-07-30 16:51:16 | [diff] [blame] | 171 | prerender_headers.SetHeader("name5", "value1"); |
| 172 | prerender_headers.SetHeader("name6", "value2"); |
Miina Koyama | d0e41f3 | 2023-11-13 06:50:09 | [diff] [blame] | 173 | net::HttpRequestHeaders potential_headers; |
Doug Turner | b204399e | 2025-07-30 16:51:16 | [diff] [blame] | 174 | potential_headers.SetHeader("name2", "value1"); |
| 175 | potential_headers.SetHeader("name6", "value2"); |
| 176 | potential_headers.SetHeader("name7", "value3"); |
| 177 | potential_headers.SetHeader("name8", "value3"); |
Miina Koyama | d0e41f3 | 2023-11-13 06:50:09 | [diff] [blame] | 178 | EXPECT_FALSE(PrerenderHost::IsActivationHeaderMatch( |
| 179 | potential_headers, prerender_headers, reason)); |
| 180 | std::vector<PrerenderMismatchedHeaders> mismatched_headers_expected; |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 181 | mismatched_headers_expected.emplace_back("name2", std::nullopt, "value1"); |
| 182 | mismatched_headers_expected.emplace_back("name5", "value1", std::nullopt); |
| 183 | mismatched_headers_expected.emplace_back("name7", std::nullopt, "value3"); |
| 184 | mismatched_headers_expected.emplace_back("name8", std::nullopt, "value3"); |
Miina Koyama | d0e41f3 | 2023-11-13 06:50:09 | [diff] [blame] | 185 | |
| 186 | EXPECT_TRUE(std::equal(reason.GetPrerenderMismatchedHeaders()->begin(), |
| 187 | reason.GetPrerenderMismatchedHeaders()->end(), |
| 188 | mismatched_headers_expected.begin(), |
| 189 | mismatched_headers_expected.end(), same_key_value)); |
| 190 | } |
| 191 | { |
| 192 | PrerenderCancellationReason reason = PrerenderCancellationReason( |
| 193 | PrerenderFinalStatus::kActivationNavigationParameterMismatch); |
| 194 | net::HttpRequestHeaders prerender_headers; |
Miina Koyama | d0e41f3 | 2023-11-13 06:50:09 | [diff] [blame] | 195 | net::HttpRequestHeaders potential_headers; |
Doug Turner | b204399e | 2025-07-30 16:51:16 | [diff] [blame] | 196 | potential_headers.SetHeader("name1", "value1"); |
| 197 | potential_headers.SetHeader("name2", "value2"); |
| 198 | potential_headers.SetHeader("name3", "value3"); |
Miina Koyama | d0e41f3 | 2023-11-13 06:50:09 | [diff] [blame] | 199 | EXPECT_FALSE(PrerenderHost::IsActivationHeaderMatch( |
| 200 | potential_headers, prerender_headers, reason)); |
| 201 | std::vector<PrerenderMismatchedHeaders> mismatched_headers_expected; |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 202 | mismatched_headers_expected.emplace_back("name1", std::nullopt, "value1"); |
| 203 | mismatched_headers_expected.emplace_back("name2", std::nullopt, "value2"); |
| 204 | mismatched_headers_expected.emplace_back("name3", std::nullopt, "value3"); |
Miina Koyama | d0e41f3 | 2023-11-13 06:50:09 | [diff] [blame] | 205 | |
| 206 | EXPECT_TRUE(std::equal(reason.GetPrerenderMismatchedHeaders()->begin(), |
| 207 | reason.GetPrerenderMismatchedHeaders()->end(), |
| 208 | mismatched_headers_expected.begin(), |
| 209 | mismatched_headers_expected.end(), same_key_value)); |
| 210 | } |
| 211 | { |
| 212 | PrerenderCancellationReason reason = PrerenderCancellationReason( |
| 213 | PrerenderFinalStatus::kActivationNavigationParameterMismatch); |
| 214 | net::HttpRequestHeaders prerender_headers; |
Doug Turner | b204399e | 2025-07-30 16:51:16 | [diff] [blame] | 215 | prerender_headers.SetHeader("name1", "value1"); |
| 216 | prerender_headers.SetHeader("name2", "value2"); |
| 217 | prerender_headers.SetHeader("name3", "value3"); |
Miina Koyama | d0e41f3 | 2023-11-13 06:50:09 | [diff] [blame] | 218 | net::HttpRequestHeaders potential_headers; |
Miina Koyama | d0e41f3 | 2023-11-13 06:50:09 | [diff] [blame] | 219 | EXPECT_FALSE(PrerenderHost::IsActivationHeaderMatch( |
| 220 | potential_headers, prerender_headers, reason)); |
| 221 | std::vector<PrerenderMismatchedHeaders> mismatched_headers_expected; |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 222 | mismatched_headers_expected.emplace_back("name1", "value1", std::nullopt); |
| 223 | mismatched_headers_expected.emplace_back("name2", "value2", std::nullopt); |
| 224 | mismatched_headers_expected.emplace_back("name3", "value3", std::nullopt); |
Miina Koyama | d0e41f3 | 2023-11-13 06:50:09 | [diff] [blame] | 225 | |
| 226 | EXPECT_TRUE(std::equal(reason.GetPrerenderMismatchedHeaders()->begin(), |
| 227 | reason.GetPrerenderMismatchedHeaders()->end(), |
| 228 | mismatched_headers_expected.begin(), |
| 229 | mismatched_headers_expected.end(), same_key_value)); |
| 230 | } |
lingqi | 5e583f1f | 2023-05-14 06:16:40 | [diff] [blame] | 231 | } |
| 232 | |
Lingqi Chi | 8098c5e9 | 2022-09-21 13:24:50 | [diff] [blame] | 233 | using ExpectedReadyForActivationState = |
| 234 | base::StrongAlias<class ExpectedReadyForActivationStateType, bool>; |
Sreeja Kamishetty | 0be3b1b | 2021-08-12 17:04:15 | [diff] [blame] | 235 | |
Matt Falkenhagen | 21ee4f8 | 2021-04-13 08:14:28 | [diff] [blame] | 236 | // Finish a prerendering navigation that was already started with |
| 237 | // CreateAndStartHost(). |
Lingqi Chi | 8098c5e9 | 2022-09-21 13:24:50 | [diff] [blame] | 238 | void CommitPrerenderNavigation( |
| 239 | PrerenderHost& host, |
| 240 | ExpectedReadyForActivationState ready_for_activation = |
Liviu Tinta | 0fcb2902 | 2024-03-14 14:03:56 | [diff] [blame] | 241 | ExpectedReadyForActivationState(true), |
| 242 | scoped_refptr<net::HttpResponseHeaders> headers = nullptr) { |
Matt Falkenhagen | 21ee4f8 | 2021-04-13 08:14:28 | [diff] [blame] | 243 | // Normally we could use EmbeddedTestServer to provide a response, but these |
| 244 | // tests use RenderViewHostImplTestHarness so the load goes through a |
| 245 | // TestNavigationURLLoader which we don't have access to in order to |
| 246 | // complete. Use NavigationSimulator to finish the navigation. |
| 247 | FrameTreeNode* ftn = FrameTreeNode::From(host.GetPrerenderedMainFrameHost()); |
| 248 | std::unique_ptr<NavigationSimulator> sim = |
| 249 | NavigationSimulatorImpl::CreateFromPendingInFrame(ftn); |
Liviu Tinta | 0fcb2902 | 2024-03-14 14:03:56 | [diff] [blame] | 250 | sim->SetResponseHeaders(headers); |
Matt Falkenhagen | 21ee4f8 | 2021-04-13 08:14:28 | [diff] [blame] | 251 | sim->Commit(); |
Lingqi Chi | 8098c5e9 | 2022-09-21 13:24:50 | [diff] [blame] | 252 | EXPECT_EQ(host.is_ready_for_activation(), ready_for_activation.value()); |
Matt Falkenhagen | 21ee4f8 | 2021-04-13 08:14:28 | [diff] [blame] | 253 | } |
| 254 | |
Harkiran Bolaria | 2fb0e0e | 2021-08-09 19:13:52 | [diff] [blame] | 255 | std::unique_ptr<NavigationSimulatorImpl> CreateActivation( |
| 256 | const GURL& prerendering_url, |
| 257 | WebContentsImpl& web_contents) { |
| 258 | std::unique_ptr<NavigationSimulatorImpl> navigation = |
| 259 | NavigationSimulatorImpl::CreateRendererInitiated( |
Dave Tapuska | 327c06c9 | 2022-06-13 20:31:51 | [diff] [blame] | 260 | prerendering_url, web_contents.GetPrimaryMainFrame()); |
Harkiran Bolaria | 2fb0e0e | 2021-08-09 19:13:52 | [diff] [blame] | 261 | navigation->SetReferrer(blink::mojom::Referrer::New( |
Dave Tapuska | 327c06c9 | 2022-06-13 20:31:51 | [diff] [blame] | 262 | web_contents.GetPrimaryMainFrame()->GetLastCommittedURL(), |
Harkiran Bolaria | 2fb0e0e | 2021-08-09 19:13:52 | [diff] [blame] | 263 | network::mojom::ReferrerPolicy::kStrictOriginWhenCrossOrigin)); |
| 264 | return navigation; |
| 265 | } |
| 266 | |
Hiroki Nakagawa | 0a90bd4 | 2021-04-21 01:53:05 | [diff] [blame] | 267 | class PrerenderHostTest : public RenderViewHostImplTestHarness { |
Hiroki Nakagawa | 968139e2 | 2020-10-22 15:03:56 | [diff] [blame] | 268 | public: |
Asami Doi | 3965173 | 2023-01-31 05:25:26 | [diff] [blame] | 269 | ~PrerenderHostTest() override = default; |
Hiroki Nakagawa | 968139e2 | 2020-10-22 15:03:56 | [diff] [blame] | 270 | |
| 271 | void SetUp() override { |
Hiroki Nakagawa | 968139e2 | 2020-10-22 15:03:56 | [diff] [blame] | 272 | RenderViewHostImplTestHarness::SetUp(); |
Johann | becce08 | 2023-01-17 05:14:32 | [diff] [blame] | 273 | web_contents_delegate_ = |
| 274 | std::make_unique<test::ScopedPrerenderWebContentsDelegate>(*contents()); |
Hiroki Nakagawa | e72cf55c | 2022-11-30 05:58:14 | [diff] [blame] | 275 | contents()->NavigateAndCommit(GURL("https://example.com")); |
Hiroki Nakagawa | 968139e2 | 2020-10-22 15:03:56 | [diff] [blame] | 276 | } |
| 277 | |
Hiroki Nakagawa | e72cf55c | 2022-11-30 05:58:14 | [diff] [blame] | 278 | PrerenderAttributes GeneratePrerenderAttributes(const GURL& url) { |
Arthur Sonzogni | fd1e08d | 2024-03-05 15:59:36 | [diff] [blame] | 279 | return GeneratePrerenderAttributesWithPredicate(url, |
| 280 | /*url_match_predicate=*/{}); |
Hiroki Nakagawa | e72cf55c | 2022-11-30 05:58:14 | [diff] [blame] | 281 | } |
| 282 | |
| 283 | PrerenderAttributes GeneratePrerenderAttributesWithPredicate( |
| 284 | const GURL& url, |
Liviu Tinta | cf066d5 | 2024-07-24 16:00:55 | [diff] [blame] | 285 | base::RepeatingCallback<bool(const GURL&, |
| 286 | const std::optional<content::UrlMatchType>&)> |
| 287 | url_match_predicate) { |
Hiroki Nakagawa | e72cf55c | 2022-11-30 05:58:14 | [diff] [blame] | 288 | RenderFrameHostImpl* rfh = contents()->GetPrimaryMainFrame(); |
| 289 | return PrerenderAttributes( |
Kouhei Ueno | 3f37992b | 2023-11-09 23:29:02 | [diff] [blame] | 290 | url, PreloadingTriggerType::kSpeculationRule, |
Hiroki Nakagawa | eeecc56e | 2025-03-27 02:57:30 | [diff] [blame] | 291 | /*embedder_histogram_suffix=*/"", SpeculationRulesParams(), Referrer(), |
Rulong Chen(陈汝龙) | bf12169c | 2024-12-16 05:38:16 | [diff] [blame] | 292 | /*no_vary_search_hint=*/std::nullopt, rfh, contents()->GetWeakPtr(), |
Lingqi Chi | 8ebe71e | 2024-10-22 07:08:39 | [diff] [blame] | 293 | ui::PAGE_TRANSITION_LINK, |
Lingqi Chi | a2efa8c | 2024-11-08 10:20:29 | [diff] [blame] | 294 | /*should_warm_up_compositor=*/false, |
Lingqi Chi | bc88ab5 | 2025-07-24 00:54:14 | [diff] [blame] | 295 | /*should_prepare_paint_tree=*/false, |
| 296 | /*should_pause_javascript_execution=*/false, |
| 297 | std::move(url_match_predicate), |
kenoss | 3bd73b8 | 2024-10-10 20:33:49 | [diff] [blame] | 298 | /*prerender_navigation_handle_callback=*/{}, |
kenoss | c3f9a2c | 2025-03-06 15:35:51 | [diff] [blame] | 299 | PreloadPipelineInfoImpl::Create( |
Jiacheng Guo | ea20d39 | 2025-07-07 01:08:14 | [diff] [blame] | 300 | /*planned_max_preloading_type=*/PreloadingType::kPrerender), |
| 301 | /*allow_reuse=*/false); |
Hiroki Nakagawa | 968139e2 | 2020-10-22 15:03:56 | [diff] [blame] | 302 | } |
| 303 | |
Yoshiki Tanioka | 49b4cfb | 2022-10-20 09:25:31 | [diff] [blame] | 304 | void ExpectFinalStatus(PrerenderFinalStatus status) { |
Asami Doi | 2dfb267 | 2022-02-21 10:45:52 | [diff] [blame] | 305 | // Check FinalStatus in UMA. |
Matt Falkenhagen | 9c56f5a0 | 2021-01-23 04:51:49 | [diff] [blame] | 306 | histogram_tester_.ExpectUniqueSample( |
Asami Doi | 4584b3b | 2021-12-13 04:17:14 | [diff] [blame] | 307 | "Prerender.Experimental.PrerenderHostFinalStatus.SpeculationRule", |
| 308 | status, 1); |
Asami Doi | 2dfb267 | 2022-02-21 10:45:52 | [diff] [blame] | 309 | |
| 310 | // Check all entries in UKM to make sure that the recorded FinalStatus is |
| 311 | // equal to `status`. At least one entry should exist. |
| 312 | bool final_status_entry_found = false; |
| 313 | const auto entries = ukm_recorder_.GetEntriesByName( |
| 314 | ukm::builders::PrerenderPageLoad::kEntryName); |
Ali Hijazi | e63cbaf6 | 2023-12-20 19:29:35 | [diff] [blame] | 315 | for (const ukm::mojom::UkmEntry* entry : entries) { |
Asami Doi | 2dfb267 | 2022-02-21 10:45:52 | [diff] [blame] | 316 | if (ukm_recorder_.EntryHasMetric( |
| 317 | entry, ukm::builders::PrerenderPageLoad::kFinalStatusName)) { |
| 318 | final_status_entry_found = true; |
| 319 | ukm_recorder_.ExpectEntryMetric( |
| 320 | entry, ukm::builders::PrerenderPageLoad::kFinalStatusName, |
| 321 | static_cast<int>(status)); |
| 322 | } |
| 323 | } |
| 324 | |
| 325 | EXPECT_TRUE(final_status_entry_found); |
Matt Falkenhagen | 9c56f5a0 | 2021-01-23 04:51:49 | [diff] [blame] | 326 | } |
| 327 | |
Hiroki Nakagawa | e72cf55c | 2022-11-30 05:58:14 | [diff] [blame] | 328 | PrerenderHostRegistry& registry() { |
| 329 | return *contents()->GetPrerenderHostRegistry(); |
Hiroki Nakagawa | 968139e2 | 2020-10-22 15:03:56 | [diff] [blame] | 330 | } |
| 331 | |
| 332 | private: |
Johann | a4bf1cd | 2022-11-30 23:59:39 | [diff] [blame] | 333 | test::ScopedPrerenderFeatureList prerender_feature_list_; |
Johann | becce08 | 2023-01-17 05:14:32 | [diff] [blame] | 334 | std::unique_ptr<test::ScopedPrerenderWebContentsDelegate> |
| 335 | web_contents_delegate_; |
Matt Falkenhagen | 9c56f5a0 | 2021-01-23 04:51:49 | [diff] [blame] | 336 | base::HistogramTester histogram_tester_; |
Asami Doi | 2dfb267 | 2022-02-21 10:45:52 | [diff] [blame] | 337 | ukm::TestAutoSetUkmRecorder ukm_recorder_; |
Hiroki Nakagawa | 968139e2 | 2020-10-22 15:03:56 | [diff] [blame] | 338 | }; |
| 339 | |
Hiroki Nakagawa | d176addb | 2025-03-07 07:04:15 | [diff] [blame] | 340 | TEST_F(PrerenderHostTest, IsNoVarySearchHeaderSet) { |
Liviu Tinta | 0fcb2902 | 2024-03-14 14:03:56 | [diff] [blame] | 341 | // Start prerendering a page. |
| 342 | const GURL kPrerenderingUrl("https://example.com/next"); |
Avi Drissman | dcc8e68 | 2024-09-04 14:14:48 | [diff] [blame] | 343 | FrameTreeNodeId prerender_frame_tree_node_id = |
| 344 | contents()->AddPrerender(kPrerenderingUrl); |
Liviu Tinta | 0fcb2902 | 2024-03-14 14:03:56 | [diff] [blame] | 345 | PrerenderHost* prerender_host = |
| 346 | registry().FindNonReservedHostById(prerender_frame_tree_node_id); |
| 347 | CommitPrerenderNavigation( |
| 348 | *prerender_host, ExpectedReadyForActivationState(true), |
| 349 | net::HttpResponseHeaders::Builder(net::HttpVersion(1, 1), "200 OK") |
| 350 | .AddHeader("No-Vary-Search", "params=(\"a\")") |
| 351 | .Build()); |
Hiroki Nakagawa | d176addb | 2025-03-07 07:04:15 | [diff] [blame] | 352 | EXPECT_TRUE(prerender_host->no_vary_search().has_value()); |
Liviu Tinta | 0fcb2902 | 2024-03-14 14:03:56 | [diff] [blame] | 353 | } |
| 354 | |
Hiroki Nakagawa | 0a90bd4 | 2021-04-21 01:53:05 | [diff] [blame] | 355 | TEST_F(PrerenderHostTest, Activate) { |
Matt Falkenhagen | 98b8373 | 2021-03-23 00:40:16 | [diff] [blame] | 356 | // Start prerendering a page. |
Hiroki Nakagawa | 968139e2 | 2020-10-22 15:03:56 | [diff] [blame] | 357 | const GURL kPrerenderingUrl("https://example.com/next"); |
Avi Drissman | dcc8e68 | 2024-09-04 14:14:48 | [diff] [blame] | 358 | FrameTreeNodeId prerender_frame_tree_node_id = |
| 359 | contents()->AddPrerender(kPrerenderingUrl); |
Hiroki Nakagawa | 9ba6669 | 2021-03-09 07:26:55 | [diff] [blame] | 360 | PrerenderHost* prerender_host = |
Hiroki Nakagawa | e72cf55c | 2022-11-30 05:58:14 | [diff] [blame] | 361 | registry().FindNonReservedHostById(prerender_frame_tree_node_id); |
Matt Falkenhagen | 21ee4f8 | 2021-04-13 08:14:28 | [diff] [blame] | 362 | CommitPrerenderNavigation(*prerender_host); |
Hiroki Nakagawa | 968139e2 | 2020-10-22 15:03:56 | [diff] [blame] | 363 | |
Matt Falkenhagen | 98b8373 | 2021-03-23 00:40:16 | [diff] [blame] | 364 | // Perform a navigation in the primary frame tree which activates the |
| 365 | // prerendered page. |
Hiroki Nakagawa | e72cf55c | 2022-11-30 05:58:14 | [diff] [blame] | 366 | contents()->ActivatePrerenderedPage(kPrerenderingUrl); |
Yoshiki Tanioka | 49b4cfb | 2022-10-20 09:25:31 | [diff] [blame] | 367 | ExpectFinalStatus(PrerenderFinalStatus::kActivated); |
Matt Falkenhagen | 9c56f5a0 | 2021-01-23 04:51:49 | [diff] [blame] | 368 | } |
| 369 | |
Hiroki Nakagawa | 0a90bd4 | 2021-04-21 01:53:05 | [diff] [blame] | 370 | TEST_F(PrerenderHostTest, DontActivate) { |
Matt Falkenhagen | 9c56f5a0 | 2021-01-23 04:51:49 | [diff] [blame] | 371 | // Start the prerendering navigation, but don't activate it. |
Hiroki Nakagawa | e72cf55c | 2022-11-30 05:58:14 | [diff] [blame] | 372 | const GURL kPrerenderingUrl("https://example.com/next"); |
Avi Drissman | dcc8e68 | 2024-09-04 14:14:48 | [diff] [blame] | 373 | const FrameTreeNodeId prerender_frame_tree_node_id = |
Hiroki Nakagawa | e72cf55c | 2022-11-30 05:58:14 | [diff] [blame] | 374 | contents()->AddPrerender(kPrerenderingUrl); |
| 375 | registry().CancelHost(prerender_frame_tree_node_id, |
| 376 | PrerenderFinalStatus::kDestroyed); |
Yoshiki Tanioka | 49b4cfb | 2022-10-20 09:25:31 | [diff] [blame] | 377 | ExpectFinalStatus(PrerenderFinalStatus::kDestroyed); |
Hiroki Nakagawa | 968139e2 | 2020-10-22 15:03:56 | [diff] [blame] | 378 | } |
| 379 | |
Asami Doi | 3965173 | 2023-01-31 05:25:26 | [diff] [blame] | 380 | // Tests that cross-site main frame navigations in a prerendered page cannot |
| 381 | // occur even if they start after the prerendered page has been reserved for |
| 382 | // activation. |
Hiroki Nakagawa | 0a90bd4 | 2021-04-21 01:53:05 | [diff] [blame] | 383 | TEST_F(PrerenderHostTest, MainFrameNavigationForReservedHost) { |
Matt Falkenhagen | 21ee4f8 | 2021-04-13 08:14:28 | [diff] [blame] | 384 | // Start prerendering a page. |
| 385 | const GURL kPrerenderingUrl("https://example.com/next"); |
Adithya Srinivasan | 8bda0b2 | 2021-06-14 20:41:37 | [diff] [blame] | 386 | RenderFrameHostImpl* prerender_rfh = |
Hiroki Nakagawa | e72cf55c | 2022-11-30 05:58:14 | [diff] [blame] | 387 | contents()->AddPrerenderAndCommitNavigation(kPrerenderingUrl); |
Matt Falkenhagen | 16414e0 | 2021-06-22 05:58:54 | [diff] [blame] | 388 | FrameTreeNode* ftn = prerender_rfh->frame_tree_node(); |
| 389 | EXPECT_FALSE(ftn->HasNavigation()); |
Matt Falkenhagen | 21ee4f8 | 2021-04-13 08:14:28 | [diff] [blame] | 390 | |
Hiroki Nakagawa | e72cf55c | 2022-11-30 05:58:14 | [diff] [blame] | 391 | test::PrerenderHostObserver prerender_host_observer(*contents(), |
Takashi Toyoshima | 9c8b08c | 2022-05-17 10:11:33 | [diff] [blame] | 392 | kPrerenderingUrl); |
Hiroki Nakagawa | 6c5f39bd | 2021-07-13 00:22:36 | [diff] [blame] | 393 | |
| 394 | // Now navigate the primary page to the prerendered URL so that we activate |
| 395 | // the prerender. Use a CommitDeferringCondition to pause activation |
| 396 | // before it completes. |
| 397 | std::unique_ptr<NavigationSimulatorImpl> navigation; |
Hiroki Nakagawa | 6c5f39bd | 2021-07-13 00:22:36 | [diff] [blame] | 398 | |
David Bokan | b650c95 | 2022-02-17 19:56:40 | [diff] [blame] | 399 | { |
| 400 | MockCommitDeferringConditionInstaller installer( |
Mingyu Lei | fec7c7d | 2023-07-21 16:45:26 | [diff] [blame] | 401 | kPrerenderingUrl, CommitDeferringCondition::Result::kDefer); |
Hiroki Nakagawa | 6c5f39bd | 2021-07-13 00:22:36 | [diff] [blame] | 402 | // Start trying to activate the prerendered page. |
Hiroki Nakagawa | e72cf55c | 2022-11-30 05:58:14 | [diff] [blame] | 403 | navigation = CreateActivation(kPrerenderingUrl, *contents()); |
Hiroki Nakagawa | 6c5f39bd | 2021-07-13 00:22:36 | [diff] [blame] | 404 | navigation->Start(); |
| 405 | |
| 406 | // Wait for the condition to pause the activation. |
David Bokan | b650c95 | 2022-02-17 19:56:40 | [diff] [blame] | 407 | installer.WaitUntilInstalled(); |
| 408 | installer.condition().WaitUntilInvoked(); |
| 409 | |
| 410 | // The request should be deferred by the condition. |
| 411 | NavigationRequest* navigation_request = |
| 412 | static_cast<NavigationRequest*>(navigation->GetNavigationHandle()); |
| 413 | EXPECT_TRUE( |
| 414 | navigation_request->IsCommitDeferringConditionDeferredForTesting()); |
| 415 | |
| 416 | // The primary page should still be the original page. |
Hiroki Nakagawa | e72cf55c | 2022-11-30 05:58:14 | [diff] [blame] | 417 | EXPECT_EQ(contents()->GetLastCommittedURL(), "https://example.com/"); |
David Bokan | b650c95 | 2022-02-17 19:56:40 | [diff] [blame] | 418 | |
| 419 | const GURL kBadUrl("https://example2.test/"); |
Hiroki Nakagawa | e72cf55c | 2022-11-30 05:58:14 | [diff] [blame] | 420 | TestNavigationManager tno(contents(), kBadUrl); |
David Bokan | b650c95 | 2022-02-17 19:56:40 | [diff] [blame] | 421 | |
Asami Doi | 3965173 | 2023-01-31 05:25:26 | [diff] [blame] | 422 | // Start a cross-site navigation in the prerendered page. It should be |
David Bokan | b650c95 | 2022-02-17 19:56:40 | [diff] [blame] | 423 | // cancelled. |
| 424 | auto navigation_2 = NavigationSimulatorImpl::CreateRendererInitiated( |
| 425 | kBadUrl, prerender_rfh); |
| 426 | navigation_2->Start(); |
| 427 | EXPECT_EQ(NavigationThrottle::CANCEL, |
| 428 | navigation_2->GetLastThrottleCheckResult()); |
Fergal Daly | 664780d3 | 2023-01-11 08:26:23 | [diff] [blame] | 429 | ASSERT_TRUE(tno.WaitForNavigationFinished()); |
David Bokan | b650c95 | 2022-02-17 19:56:40 | [diff] [blame] | 430 | EXPECT_FALSE(tno.was_committed()); |
| 431 | |
Asami Doi | 3965173 | 2023-01-31 05:25:26 | [diff] [blame] | 432 | // The cross-site navigation cancels the activation. |
David Bokan | b650c95 | 2022-02-17 19:56:40 | [diff] [blame] | 433 | installer.condition().CallResumeClosure(); |
Takashi Toyoshima | 9c8b08c | 2022-05-17 10:11:33 | [diff] [blame] | 434 | prerender_host_observer.WaitForDestroyed(); |
| 435 | EXPECT_FALSE(prerender_host_observer.was_activated()); |
Hiroki Nakagawa | e72cf55c | 2022-11-30 05:58:14 | [diff] [blame] | 436 | EXPECT_EQ(registry().FindHostByUrlForTesting(kPrerenderingUrl), nullptr); |
Hiroki Nakagawa | d04aaaf9 | 2023-03-20 17:13:28 | [diff] [blame] | 437 | ExpectFinalStatus( |
| 438 | PrerenderFinalStatus::kCrossSiteNavigationInMainFrameNavigation); |
Hiroki Nakagawa | 6c5f39bd | 2021-07-13 00:22:36 | [diff] [blame] | 439 | } |
| 440 | |
Hiroki Nakagawa | 6c5f39bd | 2021-07-13 00:22:36 | [diff] [blame] | 441 | // The activation falls back to regular navigation. |
Hiroki Nakagawa | 6c5f39bd | 2021-07-13 00:22:36 | [diff] [blame] | 442 | navigation->Commit(); |
Hiroki Nakagawa | e72cf55c | 2022-11-30 05:58:14 | [diff] [blame] | 443 | EXPECT_EQ(contents()->GetPrimaryMainFrame()->GetLastCommittedURL(), |
Hiroki Nakagawa | 6c5f39bd | 2021-07-13 00:22:36 | [diff] [blame] | 444 | kPrerenderingUrl); |
Matt Falkenhagen | 21ee4f8 | 2021-04-13 08:14:28 | [diff] [blame] | 445 | } |
| 446 | |
Alexander Timin | 46fb6eec | 2021-06-04 15:46:30 | [diff] [blame] | 447 | // Tests that an activation can successfully commit after the prerendering page |
| 448 | // has updated its PageState. |
| 449 | TEST_F(PrerenderHostTest, ActivationAfterPageStateUpdate) { |
Alexander Timin | 46fb6eec | 2021-06-04 15:46:30 | [diff] [blame] | 450 | // Start prerendering a page. |
| 451 | const GURL kPrerenderingUrl("https://example.com/next"); |
Avi Drissman | dcc8e68 | 2024-09-04 14:14:48 | [diff] [blame] | 452 | const FrameTreeNodeId prerender_frame_tree_node_id = |
| 453 | registry().CreateAndStartHost( |
| 454 | GeneratePrerenderAttributes(kPrerenderingUrl)); |
Alexander Timin | 46fb6eec | 2021-06-04 15:46:30 | [diff] [blame] | 455 | PrerenderHost* prerender_host = |
Hiroki Nakagawa | e72cf55c | 2022-11-30 05:58:14 | [diff] [blame] | 456 | registry().FindNonReservedHostById(prerender_frame_tree_node_id); |
Alexander Timin | 46fb6eec | 2021-06-04 15:46:30 | [diff] [blame] | 457 | CommitPrerenderNavigation(*prerender_host); |
| 458 | |
Hiroki Nakagawa | e72cf55c | 2022-11-30 05:58:14 | [diff] [blame] | 459 | auto* prerender_root_ftn = |
Alexander Timin | 46fb6eec | 2021-06-04 15:46:30 | [diff] [blame] | 460 | FrameTreeNode::GloballyFindByID(prerender_frame_tree_node_id); |
| 461 | RenderFrameHostImpl* prerender_rfh = prerender_root_ftn->current_frame_host(); |
| 462 | NavigationEntryImpl* prerender_nav_entry = |
Arthur Sonzogni | f6785ec | 2022-12-05 10:11:50 | [diff] [blame] | 463 | prerender_root_ftn->frame_tree().controller().GetLastCommittedEntry(); |
Alexander Timin | 46fb6eec | 2021-06-04 15:46:30 | [diff] [blame] | 464 | FrameNavigationEntry* prerender_root_fne = |
| 465 | prerender_nav_entry->GetFrameEntry(prerender_root_ftn); |
| 466 | |
Hiroki Nakagawa | e72cf55c | 2022-11-30 05:58:14 | [diff] [blame] | 467 | auto page_state = blink::PageState::CreateForTestingWithSequenceNumbers( |
| 468 | GURL("about:blank"), prerender_root_fne->item_sequence_number(), |
| 469 | prerender_root_fne->document_sequence_number()); |
Alexander Timin | 46fb6eec | 2021-06-04 15:46:30 | [diff] [blame] | 470 | |
| 471 | // Update PageState for prerender RFH, causing it to become different from |
| 472 | // the one stored in RFH's last commit params. |
| 473 | static_cast<mojom::FrameHost*>(prerender_rfh)->UpdateState(page_state); |
| 474 | |
| 475 | // Perform a navigation in the primary frame tree which activates the |
| 476 | // prerendered page. The main expectation is that this navigation commits |
Ho Cheung | 13d432c2 | 2023-03-28 08:39:42 | [diff] [blame] | 477 | // successfully and doesn't hit any CHECKs. |
Hiroki Nakagawa | e72cf55c | 2022-11-30 05:58:14 | [diff] [blame] | 478 | contents()->ActivatePrerenderedPage(kPrerenderingUrl); |
Yoshiki Tanioka | 49b4cfb | 2022-10-20 09:25:31 | [diff] [blame] | 479 | ExpectFinalStatus(PrerenderFinalStatus::kActivated); |
Alexander Timin | 46fb6eec | 2021-06-04 15:46:30 | [diff] [blame] | 480 | |
| 481 | // Ensure that the the page_state was preserved. |
Hiroki Nakagawa | e72cf55c | 2022-11-30 05:58:14 | [diff] [blame] | 482 | EXPECT_EQ(contents()->GetPrimaryMainFrame(), prerender_rfh); |
Alexander Timin | 46fb6eec | 2021-06-04 15:46:30 | [diff] [blame] | 483 | NavigationEntryImpl* activated_nav_entry = |
Hiroki Nakagawa | e72cf55c | 2022-11-30 05:58:14 | [diff] [blame] | 484 | contents()->GetController().GetLastCommittedEntry(); |
Carlos Caballero | 15caeeb | 2021-10-27 09:57:55 | [diff] [blame] | 485 | EXPECT_EQ(page_state, |
| 486 | activated_nav_entry |
Hiroki Nakagawa | e72cf55c | 2022-11-30 05:58:14 | [diff] [blame] | 487 | ->GetFrameEntry(contents()->GetPrimaryFrameTree().root()) |
Carlos Caballero | 15caeeb | 2021-10-27 09:57:55 | [diff] [blame] | 488 | ->page_state()); |
Alexander Timin | 46fb6eec | 2021-06-04 15:46:30 | [diff] [blame] | 489 | } |
| 490 | |
Sreeja Kamishetty | 0be3b1b | 2021-08-12 17:04:15 | [diff] [blame] | 491 | // Test that WebContentsObserver::LoadProgressChanged is not invoked when the |
| 492 | // page gets loaded while prerendering but is invoked on prerender activation. |
| 493 | // Check that in case the load is incomplete with load progress |
| 494 | // `kPartialLoadProgress`, we would see |
| 495 | // LoadProgressChanged(kPartialLoadProgress) called on activation. |
| 496 | TEST_F(PrerenderHostTest, LoadProgressChangedInvokedOnActivation) { |
Hiroki Nakagawa | e72cf55c | 2022-11-30 05:58:14 | [diff] [blame] | 497 | contents()->set_minimum_delay_between_loading_updates_for_testing( |
Peter Kasting | e5a38ed | 2021-10-02 03:06:35 | [diff] [blame] | 498 | base::Milliseconds(0)); |
Sreeja Kamishetty | 0be3b1b | 2021-08-12 17:04:15 | [diff] [blame] | 499 | |
| 500 | // Initialize a MockWebContentsObserver and ensure that LoadProgressChanged is |
| 501 | // not invoked while prerendering. |
Hiroki Nakagawa | e72cf55c | 2022-11-30 05:58:14 | [diff] [blame] | 502 | testing::NiceMock<MockWebContentsObserver> observer(contents()); |
Sreeja Kamishetty | 0be3b1b | 2021-08-12 17:04:15 | [diff] [blame] | 503 | testing::InSequence s; |
| 504 | EXPECT_CALL(observer, LoadProgressChanged(testing::_)).Times(0); |
| 505 | |
| 506 | // Start prerendering a page and commit prerender navigation. |
| 507 | const GURL kPrerenderingUrl("https://example.com/next"); |
| 508 | constexpr double kPartialLoadProgress = 0.7; |
| 509 | RenderFrameHostImpl* prerender_rfh = |
Hiroki Nakagawa | e72cf55c | 2022-11-30 05:58:14 | [diff] [blame] | 510 | contents()->AddPrerenderAndCommitNavigation(kPrerenderingUrl); |
Sreeja Kamishetty | 0be3b1b | 2021-08-12 17:04:15 | [diff] [blame] | 511 | FrameTreeNode* ftn = prerender_rfh->frame_tree_node(); |
| 512 | EXPECT_FALSE(ftn->HasNavigation()); |
| 513 | |
| 514 | // Verify and clear all expectations on the mock observer before setting new |
| 515 | // ones. |
| 516 | testing::Mock::VerifyAndClearExpectations(&observer); |
| 517 | |
| 518 | // Activate the prerendered page. This should result in invoking |
| 519 | // LoadProgressChanged for the following cases: |
| 520 | { |
| 521 | // 1) During DidStartLoading LoadProgressChanged is invoked with |
| 522 | // kInitialLoadProgress value. |
| 523 | EXPECT_CALL(observer, LoadProgressChanged(blink::kInitialLoadProgress)); |
| 524 | |
| 525 | // Verify that DidFinishNavigation is invoked before final load progress |
| 526 | // notification. |
| 527 | EXPECT_CALL(observer, DidFinishNavigation(testing::_)); |
| 528 | |
| 529 | // 2) After DidCommitNavigationInternal on activation with |
| 530 | // LoadProgressChanged is invoked with kPartialLoadProgress value. |
| 531 | EXPECT_CALL(observer, LoadProgressChanged(kPartialLoadProgress)); |
| 532 | |
| 533 | // 3) During DidStopLoading LoadProgressChanged is invoked with |
| 534 | // kFinalLoadProgress. |
| 535 | EXPECT_CALL(observer, LoadProgressChanged(blink::kFinalLoadProgress)); |
| 536 | } |
| 537 | |
| 538 | // Set load_progress value to kPartialLoadProgress in prerendering state, |
| 539 | // this should result in invoking LoadProgressChanged(kPartialLoadProgress) on |
| 540 | // activation. |
| 541 | prerender_rfh->GetPage().set_load_progress(kPartialLoadProgress); |
| 542 | |
| 543 | // Perform a navigation in the primary frame tree which activates the |
| 544 | // prerendered page. |
Hiroki Nakagawa | e72cf55c | 2022-11-30 05:58:14 | [diff] [blame] | 545 | contents()->ActivatePrerenderedPage(kPrerenderingUrl); |
Yoshiki Tanioka | 49b4cfb | 2022-10-20 09:25:31 | [diff] [blame] | 546 | ExpectFinalStatus(PrerenderFinalStatus::kActivated); |
Sreeja Kamishetty | 0be3b1b | 2021-08-12 17:04:15 | [diff] [blame] | 547 | } |
| 548 | |
Asami Doi | 7e33f2f | 2022-12-12 16:15:09 | [diff] [blame] | 549 | TEST_F(PrerenderHostTest, DontCancelPrerenderWhenTriggerGetsHidden) { |
Robert Lin | 1ae4056 | 2021-09-17 02:48:01 | [diff] [blame] | 550 | const GURL kPrerenderingUrl = GURL("https://example.com/empty.html"); |
Avi Drissman | dcc8e68 | 2024-09-04 14:14:48 | [diff] [blame] | 551 | const FrameTreeNodeId prerender_frame_tree_node_id = |
| 552 | registry().CreateAndStartHost( |
| 553 | GeneratePrerenderAttributes(kPrerenderingUrl)); |
Robert Lin | 1ae4056 | 2021-09-17 02:48:01 | [diff] [blame] | 554 | PrerenderHost* prerender_host = |
Hiroki Nakagawa | e72cf55c | 2022-11-30 05:58:14 | [diff] [blame] | 555 | registry().FindNonReservedHostById(prerender_frame_tree_node_id); |
Robert Lin | 1ae4056 | 2021-09-17 02:48:01 | [diff] [blame] | 556 | ASSERT_NE(prerender_host, nullptr); |
| 557 | CommitPrerenderNavigation(*prerender_host); |
| 558 | |
Asami Doi | 7e33f2f | 2022-12-12 16:15:09 | [diff] [blame] | 559 | // Changing the visibility state to HIDDEN will not stop prerendering. |
Hiroki Nakagawa | e72cf55c | 2022-11-30 05:58:14 | [diff] [blame] | 560 | contents()->WasHidden(); |
Asami Doi | 7e33f2f | 2022-12-12 16:15:09 | [diff] [blame] | 561 | |
| 562 | // Activation from the foreground page should succeed. |
| 563 | contents()->WasShown(); |
| 564 | contents()->ActivatePrerenderedPage(kPrerenderingUrl); |
| 565 | ExpectFinalStatus(PrerenderFinalStatus::kActivated); |
| 566 | } |
| 567 | |
| 568 | TEST_F(PrerenderHostTest, CancelActivationFromHiddenPage) { |
| 569 | const GURL kPrerenderingUrl = GURL("https://example.com/empty.html"); |
Avi Drissman | dcc8e68 | 2024-09-04 14:14:48 | [diff] [blame] | 570 | const FrameTreeNodeId prerender_frame_tree_node_id = |
| 571 | registry().CreateAndStartHost( |
| 572 | GeneratePrerenderAttributes(kPrerenderingUrl)); |
Asami Doi | 7e33f2f | 2022-12-12 16:15:09 | [diff] [blame] | 573 | PrerenderHost* prerender_host = |
| 574 | registry().FindNonReservedHostById(prerender_frame_tree_node_id); |
| 575 | ASSERT_NE(prerender_host, nullptr); |
| 576 | CommitPrerenderNavigation(*prerender_host); |
| 577 | |
| 578 | // Changing the visibility state to HIDDEN will not stop prerendering. |
| 579 | contents()->WasHidden(); |
| 580 | |
| 581 | // Activation from the background page should fail. |
| 582 | test::PrerenderHostObserver prerender_host_observer( |
| 583 | *contents(), prerender_frame_tree_node_id); |
| 584 | std::unique_ptr<NavigationSimulatorImpl> navigation = |
| 585 | NavigationSimulatorImpl::CreateRendererInitiated( |
| 586 | kPrerenderingUrl, contents()->GetPrimaryMainFrame()); |
| 587 | navigation->SetReferrer(blink::mojom::Referrer::New( |
| 588 | contents()->GetPrimaryMainFrame()->GetLastCommittedURL(), |
| 589 | network::mojom::ReferrerPolicy::kStrictOriginWhenCrossOrigin)); |
| 590 | navigation->Commit(); |
| 591 | prerender_host_observer.WaitForDestroyed(); |
| 592 | |
| 593 | EXPECT_FALSE(prerender_host_observer.was_activated()); |
| 594 | ExpectFinalStatus(PrerenderFinalStatus::kActivatedInBackground); |
Robert Lin | 1ae4056 | 2021-09-17 02:48:01 | [diff] [blame] | 595 | } |
| 596 | |
| 597 | TEST_F(PrerenderHostTest, DontCancelPrerenderWhenTriggerGetsVisible) { |
Robert Lin | 1ae4056 | 2021-09-17 02:48:01 | [diff] [blame] | 598 | const GURL kPrerenderingUrl = GURL("https://example.com/empty.html"); |
Avi Drissman | dcc8e68 | 2024-09-04 14:14:48 | [diff] [blame] | 599 | const FrameTreeNodeId prerender_frame_tree_node_id = |
| 600 | registry().CreateAndStartHost( |
| 601 | GeneratePrerenderAttributes(kPrerenderingUrl)); |
Robert Lin | 1ae4056 | 2021-09-17 02:48:01 | [diff] [blame] | 602 | PrerenderHost* prerender_host = |
Hiroki Nakagawa | e72cf55c | 2022-11-30 05:58:14 | [diff] [blame] | 603 | registry().FindNonReservedHostById(prerender_frame_tree_node_id); |
Robert Lin | 1ae4056 | 2021-09-17 02:48:01 | [diff] [blame] | 604 | ASSERT_NE(prerender_host, nullptr); |
| 605 | CommitPrerenderNavigation(*prerender_host); |
| 606 | |
Asami Doi | d1baa442 | 2022-10-04 09:04:07 | [diff] [blame] | 607 | // Changing the visibility state to VISIBLE will not stop prerendering. |
Hiroki Nakagawa | e72cf55c | 2022-11-30 05:58:14 | [diff] [blame] | 608 | contents()->WasShown(); |
| 609 | contents()->ActivatePrerenderedPage(kPrerenderingUrl); |
Yoshiki Tanioka | 49b4cfb | 2022-10-20 09:25:31 | [diff] [blame] | 610 | ExpectFinalStatus(PrerenderFinalStatus::kActivated); |
Robert Lin | 1ae4056 | 2021-09-17 02:48:01 | [diff] [blame] | 611 | } |
| 612 | |
| 613 | // Skip this test on Android as it doesn't support the OCCLUDED state. |
Xiaohan Wang | 1e4ebde | 2022-01-15 17:29:12 | [diff] [blame] | 614 | #if !BUILDFLAG(IS_ANDROID) |
Robert Lin | 1ae4056 | 2021-09-17 02:48:01 | [diff] [blame] | 615 | TEST_F(PrerenderHostTest, DontCancelPrerenderWhenTriggerGetsOcculded) { |
Robert Lin | 1ae4056 | 2021-09-17 02:48:01 | [diff] [blame] | 616 | const GURL kPrerenderingUrl = GURL("https://example.com/empty.html"); |
Avi Drissman | dcc8e68 | 2024-09-04 14:14:48 | [diff] [blame] | 617 | const FrameTreeNodeId prerender_frame_tree_node_id = |
| 618 | registry().CreateAndStartHost( |
| 619 | GeneratePrerenderAttributes(kPrerenderingUrl)); |
Robert Lin | 1ae4056 | 2021-09-17 02:48:01 | [diff] [blame] | 620 | PrerenderHost* prerender_host = |
Hiroki Nakagawa | e72cf55c | 2022-11-30 05:58:14 | [diff] [blame] | 621 | registry().FindNonReservedHostById(prerender_frame_tree_node_id); |
Robert Lin | 1ae4056 | 2021-09-17 02:48:01 | [diff] [blame] | 622 | ASSERT_NE(prerender_host, nullptr); |
| 623 | CommitPrerenderNavigation(*prerender_host); |
| 624 | |
Asami Doi | d1baa442 | 2022-10-04 09:04:07 | [diff] [blame] | 625 | // Changing the visibility state to OCCLUDED will not stop prerendering. |
Hiroki Nakagawa | e72cf55c | 2022-11-30 05:58:14 | [diff] [blame] | 626 | contents()->WasOccluded(); |
| 627 | contents()->ActivatePrerenderedPage(kPrerenderingUrl); |
Yoshiki Tanioka | 49b4cfb | 2022-10-20 09:25:31 | [diff] [blame] | 628 | ExpectFinalStatus(PrerenderFinalStatus::kActivated); |
Robert Lin | 1ae4056 | 2021-09-17 02:48:01 | [diff] [blame] | 629 | } |
| 630 | #endif |
| 631 | |
Lingqi Chi | 21d9feb | 2022-02-02 09:42:18 | [diff] [blame] | 632 | TEST_F(PrerenderHostTest, UrlMatchPredicate) { |
Lingqi Chi | 21d9feb | 2022-02-02 09:42:18 | [diff] [blame] | 633 | const GURL kPrerenderingUrl = GURL("https://example.com/empty.html"); |
Liviu Tinta | cf066d5 | 2024-07-24 16:00:55 | [diff] [blame] | 634 | base::RepeatingCallback callback = base::BindRepeating( |
| 635 | [](const GURL&, const std::optional<content::UrlMatchType>&) { |
| 636 | return true; |
| 637 | }); |
Avi Drissman | dcc8e68 | 2024-09-04 14:14:48 | [diff] [blame] | 638 | const FrameTreeNodeId prerender_frame_tree_node_id = |
| 639 | registry().CreateAndStartHost( |
| 640 | GeneratePrerenderAttributesWithPredicate(kPrerenderingUrl, callback)); |
Lingqi Chi | 21d9feb | 2022-02-02 09:42:18 | [diff] [blame] | 641 | PrerenderHost* prerender_host = |
Hiroki Nakagawa | e72cf55c | 2022-11-30 05:58:14 | [diff] [blame] | 642 | registry().FindNonReservedHostById(prerender_frame_tree_node_id); |
Lingqi Chi | 21d9feb | 2022-02-02 09:42:18 | [diff] [blame] | 643 | ASSERT_NE(prerender_host, nullptr); |
| 644 | const GURL kActivatedUrl = GURL("https://example.com/empty.html?activate"); |
| 645 | ASSERT_NE(kActivatedUrl, kPrerenderingUrl); |
| 646 | EXPECT_TRUE(prerender_host->IsUrlMatch(kActivatedUrl)); |
| 647 | // Even if the predicate always returns true, a cross-origin url shouldn't be |
| 648 | // able to activate a prerendered page. |
| 649 | EXPECT_FALSE( |
| 650 | prerender_host->IsUrlMatch(GURL("https://example2.com/empty.html"))); |
| 651 | } |
| 652 | |
Lingqi Chi | 8098c5e9 | 2022-09-21 13:24:50 | [diff] [blame] | 653 | // Regression test for https://crbug.com/1366046: This test will crash if |
| 654 | // PrerenderHost is set to "ready_for_activation" after getting canceled. |
| 655 | TEST_F(PrerenderHostTest, CanceledPrerenderCannotBeReadyForActivation) { |
Lingqi Chi | 8098c5e9 | 2022-09-21 13:24:50 | [diff] [blame] | 656 | const GURL kPrerenderingUrl = GURL("https://example.com/empty.html"); |
Lingqi Chi | 8098c5e9 | 2022-09-21 13:24:50 | [diff] [blame] | 657 | |
Hiroki Nakagawa | e72cf55c | 2022-11-30 05:58:14 | [diff] [blame] | 658 | auto* preloading_data = PreloadingData::GetOrCreateForWebContents(contents()); |
Lingqi Chi | 8098c5e9 | 2022-09-21 13:24:50 | [diff] [blame] | 659 | |
| 660 | // Create new PreloadingAttempt and pass all the values corresponding to |
| 661 | // this prerendering attempt. |
| 662 | PreloadingURLMatchCallback same_url_matcher = |
| 663 | PreloadingData::GetSameURLMatcher(kPrerenderingUrl); |
| 664 | PreloadingAttempt* preloading_attempt = preloading_data->AddPreloadingAttempt( |
William Liu | 238a9e5 | 2023-01-23 20:32:40 | [diff] [blame] | 665 | content_preloading_predictor::kSpeculationRules, |
Hiroki Nakagawa | f93776b | 2023-09-12 22:04:27 | [diff] [blame] | 666 | PreloadingType::kPrerender, std::move(same_url_matcher), |
| 667 | contents()->GetPrimaryMainFrame()->GetPageUkmSourceId()); |
Lingqi Chi | 8098c5e9 | 2022-09-21 13:24:50 | [diff] [blame] | 668 | |
Avi Drissman | dcc8e68 | 2024-09-04 14:14:48 | [diff] [blame] | 669 | const FrameTreeNodeId prerender_frame_tree_node_id = |
| 670 | registry().CreateAndStartHost( |
| 671 | GeneratePrerenderAttributes(kPrerenderingUrl), preloading_attempt); |
Lingqi Chi | 8098c5e9 | 2022-09-21 13:24:50 | [diff] [blame] | 672 | PrerenderHost* prerender_host = |
Hiroki Nakagawa | e72cf55c | 2022-11-30 05:58:14 | [diff] [blame] | 673 | registry().FindNonReservedHostById(prerender_frame_tree_node_id); |
Lingqi Chi | 8098c5e9 | 2022-09-21 13:24:50 | [diff] [blame] | 674 | ASSERT_NE(prerender_host, nullptr); |
| 675 | |
Lingqi Chi | 8e192ba | 2022-11-22 04:34:25 | [diff] [blame] | 676 | // Registry keeps alive through this test, so it is safe to capture the |
| 677 | // reference to `registry`. |
Sean Maher | 52fa5a7 | 2022-11-14 15:53:25 | [diff] [blame] | 678 | base::SequencedTaskRunner::GetCurrentDefault()->PostTask( |
Lingqi Chi | 8e192ba | 2022-11-22 04:34:25 | [diff] [blame] | 679 | FROM_HERE, base::BindOnce(base::BindLambdaForTesting([&]() { |
Hiroki Nakagawa | e72cf55c | 2022-11-30 05:58:14 | [diff] [blame] | 680 | registry().CancelHost(prerender_frame_tree_node_id, |
| 681 | PrerenderFinalStatus::kTriggerDestroyed); |
Lingqi Chi | 8e192ba | 2022-11-22 04:34:25 | [diff] [blame] | 682 | }))); |
Lingqi Chi | 8098c5e9 | 2022-09-21 13:24:50 | [diff] [blame] | 683 | |
| 684 | // For some reasons triggers want to set the failure reason by themselves, |
| 685 | // this would happen together with cancelling prerender. |
Sean Maher | 52fa5a7 | 2022-11-14 15:53:25 | [diff] [blame] | 686 | base::SequencedTaskRunner::GetCurrentDefault()->PostTask( |
Lingqi Chi | 8098c5e9 | 2022-09-21 13:24:50 | [diff] [blame] | 687 | FROM_HERE, |
| 688 | base::BindOnce( |
| 689 | &PreloadingAttempt::SetFailureReason, |
| 690 | base::Unretained(preloading_attempt), |
| 691 | static_cast<PreloadingFailureReason>( |
Yoshiki Tanioka | 49b4cfb | 2022-10-20 09:25:31 | [diff] [blame] | 692 | static_cast<int>(PrerenderFinalStatus::kTriggerDestroyed) + |
Lingqi Chi | 8098c5e9 | 2022-09-21 13:24:50 | [diff] [blame] | 693 | static_cast<int>(PreloadingFailureReason:: |
| 694 | kPreloadingFailureReasonCommonEnd)))); |
| 695 | |
| 696 | base::RunLoop run_loop; |
Sean Maher | 52fa5a7 | 2022-11-14 15:53:25 | [diff] [blame] | 697 | base::SequencedTaskRunner::GetCurrentDefault()->PostTask( |
Lingqi Chi | 8098c5e9 | 2022-09-21 13:24:50 | [diff] [blame] | 698 | FROM_HERE, base::BindLambdaForTesting([&]() { |
| 699 | CommitPrerenderNavigation(*prerender_host, |
| 700 | ExpectedReadyForActivationState(false)); |
| 701 | run_loop.Quit(); |
| 702 | })); |
| 703 | |
| 704 | // Wait for the completion of CommitPrerenderNavigation() above. |
| 705 | run_loop.Run(); |
| 706 | |
Sreeja Kamishetty | 26e40d2 | 2022-10-17 17:54:35 | [diff] [blame] | 707 | EXPECT_EQ(test::PreloadingAttemptAccessor(preloading_attempt) |
| 708 | .GetTriggeringOutcome(), |
Lingqi Chi | 8098c5e9 | 2022-09-21 13:24:50 | [diff] [blame] | 709 | PreloadingTriggeringOutcome::kFailure); |
| 710 | } |
| 711 | |
Miina Koyama | 6f3bbc7 | 2023-09-08 08:13:02 | [diff] [blame] | 712 | TEST(AreHttpRequestHeadersCompatible, IgnoreRTT) { |
Miina Koyama | d0e41f3 | 2023-11-13 06:50:09 | [diff] [blame] | 713 | PrerenderCancellationReason reason = PrerenderCancellationReason( |
| 714 | PrerenderFinalStatus::kActivationNavigationParameterMismatch); |
Miina Koyama | 6f3bbc7 | 2023-09-08 08:13:02 | [diff] [blame] | 715 | const std::string prerender_headers = "rtt: 1 \r\n downlink: 3"; |
| 716 | const std::string potential_activation_headers = "rtt: 2 \r\n downlink: 4"; |
Doug Turner | 7ce58cf | 2025-08-04 22:03:25 | [diff] [blame] | 717 | #if BUILDFLAG(IS_ANDROID) |
| 718 | net::HttpRequestHeaders potential_activation_additional_headers; |
| 719 | #endif |
| 720 | |
Miina Koyama | 6f3bbc7 | 2023-09-08 08:13:02 | [diff] [blame] | 721 | EXPECT_TRUE(PrerenderHost::AreHttpRequestHeadersCompatible( |
Hiroki Nakagawa | 8348bc4 | 2024-12-13 16:24:42 | [diff] [blame] | 722 | potential_activation_headers, |
| 723 | #if BUILDFLAG(IS_ANDROID) |
Doug Turner | 7ce58cf | 2025-08-04 22:03:25 | [diff] [blame] | 724 | potential_activation_additional_headers, |
Hiroki Nakagawa | 8348bc4 | 2024-12-13 16:24:42 | [diff] [blame] | 725 | #endif // BUILDFLAG(IS_ANDROID) |
| 726 | prerender_headers, PreloadingTriggerType::kSpeculationRule, |
Hiroki Nakagawa | aadc329 | 2025-04-03 00:46:32 | [diff] [blame] | 727 | /*embedder_histogram_suffix=*/"", /*allow_x_header_mismatch=*/false, |
| 728 | reason)); |
| 729 | } |
| 730 | |
| 731 | TEST(AreHttpRequestHeadersCompatible, XHeaders) { |
| 732 | PrerenderCancellationReason reason = PrerenderCancellationReason( |
| 733 | PrerenderFinalStatus::kActivationNavigationParameterMismatch); |
| 734 | const std::string prerender_headers = "x-hello: 1"; |
| 735 | const std::string potential_activation_headers = "X-world: 2"; |
Doug Turner | 7ce58cf | 2025-08-04 22:03:25 | [diff] [blame] | 736 | #if BUILDFLAG(IS_ANDROID) |
| 737 | net::HttpRequestHeaders potential_activation_additional_headers; |
| 738 | #endif |
Hiroki Nakagawa | aadc329 | 2025-04-03 00:46:32 | [diff] [blame] | 739 | |
| 740 | EXPECT_FALSE(PrerenderHost::AreHttpRequestHeadersCompatible( |
| 741 | potential_activation_headers, |
| 742 | #if BUILDFLAG(IS_ANDROID) |
Doug Turner | 7ce58cf | 2025-08-04 22:03:25 | [diff] [blame] | 743 | potential_activation_additional_headers, |
Hiroki Nakagawa | aadc329 | 2025-04-03 00:46:32 | [diff] [blame] | 744 | #endif // BUILDFLAG(IS_ANDROID) |
| 745 | prerender_headers, PreloadingTriggerType::kSpeculationRule, |
| 746 | /*embedder_histogram_suffix=*/"", /*allow_x_header_mismatch=*/false, |
| 747 | reason)); |
| 748 | |
| 749 | EXPECT_TRUE(PrerenderHost::AreHttpRequestHeadersCompatible( |
| 750 | potential_activation_headers, |
| 751 | #if BUILDFLAG(IS_ANDROID) |
Doug Turner | 7ce58cf | 2025-08-04 22:03:25 | [diff] [blame] | 752 | potential_activation_additional_headers, |
Hiroki Nakagawa | aadc329 | 2025-04-03 00:46:32 | [diff] [blame] | 753 | #endif // BUILDFLAG(IS_ANDROID) |
| 754 | prerender_headers, PreloadingTriggerType::kSpeculationRule, |
| 755 | /*embedder_histogram_suffix=*/"", /*allow_x_header_mismatch=*/true, |
| 756 | reason)); |
Miina Koyama | 6f3bbc7 | 2023-09-08 08:13:02 | [diff] [blame] | 757 | } |
| 758 | |
Hiroki Nakagawa | 968139e2 | 2020-10-22 15:03:56 | [diff] [blame] | 759 | } // namespace |
| 760 | } // namespace content |