blob: a2131e3b731d76ce00d694c1530f6ec98ff459d8 [file] [log] [blame]
Dmitry Gozmancd3529822019-01-11 21:12:161// Copyright 2019 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "content/renderer/loader/navigation_body_loader.h"
6
7#include "base/bind.h"
8#include "base/macros.h"
9#include "base/run_loop.h"
10#include "base/single_thread_task_runner.h"
Gabriel Charettec7108742019-08-23 03:31:4011#include "base/test/task_environment.h"
Lucas Furukawa Gadanief8290a2019-07-29 20:27:5112#include "content/common/navigation_params.mojom.h"
Julie Jeongeun Kim6dd4c7b2019-11-18 05:56:3013#include "mojo/public/cpp/bindings/remote.h"
Emily Stark1225b892019-07-03 05:51:3414#include "net/cert/x509_util.h"
15#include "net/ssl/ssl_connection_status_flags.h"
16#include "net/test/cert_test_util.h"
Dmitry Gozmancd3529822019-01-11 21:12:1617#include "services/network/public/cpp/url_loader_completion_status.h"
18#include "testing/gtest/include/gtest/gtest.h"
19#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
20#include "third_party/blink/public/platform/web_navigation_body_loader.h"
Dmitry Gozman00fd5bb2019-01-25 20:25:3321#include "third_party/blink/public/web/web_navigation_params.h"
Dmitry Gozmancd3529822019-01-11 21:12:1622
23namespace content {
24
25namespace {
26
27class NavigationBodyLoaderTest : public ::testing::Test,
28 public blink::WebNavigationBodyLoader::Client {
29 protected:
30 NavigationBodyLoaderTest() {}
31
32 ~NavigationBodyLoaderTest() override { base::RunLoop().RunUntilIdle(); }
33
34 MojoCreateDataPipeOptions CreateDataPipeOptions() {
35 MojoCreateDataPipeOptions options;
36 options.struct_size = sizeof(MojoCreateDataPipeOptions);
37 options.flags = MOJO_CREATE_DATA_PIPE_FLAG_NONE;
38 options.element_num_bytes = 1;
39 options.capacity_num_bytes = 1024;
40 return options;
41 }
42
43 void CreateBodyLoader() {
Robert Sesek76af6692021-01-29 20:57:2344 mojo::ScopedDataPipeProducerHandle producer_handle;
45 mojo::ScopedDataPipeConsumerHandle consumer_handle;
46 MojoCreateDataPipeOptions options = CreateDataPipeOptions();
47 ASSERT_EQ(mojo::CreateDataPipe(&options, producer_handle, consumer_handle),
48 MOJO_RESULT_OK);
49
50 writer_ = std::move(producer_handle);
Dmitry Gozmancd3529822019-01-11 21:12:1651 auto endpoints = network::mojom::URLLoaderClientEndpoints::New();
Julie Jeongeun Kim6dd4c7b2019-11-18 05:56:3052 endpoints->url_loader_client = client_remote_.BindNewPipeAndPassReceiver();
Dmitry Gozman00fd5bb2019-01-25 20:25:3353 blink::WebNavigationParams navigation_params;
arthursonzognid5a8d0b2021-03-11 17:36:4354 navigation_params.sandbox_flags = network::mojom::WebSandboxFlags::kNone;
Lucas Furukawa Gadanieeddf2de2019-08-01 23:37:5755 auto common_params = CreateCommonNavigationParams();
Lucas Furukawa Gadania9c45682019-07-31 22:05:1456 auto commit_params = CreateCommitNavigationParams();
Dmitry Gozman00fd5bb2019-01-25 20:25:3357 NavigationBodyLoader::FillNavigationParamsResponseAndBodyLoader(
Minggang Wange0d5db32020-10-07 15:55:3158 std::move(common_params), std::move(commit_params), /*request_id=*/1,
Robert Sesek76af6692021-01-29 20:57:2359 network::mojom::URLResponseHead::New(), std::move(consumer_handle),
60 std::move(endpoints),
Dmitry Gozmancd3529822019-01-11 21:12:1661 blink::scheduler::GetSingleThreadTaskRunnerForTesting(),
Minggang Wange0d5db32020-10-07 15:55:3162 /*render_frame_impl=*/nullptr, /*is_main_frame=*/true,
63 &navigation_params);
Dmitry Gozman00fd5bb2019-01-25 20:25:3364 loader_ = std::move(navigation_params.body_loader);
Dmitry Gozmancd3529822019-01-11 21:12:1665 }
66
67 void StartLoading() {
Mythri Afefc0c462021-05-26 08:37:2668 loader_->StartLoadingBody(this, nullptr /*code_cache_host*/);
Dmitry Gozmancd3529822019-01-11 21:12:1669 base::RunLoop().RunUntilIdle();
70 }
71
72 void Write(const std::string& buffer) {
73 uint32_t size = buffer.size();
74 MojoResult result = writer_->WriteData(buffer.c_str(), &size, kNone);
75 ASSERT_EQ(MOJO_RESULT_OK, result);
76 ASSERT_EQ(buffer.size(), size);
77 }
78
79 void Complete(int net_error) {
Julie Jeongeun Kim6dd4c7b2019-11-18 05:56:3080 client_remote_->OnComplete(network::URLLoaderCompletionStatus(net_error));
Dmitry Gozmancd3529822019-01-11 21:12:1681 base::RunLoop().RunUntilIdle();
82 }
83
Bill Budge4405d8d52019-08-22 16:45:4584 void BodyCodeCacheReceived(mojo_base::BigBuffer data) override {}
Dmitry Gozmancd3529822019-01-11 21:12:1685
86 void BodyDataReceived(base::span<const char> data) override {
87 ASSERT_TRUE(expecting_data_received_);
88 did_receive_data_ = true;
89 data_received_ += std::string(data.data(), data.size());
90 TakeActions();
91 if (run_loop_.running())
92 run_loop_.Quit();
93 }
94
95 void BodyLoadingFinished(
96 base::TimeTicks completion_time,
97 int64_t total_encoded_data_length,
98 int64_t total_encoded_body_length,
99 int64_t total_decoded_body_length,
100 bool should_report_corb_blocking,
Anton Bikineevf62d1bf2021-05-15 17:56:07101 const absl::optional<blink::WebURLError>& error) override {
Dmitry Gozmancd3529822019-01-11 21:12:16102 ASSERT_TRUE(expecting_finished_);
103 did_finish_ = true;
104 error_ = error;
105 TakeActions();
106 if (run_loop_.running())
107 run_loop_.Quit();
108 }
109
110 void TakeActions() {
111 if (!buffer_to_write_.empty()) {
112 std::string buffer = buffer_to_write_;
113 buffer_to_write_ = std::string();
114 ExpectDataReceived();
115 Write(buffer);
116 }
117 if (toggle_defers_loading_) {
118 toggle_defers_loading_ = false;
Yutaka Hirano731ba542021-05-24 14:27:05119 loader_->SetDefersLoading(blink::WebLoaderFreezeMode::kNone);
120 loader_->SetDefersLoading(blink::WebLoaderFreezeMode::kStrict);
Dmitry Gozmancd3529822019-01-11 21:12:16121 }
122 if (destroy_loader_) {
123 destroy_loader_ = false;
124 loader_.reset();
125 }
126 }
127
128 void ExpectDataReceived() {
129 expecting_data_received_ = true;
130 did_receive_data_ = false;
131 }
132
133 void ExpectFinished() {
134 expecting_finished_ = true;
135 did_finish_ = false;
136 }
137
138 std::string TakeDataReceived() {
139 std::string data = data_received_;
140 data_received_ = std::string();
141 return data;
142 }
143
144 void Wait() {
145 if (expecting_data_received_) {
146 if (!did_receive_data_)
147 run_loop_.Run();
148 ASSERT_TRUE(did_receive_data_);
149 expecting_data_received_ = false;
150 }
151 if (expecting_finished_) {
152 if (!did_finish_)
153 run_loop_.Run();
154 ASSERT_TRUE(did_finish_);
155 expecting_finished_ = false;
156 }
157 }
158
Gabriel Charette694c3c332019-08-19 14:53:05159 base::test::TaskEnvironment task_environment_;
Dmitry Gozmancd3529822019-01-11 21:12:16160 static const MojoWriteDataFlags kNone = MOJO_WRITE_DATA_FLAG_NONE;
Julie Jeongeun Kim6dd4c7b2019-11-18 05:56:30161 mojo::Remote<network::mojom::URLLoaderClient> client_remote_;
Dmitry Gozmancd3529822019-01-11 21:12:16162 std::unique_ptr<blink::WebNavigationBodyLoader> loader_;
Dmitry Gozmancd3529822019-01-11 21:12:16163 mojo::ScopedDataPipeProducerHandle writer_;
164
165 base::RunLoop run_loop_;
166 bool expecting_data_received_ = false;
167 bool did_receive_data_ = false;
168 bool expecting_finished_ = false;
169 bool did_finish_ = false;
170 std::string buffer_to_write_;
171 bool toggle_defers_loading_ = false;
172 bool destroy_loader_ = false;
173 std::string data_received_;
Anton Bikineevf62d1bf2021-05-15 17:56:07174 absl::optional<blink::WebURLError> error_;
Dmitry Gozmancd3529822019-01-11 21:12:16175};
176
Dmitry Gozman98e8b192019-01-17 13:15:24177TEST_F(NavigationBodyLoaderTest, SetDefersBeforeStart) {
178 CreateBodyLoader();
Yutaka Hirano731ba542021-05-24 14:27:05179 loader_->SetDefersLoading(blink::WebLoaderFreezeMode::kStrict);
180 loader_->SetDefersLoading(blink::WebLoaderFreezeMode::kNone);
Dmitry Gozman98e8b192019-01-17 13:15:24181 // Should not crash.
182}
183
Dmitry Gozmancd3529822019-01-11 21:12:16184TEST_F(NavigationBodyLoaderTest, DataReceived) {
185 CreateBodyLoader();
186 StartLoading();
187 ExpectDataReceived();
188 Write("hello");
189 Wait();
190 EXPECT_EQ("hello", TakeDataReceived());
191}
192
193TEST_F(NavigationBodyLoaderTest, DataReceivedFromDataReceived) {
194 CreateBodyLoader();
195 StartLoading();
196 ExpectDataReceived();
197 buffer_to_write_ = "world";
198 Write("hello");
199 Wait();
200 EXPECT_EQ("helloworld", TakeDataReceived());
201}
202
203TEST_F(NavigationBodyLoaderTest, DestroyFromDataReceived) {
204 CreateBodyLoader();
205 StartLoading();
206 ExpectDataReceived();
207 destroy_loader_ = false;
208 Write("hello");
209 Wait();
210 EXPECT_EQ("hello", TakeDataReceived());
211}
212
213TEST_F(NavigationBodyLoaderTest, SetDefersLoadingFromDataReceived) {
214 CreateBodyLoader();
215 StartLoading();
216 ExpectDataReceived();
217 toggle_defers_loading_ = true;
218 Write("hello");
219 Wait();
220 EXPECT_EQ("hello", TakeDataReceived());
221}
222
223TEST_F(NavigationBodyLoaderTest, StartDeferred) {
224 CreateBodyLoader();
Yutaka Hirano731ba542021-05-24 14:27:05225 loader_->SetDefersLoading(blink::WebLoaderFreezeMode::kStrict);
Dmitry Gozmancd3529822019-01-11 21:12:16226 StartLoading();
227 Write("hello");
228 ExpectDataReceived();
Yutaka Hirano731ba542021-05-24 14:27:05229 loader_->SetDefersLoading(blink::WebLoaderFreezeMode::kNone);
Dmitry Gozmancd3529822019-01-11 21:12:16230 Wait();
231 EXPECT_EQ("hello", TakeDataReceived());
232}
233
Yuzu Saijoa3610fab2020-11-24 10:05:57234TEST_F(NavigationBodyLoaderTest, StartDeferredWithBackForwardCache) {
235 CreateBodyLoader();
Yutaka Hirano731ba542021-05-24 14:27:05236 loader_->SetDefersLoading(blink::WebLoaderFreezeMode::kBufferIncoming);
Yuzu Saijoa3610fab2020-11-24 10:05:57237 StartLoading();
238 Write("hello");
239 ExpectDataReceived();
Yutaka Hirano731ba542021-05-24 14:27:05240 loader_->SetDefersLoading(blink::WebLoaderFreezeMode::kNone);
Yuzu Saijoa3610fab2020-11-24 10:05:57241 Wait();
242 EXPECT_EQ("hello", TakeDataReceived());
243}
244
Dmitry Gozmancd3529822019-01-11 21:12:16245TEST_F(NavigationBodyLoaderTest, OnCompleteThenClose) {
246 CreateBodyLoader();
247 StartLoading();
248 Complete(net::ERR_FAILED);
249 ExpectFinished();
250 writer_.reset();
251 Wait();
252 EXPECT_TRUE(error_.has_value());
253}
254
255TEST_F(NavigationBodyLoaderTest, DestroyFromOnCompleteThenClose) {
256 CreateBodyLoader();
257 StartLoading();
258 Complete(net::ERR_FAILED);
259 ExpectFinished();
260 destroy_loader_ = true;
261 writer_.reset();
262 Wait();
263 EXPECT_TRUE(error_.has_value());
264}
265
266TEST_F(NavigationBodyLoaderTest, SetDefersLoadingFromOnCompleteThenClose) {
267 CreateBodyLoader();
268 StartLoading();
269 Complete(net::ERR_FAILED);
270 ExpectFinished();
271 toggle_defers_loading_ = true;
272 writer_.reset();
273 Wait();
274 EXPECT_TRUE(error_.has_value());
275}
276
277TEST_F(NavigationBodyLoaderTest, CloseThenOnComplete) {
278 CreateBodyLoader();
279 StartLoading();
280 writer_.reset();
281 ExpectFinished();
282 Complete(net::ERR_FAILED);
283 Wait();
284 EXPECT_TRUE(error_.has_value());
285}
286
287TEST_F(NavigationBodyLoaderTest, DestroyFromCloseThenOnComplete) {
288 CreateBodyLoader();
289 StartLoading();
290 writer_.reset();
291 ExpectFinished();
292 destroy_loader_ = true;
293 Complete(net::ERR_FAILED);
294 Wait();
295 EXPECT_TRUE(error_.has_value());
296}
297
298TEST_F(NavigationBodyLoaderTest, SetDefersLoadingFromCloseThenOnComplete) {
299 CreateBodyLoader();
300 StartLoading();
301 writer_.reset();
302 ExpectFinished();
303 toggle_defers_loading_ = true;
304 Complete(net::ERR_FAILED);
305 Wait();
306 EXPECT_TRUE(error_.has_value());
307}
308
Emily Stark1225b892019-07-03 05:51:34309// Tests that FillNavigationParamsResponseAndBodyLoader populates security
310// details on the response when they are present.
311TEST_F(NavigationBodyLoaderTest, FillResponseWithSecurityDetails) {
Lucas Gadanif7430a742019-10-11 17:42:14312 auto response = network::mojom::URLResponseHead::New();
313 response->ssl_info = net::SSLInfo();
Emily Stark1225b892019-07-03 05:51:34314 net::CertificateList certs;
315 ASSERT_TRUE(net::LoadCertificateFiles(
316 {"subjectAltName_sanity_check.pem", "root_ca_cert.pem"}, &certs));
317 ASSERT_EQ(2U, certs.size());
318
319 base::StringPiece cert0_der =
320 net::x509_util::CryptoBufferAsStringPiece(certs[0]->cert_buffer());
321 base::StringPiece cert1_der =
322 net::x509_util::CryptoBufferAsStringPiece(certs[1]->cert_buffer());
323
Lucas Gadanif7430a742019-10-11 17:42:14324 response->ssl_info->cert =
Emily Stark1225b892019-07-03 05:51:34325 net::X509Certificate::CreateFromDERCertChain({cert0_der, cert1_der});
326 net::SSLConnectionStatusSetVersion(net::SSL_CONNECTION_VERSION_TLS1_2,
Lucas Gadanif7430a742019-10-11 17:42:14327 &response->ssl_info->connection_status);
Emily Stark1225b892019-07-03 05:51:34328
Lucas Furukawa Gadanieeddf2de2019-08-01 23:37:57329 auto common_params = CreateCommonNavigationParams();
Lucas Furukawa Gadanief8290a2019-07-29 20:27:51330 common_params->url = GURL("https://example.test");
Lucas Furukawa Gadania9c45682019-07-31 22:05:14331 auto commit_params = CreateCommitNavigationParams();
Emily Stark1225b892019-07-03 05:51:34332
333 blink::WebNavigationParams navigation_params;
arthursonzognid5a8d0b2021-03-11 17:36:43334 navigation_params.sandbox_flags = network::mojom::WebSandboxFlags::kNone;
Emily Stark1225b892019-07-03 05:51:34335 auto endpoints = network::mojom::URLLoaderClientEndpoints::New();
Minggang Wang83f7f3712019-11-16 11:28:16336 mojo::ScopedDataPipeProducerHandle producer_handle;
337 mojo::ScopedDataPipeConsumerHandle consumer_handle;
338 MojoResult rv =
Robert Sesek3bce5dd2021-02-19 19:27:58339 mojo::CreateDataPipe(nullptr, producer_handle, consumer_handle);
Minggang Wang83f7f3712019-11-16 11:28:16340 ASSERT_EQ(MOJO_RESULT_OK, rv);
Emily Stark1225b892019-07-03 05:51:34341 NavigationBodyLoader::FillNavigationParamsResponseAndBodyLoader(
Minggang Wange0d5db32020-10-07 15:55:31342 std::move(common_params), std::move(commit_params), /*request_id=*/1,
Minggang Wang83f7f3712019-11-16 11:28:16343 std::move(response), std::move(consumer_handle), std::move(endpoints),
Emily Stark1225b892019-07-03 05:51:34344 blink::scheduler::GetSingleThreadTaskRunnerForTesting(),
Minggang Wange0d5db32020-10-07 15:55:31345 /*render_frame_impl=*/nullptr, /*is_main_frame=*/true,
346 &navigation_params);
Emily Stark1225b892019-07-03 05:51:34347 EXPECT_TRUE(
348 navigation_params.response.SecurityDetailsForTesting().has_value());
349}
350
Dmitry Gozmancd3529822019-01-11 21:12:16351} // namespace
352
353} // namespace content