• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2024 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef NET_BASE_NETWORK_COST_CHANGE_NOTIFIER_WIN_H_
6 #define NET_BASE_NETWORK_COST_CHANGE_NOTIFIER_WIN_H_
7 
8 #include <netlistmgr.h>
9 #include <wrl/client.h>
10 
11 #include "base/functional/callback_forward.h"
12 #include "base/memory/weak_ptr.h"
13 #include "base/sequence_checker.h"
14 #include "base/threading/sequence_bound.h"
15 #include "base/win/windows_version.h"
16 #include "net/base/net_export.h"
17 #include "net/base/network_change_notifier.h"
18 
19 namespace net {
20 class NetworkCostManagerEventSinkWin;
21 
22 // Uses the `INetworkCostManager` Windows OS API to monitor the cost of the
23 // current connection.  `INetworkCostManager` performs blocking IO and
24 // synchronous RPC, which must be accessed through a thread pool worker thread.
25 // `NetworkCostChangeNotifierWin` uses `base::SequenceBound` to prevent these
26 // expensive operations from happening on the UI thread.
27 class NET_EXPORT_PRIVATE NetworkCostChangeNotifierWin final {
28  public:
29   // `INetworkCostManager` requires Windows Build 19041 or higher.  On prior
30   // builds, calls to the Windows OS API `IConnectionPoint::Advise()` may hang.
31   static constexpr base::win::Version kSupportedOsVersion =
32       base::win::Version::WIN10_20H1;
33 
34   using CostChangedCallback =
35       base::RepeatingCallback<void(NetworkChangeNotifier::ConnectionCost)>;
36 
37   // Constructs a new instance using a COM STA single threaded task runner.
38   // Posts the task that subscribes to cost change events using Windows OS APIs.
39   static base::SequenceBound<NetworkCostChangeNotifierWin> CreateInstance(
40       CostChangedCallback cost_changed_callback);
41 
42   // Use `CreateInstance()` above.  This constructor is public for use by
43   // `base::SequenceBound` only.
44   explicit NetworkCostChangeNotifierWin(
45       CostChangedCallback cost_changed_callback);
46   ~NetworkCostChangeNotifierWin();
47 
48   // Tests use this hook to provide a fake implementation of the OS APIs.
49   // The fake implementation enables tests to simulate different network
50   // conditions.
51   using CoCreateInstanceCallback = base::RepeatingCallback<
52       HRESULT(REFCLSID, LPUNKNOWN, DWORD, REFIID, LPVOID*)>;
53   static void OverrideCoCreateInstanceForTesting(
54       CoCreateInstanceCallback callback_for_testing);
55 
56   NetworkCostChangeNotifierWin(const NetworkCostChangeNotifierWin&) = delete;
57   NetworkCostChangeNotifierWin& operator=(const NetworkCostChangeNotifierWin&) =
58       delete;
59 
60  private:
61   // Creates `INetworkCostManager` for `cost_manager_` and subscribe to cost
62   // change events.
63   void StartWatching();
64 
65   // Stops monitoring the cost of the current connection by unsubscribing to
66   // `INetworkCostManager` events and releasing all members.
67   void StopWatching();
68 
69   // Gets the current cost from `cost_manager_` and then runs
70   // `cost_changed_callback_`.
71   void HandleCostChanged();
72 
73   // All members must be accessed on the sequence from `sequence_checker_`
74   SEQUENCE_CHECKER(sequence_checker_);
75 
76   CostChangedCallback cost_changed_callback_;
77 
78   Microsoft::WRL::ComPtr<INetworkCostManager> cost_manager_;
79 
80   Microsoft::WRL::ComPtr<NetworkCostManagerEventSinkWin>
81       cost_manager_event_sink_;
82 
83   base::WeakPtrFactory<NetworkCostChangeNotifierWin> weak_ptr_factory_{this};
84 };
85 
86 }  // namespace net
87 
88 #endif  // NET_BASE_NETWORK_COST_CHANGE_NOTIFIER_WIN_H_
89