NEL: Don't crash on failed requests without response headers

Make sure we have response headers before trying to get the response
code. Also, add a unittest that uses an EmbeddedTestServer to make sure
we're exercising the interaction with URLRequestHttpJob. Also also,
convert some related Bind calls to BindRepeating.

Bug: 792971
Change-Id: I4e7dcde3526f137af032bc44b41bac085e201715
Reviewed-on: https://chromium-review.googlesource.com/814837
Commit-Queue: Julia Tuttle <[email protected]>
Reviewed-by: Miriam Gershenson <[email protected]>
Cr-Commit-Position: refs/heads/master@{#522873}
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
index 764451c..035a5349 100644
--- a/net/url_request/url_request_unittest.cc
+++ b/net/url_request/url_request_unittest.cc
@@ -7060,7 +7060,8 @@
 }  // namespace
 
 TEST_F(URLRequestTestHTTP, DontProcessReportToHeaderNoService) {
-  http_test_server()->RegisterRequestHandler(base::Bind(&SendReportToHeader));
+  http_test_server()->RegisterRequestHandler(
+      base::BindRepeating(&SendReportToHeader));
   ASSERT_TRUE(http_test_server()->Start());
   GURL request_url = http_test_server()->GetURL("/");
 
@@ -7077,7 +7078,8 @@
 }
 
 TEST_F(URLRequestTestHTTP, DontProcessReportToHeaderHTTP) {
-  http_test_server()->RegisterRequestHandler(base::Bind(&SendReportToHeader));
+  http_test_server()->RegisterRequestHandler(
+      base::BindRepeating(&SendReportToHeader));
   ASSERT_TRUE(http_test_server()->Start());
   GURL request_url = http_test_server()->GetURL("/");
 
@@ -7099,7 +7101,8 @@
 
 TEST_F(URLRequestTestHTTP, ProcessReportToHeaderHTTPS) {
   EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
-  https_test_server.RegisterRequestHandler(base::Bind(&SendReportToHeader));
+  https_test_server.RegisterRequestHandler(
+      base::BindRepeating(&SendReportToHeader));
   ASSERT_TRUE(https_test_server.Start());
   GURL request_url = https_test_server.GetURL("/");
 
@@ -7124,7 +7127,8 @@
 TEST_F(URLRequestTestHTTP, DontProcessReportToHeaderInvalidHttps) {
   EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
   https_test_server.SetSSLConfig(net::EmbeddedTestServer::CERT_MISMATCHED_NAME);
-  https_test_server.RegisterRequestHandler(base::Bind(&SendReportToHeader));
+  https_test_server.RegisterRequestHandler(
+      base::BindRepeating(&SendReportToHeader));
   ASSERT_TRUE(https_test_server.Start());
   GURL request_url = https_test_server.GetURL("/");
 
@@ -7199,10 +7203,16 @@
   return std::move(http_response);
 }
 
+std::unique_ptr<test_server::HttpResponse> SendEmptyResponse(
+    const test_server::HttpRequest& request) {
+  return base::MakeUnique<test_server::RawHttpResponse>("", "");
+}
+
 }  // namespace
 
 TEST_F(URLRequestTestHTTP, DontProcessNelHeaderNoDelegate) {
-  http_test_server()->RegisterRequestHandler(base::Bind(&SendNelHeader));
+  http_test_server()->RegisterRequestHandler(
+      base::BindRepeating(&SendNelHeader));
   ASSERT_TRUE(http_test_server()->Start());
   GURL request_url = http_test_server()->GetURL("/");
 
@@ -7219,7 +7229,8 @@
 }
 
 TEST_F(URLRequestTestHTTP, DontProcessNelHeaderHttp) {
-  http_test_server()->RegisterRequestHandler(base::Bind(&SendNelHeader));
+  http_test_server()->RegisterRequestHandler(
+      base::BindRepeating(&SendNelHeader));
   ASSERT_TRUE(http_test_server()->Start());
   GURL request_url = http_test_server()->GetURL("/");
 
@@ -7241,7 +7252,7 @@
 
 TEST_F(URLRequestTestHTTP, ProcessNelHeaderHttps) {
   EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
-  https_test_server.RegisterRequestHandler(base::Bind(&SendNelHeader));
+  https_test_server.RegisterRequestHandler(base::BindRepeating(&SendNelHeader));
   ASSERT_TRUE(https_test_server.Start());
   GURL request_url = https_test_server.GetURL("/");
 
@@ -7266,7 +7277,7 @@
 TEST_F(URLRequestTestHTTP, DontProcessNelHeaderInvalidHttps) {
   EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
   https_test_server.SetSSLConfig(net::EmbeddedTestServer::CERT_MISMATCHED_NAME);
-  https_test_server.RegisterRequestHandler(base::Bind(&SendNelHeader));
+  https_test_server.RegisterRequestHandler(base::BindRepeating(&SendNelHeader));
   ASSERT_TRUE(https_test_server.Start());
   GURL request_url = https_test_server.GetURL("/");
 
@@ -7335,7 +7346,7 @@
   URLRequestFilter::GetInstance()->ClearHandlers();
 }
 
-TEST_F(URLRequestTestHTTP, ForwardErrorToNelHttps) {
+TEST_F(URLRequestTestHTTP, ForwardErrorToNelHttps_Mock) {
   URLRequestFailedJob::AddUrlHandler();
 
   GURL request_url =
@@ -7362,6 +7373,34 @@
   URLRequestFilter::GetInstance()->ClearHandlers();
 }
 
+// Also test with a real server, to exercise interactions with
+// URLRequestHttpJob.
+TEST_F(URLRequestTestHTTP, ForwardErrorToNelHttps_Real) {
+  EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
+  https_test_server.RegisterRequestHandler(
+      base::BindRepeating(&SendEmptyResponse));
+  ASSERT_TRUE(https_test_server.Start());
+  GURL request_url = https_test_server.GetURL("/");
+
+  TestNetworkDelegate network_delegate;
+  TestNetworkErrorLoggingDelegate nel_delegate;
+  TestURLRequestContext context(true);
+  context.set_network_delegate(&network_delegate);
+  context.set_network_error_logging_delegate(&nel_delegate);
+  context.Init();
+
+  TestDelegate d;
+  std::unique_ptr<URLRequest> request(context.CreateRequest(
+      request_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
+  request->Start();
+  base::RunLoop().Run();
+
+  ASSERT_EQ(1u, nel_delegate.errors().size());
+  EXPECT_EQ(request_url, nel_delegate.errors()[0].uri);
+  EXPECT_EQ(0, nel_delegate.errors()[0].status_code);
+  EXPECT_EQ(ERR_EMPTY_RESPONSE, nel_delegate.errors()[0].type);
+}
+
 #endif  // BUILDFLAG(ENABLE_REPORTING)
 
 TEST_F(URLRequestTestHTTP, ContentTypeNormalizationTest) {