Add ERR_END_OF_STREAM

Add new error code "END_OF_STREAM" and use it in HttpStreamParser.
Update a test to expect failure instead of success on an incomplete stream.

BUG=25032
TEST=updated unittests

Review URL: http://codereview.chromium.org/650190

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@39822 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/net/base/net_error_list.h b/net/base/net_error_list.h
index e544897..db94f69a 100644
--- a/net/base/net_error_list.h
+++ b/net/base/net_error_list.h
@@ -134,6 +134,9 @@
 // because that host is unreachable.
 NET_ERROR(SOCKS_CONNECTION_HOST_UNREACHABLE, -121)
 
+// There is no more data left in the logical stream.
+NET_ERROR(END_OF_STREAM, -122)
+
 // Certificate error codes
 //
 // The values of certificate error codes must be consecutive.
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index edc519ab..0f66188e 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -956,13 +956,11 @@
   }
 
   if (result == ERR_CONNECTION_CLOSED) {
+    // For now, if we get at last some data, we do the best we can to make
+    // sense of it and send it back up the stack.
     int rv = HandleConnectionClosedBeforeEndOfHeaders();
     if (rv != OK)
       return rv;
-    // TODO(wtc): Traditionally this code has returned 0 when reading a closed
-    // socket.  That is partially corrected in classes that we call, but
-    // callers need to be updated.
-    result = 0;
   }
 
   if (response_.headers->GetParsedHttpVersion() < HttpVersion(1, 0)) {
@@ -1062,11 +1060,16 @@
     // TODO(wtc): Traditionally this code has returned 0 when reading a closed
     // socket.  That is partially corrected in classes that we call, but
     // callers need to be updated.
-    if (result == ERR_CONNECTION_CLOSED)
+    if (result == ERR_END_OF_STREAM || (!http_stream_->CanFindEndOfResponse() &&
+                                        result == ERR_CONNECTION_CLOSED)) {
       result = 0;
-  } else if (http_stream_->IsResponseBodyComplete()) {
+    }
+  }
+
+  if (http_stream_->IsResponseBodyComplete()) {
     done = true;
-    keep_alive = GetResponseHeaders()->IsKeepAlive();
+    if (http_stream_->CanFindEndOfResponse())
+        keep_alive = GetResponseHeaders()->IsKeepAlive();
   }
 
   // Clean up connection_->if we are done.
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc
index af4f2a39..8d547cf 100644
--- a/net/http/http_network_transaction_unittest.cc
+++ b/net/http/http_network_transaction_unittest.cc
@@ -4022,15 +4022,39 @@
 }
 
 TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
+  SessionDependencies session_deps;
+  scoped_ptr<HttpTransaction> trans(
+      new HttpNetworkTransaction(CreateSession(&session_deps)));
+
+  HttpRequestInfo request;
+  request.method = "GET";
+  request.url = GURL("http://www.google.com/");
+  request.load_flags = 0;
+
   MockRead data_reads[] = {
     MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
     MockRead(false, OK),
   };
-  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
-                                              arraysize(data_reads));
-  EXPECT_EQ(OK, out.rv);
-  EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
-  EXPECT_EQ("", out.response_data);
+
+  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
+  session_deps.socket_factory.AddSocketDataProvider(&data);
+
+  TestCompletionCallback callback;
+
+  int rv = trans->Start(&request, &callback, NULL);
+  EXPECT_EQ(ERR_IO_PENDING, rv);
+
+  EXPECT_EQ(OK, callback.WaitForResult());
+
+  const HttpResponseInfo* response = trans->GetResponseInfo();
+  EXPECT_TRUE(response != NULL);
+
+  EXPECT_TRUE(response->headers != NULL);
+  EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
+
+  std::string response_data;
+  rv = ReadTransaction(trans.get(), &response_data);
+  EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
 }
 
 TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
diff --git a/net/http/http_stream.h b/net/http/http_stream.h
index 183aee11..978ebdb 100644
--- a/net/http/http_stream.h
+++ b/net/http/http_stream.h
@@ -53,12 +53,14 @@
 
   // Reads response body data, up to |buf_len| bytes. |buf_len| should be a
   // reasonable size (<2MB). The number of bytes read is returned, or an
-  // error is returned upon failure.  ERR_CONNECTION_CLOSED is returned to
-  // indicate end-of-connection.  ERR_IO_PENDING is returned if the operation
-  // could not be completed synchronously, in which case the result will be
-  // passed to the callback when available. If the operation is not completed
-  // immediately, the socket acquires a reference to the provided buffer until
-  // the callback is invoked or the socket is destroyed.
+  // error is returned upon failure.  ERR_END_OF_STREAM indicates that the
+  // request has been fully satisfied and there is no more data to read.
+  // ERR_CONNECTION_CLOSED is returned when the connection has been closed
+  // prematurely.  ERR_IO_PENDING is returned if the operation could not be
+  // completed synchronously, in which case the result will be passed to the
+  // callback when available. If the operation is not completed immediately,
+  // the socket acquires a reference to the provided buffer until the callback
+  // is invoked or the socket is destroyed.
   virtual int ReadResponseBody(IOBuffer* buf, int buf_len,
                                CompletionCallback* callback) = 0;
 
diff --git a/net/http/http_stream_parser.cc b/net/http/http_stream_parser.cc
index eafa90b..b16c1bf 100644
--- a/net/http/http_stream_parser.cc
+++ b/net/http/http_stream_parser.cc
@@ -355,7 +355,7 @@
 
   // Check to see if we're done reading.
   if (IsResponseBodyComplete())
-    return 0;
+    return ERR_END_OF_STREAM;
 
   DCHECK_EQ(0, read_buf_->offset());
   return connection_->socket()->Read(user_read_buf_, user_read_buf_len_,