• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 The Chromium Authors
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 "net/reporting/reporting_uploader.h"
6 
7 #include <memory>
8 #include <string>
9 #include <utility>
10 
11 #include "base/functional/bind.h"
12 #include "base/functional/callback.h"
13 #include "base/run_loop.h"
14 #include "base/test/scoped_feature_list.h"
15 #include "net/base/features.h"
16 #include "net/base/network_anonymization_key.h"
17 #include "net/base/schemeful_site.h"
18 #include "net/cookies/cookie_access_result.h"
19 #include "net/cookies/cookie_store.h"
20 #include "net/cookies/cookie_store_test_callbacks.h"
21 #include "net/http/http_status_code.h"
22 #include "net/socket/socket_test_util.h"
23 #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"
26 #include "net/test/test_with_task_environment.h"
27 #include "net/url_request/url_request_context.h"
28 #include "net/url_request/url_request_context_builder.h"
29 #include "net/url_request/url_request_test_util.h"
30 #include "testing/gtest/include/gtest/gtest.h"
31 #include "url/gurl.h"
32 #include "url/origin.h"
33 
34 namespace net {
35 namespace {
36 
37 class ReportingUploaderTest : public TestWithTaskEnvironment {
38  protected:
ReportingUploaderTest()39   ReportingUploaderTest()
40       : server_(test_server::EmbeddedTestServer::TYPE_HTTPS),
41         context_(CreateTestURLRequestContextBuilder()->Build()),
42         uploader_(ReportingUploader::Create(context_.get())) {}
43 
44   test_server::EmbeddedTestServer server_;
45   std::unique_ptr<URLRequestContext> context_;
46   std::unique_ptr<ReportingUploader> uploader_;
47 
48   const url::Origin kOrigin = url::Origin::Create(GURL("https://origin/"));
49 };
50 
51 const char kUploadBody[] = "{}";
52 
CheckUpload(const test_server::HttpRequest & request)53 void CheckUpload(const test_server::HttpRequest& request) {
54   if (request.method_string != "POST") {
55     return;
56   }
57   auto it = request.headers.find("Content-Type");
58   EXPECT_TRUE(it != request.headers.end());
59   EXPECT_EQ("application/reports+json", it->second);
60   EXPECT_TRUE(request.has_content);
61   EXPECT_EQ(kUploadBody, request.content);
62 }
63 
AllowPreflight(const test_server::HttpRequest & request)64 std::unique_ptr<test_server::HttpResponse> AllowPreflight(
65     const test_server::HttpRequest& request) {
66   if (request.method_string != "OPTIONS") {
67     return nullptr;
68   }
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 
ReturnResponse(HttpStatusCode code,const test_server::HttpRequest & request)81 std::unique_ptr<test_server::HttpResponse> ReturnResponse(
82     HttpStatusCode code,
83     const test_server::HttpRequest& request) {
84   auto response = std::make_unique<test_server::BasicHttpResponse>();
85   response->set_code(code);
86   response->set_content("");
87   response->set_content_type("text/plain");
88   return std::move(response);
89 }
90 
ReturnInvalidResponse(const test_server::HttpRequest & request)91 std::unique_ptr<test_server::HttpResponse> ReturnInvalidResponse(
92     const test_server::HttpRequest& request) {
93   return std::make_unique<test_server::RawHttpResponse>(
94       "", "Not a valid HTTP response.");
95 }
96 
97 class TestUploadCallback {
98  public:
99   TestUploadCallback() = default;
100 
callback()101   ReportingUploader::UploadCallback callback() {
102     return base::BindOnce(&TestUploadCallback::OnUploadComplete,
103                           base::Unretained(this));
104   }
105 
WaitForCall()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 
outcome() const117   ReportingUploader::Outcome outcome() const { return outcome_; }
118 
119  private:
OnUploadComplete(ReportingUploader::Outcome outcome)120   void OnUploadComplete(ReportingUploader::Outcome outcome) {
121     EXPECT_FALSE(called_);
122 
123     called_ = true;
124     outcome_ = outcome;
125 
126     if (waiting_) {
127       waiting_ = false;
128       std::move(closure_).Run();
129     }
130   }
131 
132   bool called_ = false;
133   ReportingUploader::Outcome outcome_;
134 
135   bool waiting_ = false;
136   base::OnceClosure closure_;
137 };
138 
TEST_F(ReportingUploaderTest,Upload)139 TEST_F(ReportingUploaderTest, Upload) {
140   server_.RegisterRequestMonitor(base::BindRepeating(&CheckUpload));
141   server_.RegisterRequestHandler(base::BindRepeating(&AllowPreflight));
142   server_.RegisterRequestHandler(base::BindRepeating(&ReturnResponse, HTTP_OK));
143   ASSERT_TRUE(server_.Start());
144 
145   TestUploadCallback callback;
146   uploader_->StartUpload(kOrigin, server_.GetURL("/"),
147                          IsolationInfo::CreateTransient(), kUploadBody, 0,
148                          false, callback.callback());
149   callback.WaitForCall();
150 }
151 
TEST_F(ReportingUploaderTest,Success)152 TEST_F(ReportingUploaderTest, Success) {
153   server_.RegisterRequestHandler(base::BindRepeating(&AllowPreflight));
154   server_.RegisterRequestHandler(base::BindRepeating(&ReturnResponse, HTTP_OK));
155   ASSERT_TRUE(server_.Start());
156 
157   TestUploadCallback callback;
158   uploader_->StartUpload(kOrigin, server_.GetURL("/"),
159                          IsolationInfo::CreateTransient(), kUploadBody, 0,
160                          false, callback.callback());
161   callback.WaitForCall();
162 
163   EXPECT_EQ(ReportingUploader::Outcome::SUCCESS, callback.outcome());
164 }
165 
TEST_F(ReportingUploaderTest,NetworkError1)166 TEST_F(ReportingUploaderTest, NetworkError1) {
167   ASSERT_TRUE(server_.Start());
168   GURL url = server_.GetURL("/");
169   ASSERT_TRUE(server_.ShutdownAndWaitUntilComplete());
170 
171   TestUploadCallback callback;
172   uploader_->StartUpload(kOrigin, url, IsolationInfo::CreateTransient(),
173                          kUploadBody, 0, false, callback.callback());
174   callback.WaitForCall();
175 
176   EXPECT_EQ(ReportingUploader::Outcome::FAILURE, callback.outcome());
177 }
178 
TEST_F(ReportingUploaderTest,NetworkError2)179 TEST_F(ReportingUploaderTest, NetworkError2) {
180   server_.RegisterRequestHandler(base::BindRepeating(&AllowPreflight));
181   server_.RegisterRequestHandler(base::BindRepeating(&ReturnInvalidResponse));
182   ASSERT_TRUE(server_.Start());
183 
184   TestUploadCallback callback;
185   uploader_->StartUpload(kOrigin, server_.GetURL("/"),
186                          IsolationInfo::CreateTransient(), kUploadBody, 0,
187                          false, callback.callback());
188   callback.WaitForCall();
189 
190   EXPECT_EQ(ReportingUploader::Outcome::FAILURE, callback.outcome());
191 }
192 
TEST_F(ReportingUploaderTest,ServerError)193 TEST_F(ReportingUploaderTest, ServerError) {
194   server_.RegisterRequestHandler(base::BindRepeating(&AllowPreflight));
195   server_.RegisterRequestHandler(
196       base::BindRepeating(&ReturnResponse, HTTP_INTERNAL_SERVER_ERROR));
197   ASSERT_TRUE(server_.Start());
198 
199   TestUploadCallback callback;
200   uploader_->StartUpload(kOrigin, server_.GetURL("/"),
201                          IsolationInfo::CreateTransient(), kUploadBody, 0,
202                          false, callback.callback());
203   callback.WaitForCall();
204 
205   EXPECT_EQ(ReportingUploader::Outcome::FAILURE, callback.outcome());
206 }
207 
VerifyPreflight(bool * preflight_received_out,const test_server::HttpRequest & request)208 std::unique_ptr<test_server::HttpResponse> VerifyPreflight(
209     bool* preflight_received_out,
210     const test_server::HttpRequest& request) {
211   if (request.method_string != "OPTIONS") {
212     return nullptr;
213   }
214   *preflight_received_out = true;
215   return AllowPreflight(request);
216 }
217 
TEST_F(ReportingUploaderTest,VerifyPreflight)218 TEST_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;
226   uploader_->StartUpload(kOrigin, server_.GetURL("/"),
227                          IsolationInfo::CreateTransient(), kUploadBody, 0,
228                          false, callback.callback());
229   callback.WaitForCall();
230 
231   EXPECT_TRUE(preflight_received);
232   EXPECT_EQ(ReportingUploader::Outcome::SUCCESS, callback.outcome());
233 }
234 
TEST_F(ReportingUploaderTest,SkipPreflightForSameOrigin)235 TEST_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());
244   uploader_->StartUpload(server_origin, server_.GetURL("/"),
245                          IsolationInfo::CreateTransient(), kUploadBody, 0,
246                          false, callback.callback());
247   callback.WaitForCall();
248 
249   EXPECT_FALSE(preflight_received);
250   EXPECT_EQ(ReportingUploader::Outcome::SUCCESS, callback.outcome());
251 }
252 
ReturnPreflightError(const test_server::HttpRequest & request)253 std::unique_ptr<test_server::HttpResponse> ReturnPreflightError(
254     const test_server::HttpRequest& request) {
255   if (request.method_string != "OPTIONS") {
256     return nullptr;
257   }
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 
TEST_F(ReportingUploaderTest,FailedCorsPreflight)265 TEST_F(ReportingUploaderTest, FailedCorsPreflight) {
266   server_.RegisterRequestHandler(base::BindRepeating(&ReturnPreflightError));
267   server_.RegisterRequestHandler(base::BindRepeating(&ReturnResponse, HTTP_OK));
268   ASSERT_TRUE(server_.Start());
269 
270   TestUploadCallback callback;
271   uploader_->StartUpload(kOrigin, server_.GetURL("/"),
272                          IsolationInfo::CreateTransient(), kUploadBody, 0,
273                          false, callback.callback());
274   callback.WaitForCall();
275 
276   EXPECT_EQ(ReportingUploader::Outcome::FAILURE, callback.outcome());
277 }
278 
ReturnPreflightWithoutOrigin(const test_server::HttpRequest & request)279 std::unique_ptr<test_server::HttpResponse> ReturnPreflightWithoutOrigin(
280     const test_server::HttpRequest& request) {
281   if (request.method_string != "OPTIONS") {
282     return nullptr;
283   }
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 
TEST_F(ReportingUploaderTest,CorsPreflightWithoutOrigin)295 TEST_F(ReportingUploaderTest, CorsPreflightWithoutOrigin) {
296   server_.RegisterRequestHandler(
297       base::BindRepeating(&ReturnPreflightWithoutOrigin));
298   server_.RegisterRequestHandler(base::BindRepeating(&ReturnResponse, HTTP_OK));
299   ASSERT_TRUE(server_.Start());
300 
301   TestUploadCallback callback;
302   uploader_->StartUpload(kOrigin, server_.GetURL("/"),
303                          IsolationInfo::CreateTransient(), kUploadBody, 0,
304                          false, callback.callback());
305   callback.WaitForCall();
306 
307   EXPECT_EQ(ReportingUploader::Outcome::FAILURE, callback.outcome());
308 }
309 
ReturnPreflightWithoutMethods(const test_server::HttpRequest & request)310 std::unique_ptr<test_server::HttpResponse> ReturnPreflightWithoutMethods(
311     const test_server::HttpRequest& request) {
312   if (request.method_string != "OPTIONS") {
313     return nullptr;
314   }
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 
TEST_F(ReportingUploaderTest,CorsPreflightWithoutMethods)326 TEST_F(ReportingUploaderTest, CorsPreflightWithoutMethods) {
327   server_.RegisterRequestHandler(
328       base::BindRepeating(&ReturnPreflightWithoutMethods));
329   server_.RegisterRequestHandler(base::BindRepeating(&ReturnResponse, HTTP_OK));
330   ASSERT_TRUE(server_.Start());
331 
332   TestUploadCallback callback;
333   uploader_->StartUpload(kOrigin, server_.GetURL("/"),
334                          IsolationInfo::CreateTransient(), kUploadBody, 0,
335                          false, callback.callback());
336   callback.WaitForCall();
337 
338   EXPECT_EQ(ReportingUploader::Outcome::SUCCESS, callback.outcome());
339 }
340 
ReturnPreflightWithWildcardMethods(const test_server::HttpRequest & request)341 std::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 
TEST_F(ReportingUploaderTest,CorsPreflightWildcardMethods)358 TEST_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());
371 }
372 
ReturnPreflightWithoutHeaders(const test_server::HttpRequest & request)373 std::unique_ptr<test_server::HttpResponse> ReturnPreflightWithoutHeaders(
374     const test_server::HttpRequest& request) {
375   if (request.method_string != "OPTIONS") {
376     return nullptr;
377   }
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 
TEST_F(ReportingUploaderTest,CorsPreflightWithoutHeaders)389 TEST_F(ReportingUploaderTest, CorsPreflightWithoutHeaders) {
390   server_.RegisterRequestHandler(
391       base::BindRepeating(&ReturnPreflightWithoutHeaders));
392   server_.RegisterRequestHandler(base::BindRepeating(&ReturnResponse, HTTP_OK));
393   ASSERT_TRUE(server_.Start());
394 
395   TestUploadCallback callback;
396   uploader_->StartUpload(kOrigin, server_.GetURL("/"),
397                          IsolationInfo::CreateTransient(), kUploadBody, 0,
398                          false, callback.callback());
399   callback.WaitForCall();
400 
401   EXPECT_EQ(ReportingUploader::Outcome::FAILURE, callback.outcome());
402 }
403 
ReturnPreflightWithWildcardHeaders(const test_server::HttpRequest & request)404 std::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 
TEST_F(ReportingUploaderTest,CorsPreflightWildcardHeaders)421 TEST_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 
TEST_F(ReportingUploaderTest,RemoveEndpoint)436 TEST_F(ReportingUploaderTest, RemoveEndpoint) {
437   server_.RegisterRequestHandler(base::BindRepeating(&AllowPreflight));
438   server_.RegisterRequestHandler(
439       base::BindRepeating(&ReturnResponse, HTTP_GONE));
440   ASSERT_TRUE(server_.Start());
441 
442   TestUploadCallback callback;
443   uploader_->StartUpload(kOrigin, server_.GetURL("/"),
444                          IsolationInfo::CreateTransient(), kUploadBody, 0,
445                          false, callback.callback());
446   callback.WaitForCall();
447 
448   EXPECT_EQ(ReportingUploader::Outcome::REMOVE_ENDPOINT, callback.outcome());
449 }
450 
451 const char kRedirectPath[] = "/redirect";
452 
ReturnRedirect(const std::string & location,const test_server::HttpRequest & request)453 std::unique_ptr<test_server::HttpResponse> ReturnRedirect(
454     const std::string& location,
455     const test_server::HttpRequest& request) {
456   if (request.relative_url != "/")
457     return nullptr;
458 
459   auto response = std::make_unique<test_server::BasicHttpResponse>();
460   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 
CheckRedirect(bool * redirect_followed_out,const test_server::HttpRequest & request)468 std::unique_ptr<test_server::HttpResponse> CheckRedirect(
469     bool* redirect_followed_out,
470     const test_server::HttpRequest& request) {
471   if (request.relative_url != kRedirectPath)
472     return nullptr;
473 
474   *redirect_followed_out = true;
475   return ReturnResponse(HTTP_OK, request);
476 }
477 
TEST_F(ReportingUploaderTest,FollowHttpsRedirect)478 TEST_F(ReportingUploaderTest, FollowHttpsRedirect) {
479   bool followed = false;
480   server_.RegisterRequestHandler(base::BindRepeating(&AllowPreflight));
481   server_.RegisterRequestHandler(
482       base::BindRepeating(&ReturnRedirect, kRedirectPath));
483   server_.RegisterRequestHandler(
484       base::BindRepeating(&CheckRedirect, &followed));
485   ASSERT_TRUE(server_.Start());
486 
487   TestUploadCallback callback;
488   uploader_->StartUpload(kOrigin, server_.GetURL("/"),
489                          IsolationInfo::CreateTransient(), kUploadBody, 0,
490                          false, callback.callback());
491   callback.WaitForCall();
492 
493   EXPECT_TRUE(followed);
494   EXPECT_EQ(ReportingUploader::Outcome::SUCCESS, callback.outcome());
495 }
496 
TEST_F(ReportingUploaderTest,DontFollowHttpRedirect)497 TEST_F(ReportingUploaderTest, DontFollowHttpRedirect) {
498   bool followed = false;
499 
500   test_server::EmbeddedTestServer http_server_;
501   http_server_.RegisterRequestHandler(
502       base::BindRepeating(&CheckRedirect, &followed));
503   ASSERT_TRUE(http_server_.Start());
504 
505   const GURL target = http_server_.GetURL(kRedirectPath);
506   server_.RegisterRequestHandler(base::BindRepeating(&AllowPreflight));
507   server_.RegisterRequestHandler(
508       base::BindRepeating(&ReturnRedirect, target.spec()));
509   ASSERT_TRUE(server_.Start());
510 
511   TestUploadCallback callback;
512   uploader_->StartUpload(kOrigin, server_.GetURL("/"),
513                          IsolationInfo::CreateTransient(), kUploadBody, 0,
514                          false, callback.callback());
515   callback.WaitForCall();
516 
517   EXPECT_FALSE(followed);
518   EXPECT_EQ(ReportingUploader::Outcome::FAILURE, callback.outcome());
519 }
520 
CheckNoCookie(const test_server::HttpRequest & request)521 void CheckNoCookie(const test_server::HttpRequest& request) {
522   auto it = request.headers.find("Cookie");
523   EXPECT_TRUE(it == request.headers.end());
524 }
525 
TEST_F(ReportingUploaderTest,DontSendCookies)526 TEST_F(ReportingUploaderTest, DontSendCookies) {
527   server_.RegisterRequestMonitor(base::BindRepeating(&CheckNoCookie));
528   server_.RegisterRequestHandler(base::BindRepeating(&AllowPreflight));
529   server_.RegisterRequestHandler(base::BindRepeating(&ReturnResponse, HTTP_OK));
530   ASSERT_TRUE(server_.Start());
531 
532   ResultSavingCookieCallback<CookieAccessResult> cookie_callback;
533   GURL url = server_.GetURL("/");
534   auto cookie = CanonicalCookie::Create(
535       url, "foo=bar", base::Time::Now(), absl::nullopt /* server_time */,
536       absl::nullopt /* cookie_partition_key */);
537   context_->cookie_store()->SetCanonicalCookieAsync(
538       std::move(cookie), url, CookieOptions::MakeAllInclusive(),
539       cookie_callback.MakeCallback());
540   cookie_callback.WaitUntilDone();
541   ASSERT_TRUE(cookie_callback.result().status.IsInclude());
542 
543   TestUploadCallback upload_callback;
544   uploader_->StartUpload(kOrigin, server_.GetURL("/"),
545                          IsolationInfo::CreateTransient(), kUploadBody, 0,
546                          false, upload_callback.callback());
547   upload_callback.WaitForCall();
548 }
549 
SendCookie(const test_server::HttpRequest & request)550 std::unique_ptr<test_server::HttpResponse> SendCookie(
551     const test_server::HttpRequest& request) {
552   auto response = std::make_unique<test_server::BasicHttpResponse>();
553   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 
TEST_F(ReportingUploaderTest,DontSaveCookies)560 TEST_F(ReportingUploaderTest, DontSaveCookies) {
561   server_.RegisterRequestHandler(base::BindRepeating(&AllowPreflight));
562   server_.RegisterRequestHandler(base::BindRepeating(&SendCookie));
563   ASSERT_TRUE(server_.Start());
564 
565   TestUploadCallback upload_callback;
566   uploader_->StartUpload(kOrigin, server_.GetURL("/"),
567                          IsolationInfo::CreateTransient(), kUploadBody, 0,
568                          false, upload_callback.callback());
569   upload_callback.WaitForCall();
570 
571   GetCookieListCallback cookie_callback;
572   context_->cookie_store()->GetCookieListWithOptionsAsync(
573       server_.GetURL("/"), CookieOptions::MakeAllInclusive(),
574       CookiePartitionKeyCollection(),
575       base::BindOnce(&GetCookieListCallback::Run,
576                      base::Unretained(&cookie_callback)));
577   cookie_callback.WaitUntilDone();
578 
579   EXPECT_TRUE(cookie_callback.cookies().empty());
580 }
581 
ReturnCacheableResponse(int * request_count_out,const test_server::HttpRequest & request)582 std::unique_ptr<test_server::HttpResponse> ReturnCacheableResponse(
583     int* request_count_out,
584     const test_server::HttpRequest& request) {
585   ++*request_count_out;
586   auto response = std::make_unique<test_server::BasicHttpResponse>();
587   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.
TEST_F(ReportingUploaderTest,DontCacheResponse)598 TEST_F(ReportingUploaderTest, DontCacheResponse) {
599   int request_count = 0;
600   server_.RegisterRequestHandler(base::BindRepeating(&AllowPreflight));
601   server_.RegisterRequestHandler(
602       base::BindRepeating(&ReturnCacheableResponse, &request_count));
603   ASSERT_TRUE(server_.Start());
604 
605   {
606     TestUploadCallback callback;
607     uploader_->StartUpload(kOrigin, server_.GetURL("/"),
608                            IsolationInfo::CreateTransient(), kUploadBody, 0,
609                            false, callback.callback());
610     callback.WaitForCall();
611   }
612   EXPECT_EQ(1, request_count);
613 
614   {
615     TestUploadCallback callback;
616     uploader_->StartUpload(kOrigin, server_.GetURL("/"),
617                            IsolationInfo::CreateTransient(), kUploadBody, 0,
618                            false, callback.callback());
619     callback.WaitForCall();
620   }
621   EXPECT_EQ(2, request_count);
622 }
623 
624 // 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.
TEST_F(ReportingUploaderTest,RespectsNetworkAnonymizationKey)627 TEST_F(ReportingUploaderTest, RespectsNetworkAnonymizationKey) {
628   // While network state partitioning is not needed for reporting code to
629   // respect NetworkAnonymizationKey, this test works by ensuring that
630   // Reporting's NetworkAnonymizationKey makes it to the socket pool layer and
631   // is respected there, so this test needs to enable
632   // network state partitioning.
633   base::test::ScopedFeatureList feature_list;
634   feature_list.InitAndEnableFeature(
635       features::kPartitionConnectionsByNetworkIsolationKey);
636 
637   const SchemefulSite kSite1 = SchemefulSite(kOrigin);
638   const SchemefulSite kSite2(GURL("https://origin2/"));
639   ASSERT_NE(kSite1, kSite2);
640   const NetworkIsolationKey kNetworkIsolationKey1(kSite1, kSite1);
641   const NetworkIsolationKey kNetworkIsolationKey2(kSite2, kSite2);
642   const url::Origin kSiteOrigin1 = url::Origin::Create(kSite1.GetURL());
643   const url::Origin kSiteOrigin2 = url::Origin::Create(kSite2.GetURL());
644   const IsolationInfo kIsolationInfo1 =
645       IsolationInfo::Create(net::IsolationInfo::RequestType::kOther,
646                             kSiteOrigin1, kSiteOrigin1, net::SiteForCookies());
647   const IsolationInfo kIsolationInfo2 =
648       IsolationInfo::Create(net::IsolationInfo::RequestType::kOther,
649                             kSiteOrigin2, kSiteOrigin2, net::SiteForCookies());
650 
651   MockClientSocketFactory socket_factory;
652   auto context_builder = CreateTestURLRequestContextBuilder();
653   context_builder->set_client_socket_factory_for_testing(&socket_factory);
654   auto context = context_builder->Build();
655 
656   // First socket handles first and third requests.
657   MockWrite writes1[] = {
658       MockWrite(SYNCHRONOUS, 0,
659                 "POST /1 HTTP/1.1\r\n"
660                 "Host: origin\r\n"
661                 "Connection: keep-alive\r\n"
662                 "Content-Length: 2\r\n"
663                 "Content-Type: application/reports+json\r\n"
664                 "User-Agent: \r\n"
665                 "Accept-Encoding: gzip, deflate\r\n"
666                 "Accept-Language: en-us,fr\r\n\r\n"),
667       MockWrite(SYNCHRONOUS, 1, kUploadBody),
668       MockWrite(SYNCHRONOUS, 3,
669                 "POST /3 HTTP/1.1\r\n"
670                 "Host: origin\r\n"
671                 "Connection: keep-alive\r\n"
672                 "Content-Length: 2\r\n"
673                 "Content-Type: application/reports+json\r\n"
674                 "User-Agent: \r\n"
675                 "Accept-Encoding: gzip, deflate\r\n"
676                 "Accept-Language: en-us,fr\r\n\r\n"),
677       MockWrite(SYNCHRONOUS, 4, kUploadBody),
678   };
679   MockRead reads1[] = {
680       MockRead(SYNCHRONOUS, 2,
681                "HTTP/1.1 200 OK\r\n"
682                "Connection: Keep-Alive\r\n"
683                "Content-Length: 0\r\n\r\n"),
684       MockRead(SYNCHRONOUS, 5,
685                "HTTP/1.1 200 OK\r\n"
686                "Connection: Keep-Alive\r\n"
687                "Content-Length: 0\r\n\r\n"),
688   };
689   SequencedSocketData data1(reads1, writes1);
690   socket_factory.AddSocketDataProvider(&data1);
691   SSLSocketDataProvider ssl_data1(ASYNC, OK);
692   socket_factory.AddSSLSocketDataProvider(&ssl_data1);
693 
694   // Second socket handles second request.
695   MockWrite writes2[] = {
696       MockWrite(SYNCHRONOUS, 0,
697                 "POST /2 HTTP/1.1\r\n"
698                 "Host: origin\r\n"
699                 "Connection: keep-alive\r\n"
700                 "Content-Length: 2\r\n"
701                 "Content-Type: application/reports+json\r\n"
702                 "User-Agent: \r\n"
703                 "Accept-Encoding: gzip, deflate\r\n"
704                 "Accept-Language: en-us,fr\r\n\r\n"),
705       MockWrite(SYNCHRONOUS, 1, kUploadBody),
706   };
707   MockRead reads2[] = {
708       MockRead(SYNCHRONOUS, 2,
709                "HTTP/1.1 200 OK\r\n"
710                "Connection: Keep-Alive\r\n"
711                "Content-Length: 0\r\n\r\n"),
712   };
713   SequencedSocketData data2(reads2, writes2);
714   socket_factory.AddSocketDataProvider(&data2);
715   SSLSocketDataProvider ssl_data2(ASYNC, OK);
716   socket_factory.AddSSLSocketDataProvider(&ssl_data2);
717 
718   TestUploadCallback callback1;
719   std::unique_ptr<ReportingUploader> uploader1 =
720       ReportingUploader::Create(context.get());
721   uploader1->StartUpload(kOrigin, GURL("https://origin/1"), kIsolationInfo1,
722                          kUploadBody, 0, false, callback1.callback());
723   callback1.WaitForCall();
724   EXPECT_EQ(ReportingUploader::Outcome::SUCCESS, callback1.outcome());
725 
726   // Start two more requests in parallel. The first started uses a different
727   // NetworkAnonymizationKey, so should create a new socket, while the second
728   // one gets the other socket. Start in parallel to make sure that a new socket
729   // isn't created just because the first is returned to the socket pool
730   // asynchronously.
731   TestUploadCallback callback2;
732   std::unique_ptr<ReportingUploader> uploader2 =
733       ReportingUploader::Create(context.get());
734   uploader2->StartUpload(kOrigin, GURL("https://origin/2"), kIsolationInfo2,
735                          kUploadBody, 0, false, callback2.callback());
736   TestUploadCallback callback3;
737   std::unique_ptr<ReportingUploader> uploader3 =
738       ReportingUploader::Create(context.get());
739   uploader3->StartUpload(kOrigin, GURL("https://origin/3"), kIsolationInfo1,
740                          kUploadBody, 0, false, callback3.callback());
741 
742   callback2.WaitForCall();
743   EXPECT_EQ(ReportingUploader::Outcome::SUCCESS, callback2.outcome());
744 
745   callback3.WaitForCall();
746   EXPECT_EQ(ReportingUploader::Outcome::SUCCESS, callback3.outcome());
747 }
748 
749 }  // namespace
750 }  // namespace net
751