blob: adc23795f11305a571d0daa7c3fe05d871000489 [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"
11#include "base/test/scoped_task_environment.h"
12#include "services/network/public/cpp/url_loader_completion_status.h"
13#include "testing/gtest/include/gtest/gtest.h"
14#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
15#include "third_party/blink/public/platform/web_navigation_body_loader.h"
16
17namespace content {
18
19namespace {
20
21class NavigationBodyLoaderTest : public ::testing::Test,
22 public blink::WebNavigationBodyLoader::Client {
23 protected:
24 NavigationBodyLoaderTest() {}
25
26 ~NavigationBodyLoaderTest() override { base::RunLoop().RunUntilIdle(); }
27
28 MojoCreateDataPipeOptions CreateDataPipeOptions() {
29 MojoCreateDataPipeOptions options;
30 options.struct_size = sizeof(MojoCreateDataPipeOptions);
31 options.flags = MOJO_CREATE_DATA_PIPE_FLAG_NONE;
32 options.element_num_bytes = 1;
33 options.capacity_num_bytes = 1024;
34 return options;
35 }
36
37 void CreateBodyLoader() {
38 data_pipe_ = std::make_unique<mojo::DataPipe>(CreateDataPipeOptions());
39 writer_ = std::move(data_pipe_->producer_handle);
40 auto endpoints = network::mojom::URLLoaderClientEndpoints::New();
41 endpoints->url_loader_client = mojo::MakeRequest(&client_ptr_);
42 loader_ = std::make_unique<NavigationBodyLoader>(
Dmitry Gozmanb33c67a2019-01-16 02:20:4943 CommonNavigationParams(), CommitNavigationParams(), 1 /* request_id */,
44 network::ResourceResponseHead(), std::move(endpoints),
Dmitry Gozmancd3529822019-01-11 21:12:1645 blink::scheduler::GetSingleThreadTaskRunnerForTesting(),
Dmitry Gozmanb33c67a2019-01-16 02:20:4946 2 /* render_frame_id */, true /* is_main_frame */);
Dmitry Gozmancd3529822019-01-11 21:12:1647 }
48
49 void StartLoading() {
50 loader_->StartLoadingBody(this, false /* use_isolated_code_cache */);
51 client_ptr_->OnStartLoadingResponseBody(
52 std::move(data_pipe_->consumer_handle));
53 base::RunLoop().RunUntilIdle();
54 }
55
56 void Write(const std::string& buffer) {
57 uint32_t size = buffer.size();
58 MojoResult result = writer_->WriteData(buffer.c_str(), &size, kNone);
59 ASSERT_EQ(MOJO_RESULT_OK, result);
60 ASSERT_EQ(buffer.size(), size);
61 }
62
63 void Complete(int net_error) {
64 client_ptr_->OnComplete(network::URLLoaderCompletionStatus(net_error));
65 base::RunLoop().RunUntilIdle();
66 }
67
68 void BodyCodeCacheReceived(base::span<const uint8_t>) override {}
69
70 void BodyDataReceived(base::span<const char> data) override {
71 ASSERT_TRUE(expecting_data_received_);
72 did_receive_data_ = true;
73 data_received_ += std::string(data.data(), data.size());
74 TakeActions();
75 if (run_loop_.running())
76 run_loop_.Quit();
77 }
78
79 void BodyLoadingFinished(
80 base::TimeTicks completion_time,
81 int64_t total_encoded_data_length,
82 int64_t total_encoded_body_length,
83 int64_t total_decoded_body_length,
84 bool should_report_corb_blocking,
85 const base::Optional<blink::WebURLError>& error) override {
86 ASSERT_TRUE(expecting_finished_);
87 did_finish_ = true;
88 error_ = error;
89 TakeActions();
90 if (run_loop_.running())
91 run_loop_.Quit();
92 }
93
94 void TakeActions() {
95 if (!buffer_to_write_.empty()) {
96 std::string buffer = buffer_to_write_;
97 buffer_to_write_ = std::string();
98 ExpectDataReceived();
99 Write(buffer);
100 }
101 if (toggle_defers_loading_) {
102 toggle_defers_loading_ = false;
103 loader_->SetDefersLoading(false);
104 loader_->SetDefersLoading(true);
105 }
106 if (destroy_loader_) {
107 destroy_loader_ = false;
108 loader_.reset();
109 }
110 }
111
112 void ExpectDataReceived() {
113 expecting_data_received_ = true;
114 did_receive_data_ = false;
115 }
116
117 void ExpectFinished() {
118 expecting_finished_ = true;
119 did_finish_ = false;
120 }
121
122 std::string TakeDataReceived() {
123 std::string data = data_received_;
124 data_received_ = std::string();
125 return data;
126 }
127
128 void Wait() {
129 if (expecting_data_received_) {
130 if (!did_receive_data_)
131 run_loop_.Run();
132 ASSERT_TRUE(did_receive_data_);
133 expecting_data_received_ = false;
134 }
135 if (expecting_finished_) {
136 if (!did_finish_)
137 run_loop_.Run();
138 ASSERT_TRUE(did_finish_);
139 expecting_finished_ = false;
140 }
141 }
142
143 base::test::ScopedTaskEnvironment task_environment_;
144 static const MojoWriteDataFlags kNone = MOJO_WRITE_DATA_FLAG_NONE;
145 network::mojom::URLLoaderClientPtr client_ptr_;
146 std::unique_ptr<blink::WebNavigationBodyLoader> loader_;
147 std::unique_ptr<mojo::DataPipe> data_pipe_;
148 mojo::ScopedDataPipeProducerHandle writer_;
149
150 base::RunLoop run_loop_;
151 bool expecting_data_received_ = false;
152 bool did_receive_data_ = false;
153 bool expecting_finished_ = false;
154 bool did_finish_ = false;
155 std::string buffer_to_write_;
156 bool toggle_defers_loading_ = false;
157 bool destroy_loader_ = false;
158 std::string data_received_;
159 base::Optional<blink::WebURLError> error_;
160};
161
Dmitry Gozman98e8b192019-01-17 13:15:24162TEST_F(NavigationBodyLoaderTest, SetDefersBeforeStart) {
163 CreateBodyLoader();
164 loader_->SetDefersLoading(true);
165 loader_->SetDefersLoading(false);
166 // Should not crash.
167}
168
Dmitry Gozmancd3529822019-01-11 21:12:16169TEST_F(NavigationBodyLoaderTest, DataReceived) {
170 CreateBodyLoader();
171 StartLoading();
172 ExpectDataReceived();
173 Write("hello");
174 Wait();
175 EXPECT_EQ("hello", TakeDataReceived());
176}
177
178TEST_F(NavigationBodyLoaderTest, DataReceivedFromDataReceived) {
179 CreateBodyLoader();
180 StartLoading();
181 ExpectDataReceived();
182 buffer_to_write_ = "world";
183 Write("hello");
184 Wait();
185 EXPECT_EQ("helloworld", TakeDataReceived());
186}
187
188TEST_F(NavigationBodyLoaderTest, DestroyFromDataReceived) {
189 CreateBodyLoader();
190 StartLoading();
191 ExpectDataReceived();
192 destroy_loader_ = false;
193 Write("hello");
194 Wait();
195 EXPECT_EQ("hello", TakeDataReceived());
196}
197
198TEST_F(NavigationBodyLoaderTest, SetDefersLoadingFromDataReceived) {
199 CreateBodyLoader();
200 StartLoading();
201 ExpectDataReceived();
202 toggle_defers_loading_ = true;
203 Write("hello");
204 Wait();
205 EXPECT_EQ("hello", TakeDataReceived());
206}
207
208TEST_F(NavigationBodyLoaderTest, StartDeferred) {
209 CreateBodyLoader();
210 loader_->SetDefersLoading(true);
211 StartLoading();
212 Write("hello");
213 ExpectDataReceived();
214 loader_->SetDefersLoading(false);
215 Wait();
216 EXPECT_EQ("hello", TakeDataReceived());
217}
218
219TEST_F(NavigationBodyLoaderTest, OnCompleteThenClose) {
220 CreateBodyLoader();
221 StartLoading();
222 Complete(net::ERR_FAILED);
223 ExpectFinished();
224 writer_.reset();
225 Wait();
226 EXPECT_TRUE(error_.has_value());
227}
228
229TEST_F(NavigationBodyLoaderTest, DestroyFromOnCompleteThenClose) {
230 CreateBodyLoader();
231 StartLoading();
232 Complete(net::ERR_FAILED);
233 ExpectFinished();
234 destroy_loader_ = true;
235 writer_.reset();
236 Wait();
237 EXPECT_TRUE(error_.has_value());
238}
239
240TEST_F(NavigationBodyLoaderTest, SetDefersLoadingFromOnCompleteThenClose) {
241 CreateBodyLoader();
242 StartLoading();
243 Complete(net::ERR_FAILED);
244 ExpectFinished();
245 toggle_defers_loading_ = true;
246 writer_.reset();
247 Wait();
248 EXPECT_TRUE(error_.has_value());
249}
250
251TEST_F(NavigationBodyLoaderTest, CloseThenOnComplete) {
252 CreateBodyLoader();
253 StartLoading();
254 writer_.reset();
255 ExpectFinished();
256 Complete(net::ERR_FAILED);
257 Wait();
258 EXPECT_TRUE(error_.has_value());
259}
260
261TEST_F(NavigationBodyLoaderTest, DestroyFromCloseThenOnComplete) {
262 CreateBodyLoader();
263 StartLoading();
264 writer_.reset();
265 ExpectFinished();
266 destroy_loader_ = true;
267 Complete(net::ERR_FAILED);
268 Wait();
269 EXPECT_TRUE(error_.has_value());
270}
271
272TEST_F(NavigationBodyLoaderTest, SetDefersLoadingFromCloseThenOnComplete) {
273 CreateBodyLoader();
274 StartLoading();
275 writer_.reset();
276 ExpectFinished();
277 toggle_defers_loading_ = true;
278 Complete(net::ERR_FAILED);
279 Wait();
280 EXPECT_TRUE(error_.has_value());
281}
282
283} // namespace
284
285} // namespace content