Merge from Chromium at DEPS revision r215573

This commit was generated by merge_to_master.py.

Change-Id: Ib95814f98e5765b459dd32425f9bf9138edf2bca
diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc
index d085a4d..8a730ce 100644
--- a/net/spdy/spdy_session.cc
+++ b/net/spdy/spdy_session.cc
@@ -205,9 +205,6 @@
   return dict;
 }
 
-// Maximum number of concurrent streams we will create, unless the server
-// sends a SETTINGS frame with a different value.
-const size_t kInitialMaxConcurrentStreams = 100;
 // The maximum number of concurrent streams we will ever create.  Even if
 // the server permits more, we will never exceed this limit.
 const size_t kMaxConcurrentStreamLimit = 256;
@@ -320,7 +317,7 @@
     const SpdySessionKey& spdy_session_key,
     const base::WeakPtr<HttpServerProperties>& http_server_properties,
     bool verify_domain_authentication,
-    bool enable_sending_initial_settings,
+    bool enable_sending_initial_data,
     bool enable_credential_frames,
     bool enable_compression,
     bool enable_ping_based_connection_checking,
@@ -364,6 +361,7 @@
       next_ping_id_(1),
       last_activity_time_(time_func()),
       check_ping_status_pending_(false),
+      send_connection_header_prefix_(false),
       flow_control_state_(FLOW_CONTROL_NONE),
       stream_initial_send_window_size_(kSpdyStreamInitialWindowSize),
       stream_initial_recv_window_size_(stream_initial_recv_window_size == 0 ?
@@ -374,7 +372,7 @@
       session_unacked_recv_window_bytes_(0),
       net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SPDY_SESSION)),
       verify_domain_authentication_(verify_domain_authentication),
-      enable_sending_initial_settings_(enable_sending_initial_settings),
+      enable_sending_initial_data_(enable_sending_initial_data),
       enable_credential_frames_(enable_credential_frames),
       enable_compression_(enable_compression),
       enable_ping_based_connection_checking_(
@@ -458,6 +456,9 @@
                                             host_port_pair().ToString()));
   }
 
+  if (protocol_ == kProtoHTTP2Draft04)
+    send_connection_header_prefix_ = true;
+
   if (protocol_ >= kProtoSPDY31) {
     flow_control_state_ = FLOW_CONTROL_STREAM_AND_SESSION;
     session_send_window_size_ = kSpdySessionInitialWindowSize;
@@ -490,7 +491,8 @@
   if (error == OK) {
     DCHECK_NE(availability_state_, STATE_CLOSED);
     connection_->AddLayeredPool(this);
-    SendInitialSettings();
+    if (enable_sending_initial_data_)
+      SendInitialData();
     pool_ = pool;
   } else {
     DcheckClosed();
@@ -672,29 +674,37 @@
 }
 
 void SpdySession::ProcessPendingStreamRequests() {
-  while (!max_concurrent_streams_ ||
-         (active_streams_.size() + created_streams_.size() <
-          max_concurrent_streams_)) {
-    bool no_pending_create_streams = true;
-    for (int i = NUM_PRIORITIES - 1; i >= MINIMUM_PRIORITY; --i) {
-      if (!pending_create_stream_queues_[i].empty()) {
-        SpdyStreamRequest* pending_request =
-            pending_create_stream_queues_[i].front();
-        CHECK(pending_request);
-        pending_create_stream_queues_[i].pop_front();
-        no_pending_create_streams = false;
-        DCHECK(!ContainsKey(pending_stream_request_completions_,
-                            pending_request));
-        pending_stream_request_completions_.insert(pending_request);
-        base::MessageLoop::current()->PostTask(
-            FROM_HERE,
-            base::Bind(&SpdySession::CompleteStreamRequest,
-                       weak_factory_.GetWeakPtr(), pending_request));
-        break;
-      }
+  // Like |max_concurrent_streams_|, 0 means infinite for
+  // |max_requests_to_process|.
+  size_t max_requests_to_process = 0;
+  if (max_concurrent_streams_ != 0) {
+    max_requests_to_process =
+        max_concurrent_streams_ -
+        (active_streams_.size() + created_streams_.size());
+  }
+  for (size_t i = 0;
+       max_requests_to_process == 0 || i < max_requests_to_process; ++i) {
+    bool processed_request = false;
+    for (int j = NUM_PRIORITIES - 1; j >= MINIMUM_PRIORITY; --j) {
+      if (pending_create_stream_queues_[j].empty())
+        continue;
+
+      SpdyStreamRequest* pending_request =
+          pending_create_stream_queues_[j].front();
+      CHECK(pending_request);
+      pending_create_stream_queues_[j].pop_front();
+      processed_request = true;
+      DCHECK(!ContainsKey(pending_stream_request_completions_,
+                          pending_request));
+      pending_stream_request_completions_.insert(pending_request);
+      base::MessageLoop::current()->PostTask(
+          FROM_HERE,
+          base::Bind(&SpdySession::CompleteStreamRequest,
+                     weak_factory_.GetWeakPtr(), pending_request));
+      break;
     }
-    if (no_pending_create_streams)
-      return;  // there were no streams in any queue
+    if (!processed_request)
+      break;
   }
 }
 
@@ -2348,29 +2358,38 @@
       stream_id, delta_window_size, it->second.stream->priority());
 }
 
-void SpdySession::SendInitialSettings() {
+void SpdySession::SendInitialData() {
+  DCHECK(enable_sending_initial_data_);
   DCHECK_NE(availability_state_, STATE_CLOSED);
 
+  if (send_connection_header_prefix_) {
+    DCHECK_EQ(protocol_, kProtoHTTP2Draft04);
+    scoped_ptr<SpdyFrame> connection_header_prefix_frame(
+        new SpdyFrame(const_cast<char*>(kHttp2ConnectionHeaderPrefix),
+                      kHttp2ConnectionHeaderPrefixSize,
+                      false /* take_ownership */));
+    // Count the prefix as part of the subsequent SETTINGS frame.
+    EnqueueSessionWrite(HIGHEST, SETTINGS,
+                        connection_header_prefix_frame.Pass());
+  }
+
   // First, notify the server about the settings they should use when
   // communicating with us.
-  if (GetProtocolVersion() >= 2 && enable_sending_initial_settings_) {
-    SettingsMap settings_map;
-    // Create a new settings frame notifying the sever of our
-    // max_concurrent_streams_ and initial window size.
-    settings_map[SETTINGS_MAX_CONCURRENT_STREAMS] =
-        SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
-    if (GetProtocolVersion() > 2 &&
-        stream_initial_recv_window_size_ != kSpdyStreamInitialWindowSize) {
-      settings_map[SETTINGS_INITIAL_WINDOW_SIZE] =
-          SettingsFlagsAndValue(SETTINGS_FLAG_NONE,
-                                stream_initial_recv_window_size_);
-    }
-    SendSettings(settings_map);
+  SettingsMap settings_map;
+  // Create a new settings frame notifying the server of our
+  // max concurrent streams and initial window size.
+  settings_map[SETTINGS_MAX_CONCURRENT_STREAMS] =
+      SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
+  if (flow_control_state_ >= FLOW_CONTROL_STREAM &&
+      stream_initial_recv_window_size_ != kSpdyStreamInitialWindowSize) {
+    settings_map[SETTINGS_INITIAL_WINDOW_SIZE] =
+        SettingsFlagsAndValue(SETTINGS_FLAG_NONE,
+                              stream_initial_recv_window_size_);
   }
+  SendSettings(settings_map);
 
   // Next, notify the server about our initial recv window size.
-  if (flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION &&
-      enable_sending_initial_settings_) {
+  if (flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION) {
     // Bump up the receive window size to the real initial value. This
     // has to go here since the WINDOW_UPDATE frame sent by
     // IncreaseRecvWindowSize() call uses |buffered_spdy_framer_|.
@@ -2382,30 +2401,27 @@
         kDefaultInitialRecvWindowSize - session_recv_window_size_);
   }
 
-  // Finally, notify the server about the settings they have previously
-  // told us to use when communicating with them.
-  const SettingsMap& settings_map =
+  // Finally, notify the server about the settings they have
+  // previously told us to use when communicating with them (after
+  // applying them).
+  const SettingsMap& server_settings_map =
       http_server_properties_->GetSpdySettings(host_port_pair());
-  if (settings_map.empty())
+  if (server_settings_map.empty())
     return;
 
-  const SpdySettingsIds id = SETTINGS_CURRENT_CWND;
-  SettingsMap::const_iterator it = settings_map.find(id);
-  uint32 value = 0;
-  if (it != settings_map.end())
-    value = it->second.second;
-  UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsCwndSent", value, 1, 200, 100);
+  SettingsMap::const_iterator it =
+      server_settings_map.find(SETTINGS_CURRENT_CWND);
+  uint32 cwnd = (it != server_settings_map.end()) ? it->second.second : 0;
+  UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsCwndSent", cwnd, 1, 200, 100);
 
-  const SettingsMap& settings_map_new =
-      http_server_properties_->GetSpdySettings(host_port_pair());
-  for (SettingsMap::const_iterator i = settings_map_new.begin(),
-           end = settings_map_new.end(); i != end; ++i) {
-    const SpdySettingsIds new_id = i->first;
-    const uint32 new_val = i->second.second;
+  for (SettingsMap::const_iterator it = server_settings_map.begin();
+       it != server_settings_map.end(); ++it) {
+    const SpdySettingsIds new_id = it->first;
+    const uint32 new_val = it->second.second;
     HandleSetting(new_id, new_val);
   }
 
-  SendSettings(settings_map_new);
+  SendSettings(server_settings_map);
 }