Landing Recent QUIC changes until 4/15/2016 17:20 UTC

Fix a few spurious string allocations in QuicCryptoServerStream and QuicCryptoStream. No functional change. Not flag protected.

Merge internal change: 119967190
https://codereview.chromium.org/1906803004/

Quic will push urls in x-associate-content and link headers upon ResponseHeadersComplete(). Change AcceptQuicClient() to start the request pipeline from PICKING_SERVICE for server push stream. Protected by FLAGS_quic_server_push.

Implemented server push feature in QUIC. This feature will be enabled by
both flag and connection option "kSPSH".

Merge internal change: 119871679
https://codereview.chromium.org/1905073002/

Split out QuicAlarm creation from QuicConnectionHelper to new QuicAlarmFactory. No behavior change, not protected.

This is in preparation for gRPC-over-QUIC to use a separate
QuicAlarmFactory for each GrpcQuicConnection. Currently there exists a
single Helper (and after this CL a single AlarmFactory) per Dispatcher,
and this is used to create alarms for all Connections.

gRPC-over-QUIC needs to add per-connection locking to connection alarms
before firing them, and a followup CL will create a different
AlarmFactory for each gRPC-over-QUIC connection, each with its own
mutex (rather than sharing one mutex across the alarms of connections
which is obviously terrible).

Merge internal change: 119778209
https://codereview.chromium.org/1905843003/

Make QuicDispatcher's helper argument be a unique_ptr to make ownership clear. No behavior change.

(also removes very out of date QuicDispatcher constructor comment)

Merge internal change: 119753783
https://codereview.chromium.org/1907773002/

Deprecate FLAGS_quic_sslr_byte_conservation.

Merge internal change: 119678304
https://codereview.chromium.org/1906703002/

Deprecate FLAGS_quic_consolidate_onstreamframe_errors

Merge internal change: 119653892
https://codereview.chromium.org/1906473004/

Add a server push disabled test.

Merge internal change: 119645068
https://codereview.chromium.org/1911653003/

Cleanup: Migrate references from scoped_ptr to std::unique_ptr. scoped_ptr is now just an alias for unique_ptr, so this is a purely textual change. base/scoped_ptr.h will be removed soon.

Merge internal change: 119583512
https://codereview.chromium.org/1909453005/

Cleanup: Migrate references from scoped_ptr to std::unique_ptr. scoped_ptr is now just an alias for unique_ptr, so this is a purely textual change. base/scoped_ptr.h will be removed soon.

Merge internal change: 119581790
https://codereview.chromium.org/1911653002/

Cleanup: Migrate references from scoped_ptr to std::unique_ptr. scoped_ptr is now just an alias for unique_ptr, so this is a purely textual change. base/scoped_ptr.h will be removed soon.

Merge internal change: 119576588
https://codereview.chromium.org/1908723002/

Plumbs new SpdyFramerVisitorInterface method handling through QUIC test utilities, including the test client and test server. Preparation for CL 103292114.

Merge internal change: 119568788
https://codereview.chromium.org/1910593004/

Fixes QuicSpdyStream::ConsumeHeaderList to prod the sequencer when headers are consumed. Not yet used in production.

Merge internal change: 119562680
https://codereview.chromium.org/1910483004/

Stop returning unused return value from QuicPacketCreator::CopyToBuffer. No functional change. Not flag protected.

Merge internal change: 119557380
https://codereview.chromium.org/1897153007/

ignore invalid error code in QuicFramer when process GoAway, ConnectionClose, RstStream frames to do normal goaway, connection close, and stream reset. Flag protected by FLAGS_quic_ignore_invalid_error_code.

Merge internal change: 119551887
https://codereview.chromium.org/1904833002/

Adds a DebugString() method to QuicHeaderList.

Merge internal change: 119529330
https://codereview.chromium.org/1907683002/

Review URL: https://codereview.chromium.org/1908103002

Cr-Commit-Position: refs/heads/master@{#389035}
diff --git a/net/quic/bidirectional_stream_quic_impl_unittest.cc b/net/quic/bidirectional_stream_quic_impl_unittest.cc
index 9f90d926..4f75ba3 100644
--- a/net/quic/bidirectional_stream_quic_impl_unittest.cc
+++ b/net/quic/bidirectional_stream_quic_impl_unittest.cc
@@ -24,6 +24,7 @@
 #include "net/quic/crypto/quic_decrypter.h"
 #include "net/quic/crypto/quic_encrypter.h"
 #include "net/quic/crypto/quic_server_info.h"
+#include "net/quic/quic_chromium_alarm_factory.h"
 #include "net/quic/quic_chromium_client_session.h"
 #include "net/quic/quic_chromium_client_stream.h"
 #include "net/quic/quic_chromium_connection_helper.h"
@@ -329,10 +330,11 @@
         socket_data_.get(), net_log().bound().net_log()));
     socket->Connect(peer_addr_);
     runner_ = new TestTaskRunner(&clock_);
-    helper_.reset(new QuicChromiumConnectionHelper(runner_.get(), &clock_,
-                                                   &random_generator_));
+    helper_.reset(
+        new QuicChromiumConnectionHelper(&clock_, &random_generator_));
+    alarm_factory_.reset(new QuicChromiumAlarmFactory(runner_.get(), &clock_));
     connection_ = new QuicConnection(
-        connection_id_, peer_addr_, helper_.get(),
+        connection_id_, peer_addr_, helper_.get(), alarm_factory_.get(),
         new QuicChromiumPacketWriter(socket.get()), true /* owns_writer */,
         Perspective::IS_CLIENT, SupportedVersions(GetParam()));
 
@@ -472,6 +474,7 @@
   MockClock clock_;
   QuicConnection* connection_;
   std::unique_ptr<QuicChromiumConnectionHelper> helper_;
+  std::unique_ptr<QuicChromiumAlarmFactory> alarm_factory_;
   TransportSecurityState transport_security_state_;
   std::unique_ptr<QuicChromiumClientSession> session_;
   QuicCryptoClientConfig crypto_config_;
diff --git a/net/quic/congestion_control/tcp_cubic_sender_bytes_test.cc b/net/quic/congestion_control/tcp_cubic_sender_bytes_test.cc
index 1bedee8..3bca8cb 100644
--- a/net/quic/congestion_control/tcp_cubic_sender_bytes_test.cc
+++ b/net/quic/congestion_control/tcp_cubic_sender_bytes_test.cc
@@ -5,6 +5,7 @@
 #include "net/quic/congestion_control/tcp_cubic_sender_bytes.h"
 
 #include <algorithm>
+#include <cstdint>
 #include <memory>
 
 #include "base/logging.h"
@@ -287,7 +288,6 @@
 }
 
 TEST_F(TcpCubicSenderBytesTest, SlowStartHalfPacketLossWithLargeReduction) {
-  FLAGS_quic_sslr_byte_conservation = true;
   QuicConfig config;
   QuicTagVector options;
   options.push_back(kSSLR);
diff --git a/net/quic/congestion_control/tcp_cubic_sender_packets.cc b/net/quic/congestion_control/tcp_cubic_sender_packets.cc
index e1c225fe..aee29ba1 100644
--- a/net/quic/congestion_control/tcp_cubic_sender_packets.cc
+++ b/net/quic/congestion_control/tcp_cubic_sender_packets.cc
@@ -89,17 +89,10 @@
       ++stats_->slowstart_packets_lost;
       stats_->slowstart_bytes_lost += lost_bytes;
       if (slow_start_large_reduction_) {
-        if (FLAGS_quic_sslr_byte_conservation) {
-          if (stats_->slowstart_packets_lost == 1 ||
-              (stats_->slowstart_bytes_lost / kDefaultTCPMSS) >
-                  (stats_->slowstart_bytes_lost - lost_bytes) /
-                      kDefaultTCPMSS) {
-            // Reduce congestion window by 1 for every mss of bytes lost.
-            congestion_window_ =
-                max(congestion_window_ - 1, min_congestion_window_);
-          }
-        } else {
-          // Reduce congestion window by 1 for every loss.
+        if (stats_->slowstart_packets_lost == 1 ||
+            (stats_->slowstart_bytes_lost / kDefaultTCPMSS) >
+                (stats_->slowstart_bytes_lost - lost_bytes) / kDefaultTCPMSS) {
+          // Reduce congestion window by 1 for every mss of bytes lost.
           congestion_window_ =
               max(congestion_window_ - 1, min_congestion_window_);
         }
diff --git a/net/quic/congestion_control/tcp_cubic_sender_packets_test.cc b/net/quic/congestion_control/tcp_cubic_sender_packets_test.cc
index 18359b1..892ee04 100644
--- a/net/quic/congestion_control/tcp_cubic_sender_packets_test.cc
+++ b/net/quic/congestion_control/tcp_cubic_sender_packets_test.cc
@@ -296,7 +296,6 @@
 }
 
 TEST_F(TcpCubicSenderPacketsTest, SlowStartHalfPacketLossWithLargeReduction) {
-  FLAGS_quic_sslr_byte_conservation = true;
   QuicConfig config;
   QuicTagVector options;
   options.push_back(kSSLR);
diff --git a/net/quic/crypto/aes_128_gcm_12_decrypter_test.cc b/net/quic/crypto/aes_128_gcm_12_decrypter_test.cc
index f045afa0..9f24aa0 100644
--- a/net/quic/crypto/aes_128_gcm_12_decrypter_test.cc
+++ b/net/quic/crypto/aes_128_gcm_12_decrypter_test.cc
@@ -4,6 +4,8 @@
 
 #include "net/quic/crypto/aes_128_gcm_12_decrypter.h"
 
+#include <memory>
+
 #include "net/quic/quic_flags.h"
 #include "net/quic/test_tools/quic_test_utils.h"
 
diff --git a/net/quic/crypto/aes_128_gcm_12_encrypter_test.cc b/net/quic/crypto/aes_128_gcm_12_encrypter_test.cc
index 7b61962..88e7401 100644
--- a/net/quic/crypto/aes_128_gcm_12_encrypter_test.cc
+++ b/net/quic/crypto/aes_128_gcm_12_encrypter_test.cc
@@ -4,6 +4,8 @@
 
 #include "net/quic/crypto/aes_128_gcm_12_encrypter.h"
 
+#include <memory>
+
 #include "net/quic/test_tools/quic_test_utils.h"
 
 using base::StringPiece;
diff --git a/net/quic/crypto/cert_compressor.cc b/net/quic/crypto/cert_compressor.cc
index 0f1075d..366252b2 100644
--- a/net/quic/crypto/cert_compressor.cc
+++ b/net/quic/crypto/cert_compressor.cc
@@ -4,6 +4,7 @@
 
 #include "net/quic/crypto/cert_compressor.h"
 
+#include <cstdint>
 #include <memory>
 
 #include "base/logging.h"
diff --git a/net/quic/crypto/cert_compressor_test.cc b/net/quic/crypto/cert_compressor_test.cc
index 251313b..9005086 100644
--- a/net/quic/crypto/cert_compressor_test.cc
+++ b/net/quic/crypto/cert_compressor_test.cc
@@ -4,6 +4,8 @@
 
 #include "net/quic/crypto/cert_compressor.h"
 
+#include <memory>
+
 #include "base/strings/string_number_conversions.h"
 #include "net/quic/quic_utils.h"
 #include "net/quic/test_tools/crypto_test_utils.h"
diff --git a/net/quic/crypto/chacha20_poly1305_rfc7539_decrypter_test.cc b/net/quic/crypto/chacha20_poly1305_rfc7539_decrypter_test.cc
index ca80202..bc09d3e1 100644
--- a/net/quic/crypto/chacha20_poly1305_rfc7539_decrypter_test.cc
+++ b/net/quic/crypto/chacha20_poly1305_rfc7539_decrypter_test.cc
@@ -4,6 +4,8 @@
 
 #include "net/quic/crypto/chacha20_poly1305_rfc7539_decrypter.h"
 
+#include <memory>
+
 #include "net/quic/quic_flags.h"
 #include "net/quic/test_tools/quic_test_utils.h"
 
diff --git a/net/quic/crypto/chacha20_poly1305_rfc7539_encrypter_test.cc b/net/quic/crypto/chacha20_poly1305_rfc7539_encrypter_test.cc
index b9d9d47..ea55594c 100644
--- a/net/quic/crypto/chacha20_poly1305_rfc7539_encrypter_test.cc
+++ b/net/quic/crypto/chacha20_poly1305_rfc7539_encrypter_test.cc
@@ -5,6 +5,7 @@
 #include "net/quic/crypto/chacha20_poly1305_rfc7539_encrypter.h"
 
 #include <stdint.h>
+#include <memory>
 
 #include "net/quic/crypto/chacha20_poly1305_rfc7539_decrypter.h"
 #include "net/quic/test_tools/quic_test_utils.h"
diff --git a/net/quic/crypto/channel_id_test.cc b/net/quic/crypto/channel_id_test.cc
index 1453071b..bc1ca44 100644
--- a/net/quic/crypto/channel_id_test.cc
+++ b/net/quic/crypto/channel_id_test.cc
@@ -4,6 +4,8 @@
 
 #include "net/quic/crypto/channel_id.h"
 
+#include <memory>
+
 #include "net/quic/test_tools/crypto_test_utils.h"
 #include "net/quic/test_tools/quic_test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/net/quic/crypto/crypto_framer.cc b/net/quic/crypto/crypto_framer.cc
index 8e04aef..9b2fc2d8 100644
--- a/net/quic/crypto/crypto_framer.cc
+++ b/net/quic/crypto/crypto_framer.cc
@@ -4,6 +4,8 @@
 
 #include "net/quic/crypto/crypto_framer.h"
 
+#include <memory>
+
 #include "base/strings/stringprintf.h"
 #include "net/quic/crypto/crypto_protocol.h"
 #include "net/quic/quic_data_reader.h"
diff --git a/net/quic/crypto/crypto_handshake_message.cc b/net/quic/crypto/crypto_handshake_message.cc
index 05ffa67..70857ff 100644
--- a/net/quic/crypto/crypto_handshake_message.cc
+++ b/net/quic/crypto/crypto_handshake_message.cc
@@ -4,6 +4,8 @@
 
 #include "net/quic/crypto/crypto_handshake_message.h"
 
+#include <memory>
+
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "net/quic/crypto/crypto_framer.h"
diff --git a/net/quic/crypto/crypto_handshake_message.h b/net/quic/crypto/crypto_handshake_message.h
index 86052f2..0f7346f4 100644
--- a/net/quic/crypto/crypto_handshake_message.h
+++ b/net/quic/crypto/crypto_handshake_message.h
@@ -8,6 +8,7 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include <cstdint>
 #include <memory>
 #include <string>
 #include <vector>
diff --git a/net/quic/crypto/crypto_server_test.cc b/net/quic/crypto/crypto_server_test.cc
index 5dfcf51..430bcf1 100644
--- a/net/quic/crypto/crypto_server_test.cc
+++ b/net/quic/crypto/crypto_server_test.cc
@@ -2,6 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <algorithm>
+#include <cstdint>
+#include <memory>
 #include <ostream>
 #include <vector>
 
diff --git a/net/quic/crypto/crypto_utils.cc b/net/quic/crypto/crypto_utils.cc
index a052520..b8c63eca 100644
--- a/net/quic/crypto/crypto_utils.cc
+++ b/net/quic/crypto/crypto_utils.cc
@@ -4,6 +4,8 @@
 
 #include "net/quic/crypto/crypto_utils.h"
 
+#include <memory>
+
 #include "crypto/hkdf.h"
 #include "crypto/secure_hash.h"
 #include "net/base/url_util.h"
diff --git a/net/quic/crypto/p256_key_exchange_test.cc b/net/quic/crypto/p256_key_exchange_test.cc
index 079eb40d..4972480 100644
--- a/net/quic/crypto/p256_key_exchange_test.cc
+++ b/net/quic/crypto/p256_key_exchange_test.cc
@@ -4,6 +4,8 @@
 
 #include "net/quic/crypto/p256_key_exchange.h"
 
+#include <memory>
+
 #include "base/logging.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/net/quic/crypto/proof_test.cc b/net/quic/crypto/proof_test.cc
index 67af4127..5e3cd9b 100644
--- a/net/quic/crypto/proof_test.cc
+++ b/net/quic/crypto/proof_test.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <memory>
+
 #include "base/files/file_path.h"
 #include "net/base/ip_endpoint.h"
 #include "net/base/net_errors.h"
diff --git a/net/quic/crypto/quic_crypto_client_config.cc b/net/quic/crypto/quic_crypto_client_config.cc
index e6dad8c1..a48560f 100644
--- a/net/quic/crypto/quic_crypto_client_config.cc
+++ b/net/quic/crypto/quic_crypto_client_config.cc
@@ -4,6 +4,8 @@
 
 #include "net/quic/crypto/quic_crypto_client_config.h"
 
+#include <memory>
+
 #include "base/metrics/histogram_macros.h"
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
diff --git a/net/quic/crypto/quic_crypto_server_config.cc b/net/quic/crypto/quic_crypto_server_config.cc
index b107df3..91705b1 100644
--- a/net/quic/crypto/quic_crypto_server_config.cc
+++ b/net/quic/crypto/quic_crypto_server_config.cc
@@ -7,6 +7,7 @@
 #include <stdlib.h>
 
 #include <algorithm>
+#include <memory>
 
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
diff --git a/net/quic/crypto/quic_crypto_server_config_test.cc b/net/quic/crypto/quic_crypto_server_config_test.cc
index 38c6d2ef..f5ca8ecf 100644
--- a/net/quic/crypto/quic_crypto_server_config_test.cc
+++ b/net/quic/crypto/quic_crypto_server_config_test.cc
@@ -6,6 +6,8 @@
 
 #include <stdarg.h>
 
+#include <memory>
+
 #include "base/stl_util.h"
 #include "net/quic/crypto/aes_128_gcm_12_encrypter.h"
 #include "net/quic/crypto/cert_compressor.h"
diff --git a/net/quic/crypto/strike_register_test.cc b/net/quic/crypto/strike_register_test.cc
index 0f63969..bff26108 100644
--- a/net/quic/crypto/strike_register_test.cc
+++ b/net/quic/crypto/strike_register_test.cc
@@ -4,6 +4,8 @@
 
 #include "net/quic/crypto/strike_register.h"
 
+#include <cstdint>
+#include <memory>
 #include <set>
 #include <string>
 
diff --git a/net/quic/p2p/quic_p2p_session_test.cc b/net/quic/p2p/quic_p2p_session_test.cc
index 02230690..1c8168b 100644
--- a/net/quic/p2p/quic_p2p_session_test.cc
+++ b/net/quic/p2p/quic_p2p_session_test.cc
@@ -18,6 +18,7 @@
 #include "net/quic/crypto/quic_random.h"
 #include "net/quic/p2p/quic_p2p_crypto_config.h"
 #include "net/quic/p2p/quic_p2p_stream.h"
+#include "net/quic/quic_chromium_alarm_factory.h"
 #include "net/quic/quic_chromium_connection_helper.h"
 #include "net/quic/quic_chromium_packet_writer.h"
 #include "net/quic/test_tools/quic_session_peer.h"
@@ -196,9 +197,9 @@
 
  protected:
   QuicP2PSessionTest()
-      : quic_helper_(base::ThreadTaskRunnerHandle::Get().get(),
-                     &quic_clock_,
-                     QuicRandom::GetInstance()) {
+      : quic_helper_(&quic_clock_, QuicRandom::GetInstance()),
+        alarm_factory_(base::ThreadTaskRunnerHandle::Get().get(),
+                       &quic_clock_) {
     // Simulate out-of-bound config handshake.
     CryptoHandshakeMessage hello_message;
     config_.ToHandshakeMessage(&hello_message);
@@ -230,8 +231,9 @@
     QuicChromiumPacketWriter* writer =
         new QuicChromiumPacketWriter(socket.get());
     std::unique_ptr<QuicConnection> quic_connection1(new QuicConnection(
-        0, IPEndPoint(IPAddress::IPv4AllZeros(), 0), &quic_helper_, writer,
-        true /* owns_writer */, perspective, QuicSupportedVersions()));
+        0, IPEndPoint(IPAddress::IPv4AllZeros(), 0), &quic_helper_,
+        &alarm_factory_, writer, true /* owns_writer */, perspective,
+        QuicSupportedVersions()));
     writer->SetConnection(quic_connection1.get());
 
     std::unique_ptr<QuicP2PSession> result(
@@ -247,6 +249,7 @@
 
   QuicClock quic_clock_;
   QuicChromiumConnectionHelper quic_helper_;
+  QuicChromiumAlarmFactory alarm_factory_;
   QuicConfig config_;
 
   base::WeakPtr<FakeP2PDatagramSocket> socket1_;
diff --git a/net/quic/quic_alarm_factory.h b/net/quic/quic_alarm_factory.h
new file mode 100644
index 0000000..237f2a2
--- /dev/null
+++ b/net/quic/quic_alarm_factory.h
@@ -0,0 +1,40 @@
+// Copyright (c) 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_QUIC_QUIC_ALARM_FACTORY_H_
+#define NET_QUIC_QUIC_ALARM_FACTORY_H_
+
+#include "net/base/net_export.h"
+#include "net/quic/quic_alarm.h"
+#include "net/quic/quic_one_block_arena.h"
+
+namespace net {
+
+// QuicConnections currently use around 1KB of polymorphic types which would
+// ordinarily be on the heap. Instead, store them inline in an arena.
+using QuicConnectionArena = QuicOneBlockArena<1024>;
+
+// Creates platform-specific alarms used throughout QUIC.
+class NET_EXPORT_PRIVATE QuicAlarmFactory {
+ public:
+  virtual ~QuicAlarmFactory() {}
+
+  // Creates a new platform-specific alarm which will be configured to notify
+  // |delegate| when the alarm fires. Returns an alarm allocated on the heap.
+  // Caller takes ownership of the new alarm, which will not yet be "set" to
+  // fire.
+  virtual QuicAlarm* CreateAlarm(QuicAlarm::Delegate* delegate) = 0;
+
+  // Creates a new platform-specific alarm which will be configured to notify
+  // |delegate| when the alarm fires. Caller takes ownership of the new alarm,
+  // which will not yet be "set" to fire. If |arena| is null, then the alarm
+  // will be created on the heap. Otherwise, it will be created in |arena|.
+  virtual QuicArenaScopedPtr<QuicAlarm> CreateAlarm(
+      QuicArenaScopedPtr<QuicAlarm::Delegate> delegate,
+      QuicConnectionArena* arena) = 0;
+};
+
+}  // namespace net
+
+#endif  // NET_QUIC_QUIC_ALARM_FACTORY_H_
diff --git a/net/quic/quic_chromium_alarm_factory.cc b/net/quic/quic_chromium_alarm_factory.cc
new file mode 100644
index 0000000..8973b97
--- /dev/null
+++ b/net/quic/quic_chromium_alarm_factory.cc
@@ -0,0 +1,117 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/quic_chromium_alarm_factory.h"
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/metrics/sparse_histogram.h"
+#include "base/task_runner.h"
+#include "base/time/time.h"
+
+namespace net {
+
+namespace {
+
+class QuicChromeAlarm : public QuicAlarm {
+ public:
+  QuicChromeAlarm(const QuicClock* clock,
+                  base::TaskRunner* task_runner,
+                  QuicArenaScopedPtr<QuicAlarm::Delegate> delegate)
+      : QuicAlarm(std::move(delegate)),
+        clock_(clock),
+        task_runner_(task_runner),
+        task_deadline_(QuicTime::Zero()),
+        weak_factory_(this) {}
+
+ protected:
+  void SetImpl() override {
+    DCHECK(deadline().IsInitialized());
+    if (task_deadline_.IsInitialized()) {
+      if (task_deadline_ <= deadline()) {
+        // Since tasks can not be un-posted, OnAlarm will be invoked which
+        // will notice that deadline has not yet been reached, and will set
+        // the alarm for the new deadline.
+        return;
+      }
+      // The scheduled task is after new deadline.  Invalidate the weak ptrs
+      // so that task does not execute when we're not expecting it.
+      weak_factory_.InvalidateWeakPtrs();
+    }
+
+    int64_t delay_us = deadline().Subtract(clock_->Now()).ToMicroseconds();
+    if (delay_us < 0) {
+      delay_us = 0;
+    }
+    task_runner_->PostDelayedTask(
+        FROM_HERE,
+        base::Bind(&QuicChromeAlarm::OnAlarm, weak_factory_.GetWeakPtr()),
+        base::TimeDelta::FromMicroseconds(delay_us));
+    task_deadline_ = deadline();
+  }
+
+  void CancelImpl() override {
+    DCHECK(!deadline().IsInitialized());
+    // Since tasks can not be un-posted, OnAlarm will be invoked which
+    // will notice that deadline is not Initialized and will do nothing.
+  }
+
+ private:
+  void OnAlarm() {
+    DCHECK(task_deadline_.IsInitialized());
+    task_deadline_ = QuicTime::Zero();
+    // The alarm may have been cancelled.
+    if (!deadline().IsInitialized()) {
+      return;
+    }
+
+    // The alarm may have been re-set to a later time.
+    if (clock_->Now() < deadline()) {
+      SetImpl();
+      return;
+    }
+
+    Fire();
+  }
+
+  const QuicClock* clock_;
+  base::TaskRunner* task_runner_;
+  // If a task has been posted to the message loop, this is the time it
+  // was scheduled to fire.  Tracking this allows us to avoid posting a
+  // new tast if the new deadline is in the future, but permits us to
+  // post a new task when the new deadline now earlier than when
+  // previously posted.
+  QuicTime task_deadline_;
+  base::WeakPtrFactory<QuicChromeAlarm> weak_factory_;
+};
+
+}  // namespace
+
+QuicChromiumAlarmFactory::QuicChromiumAlarmFactory(
+    base::TaskRunner* task_runner,
+    const QuicClock* clock)
+    : task_runner_(task_runner), clock_(clock), weak_factory_(this) {}
+
+QuicChromiumAlarmFactory::~QuicChromiumAlarmFactory() {}
+
+QuicArenaScopedPtr<QuicAlarm> QuicChromiumAlarmFactory::CreateAlarm(
+    QuicArenaScopedPtr<QuicAlarm::Delegate> delegate,
+    QuicConnectionArena* arena) {
+  if (arena != nullptr) {
+    return arena->New<QuicChromeAlarm>(clock_, task_runner_,
+                                       std::move(delegate));
+  } else {
+    return QuicArenaScopedPtr<QuicAlarm>(
+        new QuicChromeAlarm(clock_, task_runner_, std::move(delegate)));
+  }
+}
+
+QuicAlarm* QuicChromiumAlarmFactory::CreateAlarm(
+    QuicAlarm::Delegate* delegate) {
+  return new QuicChromeAlarm(clock_, task_runner_,
+                             QuicArenaScopedPtr<QuicAlarm::Delegate>(delegate));
+}
+
+}  // namespace net
diff --git a/net/quic/quic_chromium_alarm_factory.h b/net/quic/quic_chromium_alarm_factory.h
new file mode 100644
index 0000000..16345b72
--- /dev/null
+++ b/net/quic/quic_chromium_alarm_factory.h
@@ -0,0 +1,48 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// The Chrome-specific helper for QuicConnection which uses
+// a TaskRunner for alarms, and uses a DatagramClientSocket for writing data.
+
+#ifndef NET_QUIC_QUIC_CHROMIUM_ALARM_FACTORY_H_
+#define NET_QUIC_QUIC_CHROMIUM_ALARM_FACTORY_H_
+
+#include <set>
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "net/quic/quic_alarm_factory.h"
+#include "net/quic/quic_clock.h"
+#include "net/quic/quic_protocol.h"
+#include "net/quic/quic_time.h"
+
+namespace base {
+class TaskRunner;
+}  // namespace base
+
+namespace net {
+
+class NET_EXPORT_PRIVATE QuicChromiumAlarmFactory : public QuicAlarmFactory {
+ public:
+  QuicChromiumAlarmFactory(base::TaskRunner* task_runner,
+                           const QuicClock* clock);
+  ~QuicChromiumAlarmFactory() override;
+
+  // QuicAlarmFactory
+  QuicAlarm* CreateAlarm(QuicAlarm::Delegate* delegate) override;
+  QuicArenaScopedPtr<QuicAlarm> CreateAlarm(
+      QuicArenaScopedPtr<QuicAlarm::Delegate> delegate,
+      QuicConnectionArena* arena) override;
+
+ private:
+  base::TaskRunner* task_runner_;
+  const QuicClock* clock_;
+  base::WeakPtrFactory<QuicChromiumAlarmFactory> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(QuicChromiumAlarmFactory);
+};
+
+}  // namespace net
+
+#endif  // NET_QUIC_QUIC_CHROMIUM_ALARM_FACTORY_H_
diff --git a/net/quic/quic_chromium_alarm_factory_test.cc b/net/quic/quic_chromium_alarm_factory_test.cc
new file mode 100644
index 0000000..d47c98e
--- /dev/null
+++ b/net/quic/quic_chromium_alarm_factory_test.cc
@@ -0,0 +1,175 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/quic_chromium_alarm_factory.h"
+
+#include "net/quic/test_tools/mock_clock.h"
+#include "net/quic/test_tools/test_task_runner.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace test {
+namespace {
+
+class TestDelegate : public QuicAlarm::Delegate {
+ public:
+  TestDelegate() : fired_(false) {}
+
+  void OnAlarm() override { fired_ = true; }
+
+  bool fired() const { return fired_; }
+  void Clear() { fired_ = false; }
+
+ private:
+  bool fired_;
+};
+
+class QuicChromiumAlarmFactoryTest : public ::testing::Test {
+ protected:
+  QuicChromiumAlarmFactoryTest()
+      : runner_(new TestTaskRunner(&clock_)),
+        alarm_factory_(runner_.get(), &clock_) {}
+
+  scoped_refptr<TestTaskRunner> runner_;
+  QuicChromiumAlarmFactory alarm_factory_;
+  MockClock clock_;
+};
+
+TEST_F(QuicChromiumAlarmFactoryTest, CreateAlarm) {
+  TestDelegate* delegate = new TestDelegate();
+  std::unique_ptr<QuicAlarm> alarm(alarm_factory_.CreateAlarm(delegate));
+
+  QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1);
+  alarm->Set(clock_.Now().Add(delta));
+
+  // Verify that the alarm task has been posted.
+  ASSERT_EQ(1u, runner_->GetPostedTasks().size());
+  EXPECT_EQ(base::TimeDelta::FromMicroseconds(delta.ToMicroseconds()),
+            runner_->GetPostedTasks()[0].delay);
+
+  runner_->RunNextTask();
+  EXPECT_EQ(QuicTime::Zero().Add(delta), clock_.Now());
+  EXPECT_TRUE(delegate->fired());
+}
+
+TEST_F(QuicChromiumAlarmFactoryTest, CreateAlarmAndCancel) {
+  TestDelegate* delegate = new TestDelegate();
+  std::unique_ptr<QuicAlarm> alarm(alarm_factory_.CreateAlarm(delegate));
+
+  QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1);
+  alarm->Set(clock_.Now().Add(delta));
+  alarm->Cancel();
+
+  // The alarm task should still be posted.
+  ASSERT_EQ(1u, runner_->GetPostedTasks().size());
+  EXPECT_EQ(base::TimeDelta::FromMicroseconds(delta.ToMicroseconds()),
+            runner_->GetPostedTasks()[0].delay);
+
+  runner_->RunNextTask();
+  EXPECT_EQ(QuicTime::Zero().Add(delta), clock_.Now());
+  EXPECT_FALSE(delegate->fired());
+}
+
+TEST_F(QuicChromiumAlarmFactoryTest, CreateAlarmAndReset) {
+  TestDelegate* delegate = new TestDelegate();
+  std::unique_ptr<QuicAlarm> alarm(alarm_factory_.CreateAlarm(delegate));
+
+  QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1);
+  alarm->Set(clock_.Now().Add(delta));
+  alarm->Cancel();
+  QuicTime::Delta new_delta = QuicTime::Delta::FromMicroseconds(3);
+  alarm->Set(clock_.Now().Add(new_delta));
+
+  // The alarm task should still be posted.
+  ASSERT_EQ(1u, runner_->GetPostedTasks().size());
+  EXPECT_EQ(base::TimeDelta::FromMicroseconds(delta.ToMicroseconds()),
+            runner_->GetPostedTasks()[0].delay);
+
+  runner_->RunNextTask();
+  EXPECT_EQ(QuicTime::Zero().Add(delta), clock_.Now());
+  EXPECT_FALSE(delegate->fired());
+
+  // The alarm task should be posted again.
+  ASSERT_EQ(1u, runner_->GetPostedTasks().size());
+
+  runner_->RunNextTask();
+  EXPECT_EQ(QuicTime::Zero().Add(new_delta), clock_.Now());
+  EXPECT_TRUE(delegate->fired());
+}
+
+TEST_F(QuicChromiumAlarmFactoryTest, CreateAlarmAndResetEarlier) {
+  TestDelegate* delegate = new TestDelegate();
+  std::unique_ptr<QuicAlarm> alarm(alarm_factory_.CreateAlarm(delegate));
+
+  QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(3);
+  alarm->Set(clock_.Now().Add(delta));
+  alarm->Cancel();
+  QuicTime::Delta new_delta = QuicTime::Delta::FromMicroseconds(1);
+  alarm->Set(clock_.Now().Add(new_delta));
+
+  // Both alarm tasks will be posted.
+  ASSERT_EQ(2u, runner_->GetPostedTasks().size());
+
+  // The earlier task will execute and will fire the alarm->
+  runner_->RunNextTask();
+  EXPECT_EQ(QuicTime::Zero().Add(new_delta), clock_.Now());
+  EXPECT_TRUE(delegate->fired());
+  delegate->Clear();
+
+  // The latter task is still posted.
+  ASSERT_EQ(1u, runner_->GetPostedTasks().size());
+
+  // When the latter task is executed, the weak ptr will be invalid and
+  // the alarm will not fire.
+  runner_->RunNextTask();
+  EXPECT_EQ(QuicTime::Zero().Add(delta), clock_.Now());
+  EXPECT_FALSE(delegate->fired());
+}
+
+TEST_F(QuicChromiumAlarmFactoryTest, CreateAlarmAndUpdate) {
+  TestDelegate* delegate = new TestDelegate();
+  std::unique_ptr<QuicAlarm> alarm(alarm_factory_.CreateAlarm(delegate));
+
+  QuicTime start = clock_.Now();
+  QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1);
+  alarm->Set(clock_.Now().Add(delta));
+  QuicTime::Delta new_delta = QuicTime::Delta::FromMicroseconds(3);
+  alarm->Update(clock_.Now().Add(new_delta),
+                QuicTime::Delta::FromMicroseconds(1));
+
+  // The alarm task should still be posted.
+  ASSERT_EQ(1u, runner_->GetPostedTasks().size());
+  EXPECT_EQ(base::TimeDelta::FromMicroseconds(delta.ToMicroseconds()),
+            runner_->GetPostedTasks()[0].delay);
+
+  runner_->RunNextTask();
+  EXPECT_EQ(QuicTime::Zero().Add(delta), clock_.Now());
+  EXPECT_FALSE(delegate->fired());
+
+  // Move the alarm forward 1us and ensure it doesn't move forward.
+  alarm->Update(clock_.Now().Add(new_delta),
+                QuicTime::Delta::FromMicroseconds(2));
+
+  ASSERT_EQ(1u, runner_->GetPostedTasks().size());
+  EXPECT_EQ(base::TimeDelta::FromMicroseconds(
+                new_delta.Subtract(delta).ToMicroseconds()),
+            runner_->GetPostedTasks()[0].delay);
+  runner_->RunNextTask();
+  EXPECT_EQ(start.Add(new_delta), clock_.Now());
+  EXPECT_TRUE(delegate->fired());
+
+  // Set the alarm via an update call.
+  new_delta = QuicTime::Delta::FromMicroseconds(5);
+  alarm->Update(clock_.Now().Add(new_delta),
+                QuicTime::Delta::FromMicroseconds(1));
+  EXPECT_TRUE(alarm->IsSet());
+
+  // Update it with an uninitialized time and ensure it's cancelled.
+  alarm->Update(QuicTime::Zero(), QuicTime::Delta::FromMicroseconds(1));
+  EXPECT_FALSE(alarm->IsSet());
+}
+
+}  // namespace
+}  // namespace test
+}  // namespace net
diff --git a/net/quic/quic_chromium_client_session_test.cc b/net/quic/quic_chromium_client_session_test.cc
index a17b663ce..f8e17f9 100644
--- a/net/quic/quic_chromium_client_session_test.cc
+++ b/net/quic/quic_chromium_client_session_test.cc
@@ -23,6 +23,7 @@
 #include "net/quic/crypto/quic_decrypter.h"
 #include "net/quic/crypto/quic_encrypter.h"
 #include "net/quic/crypto/quic_server_info.h"
+#include "net/quic/quic_chromium_alarm_factory.h"
 #include "net/quic/quic_chromium_connection_helper.h"
 #include "net/quic/quic_chromium_packet_reader.h"
 #include "net/quic/quic_chromium_packet_writer.h"
@@ -63,7 +64,8 @@
         socket_data_(
             new SequencedSocketData(default_read_.get(), 1, nullptr, 0)),
         random_(0),
-        helper_(base::ThreadTaskRunnerHandle::Get().get(), &clock_, &random_),
+        helper_(&clock_, &random_),
+        alarm_factory_(base::ThreadTaskRunnerHandle::Get().get(), &clock_),
         maker_(GetParam(), 0, &clock_, kServerHostname) {
     // Advance the time, because timers do not like uninitialized times.
     clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
@@ -79,8 +81,8 @@
     QuicChromiumPacketWriter* writer =
         new net::QuicChromiumPacketWriter(socket.get());
     QuicConnection* connection = new QuicConnection(
-        0, kIpEndPoint, &helper_, writer, true, Perspective::IS_CLIENT,
-        SupportedVersions(GetParam()));
+        0, kIpEndPoint, &helper_, &alarm_factory_, writer, true,
+        Perspective::IS_CLIENT, SupportedVersions(GetParam()));
     writer->SetConnection(connection);
     session_.reset(new QuicChromiumClientSession(
         connection, std::move(socket),
@@ -127,6 +129,7 @@
   MockClock clock_;
   MockRandom random_;
   QuicChromiumConnectionHelper helper_;
+  QuicChromiumAlarmFactory alarm_factory_;
   TransportSecurityState transport_security_state_;
   MockCryptoClientStreamFactory crypto_client_stream_factory_;
   std::unique_ptr<QuicChromiumClientSession> session_;
diff --git a/net/quic/quic_chromium_client_stream_test.cc b/net/quic/quic_chromium_client_stream_test.cc
index 4b1d31ed..b7c888c 100644
--- a/net/quic/quic_chromium_client_stream_test.cc
+++ b/net/quic/quic_chromium_client_stream_test.cc
@@ -144,6 +144,7 @@
   QuicChromiumClientStreamTest()
       : crypto_config_(CryptoTestUtils::ProofVerifierForTesting()),
         session_(new MockConnection(&helper_,
+                                    &alarm_factory_,
                                     Perspective::IS_CLIENT,
                                     SupportedVersions(GetParam())),
                  &push_promise_index_) {
@@ -194,6 +195,7 @@
   QuicCryptoClientConfig crypto_config_;
   testing::StrictMock<MockDelegate> delegate_;
   MockConnectionHelper helper_;
+  MockAlarmFactory alarm_factory_;
   MockQuicClientSessionBase session_;
   QuicChromiumClientStream* stream_;
   SpdyHeaderBlock headers_;
diff --git a/net/quic/quic_chromium_connection_helper.cc b/net/quic/quic_chromium_connection_helper.cc
index d88648f..9bdb407 100644
--- a/net/quic/quic_chromium_connection_helper.cc
+++ b/net/quic/quic_chromium_connection_helper.cc
@@ -4,101 +4,12 @@
 
 #include "net/quic/quic_chromium_connection_helper.h"
 
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/metrics/sparse_histogram.h"
-#include "base/task_runner.h"
-#include "base/time/time.h"
-#include "net/base/io_buffer.h"
-#include "net/base/net_errors.h"
-#include "net/quic/quic_utils.h"
-
 namespace net {
 
-namespace {
-
-class QuicChromeAlarm : public QuicAlarm {
- public:
-  QuicChromeAlarm(const QuicClock* clock,
-                  base::TaskRunner* task_runner,
-                  QuicArenaScopedPtr<QuicAlarm::Delegate> delegate)
-      : QuicAlarm(std::move(delegate)),
-        clock_(clock),
-        task_runner_(task_runner),
-        task_deadline_(QuicTime::Zero()),
-        weak_factory_(this) {}
-
- protected:
-  void SetImpl() override {
-    DCHECK(deadline().IsInitialized());
-    if (task_deadline_.IsInitialized()) {
-      if (task_deadline_ <= deadline()) {
-        // Since tasks can not be un-posted, OnAlarm will be invoked which
-        // will notice that deadline has not yet been reached, and will set
-        // the alarm for the new deadline.
-        return;
-      }
-      // The scheduled task is after new deadline.  Invalidate the weak ptrs
-      // so that task does not execute when we're not expecting it.
-      weak_factory_.InvalidateWeakPtrs();
-    }
-
-    int64_t delay_us = deadline().Subtract(clock_->Now()).ToMicroseconds();
-    if (delay_us < 0) {
-      delay_us = 0;
-    }
-    task_runner_->PostDelayedTask(
-        FROM_HERE,
-        base::Bind(&QuicChromeAlarm::OnAlarm, weak_factory_.GetWeakPtr()),
-        base::TimeDelta::FromMicroseconds(delay_us));
-    task_deadline_ = deadline();
-  }
-
-  void CancelImpl() override {
-    DCHECK(!deadline().IsInitialized());
-    // Since tasks can not be un-posted, OnAlarm will be invoked which
-    // will notice that deadline is not Initialized and will do nothing.
-  }
-
- private:
-  void OnAlarm() {
-    DCHECK(task_deadline_.IsInitialized());
-    task_deadline_ = QuicTime::Zero();
-    // The alarm may have been cancelled.
-    if (!deadline().IsInitialized()) {
-      return;
-    }
-
-    // The alarm may have been re-set to a later time.
-    if (clock_->Now() < deadline()) {
-      SetImpl();
-      return;
-    }
-
-    Fire();
-  }
-
-  const QuicClock* clock_;
-  base::TaskRunner* task_runner_;
-  // If a task has been posted to the message loop, this is the time it
-  // was scheduled to fire.  Tracking this allows us to avoid posting a
-  // new tast if the new deadline is in the future, but permits us to
-  // post a new task when the new deadline now earlier than when
-  // previously posted.
-  QuicTime task_deadline_;
-  base::WeakPtrFactory<QuicChromeAlarm> weak_factory_;
-};
-
-}  // namespace
-
 QuicChromiumConnectionHelper::QuicChromiumConnectionHelper(
-    base::TaskRunner* task_runner,
     const QuicClock* clock,
     QuicRandom* random_generator)
-    : task_runner_(task_runner),
-      clock_(clock),
-      random_generator_(random_generator),
-      weak_factory_(this) {}
+    : clock_(clock), random_generator_(random_generator) {}
 
 QuicChromiumConnectionHelper::~QuicChromiumConnectionHelper() {}
 
@@ -110,24 +21,6 @@
   return random_generator_;
 }
 
-QuicArenaScopedPtr<QuicAlarm> QuicChromiumConnectionHelper::CreateAlarm(
-    QuicArenaScopedPtr<QuicAlarm::Delegate> delegate,
-    QuicConnectionArena* arena) {
-  if (arena != nullptr) {
-    return arena->New<QuicChromeAlarm>(clock_, task_runner_,
-                                       std::move(delegate));
-  } else {
-    return QuicArenaScopedPtr<QuicAlarm>(
-        new QuicChromeAlarm(clock_, task_runner_, std::move(delegate)));
-  }
-}
-
-QuicAlarm* QuicChromiumConnectionHelper::CreateAlarm(
-    QuicAlarm::Delegate* delegate) {
-  return new QuicChromeAlarm(clock_, task_runner_,
-                             QuicArenaScopedPtr<QuicAlarm::Delegate>(delegate));
-}
-
 QuicBufferAllocator* QuicChromiumConnectionHelper::GetBufferAllocator() {
   return &buffer_allocator_;
 }
diff --git a/net/quic/quic_chromium_connection_helper.h b/net/quic/quic_chromium_connection_helper.h
index 281a3f3..34fbe47 100644
--- a/net/quic/quic_chromium_connection_helper.h
+++ b/net/quic/quic_chromium_connection_helper.h
@@ -8,10 +8,7 @@
 #ifndef NET_QUIC_QUIC_CONNECTION_HELPER_H_
 #define NET_QUIC_QUIC_CONNECTION_HELPER_H_
 
-#include <set>
-
 #include "base/macros.h"
-#include "base/memory/weak_ptr.h"
 #include "net/base/ip_endpoint.h"
 #include "net/quic/quic_connection.h"
 #include "net/quic/quic_protocol.h"
@@ -31,26 +28,19 @@
 class NET_EXPORT_PRIVATE QuicChromiumConnectionHelper
     : public QuicConnectionHelperInterface {
  public:
-  QuicChromiumConnectionHelper(base::TaskRunner* task_runner,
-                               const QuicClock* clock,
+  QuicChromiumConnectionHelper(const QuicClock* clock,
                                QuicRandom* random_generator);
   ~QuicChromiumConnectionHelper() override;
 
   // QuicConnectionHelperInterface
   const QuicClock* GetClock() const override;
   QuicRandom* GetRandomGenerator() override;
-  QuicAlarm* CreateAlarm(QuicAlarm::Delegate* delegate) override;
-  QuicArenaScopedPtr<QuicAlarm> CreateAlarm(
-      QuicArenaScopedPtr<QuicAlarm::Delegate> delegate,
-      QuicConnectionArena* arena) override;
   QuicBufferAllocator* GetBufferAllocator() override;
 
  private:
-  base::TaskRunner* task_runner_;
   const QuicClock* clock_;
   QuicRandom* random_generator_;
   SimpleBufferAllocator buffer_allocator_;
-  base::WeakPtrFactory<QuicChromiumConnectionHelper> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(QuicChromiumConnectionHelper);
 };
diff --git a/net/quic/quic_chromium_connection_helper_test.cc b/net/quic/quic_chromium_connection_helper_test.cc
index 2774d17..356ac6c 100644
--- a/net/quic/quic_chromium_connection_helper_test.cc
+++ b/net/quic/quic_chromium_connection_helper_test.cc
@@ -6,33 +6,16 @@
 
 #include "net/quic/test_tools/mock_clock.h"
 #include "net/quic/test_tools/mock_random.h"
-#include "net/quic/test_tools/test_task_runner.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace net {
 namespace test {
 namespace {
 
-class TestDelegate : public QuicAlarm::Delegate {
- public:
-  TestDelegate() : fired_(false) {}
-
-  void OnAlarm() override { fired_ = true; }
-
-  bool fired() const { return fired_; }
-  void Clear() { fired_ = false; }
-
- private:
-  bool fired_;
-};
-
 class QuicChromiumConnectionHelperTest : public ::testing::Test {
  protected:
-  QuicChromiumConnectionHelperTest()
-      : runner_(new TestTaskRunner(&clock_)),
-        helper_(runner_.get(), &clock_, &random_generator_) {}
+  QuicChromiumConnectionHelperTest() : helper_(&clock_, &random_generator_) {}
 
-  scoped_refptr<TestTaskRunner> runner_;
   QuicChromiumConnectionHelper helper_;
   MockClock clock_;
   MockRandom random_generator_;
@@ -46,141 +29,6 @@
   EXPECT_EQ(&random_generator_, helper_.GetRandomGenerator());
 }
 
-TEST_F(QuicChromiumConnectionHelperTest, CreateAlarm) {
-  TestDelegate* delegate = new TestDelegate();
-  std::unique_ptr<QuicAlarm> alarm(helper_.CreateAlarm(delegate));
-
-  QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1);
-  alarm->Set(clock_.Now().Add(delta));
-
-  // Verify that the alarm task has been posted.
-  ASSERT_EQ(1u, runner_->GetPostedTasks().size());
-  EXPECT_EQ(base::TimeDelta::FromMicroseconds(delta.ToMicroseconds()),
-            runner_->GetPostedTasks()[0].delay);
-
-  runner_->RunNextTask();
-  EXPECT_EQ(QuicTime::Zero().Add(delta), clock_.Now());
-  EXPECT_TRUE(delegate->fired());
-}
-
-TEST_F(QuicChromiumConnectionHelperTest, CreateAlarmAndCancel) {
-  TestDelegate* delegate = new TestDelegate();
-  std::unique_ptr<QuicAlarm> alarm(helper_.CreateAlarm(delegate));
-
-  QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1);
-  alarm->Set(clock_.Now().Add(delta));
-  alarm->Cancel();
-
-  // The alarm task should still be posted.
-  ASSERT_EQ(1u, runner_->GetPostedTasks().size());
-  EXPECT_EQ(base::TimeDelta::FromMicroseconds(delta.ToMicroseconds()),
-            runner_->GetPostedTasks()[0].delay);
-
-  runner_->RunNextTask();
-  EXPECT_EQ(QuicTime::Zero().Add(delta), clock_.Now());
-  EXPECT_FALSE(delegate->fired());
-}
-
-TEST_F(QuicChromiumConnectionHelperTest, CreateAlarmAndReset) {
-  TestDelegate* delegate = new TestDelegate();
-  std::unique_ptr<QuicAlarm> alarm(helper_.CreateAlarm(delegate));
-
-  QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1);
-  alarm->Set(clock_.Now().Add(delta));
-  alarm->Cancel();
-  QuicTime::Delta new_delta = QuicTime::Delta::FromMicroseconds(3);
-  alarm->Set(clock_.Now().Add(new_delta));
-
-  // The alarm task should still be posted.
-  ASSERT_EQ(1u, runner_->GetPostedTasks().size());
-  EXPECT_EQ(base::TimeDelta::FromMicroseconds(delta.ToMicroseconds()),
-            runner_->GetPostedTasks()[0].delay);
-
-  runner_->RunNextTask();
-  EXPECT_EQ(QuicTime::Zero().Add(delta), clock_.Now());
-  EXPECT_FALSE(delegate->fired());
-
-  // The alarm task should be posted again.
-  ASSERT_EQ(1u, runner_->GetPostedTasks().size());
-
-  runner_->RunNextTask();
-  EXPECT_EQ(QuicTime::Zero().Add(new_delta), clock_.Now());
-  EXPECT_TRUE(delegate->fired());
-}
-
-TEST_F(QuicChromiumConnectionHelperTest, CreateAlarmAndResetEarlier) {
-  TestDelegate* delegate = new TestDelegate();
-  std::unique_ptr<QuicAlarm> alarm(helper_.CreateAlarm(delegate));
-
-  QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(3);
-  alarm->Set(clock_.Now().Add(delta));
-  alarm->Cancel();
-  QuicTime::Delta new_delta = QuicTime::Delta::FromMicroseconds(1);
-  alarm->Set(clock_.Now().Add(new_delta));
-
-  // Both alarm tasks will be posted.
-  ASSERT_EQ(2u, runner_->GetPostedTasks().size());
-
-  // The earlier task will execute and will fire the alarm->
-  runner_->RunNextTask();
-  EXPECT_EQ(QuicTime::Zero().Add(new_delta), clock_.Now());
-  EXPECT_TRUE(delegate->fired());
-  delegate->Clear();
-
-  // The latter task is still posted.
-  ASSERT_EQ(1u, runner_->GetPostedTasks().size());
-
-  // When the latter task is executed, the weak ptr will be invalid and
-  // the alarm will not fire.
-  runner_->RunNextTask();
-  EXPECT_EQ(QuicTime::Zero().Add(delta), clock_.Now());
-  EXPECT_FALSE(delegate->fired());
-}
-
-TEST_F(QuicChromiumConnectionHelperTest, CreateAlarmAndUpdate) {
-  TestDelegate* delegate = new TestDelegate();
-  std::unique_ptr<QuicAlarm> alarm(helper_.CreateAlarm(delegate));
-
-  const QuicClock* clock = helper_.GetClock();
-  QuicTime start = clock->Now();
-  QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1);
-  alarm->Set(clock->Now().Add(delta));
-  QuicTime::Delta new_delta = QuicTime::Delta::FromMicroseconds(3);
-  alarm->Update(clock->Now().Add(new_delta),
-                QuicTime::Delta::FromMicroseconds(1));
-
-  // The alarm task should still be posted.
-  ASSERT_EQ(1u, runner_->GetPostedTasks().size());
-  EXPECT_EQ(base::TimeDelta::FromMicroseconds(delta.ToMicroseconds()),
-            runner_->GetPostedTasks()[0].delay);
-
-  runner_->RunNextTask();
-  EXPECT_EQ(QuicTime::Zero().Add(delta), clock->Now());
-  EXPECT_FALSE(delegate->fired());
-
-  // Move the alarm forward 1us and ensure it doesn't move forward.
-  alarm->Update(clock->Now().Add(new_delta),
-                QuicTime::Delta::FromMicroseconds(2));
-
-  ASSERT_EQ(1u, runner_->GetPostedTasks().size());
-  EXPECT_EQ(base::TimeDelta::FromMicroseconds(
-                new_delta.Subtract(delta).ToMicroseconds()),
-            runner_->GetPostedTasks()[0].delay);
-  runner_->RunNextTask();
-  EXPECT_EQ(start.Add(new_delta), clock->Now());
-  EXPECT_TRUE(delegate->fired());
-
-  // Set the alarm via an update call.
-  new_delta = QuicTime::Delta::FromMicroseconds(5);
-  alarm->Update(clock->Now().Add(new_delta),
-                QuicTime::Delta::FromMicroseconds(1));
-  EXPECT_TRUE(alarm->IsSet());
-
-  // Update it with an uninitialized time and ensure it's cancelled.
-  alarm->Update(QuicTime::Zero(), QuicTime::Delta::FromMicroseconds(1));
-  EXPECT_FALSE(alarm->IsSet());
-}
-
 }  // namespace
 }  // namespace test
 }  // namespace net
diff --git a/net/quic/quic_client_promised_info.cc b/net/quic/quic_client_promised_info.cc
index f4bef0bc..14cba80e 100644
--- a/net/quic/quic_client_promised_info.cc
+++ b/net/quic/quic_client_promised_info.cc
@@ -17,7 +17,6 @@
                                                QuicStreamId id,
                                                string url)
     : session_(session),
-      helper_(session->connection()->helper()),
       id_(id),
       url_(url),
       client_request_delegate_(nullptr) {}
@@ -30,10 +29,11 @@
 }
 
 void QuicClientPromisedInfo::Init() {
-  cleanup_alarm_.reset(
-      helper_->CreateAlarm(new QuicClientPromisedInfo::CleanupAlarm(this)));
-  cleanup_alarm_->Set(helper_->GetClock()->ApproximateNow().Add(
-      QuicTime::Delta::FromSeconds(kPushPromiseTimeoutSecs)));
+  cleanup_alarm_.reset(session_->connection()->alarm_factory()->CreateAlarm(
+      new QuicClientPromisedInfo::CleanupAlarm(this)));
+  cleanup_alarm_->Set(
+      session_->connection()->helper()->GetClock()->ApproximateNow().Add(
+          QuicTime::Delta::FromSeconds(kPushPromiseTimeoutSecs)));
 }
 
 void QuicClientPromisedInfo::OnPromiseHeaders(const SpdyHeaderBlock& headers) {
diff --git a/net/quic/quic_client_promised_info.h b/net/quic/quic_client_promised_info.h
index f4bb50f2..5b14d14 100644
--- a/net/quic/quic_client_promised_info.h
+++ b/net/quic/quic_client_promised_info.h
@@ -54,6 +54,8 @@
 
   void Cancel() override;
 
+  void Reset(QuicRstStreamErrorCode error_code);
+
   // Client requests are initially associated to promises by matching
   // URL in the client request against the URL in the promise headers,
   // uing the |promised_by_url| map.  The push can be cross-origin, so
@@ -88,12 +90,9 @@
     QuicClientPromisedInfo* promised_;
   };
 
-  void Reset(QuicRstStreamErrorCode error_code);
-
   QuicAsyncStatus FinalValidation();
 
   QuicClientSessionBase* session_;
-  QuicConnectionHelperInterface* helper_;
   QuicStreamId id_;
   std::string url_;
   std::unique_ptr<SpdyHeaderBlock> request_headers_;
diff --git a/net/quic/quic_client_promised_info_test.cc b/net/quic/quic_client_promised_info_test.cc
index df4694c..f05f8f2e 100644
--- a/net/quic/quic_client_promised_info_test.cc
+++ b/net/quic/quic_client_promised_info_test.cc
@@ -4,6 +4,8 @@
 
 #include "net/quic/quic_client_promised_info.h"
 
+#include <memory>
+
 #include "base/macros.h"
 #include "base/scoped_ptr.h"
 #include "net/gfe2/balsa_headers.h"
@@ -70,8 +72,9 @@
   class StreamVisitor;
 
   QuicClientPromisedInfoTest()
-      : connection_(
-            new StrictMock<MockConnection>(&helper_, Perspective::IS_CLIENT)),
+      : connection_(new StrictMock<MockConnection>(&helper_,
+                                                   &alarm_factory_,
+                                                   Perspective::IS_CLIENT)),
         session_(connection_, &push_promise_index_),
         body_("hello world"),
         promise_id_(gfe_quic::test::kServerDataStreamId1) {
@@ -142,6 +145,7 @@
   }
 
   MockConnectionHelper helper_;
+  MockAlarmFactory alarm_factory_;
   StrictMock<MockConnection>* connection_;
   QuicClientPushPromiseIndex push_promise_index_;
 
@@ -176,7 +180,7 @@
   // Fire the alarm that will cancel the promised stream.
   EXPECT_CALL(*connection_,
               SendRstStream(promise_id_, QUIC_STREAM_CANCELLED, 0));
-  helper_.FireAlarm(QuicClientPromisedInfoPeer::GetAlarm(promised));
+  alarm_factory_.FireAlarm(QuicClientPromisedInfoPeer::GetAlarm(promised));
 
   // Verify that the promise is gone after the alarm fires.
   EXPECT_EQ(session_.GetPromisedById(promise_id_), nullptr);
diff --git a/net/quic/quic_client_push_promise_index_test.cc b/net/quic/quic_client_push_promise_index_test.cc
index 85c7f0c..672fcfc 100644
--- a/net/quic/quic_client_push_promise_index_test.cc
+++ b/net/quic/quic_client_push_promise_index_test.cc
@@ -45,8 +45,9 @@
 class QuicClientPushPromiseIndexTest : public ::testing::Test {
  public:
   QuicClientPushPromiseIndexTest()
-      : connection_(
-            new StrictMock<MockConnection>(&helper_, Perspective::IS_CLIENT)),
+      : connection_(new StrictMock<MockConnection>(&helper_,
+                                                   &alarm_factory_,
+                                                   Perspective::IS_CLIENT)),
         session_(connection_, &index_),
         promised_(&session_, kServerDataStreamId1, url_) {
     FLAGS_quic_supports_push_promise = true;
@@ -59,6 +60,7 @@
   }
 
   MockConnectionHelper helper_;
+  MockAlarmFactory alarm_factory_;
   StrictMock<MockConnection>* connection_;
   MockQuicClientSession session_;
   QuicClientPushPromiseIndex index_;
diff --git a/net/quic/quic_client_session_base.cc b/net/quic/quic_client_session_base.cc
index 14c6f5e..dff71e4 100644
--- a/net/quic/quic_client_session_base.cc
+++ b/net/quic/quic_client_session_base.cc
@@ -81,6 +81,30 @@
   stream->OnPromiseHeadersComplete(promised_stream_id, frame_len);
 }
 
+void QuicClientSessionBase::OnPromiseHeaderList(
+    QuicStreamId stream_id,
+    QuicStreamId promised_stream_id,
+    size_t frame_len,
+    const QuicHeaderList& header_list) {
+  if (promised_stream_id != kInvalidStreamId &&
+      promised_stream_id <= largest_promised_stream_id_) {
+    connection()->CloseConnection(
+        QUIC_INVALID_STREAM_ID,
+        "Received push stream id lesser or equal to the"
+        " last accepted before",
+        ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+    return;
+  }
+  largest_promised_stream_id_ = promised_stream_id;
+
+  QuicSpdyStream* stream = GetSpdyDataStream(stream_id);
+  if (!stream) {
+    // It's quite possible to receive headers after a stream has been reset.
+    return;
+  }
+  stream->OnPromiseHeaderList(promised_stream_id, frame_len, header_list);
+}
+
 void QuicClientSessionBase::HandlePromised(QuicStreamId /* associated_id */,
                                            QuicStreamId id,
                                            const SpdyHeaderBlock& headers) {
diff --git a/net/quic/quic_client_session_base.h b/net/quic/quic_client_session_base.h
index 96231102..58c7d65b 100644
--- a/net/quic/quic_client_session_base.h
+++ b/net/quic/quic_client_session_base.h
@@ -51,12 +51,18 @@
                         base::StringPiece headers_data) override;
 
   // Called by |headers_stream_| when push promise headers have been
-  // completely received.  |fin| will be true if the fin flag was set
-  // in the headers.
+  // completely received.
   void OnPromiseHeadersComplete(QuicStreamId stream_id,
                                 QuicStreamId promised_stream_id,
                                 size_t frame_len) override;
 
+  // Called by |headers_stream_| when push promise headers have been
+  // completely received.
+  void OnPromiseHeaderList(QuicStreamId stream_id,
+                           QuicStreamId promised_stream_id,
+                           size_t frame_len,
+                           const QuicHeaderList& header_list) override;
+
   // Called by |QuicSpdyClientStream| on receipt of response headers,
   // needed to detect promised server push streams, as part of
   // client-request to push-stream rendezvous.
diff --git a/net/quic/quic_connection.cc b/net/quic/quic_connection.cc
index 60f5395..c8a132f 100644
--- a/net/quic/quic_connection.cc
+++ b/net/quic/quic_connection.cc
@@ -204,6 +204,7 @@
 QuicConnection::QuicConnection(QuicConnectionId connection_id,
                                IPEndPoint address,
                                QuicConnectionHelperInterface* helper,
+                               QuicAlarmFactory* alarm_factory,
                                QuicPacketWriter* writer,
                                bool owns_writer,
                                Perspective perspective,
@@ -212,6 +213,7 @@
               helper->GetClock()->ApproximateNow(),
               perspective),
       helper_(helper),
+      alarm_factory_(alarm_factory),
       per_packet_options_(nullptr),
       writer_(writer),
       owns_writer_(owns_writer),
@@ -248,17 +250,22 @@
       pending_retransmission_alarm_(false),
       defer_send_in_response_to_packets_(false),
       arena_(),
-      ack_alarm_(helper->CreateAlarm(arena_.New<AckAlarm>(this), &arena_)),
+      ack_alarm_(
+          alarm_factory_->CreateAlarm(arena_.New<AckAlarm>(this), &arena_)),
       retransmission_alarm_(
-          helper->CreateAlarm(arena_.New<RetransmissionAlarm>(this), &arena_)),
-      send_alarm_(helper->CreateAlarm(arena_.New<SendAlarm>(this), &arena_)),
+          alarm_factory_->CreateAlarm(arena_.New<RetransmissionAlarm>(this),
+                                      &arena_)),
+      send_alarm_(
+          alarm_factory_->CreateAlarm(arena_.New<SendAlarm>(this), &arena_)),
       resume_writes_alarm_(
-          helper->CreateAlarm(arena_.New<SendAlarm>(this), &arena_)),
+          alarm_factory_->CreateAlarm(arena_.New<SendAlarm>(this), &arena_)),
       timeout_alarm_(
-          helper->CreateAlarm(arena_.New<TimeoutAlarm>(this), &arena_)),
-      ping_alarm_(helper->CreateAlarm(arena_.New<PingAlarm>(this), &arena_)),
+          alarm_factory_->CreateAlarm(arena_.New<TimeoutAlarm>(this), &arena_)),
+      ping_alarm_(
+          alarm_factory_->CreateAlarm(arena_.New<PingAlarm>(this), &arena_)),
       mtu_discovery_alarm_(
-          helper->CreateAlarm(arena_.New<MtuDiscoveryAlarm>(this), &arena_)),
+          alarm_factory_->CreateAlarm(arena_.New<MtuDiscoveryAlarm>(this),
+                                      &arena_)),
       visitor_(nullptr),
       debug_visitor_(nullptr),
       packet_generator_(connection_id_,
diff --git a/net/quic/quic_connection.h b/net/quic/quic_connection.h
index 597edd5..443aaa44 100644
--- a/net/quic/quic_connection.h
+++ b/net/quic/quic_connection.h
@@ -34,6 +34,7 @@
 #include "net/base/ip_endpoint.h"
 #include "net/quic/crypto/quic_decrypter.h"
 #include "net/quic/quic_alarm.h"
+#include "net/quic/quic_alarm_factory.h"
 #include "net/quic/quic_blocked_writer_interface.h"
 #include "net/quic/quic_fec_group.h"
 #include "net/quic/quic_framer.h"
@@ -273,20 +274,6 @@
   // Returns a QuicRandom to be used for all random number related functions.
   virtual QuicRandom* GetRandomGenerator() = 0;
 
-  // Creates a new platform-specific alarm which will be configured to notify
-  // |delegate| when the alarm fires. Returns an alarm allocated on the heap.
-  // Caller takes ownership of the new alarm, which will not yet be "set" to
-  // fire.
-  virtual QuicAlarm* CreateAlarm(QuicAlarm::Delegate* delegate) = 0;
-
-  // Creates a new platform-specific alarm which will be configured to notify
-  // |delegate| when the alarm fires. Caller takes ownership of the new alarm,
-  // which will not yet be "set" to fire. If |arena| is null, then the alarm
-  // will be created on the heap. Otherwise, it will be created in |arena|.
-  virtual QuicArenaScopedPtr<QuicAlarm> CreateAlarm(
-      QuicArenaScopedPtr<QuicAlarm::Delegate> delegate,
-      QuicConnectionArena* arena) = 0;
-
   // Returns a QuicBufferAllocator to be used for all stream frame buffers.
   virtual QuicBufferAllocator* GetBufferAllocator() = 0;
 };
@@ -314,6 +301,7 @@
   QuicConnection(QuicConnectionId connection_id,
                  IPEndPoint address,
                  QuicConnectionHelperInterface* helper,
+                 QuicAlarmFactory* alarm_factory,
                  QuicPacketWriter* writer,
                  bool owns_writer,
                  Perspective perspective,
@@ -665,6 +653,7 @@
   bool ack_frame_updated() const;
 
   QuicConnectionHelperInterface* helper() { return helper_; }
+  QuicAlarmFactory* alarm_factory() { return alarm_factory_; }
 
   base::StringPiece GetCurrentPacket();
 
@@ -839,6 +828,7 @@
 
   QuicFramer framer_;
   QuicConnectionHelperInterface* helper_;  // Not owned.
+  QuicAlarmFactory* alarm_factory_;        // Not owned.
   PerPacketOptions* per_packet_options_;   // Not owned.
   QuicPacketWriter* writer_;  // Owned or not depending on |owns_writer_|.
   bool owns_writer_;
diff --git a/net/quic/quic_connection_logger_unittest.cc b/net/quic/quic_connection_logger_unittest.cc
index ebaa12d..268e7f7 100644
--- a/net/quic/quic_connection_logger_unittest.cc
+++ b/net/quic/quic_connection_logger_unittest.cc
@@ -32,7 +32,9 @@
 class QuicConnectionLoggerTest : public ::testing::Test {
  protected:
   QuicConnectionLoggerTest()
-      : session_(new MockConnection(&helper_, Perspective::IS_CLIENT)),
+      : session_(new MockConnection(&helper_,
+                                    &alarm_factory_,
+                                    Perspective::IS_CLIENT)),
         logger_(&session_,
                 "CONNECTION_UNKNOWN",
                 /*socket_performance_watcher=*/nullptr,
@@ -40,6 +42,7 @@
 
   BoundNetLog net_log_;
   MockConnectionHelper helper_;
+  MockAlarmFactory alarm_factory_;
   MockQuicSpdySession session_;
   QuicConnectionLogger logger_;
 };
diff --git a/net/quic/quic_connection_test.cc b/net/quic/quic_connection_test.cc
index cf652af1..54b6dd0 100644
--- a/net/quic/quic_connection_test.cc
+++ b/net/quic/quic_connection_test.cc
@@ -4,8 +4,10 @@
 
 #include "net/quic/quic_connection.h"
 
+#include <errno.h>
 #include <memory>
 #include <ostream>
+#include <utility>
 
 #include "base/bind.h"
 #include "base/macros.h"
@@ -204,16 +206,6 @@
 
 class TestConnectionHelper : public QuicConnectionHelperInterface {
  public:
-  class TestAlarm : public QuicAlarm {
-   public:
-    explicit TestAlarm(QuicArenaScopedPtr<QuicAlarm::Delegate> delegate)
-        : QuicAlarm(std::move(delegate)) {}
-
-    void SetImpl() override {}
-    void CancelImpl() override {}
-    using QuicAlarm::Fire;
-  };
-
   TestConnectionHelper(MockClock* clock, MockRandom* random_generator)
       : clock_(clock), random_generator_(random_generator) {
     clock_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
@@ -224,16 +216,6 @@
 
   QuicRandom* GetRandomGenerator() override { return random_generator_; }
 
-  QuicAlarm* CreateAlarm(QuicAlarm::Delegate* delegate) override {
-    return new TestAlarm(QuicArenaScopedPtr<QuicAlarm::Delegate>(delegate));
-  }
-
-  QuicArenaScopedPtr<QuicAlarm> CreateAlarm(
-      QuicArenaScopedPtr<QuicAlarm::Delegate> delegate,
-      QuicConnectionArena* arena) override {
-    return arena->New<TestAlarm>(std::move(delegate));
-  }
-
   QuicBufferAllocator* GetBufferAllocator() override {
     return &buffer_allocator_;
   }
@@ -246,6 +228,34 @@
   DISALLOW_COPY_AND_ASSIGN(TestConnectionHelper);
 };
 
+class TestAlarmFactory : public QuicAlarmFactory {
+ public:
+  class TestAlarm : public QuicAlarm {
+   public:
+    explicit TestAlarm(QuicArenaScopedPtr<QuicAlarm::Delegate> delegate)
+        : QuicAlarm(std::move(delegate)) {}
+
+    void SetImpl() override {}
+    void CancelImpl() override {}
+    using QuicAlarm::Fire;
+  };
+
+  TestAlarmFactory() {}
+
+  QuicAlarm* CreateAlarm(QuicAlarm::Delegate* delegate) override {
+    return new TestAlarm(QuicArenaScopedPtr<QuicAlarm::Delegate>(delegate));
+  }
+
+  QuicArenaScopedPtr<QuicAlarm> CreateAlarm(
+      QuicArenaScopedPtr<QuicAlarm::Delegate> delegate,
+      QuicConnectionArena* arena) override {
+    return arena->New<TestAlarm>(std::move(delegate));
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(TestAlarmFactory);
+};
+
 class TestPacketWriter : public QuicPacketWriter {
  public:
   TestPacketWriter(QuicVersion version, MockClock* clock)
@@ -425,12 +435,14 @@
   TestConnection(QuicConnectionId connection_id,
                  IPEndPoint address,
                  TestConnectionHelper* helper,
+                 TestAlarmFactory* alarm_factory,
                  TestPacketWriter* writer,
                  Perspective perspective,
                  QuicVersion version)
       : QuicConnection(connection_id,
                        address,
                        helper,
+                       alarm_factory,
                        writer,
                        /* owns_writer= */ false,
                        perspective,
@@ -542,38 +554,38 @@
         .WillRepeatedly(Return(QuicBandwidth::FromKBytesPerSecond(10000)));
   }
 
-  TestConnectionHelper::TestAlarm* GetAckAlarm() {
-    return reinterpret_cast<TestConnectionHelper::TestAlarm*>(
+  TestAlarmFactory::TestAlarm* GetAckAlarm() {
+    return reinterpret_cast<TestAlarmFactory::TestAlarm*>(
         QuicConnectionPeer::GetAckAlarm(this));
   }
 
-  TestConnectionHelper::TestAlarm* GetPingAlarm() {
-    return reinterpret_cast<TestConnectionHelper::TestAlarm*>(
+  TestAlarmFactory::TestAlarm* GetPingAlarm() {
+    return reinterpret_cast<TestAlarmFactory::TestAlarm*>(
         QuicConnectionPeer::GetPingAlarm(this));
   }
 
-  TestConnectionHelper::TestAlarm* GetResumeWritesAlarm() {
-    return reinterpret_cast<TestConnectionHelper::TestAlarm*>(
+  TestAlarmFactory::TestAlarm* GetResumeWritesAlarm() {
+    return reinterpret_cast<TestAlarmFactory::TestAlarm*>(
         QuicConnectionPeer::GetResumeWritesAlarm(this));
   }
 
-  TestConnectionHelper::TestAlarm* GetRetransmissionAlarm() {
-    return reinterpret_cast<TestConnectionHelper::TestAlarm*>(
+  TestAlarmFactory::TestAlarm* GetRetransmissionAlarm() {
+    return reinterpret_cast<TestAlarmFactory::TestAlarm*>(
         QuicConnectionPeer::GetRetransmissionAlarm(this));
   }
 
-  TestConnectionHelper::TestAlarm* GetSendAlarm() {
-    return reinterpret_cast<TestConnectionHelper::TestAlarm*>(
+  TestAlarmFactory::TestAlarm* GetSendAlarm() {
+    return reinterpret_cast<TestAlarmFactory::TestAlarm*>(
         QuicConnectionPeer::GetSendAlarm(this));
   }
 
-  TestConnectionHelper::TestAlarm* GetTimeoutAlarm() {
-    return reinterpret_cast<TestConnectionHelper::TestAlarm*>(
+  TestAlarmFactory::TestAlarm* GetTimeoutAlarm() {
+    return reinterpret_cast<TestAlarmFactory::TestAlarm*>(
         QuicConnectionPeer::GetTimeoutAlarm(this));
   }
 
-  TestConnectionHelper::TestAlarm* GetMtuDiscoveryAlarm() {
-    return reinterpret_cast<TestConnectionHelper::TestAlarm*>(
+  TestAlarmFactory::TestAlarm* GetMtuDiscoveryAlarm() {
+    return reinterpret_cast<TestAlarmFactory::TestAlarm*>(
         QuicConnectionPeer::GetMtuDiscoveryAlarm(this));
   }
 
@@ -635,6 +647,7 @@
         send_algorithm_(new StrictMock<MockSendAlgorithm>),
         loss_algorithm_(new MockLossAlgorithm()),
         helper_(new TestConnectionHelper(&clock_, &random_generator_)),
+        alarm_factory_(new TestAlarmFactory()),
         peer_creator_(connection_id_,
                       &framer_,
                       &random_generator_,
@@ -644,6 +657,7 @@
         connection_(connection_id_,
                     kPeerAddress,
                     helper_.get(),
+                    alarm_factory_.get(),
                     writer_.get(),
                     Perspective::IS_CLIENT,
                     version()),
@@ -995,6 +1009,7 @@
   MockRandom random_generator_;
   SimpleBufferAllocator buffer_allocator_;
   std::unique_ptr<TestConnectionHelper> helper_;
+  std::unique_ptr<TestAlarmFactory> alarm_factory_;
   QuicPacketCreator peer_creator_;
   std::unique_ptr<TestPacketWriter> writer_;
   TestConnection connection_;
@@ -1066,7 +1081,8 @@
 TEST_P(QuicConnectionTest, SmallerServerMaxPacketSize) {
   QuicConnectionId connection_id = 42;
   TestConnection connection(connection_id, kPeerAddress, helper_.get(),
-                            writer_.get(), Perspective::IS_SERVER, version());
+                            alarm_factory_.get(), writer_.get(),
+                            Perspective::IS_SERVER, version());
   EXPECT_EQ(Perspective::IS_SERVER, connection.perspective());
   EXPECT_EQ(1000u, connection.max_packet_length());
 }
@@ -1154,7 +1170,8 @@
   const QuicByteCount lower_max_packet_size = 1240;
   writer_->set_max_packet_size(lower_max_packet_size);
   TestConnection connection(connection_id, kPeerAddress, helper_.get(),
-                            writer_.get(), Perspective::IS_CLIENT, version());
+                            alarm_factory_.get(), writer_.get(),
+                            Perspective::IS_CLIENT, version());
   EXPECT_EQ(Perspective::IS_CLIENT, connection.perspective());
   EXPECT_EQ(lower_max_packet_size, connection.max_packet_length());
 }
@@ -4509,9 +4526,11 @@
 
 TEST_P(QuicConnectionTest, Pacing) {
   TestConnection server(connection_id_, kSelfAddress, helper_.get(),
-                        writer_.get(), Perspective::IS_SERVER, version());
+                        alarm_factory_.get(), writer_.get(),
+                        Perspective::IS_SERVER, version());
   TestConnection client(connection_id_, kPeerAddress, helper_.get(),
-                        writer_.get(), Perspective::IS_CLIENT, version());
+                        alarm_factory_.get(), writer_.get(),
+                        Perspective::IS_CLIENT, version());
   EXPECT_FALSE(client.sent_packet_manager().using_pacing());
   EXPECT_FALSE(server.sent_packet_manager().using_pacing());
 }
diff --git a/net/quic/quic_crypto_client_stream.cc b/net/quic/quic_crypto_client_stream.cc
index 55f29a0..4ce3d0f 100644
--- a/net/quic/quic_crypto_client_stream.cc
+++ b/net/quic/quic_crypto_client_stream.cc
@@ -4,6 +4,7 @@
 
 #include "net/quic/quic_crypto_client_stream.h"
 
+#include <memory>
 #include <vector>
 
 #include "base/metrics/histogram_macros.h"
diff --git a/net/quic/quic_crypto_client_stream.h b/net/quic/quic_crypto_client_stream.h
index f9eabbb..75913d1 100644
--- a/net/quic/quic_crypto_client_stream.h
+++ b/net/quic/quic_crypto_client_stream.h
@@ -5,8 +5,8 @@
 #ifndef NET_QUIC_QUIC_CRYPTO_CLIENT_STREAM_H_
 #define NET_QUIC_QUIC_CRYPTO_CLIENT_STREAM_H_
 
-#include <stdint.h>
-
+#include <cstdint>
+#include <memory>
 #include <string>
 
 #include "base/macros.h"
diff --git a/net/quic/quic_crypto_client_stream_test.cc b/net/quic/quic_crypto_client_stream_test.cc
index 54ecb914..a42585a 100644
--- a/net/quic/quic_crypto_client_stream_test.cc
+++ b/net/quic/quic_crypto_client_stream_test.cc
@@ -40,7 +40,8 @@
   }
 
   void CreateConnection() {
-    connection_ = new PacketSavingConnection(&helper_, Perspective::IS_CLIENT);
+    connection_ = new PacketSavingConnection(&helper_, &alarm_factory_,
+                                             Perspective::IS_CLIENT);
     // Advance the time, because timers do not like uninitialized times.
     connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
 
@@ -50,8 +51,8 @@
 
   void CompleteCryptoHandshake() {
     stream()->CryptoConnect();
-    CryptoTestUtils::HandshakeWithFakeServer(&helper_, connection_, stream(),
-                                             server_options_);
+    CryptoTestUtils::HandshakeWithFakeServer(
+        &helper_, &alarm_factory_, connection_, stream(), server_options_);
   }
 
   void ConstructHandshakeMessage() {
@@ -62,6 +63,7 @@
   QuicCryptoClientStream* stream() { return session_->GetCryptoStream(); }
 
   MockConnectionHelper helper_;
+  MockAlarmFactory alarm_factory_;
   PacketSavingConnection* connection_;
   std::unique_ptr<TestQuicSpdyClientSession> session_;
   QuicServerId server_id_;
@@ -267,11 +269,12 @@
             QuicCompressedCertsCache::kQuicCompressedCertsCacheSize),
         server_id_(kServerHostname, kServerPort, PRIVACY_MODE_DISABLED) {
     TestQuicSpdyClientSession* client_session = nullptr;
-    CreateClientSessionForTest(
-        server_id_,
-        /* supports_stateless_rejects= */ true,
-        QuicTime::Delta::FromSeconds(100000), QuicSupportedVersions(), &helper_,
-        &client_crypto_config_, &client_connection_, &client_session);
+    CreateClientSessionForTest(server_id_,
+                               /* supports_stateless_rejects= */ true,
+                               QuicTime::Delta::FromSeconds(100000),
+                               QuicSupportedVersions(), &helper_,
+                               &alarm_factory_, &client_crypto_config_,
+                               &client_connection_, &client_session);
     CHECK(client_session);
     client_session_.reset(client_session);
   }
@@ -290,10 +293,11 @@
   // Initializes the server_stream_ for stateless rejects.
   void InitializeFakeStatelessRejectServer() {
     TestQuicSpdyServerSession* server_session = nullptr;
-    CreateServerSessionForTest(
-        server_id_, QuicTime::Delta::FromSeconds(100000),
-        QuicSupportedVersions(), &helper_, &server_crypto_config_,
-        &server_compressed_certs_cache_, &server_connection_, &server_session);
+    CreateServerSessionForTest(server_id_, QuicTime::Delta::FromSeconds(100000),
+                               QuicSupportedVersions(), &helper_,
+                               &alarm_factory_, &server_crypto_config_,
+                               &server_compressed_certs_cache_,
+                               &server_connection_, &server_session);
     CHECK(server_session);
     server_session_.reset(server_session);
     CryptoTestUtils::FakeServerOptions options;
@@ -304,6 +308,7 @@
   }
 
   MockConnectionHelper helper_;
+  MockAlarmFactory alarm_factory_;
 
   // Client crypto stream state
   PacketSavingConnection* client_connection_;
diff --git a/net/quic/quic_crypto_server_stream.cc b/net/quic/quic_crypto_server_stream.cc
index cee73caa..967ada03 100644
--- a/net/quic/quic_crypto_server_stream.cc
+++ b/net/quic/quic_crypto_server_stream.cc
@@ -4,6 +4,8 @@
 
 #include "net/quic/quic_crypto_server_stream.h"
 
+#include <memory>
+
 #include "base/base64.h"
 #include "crypto/secure_hash.h"
 #include "net/quic/crypto/crypto_protocol.h"
@@ -16,6 +18,7 @@
 #include "net/quic/quic_protocol.h"
 #include "net/quic/quic_session.h"
 
+using base::StringPiece;
 using std::string;
 
 namespace net {
@@ -236,7 +239,7 @@
   DVLOG(1) << "Server: Sending server config update: "
            << server_config_update_message.DebugString();
   const QuicData& data = server_config_update_message.GetSerialized();
-  WriteOrBufferData(string(data.data(), data.length()), false, nullptr);
+  WriteOrBufferData(StringPiece(data.data(), data.length()), false, nullptr);
 
   ++num_server_config_update_messages_sent_;
 }
diff --git a/net/quic/quic_crypto_server_stream.h b/net/quic/quic_crypto_server_stream.h
index 65e8f04c3..f85a9f4 100644
--- a/net/quic/quic_crypto_server_stream.h
+++ b/net/quic/quic_crypto_server_stream.h
@@ -5,8 +5,8 @@
 #ifndef NET_QUIC_QUIC_CRYPTO_SERVER_STREAM_H_
 #define NET_QUIC_QUIC_CRYPTO_SERVER_STREAM_H_
 
-#include <stdint.h>
-
+#include <cstdint>
+#include <memory>
 #include <string>
 
 #include "base/macros.h"
diff --git a/net/quic/quic_crypto_server_stream_test.cc b/net/quic/quic_crypto_server_stream_test.cc
index b82e0c1..e5cdfe1 100644
--- a/net/quic/quic_crypto_server_stream_test.cc
+++ b/net/quic/quic_crypto_server_stream_test.cc
@@ -102,6 +102,7 @@
     server_session_.reset();
     client_session_.reset();
     STLDeleteElements(&helpers_);
+    STLDeleteElements(&alarm_factories_);
   }
 
   // Initializes the crypto server stream state for testing.  May be
@@ -109,9 +110,10 @@
   void InitializeServer() {
     TestQuicSpdyServerSession* server_session = nullptr;
     helpers_.push_back(new MockConnectionHelper);
+    alarm_factories_.push_back(new MockAlarmFactory);
     CreateServerSessionForTest(
         server_id_, QuicTime::Delta::FromSeconds(100000), supported_versions_,
-        helpers_.back(), &server_crypto_config_,
+        helpers_.back(), alarm_factories_.back(), &server_crypto_config_,
         &server_compressed_certs_cache_, &server_connection_, &server_session);
     CHECK(server_session);
     server_session_.reset(server_session);
@@ -135,12 +137,13 @@
   void InitializeFakeClient(bool supports_stateless_rejects) {
     TestQuicSpdyClientSession* client_session = nullptr;
     helpers_.push_back(new MockConnectionHelper);
-    CreateClientSessionForTest(server_id_, supports_stateless_rejects,
-                               QuicTime::Delta::FromSeconds(100000),
-                               supported_versions_,
+    alarm_factories_.push_back(new MockAlarmFactory);
+    CreateClientSessionForTest(
+        server_id_, supports_stateless_rejects,
+        QuicTime::Delta::FromSeconds(100000), supported_versions_,
 
-                               helpers_.back(), &client_crypto_config_,
-                               &client_connection_, &client_session);
+        helpers_.back(), alarm_factories_.back(), &client_crypto_config_,
+        &client_connection_, &client_session);
     CHECK(client_session);
     client_session_.reset(client_session);
   }
@@ -161,8 +164,8 @@
     CHECK(server_connection_);
     CHECK(server_session_ != nullptr);
     return CryptoTestUtils::HandshakeWithFakeClient(
-        helpers_.back(), server_connection_, server_stream(), server_id_,
-        client_options_);
+        helpers_.back(), alarm_factories_.back(), server_connection_,
+        server_stream(), server_id_, client_options_);
   }
 
   // Performs a single round of handshake message-exchange between the
@@ -178,10 +181,12 @@
   }
 
  protected:
-  // Every connection gets its own MockConnectionHelper, tracked separately
-  // from the server and client state so their lifetimes persist through the
-  // whole test.
+  // Every connection gets its own MockConnectionHelper and MockAlarmFactory,
+  // tracked separately from
+  // the server and client state so their lifetimes persist through the whole
+  // test.
   std::vector<MockConnectionHelper*> helpers_;
+  std::vector<MockAlarmFactory*> alarm_factories_;
 
   // Server state
   PacketSavingConnection* server_connection_;
diff --git a/net/quic/quic_crypto_stream.cc b/net/quic/quic_crypto_stream.cc
index ee44b6c..f904871 100644
--- a/net/quic/quic_crypto_stream.cc
+++ b/net/quic/quic_crypto_stream.cc
@@ -72,7 +72,7 @@
   session()->OnCryptoHandshakeMessageSent(message);
   const QuicData& data = message.GetSerialized();
   // TODO(wtc): check the return value.
-  WriteOrBufferData(string(data.data(), data.length()), false, listener);
+  WriteOrBufferData(StringPiece(data.data(), data.length()), false, listener);
 }
 
 bool QuicCryptoStream::ExportKeyingMaterial(StringPiece label,
diff --git a/net/quic/quic_crypto_stream_test.cc b/net/quic/quic_crypto_stream_test.cc
index e7cc92a..326ece8c 100644
--- a/net/quic/quic_crypto_stream_test.cc
+++ b/net/quic/quic_crypto_stream_test.cc
@@ -4,6 +4,7 @@
 
 #include "net/quic/quic_crypto_stream.h"
 
+#include <cstdint>
 #include <memory>
 #include <string>
 #include <vector>
@@ -44,7 +45,9 @@
 class QuicCryptoStreamTest : public ::testing::Test {
  public:
   QuicCryptoStreamTest()
-      : connection_(new MockConnection(&helper_, Perspective::IS_CLIENT)),
+      : connection_(new MockConnection(&helper_,
+                                       &alarm_factory_,
+                                       Perspective::IS_CLIENT)),
         session_(connection_),
         stream_(&session_) {
     message_.set_tag(kSHLO);
@@ -60,6 +63,7 @@
 
  protected:
   MockConnectionHelper helper_;
+  MockAlarmFactory alarm_factory_;
   MockConnection* connection_;
   MockQuicSpdySession session_;
   MockQuicCryptoStream stream_;
diff --git a/net/quic/quic_flags.cc b/net/quic/quic_flags.cc
index 8778704..a4a39dcf 100644
--- a/net/quic/quic_flags.cc
+++ b/net/quic/quic_flags.cc
@@ -107,17 +107,13 @@
 // consecutive RTOs are sent.
 bool FLAGS_quic_enable_rto_timeout = true;
 
-// Use a byte conservation approach instead of packet conservation in the
-// Slow Start Large Reduction experiment.
-bool FLAGS_quic_sslr_byte_conservation = true;
-
 // Try to use the socket timestamp to determine the time a packet was
 // received instead of Now().
 bool FLAGS_quic_use_socket_timestamp = true;
 
-// If true, handling of errors from invalid stream frames is done in
-// one place in QuicStreamSequencer::OnStreamFrame.
-bool FLAGS_quic_consolidate_onstreamframe_errors = true;
-
 // Resend 0RTT requests in response to an REJ that re-establishes encryption.
 bool FLAGS_quic_reply_to_rej = true;
+
+// If true, QuicFramer will ignore invalid error codes when processing GoAway,
+// ConnectionClose, and RstStream frames.
+bool FLAGS_quic_ignore_invalid_error_code = true;
diff --git a/net/quic/quic_flags.h b/net/quic/quic_flags.h
index bfc4c18..8af48b7 100644
--- a/net/quic/quic_flags.h
+++ b/net/quic/quic_flags.h
@@ -37,9 +37,8 @@
 NET_EXPORT_PRIVATE extern bool FLAGS_spdy_on_stream_end;
 NET_EXPORT_PRIVATE extern bool FLAGS_quic_use_cached_compressed_certs;
 NET_EXPORT_PRIVATE extern bool FLAGS_quic_enable_rto_timeout;
-NET_EXPORT_PRIVATE extern bool FLAGS_quic_sslr_byte_conservation;
 NET_EXPORT_PRIVATE extern bool FLAGS_quic_use_socket_timestamp;
-NET_EXPORT_PRIVATE extern bool FLAGS_quic_consolidate_onstreamframe_errors;
 NET_EXPORT_PRIVATE extern bool FLAGS_quic_reply_to_rej;
+NET_EXPORT_PRIVATE extern bool FLAGS_quic_ignore_invalid_error_code;
 
 #endif  // NET_QUIC_QUIC_FLAGS_H_
diff --git a/net/quic/quic_flow_controller_test.cc b/net/quic/quic_flow_controller_test.cc
index b189a408..e4a53e6 100644
--- a/net/quic/quic_flow_controller_test.cc
+++ b/net/quic/quic_flow_controller_test.cc
@@ -4,6 +4,8 @@
 
 #include "net/quic/quic_flow_controller.h"
 
+#include <memory>
+
 #include "base/format_macros.h"
 #include "base/strings/stringprintf.h"
 #include "net/quic/quic_flags.h"
@@ -29,7 +31,7 @@
       : stream_id_(1234),
         send_window_(kInitialSessionFlowControlWindowForTest),
         receive_window_(kInitialSessionFlowControlWindowForTest),
-        connection_(&helper_, Perspective::IS_CLIENT) {}
+        connection_(&helper_, &alarm_factory_, Perspective::IS_CLIENT) {}
 
   void Initialize() {
     flow_controller_.reset(
@@ -43,6 +45,7 @@
   QuicByteCount receive_window_;
   std::unique_ptr<QuicFlowController> flow_controller_;
   MockConnectionHelper helper_;
+  MockAlarmFactory alarm_factory_;
   MockConnection connection_;
 };
 
diff --git a/net/quic/quic_framer.cc b/net/quic/quic_framer.cc
index da91cfc..1dd00645 100644
--- a/net/quic/quic_framer.cc
+++ b/net/quic/quic_framer.cc
@@ -4,7 +4,8 @@
 
 #include "net/quic/quic_framer.h"
 
-#include <stdint.h>
+#include <cstdint>
+#include <memory>
 
 #include "base/compiler_specific.h"
 #include "base/logging.h"
@@ -1494,8 +1495,13 @@
   }
 
   if (error_code >= QUIC_STREAM_LAST_ERROR) {
-    set_detailed_error("Invalid rst stream error code.");
-    return false;
+    if (FLAGS_quic_ignore_invalid_error_code) {
+      // Ignore invalid stream error code if any.
+      error_code = QUIC_STREAM_LAST_ERROR;
+    } else {
+      set_detailed_error("Invalid rst stream error code.");
+      return false;
+    }
   }
 
   frame->error_code = static_cast<QuicRstStreamErrorCode>(error_code);
@@ -1511,8 +1517,13 @@
   }
 
   if (error_code >= QUIC_LAST_ERROR) {
-    set_detailed_error("Invalid error code.");
-    return false;
+    if (FLAGS_quic_ignore_invalid_error_code) {
+      // Ignore invalid QUIC error code if any.
+      error_code = QUIC_LAST_ERROR;
+    } else {
+      set_detailed_error("Invalid error code.");
+      return false;
+    }
   }
 
   frame->error_code = static_cast<QuicErrorCode>(error_code);
@@ -1534,12 +1545,17 @@
     set_detailed_error("Unable to read go away error code.");
     return false;
   }
-  frame->error_code = static_cast<QuicErrorCode>(error_code);
 
   if (error_code >= QUIC_LAST_ERROR) {
-    set_detailed_error("Invalid error code.");
-    return false;
+    if (FLAGS_quic_ignore_invalid_error_code) {
+      // Ignore invalid QUIC error code if any.
+      error_code = QUIC_LAST_ERROR;
+    } else {
+      set_detailed_error("Invalid error code.");
+      return false;
+    }
   }
+  frame->error_code = static_cast<QuicErrorCode>(error_code);
 
   uint32_t stream_id;
   if (!reader->ReadUInt32(&stream_id)) {
diff --git a/net/quic/quic_header_list.cc b/net/quic/quic_header_list.cc
index 2edb343..4d2f3f6 100644
--- a/net/quic/quic_header_list.cc
+++ b/net/quic/quic_header_list.cc
@@ -4,6 +4,8 @@
 
 #include "net/quic/quic_header_list.h"
 
+using std::string;
+
 namespace net {
 
 QuicHeaderList::QuicHeaderList() : uncompressed_header_bytes_(0) {}
@@ -37,4 +39,13 @@
   uncompressed_header_bytes_ = 0;
 }
 
+string QuicHeaderList::DebugString() const {
+  string s = "{ ";
+  for (const auto& p : *this) {
+    s.append(p.first + "=" + p.second + ", ");
+  }
+  s.append("}");
+  return s;
+}
+
 }  // namespace net
diff --git a/net/quic/quic_header_list.h b/net/quic/quic_header_list.h
index 3d07061..b218f35 100644
--- a/net/quic/quic_header_list.h
+++ b/net/quic/quic_header_list.h
@@ -20,6 +20,7 @@
 class NET_EXPORT_PRIVATE QuicHeaderList : public SpdyHeadersHandlerInterface {
  public:
   typedef std::deque<std::pair<std::string, std::string>> ListType;
+  typedef ListType::const_iterator const_iterator;
 
   QuicHeaderList();
   QuicHeaderList(QuicHeaderList&& other);
@@ -35,14 +36,16 @@
 
   void Clear();
 
-  ListType::const_iterator begin() const { return header_list_.begin(); }
-  ListType::const_iterator end() const { return header_list_.end(); }
+  const_iterator begin() const { return header_list_.begin(); }
+  const_iterator end() const { return header_list_.end(); }
 
   bool empty() const { return header_list_.empty(); }
   size_t uncompressed_header_bytes() const {
     return uncompressed_header_bytes_;
   }
 
+  std::string DebugString() const;
+
  private:
   std::deque<std::pair<std::string, std::string>> header_list_;
   size_t uncompressed_header_bytes_;
diff --git a/net/quic/quic_header_list_test.cc b/net/quic/quic_header_list_test.cc
index bd4e560..94f82497 100644
--- a/net/quic/quic_header_list_test.cc
+++ b/net/quic/quic_header_list_test.cc
@@ -16,11 +16,7 @@
   headers.OnHeader("april", "fools");
   headers.OnHeader("beep", "");
 
-  std::string accumulator;
-  for (const auto& p : headers) {
-    accumulator.append("(" + p.first + ", " + p.second + ") ");
-  }
-  EXPECT_EQ("(foo, bar) (april, fools) (beep, ) ", accumulator);
+  EXPECT_EQ("{ foo=bar, april=fools, beep=, }", headers.DebugString());
 }
 
 // This test verifies that QuicHeaderList is copyable and assignable.
@@ -33,17 +29,8 @@
   QuicHeaderList headers2(headers);
   QuicHeaderList headers3 = headers;
 
-  std::string accumulator;
-  for (const auto& p : headers2) {
-    accumulator.append("(" + p.first + ", " + p.second + ") ");
-  }
-  EXPECT_EQ("(foo, bar) (april, fools) (beep, ) ", accumulator);
-
-  accumulator.clear();
-  for (const auto& p : headers3) {
-    accumulator.append("(" + p.first + ", " + p.second + ") ");
-  }
-  EXPECT_EQ("(foo, bar) (april, fools) (beep, ) ", accumulator);
+  EXPECT_EQ("{ foo=bar, april=fools, beep=, }", headers2.DebugString());
+  EXPECT_EQ("{ foo=bar, april=fools, beep=, }", headers3.DebugString());
 }
 
 }  // namespace net
diff --git a/net/quic/quic_headers_stream_test.cc b/net/quic/quic_headers_stream_test.cc
index e02f530..1954d91 100644
--- a/net/quic/quic_headers_stream_test.cc
+++ b/net/quic/quic_headers_stream_test.cc
@@ -133,6 +133,7 @@
  public:
   QuicHeadersStreamTest()
       : connection_(new StrictMock<MockConnection>(&helper_,
+                                                   &alarm_factory_,
                                                    perspective(),
                                                    GetVersion())),
         session_(connection_),
@@ -249,6 +250,7 @@
   static const bool kHasPriority = true;
 
   MockConnectionHelper helper_;
+  MockAlarmFactory alarm_factory_;
   StrictMock<MockConnection>* connection_;
   StrictMock<MockQuicSpdySession> session_;
   QuicHeadersStream* headers_stream_;
diff --git a/net/quic/quic_http_stream_test.cc b/net/quic/quic_http_stream_test.cc
index 4774365..395f8cc 100644
--- a/net/quic/quic_http_stream_test.cc
+++ b/net/quic/quic_http_stream_test.cc
@@ -29,6 +29,7 @@
 #include "net/quic/crypto/quic_decrypter.h"
 #include "net/quic/crypto/quic_encrypter.h"
 #include "net/quic/crypto/quic_server_info.h"
+#include "net/quic/quic_chromium_alarm_factory.h"
 #include "net/quic/quic_chromium_client_session.h"
 #include "net/quic/quic_chromium_client_stream.h"
 #include "net/quic/quic_chromium_connection_helper.h"
@@ -74,10 +75,12 @@
                      QuicConnectionId connection_id,
                      IPEndPoint address,
                      QuicChromiumConnectionHelper* helper,
+                     QuicChromiumAlarmFactory* alarm_factory,
                      QuicPacketWriter* writer)
       : QuicConnection(connection_id,
                        address,
                        helper,
+                       alarm_factory,
                        writer,
                        true /* owns_writer */,
                        Perspective::IS_CLIENT,
@@ -218,11 +221,14 @@
     EXPECT_CALL(*send_algorithm_, BandwidthEstimate())
         .WillRepeatedly(Return(QuicBandwidth::Zero()));
     EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)).Times(AnyNumber());
-    helper_.reset(new QuicChromiumConnectionHelper(runner_.get(), &clock_,
-                                                   &random_generator_));
-    connection_ = new TestQuicConnection(
-        SupportedVersions(GetParam()), connection_id_, peer_addr_,
-        helper_.get(), new QuicChromiumPacketWriter(socket.get()));
+    helper_.reset(
+        new QuicChromiumConnectionHelper(&clock_, &random_generator_));
+    alarm_factory_.reset(new QuicChromiumAlarmFactory(runner_.get(), &clock_));
+
+    connection_ =
+        new TestQuicConnection(SupportedVersions(GetParam()), connection_id_,
+                               peer_addr_, helper_.get(), alarm_factory_.get(),
+                               new QuicChromiumPacketWriter(socket.get()));
     connection_->set_visitor(&visitor_);
     connection_->SetSendAlgorithm(send_algorithm_);
 
@@ -429,6 +435,7 @@
   MockClock clock_;
   TestQuicConnection* connection_;
   std::unique_ptr<QuicChromiumConnectionHelper> helper_;
+  std::unique_ptr<QuicChromiumAlarmFactory> alarm_factory_;
   testing::StrictMock<MockConnectionVisitor> visitor_;
   std::unique_ptr<QuicHttpStream> stream_;
   TransportSecurityState transport_security_state_;
diff --git a/net/quic/quic_network_transaction_unittest.cc b/net/quic/quic_network_transaction_unittest.cc
index effc787..6cd0628 100644
--- a/net/quic/quic_network_transaction_unittest.cc
+++ b/net/quic/quic_network_transaction_unittest.cc
@@ -2030,6 +2030,7 @@
 
 TEST_P(QuicNetworkTransactionTest,
        LogGranularQuicErrorCodeOnQuicProtocolErrorRemote) {
+  ValueRestore<bool> old_flag(&FLAGS_quic_ignore_invalid_error_code, false);
   MockQuicData mock_quic_data;
   mock_quic_data.AddWrite(
       ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true,
diff --git a/net/quic/quic_packet_creator.cc b/net/quic/quic_packet_creator.cc
index 5147b09..bb4d8e5 100644
--- a/net/quic/quic_packet_creator.cc
+++ b/net/quic/quic_packet_creator.cc
@@ -186,12 +186,12 @@
          QuicFramer::GetMinStreamFrameSize(1u, offset, true);
 }
 
-size_t QuicPacketCreator::CreateStreamFrame(QuicStreamId id,
-                                            QuicIOVector iov,
-                                            size_t iov_offset,
-                                            QuicStreamOffset offset,
-                                            bool fin,
-                                            QuicFrame* frame) {
+void QuicPacketCreator::CreateStreamFrame(QuicStreamId id,
+                                          QuicIOVector iov,
+                                          size_t iov_offset,
+                                          QuicStreamOffset offset,
+                                          bool fin,
+                                          QuicFrame* frame) {
   DCHECK_GT(max_packet_length_,
             StreamFramePacketOverhead(connection_id_length_, kIncludeVersion,
                                       kIncludePathId,
@@ -208,7 +208,7 @@
     QUIC_BUG_IF(!fin) << "Creating a stream frame with no data or fin.";
     // Create a new packet for the fin, if necessary.
     *frame = QuicFrame(new QuicStreamFrame(id, true, offset, StringPiece()));
-    return 0;
+    return;
   }
 
   const size_t data_size = iov.total_length - iov_offset;
@@ -222,7 +222,6 @@
   CopyToBuffer(iov, iov_offset, bytes_consumed, buffer.get());
   *frame = QuicFrame(new QuicStreamFrame(id, set_fin, offset, bytes_consumed,
                                          std::move(buffer)));
-  return bytes_consumed;
 }
 
 // static
diff --git a/net/quic/quic_packet_creator.h b/net/quic/quic_packet_creator.h
index b279d51..bf9035b5 100644
--- a/net/quic/quic_packet_creator.h
+++ b/net/quic/quic_packet_creator.h
@@ -214,16 +214,15 @@
 
   // Converts a raw payload to a frame which fits into the current open
   // packet.  The payload begins at |iov_offset| into the |iov|.
-  // Returns the number of bytes consumed from data.
   // If data is empty and fin is true, the expected behavior is to consume the
   // fin but return 0.  If any data is consumed, it will be copied into a
   // new buffer that |frame| will point to and own.
-  size_t CreateStreamFrame(QuicStreamId id,
-                           QuicIOVector iov,
-                           size_t iov_offset,
-                           QuicStreamOffset offset,
-                           bool fin,
-                           QuicFrame* frame);
+  void CreateStreamFrame(QuicStreamId id,
+                         QuicIOVector iov,
+                         size_t iov_offset,
+                         QuicStreamOffset offset,
+                         bool fin,
+                         QuicFrame* frame);
 
   // Copies |length| bytes from iov starting at offset |iov_offset| into buffer.
   // |iov| must be at least iov_offset+length total length and buffer must be
diff --git a/net/quic/quic_packet_creator_test.cc b/net/quic/quic_packet_creator_test.cc
index a3e3c2a1..9731eba 100644
--- a/net/quic/quic_packet_creator_test.cc
+++ b/net/quic/quic_packet_creator_test.cc
@@ -4,7 +4,9 @@
 
 #include "net/quic/quic_packet_creator.h"
 
-#include <stdint.h>
+#include <cstdint>
+#include <memory>
+#include <string>
 
 #include "base/macros.h"
 #include "base/stl_util.h"
diff --git a/net/quic/quic_packet_generator_test.cc b/net/quic/quic_packet_generator_test.cc
index d913672..e1d7b1e 100644
--- a/net/quic/quic_packet_generator_test.cc
+++ b/net/quic/quic_packet_generator_test.cc
@@ -4,6 +4,8 @@
 
 #include "net/quic/quic_packet_generator.h"
 
+#include <cstdint>
+#include <memory>
 #include <string>
 
 #include "base/macros.h"
diff --git a/net/quic/quic_sent_packet_manager_test.cc b/net/quic/quic_sent_packet_manager_test.cc
index 7465e56..c36bab5b4 100644
--- a/net/quic/quic_sent_packet_manager_test.cc
+++ b/net/quic/quic_sent_packet_manager_test.cc
@@ -4,6 +4,8 @@
 
 #include "net/quic/quic_sent_packet_manager.h"
 
+#include <memory>
+
 #include "base/stl_util.h"
 #include "net/quic/quic_flags.h"
 #include "net/quic/test_tools/quic_config_peer.h"
diff --git a/net/quic/quic_session_test.cc b/net/quic/quic_session_test.cc
index 2c18073..770b15dc 100644
--- a/net/quic/quic_session_test.cc
+++ b/net/quic/quic_session_test.cc
@@ -197,6 +197,7 @@
   explicit QuicSessionTestBase(Perspective perspective)
       : connection_(
             new StrictMock<MockConnection>(&helper_,
+                                           &alarm_factory_,
                                            perspective,
                                            SupportedVersions(GetParam()))),
         session_(connection_) {
@@ -257,6 +258,7 @@
   QuicVersion version() const { return connection_->version(); }
 
   MockConnectionHelper helper_;
+  MockAlarmFactory alarm_factory_;
   StrictMock<MockConnection>* connection_;
   TestSession session_;
   set<QuicStreamId> closed_streams_;
diff --git a/net/quic/quic_spdy_session.h b/net/quic/quic_spdy_session.h
index 2780d80b..6b671f7 100644
--- a/net/quic/quic_spdy_session.h
+++ b/net/quic/quic_spdy_session.h
@@ -7,6 +7,8 @@
 
 #include <stddef.h>
 
+#include <memory>
+
 #include "base/macros.h"
 #include "net/quic/quic_header_list.h"
 #include "net/quic/quic_headers_stream.h"
diff --git a/net/quic/quic_spdy_stream.cc b/net/quic/quic_spdy_stream.cc
index c946e0c..bf5b734 100644
--- a/net/quic/quic_spdy_stream.cc
+++ b/net/quic/quic_spdy_stream.cc
@@ -95,6 +95,8 @@
 
   // The header block must contain the final offset for this stream, as the
   // trailers may be processed out of order at the peer.
+  DVLOG(1) << "Inserting trailer: (" << kFinalOffsetHeaderKey << ", "
+           << stream_bytes_written() + queued_data_bytes() << ")";
   trailer_block.insert(std::make_pair(
       kFinalOffsetHeaderKey,
       base::IntToString(stream_bytes_written() + queued_data_bytes())));
@@ -155,6 +157,13 @@
   decompressed_trailers_.erase(0, bytes_consumed);
 }
 
+void QuicSpdyStream::ConsumeHeaderList() {
+  header_list_.Clear();
+  if (FinishedReadingHeaders()) {
+    sequencer()->SetUnblocked();
+  }
+}
+
 void QuicSpdyStream::SetPriority(SpdyPriority priority) {
   DCHECK_EQ(0u, stream_bytes_written());
   spdy_session_->UpdateStreamPriority(id(), priority);
diff --git a/net/quic/quic_spdy_stream.h b/net/quic/quic_spdy_stream.h
index cedc25d2..ca52cd3 100644
--- a/net/quic/quic_spdy_stream.h
+++ b/net/quic/quic_spdy_stream.h
@@ -52,6 +52,10 @@
     // Called when the stream is closed.
     virtual void OnClose(QuicSpdyStream* stream) = 0;
 
+    // Allows subclasses to override and do work.
+    virtual void OnPromiseHeadersComplete(QuicStreamId promised_id,
+                                          size_t frame_len) {}
+
    protected:
     virtual ~Visitor() {}
 
@@ -136,7 +140,7 @@
   void MarkTrailersConsumed(size_t bytes_consumed);
 
   // Clears |header_list_|.
-  void ConsumeHeaderList() { header_list_.Clear(); }
+  void ConsumeHeaderList();
 
   // This block of functions wraps the sequencer's functions of the same
   // name.  These methods return uncompressed data until that has
diff --git a/net/quic/quic_spdy_stream_test.cc b/net/quic/quic_spdy_stream_test.cc
index d01a2cd2..8edf223 100644
--- a/net/quic/quic_spdy_stream_test.cc
+++ b/net/quic/quic_spdy_stream_test.cc
@@ -4,8 +4,9 @@
 
 #include "net/quic/quic_spdy_stream.h"
 
-#include "base/strings/string_number_conversions.h"
+#include <memory>
 
+#include "base/strings/string_number_conversions.h"
 #include "net/quic/quic_connection.h"
 #include "net/quic/quic_utils.h"
 #include "net/quic/quic_write_blocked_list.h"
@@ -97,7 +98,8 @@
 
   void Initialize(bool stream_should_process_data) {
     connection_ = new testing::StrictMock<MockConnection>(
-        &helper_, Perspective::IS_SERVER, SupportedVersions(GetParam()));
+        &helper_, &alarm_factory_, Perspective::IS_SERVER,
+        SupportedVersions(GetParam()));
     session_.reset(new testing::StrictMock<MockQuicSpdySession>(connection_));
     stream_ = new TestStream(kClientDataStreamId1, session_.get(),
                              stream_should_process_data);
@@ -109,6 +111,7 @@
 
  protected:
   MockConnectionHelper helper_;
+  MockAlarmFactory alarm_factory_;
   MockConnection* connection_;
   std::unique_ptr<MockQuicSpdySession> session_;
 
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc
index 46ec8f8..f572a728 100644
--- a/net/quic/quic_stream_factory.cc
+++ b/net/quic/quic_stream_factory.cc
@@ -40,6 +40,7 @@
 #include "net/quic/crypto/quic_random.h"
 #include "net/quic/crypto/quic_server_info.h"
 #include "net/quic/port_suggester.h"
+#include "net/quic/quic_chromium_alarm_factory.h"
 #include "net/quic/quic_chromium_client_session.h"
 #include "net/quic/quic_chromium_connection_helper.h"
 #include "net/quic/quic_chromium_packet_reader.h"
@@ -1546,17 +1547,21 @@
   }
 
   if (!helper_.get()) {
-    helper_.reset(new QuicChromiumConnectionHelper(
-        base::ThreadTaskRunnerHandle::Get().get(), clock_.get(),
-        random_generator_));
+    helper_.reset(
+        new QuicChromiumConnectionHelper(clock_.get(), random_generator_));
+  }
+
+  if (!alarm_factory_.get()) {
+    alarm_factory_.reset(new QuicChromiumAlarmFactory(
+        base::ThreadTaskRunnerHandle::Get().get(), clock_.get()));
   }
   QuicConnectionId connection_id = random_generator_->RandUint64();
   InitializeCachedStateInCryptoConfig(server_id, server_info, &connection_id);
 
   QuicChromiumPacketWriter* writer = new QuicChromiumPacketWriter(socket.get());
   QuicConnection* connection = new QuicConnection(
-      connection_id, addr, helper_.get(), writer, true /* owns_writer */,
-      Perspective::IS_CLIENT, supported_versions_);
+      connection_id, addr, helper_.get(), alarm_factory_.get(), writer,
+      true /* owns_writer */, Perspective::IS_CLIENT, supported_versions_);
   writer->SetConnection(connection);
   connection->SetMaxPacketLength(max_packet_length_);
 
diff --git a/net/quic/quic_stream_factory.h b/net/quic/quic_stream_factory.h
index 75a5583..a03edf3 100644
--- a/net/quic/quic_stream_factory.h
+++ b/net/quic/quic_stream_factory.h
@@ -49,6 +49,7 @@
 class HostResolver;
 class HttpServerProperties;
 class QuicClock;
+class QuicChromiumAlarmFactory;
 class QuicChromiumClientSession;
 class QuicChromiumConnectionHelper;
 class QuicCryptoClientStreamFactory;
@@ -303,6 +304,8 @@
 
   QuicChromiumConnectionHelper* helper() { return helper_.get(); }
 
+  QuicChromiumAlarmFactory* alarm_factory() { return alarm_factory_.get(); }
+
   bool enable_port_selection() const { return enable_port_selection_; }
 
   bool has_quic_server_info_factory() {
@@ -428,6 +431,9 @@
   // The helper used for all connections.
   std::unique_ptr<QuicChromiumConnectionHelper> helper_;
 
+  // The alarm factory used for all connections.
+  std::unique_ptr<QuicChromiumAlarmFactory> alarm_factory_;
+
   // Contains owning pointers to all sessions that currently exist.
   SessionIdMap all_sessions_;
   // Contains non-owning pointers to currently active session
diff --git a/net/quic/quic_stream_sequencer.cc b/net/quic/quic_stream_sequencer.cc
index b30264fa..991083b 100644
--- a/net/quic/quic_stream_sequencer.cc
+++ b/net/quic/quic_stream_sequencer.cc
@@ -43,15 +43,6 @@
   ++num_frames_received_;
   const QuicStreamOffset byte_offset = frame.offset;
   const size_t data_len = frame.frame_length;
-  bool consolidate_errors = FLAGS_quic_consolidate_onstreamframe_errors;
-  if (!consolidate_errors && data_len == 0 && !frame.fin) {
-    // Stream frames must have data or a fin flag.
-    LOG(WARNING) << "QUIC_INVALID_STREAM_FRAM: Empty stream frame "
-                    "without FIN set.";
-    stream_->CloseConnectionWithDetails(QUIC_EMPTY_STREAM_FRAME_NO_FIN,
-                                        "Empty stream frame without FIN set.");
-    return;
-  }
 
   if (frame.fin) {
     CloseStreamAtOffset(frame.offset + data_len);
@@ -64,24 +55,14 @@
   QuicErrorCode result = buffered_frames_.OnStreamData(
       byte_offset, StringPiece(frame.frame_buffer, frame.frame_length),
       clock_->ApproximateNow(), &bytes_written, &error_details);
-  if (!consolidate_errors) {
-    if (result == QUIC_OVERLAPPING_STREAM_DATA) {
-      LOG(WARNING) << "QUIC_INVALID_STREAM_FRAME: Stream frame "
-                      "overlaps with buffered data.";
-      stream_->CloseConnectionWithDetails(
-          QUIC_EMPTY_STREAM_FRAME_NO_FIN,
-          "Stream frame overlaps with buffered data.");
-      return;
-    }
-  } else {
-    if (result != QUIC_NO_ERROR) {
-      LOG(WARNING) << QuicUtils::ErrorToString(result) << ": " << error_details;
-      stream_->CloseConnectionWithDetails(result, error_details);
-      return;
-    }
+  if (result != QUIC_NO_ERROR) {
+    DLOG(WARNING) << QuicUtils::ErrorToString(result);
+    DLOG(WARNING) << error_details;
+    stream_->CloseConnectionWithDetails(result, error_details);
+    return;
   }
 
-  if ((consolidate_errors || result == QUIC_NO_ERROR) && bytes_written == 0) {
+  if (bytes_written == 0) {
     ++num_duplicate_frames_received_;
     // Silently ignore duplicates.
     return;
diff --git a/net/quic/quic_stream_sequencer_test.cc b/net/quic/quic_stream_sequencer_test.cc
index ed55119..667c044 100644
--- a/net/quic/quic_stream_sequencer_test.cc
+++ b/net/quic/quic_stream_sequencer_test.cc
@@ -4,6 +4,9 @@
 
 #include "net/quic/quic_stream_sequencer.h"
 
+#include <algorithm>
+#include <cstdint>
+#include <memory>
 #include <utility>
 #include <vector>
 
@@ -69,7 +72,9 @@
 
  protected:
   QuicStreamSequencerTest()
-      : connection_(new MockConnection(&helper_, Perspective::IS_CLIENT)),
+      : connection_(new MockConnection(&helper_,
+                                       &alarm_factory_,
+                                       Perspective::IS_CLIENT)),
         session_(connection_),
         stream_(&session_, 1),
         sequencer_(new QuicStreamSequencer(&stream_, &clock_)) {}
@@ -146,6 +151,7 @@
   }
 
   MockConnectionHelper helper_;
+  MockAlarmFactory alarm_factory_;
   MockConnection* connection_;
   MockClock clock_;
   MockQuicSpdySession session_;
@@ -563,11 +569,8 @@
   sequencer_->OnStreamFrame(frame1);
 
   QuicStreamFrame frame2(kClientDataStreamId1, false, 2, StringPiece("hello"));
-  EXPECT_CALL(stream_, CloseConnectionWithDetails(
-                           FLAGS_quic_consolidate_onstreamframe_errors
-                               ? QUIC_OVERLAPPING_STREAM_DATA
-                               : QUIC_EMPTY_STREAM_FRAME_NO_FIN,
-                           _))
+  EXPECT_CALL(stream_,
+              CloseConnectionWithDetails(QUIC_OVERLAPPING_STREAM_DATA, _))
       .Times(1);
   sequencer_->OnStreamFrame(frame2);
 }
diff --git a/net/quic/reliable_quic_stream_test.cc b/net/quic/reliable_quic_stream_test.cc
index a4bd67d8..bfa8d2d 100644
--- a/net/quic/reliable_quic_stream_test.cc
+++ b/net/quic/reliable_quic_stream_test.cc
@@ -4,6 +4,8 @@
 
 #include "net/quic/reliable_quic_stream.h"
 
+#include <memory>
+
 #include "net/quic/quic_connection.h"
 #include "net/quic/quic_flags.h"
 #include "net/quic/quic_utils.h"
@@ -104,7 +106,7 @@
 
   void Initialize(bool stream_should_process_data) {
     connection_ = new StrictMock<MockConnection>(
-        &helper_, Perspective::IS_SERVER, supported_versions_);
+        &helper_, &alarm_factory_, Perspective::IS_SERVER, supported_versions_);
     session_.reset(new StrictMock<MockQuicSpdySession>(connection_));
 
     // New streams rely on having the peer's flow control receive window
@@ -148,6 +150,7 @@
 
  protected:
   MockConnectionHelper helper_;
+  MockAlarmFactory alarm_factory_;
   MockConnection* connection_;
   std::unique_ptr<MockQuicSpdySession> session_;
   TestStream* stream_;
diff --git a/net/quic/spdy_utils.cc b/net/quic/spdy_utils.cc
index 7343ccea..bdb4a75 100644
--- a/net/quic/spdy_utils.cc
+++ b/net/quic/spdy_utils.cc
@@ -16,6 +16,7 @@
 #include "net/spdy/spdy_protocol.h"
 #include "url/gurl.h"
 
+using base::StringPiece;
 using std::string;
 using std::vector;
 
@@ -108,11 +109,76 @@
   return true;
 }
 
+bool SpdyUtils::CopyAndValidateHeaders(const QuicHeaderList& header_list,
+                                       int64_t* content_length,
+                                       SpdyHeaderBlock* headers) {
+  for (const auto& p : header_list) {
+    const string& name = p.first;
+    if (name.empty()) {
+      DVLOG(1) << "Header name must not be empty.";
+      return false;
+    }
+
+    if (std::any_of(name.begin(), name.end(), base::IsAsciiUpper<char>)) {
+      DLOG(ERROR) << "Malformed header: Header name " << name
+                  << " contains upper-case characters.";
+      return false;
+    }
+
+    if (headers->find(name) != headers->end()) {
+      DLOG(ERROR) << "Duplicate header '" << name << "' found.";
+      return false;
+    }
+
+    (*headers)[name] = p.second;
+  }
+
+  if (ContainsKey(*headers, "content-length")) {
+    // Check whether multiple values are consistent.
+    StringPiece content_length_header = (*headers)["content-length"];
+    vector<string> values =
+        base::SplitString(content_length_header, base::StringPiece("\0", 1),
+                          base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+    for (const string& value : values) {
+      int new_value;
+      if (!base::StringToInt(value, &new_value) || new_value < 0) {
+        DLOG(ERROR) << "Content length was either unparseable or negative.";
+        return false;
+      }
+      if (*content_length < 0) {
+        *content_length = new_value;
+        continue;
+      }
+      if (new_value != *content_length) {
+        DLOG(ERROR) << "Parsed content length " << new_value << " is "
+                    << "inconsistent with previously detected content length "
+                    << *content_length;
+        return false;
+      }
+    }
+  }
+
+  DVLOG(1) << "Successfully parsed headers: " << headers->DebugString();
+  return true;
+}
+
 bool SpdyUtils::CopyAndValidateTrailers(const QuicHeaderList& header_list,
                                         size_t* final_byte_offset,
                                         SpdyHeaderBlock* trailers) {
+  bool found_final_byte_offset = false;
   for (const auto& p : header_list) {
     const string& name = p.first;
+
+    // Pull out the final offset pseudo header which indicates the number of
+    // response body bytes expected.
+    int offset;
+    if (!found_final_byte_offset && name == kFinalOffsetHeaderKey &&
+        base::StringToInt(p.second, &offset)) {
+      *final_byte_offset = offset;
+      found_final_byte_offset = true;
+      continue;
+    }
+
     if (name.empty() || name[0] == ':') {
       DVLOG(1) << "Trailers must not be empty, and must not contain pseudo-"
                << "headers. Found: '" << name << "'";
@@ -133,20 +199,10 @@
     (*trailers)[name] = p.second;
   }
 
-  if (trailers->empty()) {
-    DVLOG(1) << "Request Trailers are invalid.";
-    return false;  // Trailers were invalid.
-  }
-
-  // Pull out the final offset pseudo header which indicates the number of
-  // response body bytes expected.
-  auto it = trailers->find(kFinalOffsetHeaderKey);
-  if (it == trailers->end() || !StringToSizeT(it->second, final_byte_offset)) {
+  if (!found_final_byte_offset) {
     DVLOG(1) << "Required key '" << kFinalOffsetHeaderKey << "' not present";
     return false;
   }
-  // The final offset header is no longer needed.
-  trailers->erase(it->first);
 
   // TODO(rjshade): Check for other forbidden keys, following the HTTP/2 spec.
 
diff --git a/net/quic/spdy_utils.h b/net/quic/spdy_utils.h
index 708e0c3..6a9b15e 100644
--- a/net/quic/spdy_utils.h
+++ b/net/quic/spdy_utils.h
@@ -45,7 +45,13 @@
                             SpdyHeaderBlock* trailers);
 
   // Copies a list of headers to a SpdyHeaderBlock. Performs similar validation
-  // to SpdyFramer::ParseHeaderBlockInBuffer.
+  // to SpdyFramer::ParseHeaderBlockInBuffer and ParseHeaders, above.
+  static bool CopyAndValidateHeaders(const QuicHeaderList& header_list,
+                                     int64_t* content_length,
+                                     SpdyHeaderBlock* headers);
+
+  // Copies a list of headers to a SpdyHeaderBlock. Performs similar validation
+  // to SpdyFramer::ParseHeaderBlockInBuffer and ParseTrailers, above.
   static bool CopyAndValidateTrailers(const QuicHeaderList& header_list,
                                       size_t* final_byte_offset,
                                       SpdyHeaderBlock* trailers);
diff --git a/net/quic/test_tools/crypto_test_utils.cc b/net/quic/test_tools/crypto_test_utils.cc
index fc13ff35..38d7b2c4 100644
--- a/net/quic/test_tools/crypto_test_utils.cc
+++ b/net/quic/test_tools/crypto_test_utils.cc
@@ -4,6 +4,8 @@
 
 #include "net/quic/test_tools/crypto_test_utils.h"
 
+#include <memory>
+
 #include "base/strings/string_util.h"
 #include "net/quic/crypto/channel_id.h"
 #include "net/quic/crypto/common_cert_set.h"
@@ -128,11 +130,13 @@
 // static
 int CryptoTestUtils::HandshakeWithFakeServer(
     MockConnectionHelper* helper,
+    MockAlarmFactory* alarm_factory,
     PacketSavingConnection* client_conn,
     QuicCryptoClientStream* client,
     const FakeServerOptions& options) {
-  PacketSavingConnection* server_conn = new PacketSavingConnection(
-      helper, Perspective::IS_SERVER, client_conn->supported_versions());
+  PacketSavingConnection* server_conn =
+      new PacketSavingConnection(helper, alarm_factory, Perspective::IS_SERVER,
+                                 client_conn->supported_versions());
 
   QuicConfig config = DefaultQuicConfig();
   QuicCryptoServerConfig crypto_config(QuicCryptoServerConfig::TESTING,
@@ -160,12 +164,13 @@
 // static
 int CryptoTestUtils::HandshakeWithFakeClient(
     MockConnectionHelper* helper,
+    MockAlarmFactory* alarm_factory,
     PacketSavingConnection* server_conn,
     QuicCryptoServerStream* server,
     const QuicServerId& server_id,
     const FakeClientOptions& options) {
   PacketSavingConnection* client_conn =
-      new PacketSavingConnection(helper, Perspective::IS_CLIENT);
+      new PacketSavingConnection(helper, alarm_factory, Perspective::IS_CLIENT);
   // Advance the time, because timers do not like uninitialized times.
   client_conn->AdvanceTime(QuicTime::Delta::FromSeconds(1));
 
diff --git a/net/quic/test_tools/crypto_test_utils.h b/net/quic/test_tools/crypto_test_utils.h
index 6d2ad00..c8beb60 100644
--- a/net/quic/test_tools/crypto_test_utils.h
+++ b/net/quic/test_tools/crypto_test_utils.h
@@ -86,12 +86,16 @@
 
   // returns: the number of client hellos that the client sent.
   static int HandshakeWithFakeServer(MockConnectionHelper* helper,
+                                     MockAlarmFactory* alarm_factory,
                                      PacketSavingConnection* client_conn,
                                      QuicCryptoClientStream* client,
                                      const FakeServerOptions& options);
 
   // returns: the number of client hellos that the client sent.
   static int HandshakeWithFakeClient(MockConnectionHelper* helper,
+
+                                     MockAlarmFactory* alarm_factory,
+
                                      PacketSavingConnection* server_conn,
                                      QuicCryptoServerStream* server,
                                      const QuicServerId& server_id,
diff --git a/net/quic/test_tools/crypto_test_utils_openssl.cc b/net/quic/test_tools/crypto_test_utils_openssl.cc
index 2c39122..1a995de 100644
--- a/net/quic/test_tools/crypto_test_utils_openssl.cc
+++ b/net/quic/test_tools/crypto_test_utils_openssl.cc
@@ -11,6 +11,8 @@
 #include <openssl/obj_mac.h>
 #include <openssl/sha.h>
 
+#include <memory>
+
 #include "crypto/openssl_util.h"
 #include "crypto/scoped_openssl_types.h"
 #include "crypto/secure_hash.h"
diff --git a/net/quic/test_tools/mock_quic_dispatcher.cc b/net/quic/test_tools/mock_quic_dispatcher.cc
index a3136519..dc8098c 100644
--- a/net/quic/test_tools/mock_quic_dispatcher.cc
+++ b/net/quic/test_tools/mock_quic_dispatcher.cc
@@ -12,8 +12,13 @@
 MockQuicDispatcher::MockQuicDispatcher(
     const QuicConfig& config,
     const QuicCryptoServerConfig* crypto_config,
-    QuicConnectionHelperInterface* helper)
-    : QuicDispatcher(config, crypto_config, QuicSupportedVersions(), helper) {}
+    std::unique_ptr<QuicConnectionHelperInterface> helper,
+    std::unique_ptr<QuicAlarmFactory> alarm_factory)
+    : QuicDispatcher(config,
+                     crypto_config,
+                     QuicSupportedVersions(),
+                     std::move(helper),
+                     std::move(alarm_factory)) {}
 
 MockQuicDispatcher::~MockQuicDispatcher() {}
 
diff --git a/net/quic/test_tools/mock_quic_dispatcher.h b/net/quic/test_tools/mock_quic_dispatcher.h
index 05c9c9b..8d666a151 100644
--- a/net/quic/test_tools/mock_quic_dispatcher.h
+++ b/net/quic/test_tools/mock_quic_dispatcher.h
@@ -20,7 +20,8 @@
  public:
   MockQuicDispatcher(const QuicConfig& config,
                      const QuicCryptoServerConfig* crypto_config,
-                     QuicConnectionHelperInterface* helper);
+                     std::unique_ptr<QuicConnectionHelperInterface> helper,
+                     std::unique_ptr<QuicAlarmFactory> alarm_factory);
 
   ~MockQuicDispatcher() override;
 
diff --git a/net/quic/test_tools/quic_connection_peer.cc b/net/quic/test_tools/quic_connection_peer.cc
index 8b2407c..d57c0ce 100644
--- a/net/quic/test_tools/quic_connection_peer.cc
+++ b/net/quic/test_tools/quic_connection_peer.cc
@@ -146,6 +146,12 @@
 }
 
 // static
+QuicAlarmFactory* QuicConnectionPeer::GetAlarmFactory(
+    QuicConnection* connection) {
+  return connection->alarm_factory_;
+}
+
+// static
 QuicFramer* QuicConnectionPeer::GetFramer(QuicConnection* connection) {
   return &connection->framer_;
 }
diff --git a/net/quic/test_tools/quic_connection_peer.h b/net/quic/test_tools/quic_connection_peer.h
index d6130e9..8aaac9f 100644
--- a/net/quic/test_tools/quic_connection_peer.h
+++ b/net/quic/test_tools/quic_connection_peer.h
@@ -85,6 +85,8 @@
 
   static QuicConnectionHelperInterface* GetHelper(QuicConnection* connection);
 
+  static QuicAlarmFactory* GetAlarmFactory(QuicConnection* connection);
+
   static QuicFramer* GetFramer(QuicConnection* connection);
 
   static QuicAlarm* GetAckAlarm(QuicConnection* connection);
diff --git a/net/quic/test_tools/quic_packet_creator_peer.cc b/net/quic/test_tools/quic_packet_creator_peer.cc
index 83b783c4..90821dd1 100644
--- a/net/quic/test_tools/quic_packet_creator_peer.cc
+++ b/net/quic/test_tools/quic_packet_creator_peer.cc
@@ -70,14 +70,14 @@
 }
 
 // static
-size_t QuicPacketCreatorPeer::CreateStreamFrame(QuicPacketCreator* creator,
-                                                QuicStreamId id,
-                                                QuicIOVector iov,
-                                                size_t iov_offset,
-                                                QuicStreamOffset offset,
-                                                bool fin,
-                                                QuicFrame* frame) {
-  return creator->CreateStreamFrame(id, iov, iov_offset, offset, fin, frame);
+void QuicPacketCreatorPeer::CreateStreamFrame(QuicPacketCreator* creator,
+                                              QuicStreamId id,
+                                              QuicIOVector iov,
+                                              size_t iov_offset,
+                                              QuicStreamOffset offset,
+                                              bool fin,
+                                              QuicFrame* frame) {
+  creator->CreateStreamFrame(id, iov, iov_offset, offset, fin, frame);
 }
 
 // static
diff --git a/net/quic/test_tools/quic_packet_creator_peer.h b/net/quic/test_tools/quic_packet_creator_peer.h
index 6849c1f..7c56c45 100644
--- a/net/quic/test_tools/quic_packet_creator_peer.h
+++ b/net/quic/test_tools/quic_packet_creator_peer.h
@@ -37,13 +37,13 @@
   static void SetPacketNumber(QuicPacketCreator* creator, QuicPacketNumber s);
   static void FillPacketHeader(QuicPacketCreator* creator,
                                QuicPacketHeader* header);
-  static size_t CreateStreamFrame(QuicPacketCreator* creator,
-                                  QuicStreamId id,
-                                  QuicIOVector iov,
-                                  size_t iov_offset,
-                                  QuicStreamOffset offset,
-                                  bool fin,
-                                  QuicFrame* frame);
+  static void CreateStreamFrame(QuicPacketCreator* creator,
+                                QuicStreamId id,
+                                QuicIOVector iov,
+                                size_t iov_offset,
+                                QuicStreamOffset offset,
+                                bool fin,
+                                QuicFrame* frame);
   static SerializedPacket SerializeAllFrames(QuicPacketCreator* creator,
                                              const QuicFrames& frames,
                                              char* buffer,
diff --git a/net/quic/test_tools/quic_test_utils.cc b/net/quic/test_tools/quic_test_utils.cc
index 5fd9d7de..c9b81de 100644
--- a/net/quic/test_tools/quic_test_utils.cc
+++ b/net/quic/test_tools/quic_test_utils.cc
@@ -4,6 +4,8 @@
 
 #include "net/quic/test_tools/quic_test_utils.h"
 
+#include <memory>
+
 #include "base/sha1.h"
 #include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
@@ -199,18 +201,18 @@
   return &random_generator_;
 }
 
-QuicAlarm* MockConnectionHelper::CreateAlarm(QuicAlarm::Delegate* delegate) {
-  return new MockConnectionHelper::TestAlarm(
+QuicAlarm* MockAlarmFactory::CreateAlarm(QuicAlarm::Delegate* delegate) {
+  return new MockAlarmFactory::TestAlarm(
       QuicArenaScopedPtr<QuicAlarm::Delegate>(delegate));
 }
 
-QuicArenaScopedPtr<QuicAlarm> MockConnectionHelper::CreateAlarm(
+QuicArenaScopedPtr<QuicAlarm> MockAlarmFactory::CreateAlarm(
     QuicArenaScopedPtr<QuicAlarm::Delegate> delegate,
     QuicConnectionArena* arena) {
   if (arena != nullptr) {
-    return arena->New<MockConnectionHelper::TestAlarm>(std::move(delegate));
+    return arena->New<MockAlarmFactory::TestAlarm>(std::move(delegate));
   } else {
-    return QuicArenaScopedPtr<MockConnectionHelper::TestAlarm>(
+    return QuicArenaScopedPtr<MockAlarmFactory::TestAlarm>(
         new TestAlarm(std::move(delegate)));
   }
 }
@@ -224,48 +226,58 @@
 }
 
 MockConnection::MockConnection(MockConnectionHelper* helper,
+                               MockAlarmFactory* alarm_factory,
                                Perspective perspective)
     : MockConnection(kTestConnectionId,
                      IPEndPoint(TestPeerIPAddress(), kTestPort),
                      helper,
+                     alarm_factory,
                      perspective,
                      QuicSupportedVersions()) {}
 
 MockConnection::MockConnection(IPEndPoint address,
                                MockConnectionHelper* helper,
+                               MockAlarmFactory* alarm_factory,
                                Perspective perspective)
     : MockConnection(kTestConnectionId,
                      address,
                      helper,
+                     alarm_factory,
                      perspective,
                      QuicSupportedVersions()) {}
 
 MockConnection::MockConnection(QuicConnectionId connection_id,
                                MockConnectionHelper* helper,
+                               MockAlarmFactory* alarm_factory,
                                Perspective perspective)
     : MockConnection(connection_id,
                      IPEndPoint(TestPeerIPAddress(), kTestPort),
                      helper,
+                     alarm_factory,
                      perspective,
                      QuicSupportedVersions()) {}
 
 MockConnection::MockConnection(MockConnectionHelper* helper,
+                               MockAlarmFactory* alarm_factory,
                                Perspective perspective,
                                const QuicVersionVector& supported_versions)
     : MockConnection(kTestConnectionId,
                      IPEndPoint(TestPeerIPAddress(), kTestPort),
                      helper,
+                     alarm_factory,
                      perspective,
                      supported_versions) {}
 
 MockConnection::MockConnection(QuicConnectionId connection_id,
                                IPEndPoint address,
                                MockConnectionHelper* helper,
+                               MockAlarmFactory* alarm_factory,
                                Perspective perspective,
                                const QuicVersionVector& supported_versions)
     : QuicConnection(connection_id,
                      address,
                      helper,
+                     alarm_factory,
                      new testing::NiceMock<MockPacketWriter>(),
                      /* owns_writer= */ true,
                      perspective,
@@ -282,14 +294,16 @@
 }
 
 PacketSavingConnection::PacketSavingConnection(MockConnectionHelper* helper,
+                                               MockAlarmFactory* alarm_factory,
                                                Perspective perspective)
-    : MockConnection(helper, perspective) {}
+    : MockConnection(helper, alarm_factory, perspective) {}
 
 PacketSavingConnection::PacketSavingConnection(
     MockConnectionHelper* helper,
+    MockAlarmFactory* alarm_factory,
     Perspective perspective,
     const QuicVersionVector& supported_versions)
-    : MockConnection(helper, perspective, supported_versions) {}
+    : MockConnection(helper, alarm_factory, perspective, supported_versions) {}
 
 PacketSavingConnection::~PacketSavingConnection() {
   STLDeleteElements(&encrypted_packets_);
@@ -759,6 +773,7 @@
                                 QuicTime::Delta connection_start_time,
                                 QuicVersionVector supported_versions,
                                 MockConnectionHelper* helper,
+                                MockAlarmFactory* alarm_factory,
                                 QuicCryptoClientConfig* crypto_client_config,
                                 PacketSavingConnection** client_connection,
                                 TestQuicSpdyClientSession** client_session) {
@@ -773,7 +788,7 @@
                           ? DefaultQuicConfigStatelessRejects()
                           : DefaultQuicConfig();
   *client_connection = new PacketSavingConnection(
-      helper, Perspective::IS_CLIENT, supported_versions);
+      helper, alarm_factory, Perspective::IS_CLIENT, supported_versions);
   *client_session = new TestQuicSpdyClientSession(
       *client_connection, config, server_id, crypto_client_config);
   (*client_connection)->AdvanceTime(connection_start_time);
@@ -784,6 +799,7 @@
     QuicTime::Delta connection_start_time,
     QuicVersionVector supported_versions,
     MockConnectionHelper* helper,
+    MockAlarmFactory* alarm_factory,
     QuicCryptoServerConfig* server_crypto_config,
     QuicCompressedCertsCache* compressed_certs_cache,
     PacketSavingConnection** server_connection,
@@ -796,7 +812,7 @@
       << "strike-register will be unhappy.";
 
   *server_connection = new PacketSavingConnection(
-      helper, Perspective::IS_SERVER, supported_versions);
+      helper, alarm_factory, Perspective::IS_SERVER, supported_versions);
   *server_session = new TestQuicSpdyServerSession(
       *server_connection, DefaultQuicConfig(), server_crypto_config,
       compressed_certs_cache);
diff --git a/net/quic/test_tools/quic_test_utils.h b/net/quic/test_tools/quic_test_utils.h
index 69b0b79..2e6d646c 100644
--- a/net/quic/test_tools/quic_test_utils.h
+++ b/net/quic/test_tools/quic_test_utils.h
@@ -10,6 +10,8 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include <cstdint>
+#include <memory>
 #include <string>
 #include <vector>
 
@@ -320,12 +322,23 @@
   ~MockConnectionHelper() override;
   const QuicClock* GetClock() const override;
   QuicRandom* GetRandomGenerator() override;
+  QuicBufferAllocator* GetBufferAllocator() override;
+  void AdvanceTime(QuicTime::Delta delta);
+
+ private:
+  MockClock clock_;
+  MockRandom random_generator_;
+  SimpleBufferAllocator buffer_allocator_;
+
+  DISALLOW_COPY_AND_ASSIGN(MockConnectionHelper);
+};
+
+class MockAlarmFactory : public QuicAlarmFactory {
+ public:
   QuicAlarm* CreateAlarm(QuicAlarm::Delegate* delegate) override;
   QuicArenaScopedPtr<QuicAlarm> CreateAlarm(
       QuicArenaScopedPtr<QuicAlarm::Delegate> delegate,
       QuicConnectionArena* arena) override;
-  QuicBufferAllocator* GetBufferAllocator() override;
-  void AdvanceTime(QuicTime::Delta delta);
 
   // No-op alarm implementation
   class TestAlarm : public QuicAlarm {
@@ -342,38 +355,37 @@
   void FireAlarm(QuicAlarm* alarm) {
     reinterpret_cast<TestAlarm*>(alarm)->Fire();
   }
-
- private:
-  MockClock clock_;
-  MockRandom random_generator_;
-  SimpleBufferAllocator buffer_allocator_;
-
-  DISALLOW_COPY_AND_ASSIGN(MockConnectionHelper);
 };
 
 class MockConnection : public QuicConnection {
  public:
   // Uses a ConnectionId of 42 and 127.0.0.1:123.
-  MockConnection(MockConnectionHelper* helper, Perspective perspective);
+  MockConnection(MockConnectionHelper* helper,
+                 MockAlarmFactory* alarm_factory,
+                 Perspective perspective);
 
   // Uses a ConnectionId of 42.
   MockConnection(IPEndPoint address,
                  MockConnectionHelper* helper,
+                 MockAlarmFactory* alarm_factory,
                  Perspective perspective);
 
   // Uses 127.0.0.1:123.
   MockConnection(QuicConnectionId connection_id,
                  MockConnectionHelper* helper,
+                 MockAlarmFactory* alarm_factory,
                  Perspective perspective);
 
   // Uses a ConnectionId of 42, and 127.0.0.1:123.
   MockConnection(MockConnectionHelper* helper,
+                 MockAlarmFactory* alarm_factory,
                  Perspective perspective,
                  const QuicVersionVector& supported_versions);
 
   MockConnection(QuicConnectionId connection_id,
                  IPEndPoint address,
                  MockConnectionHelper* helper,
+                 MockAlarmFactory* alarm_factory,
                  Perspective perspective,
                  const QuicVersionVector& supported_versions);
 
@@ -437,9 +449,12 @@
 
 class PacketSavingConnection : public MockConnection {
  public:
-  PacketSavingConnection(MockConnectionHelper* helper, Perspective perspective);
+  PacketSavingConnection(MockConnectionHelper* helper,
+                         MockAlarmFactory* alarm_factory,
+                         Perspective perspective);
 
   PacketSavingConnection(MockConnectionHelper* helper,
+                         MockAlarmFactory* alarm_factory,
                          Perspective perspective,
                          const QuicVersionVector& supported_versions);
 
@@ -488,13 +503,23 @@
                void(QuicStreamId stream_id, SpdyPriority priority));
   MOCK_METHOD3(OnStreamHeadersComplete,
                void(QuicStreamId stream_id, bool fin, size_t frame_len));
+  MOCK_METHOD4(OnStreamHeaderList,
+               void(QuicStreamId stream_id,
+                    bool fin,
+                    size_t frame_len,
+                    const QuicHeaderList& header_list));
+  MOCK_METHOD0(IsCryptoHandshakeConfirmed, bool());
   MOCK_METHOD2(OnPromiseHeaders,
                void(QuicStreamId stream_id, StringPiece headers_data));
   MOCK_METHOD3(OnPromiseHeadersComplete,
                void(QuicStreamId stream_id,
                     QuicStreamId promised_stream_id,
                     size_t frame_len));
-  MOCK_METHOD0(IsCryptoHandshakeConfirmed, bool());
+  MOCK_METHOD4(OnPromiseHeaderList,
+               void(QuicStreamId stream_id,
+                    QuicStreamId promised_stream_id,
+                    size_t frame_len,
+                    const QuicHeaderList& header_list));
   MOCK_METHOD5(WriteHeaders,
                size_t(QuicStreamId id,
                       const SpdyHeaderBlock& headers,
@@ -793,6 +818,7 @@
                                 QuicTime::Delta connection_start_time,
                                 QuicVersionVector supported_versions,
                                 MockConnectionHelper* helper,
+                                MockAlarmFactory* alarm_factory,
                                 QuicCryptoClientConfig* crypto_client_config,
                                 PacketSavingConnection** client_connection,
                                 TestQuicSpdyClientSession** client_session);
@@ -817,6 +843,7 @@
     QuicTime::Delta connection_start_time,
     QuicVersionVector supported_versions,
     MockConnectionHelper* helper,
+    MockAlarmFactory* alarm_factory,
     QuicCryptoServerConfig* crypto_server_config,
     QuicCompressedCertsCache* compressed_certs_cache,
     PacketSavingConnection** server_connection,
diff --git a/net/quic/test_tools/simple_quic_framer.cc b/net/quic/test_tools/simple_quic_framer.cc
index 62e74b61..b26b97e 100644
--- a/net/quic/test_tools/simple_quic_framer.cc
+++ b/net/quic/test_tools/simple_quic_framer.cc
@@ -4,6 +4,8 @@
 
 #include "net/quic/test_tools/simple_quic_framer.h"
 
+#include <memory>
+
 #include "base/macros.h"
 #include "base/stl_util.h"
 #include "net/quic/crypto/quic_decrypter.h"