If a QuicAlarm belongs to a single QuicConnection, make sure the alarm fires under the corresponding QuicConnectionContext.

Protected by FLAGS_quic_reloadable_flag_quic_restore_connection_context_in_alarms.

PiperOrigin-RevId: 394230753
diff --git a/quic/core/http/quic_client_promised_info.h b/quic/core/http/quic_client_promised_info.h
index 0666c3a..ec071f0 100644
--- a/quic/core/http/quic_client_promised_info.h
+++ b/quic/core/http/quic_client_promised_info.h
@@ -84,7 +84,8 @@
  private:
   friend class test::QuicClientPromisedInfoPeer;
 
-  class QUIC_EXPORT_PRIVATE CleanupAlarm : public QuicAlarm::Delegate {
+  class QUIC_EXPORT_PRIVATE CleanupAlarm
+      : public QuicAlarm::DelegateWithoutContext {
    public:
     explicit CleanupAlarm(QuicClientPromisedInfo* promised)
         : promised_(promised) {}
diff --git a/quic/core/quic_alarm.cc b/quic/core/quic_alarm.cc
index 81640a4..67e0a74 100644
--- a/quic/core/quic_alarm.cc
+++ b/quic/core/quic_alarm.cc
@@ -100,6 +100,11 @@
 
   deadline_ = QuicTime::Zero();
   if (!IsPermanentlyCancelled()) {
+    absl::optional<QuicConnectionContextSwitcher> context_switcher;
+    if (GetQuicReloadableFlag(quic_restore_connection_context_in_alarms)) {
+      QUIC_RELOADABLE_FLAG_COUNT(quic_restore_connection_context_in_alarms);
+      context_switcher.emplace(delegate_->GetConnectionContext());
+    }
     delegate_->OnAlarm();
   }
 }
diff --git a/quic/core/quic_alarm.h b/quic/core/quic_alarm.h
index 5080fd4..26ebfe8 100644
--- a/quic/core/quic_alarm.h
+++ b/quic/core/quic_alarm.h
@@ -6,6 +6,7 @@
 #define QUICHE_QUIC_CORE_QUIC_ALARM_H_
 
 #include "quic/core/quic_arena_scoped_ptr.h"
+#include "quic/core/quic_connection_context.h"
 #include "quic/core/quic_time.h"
 #include "quic/platform/api/quic_export.h"
 
@@ -22,10 +23,39 @@
    public:
     virtual ~Delegate() {}
 
+    // If the alarm belongs to a single QuicConnection, return the corresponding
+    // QuicConnection.context_. Note the context_ is the first member of
+    // QuicConnection, so it should outlive the delegate.
+    // Otherwise return nullptr.
+    // The OnAlarm function will be called under the connection context, if any.
+    virtual QuicConnectionContext* GetConnectionContext() = 0;
+
     // Invoked when the alarm fires.
     virtual void OnAlarm() = 0;
   };
 
+  // DelegateWithContext is a Delegate with a QuicConnectionContext* stored as a
+  // member variable.
+  class QUIC_EXPORT_PRIVATE DelegateWithContext : public Delegate {
+   public:
+    explicit DelegateWithContext(QuicConnectionContext* context)
+        : context_(context) {}
+    ~DelegateWithContext() override {}
+    QuicConnectionContext* GetConnectionContext() override { return context_; }
+
+   private:
+    QuicConnectionContext* context_;
+  };
+
+  // DelegateWithoutContext is a Delegate that does not have a corresponding
+  // context. Typically this means one object of the child class deals with many
+  // connections.
+  class QUIC_EXPORT_PRIVATE DelegateWithoutContext : public Delegate {
+   public:
+    ~DelegateWithoutContext() override {}
+    QuicConnectionContext* GetConnectionContext() override { return nullptr; }
+  };
+
   explicit QuicAlarm(QuicArenaScopedPtr<Delegate> delegate);
   QuicAlarm(const QuicAlarm&) = delete;
   QuicAlarm& operator=(const QuicAlarm&) = delete;
diff --git a/quic/core/quic_alarm_test.cc b/quic/core/quic_alarm_test.cc
index ab07002..bc3ea2c 100644
--- a/quic/core/quic_alarm_test.cc
+++ b/quic/core/quic_alarm_test.cc
@@ -4,21 +4,41 @@
 
 #include "quic/core/quic_alarm.h"
 
+#include "quic/core/quic_connection_context.h"
 #include "quic/platform/api/quic_expect_bug.h"
 #include "quic/platform/api/quic_test.h"
 
+using testing::ElementsAre;
 using testing::Invoke;
+using testing::Return;
 
 namespace quic {
 namespace test {
 namespace {
 
+class TraceCollector : public QuicConnectionTracer {
+ public:
+  ~TraceCollector() override = default;
+
+  void PrintLiteral(const char* literal) override { trace_.push_back(literal); }
+
+  void PrintString(absl::string_view s) override {
+    trace_.push_back(std::string(s));
+  }
+
+  const std::vector<std::string>& trace() const { return trace_; }
+
+ private:
+  std::vector<std::string> trace_;
+};
+
 class MockDelegate : public QuicAlarm::Delegate {
  public:
+  MOCK_METHOD(QuicConnectionContext*, GetConnectionContext, (), (override));
   MOCK_METHOD(void, OnAlarm, (), (override));
 };
 
-class DestructiveDelegate : public QuicAlarm::Delegate {
+class DestructiveDelegate : public QuicAlarm::DelegateWithoutContext {
  public:
   DestructiveDelegate() : alarm_(nullptr) {}
 
@@ -204,6 +224,67 @@
   alarm->FireAlarm();
 }
 
+TEST_F(QuicAlarmTest, NullAlarmContext) {
+  QuicTime deadline = QuicTime::Zero() + QuicTime::Delta::FromSeconds(7);
+  alarm_.Set(deadline);
+
+  if (GetQuicReloadableFlag(quic_restore_connection_context_in_alarms)) {
+    EXPECT_CALL(*delegate_, GetConnectionContext()).WillOnce(Return(nullptr));
+  }
+
+  EXPECT_CALL(*delegate_, OnAlarm()).WillOnce(Invoke([] {
+    QUIC_TRACELITERAL("Alarm fired.");
+  }));
+  alarm_.FireAlarm();
+}
+
+TEST_F(QuicAlarmTest, AlarmContextWithNullTracer) {
+  QuicConnectionContext context;
+  ASSERT_EQ(context.tracer, nullptr);
+
+  QuicTime deadline = QuicTime::Zero() + QuicTime::Delta::FromSeconds(7);
+  alarm_.Set(deadline);
+
+  if (GetQuicReloadableFlag(quic_restore_connection_context_in_alarms)) {
+    EXPECT_CALL(*delegate_, GetConnectionContext()).WillOnce(Return(&context));
+  }
+
+  EXPECT_CALL(*delegate_, OnAlarm()).WillOnce(Invoke([] {
+    QUIC_TRACELITERAL("Alarm fired.");
+  }));
+  alarm_.FireAlarm();
+}
+
+TEST_F(QuicAlarmTest, AlarmContextWithTracer) {
+  QuicConnectionContext context;
+  std::unique_ptr<TraceCollector> tracer = std::make_unique<TraceCollector>();
+  const TraceCollector& tracer_ref = *tracer;
+  context.tracer = std::move(tracer);
+
+  QuicTime deadline = QuicTime::Zero() + QuicTime::Delta::FromSeconds(7);
+  alarm_.Set(deadline);
+
+  if (GetQuicReloadableFlag(quic_restore_connection_context_in_alarms)) {
+    EXPECT_CALL(*delegate_, GetConnectionContext()).WillOnce(Return(&context));
+  }
+
+  EXPECT_CALL(*delegate_, OnAlarm()).WillOnce(Invoke([] {
+    QUIC_TRACELITERAL("Alarm fired.");
+  }));
+
+  // Since |context| is not installed in the current thread, the messages before
+  // and after FireAlarm() should not be collected by |tracer|.
+  QUIC_TRACELITERAL("Should not be collected before alarm.");
+  alarm_.FireAlarm();
+  QUIC_TRACELITERAL("Should not be collected after alarm.");
+
+  if (GetQuicReloadableFlag(quic_restore_connection_context_in_alarms)) {
+    EXPECT_THAT(tracer_ref.trace(), ElementsAre("Alarm fired."));
+  } else {
+    EXPECT_TRUE(tracer_ref.trace().empty());
+  }
+}
+
 }  // namespace
 }  // namespace test
 }  // namespace quic
diff --git a/quic/core/quic_buffered_packet_store.cc b/quic/core/quic_buffered_packet_store.cc
index 9312ea5..ed1b80e 100644
--- a/quic/core/quic_buffered_packet_store.cc
+++ b/quic/core/quic_buffered_packet_store.cc
@@ -24,7 +24,7 @@
 namespace {
 
 // This alarm removes expired entries in map each time this alarm fires.
-class ConnectionExpireAlarm : public QuicAlarm::Delegate {
+class ConnectionExpireAlarm : public QuicAlarm::DelegateWithoutContext {
  public:
   explicit ConnectionExpireAlarm(QuicBufferedPacketStore* store)
       : connection_store_(store) {}
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc
index b77bb1b..170a206 100644
--- a/quic/core/quic_connection.cc
+++ b/quic/core/quic_connection.cc
@@ -72,6 +72,10 @@
   QuicConnectionAlarmDelegate& operator=(const QuicConnectionAlarmDelegate&) =
       delete;
 
+  QuicConnectionContext* GetConnectionContext() override {
+    return (connection_ == nullptr) ? nullptr : connection_->context();
+  }
+
  protected:
   QuicConnection* connection_;
 };
@@ -216,16 +220,11 @@
     QuicConnectionId server_connection_id,
     QuicSocketAddress initial_self_address,
     QuicSocketAddress initial_peer_address,
-    QuicConnectionHelperInterface* helper,
-    QuicAlarmFactory* alarm_factory,
-    QuicPacketWriter* writer,
-    bool owns_writer,
-    Perspective perspective,
+    QuicConnectionHelperInterface* helper, QuicAlarmFactory* alarm_factory,
+    QuicPacketWriter* writer, bool owns_writer, Perspective perspective,
     const ParsedQuicVersionVector& supported_versions)
-    : framer_(supported_versions,
-              helper->GetClock()->ApproximateNow(),
-              perspective,
-              server_connection_id.length()),
+    : framer_(supported_versions, helper->GetClock()->ApproximateNow(),
+              perspective, server_connection_id.length()),
       current_packet_content_(NO_FRAMES_RECEIVED),
       is_current_packet_connectivity_probing_(false),
       has_path_challenge_in_current_packet_(false),
@@ -240,8 +239,7 @@
       random_generator_(helper->GetRandomGenerator()),
       client_connection_id_is_set_(false),
       direct_peer_address_(initial_peer_address),
-      default_path_(initial_self_address,
-                    QuicSocketAddress(),
+      default_path_(initial_self_address, QuicSocketAddress(),
                     /*client_connection_id=*/EmptyQuicConnectionId(),
                     server_connection_id,
                     /*stateless_reset_token_received=*/false,
@@ -270,23 +268,17 @@
       ack_alarm_(alarm_factory_->CreateAlarm(arena_.New<AckAlarmDelegate>(this),
                                              &arena_)),
       retransmission_alarm_(alarm_factory_->CreateAlarm(
-          arena_.New<RetransmissionAlarmDelegate>(this),
-          &arena_)),
-      send_alarm_(
-          alarm_factory_->CreateAlarm(arena_.New<SendAlarmDelegate>(this),
-                                      &arena_)),
-      ping_alarm_(
-          alarm_factory_->CreateAlarm(arena_.New<PingAlarmDelegate>(this),
-                                      &arena_)),
+          arena_.New<RetransmissionAlarmDelegate>(this), &arena_)),
+      send_alarm_(alarm_factory_->CreateAlarm(
+          arena_.New<SendAlarmDelegate>(this), &arena_)),
+      ping_alarm_(alarm_factory_->CreateAlarm(
+          arena_.New<PingAlarmDelegate>(this), &arena_)),
       mtu_discovery_alarm_(alarm_factory_->CreateAlarm(
-          arena_.New<MtuDiscoveryAlarmDelegate>(this),
-          &arena_)),
+          arena_.New<MtuDiscoveryAlarmDelegate>(this), &arena_)),
       process_undecryptable_packets_alarm_(alarm_factory_->CreateAlarm(
-          arena_.New<ProcessUndecryptablePacketsAlarmDelegate>(this),
-          &arena_)),
+          arena_.New<ProcessUndecryptablePacketsAlarmDelegate>(this), &arena_)),
       discard_previous_one_rtt_keys_alarm_(alarm_factory_->CreateAlarm(
-          arena_.New<DiscardPreviousOneRttKeysAlarmDelegate>(this),
-          &arena_)),
+          arena_.New<DiscardPreviousOneRttKeysAlarmDelegate>(this), &arena_)),
       discard_zero_rtt_decryption_keys_alarm_(alarm_factory_->CreateAlarm(
           arena_.New<DiscardZeroRttDecryptionKeysAlarmDelegate>(this),
           &arena_)),
@@ -294,10 +286,7 @@
       debug_visitor_(nullptr),
       packet_creator_(server_connection_id, &framer_, random_generator_, this),
       last_received_packet_info_(clock_->ApproximateNow()),
-      sent_packet_manager_(perspective,
-                           clock_,
-                           random_generator_,
-                           &stats_,
+      sent_packet_manager_(perspective, clock_, random_generator_, &stats_,
                            GetDefaultCongestionControlType()),
       version_negotiated_(false),
       perspective_(perspective),
@@ -320,12 +309,11 @@
       processing_ack_frame_(false),
       supports_release_time_(false),
       release_time_into_future_(QuicTime::Delta::Zero()),
-      blackhole_detector_(this, &arena_, alarm_factory_),
-      idle_network_detector_(this,
-                             clock_->ApproximateNow(),
-                             &arena_,
-                             alarm_factory_),
-      path_validator_(alarm_factory_, &arena_, this, random_generator_),
+      blackhole_detector_(this, &arena_, alarm_factory_, &context_),
+      idle_network_detector_(this, clock_->ApproximateNow(), &arena_,
+                             alarm_factory_, &context_),
+      path_validator_(alarm_factory_, &arena_, this, random_generator_,
+                      &context_),
       most_recent_frame_type_(NUM_FRAME_TYPES) {
   QUICHE_DCHECK(perspective_ == Perspective::IS_CLIENT ||
                 default_path_.self_address.IsInitialized());
@@ -2983,7 +2971,7 @@
         peer_issued_cid_manager_ =
             std::make_unique<QuicPeerIssuedConnectionIdManager>(
                 kMinNumOfActiveConnectionIds, new_server_connection_id, clock_,
-                alarm_factory_, this);
+                alarm_factory_, this, context());
       }
     }
   }
@@ -4070,7 +4058,7 @@
       perspective_ == Perspective::IS_CLIENT
           ? default_path_.client_connection_id
           : default_path_.server_connection_id,
-      clock_, alarm_factory_, this);
+      clock_, alarm_factory_, this, context());
 }
 
 void QuicConnection::MaybeSendConnectionIdToClient() {
@@ -6264,7 +6252,7 @@
       peer_issued_cid_manager_ =
           std::make_unique<QuicPeerIssuedConnectionIdManager>(
               kMinNumOfActiveConnectionIds, client_connection_id, clock_,
-              alarm_factory_, this);
+              alarm_factory_, this, context());
     } else {
       // Note in Chromium client, set_client_connection_id is not called and
       // thus self_issued_cid_manager_ should be null.
@@ -6876,7 +6864,7 @@
       peer_issued_cid_manager_ =
           std::make_unique<QuicPeerIssuedConnectionIdManager>(
               kMinNumOfActiveConnectionIds, default_path_.server_connection_id,
-              clock_, alarm_factory_, this);
+              clock_, alarm_factory_, this, context());
     }
   } else {
     if (!default_path_.server_connection_id.IsEmpty()) {
diff --git a/quic/core/quic_connection_id_manager.cc b/quic/core/quic_connection_id_manager.cc
index c7e8972..1138a2e 100644
--- a/quic/core/quic_connection_id_manager.cc
+++ b/quic/core/quic_connection_id_manager.cc
@@ -24,11 +24,13 @@
 
 namespace {
 
-class RetirePeerIssuedConnectionIdAlarm : public QuicAlarm::Delegate {
+class RetirePeerIssuedConnectionIdAlarm
+    : public QuicAlarm::DelegateWithContext {
  public:
   explicit RetirePeerIssuedConnectionIdAlarm(
-      QuicConnectionIdManagerVisitorInterface* visitor)
-      : visitor_(visitor) {}
+      QuicConnectionIdManagerVisitorInterface* visitor,
+      QuicConnectionContext* context)
+      : QuicAlarm::DelegateWithContext(context), visitor_(visitor) {}
   RetirePeerIssuedConnectionIdAlarm(const RetirePeerIssuedConnectionIdAlarm&) =
       delete;
   RetirePeerIssuedConnectionIdAlarm& operator=(
@@ -63,13 +65,13 @@
 QuicPeerIssuedConnectionIdManager::QuicPeerIssuedConnectionIdManager(
     size_t active_connection_id_limit,
     const QuicConnectionId& initial_peer_issued_connection_id,
-    const QuicClock* clock,
-    QuicAlarmFactory* alarm_factory,
-    QuicConnectionIdManagerVisitorInterface* visitor)
+    const QuicClock* clock, QuicAlarmFactory* alarm_factory,
+    QuicConnectionIdManagerVisitorInterface* visitor,
+    QuicConnectionContext* context)
     : active_connection_id_limit_(active_connection_id_limit),
       clock_(clock),
       retire_connection_id_alarm_(alarm_factory->CreateAlarm(
-          new RetirePeerIssuedConnectionIdAlarm(visitor))) {
+          new RetirePeerIssuedConnectionIdAlarm(visitor, context))) {
   QUICHE_DCHECK_GE(active_connection_id_limit_, 2u);
   QUICHE_DCHECK(!initial_peer_issued_connection_id.IsEmpty());
   active_connection_id_data_.emplace_back<const QuicConnectionId&, uint64_t,
@@ -251,11 +253,14 @@
 
 namespace {
 
-class RetireSelfIssuedConnectionIdAlarmDelegate : public QuicAlarm::Delegate {
+class RetireSelfIssuedConnectionIdAlarmDelegate
+    : public QuicAlarm::DelegateWithContext {
  public:
   explicit RetireSelfIssuedConnectionIdAlarmDelegate(
-      QuicSelfIssuedConnectionIdManager* connection_id_manager)
-      : connection_id_manager_(connection_id_manager) {}
+      QuicSelfIssuedConnectionIdManager* connection_id_manager,
+      QuicConnectionContext* context)
+      : QuicAlarm::DelegateWithContext(context),
+        connection_id_manager_(connection_id_manager) {}
   RetireSelfIssuedConnectionIdAlarmDelegate(
       const RetireSelfIssuedConnectionIdAlarmDelegate&) = delete;
   RetireSelfIssuedConnectionIdAlarmDelegate& operator=(
@@ -271,15 +276,15 @@
 
 QuicSelfIssuedConnectionIdManager::QuicSelfIssuedConnectionIdManager(
     size_t active_connection_id_limit,
-    const QuicConnectionId& initial_connection_id,
-    const QuicClock* clock,
+    const QuicConnectionId& initial_connection_id, const QuicClock* clock,
     QuicAlarmFactory* alarm_factory,
-    QuicConnectionIdManagerVisitorInterface* visitor)
+    QuicConnectionIdManagerVisitorInterface* visitor,
+    QuicConnectionContext* context)
     : active_connection_id_limit_(active_connection_id_limit),
       clock_(clock),
       visitor_(visitor),
       retire_connection_id_alarm_(alarm_factory->CreateAlarm(
-          new RetireSelfIssuedConnectionIdAlarmDelegate(this))),
+          new RetireSelfIssuedConnectionIdAlarmDelegate(this, context))),
       last_connection_id_(initial_connection_id),
       next_connection_id_sequence_number_(1u),
       last_connection_id_consumed_by_self_sequence_number_(0u) {
diff --git a/quic/core/quic_connection_id_manager.h b/quic/core/quic_connection_id_manager.h
index 775c016..e23668d 100644
--- a/quic/core/quic_connection_id_manager.h
+++ b/quic/core/quic_connection_id_manager.h
@@ -60,9 +60,9 @@
   QuicPeerIssuedConnectionIdManager(
       size_t active_connection_id_limit,
       const QuicConnectionId& initial_peer_issued_connection_id,
-      const QuicClock* clock,
-      QuicAlarmFactory* alarm_factory,
-      QuicConnectionIdManagerVisitorInterface* visitor);
+      const QuicClock* clock, QuicAlarmFactory* alarm_factory,
+      QuicConnectionIdManagerVisitorInterface* visitor,
+      QuicConnectionContext* context);
 
   ~QuicPeerIssuedConnectionIdManager();
 
@@ -123,10 +123,10 @@
  public:
   QuicSelfIssuedConnectionIdManager(
       size_t active_connection_id_limit,
-      const QuicConnectionId& initial_connection_id,
-      const QuicClock* clock,
+      const QuicConnectionId& initial_connection_id, const QuicClock* clock,
       QuicAlarmFactory* alarm_factory,
-      QuicConnectionIdManagerVisitorInterface* visitor);
+      QuicConnectionIdManagerVisitorInterface* visitor,
+      QuicConnectionContext* context);
 
   virtual ~QuicSelfIssuedConnectionIdManager();
 
diff --git a/quic/core/quic_connection_id_manager_test.cc b/quic/core/quic_connection_id_manager_test.cc
index 7baeb2b..fdb73da 100644
--- a/quic/core/quic_connection_id_manager_test.cc
+++ b/quic/core/quic_connection_id_manager_test.cc
@@ -78,11 +78,9 @@
 class QuicPeerIssuedConnectionIdManagerTest : public QuicTest {
  public:
   QuicPeerIssuedConnectionIdManagerTest()
-      : peer_issued_cid_manager_(/*active_connection_id_limit=*/2,
-                                 initial_connection_id_,
-                                 &clock_,
-                                 &alarm_factory_,
-                                 &cid_manager_visitor_) {
+      : peer_issued_cid_manager_(
+            /*active_connection_id_limit=*/2, initial_connection_id_, &clock_,
+            &alarm_factory_, &cid_manager_visitor_, /*context=*/nullptr) {
     clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
     cid_manager_visitor_.SetPeerIssuedConnectionIdManager(
         &peer_issued_cid_manager_);
@@ -538,11 +536,9 @@
 class QuicSelfIssuedConnectionIdManagerTest : public QuicTest {
  public:
   QuicSelfIssuedConnectionIdManagerTest()
-      : cid_manager_(/*active_connection_id_limit*/ 2,
-                     initial_connection_id_,
-                     &clock_,
-                     &alarm_factory_,
-                     &cid_manager_visitor_) {
+      : cid_manager_(/*active_connection_id_limit*/ 2, initial_connection_id_,
+                     &clock_, &alarm_factory_, &cid_manager_visitor_,
+                     /*context=*/nullptr) {
     clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
     retire_self_issued_cid_alarm_ =
         QuicConnectionIdManagerPeer::GetRetireSelfIssuedConnectionIdAlarm(
diff --git a/quic/core/quic_dispatcher.cc b/quic/core/quic_dispatcher.cc
index a7345ea..32c508b 100644
--- a/quic/core/quic_dispatcher.cc
+++ b/quic/core/quic_dispatcher.cc
@@ -40,7 +40,7 @@
 const QuicPacketLength kMinClientInitialPacketLength = 1200;
 
 // An alarm that informs the QuicDispatcher to delete old sessions.
-class DeleteSessionsAlarm : public QuicAlarm::Delegate {
+class DeleteSessionsAlarm : public QuicAlarm::DelegateWithoutContext {
  public:
   explicit DeleteSessionsAlarm(QuicDispatcher* dispatcher)
       : dispatcher_(dispatcher) {}
diff --git a/quic/core/quic_epoll_alarm_factory_test.cc b/quic/core/quic_epoll_alarm_factory_test.cc
index e2268db..d815fae 100644
--- a/quic/core/quic_epoll_alarm_factory_test.cc
+++ b/quic/core/quic_epoll_alarm_factory_test.cc
@@ -12,7 +12,7 @@
 namespace test {
 namespace {
 
-class TestDelegate : public QuicAlarm::Delegate {
+class TestDelegate : public QuicAlarm::DelegateWithoutContext {
  public:
   TestDelegate() : fired_(false) {}
 
diff --git a/quic/core/quic_flags_list.h b/quic/core/quic_flags_list.h
index e6a430d..6c715d0 100644
--- a/quic/core/quic_flags_list.h
+++ b/quic/core/quic_flags_list.h
@@ -23,6 +23,8 @@
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_tls_set_signature_algorithm_prefs, true)
 // If true, QUIC will default enable MTU discovery at server, with a target of 1450 bytes.
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_enable_mtu_discovery_at_server, false)
+// If true, QuicAlarms that belong to a single QuicConnection will fire under the corresponding QuicConnectionContext.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_restore_connection_context_in_alarms, true)
 // If true, QuicGsoBatchWriter will support release time if it is available and the process has the permission to do so.
 QUIC_FLAG(FLAGS_quic_restart_flag_quic_support_release_time_for_gso, false)
 // If true, abort async QPACK header decompression in QuicSpdyStream::Reset() and in QuicSpdyStream::OnStreamReset().
diff --git a/quic/core/quic_idle_network_detector.cc b/quic/core/quic_idle_network_detector.cc
index 05203df..fceb1e7 100644
--- a/quic/core/quic_idle_network_detector.cc
+++ b/quic/core/quic_idle_network_detector.cc
@@ -11,10 +11,11 @@
 
 namespace {
 
-class AlarmDelegate : public QuicAlarm::Delegate {
+class AlarmDelegate : public QuicAlarm::DelegateWithContext {
  public:
-  explicit AlarmDelegate(QuicIdleNetworkDetector* detector)
-      : detector_(detector) {}
+  explicit AlarmDelegate(QuicIdleNetworkDetector* detector,
+                         QuicConnectionContext* context)
+      : QuicAlarm::DelegateWithContext(context), detector_(detector) {}
   AlarmDelegate(const AlarmDelegate&) = delete;
   AlarmDelegate& operator=(const AlarmDelegate&) = delete;
 
@@ -28,15 +29,15 @@
 
 QuicIdleNetworkDetector::QuicIdleNetworkDetector(
     Delegate* delegate, QuicTime now, QuicConnectionArena* arena,
-    QuicAlarmFactory* alarm_factory)
+    QuicAlarmFactory* alarm_factory, QuicConnectionContext* context)
     : delegate_(delegate),
       start_time_(now),
       handshake_timeout_(QuicTime::Delta::Infinite()),
       time_of_last_received_packet_(now),
       time_of_first_packet_sent_after_receiving_(QuicTime::Zero()),
       idle_network_timeout_(QuicTime::Delta::Infinite()),
-      alarm_(
-          alarm_factory->CreateAlarm(arena->New<AlarmDelegate>(this), arena)) {}
+      alarm_(alarm_factory->CreateAlarm(
+          arena->New<AlarmDelegate>(this, context), arena)) {}
 
 void QuicIdleNetworkDetector::OnAlarm() {
   if (handshake_timeout_.IsInfinite()) {
diff --git a/quic/core/quic_idle_network_detector.h b/quic/core/quic_idle_network_detector.h
index c380b0d..2381c12 100644
--- a/quic/core/quic_idle_network_detector.h
+++ b/quic/core/quic_idle_network_detector.h
@@ -36,10 +36,10 @@
     virtual void OnIdleNetworkDetected() = 0;
   };
 
-  QuicIdleNetworkDetector(Delegate* delegate,
-                          QuicTime now,
+  QuicIdleNetworkDetector(Delegate* delegate, QuicTime now,
                           QuicConnectionArena* arena,
-                          QuicAlarmFactory* alarm_factory);
+                          QuicAlarmFactory* alarm_factory,
+                          QuicConnectionContext* context);
 
   void OnAlarm();
 
diff --git a/quic/core/quic_idle_network_detector_test.cc b/quic/core/quic_idle_network_detector_test.cc
index 21549d9..a6fd5d2 100644
--- a/quic/core/quic_idle_network_detector_test.cc
+++ b/quic/core/quic_idle_network_detector_test.cc
@@ -32,7 +32,8 @@
   QuicIdleNetworkDetectorTest() {
     clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
     detector_ = std::make_unique<QuicIdleNetworkDetector>(
-        &delegate_, clock_.Now(), &arena_, &alarm_factory_);
+        &delegate_, clock_.Now(), &arena_, &alarm_factory_,
+        /*context=*/nullptr);
     alarm_ = static_cast<MockAlarmFactory::TestAlarm*>(
         QuicIdleNetworkDetectorTestPeer::GetAlarm(detector_.get()));
   }
diff --git a/quic/core/quic_network_blackhole_detector.cc b/quic/core/quic_network_blackhole_detector.cc
index 4dca508..2d9fc2d 100644
--- a/quic/core/quic_network_blackhole_detector.cc
+++ b/quic/core/quic_network_blackhole_detector.cc
@@ -10,10 +10,11 @@
 
 namespace {
 
-class AlarmDelegate : public QuicAlarm::Delegate {
+class AlarmDelegate : public QuicAlarm::DelegateWithContext {
  public:
-  explicit AlarmDelegate(QuicNetworkBlackholeDetector* detector)
-      : detector_(detector) {}
+  explicit AlarmDelegate(QuicNetworkBlackholeDetector* detector,
+                         QuicConnectionContext* context)
+      : QuicAlarm::DelegateWithContext(context), detector_(detector) {}
   AlarmDelegate(const AlarmDelegate&) = delete;
   AlarmDelegate& operator=(const AlarmDelegate&) = delete;
 
@@ -26,12 +27,11 @@
 }  // namespace
 
 QuicNetworkBlackholeDetector::QuicNetworkBlackholeDetector(
-    Delegate* delegate,
-    QuicConnectionArena* arena,
-    QuicAlarmFactory* alarm_factory)
+    Delegate* delegate, QuicConnectionArena* arena,
+    QuicAlarmFactory* alarm_factory, QuicConnectionContext* context)
     : delegate_(delegate),
-      alarm_(
-          alarm_factory->CreateAlarm(arena->New<AlarmDelegate>(this), arena)) {}
+      alarm_(alarm_factory->CreateAlarm(
+          arena->New<AlarmDelegate>(this, context), arena)) {}
 
 void QuicNetworkBlackholeDetector::OnAlarm() {
   QuicTime next_deadline = GetEarliestDeadline();
diff --git a/quic/core/quic_network_blackhole_detector.h b/quic/core/quic_network_blackhole_detector.h
index 82753f9..db52e8f 100644
--- a/quic/core/quic_network_blackhole_detector.h
+++ b/quic/core/quic_network_blackhole_detector.h
@@ -40,9 +40,9 @@
     virtual void OnPathMtuReductionDetected() = 0;
   };
 
-  QuicNetworkBlackholeDetector(Delegate* delegate,
-                               QuicConnectionArena* arena,
-                               QuicAlarmFactory* alarm_factory);
+  QuicNetworkBlackholeDetector(Delegate* delegate, QuicConnectionArena* arena,
+                               QuicAlarmFactory* alarm_factory,
+                               QuicConnectionContext* context);
 
   // Called to stop all detections. If |permanent|, the alarm will be cancelled
   // permanently and future calls to RestartDetection will be no-op.
diff --git a/quic/core/quic_network_blackhole_detector_test.cc b/quic/core/quic_network_blackhole_detector_test.cc
index 66bebfd..764ee9a 100644
--- a/quic/core/quic_network_blackhole_detector_test.cc
+++ b/quic/core/quic_network_blackhole_detector_test.cc
@@ -33,7 +33,7 @@
 class QuicNetworkBlackholeDetectorTest : public QuicTest {
  public:
   QuicNetworkBlackholeDetectorTest()
-      : detector_(&delegate_, &arena_, &alarm_factory_),
+      : detector_(&delegate_, &arena_, &alarm_factory_, /*context=*/nullptr),
         alarm_(static_cast<MockAlarmFactory::TestAlarm*>(
             QuicNetworkBlackholeDetectorPeer::GetAlarm(&detector_))),
         path_degrading_delay_(
diff --git a/quic/core/quic_one_block_arena.h b/quic/core/quic_one_block_arena.h
index 53882ea..02aae87 100644
--- a/quic/core/quic_one_block_arena.h
+++ b/quic/core/quic_one_block_arena.h
@@ -69,7 +69,7 @@
 
 // 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<1056>;
+using QuicConnectionArena = QuicOneBlockArena<1152>;
 
 }  // namespace quic
 
diff --git a/quic/core/quic_path_validator.cc b/quic/core/quic_path_validator.cc
index bb83e94..658dfef 100644
--- a/quic/core/quic_path_validator.cc
+++ b/quic/core/quic_path_validator.cc
@@ -10,10 +10,12 @@
 
 namespace quic {
 
-class RetryAlarmDelegate : public QuicAlarm::Delegate {
+class RetryAlarmDelegate : public QuicAlarm::DelegateWithContext {
  public:
-  explicit RetryAlarmDelegate(QuicPathValidator* path_validator)
-      : path_validator_(path_validator) {}
+  explicit RetryAlarmDelegate(QuicPathValidator* path_validator,
+                              QuicConnectionContext* context)
+      : QuicAlarm::DelegateWithContext(context),
+        path_validator_(path_validator) {}
   RetryAlarmDelegate(const RetryAlarmDelegate&) = delete;
   RetryAlarmDelegate& operator=(const RetryAlarmDelegate&) = delete;
 
@@ -32,12 +34,12 @@
 QuicPathValidator::QuicPathValidator(QuicAlarmFactory* alarm_factory,
                                      QuicConnectionArena* arena,
                                      SendDelegate* send_delegate,
-                                     QuicRandom* random)
+                                     QuicRandom* random,
+                                     QuicConnectionContext* context)
     : send_delegate_(send_delegate),
       random_(random),
-      retry_timer_(
-          alarm_factory->CreateAlarm(arena->New<RetryAlarmDelegate>(this),
-                                     arena)),
+      retry_timer_(alarm_factory->CreateAlarm(
+          arena->New<RetryAlarmDelegate>(this, context), arena)),
       retry_count_(0u) {}
 
 void QuicPathValidator::OnPathResponse(const QuicPathFrameBuffer& probing_data,
diff --git a/quic/core/quic_path_validator.h b/quic/core/quic_path_validator.h
index 9ea1554..9fe2cef 100644
--- a/quic/core/quic_path_validator.h
+++ b/quic/core/quic_path_validator.h
@@ -13,6 +13,7 @@
 #include "quic/core/quic_alarm_factory.h"
 #include "quic/core/quic_arena_scoped_ptr.h"
 #include "quic/core/quic_clock.h"
+#include "quic/core/quic_connection_context.h"
 #include "quic/core/quic_one_block_arena.h"
 #include "quic/core/quic_packet_writer.h"
 #include "quic/core/quic_types.h"
@@ -107,10 +108,9 @@
         std::unique_ptr<QuicPathValidationContext> context) = 0;
   };
 
-  QuicPathValidator(QuicAlarmFactory* alarm_factory,
-                    QuicConnectionArena* arena,
-                    SendDelegate* delegate,
-                    QuicRandom* random);
+  QuicPathValidator(QuicAlarmFactory* alarm_factory, QuicConnectionArena* arena,
+                    SendDelegate* delegate, QuicRandom* random,
+                    QuicConnectionContext* context);
 
   // Send PATH_CHALLENGE and start the retry timer.
   void StartPathValidation(std::unique_ptr<QuicPathValidationContext> context,
diff --git a/quic/core/quic_path_validator_test.cc b/quic/core/quic_path_validator_test.cc
index 1dfafc3..28e1259 100644
--- a/quic/core/quic_path_validator_test.cc
+++ b/quic/core/quic_path_validator_test.cc
@@ -48,11 +48,10 @@
 class QuicPathValidatorTest : public QuicTest {
  public:
   QuicPathValidatorTest()
-      : path_validator_(&alarm_factory_, &arena_, &send_delegate_, &random_),
-        context_(new MockQuicPathValidationContext(self_address_,
-                                                   peer_address_,
-                                                   effective_peer_address_,
-                                                   &writer_)),
+      : path_validator_(&alarm_factory_, &arena_, &send_delegate_, &random_,
+                        /*context=*/nullptr),
+        context_(new MockQuicPathValidationContext(
+            self_address_, peer_address_, effective_peer_address_, &writer_)),
         result_delegate_(
             new testing::StrictMock<MockQuicPathValidationResultDelegate>()) {
     clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
diff --git a/quic/core/quic_session.cc b/quic/core/quic_session.cc
index 193783a..1e07162 100644
--- a/quic/core/quic_session.cc
+++ b/quic/core/quic_session.cc
@@ -41,6 +41,12 @@
   ClosedStreamsCleanUpDelegate& operator=(const ClosedStreamsCleanUpDelegate&) =
       delete;
 
+  QuicConnectionContext* GetConnectionContext() override {
+    return (session_->connection() == nullptr)
+               ? nullptr
+               : session_->connection()->context();
+  }
+
   void OnAlarm() override { session_->CleanUpClosedStreams(); }
 
  private:
diff --git a/quic/core/quic_time_wait_list_manager.cc b/quic/core/quic_time_wait_list_manager.cc
index 69b85fa..80986a3 100644
--- a/quic/core/quic_time_wait_list_manager.cc
+++ b/quic/core/quic_time_wait_list_manager.cc
@@ -30,7 +30,7 @@
 // A very simple alarm that just informs the QuicTimeWaitListManager to clean
 // up old connection_ids. This alarm should be cancelled and deleted before
 // the QuicTimeWaitListManager is deleted.
-class ConnectionIdCleanUpAlarm : public QuicAlarm::Delegate {
+class ConnectionIdCleanUpAlarm : public QuicAlarm::DelegateWithoutContext {
  public:
   explicit ConnectionIdCleanUpAlarm(
       QuicTimeWaitListManager* time_wait_list_manager)
diff --git a/quic/test_tools/packet_dropping_test_writer.cc b/quic/test_tools/packet_dropping_test_writer.cc
index 76dd778..079b228 100644
--- a/quic/test_tools/packet_dropping_test_writer.cc
+++ b/quic/test_tools/packet_dropping_test_writer.cc
@@ -18,7 +18,7 @@
 
 // An alarm that is scheduled if a blocked socket is simulated to indicate
 // it's writable again.
-class WriteUnblockedAlarm : public QuicAlarm::Delegate {
+class WriteUnblockedAlarm : public QuicAlarm::DelegateWithoutContext {
  public:
   explicit WriteUnblockedAlarm(PacketDroppingTestWriter* writer)
       : writer_(writer) {}
@@ -34,7 +34,7 @@
 
 // An alarm that is scheduled every time a new packet is to be written at a
 // later point.
-class DelayAlarm : public QuicAlarm::Delegate {
+class DelayAlarm : public QuicAlarm::DelegateWithoutContext {
  public:
   explicit DelayAlarm(PacketDroppingTestWriter* writer) : writer_(writer) {}
 
diff --git a/quic/test_tools/simulator/queue.h b/quic/test_tools/simulator/queue.h
index 7e4be83..dd810e7 100644
--- a/quic/test_tools/simulator/queue.h
+++ b/quic/test_tools/simulator/queue.h
@@ -73,7 +73,7 @@
   };
 
   // Alarm handler for aggregation timeout.
-  class AggregationAlarmDelegate : public QuicAlarm::Delegate {
+  class AggregationAlarmDelegate : public QuicAlarm::DelegateWithoutContext {
    public:
     explicit AggregationAlarmDelegate(Queue* queue);
 
diff --git a/quic/test_tools/simulator/simulator.h b/quic/test_tools/simulator/simulator.h
index 8f31717..b4298f5 100644
--- a/quic/test_tools/simulator/simulator.h
+++ b/quic/test_tools/simulator/simulator.h
@@ -88,7 +88,7 @@
   };
 
   // The delegate used for RunFor().
-  class RunForDelegate : public QuicAlarm::Delegate {
+  class RunForDelegate : public QuicAlarm::DelegateWithoutContext {
    public:
     explicit RunForDelegate(bool* run_for_should_stop);
     void OnAlarm() override;
diff --git a/quic/test_tools/simulator/simulator_test.cc b/quic/test_tools/simulator/simulator_test.cc
index a71649e..fe84170 100644
--- a/quic/test_tools/simulator/simulator_test.cc
+++ b/quic/test_tools/simulator/simulator_test.cc
@@ -475,7 +475,7 @@
 };
 
 // Counts the number of times an alarm has fired.
-class CounterDelegate : public QuicAlarm::Delegate {
+class CounterDelegate : public QuicAlarm::DelegateWithoutContext {
  public:
   explicit CounterDelegate(size_t* counter) : counter_(counter) {}