Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / net / http / http_network_transaction.cc
index 32af2dd..20ffdd1 100644 (file)
@@ -15,6 +15,7 @@
 #include "base/metrics/field_trial.h"
 #include "base/metrics/histogram.h"
 #include "base/metrics/stats_counters.h"
+#include "base/profiler/scoped_tracker.h"
 #include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
@@ -44,7 +45,7 @@
 #include "net/http/http_response_info.h"
 #include "net/http/http_server_properties.h"
 #include "net/http/http_status_code.h"
-#include "net/http/http_stream_base.h"
+#include "net/http/http_stream.h"
 #include "net/http/http_stream_factory.h"
 #include "net/http/http_util.h"
 #include "net/http/transport_security_state.h"
 #include "net/ssl/ssl_cert_request_info.h"
 #include "net/ssl/ssl_connection_status_flags.h"
 #include "url/gurl.h"
-
-#if defined(SPDY_PROXY_AUTH_ORIGIN)
-#include <algorithm>
-#include "net/proxy/proxy_server.h"
-#endif
-
-
-using base::Time;
-using base::TimeDelta;
+#include "url/url_canon.h"
 
 namespace net {
 
@@ -79,34 +72,24 @@ void ProcessAlternateProtocol(
     HttpNetworkSession* session,
     const HttpResponseHeaders& headers,
     const HostPortPair& http_host_port_pair) {
-  std::string alternate_protocol_str;
-
-  if (!headers.EnumerateHeader(NULL, kAlternateProtocolHeader,
-                               &alternate_protocol_str)) {
-    // Header is not present.
+  if (!headers.HasHeader(kAlternateProtocolHeader))
     return;
+
+  std::vector<std::string> alternate_protocol_values;
+  void* iter = NULL;
+  std::string alternate_protocol_str;
+  while (headers.EnumerateHeader(&iter, kAlternateProtocolHeader,
+                                 &alternate_protocol_str)) {
+    alternate_protocol_values.push_back(alternate_protocol_str);
   }
 
   session->http_stream_factory()->ProcessAlternateProtocol(
       session->http_server_properties(),
-      alternate_protocol_str,
+      alternate_protocol_values,
       http_host_port_pair,
       *session);
 }
 
-// Returns true if |error| is a client certificate authentication error.
-bool IsClientCertificateError(int error) {
-  switch (error) {
-    case ERR_BAD_SSL_CLIENT_AUTH_CERT:
-    case ERR_SSL_CLIENT_AUTH_PRIVATE_KEY_ACCESS_DENIED:
-    case ERR_SSL_CLIENT_AUTH_CERT_NO_PRIVATE_KEY:
-    case ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED:
-      return true;
-    default:
-      return false;
-  }
-}
-
 base::Value* NetLogSSLVersionFallbackCallback(
     const GURL* url,
     int net_error,
@@ -134,7 +117,6 @@ HttpNetworkTransaction::HttpNetworkTransaction(RequestPriority priority,
       request_(NULL),
       priority_(priority),
       headers_valid_(false),
-      logged_response_time_(false),
       fallback_error_code_(ERR_SSL_INAPPROPRIATE_FALLBACK),
       request_headers_(),
       read_buf_len_(0),
@@ -168,7 +150,7 @@ HttpNetworkTransaction::~HttpNetworkTransaction() {
         stream_->Close(true /* not reusable */);
       } else {
         // Otherwise, we try to drain the response body.
-        HttpStreamBase* stream = stream_.release();
+        HttpStream* stream = stream_.release();
         stream->Drain(session_);
       }
     }
@@ -185,7 +167,6 @@ int HttpNetworkTransaction::Start(const HttpRequestInfo* request_info,
 
   net_log_ = net_log;
   request_ = request_info;
-  start_time_ = base::Time::Now();
 
   if (request_->load_flags & LOAD_DISABLE_CERT_REVOCATION_CHECKING) {
     server_ssl_config_.rev_checking_enabled = false;
@@ -311,8 +292,7 @@ void HttpNetworkTransaction::DidDrainBodyForAuthRestart(bool keep_alive) {
       // We should call connection_->set_idle_time(), but this doesn't occur
       // often enough to be worth the trouble.
       stream_->SetConnectionReused();
-      new_stream =
-          static_cast<HttpStream*>(stream_.get())->RenewStreamForAuth();
+      new_stream = stream_->RenewStreamForAuth();
     }
 
     if (!new_stream) {
@@ -427,8 +407,7 @@ UploadProgress HttpNetworkTransaction::GetUploadProgress() const {
   if (!stream_.get())
     return UploadProgress();
 
-  // TODO(bashi): This cast is temporary. Remove later.
-  return static_cast<HttpStream*>(stream_.get())->GetUploadProgress();
+  return stream_->GetUploadProgress();
 }
 
 void HttpNetworkTransaction::SetQuicServerInfo(
@@ -465,6 +444,11 @@ void HttpNetworkTransaction::SetBeforeNetworkStartCallback(
   before_network_start_callback_ = callback;
 }
 
+void HttpNetworkTransaction::SetBeforeProxyHeadersSentCallback(
+    const BeforeProxyHeadersSentCallback& callback) {
+  before_proxy_headers_sent_callback_ = callback;
+}
+
 int HttpNetworkTransaction::ResumeNetworkStart() {
   DCHECK_EQ(next_state_, STATE_CREATE_STREAM);
   return DoLoop(OK);
@@ -472,7 +456,7 @@ int HttpNetworkTransaction::ResumeNetworkStart() {
 
 void HttpNetworkTransaction::OnStreamReady(const SSLConfig& used_ssl_config,
                                            const ProxyInfo& used_proxy_info,
-                                           HttpStreamBase* stream) {
+                                           HttpStream* stream) {
   DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
   DCHECK(stream_request_.get());
 
@@ -565,7 +549,7 @@ void HttpNetworkTransaction::OnHttpsProxyTunnelResponse(
     const HttpResponseInfo& response_info,
     const SSLConfig& used_ssl_config,
     const ProxyInfo& used_proxy_info,
-    HttpStreamBase* stream) {
+    HttpStream* stream) {
   DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
 
   headers_valid_ = true;
@@ -594,7 +578,18 @@ void HttpNetworkTransaction::DoCallback(int rv) {
 }
 
 void HttpNetworkTransaction::OnIOComplete(int result) {
+  // TODO(vadimt): Remove ScopedTracker below once crbug.com/424359 is fixed.
+  tracked_objects::ScopedTracker tracking_profile1(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "424359 HttpNetworkTransaction::OnIOComplete 1"));
+
   int rv = DoLoop(result);
+
+  // TODO(vadimt): Remove ScopedTracker below once crbug.com/424359 is fixed.
+  tracked_objects::ScopedTracker tracking_profile2(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "424359 HttpNetworkTransaction::OnIOComplete 2"));
+
   if (rv != ERR_IO_PENDING)
     DoCallback(rv);
 }
@@ -880,6 +875,10 @@ void HttpNetworkTransaction::BuildRequestHeaders(bool using_proxy) {
         &request_headers_);
 
   request_headers_.MergeFrom(request_->extra_headers);
+
+  if (using_proxy && !before_proxy_headers_sent_callback_.is_null())
+    before_proxy_headers_sent_callback_.Run(proxy_info_, &request_headers_);
+
   response_.did_use_http_auth =
       request_headers_.HasHeader(HttpRequestHeaders::kAuthorization) ||
       request_headers_.HasHeader(HttpRequestHeaders::kProxyAuthorization);
@@ -967,12 +966,6 @@ int HttpNetworkTransaction::DoReadHeadersComplete(int result) {
     return OK;
   }
 
-  // After we call RestartWithAuth a new response_time will be recorded, and
-  // we need to be cautious about incorrectly logging the duration across the
-  // authentication activity.
-  if (result == OK)
-    LogTransactionConnectedMetrics();
-
   // ERR_CONNECTION_CLOSED is treated differently at this point; if partial
   // response headers were received, we do the best we can to make sense of it
   // and send it back up the stack.
@@ -1054,7 +1047,7 @@ int HttpNetworkTransaction::DoReadHeadersComplete(int result) {
         *request_,
         request_headers_,
         proxy_info_.proxy_server(),
-        *response_.headers);
+        *response_.headers.get());
   }
   return OK;
 }
@@ -1097,7 +1090,6 @@ int HttpNetworkTransaction::DoReadBodyComplete(int result) {
 
   // Clean up connection if we are done.
   if (done) {
-    LogTransactionMetrics();
     stream_->Close(!keep_alive);
     // Note: we don't reset the stream here.  We've closed it, but we still
     // need it around so that callers can call methods such as
@@ -1149,72 +1141,6 @@ int HttpNetworkTransaction::DoDrainBodyForAuthRestartComplete(int result) {
   return OK;
 }
 
-void HttpNetworkTransaction::LogTransactionConnectedMetrics() {
-  if (logged_response_time_)
-    return;
-
-  logged_response_time_ = true;
-
-  base::TimeDelta total_duration = response_.response_time - start_time_;
-
-  UMA_HISTOGRAM_CUSTOM_TIMES(
-      "Net.Transaction_Connected",
-      total_duration,
-      base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
-      100);
-
-  bool reused_socket = stream_->IsConnectionReused();
-  if (!reused_socket) {
-    UMA_HISTOGRAM_CUSTOM_TIMES(
-        "Net.Transaction_Connected_New_b",
-        total_duration,
-        base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
-        100);
-  }
-
-  // Currently, non-HIGHEST priority requests are frame or sub-frame resource
-  // types.  This will change when we also prioritize certain subresources like
-  // css, js, etc.
-  if (priority_ != HIGHEST) {
-    UMA_HISTOGRAM_CUSTOM_TIMES(
-        "Net.Priority_High_Latency_b",
-        total_duration,
-        base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
-        100);
-  } else {
-    UMA_HISTOGRAM_CUSTOM_TIMES(
-        "Net.Priority_Low_Latency_b",
-        total_duration,
-        base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
-        100);
-  }
-}
-
-void HttpNetworkTransaction::LogTransactionMetrics() const {
-  base::TimeDelta duration = base::Time::Now() -
-                             response_.request_time;
-  if (60 < duration.InMinutes())
-    return;
-
-  base::TimeDelta total_duration = base::Time::Now() - start_time_;
-
-  UMA_HISTOGRAM_CUSTOM_TIMES("Net.Transaction_Latency_b", duration,
-                             base::TimeDelta::FromMilliseconds(1),
-                             base::TimeDelta::FromMinutes(10),
-                             100);
-  UMA_HISTOGRAM_CUSTOM_TIMES("Net.Transaction_Latency_Total",
-                             total_duration,
-                             base::TimeDelta::FromMilliseconds(1),
-                             base::TimeDelta::FromMinutes(10), 100);
-
-  if (!stream_->IsConnectionReused()) {
-    UMA_HISTOGRAM_CUSTOM_TIMES(
-        "Net.Transaction_Latency_Total_New_Connection",
-        total_duration, base::TimeDelta::FromMilliseconds(1),
-        base::TimeDelta::FromMinutes(10), 100);
-  }
-}
-
 int HttpNetworkTransaction::HandleCertificateRequest(int error) {
   // There are two paths through which the server can request a certificate
   // from us.  The first is during the initial handshake, the second is
@@ -1297,6 +1223,7 @@ int HttpNetworkTransaction::HandleSSLHandshakeError(int error) {
   uint16 version_max = server_ssl_config_.version_max;
 
   switch (error) {
+    case ERR_CONNECTION_CLOSED:
     case ERR_SSL_PROTOCOL_ERROR:
     case ERR_SSL_VERSION_OR_CIPHER_MISMATCH:
       if (version_max >= SSL_PROTOCOL_VERSION_TLS1 &&
@@ -1320,6 +1247,26 @@ int HttpNetworkTransaction::HandleSSLHandshakeError(int error) {
         should_fallback = true;
       }
       break;
+    case ERR_CONNECTION_RESET:
+      if (version_max >= SSL_PROTOCOL_VERSION_TLS1_1 &&
+          version_max > server_ssl_config_.version_min) {
+        // Some network devices that inspect application-layer packets seem to
+        // inject TCP reset packets to break the connections when they see TLS
+        // 1.1 in ClientHello or ServerHello. See http://crbug.com/130293.
+        //
+        // Only allow ERR_CONNECTION_RESET to trigger a fallback from TLS 1.1 or
+        // 1.2. We don't lose much in this fallback because the explicit IV for
+        // CBC mode in TLS 1.1 is approximated by record splitting in TLS
+        // 1.0. The fallback will be more painful for TLS 1.2 when we have GCM
+        // support.
+        //
+        // ERR_CONNECTION_RESET is a common network error, so we don't want it
+        // to trigger a version fallback in general, especially the TLS 1.0 ->
+        // SSL 3.0 fallback, which would drop TLS extensions.
+        version_max--;
+        should_fallback = true;
+      }
+      break;
     case ERR_SSL_BAD_RECORD_MAC_ALERT:
       if (version_max >= SSL_PROTOCOL_VERSION_TLS1_1 &&
           version_max > server_ssl_config_.version_min) {
@@ -1512,6 +1459,17 @@ GURL HttpNetworkTransaction::AuthURL(HttpAuth::Target target) const {
                   proxy_info_.proxy_server().host_port_pair().ToString());
     }
     case HttpAuth::AUTH_SERVER:
+      if (ForWebSocketHandshake()) {
+        const GURL& url = request_->url;
+        url::Replacements<char> ws_to_http;
+        if (url.SchemeIs("ws")) {
+          ws_to_http.SetScheme("http", url::Component(0, 4));
+        } else {
+          DCHECK(url.SchemeIs("wss"));
+          ws_to_http.SetScheme("https", url::Component(0, 5));
+        }
+        return url.ReplaceComponents(ws_to_http);
+      }
       return request_->url;
     default:
      return GURL();