summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chromium/third_party/blink/renderer/platform/network/network_state_notifier.cc10
-rw-r--r--chromium/third_party/blink/renderer/platform/network/network_state_notifier_test.cc47
2 files changed, 55 insertions, 2 deletions
diff --git a/chromium/third_party/blink/renderer/platform/network/network_state_notifier.cc b/chromium/third_party/blink/renderer/platform/network/network_state_notifier.cc
index 32328e88187..c7227f63483 100644
--- a/chromium/third_party/blink/renderer/platform/network/network_state_notifier.cc
+++ b/chromium/third_party/blink/renderer/platform/network/network_state_notifier.cc
@@ -395,8 +395,14 @@ void NetworkStateNotifier::CollectZeroedObservers(
// If any observers were removed during the iteration they will have
// 0 values, clean them up.
- for (wtf_size_t i = 0; i < list->zeroed_observers.size(); ++i)
- list->observers.EraseAt(list->zeroed_observers[i]);
+ std::sort(list->zeroed_observers.begin(), list->zeroed_observers.end());
+ int removed = 0;
+ for (wtf_size_t i = 0; i < list->zeroed_observers.size(); ++i) {
+ int index_to_remove = list->zeroed_observers[i] - removed;
+ DCHECK_EQ(nullptr, list->observers[index_to_remove]);
+ list->observers.EraseAt(index_to_remove);
+ removed += 1;
+ }
list->zeroed_observers.clear();
diff --git a/chromium/third_party/blink/renderer/platform/network/network_state_notifier_test.cc b/chromium/third_party/blink/renderer/platform/network/network_state_notifier_test.cc
index eb2bd791529..f7c359235a8 100644
--- a/chromium/third_party/blink/renderer/platform/network/network_state_notifier_test.cc
+++ b/chromium/third_party/blink/renderer/platform/network/network_state_notifier_test.cc
@@ -528,6 +528,53 @@ TEST_F(NetworkStateNotifierTest, RemoveFutureObserverWhileNotifying) {
kUnknownThroughputMbps, SaveData::kOff));
}
+// It should be safe to remove multiple observers in one iteration.
+TEST_F(NetworkStateNotifierTest, RemoveMultipleObserversWhileNotifying) {
+ StateObserver observer1, observer2, observer3;
+ std::unique_ptr<NetworkStateNotifier::NetworkStateObserverHandle> handle1 =
+ notifier_.AddConnectionObserver(&observer1, GetTaskRunner());
+ std::unique_ptr<NetworkStateNotifier::NetworkStateObserverHandle> handle2 =
+ notifier_.AddConnectionObserver(&observer2, GetTaskRunner());
+ std::unique_ptr<NetworkStateNotifier::NetworkStateObserverHandle> handle3 =
+ notifier_.AddConnectionObserver(&observer3, GetTaskRunner());
+ observer1.RemoveObserverOnNotification(std::move(handle1));
+ observer3.RemoveObserverOnNotification(std::move(handle3));
+
+ // Running the first time should delete observers 1 and 3.
+ SetConnection(kWebConnectionTypeBluetooth, kBluetoothMaxBandwidthMbps,
+ WebEffectiveConnectionType::kTypeUnknown, kUnknownRtt,
+ kUnknownRtt, kUnknownThroughputMbps, SaveData::kOff);
+ EXPECT_TRUE(VerifyObservations(
+ observer1, kWebConnectionTypeBluetooth, kBluetoothMaxBandwidthMbps,
+ WebEffectiveConnectionType::kTypeUnknown, kUnknownRtt, kUnknownRtt,
+ kUnknownThroughputMbps, SaveData::kOff));
+ EXPECT_TRUE(VerifyObservations(
+ observer2, kWebConnectionTypeBluetooth, kBluetoothMaxBandwidthMbps,
+ WebEffectiveConnectionType::kTypeUnknown, kUnknownRtt, kUnknownRtt,
+ kUnknownThroughputMbps, SaveData::kOff));
+ EXPECT_TRUE(VerifyObservations(
+ observer3, kWebConnectionTypeBluetooth, kBluetoothMaxBandwidthMbps,
+ WebEffectiveConnectionType::kTypeUnknown, kUnknownRtt, kUnknownRtt,
+ kUnknownThroughputMbps, SaveData::kOff));
+
+ // Run again and only observer 2 should have been updated.
+ SetConnection(kWebConnectionTypeEthernet, kEthernetMaxBandwidthMbps,
+ WebEffectiveConnectionType::kTypeUnknown, kUnknownRtt,
+ kUnknownRtt, kUnknownThroughputMbps, SaveData::kOff);
+ EXPECT_TRUE(VerifyObservations(
+ observer1, kWebConnectionTypeBluetooth, kBluetoothMaxBandwidthMbps,
+ WebEffectiveConnectionType::kTypeUnknown, kUnknownRtt, kUnknownRtt,
+ kUnknownThroughputMbps, SaveData::kOff));
+ EXPECT_TRUE(VerifyObservations(
+ observer2, kWebConnectionTypeEthernet, kEthernetMaxBandwidthMbps,
+ WebEffectiveConnectionType::kTypeUnknown, kUnknownRtt, kUnknownRtt,
+ kUnknownThroughputMbps, SaveData::kOff));
+ EXPECT_TRUE(VerifyObservations(
+ observer3, kWebConnectionTypeBluetooth, kBluetoothMaxBandwidthMbps,
+ WebEffectiveConnectionType::kTypeUnknown, kUnknownRtt, kUnknownRtt,
+ kUnknownThroughputMbps, SaveData::kOff));
+}
+
TEST_F(NetworkStateNotifierTest, MultipleContextsAddObserver) {
StateObserver observer1, observer2;
std::unique_ptr<NetworkStateNotifier::NetworkStateObserverHandle> handle1 =