diff --git a/net/base/net_error_details.h b/net/base/net_error_details.h index 3da3f325aa7e1407ec8055850dc89d3178345579..41e778b9a6db9e8fc9b563d7ebd7d35f3c403deb 100644 --- a/net/base/net_error_details.h +++ b/net/base/net_error_details.h @@ -35,6 +35,9 @@ struct NET_EXPORT NetErrorDetails { bool quic_port_migration_detected = false; bool quic_connection_migration_attempted = false; bool quic_connection_migration_successful = false; +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + bool stream_created = false; +#endif // OHOS_EX_HTTP_DNS_FALLBACK }; } // namespace net diff --git a/net/base/network_change_notifier.cc b/net/base/network_change_notifier.cc index d2ffefb8a3155d7ff07a54fafa62baffee3b11ee..0c48c1a929843248862ad472c26501c13fb34e2e 100644 --- a/net/base/network_change_notifier.cc +++ b/net/base/network_change_notifier.cc @@ -1108,4 +1108,22 @@ NetworkChangeNotifier::ObserverList& NetworkChangeNotifier::GetObserverList() { return *observers; } +#if BUILDFLAG(IS_OHOS) +#ifdef OHOS_EX_HTTP_DNS_FALLBACK +// static +const std::vector NetworkChangeNotifier::GetDnsServers() { + std::vector dns_servers; + if (!g_network_change_notifier) { + return dns_servers; + } + dns_servers = g_network_change_notifier->GetCurrentDnsServers(); + return dns_servers; +} + +const std::vector NetworkChangeNotifier::GetCurrentDnsServers() { + return std::vector(); +} +#endif +#endif + } // namespace net diff --git a/net/base/network_change_notifier.h b/net/base/network_change_notifier.h index 89d1036af0dd1785c5ee86355978fcb4aa0d9496..fd1239ee9de41fe24f422b346d824e12a8be5bc1 100644 --- a/net/base/network_change_notifier.h +++ b/net/base/network_change_notifier.h @@ -568,6 +568,12 @@ class NET_EXPORT NetworkChangeNotifier { // Returns a string equivalent to |type|. static const char* ConnectionTypeToString(ConnectionType type); +#if BUILDFLAG(IS_OHOS) +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + static const std::vector GetDnsServers(); +#endif +#endif + // Allows a second NetworkChangeNotifier to be created for unit testing, so // the test suite can create a MockNetworkChangeNotifier, but platform // specific NetworkChangeNotifiers can also be created for testing. To use, @@ -657,6 +663,11 @@ class NET_EXPORT NetworkChangeNotifier { virtual SystemDnsConfigChangeNotifier* GetCurrentSystemDnsConfigNotifier(); virtual bool IsDefaultNetworkActiveInternal(); +#if BUILDFLAG(IS_OHOS) +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + virtual const std::vector GetCurrentDnsServers(); +#endif +#endif // Broadcasts a notification to all registered observers. Note that this // happens asynchronously, even for observers on the current thread, even in diff --git a/net/base/network_change_notifier_passive.cc b/net/base/network_change_notifier_passive.cc index 80d08983093af841f24f5b7092821839ff60dafd..cfd3efed46132a264c9ac1948ec8f2ced3acc964 100644 --- a/net/base/network_change_notifier_passive.cc +++ b/net/base/network_change_notifier_passive.cc @@ -27,6 +27,9 @@ #if BUILDFLAG(IS_OHOS) #include "base/logging.h" +#ifdef OHOS_EX_HTTP_DNS_FALLBACK +#include "net/dns/public/dns_protocol.h" +#endif #endif namespace { @@ -247,6 +250,18 @@ void NetworkChangeNotifierPassive::OnConnectionChanged( base::AutoLock scoped_lock(lock_); connection_type_ = connection_type; } + +#if BUILDFLAG(IS_OHOS) && defined(OHOS_EX_HTTP_DNS_FALLBACK) + std::vector dns_servers; + if (ohos_net_conn_adapter_) { + dns_servers = ohos_net_conn_adapter_->GetDnsServers(); + } + { + base::AutoLock scoped_lock(dns_server_lock_); + dns_servers_ = std::move(dns_servers); + } +#endif + NetworkChangeNotifier::NotifyObserversOfConnectionTypeChange(); } @@ -306,4 +321,12 @@ NetworkChangeNotifierPassive::NetworkChangeCalculatorParamsPassive() { return params; } +#if BUILDFLAG(IS_OHOS) && defined(OHOS_EX_HTTP_DNS_FALLBACK) +const std::vector +NetworkChangeNotifierPassive::GetCurrentDnsServers() { + base::AutoLock scoped_lock(dns_server_lock_); + return dns_servers_; +} +#endif + } // namespace net diff --git a/net/base/network_change_notifier_passive.h b/net/base/network_change_notifier_passive.h index a12c10ead18b82bfe7e6b4b620698941f00d3e04..820a10b01804ff29b6570f87fa56a40ec8c7207b 100644 --- a/net/base/network_change_notifier_passive.h +++ b/net/base/network_change_notifier_passive.h @@ -49,6 +49,10 @@ class NET_EXPORT NetworkChangeNotifierPassive : public NetworkChangeNotifier { NetworkChangeNotifier::ConnectionType connection_type, NetworkChangeNotifier::ConnectionSubtype connection_subtype); +#if BUILDFLAG(IS_OHOS) && defined(OHOS_EX_HTTP_DNS_FALLBACK) + const std::vector GetCurrentDnsServers() override; +#endif + protected: // NetworkChangeNotifier overrides. NetworkChangeNotifier::ConnectionType GetCurrentConnectionType() @@ -89,6 +93,11 @@ class NET_EXPORT NetworkChangeNotifierPassive : public NetworkChangeNotifier { std::unique_ptr ohos_net_conn_adapter_; #endif double max_bandwidth_mbps_; // Guarded by |lock_|. + +#if BUILDFLAG(IS_OHOS) && defined(OHOS_EX_HTTP_DNS_FALLBACK) + mutable base::Lock dns_server_lock_; + std::vector dns_servers_; +#endif }; } // namespace net diff --git a/net/dns/BUILD.gn b/net/dns/BUILD.gn index 533f53434ebd640cd5864726fd474ebae6dfdfcc..8a510ca81fe5c87b7039bbe9a4899849c7ced6ec 100644 --- a/net/dns/BUILD.gn +++ b/net/dns/BUILD.gn @@ -129,6 +129,12 @@ source_set("dns") { "dns_config_service_linux.cc", "dns_config_service_linux.h", ] + } else if (is_ohos && defined(ohos_ex_http_dns_fallback) && + ohos_ex_http_dns_fallback) { + sources += [ + "dns_config_service_ohos.cc", + "dns_config_service_ohos.h", + ] } else if (is_posix) { sources += [ "dns_config_service_posix.cc", diff --git a/net/dns/context_host_resolver.cc b/net/dns/context_host_resolver.cc index aa5d8cc3c04bbae64219ecc6540a2bb65a36bf34..5980b4ef17376c9ddd16b1e204b87a5c6628f377 100644 --- a/net/dns/context_host_resolver.cc +++ b/net/dns/context_host_resolver.cc @@ -169,4 +169,13 @@ void ContextHostResolver::SetTickClockForTesting( resolve_context_->host_cache()->set_tick_clock_for_testing(tick_clock); } +#ifdef OHOS_EX_HTTP_DNS_FALLBACK +bool ContextHostResolver::CanUseSecureDnsFallback() const { + if (!manager_) { + return false; + } + return manager_->CanUseSecureDnsFallback(resolve_context_.get()); +} +#endif + } // namespace net diff --git a/net/dns/context_host_resolver.h b/net/dns/context_host_resolver.h index 1e8c1352ca27ad75d0a4e2c93ff097ee7c09fe53..97c63f776a6e954b5c439cc03976bd5346687852 100644 --- a/net/dns/context_host_resolver.h +++ b/net/dns/context_host_resolver.h @@ -89,6 +89,10 @@ class NET_EXPORT ContextHostResolver : public HostResolver { return resolve_context_.get(); } +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + bool CanUseSecureDnsFallback() const override; +#endif + private: std::unique_ptr owned_manager_; // `manager_` might point to `owned_manager_`. It must be declared last and diff --git a/net/dns/dns_client.cc b/net/dns/dns_client.cc index db550a7b6ed01d4015dc3daec32b8a637a7e58e6..8b788afa64d2dd0d72bf860ff1f04511c2e6a238 100644 --- a/net/dns/dns_client.cc +++ b/net/dns/dns_client.cc @@ -99,6 +99,17 @@ class DnsClientImpl : public DnsClient { return config && !config->doh_config.servers().empty(); } +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + bool CanUseSecureDnsFallbackTransactions( + ResolveContext* context) const override { + if (context->IsHttpsDnsFallbackEnabled() && + CanUseSecureDnsTransactions()) { + return context->NumAvailableDohServers(session_.get()) > 0; + } + return false; + } +#endif + bool CanUseInsecureDnsTransactions() const override { const DnsConfig* config = GetEffectiveConfig(); return config && config->nameservers.size() > 0 && insecure_enabled_ && diff --git a/net/dns/dns_client.h b/net/dns/dns_client.h index 25dc4d94450fbc0b9ac265ebbbc13af49e9cfe99..3489ed7de1b3e77757dc311f3162b2d229e93c81 100644 --- a/net/dns/dns_client.h +++ b/net/dns/dns_client.h @@ -45,6 +45,11 @@ class NET_EXPORT DnsClient { // probe runners should not be created. virtual bool CanUseSecureDnsTransactions() const = 0; +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + virtual bool CanUseSecureDnsFallbackTransactions( + ResolveContext* context) const = 0; +#endif + // Returns true if the DnsClient is able and allowed to make insecure DNS // transactions. If false, insecure transactions should not be created. Will // always be false unless SetInsecureEnabled(true) has been called. diff --git a/net/dns/dns_config_service_ohos.cc b/net/dns/dns_config_service_ohos.cc new file mode 100644 index 0000000000000000000000000000000000000000..6cd913f30f1b2f18f4f96c56facde6b2c5b409fb --- /dev/null +++ b/net/dns/dns_config_service_ohos.cc @@ -0,0 +1,166 @@ +// Copyright 2021 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/dns/dns_config_service_ohos.h" + +#include "base/files/file_path.h" +#include "base/functional/bind.h" +#include "base/logging.h" +#include "base/memory/raw_ptr.h" +#include "base/sequence_checker.h" +#include "base/time/time.h" +#include "net/base/address_tracker_linux.h" +#include "net/base/ip_address.h" +#include "net/base/ip_endpoint.h" +#include "net/base/network_change_notifier.h" +#include "net/base/network_interfaces.h" +#include "net/dns/dns_config.h" +#include "net/dns/dns_config_service.h" +#include "net/dns/public/dns_protocol.h" +#include "net/dns/serial_worker.h" +#include "third_party/abseil-cpp/absl/types/optional.h" + +namespace net { +namespace internal { + +namespace { + +constexpr base::FilePath::CharType kFilePathHosts[] = + FILE_PATH_LITERAL("/etc/hosts"); +} // namespace + +// static +constexpr base::TimeDelta DnsConfigServiceOhos::kConfigChangeDelay; + +class DnsConfigServiceOhos::Watcher + : public DnsConfigService::Watcher, + public NetworkChangeNotifier::NetworkChangeObserver { + public: + explicit Watcher(DnsConfigServiceOhos& service) + : DnsConfigService::Watcher(service) {} + ~Watcher() override { + NetworkChangeNotifier::RemoveNetworkChangeObserver(this); + } + + Watcher(const Watcher&) = delete; + Watcher& operator=(const Watcher&) = delete; + + // DnsConfigService::Watcher: + bool Watch() override { + CheckOnCorrectSequence(); + + // On Harmony, assume DNS config may have changed on every network change. + NetworkChangeNotifier::AddNetworkChangeObserver(this); + return true; + } + + // NetworkChangeNotifier::NetworkChangeObserver: + void OnNetworkChanged(NetworkChangeNotifier::ConnectionType type) override { + if (type != NetworkChangeNotifier::CONNECTION_NONE) { + OnConfigChanged(true); + } + } +}; + +class DnsConfigServiceOhos::ConfigReader : public SerialWorker { + public: + explicit ConfigReader(DnsConfigServiceOhos& service) + : service_(&service) {} + + ~ConfigReader() override = default; + + ConfigReader(const ConfigReader&) = delete; + ConfigReader& operator=(const ConfigReader&) = delete; + + std::unique_ptr CreateWorkItem() override { + return std::make_unique(); + } + + bool OnWorkFinished(std::unique_ptr + serial_worker_work_item) override { + DCHECK(serial_worker_work_item); + DCHECK(!IsCancelled()); + + WorkItem* work_item = static_cast(serial_worker_work_item.get()); + if (work_item->dns_config_.has_value()) { + service_->OnConfigRead(std::move(work_item->dns_config_).value()); + return true; + } else { + LOG(WARNING) << "Failed to read DnsConfig."; + return false; + } + } + + private: + class WorkItem : public SerialWorker::WorkItem { + public: + explicit WorkItem() {} + + void DoWork() override { + dns_config_.emplace(); + dns_config_->unhandled_options = false; + std::vector servers = NetworkChangeNotifier::GetDnsServers(); + for (auto &server : servers) { + if (server.empty()) { + continue; + } + + auto dns_address = IPAddress::FromIPLiteral(server); + if (!dns_address || (*dns_address).empty()) { + continue; + } + IPEndPoint dns_server(std::move(*dns_address), dns_protocol::kDefaultPort); + dns_config_->nameservers.push_back(dns_server); + LOG(INFO) << "dns name server " << dns_server.ToString(); + } + } + + private: + friend class ConfigReader; + absl::optional dns_config_; + }; + + // Raw pointer to owning DnsConfigService. + const raw_ptr service_; +}; + +DnsConfigServiceOhos::DnsConfigServiceOhos() + : DnsConfigService(kFilePathHosts, kConfigChangeDelay) { + // Allow constructing on one thread and living on another. + DETACH_FROM_SEQUENCE(sequence_checker_); +} + +DnsConfigServiceOhos::~DnsConfigServiceOhos() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (config_reader_) + config_reader_->Cancel(); +} + +void DnsConfigServiceOhos::RefreshConfig() { + // do nothing +} + +void DnsConfigServiceOhos::ReadConfigNow() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (!config_reader_) { + config_reader_ = + std::make_unique(*this); + } + config_reader_->WorkNow(); +} + +bool DnsConfigServiceOhos::StartWatching() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + // TODO(crbug.com/116139): re-start watcher if that makes sense. + watcher_ = std::make_unique(*this); + return watcher_->Watch(); +} +} // namespace internal + +// static +std::unique_ptr DnsConfigService::CreateSystemService() { + return std::make_unique(); +} + +} // namespace net \ No newline at end of file diff --git a/net/dns/dns_config_service_ohos.h b/net/dns/dns_config_service_ohos.h new file mode 100644 index 0000000000000000000000000000000000000000..a8ba8f813b9af8694f78f24ee73952148d936e3a --- /dev/null +++ b/net/dns/dns_config_service_ohos.h @@ -0,0 +1,52 @@ +// Copyright 2021 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_DNS_DNS_CONFIG_SERVICE_OHOS_H_ +#define NET_DNS_DNS_CONFIG_SERVICE_OHOS_H_ + +#include + +#include "base/time/time.h" +#include "net/base/net_export.h" +#include "net/dns/dns_config_service.h" +// #include "net/base/network_change_notifier.h" + +namespace net { + +// Use DnsConfigService::CreateSystemService to use it outside of tests. +namespace internal { + +// Service for reading and watching harmony system DNS settings. This object is +// not thread-safe and methods may perform blocking I/O so methods must be +// called on a sequence that allows blocking (i.e. base::MayBlock). It may be +// constructed on a different sequence than which it's later called on. +class NET_EXPORT_PRIVATE DnsConfigServiceOhos : public DnsConfigService { + public: + static constexpr base::TimeDelta kConfigChangeDelay = base::Milliseconds(50); + + DnsConfigServiceOhos(); + ~DnsConfigServiceOhos() override; + + DnsConfigServiceOhos(const DnsConfigServiceOhos&) = delete; + DnsConfigServiceOhos& operator=(const DnsConfigServiceOhos&) = delete; + + void RefreshConfig() override; + + protected: + // DnsConfigService: + void ReadConfigNow() override; + bool StartWatching() override; + + private: + class Watcher; + class ConfigReader; + + std::unique_ptr watcher_; + std::unique_ptr config_reader_; +}; + +} // namespace internal +} // namespace net + +#endif // NET_DNS_DNS_CONFIG_SERVICE_OHOS_H_ \ No newline at end of file diff --git a/net/dns/host_resolver.h b/net/dns/host_resolver.h index b538f7514fcf477c353d52fc7ec258ff641dbcfb..733f8c0403f5abf80e8669fb4f268f3ba66ef2ab 100644 --- a/net/dns/host_resolver.h +++ b/net/dns/host_resolver.h @@ -353,6 +353,12 @@ class NET_EXPORT HostResolver { // Controls the resolver's Secure DNS behavior for this request. SecureDnsPolicy secure_dns_policy = SecureDnsPolicy::kAllow; + +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + // If /true/, the dns task type of the request is only secure dns fallback + // type. + bool only_use_secure_fallback = false; +#endif // OHOS_EX_HTTP_DNS_FALLBACK }; // Handler for an ongoing MDNS listening operation. Created by @@ -450,6 +456,10 @@ class NET_EXPORT HostResolver { virtual const URLRequestContext* GetContextForTesting() const; virtual handles::NetworkHandle GetTargetNetworkForTesting() const; +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + virtual bool CanUseSecureDnsFallback() const { return false; } +#endif + // Creates a new HostResolver. |manager| must outlive the returned resolver. // // If |mapping_rules| is non-empty, the mapping rules will be applied to diff --git a/net/dns/host_resolver_manager.cc b/net/dns/host_resolver_manager.cc index 98cb65a1770ebc6513caacce799291f7e774ed6a..b6d4dc85d1160c610879504fddc88b62d965c6e6 100644 --- a/net/dns/host_resolver_manager.cc +++ b/net/dns/host_resolver_manager.cc @@ -755,6 +755,16 @@ class HostResolverManager::RequestImpl parameters_.secure_dns_policy, is_ip, source_net_log_, &job_key_.query_types, &job_key_.flags, &job_key_.secure_dns_mode); +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + if (parameters_.only_use_secure_fallback) { + next_state_ = STATE_START_JOB; + if (resolver_->CanUseSecureDnsFallback(resolve_context())) { + tasks_.push_back(TaskType::SECURE_DNS_FALLBACK); + } + return OK; + } +#endif + // A reachability probe to determine if the network is only reachable on // IPv6 will be scheduled if the parameters are met for using NAT64 in place // of an IPv4 address. @@ -1002,6 +1012,10 @@ class HostResolverManager::RequestImpl network_anonymization_key_.ToDebugString()); dict.Set("secure_dns_policy", base::strict_cast(parameters_.secure_dns_policy)); +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + dict.Set("only_use_secure_fallback", + parameters_.only_use_secure_fallback); +#endif // OHOS_EX_HTTP_DNS_FALLBACK return dict; }); } @@ -1327,6 +1341,11 @@ class HostResolverManager::DnsTask : public base::SupportsWeakPtr { if (types.Has(DnsQueryType::HTTPS)) { if (!secure_ && !client_->CanQueryAdditionalTypesViaInsecureDns()) { types.Remove(DnsQueryType::HTTPS); +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + } else if (resolve_context_->IsHttpsDnsFallbackEnabled() && + !client_->CanQueryAdditionalTypesViaInsecureDns()) { + types.Remove(DnsQueryType::HTTPS); +#endif } else { DCHECK(!httpssvc_metrics_); httpssvc_metrics_.emplace(secure_); @@ -2279,6 +2298,9 @@ class HostResolverManager::Job : public PrioritizedDispatcher::Job, StartDnsTask(false /* secure */); break; case TaskType::SECURE_DNS: +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + case TaskType::SECURE_DNS_FALLBACK: +#endif StartDnsTask(true /* secure */); break; case TaskType::MDNS: @@ -2464,6 +2486,15 @@ class HostResolverManager::Job : public PrioritizedDispatcher::Job, auto aliases = std::set(addr_list.dns_aliases().begin(), addr_list.dns_aliases().end()); +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + if (dns_task_error_ != OK && net_error != OK && ! tasks_.empty() && + tasks_.back() == TaskType::SECURE_DNS_FALLBACK) { + KillDnsTask(); + RunNextTask(); + return; + } +#endif + // Source unknown because the system resolver could have gotten it from a // hosts file, its own cache, a DNS lookup or somewhere else. // Don't store the |ttl| in cache since it's not obtained from the server. @@ -3206,6 +3237,10 @@ void HostResolverManager::SetDnsConfigOverrides(DnsConfigOverrides overrides) { void HostResolverManager::RegisterResolveContext(ResolveContext* context) { registered_contexts_.AddObserver(context); + +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + context->SetHttpsDnsFallbackEnabled(https_dns_fallback_enabled_); +#endif context->InvalidateCachesAndPerSessionData( dns_client_ ? dns_client_->GetCurrentSession() : nullptr, false /* network_change */); @@ -3752,6 +3787,12 @@ void HostResolverManager::PushDnsTasks(bool system_task_allowed, if (system_task_allowed && (no_dns_or_secure_tasks || allow_fallback_to_systemtask_)) out_tasks->push_back(TaskType::SYSTEM); + +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + if (dns_client_->CanUseSecureDnsFallbackTransactions(resolve_context)) { + out_tasks->push_back(TaskType::SECURE_DNS_FALLBACK); + } +#endif } void HostResolverManager::CreateTaskSequence( @@ -3846,6 +3887,13 @@ void HostResolverManager::CreateTaskSequence( break; } +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + if (secure_dns_policy == SecureDnsPolicy::kBootstrap && + out_tasks->back() == TaskType::SECURE_DNS_FALLBACK) { + out_tasks->pop_back(); + } +#endif + // `HOST_RESOLVER_CANONNAME` is only supported through system resolution. if (job_key.flags & HOST_RESOLVER_CANONNAME) { DCHECK(base::ranges::find(*out_tasks, TaskType::DNS) == out_tasks->end()); @@ -4298,6 +4346,33 @@ std::unique_ptr HostResolverManager::CreateDohProbeRunner( resolve_context); } +#ifdef OHOS_EX_HTTP_DNS_FALLBACK +bool HostResolverManager::CanUseSecureDnsFallback( + ResolveContext* context) const { + if (!dns_client_.get()) { + return false; + } + + return dns_client_->CanUseSecureDnsFallbackTransactions(context); +} + +void HostResolverManager::SetHttpsDnsFallbackData( + bool enabled, + const std::string& server_template) { + https_dns_fallback_enabled_ = enabled; + doh_fallback_server_template_ = server_template; + for (auto& context : registered_contexts_) { + context.SetHttpsDnsFallbackEnabled(enabled); + } +} + +void HostResolverManager::SetSuspectIpListAndSourceHostList( + const std::vector& ip_list, + const std::vector& host_list) { + // Todo(huawei) +} +#endif + HostResolverManager::RequestImpl::~RequestImpl() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!job_.has_value()) diff --git a/net/dns/host_resolver_manager.h b/net/dns/host_resolver_manager.h index 2617812eda9a9783cf88d03a74d0869a5c6fb1ab..f337b3148c2f87433792f202ce358e82b32f178a 100644 --- a/net/dns/host_resolver_manager.h +++ b/net/dns/host_resolver_manager.h @@ -251,6 +251,17 @@ class NET_EXPORT HostResolverManager bool check_ipv6_on_wifi_for_testing() const { return check_ipv6_on_wifi_; } +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + // Return true if Doh fallback server(s) exist and it/they can resolve + // successfully + bool CanUseSecureDnsFallback(ResolveContext* context) const; + void SetHttpsDnsFallbackData(bool enabled, + const std::string& server_template); + void SetSuspectIpListAndSourceHostList( + const std::vector& ip_list, + const std::vector& host_list); +#endif + handles::NetworkHandle target_network_for_testing() const { return target_network_; } @@ -295,8 +306,12 @@ class NET_EXPORT HostResolverManager CONFIG_PRESET = 7, NAT64 = 8, HOSTS = 9, - +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + SECURE_DNS_FALLBACK = 10, + kMaxValue = SECURE_DNS_FALLBACK, +#else kMaxValue = HOSTS, +#endif }; // Returns true if the task is local, synchronous, and instantaneous. @@ -523,6 +538,11 @@ class NET_EXPORT HostResolverManager std::unique_ptr CreateDohProbeRunner( ResolveContext* resolve_context); +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + bool https_dns_fallback_enabled_{false}; + std::string doh_fallback_server_template_; +#endif + // Used for multicast DNS tasks. Created on first use using // GetOrCreateMndsClient(). std::unique_ptr mdns_socket_factory_; diff --git a/net/dns/resolve_context.h b/net/dns/resolve_context.h index 24e5b6b0803cf5d5f39fc27db6cecf4f989ce362..13412b209f643c5171f7f5912d7e467c2ca8eb2f 100644 --- a/net/dns/resolve_context.h +++ b/net/dns/resolve_context.h @@ -194,6 +194,14 @@ class NET_EXPORT_PRIVATE ResolveContext : public base::CheckedObserver { return weak_ptr_factory_.GetWeakPtr(); } +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + void SetHttpsDnsFallbackEnabled(bool value) { + is_https_dns_fallback_enabled_ = value; + } + + bool IsHttpsDnsFallbackEnabled() { return is_https_dns_fallback_enabled_; } +#endif + private: friend DohDnsServerIterator; friend ClassicDnsServerIterator; @@ -296,6 +304,9 @@ class NET_EXPORT_PRIVATE ResolveContext : public base::CheckedObserver { const IsolationInfo isolation_info_; +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + bool is_https_dns_fallback_enabled_{false}; +#endif base::WeakPtrFactory weak_ptr_factory_{this}; }; diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc index e681517d400f6b652924ffa403e3f8cc548b7567..15d95e203918bc52416d1cb2e90fff747d16d3fa 100644 --- a/net/http/http_cache_transaction.cc +++ b/net/http/http_cache_transaction.cc @@ -289,6 +289,40 @@ int HttpCache::Transaction::Start(const HttpRequestInfo* request, return rv; } +#ifdef OHOS_EX_HTTP_DNS_FALLBACK +int HttpCache::Transaction::RestartWithSecureDnsOnly(CompletionOnceCallback callback) { + // Ensure that we only have one asynchronous call at a time. + DCHECK(callback_.is_null()); + + if (!cache_.get()) { + return ERR_UNEXPECTED; + } + + int rv = RestartNetworkRequestWithSecureDnsOnly(); + if (rv == ERR_IO_PENDING) { + callback_ = std::move(callback); + } + + return rv; +} + +int HttpCache::Transaction::RestartNetworkRequestWithSecureDnsOnly() { + DCHECK(mode_ & WRITE || mode_ == NONE); + DCHECK(network_trans_.get()); + DCHECK_EQ(STATE_NONE, next_state_); + + next_state_ = STATE_SEND_REQUEST_COMPLETE; + if (request_ != initial_request_ && custom_request_) { + custom_request_->secure_dns_only = true; + } + int rv = network_trans_->RestartWithSecureDnsOnly(io_callback_); + if (rv != ERR_IO_PENDING) { + return DoLoop(rv); + } + return rv; +} +#endif + int HttpCache::Transaction::RestartIgnoringLastError( CompletionOnceCallback callback) { DCHECK(!callback.is_null()); diff --git a/net/http/http_cache_transaction.h b/net/http/http_cache_transaction.h index e3dc7eea5ad50158b2178cb4f7aa5d549e1a3759..30777c6e21d53c5f3e5d192ac1b462ba49955481 100644 --- a/net/http/http_cache_transaction.h +++ b/net/http/http_cache_transaction.h @@ -134,6 +134,9 @@ class NET_EXPORT_PRIVATE HttpCache::Transaction : public HttpTransaction { int Start(const HttpRequestInfo* request_info, CompletionOnceCallback callback, const NetLogWithSource& net_log) override; +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + int RestartWithSecureDnsOnly(CompletionOnceCallback callback) override; +#endif // OHOS_EX_HTTP_DNS_FALLBACK int RestartIgnoringLastError(CompletionOnceCallback callback) override; int RestartWithCertificate(scoped_refptr client_cert, scoped_refptr client_private_key, @@ -414,6 +417,10 @@ class NET_EXPORT_PRIVATE HttpCache::Transaction : public HttpTransaction { // error code. int RestartNetworkRequest(); +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + int RestartNetworkRequestWithSecureDnsOnly(); +#endif // OHOS_EX_HTTP_DNS_FALLBACK + // Called to restart a network transaction with a client certificate. // Returns network error code. int RestartNetworkRequestWithCertificate( diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc index 2fafd95855b99ee3bd9e83c9d38816684f1c8cf8..411cf6e21cb60ee55253cfbe2436db64d2a50a6d 100644 --- a/net/http/http_network_session.cc +++ b/net/http/http_network_session.cc @@ -424,4 +424,10 @@ void HttpNetworkSession::SetConnectTimeout(int seconds) { websocket_socket_pool_manager_->SetConnectTimeout(seconds); } #endif + +#ifdef OHOS_EX_HTTP_DNS_FALLBACK +void HttpNetworkSession::SetConnectJobWithSecureDnsOnlyTimeout(int seconds) { + normal_socket_pool_manager_->SetConnectJobWithSecureDnsOnlyTimeout(seconds); +} +#endif } // namespace net diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h index 46df1a5efcdb4ec3d059556fa453df574f2ae5b6..863e24d41cda3d104bebb2d12ce715a4f2e5342e 100644 --- a/net/http/http_network_session.h +++ b/net/http/http_network_session.h @@ -320,6 +320,9 @@ class NET_EXPORT HttpNetworkSession { #ifdef OHOS_EX_NETWORK_CONNECTION void SetConnectTimeout(int seconds); #endif +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + void SetConnectJobWithSecureDnsOnlyTimeout(int seconds); +#endif private: friend class HttpNetworkSessionPeer; diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc index 7567fe0a5c17ebb04fcee327281ec047d55325f1..2efc6a71df9f0ba499ded051ee9b08fd2e099495 100644 --- a/net/http/http_network_transaction.cc +++ b/net/http/http_network_transaction.cc @@ -370,6 +370,9 @@ void HttpNetworkTransaction::DidDrainBodyForAuthRestart(bool keep_alive) { next_state_ = STATE_CONNECTED_CALLBACK; } stream_ = std::move(new_stream); +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + stream_created_ = true; +#endif } // Reset the other member variables. @@ -485,6 +488,11 @@ bool HttpNetworkTransaction::GetRemoteEndpoint(IPEndPoint* endpoint) const { void HttpNetworkTransaction::PopulateNetErrorDetails( NetErrorDetails* details) const { *details = net_error_details_; +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + if (stream_ || next_state_ != STATE_NONE || stream_created_) { + details->stream_created = true; + } +#endif if (stream_) stream_->PopulateNetErrorDetails(details); } @@ -569,6 +577,9 @@ void HttpNetworkTransaction::OnStreamReady(const SSLConfig& used_ssl_config, response_.was_fetched_via_spdy = stream_request_->using_spdy(); response_.dns_aliases = stream_->GetDnsAliases(); SetProxyInfoInReponse(used_proxy_info, &response_); +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + stream_created_ = true; +#endif OnIOComplete(OK); } @@ -721,6 +732,14 @@ int HttpNetworkTransaction::DoLoop(int result) { case STATE_CREATE_STREAM_COMPLETE: rv = DoCreateStreamComplete(rv); break; +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + case STATE_CREATE_FALLBACK_STREAM_WITH_SECURE_DNS_ONLY: + rv = DoCreateFallbackStreamWithSecureDns(); + break; + case STATE_CREATE_FALLBACK_STREAM_WITH_SECURE_DNS_ONLY_COMPLETE: + rv = DoCreateFallbackStreamWithSecureDnsOnlyComplete(rv); + break; +#endif case STATE_INIT_STREAM: DCHECK_EQ(OK, rv); rv = DoInitStream(); @@ -872,6 +891,78 @@ int HttpNetworkTransaction::DoCreateStreamComplete(int result) { return result; } +#ifdef OHOS_EX_HTTP_DNS_FALLBACK +int HttpNetworkTransaction::RestartWithSecureDnsOnly(CompletionOnceCallback callback) { + DCHECK(!stream_.get()); + DCHECK(!stream_request_.get()); + DCHECK_EQ(STATE_NONE, next_state_); + + if (!CheckMaxRestarts()) { + return ERR_TOO_MANY_RETRIES; + } + + // Restart the other member variables. + // Note: this is necessary only with SSL renegotiation. + ResetStateForRestart(); + next_state_ = STATE_CREATE_FALLBACK_STREAM_WITH_SECURE_DNS_ONLY; + int rv = DoLoop(OK); + if (rv == ERR_IO_PENDING) { + callback_ = std::move(callback); + } + + // This always returns ERR_IO_PENDING because DoCreateStream() does, but + // GenerateNetworkErrorLoggingReportIfError() should be called here if any + // other net::Error can be returned. + CHECK_EQ(rv, ERR_IO_PENDING); + return rv; +} + +int HttpNetworkTransaction::DoCreateFallbackStreamWithSecureDnsOnly() { + response_.network_accessed = true; + + next_state_ = STATE_CREATE_FALLBACK_STREAM_WITH_SECURE_DNS_ONLY_COMPLETE; + // IP based pooling is only enabled on a retry after 421 Misdirected Request + // is received. Alternative Services are also disabled in this case (though + // they can also be disabled when retrying after a QUIC error). + if (!enable_ip_based_pooling_){ + DCHECK(!enabled_alternative_services_); + } + if (ForWebSocketHandshake()) { + stream_request_ = session_->http_stream_factory()->RequestWebSocketHandshakeStream( + *request_, priority_, + server_ssl_config_, proxy_ssl_config_, this, + websocket_handshake_stream_base_create_helper_, + enabled_ip_based_pooling_, enabled_alternative_services_, net_log_); + } else { + stream_request_ = session_->http_stream_factory()->RequestStream( + *request_, priority_, server_ssl_config_, proxy_ssl_config_, this, + enable_ip_based_pooling_, enable_alternative_services_, net_log_); + } + + CHECK(stream_request_.get()); + return ERR_IO_PENDING; +} + +int HttpNetworkTransaction::DoCreateFallbackStreamWithSecureDnsOnlyComplete(int result) { + CopyConnectionAttemptsFromStreamRequest(); + if (result == OK) { + next_state_ = STATE_CONNECTED_CALLBACK; + DCHECK(stream_.get()); + } else if (result == ERR_HTTP_1_1_REQUIRED || result == ERR_PROXY_HTTP_1_1_REQUIRED) { + return HandleHttp11Required(result); + } + + // Handle possible client certificate errors that may have occurred if the + // stream used SSL for one or more of the layers. + result = HandleSSLClientAuthError(result); + + // At this point we are done with the stream_request_. + stream_request_.reset(); + return result; +} +#endif // OHOS_EX_HTTP_DNS_FALLBACK + + int HttpNetworkTransaction::DoInitStream() { DCHECK(stream_.get()); next_state_ = STATE_INIT_STREAM_COMPLETE; diff --git a/net/http/http_network_transaction.h b/net/http/http_network_transaction.h index 8e6ade134fe0e200b1735a54274efb4257b3d984..b25f0eb1e2caecbbbd8978a7aeb55d1faedab82b 100644 --- a/net/http/http_network_transaction.h +++ b/net/http/http_network_transaction.h @@ -63,6 +63,9 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction int Start(const HttpRequestInfo* request_info, CompletionOnceCallback callback, const NetLogWithSource& net_log) override; +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + int RestartWithSecureDnsOnly(CompletionOnceCallback callback) override; +#endif int RestartIgnoringLastError(CompletionOnceCallback callback) override; int RestartWithCertificate(scoped_refptr client_cert, scoped_refptr client_private_key, @@ -144,6 +147,10 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction STATE_NOTIFY_BEFORE_CREATE_STREAM, STATE_CREATE_STREAM, STATE_CREATE_STREAM_COMPLETE, +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + STATE_CREATE_FALLBACK_STREAM_WITH_SECURE_DNS_ONLY, + STATE_CREATE_FALLBACK_STREAM_WITH_SECURE_DNS_ONLY_COMPLETE, +#endif STATE_INIT_STREAM, STATE_INIT_STREAM_COMPLETE, STATE_CONNECTED_CALLBACK, @@ -186,6 +193,10 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction int DoNotifyBeforeCreateStream(); int DoCreateStream(); int DoCreateStreamComplete(int result); +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + int DoCreateFallbackStreamWithSecureDnsOnly(); + int DoCreateFallbackStreamWithSecureDnsOnlyComplete(int result); +#endif int DoInitStream(); int DoInitStreamComplete(int result); int DoConnectedCallback(); @@ -494,6 +505,10 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction bool close_connection_on_destruction_ = false; +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + bool stream_created_ = false; +#endif + absl::optional quic_protocol_error_retry_delay_; }; diff --git a/net/http/http_response_info.h b/net/http/http_response_info.h index 1455d3771b4b0fc4ab8458f195df060f59a2a982..64ee6d77ea513d710c05d4febf1da6df922fe3a5 100644 --- a/net/http/http_response_info.h +++ b/net/http/http_response_info.h @@ -273,6 +273,10 @@ class NET_EXPORT HttpResponseInfo { absl::optional browser_run_id; static std::string ConnectionInfoToString(ConnectionInfo connection_info); + +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + bool secure_dns_only = false; +#endif }; } // namespace net diff --git a/net/http/http_stream_factory_job.cc b/net/http/http_stream_factory_job.cc index 61809e3c65be557fe3e61c69b4980d199548a282..e6fb269dc20dbb6c92b7f557210d9320d574191f 100644 --- a/net/http/http_stream_factory_job.cc +++ b/net/http/http_stream_factory_job.cc @@ -921,6 +921,10 @@ int HttpStreamFactory::Job::DoInitConnectionImpl() { request_info_.network_anonymization_key, request_info_.secure_dns_policy, request_info_.socket_tag, net_log_, connection_.get(), io_callback_, proxy_auth_callback +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + , + request_info_.secure_dns_only +#endif #if BUILDFLAG(IS_OHOS) , from_preload_ diff --git a/net/http/http_transaction.h b/net/http/http_transaction.h index bf59d6f6b604827a02695ce324187802f947f8c8..fbdb2ade3d729cc1e4fd98cccf14fea20f7b41d6 100644 --- a/net/http/http_transaction.h +++ b/net/http/http_transaction.h @@ -86,6 +86,10 @@ class NET_EXPORT_PRIVATE HttpTransaction { CompletionOnceCallback callback, const NetLogWithSource& net_log) = 0; +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + virtual int RestartWithSecureDnsOnly(CompletionOnceCallback callback) = 0; +#endif + // Restarts the HTTP transaction, ignoring the last error. This call can // only be made after a call to Start (or RestartIgnoringLastError) failed. // Once Read has been called, this method cannot be called. This method is diff --git a/net/socket/client_socket_pool.cc b/net/socket/client_socket_pool.cc index ee381b368427d4da911ba5868984c4de327c268f..e39a20906474ceacb4e2dabd6649c89632bf2eb9 100644 --- a/net/socket/client_socket_pool.cc +++ b/net/socket/client_socket_pool.cc @@ -80,14 +80,24 @@ ClientSocketPool::GroupId::GroupId( url::SchemeHostPort destination, PrivacyMode privacy_mode, NetworkAnonymizationKey network_anonymization_key, - SecureDnsPolicy secure_dns_policy) + SecureDnsPolicy secure_dns_policy +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + , + bool secure_dns_only +#endif + ) : destination_(std::move(destination)), privacy_mode_(privacy_mode), network_anonymization_key_( NetworkAnonymizationKey::IsPartitioningEnabled() ? std::move(network_anonymization_key) : NetworkAnonymizationKey()), - secure_dns_policy_(secure_dns_policy) { + secure_dns_policy_(secure_dns_policy) +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + , + secure_dns_only_(secure_dns_only) +#endif +{ DCHECK(destination_.IsValid()); // ClientSocketPool only expected to be used for HTTP/HTTPS/WS/WSS cases, and @@ -129,6 +139,12 @@ std::string ClientSocketPool::GroupId::ToString() const { break; } +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + if (secure_dns_only_) { + result = "sdo/" + result; + } +#endif // OHOS_EX_HTTP_DNS_FALLBACK + return result; } @@ -208,7 +224,12 @@ std::unique_ptr ClientSocketPool::CreateConnectJob( socket_params->ssl_config_for_proxy(), is_for_websockets_, group_id.privacy_mode(), resolution_callback, request_priority, socket_tag, group_id.network_anonymization_key(), - group_id.secure_dns_policy(), common_connect_job_params_, delegate); + group_id.secure_dns_policy(), common_connect_job_params_, delegate +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + , + group_id.secure_dns_only() +#endif + ); } #ifdef OHOS_EX_NETWORK_CONNECTION @@ -221,4 +242,13 @@ int ClientSocketPool::GetConnectTimeout() { } #endif +#ifdef OHOS_EX_HTTP_DNS_FALLBACK +void ClientSocketPool::SetConnectJobWithSecureDnsOnlyTimeout(int seconds) { + connect_job_with_secure_dns_only_timeout_ = seconds; +} + +int ClientSocketPool::GetConnectJobWithSecureDnsOnlyTimeout() { + return connect_job_with_secure_dns_only_timeout_; +} +#endif } // namespace net diff --git a/net/socket/client_socket_pool.h b/net/socket/client_socket_pool.h index eb67dfcb4b1ad7c5302ccef25f572aa674e2aa42..5d7caad7f0db8e663804e357e10e07a65d8acd54 100644 --- a/net/socket/client_socket_pool.h +++ b/net/socket/client_socket_pool.h @@ -100,7 +100,12 @@ class NET_EXPORT ClientSocketPool : public LowerLayeredPool { GroupId(url::SchemeHostPort destination, PrivacyMode privacy_mode, NetworkAnonymizationKey network_anonymization_key, - SecureDnsPolicy secure_dns_policy); + SecureDnsPolicy secure_dns_policy +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + , + bool secure_dns_only = false +#endif + ); GroupId(const GroupId& group_id); ~GroupId(); @@ -118,9 +123,22 @@ class NET_EXPORT ClientSocketPool : public LowerLayeredPool { SecureDnsPolicy secure_dns_policy() const { return secure_dns_policy_; } +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + bool secure_dns_only() const { return secure_dns_only_; } +#endif // OHOS_EX_HTTP_DNS_FALLBACK + // Returns the group ID as a string, for logging. std::string ToString() const; +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + bool operator==(const GroupId& other) const { + return std::tie(destination_, privacy_mode_, network_anonymization_key_, + secure_dns_policy_, secure_dns_only_) == + std::tie(other.destination_, other.privacy_mode_, + other.network_anonymization_key_, + other.secure_dns_policy_, other.secure_dns_only_); + } +#else bool operator==(const GroupId& other) const { return std::tie(destination_, privacy_mode_, network_anonymization_key_, secure_dns_policy_) == @@ -128,7 +146,17 @@ class NET_EXPORT ClientSocketPool : public LowerLayeredPool { other.network_anonymization_key_, other.secure_dns_policy_); } +#endif // OHOS_EX_HTTP_DNS_FALLBACK +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + bool operator<(const GroupId& other) const { + return std::tie(destination_, privacy_mode_, network_anonymization_key_, + secure_dns_policy_, secure_dns_only_) < + std::tie(other.destination_, other.privacy_mode_, + other.network_anonymization_key_, + other.secure_dns_policy_, other.secure_dns_only_); + } +#else bool operator<(const GroupId& other) const { return std::tie(destination_, privacy_mode_, network_anonymization_key_, secure_dns_policy_) < @@ -136,6 +164,7 @@ class NET_EXPORT ClientSocketPool : public LowerLayeredPool { other.network_anonymization_key_, other.secure_dns_policy_); } +#endif // OHOS_EX_HTTP_DNS_FALLBACK private: // The endpoint of the final destination (not the proxy). @@ -149,6 +178,10 @@ class NET_EXPORT ClientSocketPool : public LowerLayeredPool { // Controls the Secure DNS behavior to use when creating this socket. SecureDnsPolicy secure_dns_policy_; + +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + bool secure_dns_only_ = false; +#endif // OHOS_EX_HTTP_DNS_FALLBACK }; // Parameters that, in combination with GroupId, proxy, websocket information, @@ -357,6 +390,10 @@ class NET_EXPORT ClientSocketPool : public LowerLayeredPool { void SetConnectTimeout(int timeout_override); int GetConnectTimeout(); #endif +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + void SetConnectJobWithSecureDnsOnlyTimeout(int seconds); + int GetConnectJobWithSecureDnsOnlyTimeout(); +#endif protected: ClientSocketPool(bool is_for_websockets, @@ -380,6 +417,9 @@ class NET_EXPORT ClientSocketPool : public LowerLayeredPool { #ifdef OHOS_EX_NETWORK_CONNECTION int timeout_override_{0}; #endif +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + int connect_job_with_secure_dns_only_timeout_{15}; +#endif private: const bool is_for_websockets_; diff --git a/net/socket/client_socket_pool_manager.cc b/net/socket/client_socket_pool_manager.cc index 1761c1b39b1b73a9157022dbf92304efc84f737a..077d899ce436c253305232eafbb8aa071658644a 100644 --- a/net/socket/client_socket_pool_manager.cc +++ b/net/socket/client_socket_pool_manager.cc @@ -103,6 +103,10 @@ int InitSocketPoolHelper( HttpNetworkSession::SocketPoolType socket_pool_type, CompletionOnceCallback callback, const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + , + bool secure_dns_only = false +#endif #if BUILDFLAG(IS_OHOS) , bool from_preload = false @@ -121,7 +125,12 @@ int InitSocketPoolHelper( ClientSocketPool::GroupId connection_group( std::move(endpoint), privacy_mode, std::move(network_anonymization_key), - secure_dns_policy); + secure_dns_policy +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + , + secure_dns_only +#endif + ); scoped_refptr socket_params = CreateSocketParams(connection_group, proxy_info.proxy_server(), ssl_config_for_origin, ssl_config_for_proxy); @@ -243,6 +252,10 @@ int InitSocketHandleForHttpRequest( ClientSocketHandle* socket_handle, CompletionOnceCallback callback, const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + , + bool secure_dns_only +#endif #if BUILDFLAG(IS_OHOS) , bool from_preload @@ -256,6 +269,10 @@ int InitSocketHandleForHttpRequest( std::move(network_anonymization_key), secure_dns_policy, socket_tag, net_log, 0, socket_handle, HttpNetworkSession::NORMAL_SOCKET_POOL, std::move(callback), proxy_auth_callback +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + , + secure_dns_only +#endif #if BUILDFLAG(IS_OHOS) , from_preload diff --git a/net/socket/client_socket_pool_manager.h b/net/socket/client_socket_pool_manager.h index 4a7148902c64c20af3b5d1688e77475a6cb19ed3..52c51ba0df034f5fbfb5e9736c4dda5b3f7505c9 100644 --- a/net/socket/client_socket_pool_manager.h +++ b/net/socket/client_socket_pool_manager.h @@ -73,6 +73,9 @@ class NET_EXPORT_PRIVATE ClientSocketPoolManager { #ifdef OHOS_EX_NETWORK_CONNECTION virtual void SetConnectTimeout(int seconds) = 0; #endif +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + virtual void SetConnectJobWithSecureDnsOnlyTimeout(int seconds) = 0; +#endif }; // A helper method that uses the passed in proxy information to initialize a @@ -98,6 +101,10 @@ int InitSocketHandleForHttpRequest( ClientSocketHandle* socket_handle, CompletionOnceCallback callback, const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + , + bool secure_dns_only = false +#endif #if BUILDFLAG(IS_OHOS) , bool from_preload = false diff --git a/net/socket/client_socket_pool_manager_impl.cc b/net/socket/client_socket_pool_manager_impl.cc index c8362d628fa36acc70f035f1440bb186c784991a..3206071a0f8f0f2bb57fb55ae61fe0bec8422e2a 100644 --- a/net/socket/client_socket_pool_manager_impl.cc +++ b/net/socket/client_socket_pool_manager_impl.cc @@ -91,6 +91,10 @@ ClientSocketPool* ClientSocketPoolManagerImpl::GetSocketPool( #ifdef OHOS_EX_NETWORK_CONNECTION new_pool->SetConnectTimeout(timeout_override_); #endif +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + new_pool->SetConnectJobWithSecureDnsOnlyTimeout( + connect_job_with_secure_dns_timeout_); +#endif std::pair ret = socket_pools_.insert(std::make_pair(proxy_server, std::move(new_pool))); @@ -124,4 +128,14 @@ void ClientSocketPoolManagerImpl::SetConnectTimeout(int seconds) { } } #endif + +#ifdef OHOS_EX_HTTP_DNS_FALLBACK +void ClientSocketPoolManagerImpl::SetConnectJobWithSecureDnsOnlyTimeout( + int seconds) { + connect_job_with_secure_dns_timeout_ = seconds; + for (const auto& it : socket_pools_) { + it.second->SetConnectJobWithSecureDnsOnlyTimeout(seconds); + } +} +#endif } // namespace net diff --git a/net/socket/client_socket_pool_manager_impl.h b/net/socket/client_socket_pool_manager_impl.h index c967a255981b6e93e7de1a3554fe548b02f2d366..da777d7d3b875603924eda3e9000b2b3193990d2 100644 --- a/net/socket/client_socket_pool_manager_impl.h +++ b/net/socket/client_socket_pool_manager_impl.h @@ -54,6 +54,10 @@ class NET_EXPORT_PRIVATE ClientSocketPoolManagerImpl void SetConnectTimeout(int seconds) override; #endif +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + void SetConnectJobWithSecureDnsOnlyTimeout(int seconds) override; +#endif + private: using SocketPoolMap = std::map>; @@ -69,6 +73,9 @@ class NET_EXPORT_PRIVATE ClientSocketPoolManagerImpl SocketPoolMap socket_pools_; #ifdef OHOS_EX_NETWORK_CONNECTION int timeout_override_{0}; +#endif +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + int connect_job_with_secure_dns_timeout_{0}; #endif THREAD_CHECKER(thread_checker_); }; diff --git a/net/socket/connect_job_factory.cc b/net/socket/connect_job_factory.cc index 778faf5c00497516a4c8e4f9cb5c9dd409409d51..584032ac12faf6164d278e143b371541f29a9996 100644 --- a/net/socket/connect_job_factory.cc +++ b/net/socket/connect_job_factory.cc @@ -117,13 +117,23 @@ std::unique_ptr ConnectJobFactory::CreateConnectJob( const NetworkAnonymizationKey& network_anonymization_key, SecureDnsPolicy secure_dns_policy, const CommonConnectJobParams* common_connect_job_params, - ConnectJob::Delegate* delegate) const { + ConnectJob::Delegate* delegate +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + , + bool secure_dns_only +#endif +) const { return CreateConnectJob(Endpoint(std::move(endpoint)), proxy_server, proxy_annotation_tag, ssl_config_for_origin, ssl_config_for_proxy, force_tunnel, privacy_mode, resolution_callback, request_priority, socket_tag, network_anonymization_key, secure_dns_policy, - common_connect_job_params, delegate); + common_connect_job_params, delegate +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + , + secure_dns_only +#endif + ); } std::unique_ptr ConnectJobFactory::CreateConnectJob( @@ -141,7 +151,12 @@ std::unique_ptr ConnectJobFactory::CreateConnectJob( const NetworkAnonymizationKey& network_anonymization_key, SecureDnsPolicy secure_dns_policy, const CommonConnectJobParams* common_connect_job_params, - ConnectJob::Delegate* delegate) const { + ConnectJob::Delegate* delegate +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + , + bool secure_dns_only +#endif +) const { SchemelessEndpoint schemeless_endpoint{using_ssl, std::move(endpoint)}; return CreateConnectJob(std::move(schemeless_endpoint), proxy_server, proxy_annotation_tag, ssl_config_for_origin, @@ -179,7 +194,12 @@ std::unique_ptr ConnectJobFactory::CreateConnectJob( secure_dns_policy, resolution_callback, proxy_server.is_secure_http_like() ? SupportedProtocolsFromSSLConfig(*ssl_config_for_proxy) - : no_alpn_protocols); + : no_alpn_protocols +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + , + secure_dns_only +#endif + ); if (proxy_server.is_http_like()) { scoped_refptr ssl_params; @@ -220,7 +240,12 @@ std::unique_ptr ConnectJobFactory::CreateConnectJob( ssl_tcp_params = base::MakeRefCounted( ToTransportEndpoint(endpoint), network_anonymization_key, secure_dns_policy, resolution_callback, - SupportedProtocolsFromSSLConfig(*ssl_config_for_origin)); + SupportedProtocolsFromSSLConfig(*ssl_config_for_origin) +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + , + secure_dns_only +#endif + ); } // TODO(crbug.com/1206799): Pass `endpoint` directly (preserving scheme // when available)? @@ -249,7 +274,12 @@ std::unique_ptr ConnectJobFactory::CreateConnectJob( DCHECK(proxy_server.is_direct()); auto tcp_params = base::MakeRefCounted( ToTransportEndpoint(endpoint), network_anonymization_key, - secure_dns_policy, resolution_callback, no_alpn_protocols); + secure_dns_policy, resolution_callback, no_alpn_protocols +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + , + secure_dns_only +#endif + ); return transport_connect_job_factory_->Create( request_priority, socket_tag, common_connect_job_params, tcp_params, delegate, /*net_log=*/nullptr); diff --git a/net/socket/connect_job_factory.h b/net/socket/connect_job_factory.h index 6ea30912cd33b9320b9f7a18a19aca133b9e8c7b..57d55d76c892254b4820ca6c126a4a30d9c21cc6 100644 --- a/net/socket/connect_job_factory.h +++ b/net/socket/connect_job_factory.h @@ -76,7 +76,12 @@ class NET_EXPORT_PRIVATE ConnectJobFactory { const NetworkAnonymizationKey& network_anonymization_key, SecureDnsPolicy secure_dns_policy, const CommonConnectJobParams* common_connect_job_params, - ConnectJob::Delegate* delegate) const; + ConnectJob::Delegate* delegate +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + , + bool secure_dns_only = false +#endif + ) const; // TODO(crbug.com/1206799): Rename to discourage use except in cases where the // scheme is non-standard or unknown. @@ -112,7 +117,12 @@ class NET_EXPORT_PRIVATE ConnectJobFactory { const NetworkAnonymizationKey& network_anonymization_key, SecureDnsPolicy secure_dns_policy, const CommonConnectJobParams* common_connect_job_params, - ConnectJob::Delegate* delegate) const; + ConnectJob::Delegate* delegate +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + , + bool secure_dns_only = false +#endif + ) const; std::unique_ptr http_proxy_connect_job_factory_; std::unique_ptr socks_connect_job_factory_; diff --git a/net/socket/mock_client_socket_pool_manager.h b/net/socket/mock_client_socket_pool_manager.h index def60f5c7f474571a05afd5ddf8a202cda090390..1a88e5316f0dd5ce81a8756aefd869a56736f162 100644 --- a/net/socket/mock_client_socket_pool_manager.h +++ b/net/socket/mock_client_socket_pool_manager.h @@ -37,6 +37,9 @@ class MockClientSocketPoolManager : public ClientSocketPoolManager { void CloseIdleSockets(const char* net_log_reason_utf8) override; ClientSocketPool* GetSocketPool(const ProxyServer& proxy_server) override; base::Value SocketPoolInfoToValue() const override; +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + void SetConnectJobWithSecureDnsOnlyTimeout(int seconds) override {} +#endif private: using ClientSocketPoolMap = diff --git a/net/socket/transport_client_socket_pool.cc b/net/socket/transport_client_socket_pool.cc index 1ac54b77a2ddee569b7d1fe623eb8fd1911ec8d8..45bf4752d8af586992b01a453225ed9514511882 100644 --- a/net/socket/transport_client_socket_pool.cc +++ b/net/socket/transport_client_socket_pool.cc @@ -463,8 +463,16 @@ int TransportClientSocketPool::RequestSocketInternal( return NetLogCreateConnectJobParams(false /* backup_job */, &group_id); }); #ifdef OHOS_EX_NETWORK_CONNECTION +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + if (group_id.secure_dns_only()) { + connect_job->SetConnectTimeout(connect_job_with_secure_dns_only_timeout_); + } else { + connect_job->SetConnectTimeout(timeout_override_); + } +#else connect_job.get()->SetConnectTimeout(timeout_override_); -#endif +#endif // OHOS_EX_HTTP_DNS_FALLBACK +#endif // OHOS_EX_NETWORK_CONNECTION int rv = connect_job->Connect(); if (rv == ERR_IO_PENDING) { @@ -1653,8 +1661,17 @@ void TransportClientSocketPool::Group::OnBackupJobTimerFired( }); ConnectJob* backup_job = owned_backup_job.get(); #ifdef OHOS_EX_NETWORK_CONNECTION +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + if (group_id.secure_dns_only()) { + backup_job->SetConnectTimeout( + client_socket_pool_->GetConnectJobWithSecureDnsOnlyTimeout()); + } else { + backup_job->SetConnectTimeout(client_socket_pool_->GetConnectTimeout()); + } +#else backup_job->SetConnectTimeout(client_socket_pool_->GetConnectTimeout()); -#endif +#endif // OHOS_EX_HTTP_DNS_FALLBACK +#endif // OHOS_EX_NETWORK_CONNECTION AddJob(std::move(owned_backup_job), false); client_socket_pool_->connecting_socket_count_++; int rv = backup_job->Connect(); diff --git a/net/socket/transport_connect_job.cc b/net/socket/transport_connect_job.cc index 7010a3d17ce8911b16f08d40b55123ec739296fe..c93d362852bae9773cf3b3b4a9ef5843732cf9cb 100644 --- a/net/socket/transport_connect_job.cc +++ b/net/socket/transport_connect_job.cc @@ -55,12 +55,23 @@ TransportSocketParams::TransportSocketParams( NetworkAnonymizationKey network_anonymization_key, SecureDnsPolicy secure_dns_policy, OnHostResolutionCallback host_resolution_callback, - base::flat_set supported_alpns) + base::flat_set supported_alpns +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + , + bool secure_dns_only +#endif + ) : destination_(std::move(destination)), network_anonymization_key_(std::move(network_anonymization_key)), secure_dns_policy_(secure_dns_policy), host_resolution_callback_(std::move(host_resolution_callback)), - supported_alpns_(std::move(supported_alpns)) { + + supported_alpns_(std::move(supported_alpns)) +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + , + secure_dns_only_(secure_dns_only) +#endif +{ #if DCHECK_IS_ON() auto* scheme_host_port = absl::get_if(&destination_); if (scheme_host_port) { @@ -260,6 +271,11 @@ int TransportConnectJob::DoResolveHost() { HostResolver::ResolveHostParameters parameters; parameters.initial_priority = priority(); parameters.secure_dns_policy = params_->secure_dns_policy(); +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + if (host_resolver()->CanUseSecureDnsFallback()) { + parameters.only_use_secure_fallback = params_->secure_dns_only(); + } +#endif // OHOS_EX_HTTP_DNS_FALLBACK if (absl::holds_alternative(params_->destination())) { request_ = host_resolver()->CreateRequest( absl::get(params_->destination()), diff --git a/net/socket/transport_connect_job.h b/net/socket/transport_connect_job.h index 19c2f2bbdc35c6d097f663a8273df3fb6276a77a..1c9129a764a59a89831dc9ddb357ad35861b8f78 100644 --- a/net/socket/transport_connect_job.h +++ b/net/socket/transport_connect_job.h @@ -55,7 +55,12 @@ class NET_EXPORT_PRIVATE TransportSocketParams NetworkAnonymizationKey network_anonymization_key, SecureDnsPolicy secure_dns_policy, OnHostResolutionCallback host_resolution_callback, - base::flat_set supported_alpns); + base::flat_set supported_alpns +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + , + bool secure_dns_only = false +#endif + ); TransportSocketParams(const TransportSocketParams&) = delete; TransportSocketParams& operator=(const TransportSocketParams&) = delete; @@ -71,6 +76,9 @@ class NET_EXPORT_PRIVATE TransportSocketParams const base::flat_set& supported_alpns() const { return supported_alpns_; } +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + bool secure_dns_only() const { return secure_dns_only_; } +#endif private: friend class base::RefCounted; @@ -81,6 +89,9 @@ class NET_EXPORT_PRIVATE TransportSocketParams const SecureDnsPolicy secure_dns_policy_; const OnHostResolutionCallback host_resolution_callback_; const base::flat_set supported_alpns_; +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + const bool secure_dns_only_; +#endif }; // TransportConnectJob handles the host resolution necessary for socket creation diff --git a/net/url_request/url_request_context.cc b/net/url_request/url_request_context.cc index b080d5133be8bd141ea835ca463d41fe0b2237e7..f78660a3718bae2e920f83865b33e93577f6efca 100644 --- a/net/url_request/url_request_context.cc +++ b/net/url_request/url_request_context.cc @@ -267,4 +267,24 @@ void URLRequestContext::SetConnectTimeout(int seconds) { } #endif +#ifdef OHOS_EX_HTTP_DNS_FALLBACK +void URLRequestContext::SetConnectJobWithSecureDnsOnlyTimeout(int second) { + HttpTransactionFactory* transaction_factory = http_transaction_factory(); + if (!transaction_factory) { + return; + } + HttpNetworkSession* network_session = transaction_factory->GetSession(); + if (!network_session) { + return; + } + network_session->SetConnectJobWithSecureDnsOnlyTimeout(second); +} + +bool URLRequestContext::CanUseSecureDnsFallback() const { + if (!host_resolver()) { + return false; + } + return host_resolver()->CanUseSecureDnsFallback(); +} +#endif } // namespace net diff --git a/net/url_request/url_request_context.h b/net/url_request/url_request_context.h index a9853aec7bbed69344ee38c168e86f5b00503bdd..ad33acc0b4abcc542126580044edde2b40f2728a 100644 --- a/net/url_request/url_request_context.h +++ b/net/url_request/url_request_context.h @@ -242,6 +242,10 @@ class NET_EXPORT URLRequestContext final { #ifdef OHOS_EX_NETWORK_CONNECTION void SetConnectTimeout(int seconds); #endif +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + void SetConnectJobWithSecureDnsOnlyTimeout(int second); + bool CanUseSecureDnsFallback() const; +#endif #if BUILDFLAG(IS_OHOS) base::WeakPtr GetWeakPtr() { diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc index 5141bfdf1abb47f624b757380d88716fbeefdaf7..a4cdc8c2d27c0ed711ebf5d42e6ea5174b66a6f1 100644 --- a/net/url_request/url_request_http_job.cc +++ b/net/url_request/url_request_http_job.cc @@ -99,6 +99,13 @@ #include "net/android/network_library.h" #endif +#if BUILDFLAG(IS_OHOS) +#ifdef OHOS_EX_HTTP_DNS_FALLBACK +#include "base/command_line.h" +#include "content/public/common/content_switches.h" +#endif +#endif + namespace { base::Value::Dict CookieInclusionStatusNetLogParams( @@ -991,8 +998,134 @@ void URLRequestHttpJob::ProcessStrictTransportSecurityHeader() { security_state->AddHSTSHeader(request_info_.url.host(), value); } +#if BUILDFLAG(IS_OHOS) +#ifdef OHOS_EX_HTTP_DNS_FALLBACK +bool URLRequestHttpJob::CanRetryWithSecureDnsOnly(int net_error) { + if (!base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableNwebExHttpDnsFallback)) { + return false; + } + + if (net_error == net::OK) { + return false; + } + + if (request_->isolation_info().request_type() != + IsolationInfo::RequestType::kMainFrame) { + LOG(INFO) << "DOH-Fallback request is not mainframe"; + return false; + } + + if (transaction_ && transaction_->GetResponseInfo() && + transaction_->GetResponseInfo() + ->resolve_error_info.is_secure_network_error) { + LOG(INFO) << "DOH-Fallback won't retry for is_secure_network_error is " + "true"; + return false; + } + + if (!request_->context()->CanUseSecureDnsFallback()) { + LOG(INFO) << "DOH-Fallback can't use secure dns fallback"; + return false; + } + + // The following net errors will retry to use httpdns to resolve the ip + // in the connect phase, and connect again. + if (net_error == net::ERR_TIMED_OUT || + net_error == net::ERR_CONNECTION_CLOSED || + net_error == net::ERR_CONNECTION_RESET || + net_error == net::ERR_CONNECTION_REFUSED || + net_error == net::ERR_CONNECTION_ABORTED || + net_error == net::ERR_CONNECTION_FAILED || + net_error == net::ERR_NAME_NOT_RESOLVED || + net_error == net::ERR_ADDRESS_INVALID || + net_error == net::ERR_ADDRESS_UNREACHABLE || + net_error == net::ERR_TUNNEL_CONNECTION_FAILED || + net_error == net::ERR_CONNECTION_TIMED_OUT || + net_error == net::ERR_SOCKS_CONNECTION_FAILED || + net_error == net::ERR_SOCKS_CONNECTION_HOST_UNREACHABLE || + net_error == net::ERR_PROXY_CONNECTION_FAILED || + net_error == net::ERR_NAME_RESOLUTION_FAILED || + net_error == net::ERR_NETWORK_ACCESS_DENIED || + net_error == net::ERR_ADDRESS_IN_USE || + net_error == net::ERR_UNABLE_TO_REUSE_CONNECTION_FOR_PROXY_AUTH) { + net::NetErrorDetails details; + PopulateNetErrorDetails(&details); + // 如果stream已经创建成功。证明dns阶段没有发生问题,所以我们不需要重试. + if (details.stream_created) { + LOG(INFO) << "DOH-Fallback cann't retry with secure dns since the stream " + "is created."; + return false; + } + return true; + } + return false; +} + +void URLRequestHttpJob::RetryWithSecureDnsOnly() { + // If the transaction was destroyed, then the job was cancelled. + if (!transaction_.get()) { + return; + } + + response_info_ = nullptr; + override_response_headers_ = nullptr; // See https://crbug.com/801237. + receive_headers_end_ = base::TimeTicks(); + + ResetTimer(); + + LOG(INFO) << "DOH-Fallback will retry with secure dns only"; + request_info_.secure_dns_only = true; + int rv = transaction_->RestartWithSecureDnsOnly(base::BindOnce( + &URLRequestHttpJob::OnStartCompleted, base::Unretained(this))); + if (rv == ERR_IO_PENDING) { + return; + } + + // The transaction started synchronously, but we need to notify the + // URLRequest delegate via the message loop. + base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, base::BindOnce(&URLRequestHttpJob::OnStartCompleted, + weak_factory_.GetWeakPtr(), rv)); +} + +void URLRequestHttpJob::MaybeRetryWithSecureDnsOnly(int result) { + state_ = RetryState::DOH_FALLBACK; + if (CanRetryWithSecureDnsOnly(result)) { + original_net_error_ = result; + RetryWithSecureDnsOnly(); + return; + } + OnStartCompleted(result); +} +#endif // OHOS_EX_HTTP_DNS_FALLBACK +#endif // BUILDFLAG(IS_OHOS) + void URLRequestHttpJob::OnStartCompleted(int result) { TRACE_EVENT0(NetTracingCategory(), "URLRequestHttpJob::OnStartCompleted"); + +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + switch (state_) { + case RetryState::INIT: + MaybeRetryWithSecureDnsOnly(result); + return; + + case RetryState::DOH_FALLBACK: + if (result == net::ERR_NAME_NOT_RESOLVED && original_net_error_) { + if (transaction_ && transaction_->GetResponseInfo() && + transaction_->GetResponseInfo()->resolve_error_info.error != + net::ERR_NAME_NOT_RESOLVED) { + result = original_net_error_; + } + } + break; + + case RetryState::MAX: + // do nothing + break; + } +#endif + RecordTimer(); // If the job is done (due to cancellation), can just ignore this diff --git a/net/url_request/url_request_http_job.h b/net/url_request/url_request_http_job.h index 0d6c64d85d95bae2a84401302b8c7705c92db908..361961a502005c642bc9a584ec32d51f8808b8e0 100644 --- a/net/url_request/url_request_http_job.h +++ b/net/url_request/url_request_http_job.h @@ -107,6 +107,14 @@ class NET_EXPORT_PRIVATE URLRequestHttpJob : public URLRequestJob { kMaxValue = kSecureSetNonsecureRequest // Keep as the last value. }; +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + enum class RetryState { + INIT, + DOH_FALLBACK, + MAX, + }; +#endif + typedef base::RefCountedData SharedBoolean; // Shadows URLRequestJob's version of this method so we can grab cookies. @@ -173,6 +181,12 @@ class NET_EXPORT_PRIVATE URLRequestHttpJob : public URLRequestJob { IPEndPoint GetResponseRemoteEndpoint() const override; void NotifyURLRequestDestroyed() override; +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + bool CanRetryWithSecureDnsOnly(int net_error); + void RetryWithSecureDnsOnly(); + void MaybeRetryWithSecureDnsOnly(int result); +#endif + void RecordTimer(); void ResetTimer(); @@ -320,6 +334,11 @@ class NET_EXPORT_PRIVATE URLRequestHttpJob : public URLRequestJob { // "uncomputed" from "nothing". absl::optional> cookie_partition_key_; +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + int original_net_error_ = 0; + RetryState state_ = RetryState::INIT; +#endif + base::WeakPtrFactory weak_factory_{this}; }; diff --git a/services/network/network_service.cc b/services/network/network_service.cc index 71fb1f4f8ea2d0049a7eaa2b7be6467668b678db..4e87c527da2567e3d97a675b725db43fe93e17ff 100644 --- a/services/network/network_service.cc +++ b/services/network/network_service.cc @@ -569,6 +569,10 @@ void NetworkService::RegisterNetworkContext(NetworkContext* network_context) { LOG(INFO) << "Register network context and set network timeout " << timeout_override_ << " second(s)"; url_request_context->SetConnectTimeout(timeout_override_); +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + url_request_context->SetConnectJobWithSecureDnsOnlyTimeout( + connect_job_with_secure_dns_only_timeout_); +#endif } #endif network_contexts_.insert(network_context); @@ -695,10 +699,18 @@ void NetworkService::ConfigureStubHostResolver( insecure_dns_client_enabled, additional_dns_types_enabled); #if defined(OHOS_HTTP_DNS) + net::DnsConfigOverrides overrides; +#ifndef OHOS_EX_HTTP_DNS_FALLBACK // Since the system dnsconfig is not obtained and null in OHOS, so override // the full config with default. - net::DnsConfigOverrides overrides = - net::DnsConfigOverrides::CreateOverridingEverythingWithDefaults(); + overrides = net::DnsConfigOverrides::CreateOverridingEverythingWithDefaults(); +#else + // 如果使能Doh,则不需要获取获取Dns name servers + if (secure_dns_mode != net::SecureDnsMode::kOff) { + overrides = + net::DnsConfigOverrides::CreateOverridingEverythingWithDefaults(); + } +#endif overrides.secure_dns_mode = secure_dns_mode; overrides.dns_over_https_config = dns_over_https_config; @@ -1050,4 +1062,76 @@ void NetworkService::SetConnectTimeout(int seconds) { } #endif +#ifdef OHOS_EX_HTTP_DNS_FALLBACK +void NetworkService::SetHttpsDnsFallbackData( + mojom::HttpsDnsFallbackConfigPtr config) { + bool https_dns_fallback_enabled = false; + std::string http_dns_server_template; + // int connect_job_with_dns_only_timeout = 15; + std::vector host_list; + std::vector ip_list; + if (config) { + LOG(INFO) << "SetHttpsDnsFallbackData, enabled " << config->enabled + << ", connect_job_with_dns_only_timeout " + << config->connect_job_with_dns_only_timeout + << ", https_dns_server_template " + << config->https_dns_server_template << ", source_host_list.size " + << config->source_host_list.size() << ", suspect_ip_list.size " + << config->suspect_ip_list.size(); + https_dns_fallback_enabled = config->enabled; + http_dns_server_template = config->https_dns_server_template; + connect_job_with_secure_dns_only_timeout_ = + config->connect_job_with_dns_only_timeout; + host_list = std::move(config->source_host_list); + ip_list = std::move(config->suspect_ip_list); + } + + SetHttpsDnsHostResolver(https_dns_fallback_enabled, http_dns_server_template); + for (auto* network_context : network_contexts_) { + net::URLRequestContext* url_request_context = + network_context->url_request_context(); + if (url_request_context) { + url_request_context->SetConnectJobWithSecureDnsOnlyTimeout( + connect_job_with_secure_dns_only_timeout_); + } + } + + host_resolver_manager_->SetSuspectIpListAndSourceHostList(ip_list, host_list); +} + +void NetworkService::SetHttpsDnsHostResolver( + bool enabled, + const std::string& server_template) { + bool allow_enable_http_dns_fallback = false; + net::DnsOverHttpsConfig doh_fallback_config; + if (enabled) { + doh_fallback_config = + net::DnsOverHttpsConfig::FromStringLax(server_template); + if (doh_fallback_config.servers().size() > 0) { + allow_enable_http_dns_fallback = true; + } + } + + host_resolver_manager_->SetHttpsDnsFallbackData( + allow_enable_http_dns_fallback, server_template); + + // Enable or disable the insecure part of DnsClient. "DnsClient" is the class + // that implements the stub resolver. + host_resolver_manager_->SetInsecureDnsClientEnabled( + allow_enable_http_dns_fallback, false); + + net::DnsConfigOverrides overrides; + // 如果HTTP DNS FALLBACK去使能,则不需要获取Dns name servers + if (!allow_enable_http_dns_fallback) { + overrides = + net::DnsConfigOverrides::CreateOverridingEverythingWithDefaults(); + } + overrides.secure_dns_mode = net::SecureDnsMode::kOff; + overrides.dns_over_https_config = doh_fallback_config; + overrides.allow_dns_over_https_upgrade = false; + + host_resolver_manager_->SetDnsConfigOverrides(overrides); +} +#endif + } // namespace network diff --git a/services/network/network_service.h b/services/network/network_service.h index 37a60dd557c01736c3e0d45069cecbe3a5303d6a..8da5992922db9f7872c8ef39c99ba78aba569e01 100644 --- a/services/network/network_service.h +++ b/services/network/network_service.h @@ -61,6 +61,10 @@ #include "services/network/public/mojom/ct_log_info.mojom.h" #endif +#ifdef OHOS_EX_HTTP_DNS_FALLBACK +#include "services/network/public/mojom/network_config_ohos.mojom.h" +#endif + namespace net { class FileNetLogObserver; class HostResolverManager; @@ -309,6 +313,11 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkService void SetConnectTimeout(int seconds) override; #endif +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + void SetHttpsDnsFallbackData( + mojom::HttpsDnsFallbackConfigPtr config) override; +#endif + private: class DelayedDohProbeActivator; @@ -326,6 +335,11 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkService void SetSystemDnsResolver( mojo::PendingRemote override_remote); +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + void SetHttpsDnsHostResolver(bool enabled, + const std::string& server_template); +#endif + bool initialized_ = false; enum class FunctionTag : uint8_t { @@ -445,6 +459,9 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkService #if defined(OHOS_EX_NETWORK_CONNECTION) int timeout_override_ = 0; #endif +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + int connect_job_with_secure_dns_only_timeout_{15}; +#endif }; } // namespace network diff --git a/services/network/public/mojom/BUILD.gn b/services/network/public/mojom/BUILD.gn index 6322a324dacae1ad97ee767adc7b65b1edb30880..f4d431d78da9122aecf9b781abfbd42b19ed9df1 100644 --- a/services/network/public/mojom/BUILD.gn +++ b/services/network/public/mojom/BUILD.gn @@ -477,7 +477,7 @@ mojom("url_loader_base") { } if (defined(ohos_network_load) && ohos_network_load) { - enabled_features += ["is_ohos_network_load"] + enabled_features += [ "is_ohos_network_load" ] } # Shared by cpp_typemaps and blink_cpp_typemaps. @@ -1323,6 +1323,14 @@ mojom("mojom") { "url_loader_factory.mojom", ] + + # ifdef OHOS_EX_HTTP_DNS_FALLBACK + if (defined(ohos_ex_http_dns_fallback) && ohos_ex_http_dns_fallback) { + sources += [ "network_config_ohos.mojom" ] + } + + # endif + public_deps = [ ":cookies_mojom", ":mojom_first_party_sets", diff --git a/services/network/public/mojom/network_config_ohos.mojom b/services/network/public/mojom/network_config_ohos.mojom new file mode 100644 index 0000000000000000000000000000000000000000..78bfcf08eafa5ca794d608067470a353f4103af6 --- /dev/null +++ b/services/network/public/mojom/network_config_ohos.mojom @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +module network.mojom; + +struct HttpsDnsFallbackConfig { + bool enabled = false; + int32 connect_job_with_dns_only_timeout; + string https_dns_server_template; + array source_host_list; + array suspect_ip_list; +}; \ No newline at end of file diff --git a/services/network/public/mojom/network_service.mojom b/services/network/public/mojom/network_service.mojom index 4da5e9d64b1a4b105ae00081a4b69451abe46a03..33db878e3239bfa18908fc542bd7cad87078a216 100644 --- a/services/network/public/mojom/network_service.mojom +++ b/services/network/public/mojom/network_service.mojom @@ -41,6 +41,11 @@ import "mojo/public/mojom/base/application_state.mojom"; [EnableIf=is_ct_supported] import "services/network/public/mojom/ct_log_info.mojom"; +// #ifdef OHOS_EX_HTTP_DNS_FALLBACK +[EnableIf=ohos_ex_http_dns_fallback] +import "services/network/public/mojom/network_config_ohos.mojom"; +// #endif OHOS_EX_HTTP_DNS_FALLBACK + // Values for configuring HTTP authentication that can only be set once. struct HttpAuthStaticParams { // File name the GSSAPI library to load. Only supported on platforms where an @@ -378,4 +383,9 @@ interface NetworkService { [EnableIf=ohos_ex_network_connection] SetConnectTimeout(int32 seconds); // #endif + + // #ifdef OHOS_EX_HTTP_DNS_FALLBACK + [EnableIf=ohos_ex_http_dns_fallback] + SetHttpsDnsFallbackData(network.mojom.HttpsDnsFallbackConfig config); + // #endif }; diff --git a/services/network/throttling/throttling_network_transaction.cc b/services/network/throttling/throttling_network_transaction.cc index acbdcf75a4742b8f276272393b79b91fd7a173ab..258692f12214ce1b3cd3d7450e7549268fa100c0 100644 --- a/services/network/throttling/throttling_network_transaction.cc +++ b/services/network/throttling/throttling_network_transaction.cc @@ -149,6 +149,23 @@ int ThrottlingNetworkTransaction::Start(const net::HttpRequestInfo* request, return Throttle(true, result); } +#ifdef OHOS_EX_HTTP_DNS_FALLBACK +int ThrottlingNetworkTransaction::RestartWithSecureDnsOnly( + net::CompletionOnceCallback callback) { + if (CheckFailed()) { + return net::ERR_INTERNET_DISCONNECTED; + } + if (!interceptor_) { + return network_transaction_->RestartWithSecureDnsOnly(std::move(callback)); + } + + callback_ = std::move(callback); + int result = network_transaction_->RestartWithSecureDnsOnly(base::BindOnce( + &ThrottlingNetworkTransaction::IOCallback, base::Unretained(this), true)); + return Throttle(true, result); +} +#endif + int ThrottlingNetworkTransaction::RestartIgnoringLastError( net::CompletionOnceCallback callback) { if (CheckFailed()) diff --git a/services/network/throttling/throttling_network_transaction.h b/services/network/throttling/throttling_network_transaction.h index bb54701046c69ee7b8e22ad801c13b92ef102afd..4336c6d0846faa13e6ef6286b0c3e05b81a65753 100644 --- a/services/network/throttling/throttling_network_transaction.h +++ b/services/network/throttling/throttling_network_transaction.h @@ -56,6 +56,9 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) ThrottlingNetworkTransaction int Start(const net::HttpRequestInfo* request, net::CompletionOnceCallback callback, const net::NetLogWithSource& net_log) override; +#ifdef OHOS_EX_HTTP_DNS_FALLBACK + int RestartWithSecureDnsOnly(net::CompletionOnceCallback callback) override; +#endif // OHOS_EX_HTTP_DNS_FALLBACK int RestartIgnoringLastError(net::CompletionOnceCallback callback) override; int RestartWithCertificate( scoped_refptr client_cert,