Adds a WindowManager constructor parameter to disable automatic updates to internal window state.

By default, internal window state is updated when invoking the WindowUpdateListener. The `oghttp2` library needs the capability to disable this behavior.

PiperOrigin-RevId: 429263683
diff --git a/http2/adapter/window_manager.cc b/http2/adapter/window_manager.cc
index 76bde18..3dd9baf 100644
--- a/http2/adapter/window_manager.cc
+++ b/http2/adapter/window_manager.cc
@@ -9,11 +9,13 @@
 namespace adapter {
 
 WindowManager::WindowManager(int64_t window_size_limit,
-                             WindowUpdateListener listener)
+                             WindowUpdateListener listener,
+                             bool update_window_on_notify)
     : limit_(window_size_limit),
       window_(window_size_limit),
       buffered_(0),
-      listener_(std::move(listener)) {}
+      listener_(std::move(listener)),
+      update_window_on_notify_(update_window_on_notify) {}
 
 void WindowManager::OnWindowSizeLimitChange(const int64_t new_limit) {
   QUICHE_VLOG(2) << "WindowManager@" << this
@@ -82,7 +84,9 @@
     QUICHE_VLOG(2) << "WindowManager@" << this
                    << " Informing listener of delta: " << delta;
     listener_(delta);
-    window_ += delta;
+    if (update_window_on_notify_) {
+      window_ += delta;
+    }
   }
 }
 
diff --git a/http2/adapter/window_manager.h b/http2/adapter/window_manager.h
index f4ee23f..45a6ddd 100644
--- a/http2/adapter/window_manager.h
+++ b/http2/adapter/window_manager.h
@@ -21,7 +21,8 @@
   // A WindowUpdateListener is invoked when it is time to send a window update.
   typedef std::function<void(int64_t)> WindowUpdateListener;
 
-  WindowManager(int64_t window_size_limit, WindowUpdateListener listener);
+  WindowManager(int64_t window_size_limit, WindowUpdateListener listener,
+                bool update_window_on_notify = true);
 
   int64_t CurrentWindowSize() const { return window_; }
   int64_t WindowSizeLimit() const { return limit_; }
@@ -73,6 +74,8 @@
   int64_t buffered_;
 
   WindowUpdateListener listener_;
+
+  bool update_window_on_notify_;
 };
 
 }  // namespace adapter
diff --git a/http2/adapter/window_manager_test.cc b/http2/adapter/window_manager_test.cc
index 191ebe9..c5a9ffb 100644
--- a/http2/adapter/window_manager_test.cc
+++ b/http2/adapter/window_manager_test.cc
@@ -208,6 +208,61 @@
   EXPECT_EQ(wm_.CurrentWindowSize(), kDefaultLimit - 1000);
 }
 
+// This test verifies that when the constructor option is specified,
+// WindowManager does not update its internal accounting of the flow control
+// window when notifying the listener.
+TEST(WindowManagerNoUpdateTest, NoWindowUpdateOnListener) {
+  const int64_t kDefaultLimit = 65535;
+
+  std::list<int64_t> call_sequence1;
+  WindowManager wm1(
+      kDefaultLimit,
+      [&call_sequence1](int64_t delta) { call_sequence1.push_back(delta); },
+      /*update_window_on_notify=*/true);  // default
+  std::list<int64_t> call_sequence2;
+  WindowManager wm2(
+      kDefaultLimit,
+      [&call_sequence2](int64_t delta) { call_sequence2.push_back(delta); },
+      /*update_window_on_notify=*/false);
+
+  const int64_t consumed = kDefaultLimit / 3 - 1;
+
+  wm1.MarkWindowConsumed(consumed);
+  EXPECT_TRUE(call_sequence1.empty());
+  wm2.MarkWindowConsumed(consumed);
+  EXPECT_TRUE(call_sequence2.empty());
+
+  EXPECT_EQ(wm1.CurrentWindowSize(), kDefaultLimit - consumed);
+  EXPECT_EQ(wm2.CurrentWindowSize(), kDefaultLimit - consumed);
+
+  const int64_t extra = 1;
+  wm1.MarkWindowConsumed(extra);
+  EXPECT_THAT(call_sequence1, testing::ElementsAre(consumed + extra));
+  // Window size *is* updated after invoking the listener.
+  EXPECT_EQ(wm1.CurrentWindowSize(), kDefaultLimit);
+  call_sequence1.clear();
+
+  wm2.MarkWindowConsumed(extra);
+  EXPECT_THAT(call_sequence2, testing::ElementsAre(consumed + extra));
+  // Window size is *not* updated after invoking the listener.
+  EXPECT_EQ(wm2.CurrentWindowSize(), kDefaultLimit - (consumed + extra));
+  call_sequence2.clear();
+
+  // Manually increase the window by the listener notification amount.
+  wm2.IncreaseWindow(consumed + extra);
+  EXPECT_EQ(wm2.CurrentWindowSize(), kDefaultLimit);
+
+  wm1.SetWindowSizeLimit(kDefaultLimit * 5);
+  EXPECT_THAT(call_sequence1, testing::ElementsAre(kDefaultLimit * 4));
+  // *Does* update the window size.
+  EXPECT_EQ(wm1.CurrentWindowSize(), kDefaultLimit * 5);
+
+  wm2.SetWindowSizeLimit(kDefaultLimit * 5);
+  EXPECT_THAT(call_sequence2, testing::ElementsAre(kDefaultLimit * 4));
+  // Does *not* update the window size.
+  EXPECT_EQ(wm2.CurrentWindowSize(), kDefaultLimit);
+}
+
 }  // namespace
 }  // namespace test
 }  // namespace adapter