// Copyright 2024 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef NET_BASE_NETWORK_COST_CHANGE_NOTIFIER_WIN_H_ #define NET_BASE_NETWORK_COST_CHANGE_NOTIFIER_WIN_H_ #include #include #include "base/functional/callback_forward.h" #include "base/memory/weak_ptr.h" #include "base/sequence_checker.h" #include "base/threading/sequence_bound.h" #include "base/win/windows_version.h" #include "net/base/net_export.h" #include "net/base/network_change_notifier.h" namespace net { class NetworkCostManagerEventSinkWin; // Uses the `INetworkCostManager` Windows OS API to monitor the cost of the // current connection. `INetworkCostManager` performs blocking IO and // synchronous RPC, which must be accessed through a thread pool worker thread. // `NetworkCostChangeNotifierWin` uses `base::SequenceBound` to prevent these // expensive operations from happening on the UI thread. class NET_EXPORT_PRIVATE NetworkCostChangeNotifierWin final { public: // `INetworkCostManager` requires Windows Build 19041 or higher. On prior // builds, calls to the Windows OS API `IConnectionPoint::Advise()` may hang. static constexpr base::win::Version kSupportedOsVersion = base::win::Version::WIN10_20H1; using CostChangedCallback = base::RepeatingCallback; // Constructs a new instance using a COM STA single threaded task runner. // Posts the task that subscribes to cost change events using Windows OS APIs. static base::SequenceBound CreateInstance( CostChangedCallback cost_changed_callback); // Use `CreateInstance()` above. This constructor is public for use by // `base::SequenceBound` only. explicit NetworkCostChangeNotifierWin( CostChangedCallback cost_changed_callback); ~NetworkCostChangeNotifierWin(); // Tests use this hook to provide a fake implementation of the OS APIs. // The fake implementation enables tests to simulate different network // conditions. using CoCreateInstanceCallback = base::RepeatingCallback< HRESULT(REFCLSID, LPUNKNOWN, DWORD, REFIID, LPVOID*)>; static void OverrideCoCreateInstanceForTesting( CoCreateInstanceCallback callback_for_testing); NetworkCostChangeNotifierWin(const NetworkCostChangeNotifierWin&) = delete; NetworkCostChangeNotifierWin& operator=(const NetworkCostChangeNotifierWin&) = delete; private: // Creates `INetworkCostManager` for `cost_manager_` and subscribe to cost // change events. void StartWatching(); // Stops monitoring the cost of the current connection by unsubscribing to // `INetworkCostManager` events and releasing all members. void StopWatching(); // Gets the current cost from `cost_manager_` and then runs // `cost_changed_callback_`. void HandleCostChanged(); // All members must be accessed on the sequence from `sequence_checker_` SEQUENCE_CHECKER(sequence_checker_); CostChangedCallback cost_changed_callback_; Microsoft::WRL::ComPtr cost_manager_; Microsoft::WRL::ComPtr cost_manager_event_sink_; base::WeakPtrFactory weak_ptr_factory_{this}; }; } // namespace net #endif // NET_BASE_NETWORK_COST_CHANGE_NOTIFIER_WIN_H_