blob: 366fa424620ae025b95c63674d1483fce8c29d26 [file] [log] [blame]
Avi Drissman64595482022-09-14 20:52:291// Copyright 2017 The Chromium Authors
juliatuttle2f46b5782017-03-30 19:12:372// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/reporting/reporting_uploader.h"
6
7#include <memory>
8#include <string>
juliatuttlea35bbc82017-05-22 19:25:199#include <utility>
juliatuttle2f46b5782017-03-30 19:12:3710
Avi Drissman41c4a412023-01-11 22:45:3711#include "base/functional/bind.h"
12#include "base/functional/callback.h"
juliatuttle2f46b5782017-03-30 19:12:3713#include "base/run_loop.h"
Matt Menke5577421a2019-10-10 00:04:4914#include "base/test/scoped_feature_list.h"
15#include "net/base/features.h"
Brianna Goldsteina56efdb2022-10-06 19:55:5416#include "net/base/network_anonymization_key.h"
Matt Menke4807a9a2020-11-21 00:14:4117#include "net/base/schemeful_site.h"
Ayu Ishiif3966ca2020-07-08 17:35:1218#include "net/cookies/cookie_access_result.h"
juliatuttle2f46b5782017-03-30 19:12:3719#include "net/cookies/cookie_store.h"
20#include "net/cookies/cookie_store_test_callbacks.h"
21#include "net/http/http_status_code.h"
Matt Menke5577421a2019-10-10 00:04:4922#include "net/socket/socket_test_util.h"
juliatuttle2f46b5782017-03-30 19:12:3723#include "net/test/embedded_test_server/embedded_test_server.h"
24#include "net/test/embedded_test_server/http_request.h"
25#include "net/test/embedded_test_server/http_response.h"
Gabriel Charettec7108742019-08-23 03:31:4026#include "net/test/test_with_task_environment.h"
Yutaka Hiranod81ac3f2022-03-23 15:08:3427#include "net/url_request/url_request_context.h"
28#include "net/url_request/url_request_context_builder.h"
juliatuttle2f46b5782017-03-30 19:12:3729#include "net/url_request/url_request_test_util.h"
30#include "testing/gtest/include/gtest/gtest.h"
Matt Menke4807a9a2020-11-21 00:14:4131#include "url/gurl.h"
32#include "url/origin.h"
juliatuttle2f46b5782017-03-30 19:12:3733
34namespace net {
35namespace {
36
Gabriel Charette694c3c332019-08-19 14:53:0537class ReportingUploaderTest : public TestWithTaskEnvironment {
juliatuttle2f46b5782017-03-30 19:12:3738 protected:
39 ReportingUploaderTest()
40 : server_(test_server::EmbeddedTestServer::TYPE_HTTPS),
Yutaka Hiranod81ac3f2022-03-23 15:08:3441 context_(CreateTestURLRequestContextBuilder()->Build()),
42 uploader_(ReportingUploader::Create(context_.get())) {}
juliatuttle2f46b5782017-03-30 19:12:3743
juliatuttle2f46b5782017-03-30 19:12:3744 test_server::EmbeddedTestServer server_;
Yutaka Hiranod81ac3f2022-03-23 15:08:3445 std::unique_ptr<URLRequestContext> context_;
juliatuttle2f46b5782017-03-30 19:12:3746 std::unique_ptr<ReportingUploader> uploader_;
Douglas Creager3428d812018-07-13 03:59:5647
48 const url::Origin kOrigin = url::Origin::Create(GURL("https://origin/"));
juliatuttle2f46b5782017-03-30 19:12:3749};
50
51const char kUploadBody[] = "{}";
52
53void CheckUpload(const test_server::HttpRequest& request) {
Douglas Creager3428d812018-07-13 03:59:5654 if (request.method_string != "POST") {
55 return;
56 }
juliatuttle2f46b5782017-03-30 19:12:3757 auto it = request.headers.find("Content-Type");
58 EXPECT_TRUE(it != request.headers.end());
Douglas Creager048472b2018-07-27 15:48:0459 EXPECT_EQ("application/reports+json", it->second);
juliatuttle2f46b5782017-03-30 19:12:3760 EXPECT_TRUE(request.has_content);
61 EXPECT_EQ(kUploadBody, request.content);
62}
63
Douglas Creager3428d812018-07-13 03:59:5664std::unique_ptr<test_server::HttpResponse> AllowPreflight(
65 const test_server::HttpRequest& request) {
66 if (request.method_string != "OPTIONS") {
Lei Zhangd4a78b42021-04-14 16:40:3567 return nullptr;
Douglas Creager3428d812018-07-13 03:59:5668 }
69 auto it = request.headers.find("Origin");
70 EXPECT_TRUE(it != request.headers.end());
71 auto response = std::make_unique<test_server::BasicHttpResponse>();
72 response->AddCustomHeader("Access-Control-Allow-Origin", it->second);
73 response->AddCustomHeader("Access-Control-Allow-Methods", "POST");
74 response->AddCustomHeader("Access-Control-Allow-Headers", "Content-Type");
75 response->set_code(HTTP_OK);
76 response->set_content("");
77 response->set_content_type("text/plain");
78 return std::move(response);
79}
80
juliatuttle2f46b5782017-03-30 19:12:3781std::unique_ptr<test_server::HttpResponse> ReturnResponse(
82 HttpStatusCode code,
83 const test_server::HttpRequest& request) {
Jeremy Roman0579ed62017-08-29 15:56:1984 auto response = std::make_unique<test_server::BasicHttpResponse>();
juliatuttle2f46b5782017-03-30 19:12:3785 response->set_code(code);
86 response->set_content("");
87 response->set_content_type("text/plain");
88 return std::move(response);
89}
90
91std::unique_ptr<test_server::HttpResponse> ReturnInvalidResponse(
92 const test_server::HttpRequest& request) {
Jeremy Roman0579ed62017-08-29 15:56:1993 return std::make_unique<test_server::RawHttpResponse>(
juliatuttle2f46b5782017-03-30 19:12:3794 "", "Not a valid HTTP response.");
95}
96
97class TestUploadCallback {
98 public:
Tsuyoshi Horo2ec06e002022-06-09 01:38:5999 TestUploadCallback() = default;
juliatuttle2f46b5782017-03-30 19:12:37100
Julia Tuttleed8d84b2017-12-05 18:54:53101 ReportingUploader::UploadCallback callback() {
102 return base::BindOnce(&TestUploadCallback::OnUploadComplete,
103 base::Unretained(this));
juliatuttle2f46b5782017-03-30 19:12:37104 }
105
106 void WaitForCall() {
107 if (called_)
108 return;
109
110 base::RunLoop run_loop;
111
112 waiting_ = true;
113 closure_ = run_loop.QuitClosure();
114 run_loop.Run();
115 }
116
117 ReportingUploader::Outcome outcome() const { return outcome_; }
118
119 private:
120 void OnUploadComplete(ReportingUploader::Outcome outcome) {
121 EXPECT_FALSE(called_);
122
123 called_ = true;
124 outcome_ = outcome;
125
126 if (waiting_) {
127 waiting_ = false;
Steve Kobes3ad84b52020-07-09 00:30:02128 std::move(closure_).Run();
juliatuttle2f46b5782017-03-30 19:12:37129 }
130 }
131
Tsuyoshi Horo2ec06e002022-06-09 01:38:59132 bool called_ = false;
juliatuttle2f46b5782017-03-30 19:12:37133 ReportingUploader::Outcome outcome_;
134
Tsuyoshi Horo2ec06e002022-06-09 01:38:59135 bool waiting_ = false;
Steve Kobes3ad84b52020-07-09 00:30:02136 base::OnceClosure closure_;
juliatuttle2f46b5782017-03-30 19:12:37137};
138
139TEST_F(ReportingUploaderTest, Upload) {
Julia Tuttleed8d84b2017-12-05 18:54:53140 server_.RegisterRequestMonitor(base::BindRepeating(&CheckUpload));
Douglas Creager3428d812018-07-13 03:59:56141 server_.RegisterRequestHandler(base::BindRepeating(&AllowPreflight));
Julia Tuttleed8d84b2017-12-05 18:54:53142 server_.RegisterRequestHandler(base::BindRepeating(&ReturnResponse, HTTP_OK));
juliatuttle2f46b5782017-03-30 19:12:37143 ASSERT_TRUE(server_.Start());
144
145 TestUploadCallback callback;
Ian Clelland52035be2021-10-07 16:38:50146 uploader_->StartUpload(kOrigin, server_.GetURL("/"),
147 IsolationInfo::CreateTransient(), kUploadBody, 0,
148 false, callback.callback());
juliatuttle2f46b5782017-03-30 19:12:37149 callback.WaitForCall();
150}
151
152TEST_F(ReportingUploaderTest, Success) {
Douglas Creager3428d812018-07-13 03:59:56153 server_.RegisterRequestHandler(base::BindRepeating(&AllowPreflight));
Julia Tuttleed8d84b2017-12-05 18:54:53154 server_.RegisterRequestHandler(base::BindRepeating(&ReturnResponse, HTTP_OK));
juliatuttle2f46b5782017-03-30 19:12:37155 ASSERT_TRUE(server_.Start());
156
157 TestUploadCallback callback;
Ian Clelland52035be2021-10-07 16:38:50158 uploader_->StartUpload(kOrigin, server_.GetURL("/"),
159 IsolationInfo::CreateTransient(), kUploadBody, 0,
160 false, callback.callback());
juliatuttle2f46b5782017-03-30 19:12:37161 callback.WaitForCall();
162
163 EXPECT_EQ(ReportingUploader::Outcome::SUCCESS, callback.outcome());
164}
165
166TEST_F(ReportingUploaderTest, NetworkError1) {
167 ASSERT_TRUE(server_.Start());
168 GURL url = server_.GetURL("/");
169 ASSERT_TRUE(server_.ShutdownAndWaitUntilComplete());
170
171 TestUploadCallback callback;
Ian Clelland52035be2021-10-07 16:38:50172 uploader_->StartUpload(kOrigin, url, IsolationInfo::CreateTransient(),
173 kUploadBody, 0, false, callback.callback());
juliatuttle2f46b5782017-03-30 19:12:37174 callback.WaitForCall();
175
176 EXPECT_EQ(ReportingUploader::Outcome::FAILURE, callback.outcome());
177}
178
179TEST_F(ReportingUploaderTest, NetworkError2) {
Douglas Creager3428d812018-07-13 03:59:56180 server_.RegisterRequestHandler(base::BindRepeating(&AllowPreflight));
Julia Tuttleed8d84b2017-12-05 18:54:53181 server_.RegisterRequestHandler(base::BindRepeating(&ReturnInvalidResponse));
juliatuttle2f46b5782017-03-30 19:12:37182 ASSERT_TRUE(server_.Start());
183
184 TestUploadCallback callback;
Ian Clelland52035be2021-10-07 16:38:50185 uploader_->StartUpload(kOrigin, server_.GetURL("/"),
186 IsolationInfo::CreateTransient(), kUploadBody, 0,
187 false, callback.callback());
juliatuttle2f46b5782017-03-30 19:12:37188 callback.WaitForCall();
189
190 EXPECT_EQ(ReportingUploader::Outcome::FAILURE, callback.outcome());
191}
192
193TEST_F(ReportingUploaderTest, ServerError) {
Douglas Creager3428d812018-07-13 03:59:56194 server_.RegisterRequestHandler(base::BindRepeating(&AllowPreflight));
juliatuttle2f46b5782017-03-30 19:12:37195 server_.RegisterRequestHandler(
Julia Tuttleed8d84b2017-12-05 18:54:53196 base::BindRepeating(&ReturnResponse, HTTP_INTERNAL_SERVER_ERROR));
juliatuttle2f46b5782017-03-30 19:12:37197 ASSERT_TRUE(server_.Start());
198
199 TestUploadCallback callback;
Ian Clelland52035be2021-10-07 16:38:50200 uploader_->StartUpload(kOrigin, server_.GetURL("/"),
201 IsolationInfo::CreateTransient(), kUploadBody, 0,
202 false, callback.callback());
Douglas Creager3428d812018-07-13 03:59:56203 callback.WaitForCall();
204
205 EXPECT_EQ(ReportingUploader::Outcome::FAILURE, callback.outcome());
206}
207
208std::unique_ptr<test_server::HttpResponse> VerifyPreflight(
209 bool* preflight_received_out,
210 const test_server::HttpRequest& request) {
211 if (request.method_string != "OPTIONS") {
Lei Zhangd4a78b42021-04-14 16:40:35212 return nullptr;
Douglas Creager3428d812018-07-13 03:59:56213 }
214 *preflight_received_out = true;
215 return AllowPreflight(request);
216}
217
218TEST_F(ReportingUploaderTest, VerifyPreflight) {
219 bool preflight_received = false;
220 server_.RegisterRequestHandler(
221 base::BindRepeating(&VerifyPreflight, &preflight_received));
222 server_.RegisterRequestHandler(base::BindRepeating(&ReturnResponse, HTTP_OK));
223 ASSERT_TRUE(server_.Start());
224
225 TestUploadCallback callback;
Ian Clelland52035be2021-10-07 16:38:50226 uploader_->StartUpload(kOrigin, server_.GetURL("/"),
227 IsolationInfo::CreateTransient(), kUploadBody, 0,
228 false, callback.callback());
Douglas Creager3428d812018-07-13 03:59:56229 callback.WaitForCall();
230
231 EXPECT_TRUE(preflight_received);
232 EXPECT_EQ(ReportingUploader::Outcome::SUCCESS, callback.outcome());
233}
234
235TEST_F(ReportingUploaderTest, SkipPreflightForSameOrigin) {
236 bool preflight_received = false;
237 server_.RegisterRequestHandler(
238 base::BindRepeating(&VerifyPreflight, &preflight_received));
239 server_.RegisterRequestHandler(base::BindRepeating(&ReturnResponse, HTTP_OK));
240 ASSERT_TRUE(server_.Start());
241
242 TestUploadCallback callback;
243 auto server_origin = url::Origin::Create(server_.base_url());
Matt Menke5577421a2019-10-10 00:04:49244 uploader_->StartUpload(server_origin, server_.GetURL("/"),
Ian Clelland52035be2021-10-07 16:38:50245 IsolationInfo::CreateTransient(), kUploadBody, 0,
246 false, callback.callback());
Douglas Creager3428d812018-07-13 03:59:56247 callback.WaitForCall();
248
249 EXPECT_FALSE(preflight_received);
250 EXPECT_EQ(ReportingUploader::Outcome::SUCCESS, callback.outcome());
251}
252
253std::unique_ptr<test_server::HttpResponse> ReturnPreflightError(
254 const test_server::HttpRequest& request) {
255 if (request.method_string != "OPTIONS") {
Lei Zhangd4a78b42021-04-14 16:40:35256 return nullptr;
Douglas Creager3428d812018-07-13 03:59:56257 }
258 auto response = std::make_unique<test_server::BasicHttpResponse>();
259 response->set_code(HTTP_FORBIDDEN);
260 response->set_content("");
261 response->set_content_type("text/plain");
262 return std::move(response);
263}
264
Takashi Toyoshima2e01e692018-11-16 03:23:27265TEST_F(ReportingUploaderTest, FailedCorsPreflight) {
Douglas Creager3428d812018-07-13 03:59:56266 server_.RegisterRequestHandler(base::BindRepeating(&ReturnPreflightError));
267 server_.RegisterRequestHandler(base::BindRepeating(&ReturnResponse, HTTP_OK));
268 ASSERT_TRUE(server_.Start());
269
270 TestUploadCallback callback;
Ian Clelland52035be2021-10-07 16:38:50271 uploader_->StartUpload(kOrigin, server_.GetURL("/"),
272 IsolationInfo::CreateTransient(), kUploadBody, 0,
273 false, callback.callback());
Douglas Creager3428d812018-07-13 03:59:56274 callback.WaitForCall();
275
276 EXPECT_EQ(ReportingUploader::Outcome::FAILURE, callback.outcome());
277}
278
279std::unique_ptr<test_server::HttpResponse> ReturnPreflightWithoutOrigin(
280 const test_server::HttpRequest& request) {
281 if (request.method_string != "OPTIONS") {
Lei Zhangd4a78b42021-04-14 16:40:35282 return nullptr;
Douglas Creager3428d812018-07-13 03:59:56283 }
284 auto it = request.headers.find("Origin");
285 EXPECT_TRUE(it != request.headers.end());
286 auto response = std::make_unique<test_server::BasicHttpResponse>();
287 response->AddCustomHeader("Access-Control-Allow-Methods", "POST");
288 response->AddCustomHeader("Access-Control-Allow-Headers", "Content-Type");
289 response->set_code(HTTP_OK);
290 response->set_content("");
291 response->set_content_type("text/plain");
292 return std::move(response);
293}
294
Takashi Toyoshima2e01e692018-11-16 03:23:27295TEST_F(ReportingUploaderTest, CorsPreflightWithoutOrigin) {
Douglas Creager3428d812018-07-13 03:59:56296 server_.RegisterRequestHandler(
297 base::BindRepeating(&ReturnPreflightWithoutOrigin));
298 server_.RegisterRequestHandler(base::BindRepeating(&ReturnResponse, HTTP_OK));
299 ASSERT_TRUE(server_.Start());
300
301 TestUploadCallback callback;
Ian Clelland52035be2021-10-07 16:38:50302 uploader_->StartUpload(kOrigin, server_.GetURL("/"),
303 IsolationInfo::CreateTransient(), kUploadBody, 0,
304 false, callback.callback());
Douglas Creager3428d812018-07-13 03:59:56305 callback.WaitForCall();
306
307 EXPECT_EQ(ReportingUploader::Outcome::FAILURE, callback.outcome());
308}
309
310std::unique_ptr<test_server::HttpResponse> ReturnPreflightWithoutMethods(
311 const test_server::HttpRequest& request) {
312 if (request.method_string != "OPTIONS") {
Lei Zhangd4a78b42021-04-14 16:40:35313 return nullptr;
Douglas Creager3428d812018-07-13 03:59:56314 }
315 auto it = request.headers.find("Origin");
316 EXPECT_TRUE(it != request.headers.end());
317 auto response = std::make_unique<test_server::BasicHttpResponse>();
318 response->AddCustomHeader("Access-Control-Allow-Origin", it->second);
319 response->AddCustomHeader("Access-Control-Allow-Headers", "Content-Type");
320 response->set_code(HTTP_OK);
321 response->set_content("");
322 response->set_content_type("text/plain");
323 return std::move(response);
324}
325
Takashi Toyoshima2e01e692018-11-16 03:23:27326TEST_F(ReportingUploaderTest, CorsPreflightWithoutMethods) {
Douglas Creager3428d812018-07-13 03:59:56327 server_.RegisterRequestHandler(
328 base::BindRepeating(&ReturnPreflightWithoutMethods));
329 server_.RegisterRequestHandler(base::BindRepeating(&ReturnResponse, HTTP_OK));
330 ASSERT_TRUE(server_.Start());
331
332 TestUploadCallback callback;
Ian Clelland52035be2021-10-07 16:38:50333 uploader_->StartUpload(kOrigin, server_.GetURL("/"),
334 IsolationInfo::CreateTransient(), kUploadBody, 0,
335 false, callback.callback());
Douglas Creager3428d812018-07-13 03:59:56336 callback.WaitForCall();
337
Ian Clelland7ccccbf22022-01-17 14:43:24338 EXPECT_EQ(ReportingUploader::Outcome::SUCCESS, callback.outcome());
339}
340
341std::unique_ptr<test_server::HttpResponse> ReturnPreflightWithWildcardMethods(
342 const test_server::HttpRequest& request) {
343 if (request.method_string != "OPTIONS") {
344 return nullptr;
345 }
346 auto it = request.headers.find("Origin");
347 EXPECT_TRUE(it != request.headers.end());
348 auto response = std::make_unique<test_server::BasicHttpResponse>();
349 response->AddCustomHeader("Access-Control-Allow-Origin", it->second);
350 response->AddCustomHeader("Access-Control-Allow-Headers", "Content-Type");
351 response->AddCustomHeader("Access-Control-Allow-Methods", "*");
352 response->set_code(HTTP_OK);
353 response->set_content("");
354 response->set_content_type("text/plain");
355 return std::move(response);
356}
357
358TEST_F(ReportingUploaderTest, CorsPreflightWildcardMethods) {
359 server_.RegisterRequestHandler(
360 base::BindRepeating(&ReturnPreflightWithWildcardMethods));
361 server_.RegisterRequestHandler(base::BindRepeating(&ReturnResponse, HTTP_OK));
362 ASSERT_TRUE(server_.Start());
363
364 TestUploadCallback callback;
365 uploader_->StartUpload(kOrigin, server_.GetURL("/"),
366 IsolationInfo::CreateTransient(), kUploadBody, 0,
367 false, callback.callback());
368 callback.WaitForCall();
369
370 EXPECT_EQ(ReportingUploader::Outcome::SUCCESS, callback.outcome());
Douglas Creager3428d812018-07-13 03:59:56371}
372
373std::unique_ptr<test_server::HttpResponse> ReturnPreflightWithoutHeaders(
374 const test_server::HttpRequest& request) {
375 if (request.method_string != "OPTIONS") {
Lei Zhangd4a78b42021-04-14 16:40:35376 return nullptr;
Douglas Creager3428d812018-07-13 03:59:56377 }
378 auto it = request.headers.find("Origin");
379 EXPECT_TRUE(it != request.headers.end());
380 auto response = std::make_unique<test_server::BasicHttpResponse>();
381 response->AddCustomHeader("Access-Control-Allow-Origin", it->second);
382 response->AddCustomHeader("Access-Control-Allow-Methods", "POST");
383 response->set_code(HTTP_OK);
384 response->set_content("");
385 response->set_content_type("text/plain");
386 return std::move(response);
387}
388
Takashi Toyoshima2e01e692018-11-16 03:23:27389TEST_F(ReportingUploaderTest, CorsPreflightWithoutHeaders) {
Douglas Creager3428d812018-07-13 03:59:56390 server_.RegisterRequestHandler(
391 base::BindRepeating(&ReturnPreflightWithoutHeaders));
392 server_.RegisterRequestHandler(base::BindRepeating(&ReturnResponse, HTTP_OK));
393 ASSERT_TRUE(server_.Start());
394
395 TestUploadCallback callback;
Ian Clelland52035be2021-10-07 16:38:50396 uploader_->StartUpload(kOrigin, server_.GetURL("/"),
397 IsolationInfo::CreateTransient(), kUploadBody, 0,
398 false, callback.callback());
juliatuttle2f46b5782017-03-30 19:12:37399 callback.WaitForCall();
400
401 EXPECT_EQ(ReportingUploader::Outcome::FAILURE, callback.outcome());
402}
403
Ian Clelland7ccccbf22022-01-17 14:43:24404std::unique_ptr<test_server::HttpResponse> ReturnPreflightWithWildcardHeaders(
405 const test_server::HttpRequest& request) {
406 if (request.method_string != "OPTIONS") {
407 return nullptr;
408 }
409 auto it = request.headers.find("Origin");
410 EXPECT_TRUE(it != request.headers.end());
411 auto response = std::make_unique<test_server::BasicHttpResponse>();
412 response->AddCustomHeader("Access-Control-Allow-Origin", it->second);
413 response->AddCustomHeader("Access-Control-Allow-Headers", "*");
414 response->AddCustomHeader("Access-Control-Allow-Methods", "POST");
415 response->set_code(HTTP_OK);
416 response->set_content("");
417 response->set_content_type("text/plain");
418 return std::move(response);
419}
420
421TEST_F(ReportingUploaderTest, CorsPreflightWildcardHeaders) {
422 server_.RegisterRequestHandler(
423 base::BindRepeating(&ReturnPreflightWithWildcardHeaders));
424 server_.RegisterRequestHandler(base::BindRepeating(&ReturnResponse, HTTP_OK));
425 ASSERT_TRUE(server_.Start());
426
427 TestUploadCallback callback;
428 uploader_->StartUpload(kOrigin, server_.GetURL("/"),
429 IsolationInfo::CreateTransient(), kUploadBody, 0,
430 false, callback.callback());
431 callback.WaitForCall();
432
433 EXPECT_EQ(ReportingUploader::Outcome::SUCCESS, callback.outcome());
434}
435
juliatuttle2f46b5782017-03-30 19:12:37436TEST_F(ReportingUploaderTest, RemoveEndpoint) {
Douglas Creager3428d812018-07-13 03:59:56437 server_.RegisterRequestHandler(base::BindRepeating(&AllowPreflight));
Julia Tuttleed8d84b2017-12-05 18:54:53438 server_.RegisterRequestHandler(
439 base::BindRepeating(&ReturnResponse, HTTP_GONE));
juliatuttle2f46b5782017-03-30 19:12:37440 ASSERT_TRUE(server_.Start());
441
442 TestUploadCallback callback;
Ian Clelland52035be2021-10-07 16:38:50443 uploader_->StartUpload(kOrigin, server_.GetURL("/"),
444 IsolationInfo::CreateTransient(), kUploadBody, 0,
445 false, callback.callback());
juliatuttle2f46b5782017-03-30 19:12:37446 callback.WaitForCall();
447
448 EXPECT_EQ(ReportingUploader::Outcome::REMOVE_ENDPOINT, callback.outcome());
449}
450
451const char kRedirectPath[] = "/redirect";
452
453std::unique_ptr<test_server::HttpResponse> ReturnRedirect(
454 const std::string& location,
455 const test_server::HttpRequest& request) {
456 if (request.relative_url != "/")
Lei Zhangd4a78b42021-04-14 16:40:35457 return nullptr;
juliatuttle2f46b5782017-03-30 19:12:37458
Jeremy Roman0579ed62017-08-29 15:56:19459 auto response = std::make_unique<test_server::BasicHttpResponse>();
juliatuttle2f46b5782017-03-30 19:12:37460 response->set_code(HTTP_FOUND);
461 response->AddCustomHeader("Location", location);
462 response->set_content(
463 "Thank you, Mario! But our Princess is in another castle.");
464 response->set_content_type("text/plain");
465 return std::move(response);
466}
467
468std::unique_ptr<test_server::HttpResponse> CheckRedirect(
469 bool* redirect_followed_out,
470 const test_server::HttpRequest& request) {
471 if (request.relative_url != kRedirectPath)
Lei Zhangd4a78b42021-04-14 16:40:35472 return nullptr;
juliatuttle2f46b5782017-03-30 19:12:37473
474 *redirect_followed_out = true;
475 return ReturnResponse(HTTP_OK, request);
476}
477
478TEST_F(ReportingUploaderTest, FollowHttpsRedirect) {
479 bool followed = false;
Douglas Creager3428d812018-07-13 03:59:56480 server_.RegisterRequestHandler(base::BindRepeating(&AllowPreflight));
Julia Tuttleed8d84b2017-12-05 18:54:53481 server_.RegisterRequestHandler(
482 base::BindRepeating(&ReturnRedirect, kRedirectPath));
483 server_.RegisterRequestHandler(
484 base::BindRepeating(&CheckRedirect, &followed));
juliatuttle2f46b5782017-03-30 19:12:37485 ASSERT_TRUE(server_.Start());
486
487 TestUploadCallback callback;
Ian Clelland52035be2021-10-07 16:38:50488 uploader_->StartUpload(kOrigin, server_.GetURL("/"),
489 IsolationInfo::CreateTransient(), kUploadBody, 0,
490 false, callback.callback());
juliatuttle2f46b5782017-03-30 19:12:37491 callback.WaitForCall();
492
493 EXPECT_TRUE(followed);
494 EXPECT_EQ(ReportingUploader::Outcome::SUCCESS, callback.outcome());
495}
496
497TEST_F(ReportingUploaderTest, DontFollowHttpRedirect) {
498 bool followed = false;
499
500 test_server::EmbeddedTestServer http_server_;
Julia Tuttleed8d84b2017-12-05 18:54:53501 http_server_.RegisterRequestHandler(
502 base::BindRepeating(&CheckRedirect, &followed));
juliatuttle2f46b5782017-03-30 19:12:37503 ASSERT_TRUE(http_server_.Start());
504
505 const GURL target = http_server_.GetURL(kRedirectPath);
Douglas Creager3428d812018-07-13 03:59:56506 server_.RegisterRequestHandler(base::BindRepeating(&AllowPreflight));
Julia Tuttleed8d84b2017-12-05 18:54:53507 server_.RegisterRequestHandler(
508 base::BindRepeating(&ReturnRedirect, target.spec()));
juliatuttle2f46b5782017-03-30 19:12:37509 ASSERT_TRUE(server_.Start());
510
511 TestUploadCallback callback;
Ian Clelland52035be2021-10-07 16:38:50512 uploader_->StartUpload(kOrigin, server_.GetURL("/"),
513 IsolationInfo::CreateTransient(), kUploadBody, 0,
514 false, callback.callback());
juliatuttle2f46b5782017-03-30 19:12:37515 callback.WaitForCall();
516
517 EXPECT_FALSE(followed);
518 EXPECT_EQ(ReportingUploader::Outcome::FAILURE, callback.outcome());
519}
520
521void CheckNoCookie(const test_server::HttpRequest& request) {
522 auto it = request.headers.find("Cookie");
523 EXPECT_TRUE(it == request.headers.end());
524}
525
526TEST_F(ReportingUploaderTest, DontSendCookies) {
Julia Tuttleed8d84b2017-12-05 18:54:53527 server_.RegisterRequestMonitor(base::BindRepeating(&CheckNoCookie));
Douglas Creager3428d812018-07-13 03:59:56528 server_.RegisterRequestHandler(base::BindRepeating(&AllowPreflight));
Julia Tuttleed8d84b2017-12-05 18:54:53529 server_.RegisterRequestHandler(base::BindRepeating(&ReturnResponse, HTTP_OK));
juliatuttle2f46b5782017-03-30 19:12:37530 ASSERT_TRUE(server_.Start());
531
Ayu Ishiif3966ca2020-07-08 17:35:12532 ResultSavingCookieCallback<CookieAccessResult> cookie_callback;
Lily Chen0f208ea2019-08-08 23:37:53533 GURL url = server_.GetURL("/");
Dylan Cutlerf4a802b2021-08-03 16:38:54534 auto cookie = CanonicalCookie::Create(
535 url, "foo=bar", base::Time::Now(), absl::nullopt /* server_time */,
536 absl::nullopt /* cookie_partition_key */);
Yutaka Hiranod81ac3f2022-03-23 15:08:34537 context_->cookie_store()->SetCanonicalCookieAsync(
Lily Chen96f29a132020-04-15 17:59:36538 std::move(cookie), url, CookieOptions::MakeAllInclusive(),
Lily Chen0f208ea2019-08-08 23:37:53539 cookie_callback.MakeCallback());
juliatuttle2f46b5782017-03-30 19:12:37540 cookie_callback.WaitUntilDone();
Ayu Ishiif3966ca2020-07-08 17:35:12541 ASSERT_TRUE(cookie_callback.result().status.IsInclude());
juliatuttle2f46b5782017-03-30 19:12:37542
543 TestUploadCallback upload_callback;
Ian Clelland52035be2021-10-07 16:38:50544 uploader_->StartUpload(kOrigin, server_.GetURL("/"),
545 IsolationInfo::CreateTransient(), kUploadBody, 0,
546 false, upload_callback.callback());
juliatuttle2f46b5782017-03-30 19:12:37547 upload_callback.WaitForCall();
548}
549
550std::unique_ptr<test_server::HttpResponse> SendCookie(
551 const test_server::HttpRequest& request) {
Jeremy Roman0579ed62017-08-29 15:56:19552 auto response = std::make_unique<test_server::BasicHttpResponse>();
juliatuttle2f46b5782017-03-30 19:12:37553 response->set_code(HTTP_OK);
554 response->AddCustomHeader("Set-Cookie", "foo=bar");
555 response->set_content("");
556 response->set_content_type("text/plain");
557 return std::move(response);
558}
559
560TEST_F(ReportingUploaderTest, DontSaveCookies) {
Douglas Creager3428d812018-07-13 03:59:56561 server_.RegisterRequestHandler(base::BindRepeating(&AllowPreflight));
Julia Tuttleed8d84b2017-12-05 18:54:53562 server_.RegisterRequestHandler(base::BindRepeating(&SendCookie));
juliatuttle2f46b5782017-03-30 19:12:37563 ASSERT_TRUE(server_.Start());
564
565 TestUploadCallback upload_callback;
Ian Clelland52035be2021-10-07 16:38:50566 uploader_->StartUpload(kOrigin, server_.GetURL("/"),
567 IsolationInfo::CreateTransient(), kUploadBody, 0,
568 false, upload_callback.callback());
juliatuttle2f46b5782017-03-30 19:12:37569 upload_callback.WaitForCall();
570
571 GetCookieListCallback cookie_callback;
Yutaka Hiranod81ac3f2022-03-23 15:08:34572 context_->cookie_store()->GetCookieListWithOptionsAsync(
Maks Orlovich9d8225a52019-10-22 18:01:46573 server_.GetURL("/"), CookieOptions::MakeAllInclusive(),
Aykut Bulut244341e2021-12-09 15:57:25574 CookiePartitionKeyCollection(),
Yannic Bonenberger29ec48f2019-08-31 04:20:23575 base::BindOnce(&GetCookieListCallback::Run,
576 base::Unretained(&cookie_callback)));
juliatuttle2f46b5782017-03-30 19:12:37577 cookie_callback.WaitUntilDone();
578
579 EXPECT_TRUE(cookie_callback.cookies().empty());
580}
581
582std::unique_ptr<test_server::HttpResponse> ReturnCacheableResponse(
583 int* request_count_out,
584 const test_server::HttpRequest& request) {
585 ++*request_count_out;
Jeremy Roman0579ed62017-08-29 15:56:19586 auto response = std::make_unique<test_server::BasicHttpResponse>();
juliatuttle2f46b5782017-03-30 19:12:37587 response->set_code(HTTP_OK);
588 response->AddCustomHeader("Cache-Control", "max-age=86400");
589 response->set_content("");
590 response->set_content_type("text/plain");
591 return std::move(response);
592}
593
594// TODO(juliatuttle): This passes even if the uploader doesn't set
595// LOAD_DISABLE_CACHE. Maybe that's okay -- Chromium might not cache POST
596// responses ever -- but this test should either not exist or be sure that it is
597// testing actual functionality, not a default.
598TEST_F(ReportingUploaderTest, DontCacheResponse) {
599 int request_count = 0;
Douglas Creager3428d812018-07-13 03:59:56600 server_.RegisterRequestHandler(base::BindRepeating(&AllowPreflight));
juliatuttle2f46b5782017-03-30 19:12:37601 server_.RegisterRequestHandler(
Julia Tuttleed8d84b2017-12-05 18:54:53602 base::BindRepeating(&ReturnCacheableResponse, &request_count));
juliatuttle2f46b5782017-03-30 19:12:37603 ASSERT_TRUE(server_.Start());
604
605 {
606 TestUploadCallback callback;
Ian Clelland52035be2021-10-07 16:38:50607 uploader_->StartUpload(kOrigin, server_.GetURL("/"),
608 IsolationInfo::CreateTransient(), kUploadBody, 0,
609 false, callback.callback());
juliatuttle2f46b5782017-03-30 19:12:37610 callback.WaitForCall();
611 }
612 EXPECT_EQ(1, request_count);
613
614 {
615 TestUploadCallback callback;
Ian Clelland52035be2021-10-07 16:38:50616 uploader_->StartUpload(kOrigin, server_.GetURL("/"),
617 IsolationInfo::CreateTransient(), kUploadBody, 0,
618 false, callback.callback());
juliatuttle2f46b5782017-03-30 19:12:37619 callback.WaitForCall();
620 }
621 EXPECT_EQ(2, request_count);
622}
623
Brianna Goldsteina56efdb2022-10-06 19:55:54624// Create two requests with the same NetworkAnonymizationKey, and one request
625// with a different one, and make sure only the requests with the same
626// NetworkAnonymizationKey share a socket.
Brianna Goldsteind22b0642022-10-11 16:30:50627TEST_F(ReportingUploaderTest, RespectsNetworkAnonymizationKey) {
Matt Menke5577421a2019-10-10 00:04:49628 // While features::kPartitionConnectionsByNetworkIsolationKey is not needed
Brianna Goldsteind22b0642022-10-11 16:30:50629 // for reporting code to respect NetworkAnonymizationKey, this test works by
Brianna Goldsteina56efdb2022-10-06 19:55:54630 // ensuring that Reporting's NetworkAnonymizationKey makes it to the socket
631 // pool layer and is respected there, so this test needs to enable
Matt Menke5577421a2019-10-10 00:04:49632 // kPartitionConnectionsByNetworkIsolationKey.
633 base::test::ScopedFeatureList feature_list;
634 feature_list.InitAndEnableFeature(
635 features::kPartitionConnectionsByNetworkIsolationKey);
636
Matt Menke4807a9a2020-11-21 00:14:41637 const SchemefulSite kSite1 = SchemefulSite(kOrigin);
638 const SchemefulSite kSite2(GURL("https://origin2/"));
639 ASSERT_NE(kSite1, kSite2);
Brianna Goldsteind22b0642022-10-11 16:30:50640 const NetworkIsolationKey kNetworkIsolationKey1(kSite1, kSite1);
641 const NetworkIsolationKey kNetworkIsolationKey2(kSite2, kSite2);
Ian Clelland52035be2021-10-07 16:38:50642 const IsolationInfo kIsolationInfo1 = IsolationInfo::CreatePartial(
643 IsolationInfo::RequestType::kOther, kNetworkIsolationKey1);
644 const IsolationInfo kIsolationInfo2 = IsolationInfo::CreatePartial(
645 IsolationInfo::RequestType::kOther, kNetworkIsolationKey2);
Matt Menke5577421a2019-10-10 00:04:49646
647 MockClientSocketFactory socket_factory;
Yutaka Hiranod81ac3f2022-03-23 15:08:34648 auto context_builder = CreateTestURLRequestContextBuilder();
649 context_builder->set_client_socket_factory_for_testing(&socket_factory);
650 auto context = context_builder->Build();
Matt Menke5577421a2019-10-10 00:04:49651
652 // First socket handles first and third requests.
653 MockWrite writes1[] = {
654 MockWrite(SYNCHRONOUS, 0,
655 "POST /1 HTTP/1.1\r\n"
656 "Host: origin\r\n"
657 "Connection: keep-alive\r\n"
658 "Content-Length: 2\r\n"
659 "Content-Type: application/reports+json\r\n"
660 "User-Agent: \r\n"
661 "Accept-Encoding: gzip, deflate\r\n"
662 "Accept-Language: en-us,fr\r\n\r\n"),
663 MockWrite(SYNCHRONOUS, 1, kUploadBody),
664 MockWrite(SYNCHRONOUS, 3,
665 "POST /3 HTTP/1.1\r\n"
666 "Host: origin\r\n"
667 "Connection: keep-alive\r\n"
668 "Content-Length: 2\r\n"
669 "Content-Type: application/reports+json\r\n"
670 "User-Agent: \r\n"
671 "Accept-Encoding: gzip, deflate\r\n"
672 "Accept-Language: en-us,fr\r\n\r\n"),
673 MockWrite(SYNCHRONOUS, 4, kUploadBody),
674 };
675 MockRead reads1[] = {
676 MockRead(SYNCHRONOUS, 2,
677 "HTTP/1.1 200 OK\r\n"
678 "Connection: Keep-Alive\r\n"
679 "Content-Length: 0\r\n\r\n"),
680 MockRead(SYNCHRONOUS, 5,
681 "HTTP/1.1 200 OK\r\n"
682 "Connection: Keep-Alive\r\n"
683 "Content-Length: 0\r\n\r\n"),
684 };
685 SequencedSocketData data1(reads1, writes1);
686 socket_factory.AddSocketDataProvider(&data1);
687 SSLSocketDataProvider ssl_data1(ASYNC, OK);
688 socket_factory.AddSSLSocketDataProvider(&ssl_data1);
689
690 // Second socket handles second request.
691 MockWrite writes2[] = {
692 MockWrite(SYNCHRONOUS, 0,
693 "POST /2 HTTP/1.1\r\n"
694 "Host: origin\r\n"
695 "Connection: keep-alive\r\n"
696 "Content-Length: 2\r\n"
697 "Content-Type: application/reports+json\r\n"
698 "User-Agent: \r\n"
699 "Accept-Encoding: gzip, deflate\r\n"
700 "Accept-Language: en-us,fr\r\n\r\n"),
701 MockWrite(SYNCHRONOUS, 1, kUploadBody),
702 };
703 MockRead reads2[] = {
704 MockRead(SYNCHRONOUS, 2,
705 "HTTP/1.1 200 OK\r\n"
706 "Connection: Keep-Alive\r\n"
707 "Content-Length: 0\r\n\r\n"),
708 };
709 SequencedSocketData data2(reads2, writes2);
710 socket_factory.AddSocketDataProvider(&data2);
711 SSLSocketDataProvider ssl_data2(ASYNC, OK);
712 socket_factory.AddSSLSocketDataProvider(&ssl_data2);
713
714 TestUploadCallback callback1;
715 std::unique_ptr<ReportingUploader> uploader1 =
Yutaka Hiranod81ac3f2022-03-23 15:08:34716 ReportingUploader::Create(context.get());
Ian Clelland52035be2021-10-07 16:38:50717 uploader1->StartUpload(kOrigin, GURL("https://origin/1"), kIsolationInfo1,
718 kUploadBody, 0, false, callback1.callback());
Matt Menke5577421a2019-10-10 00:04:49719 callback1.WaitForCall();
720 EXPECT_EQ(ReportingUploader::Outcome::SUCCESS, callback1.outcome());
721
722 // Start two more requests in parallel. The first started uses a different
Brianna Goldsteina56efdb2022-10-06 19:55:54723 // NetworkAnonymizationKey, so should create a new socket, while the second
724 // one gets the other socket. Start in parallel to make sure that a new socket
Matt Menke5577421a2019-10-10 00:04:49725 // isn't created just because the first is returned to the socket pool
726 // asynchronously.
727 TestUploadCallback callback2;
728 std::unique_ptr<ReportingUploader> uploader2 =
Yutaka Hiranod81ac3f2022-03-23 15:08:34729 ReportingUploader::Create(context.get());
Ian Clelland52035be2021-10-07 16:38:50730 uploader2->StartUpload(kOrigin, GURL("https://origin/2"), kIsolationInfo2,
731 kUploadBody, 0, false, callback2.callback());
Matt Menke5577421a2019-10-10 00:04:49732 TestUploadCallback callback3;
733 std::unique_ptr<ReportingUploader> uploader3 =
Yutaka Hiranod81ac3f2022-03-23 15:08:34734 ReportingUploader::Create(context.get());
Ian Clelland52035be2021-10-07 16:38:50735 uploader3->StartUpload(kOrigin, GURL("https://origin/3"), kIsolationInfo1,
736 kUploadBody, 0, false, callback3.callback());
Matt Menke5577421a2019-10-10 00:04:49737
738 callback2.WaitForCall();
739 EXPECT_EQ(ReportingUploader::Outcome::SUCCESS, callback2.outcome());
740
741 callback3.WaitForCall();
742 EXPECT_EQ(ReportingUploader::Outcome::SUCCESS, callback3.outcome());
743}
744
juliatuttle2f46b5782017-03-30 19:12:37745} // namespace
746} // namespace net