1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors 2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file. 4*6777b538SAndroid Build Coastguard Worker 5*6777b538SAndroid Build Coastguard Worker #ifndef NET_DNS_DNS_CONFIG_SERVICE_H_ 6*6777b538SAndroid Build Coastguard Worker #define NET_DNS_DNS_CONFIG_SERVICE_H_ 7*6777b538SAndroid Build Coastguard Worker 8*6777b538SAndroid Build Coastguard Worker #include <map> 9*6777b538SAndroid Build Coastguard Worker #include <memory> 10*6777b538SAndroid Build Coastguard Worker #include <optional> 11*6777b538SAndroid Build Coastguard Worker 12*6777b538SAndroid Build Coastguard Worker #include "base/files/file_path.h" 13*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr.h" 14*6777b538SAndroid Build Coastguard Worker #include "base/memory/weak_ptr.h" 15*6777b538SAndroid Build Coastguard Worker #include "base/sequence_checker.h" 16*6777b538SAndroid Build Coastguard Worker #include "base/time/time.h" 17*6777b538SAndroid Build Coastguard Worker #include "base/timer/timer.h" 18*6777b538SAndroid Build Coastguard Worker #include "net/base/net_export.h" 19*6777b538SAndroid Build Coastguard Worker #include "net/dns/dns_config.h" 20*6777b538SAndroid Build Coastguard Worker #include "net/dns/dns_hosts.h" 21*6777b538SAndroid Build Coastguard Worker #include "net/dns/serial_worker.h" 22*6777b538SAndroid Build Coastguard Worker #include "url/gurl.h" 23*6777b538SAndroid Build Coastguard Worker 24*6777b538SAndroid Build Coastguard Worker namespace net { 25*6777b538SAndroid Build Coastguard Worker 26*6777b538SAndroid Build Coastguard Worker // Service for reading system DNS settings, on demand or when signalled by 27*6777b538SAndroid Build Coastguard Worker // internal watchers and NetworkChangeNotifier. This object is not thread-safe 28*6777b538SAndroid Build Coastguard Worker // and methods may perform blocking I/O so methods must be called on a sequence 29*6777b538SAndroid Build Coastguard Worker // that allows blocking (i.e. base::MayBlock). 30*6777b538SAndroid Build Coastguard Worker class NET_EXPORT_PRIVATE DnsConfigService { 31*6777b538SAndroid Build Coastguard Worker public: 32*6777b538SAndroid Build Coastguard Worker // Callback interface for the client, called on the same thread as 33*6777b538SAndroid Build Coastguard Worker // ReadConfig() and WatchConfig(). 34*6777b538SAndroid Build Coastguard Worker typedef base::RepeatingCallback<void(const DnsConfig& config)> CallbackType; 35*6777b538SAndroid Build Coastguard Worker 36*6777b538SAndroid Build Coastguard Worker // DHCP and user-induced changes are on the order of seconds, so 150ms should 37*6777b538SAndroid Build Coastguard Worker // not add perceivable delay. On the other hand, config readers should finish 38*6777b538SAndroid Build Coastguard Worker // within 150ms with the rare exception of I/O block or extra large HOSTS. 39*6777b538SAndroid Build Coastguard Worker static const base::TimeDelta kInvalidationTimeout; 40*6777b538SAndroid Build Coastguard Worker 41*6777b538SAndroid Build Coastguard Worker // Creates the platform-specific DnsConfigService. May return |nullptr| if 42*6777b538SAndroid Build Coastguard Worker // reading system DNS settings is not supported on the current platform. 43*6777b538SAndroid Build Coastguard Worker static std::unique_ptr<DnsConfigService> CreateSystemService(); 44*6777b538SAndroid Build Coastguard Worker 45*6777b538SAndroid Build Coastguard Worker DnsConfigService(const DnsConfigService&) = delete; 46*6777b538SAndroid Build Coastguard Worker DnsConfigService& operator=(const DnsConfigService&) = delete; 47*6777b538SAndroid Build Coastguard Worker 48*6777b538SAndroid Build Coastguard Worker virtual ~DnsConfigService(); 49*6777b538SAndroid Build Coastguard Worker 50*6777b538SAndroid Build Coastguard Worker // Attempts to read the configuration. Will run |callback| when succeeded. 51*6777b538SAndroid Build Coastguard Worker // Can be called at most once. 52*6777b538SAndroid Build Coastguard Worker void ReadConfig(const CallbackType& callback); 53*6777b538SAndroid Build Coastguard Worker 54*6777b538SAndroid Build Coastguard Worker // Registers systems watchers. Will attempt to read config after watch starts, 55*6777b538SAndroid Build Coastguard Worker // but only if watchers started successfully. Will run |callback| iff config 56*6777b538SAndroid Build Coastguard Worker // changes from last call or has to be withdrawn. Can be called at most once. 57*6777b538SAndroid Build Coastguard Worker // Might require MessageLoopForIO. 58*6777b538SAndroid Build Coastguard Worker void WatchConfig(const CallbackType& callback); 59*6777b538SAndroid Build Coastguard Worker 60*6777b538SAndroid Build Coastguard Worker // Triggers invalidation and re-read of the current configuration (followed by 61*6777b538SAndroid Build Coastguard Worker // invocation of the callback). For use only on platforms expecting 62*6777b538SAndroid Build Coastguard Worker // network-stack-external notifications of DNS config changes. 63*6777b538SAndroid Build Coastguard Worker virtual void RefreshConfig(); 64*6777b538SAndroid Build Coastguard Worker set_watch_failed_for_testing(bool watch_failed)65*6777b538SAndroid Build Coastguard Worker void set_watch_failed_for_testing(bool watch_failed) { 66*6777b538SAndroid Build Coastguard Worker watch_failed_ = watch_failed; 67*6777b538SAndroid Build Coastguard Worker } 68*6777b538SAndroid Build Coastguard Worker 69*6777b538SAndroid Build Coastguard Worker // Simulates a watcher trigger by calling OnConfigChanged(). TriggerOnConfigChangedForTesting(bool succeeded)70*6777b538SAndroid Build Coastguard Worker void TriggerOnConfigChangedForTesting(bool succeeded) { 71*6777b538SAndroid Build Coastguard Worker // Directly call ...Delayed() version to skip past delay logic. 72*6777b538SAndroid Build Coastguard Worker OnConfigChangedDelayed(succeeded); 73*6777b538SAndroid Build Coastguard Worker } 74*6777b538SAndroid Build Coastguard Worker 75*6777b538SAndroid Build Coastguard Worker protected: 76*6777b538SAndroid Build Coastguard Worker // Watcher to observe for changes to DNS config or HOSTS (via overriding 77*6777b538SAndroid Build Coastguard Worker // `Watch()` with platform specifics) and trigger necessary refreshes on 78*6777b538SAndroid Build Coastguard Worker // changes. 79*6777b538SAndroid Build Coastguard Worker class NET_EXPORT_PRIVATE Watcher { 80*6777b538SAndroid Build Coastguard Worker public: 81*6777b538SAndroid Build Coastguard Worker // `service` is expected to own the created Watcher and thus stay valid for 82*6777b538SAndroid Build Coastguard Worker // the lifetime of the created Watcher. 83*6777b538SAndroid Build Coastguard Worker explicit Watcher(DnsConfigService& service); 84*6777b538SAndroid Build Coastguard Worker virtual ~Watcher(); 85*6777b538SAndroid Build Coastguard Worker 86*6777b538SAndroid Build Coastguard Worker Watcher(const Watcher&) = delete; 87*6777b538SAndroid Build Coastguard Worker Watcher& operator=(const Watcher&) = delete; 88*6777b538SAndroid Build Coastguard Worker 89*6777b538SAndroid Build Coastguard Worker virtual bool Watch() = 0; 90*6777b538SAndroid Build Coastguard Worker 91*6777b538SAndroid Build Coastguard Worker protected: 92*6777b538SAndroid Build Coastguard Worker // Hooks for detected changes. `succeeded` false to indicate that there was 93*6777b538SAndroid Build Coastguard Worker // an error watching for the change. 94*6777b538SAndroid Build Coastguard Worker void OnConfigChanged(bool succeeded); 95*6777b538SAndroid Build Coastguard Worker void OnHostsChanged(bool succeeded); 96*6777b538SAndroid Build Coastguard Worker 97*6777b538SAndroid Build Coastguard Worker void CheckOnCorrectSequence(); 98*6777b538SAndroid Build Coastguard Worker 99*6777b538SAndroid Build Coastguard Worker private: 100*6777b538SAndroid Build Coastguard Worker // Back pointer. `this` is expected to be owned by `service_`, making this 101*6777b538SAndroid Build Coastguard Worker // raw pointer safe. 102*6777b538SAndroid Build Coastguard Worker const raw_ptr<DnsConfigService> service_; 103*6777b538SAndroid Build Coastguard Worker 104*6777b538SAndroid Build Coastguard Worker SEQUENCE_CHECKER(sequence_checker_); 105*6777b538SAndroid Build Coastguard Worker }; 106*6777b538SAndroid Build Coastguard Worker 107*6777b538SAndroid Build Coastguard Worker // Reader of HOSTS files. In this base implementation, uses standard logic 108*6777b538SAndroid Build Coastguard Worker // appropriate to most platforms to read the HOSTS file located at 109*6777b538SAndroid Build Coastguard Worker // `hosts_file_path`. 110*6777b538SAndroid Build Coastguard Worker class NET_EXPORT_PRIVATE HostsReader : public SerialWorker { 111*6777b538SAndroid Build Coastguard Worker public: 112*6777b538SAndroid Build Coastguard Worker // `service` is expected to own the created reader and thus stay valid for 113*6777b538SAndroid Build Coastguard Worker // the lifetime of the created reader. 114*6777b538SAndroid Build Coastguard Worker HostsReader(base::FilePath::StringPieceType hosts_file_path, 115*6777b538SAndroid Build Coastguard Worker DnsConfigService& service); 116*6777b538SAndroid Build Coastguard Worker ~HostsReader() override; 117*6777b538SAndroid Build Coastguard Worker 118*6777b538SAndroid Build Coastguard Worker HostsReader(const HostsReader&) = delete; 119*6777b538SAndroid Build Coastguard Worker HostsReader& operator=(const HostsReader&) = delete; 120*6777b538SAndroid Build Coastguard Worker 121*6777b538SAndroid Build Coastguard Worker protected: 122*6777b538SAndroid Build Coastguard Worker class NET_EXPORT_PRIVATE WorkItem : public SerialWorker::WorkItem { 123*6777b538SAndroid Build Coastguard Worker public: 124*6777b538SAndroid Build Coastguard Worker explicit WorkItem(std::unique_ptr<DnsHostsParser> dns_hosts_parser); 125*6777b538SAndroid Build Coastguard Worker ~WorkItem() override; 126*6777b538SAndroid Build Coastguard Worker 127*6777b538SAndroid Build Coastguard Worker // Override if needed to implement platform-specific behavior, e.g. for a 128*6777b538SAndroid Build Coastguard Worker // platform-specific HOSTS format. 129*6777b538SAndroid Build Coastguard Worker virtual std::optional<DnsHosts> ReadHosts(); 130*6777b538SAndroid Build Coastguard Worker 131*6777b538SAndroid Build Coastguard Worker // Adds any necessary additional entries to the given `DnsHosts`. Returns 132*6777b538SAndroid Build Coastguard Worker // false on failure. 133*6777b538SAndroid Build Coastguard Worker // 134*6777b538SAndroid Build Coastguard Worker // Override if needed to implement platform-specific behavior. 135*6777b538SAndroid Build Coastguard Worker virtual bool AddAdditionalHostsTo(DnsHosts& in_out_dns_hosts); 136*6777b538SAndroid Build Coastguard Worker 137*6777b538SAndroid Build Coastguard Worker // SerialWorker::WorkItem: 138*6777b538SAndroid Build Coastguard Worker void DoWork() final; 139*6777b538SAndroid Build Coastguard Worker 140*6777b538SAndroid Build Coastguard Worker private: 141*6777b538SAndroid Build Coastguard Worker friend HostsReader; 142*6777b538SAndroid Build Coastguard Worker 143*6777b538SAndroid Build Coastguard Worker std::optional<DnsHosts> hosts_; 144*6777b538SAndroid Build Coastguard Worker std::unique_ptr<DnsHostsParser> dns_hosts_parser_; 145*6777b538SAndroid Build Coastguard Worker }; 146*6777b538SAndroid Build Coastguard Worker 147*6777b538SAndroid Build Coastguard Worker // SerialWorker: 148*6777b538SAndroid Build Coastguard Worker std::unique_ptr<SerialWorker::WorkItem> CreateWorkItem() override; 149*6777b538SAndroid Build Coastguard Worker bool OnWorkFinished( 150*6777b538SAndroid Build Coastguard Worker std::unique_ptr<SerialWorker::WorkItem> work_item) final; 151*6777b538SAndroid Build Coastguard Worker 152*6777b538SAndroid Build Coastguard Worker private: 153*6777b538SAndroid Build Coastguard Worker // Raw pointer to owning DnsConfigService. This must never be accessed 154*6777b538SAndroid Build Coastguard Worker // inside DoWork(), since service may be destroyed while SerialWorker is 155*6777b538SAndroid Build Coastguard Worker // running on worker thread. 156*6777b538SAndroid Build Coastguard Worker const raw_ptr<DnsConfigService> service_; 157*6777b538SAndroid Build Coastguard Worker 158*6777b538SAndroid Build Coastguard Worker const base::FilePath hosts_file_path_; 159*6777b538SAndroid Build Coastguard Worker }; 160*6777b538SAndroid Build Coastguard Worker 161*6777b538SAndroid Build Coastguard Worker // On detecting config change, will post and wait `config_change_delay` before 162*6777b538SAndroid Build Coastguard Worker // triggering refreshes. Will trigger refreshes synchronously on nullopt. 163*6777b538SAndroid Build Coastguard Worker // Useful for platforms where multiple changes may be made and detected before 164*6777b538SAndroid Build Coastguard Worker // the config is stabilized and ready to be read. 165*6777b538SAndroid Build Coastguard Worker explicit DnsConfigService(base::FilePath::StringPieceType hosts_file_path, 166*6777b538SAndroid Build Coastguard Worker std::optional<base::TimeDelta> config_change_delay = 167*6777b538SAndroid Build Coastguard Worker base::Milliseconds(50)); 168*6777b538SAndroid Build Coastguard Worker 169*6777b538SAndroid Build Coastguard Worker // Immediately attempts to read the current configuration. 170*6777b538SAndroid Build Coastguard Worker virtual void ReadConfigNow() = 0; 171*6777b538SAndroid Build Coastguard Worker virtual void ReadHostsNow(); 172*6777b538SAndroid Build Coastguard Worker // Registers system watchers. Returns true iff succeeds. 173*6777b538SAndroid Build Coastguard Worker virtual bool StartWatching() = 0; 174*6777b538SAndroid Build Coastguard Worker 175*6777b538SAndroid Build Coastguard Worker // Called when the current config (except hosts) has changed. 176*6777b538SAndroid Build Coastguard Worker void InvalidateConfig(); 177*6777b538SAndroid Build Coastguard Worker // Called when the current hosts have changed. 178*6777b538SAndroid Build Coastguard Worker void InvalidateHosts(); 179*6777b538SAndroid Build Coastguard Worker 180*6777b538SAndroid Build Coastguard Worker // Called with new config. |config|.hosts is ignored. 181*6777b538SAndroid Build Coastguard Worker void OnConfigRead(DnsConfig config); 182*6777b538SAndroid Build Coastguard Worker // Called with new hosts. Rest of the config is assumed unchanged. 183*6777b538SAndroid Build Coastguard Worker void OnHostsRead(DnsHosts hosts); 184*6777b538SAndroid Build Coastguard Worker 185*6777b538SAndroid Build Coastguard Worker // Called when config refresh is required. `succeeded` false to indicate that 186*6777b538SAndroid Build Coastguard Worker // there was an error while watching for the change. 187*6777b538SAndroid Build Coastguard Worker void OnConfigChanged(bool succeeded); 188*6777b538SAndroid Build Coastguard Worker 189*6777b538SAndroid Build Coastguard Worker SEQUENCE_CHECKER(sequence_checker_); 190*6777b538SAndroid Build Coastguard Worker 191*6777b538SAndroid Build Coastguard Worker private: 192*6777b538SAndroid Build Coastguard Worker // The timer counts from the last Invalidate* until complete config is read. 193*6777b538SAndroid Build Coastguard Worker void StartTimer(); 194*6777b538SAndroid Build Coastguard Worker void OnTimeout(); 195*6777b538SAndroid Build Coastguard Worker // Called when the config becomes complete. Stops the timer. 196*6777b538SAndroid Build Coastguard Worker void OnCompleteConfig(); 197*6777b538SAndroid Build Coastguard Worker 198*6777b538SAndroid Build Coastguard Worker // Hooks for Watcher change notifications. `succeeded` false to indicate that 199*6777b538SAndroid Build Coastguard Worker // there was an error watching for the change. 200*6777b538SAndroid Build Coastguard Worker void OnHostsChanged(bool succeeded); 201*6777b538SAndroid Build Coastguard Worker void OnConfigChangedDelayed(bool succeeded); 202*6777b538SAndroid Build Coastguard Worker 203*6777b538SAndroid Build Coastguard Worker CallbackType callback_; 204*6777b538SAndroid Build Coastguard Worker 205*6777b538SAndroid Build Coastguard Worker DnsConfig dns_config_; 206*6777b538SAndroid Build Coastguard Worker 207*6777b538SAndroid Build Coastguard Worker // True if any of the necessary watchers failed. In that case, the service 208*6777b538SAndroid Build Coastguard Worker // will communicate changes via OnTimeout, but will only send empty DnsConfig. 209*6777b538SAndroid Build Coastguard Worker bool watch_failed_ = false; 210*6777b538SAndroid Build Coastguard Worker // True after On*Read, before Invalidate*. Tells if the config is complete. 211*6777b538SAndroid Build Coastguard Worker bool have_config_ = false; 212*6777b538SAndroid Build Coastguard Worker bool have_hosts_ = false; 213*6777b538SAndroid Build Coastguard Worker // True if receiver needs to be updated when the config becomes complete. 214*6777b538SAndroid Build Coastguard Worker bool need_update_ = false; 215*6777b538SAndroid Build Coastguard Worker // True if the last config sent was empty (instead of |dns_config_|). 216*6777b538SAndroid Build Coastguard Worker // Set when |timer_| expires. 217*6777b538SAndroid Build Coastguard Worker bool last_sent_empty_ = true; 218*6777b538SAndroid Build Coastguard Worker 219*6777b538SAndroid Build Coastguard Worker const std::optional<base::TimeDelta> config_change_delay_; 220*6777b538SAndroid Build Coastguard Worker const base::FilePath hosts_file_path_; 221*6777b538SAndroid Build Coastguard Worker 222*6777b538SAndroid Build Coastguard Worker // Created only if needed in ReadHostsNow() to avoid creating unnecessarily if 223*6777b538SAndroid Build Coastguard Worker // overridden for a platform-specific implementation. 224*6777b538SAndroid Build Coastguard Worker std::unique_ptr<HostsReader> hosts_reader_; 225*6777b538SAndroid Build Coastguard Worker 226*6777b538SAndroid Build Coastguard Worker // Started in Invalidate*, cleared in On*Read. 227*6777b538SAndroid Build Coastguard Worker base::OneShotTimer timer_; 228*6777b538SAndroid Build Coastguard Worker 229*6777b538SAndroid Build Coastguard Worker base::WeakPtrFactory<DnsConfigService> weak_factory_{this}; 230*6777b538SAndroid Build Coastguard Worker }; 231*6777b538SAndroid Build Coastguard Worker 232*6777b538SAndroid Build Coastguard Worker } // namespace net 233*6777b538SAndroid Build Coastguard Worker 234*6777b538SAndroid Build Coastguard Worker #endif // NET_DNS_DNS_CONFIG_SERVICE_H_ 235