| // Copyright 2017 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CONTENT_BROWSER_PRELOADING_PRECONNECT_PRECONNECT_MANAGER_IMPL_H_ |
| #define CONTENT_BROWSER_PRELOADING_PRECONNECT_PRECONNECT_MANAGER_IMPL_H_ |
| |
| #include <list> |
| #include <map> |
| #include <memory> |
| #include <string> |
| #include <vector> |
| |
| #include "base/containers/id_map.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/time/time.h" |
| #include "content/browser/preloading/proxy_lookup_client_impl.h" |
| #include "content/browser/preloading/resolve_host_client_impl.h" |
| #include "content/public/browser/preconnect_manager.h" |
| #include "content/public/browser/preconnect_request.h" |
| #include "content/public/browser/storage_partition_config.h" |
| #include "net/base/network_anonymization_key.h" |
| #include "services/network/public/mojom/connection_change_observer_client.mojom.h" |
| #include "url/gurl.h" |
| |
| namespace network::mojom { |
| class NetworkContext; |
| } // namespace network::mojom |
| |
| namespace content { |
| |
| class BrowserContext; |
| |
| // Stores the status of all preconnects associated with a given |url|. |
| struct CONTENT_EXPORT PreresolveInfo { |
| PreresolveInfo(const GURL& url, size_t count); |
| |
| PreresolveInfo(const PreresolveInfo&) = delete; |
| PreresolveInfo& operator=(const PreresolveInfo&) = delete; |
| |
| ~PreresolveInfo(); |
| |
| bool is_done() const { return queued_count == 0 && inflight_count == 0; } |
| |
| GURL url; |
| size_t queued_count; |
| size_t inflight_count = 0; |
| bool was_canceled = false; |
| std::unique_ptr<PreconnectStats> stats; |
| }; |
| |
| // Stores all data need for running a preresolve and a subsequent optional |
| // preconnect for a |url|. |
| struct CONTENT_EXPORT PreresolveJob { |
| PreresolveJob( |
| const GURL& url, |
| int num_sockets, |
| bool allow_credentials, |
| net::NetworkAnonymizationKey network_anonymization_key, |
| net::NetworkTrafficAnnotationTag traffic_annotation_tag, |
| std::optional<content::StoragePartitionConfig> storage_partition_config, |
| std::optional<net::ConnectionKeepAliveConfig> keepalive_config, |
| mojo::PendingRemote<network::mojom::ConnectionChangeObserverClient> |
| connection_change_observer_client, |
| PreresolveInfo* info); |
| |
| PreresolveJob(const PreresolveJob&) = delete; |
| PreresolveJob& operator=(const PreresolveJob&) = delete; |
| |
| PreresolveJob(content::PreconnectRequest preconnect_request, |
| PreresolveInfo* info, |
| net::NetworkTrafficAnnotationTag traffic_annotation_tag); |
| PreresolveJob(PreresolveJob&& other); |
| |
| ~PreresolveJob(); |
| |
| bool need_preconnect() const { |
| return num_sockets > 0 && !(info && info->was_canceled); |
| } |
| |
| GURL url; |
| int num_sockets; |
| bool allow_credentials; |
| net::NetworkAnonymizationKey network_anonymization_key; |
| net::NetworkTrafficAnnotationTag traffic_annotation_tag; |
| // The default for the profile is used if this is absent. |
| std::optional<content::StoragePartitionConfig> storage_partition_config; |
| |
| std::optional<net::ConnectionKeepAliveConfig> keepalive_config; |
| mojo::PendingRemote<network::mojom::ConnectionChangeObserverClient> |
| connection_change_observer_client; |
| // Raw pointer usage is fine here because even though PreresolveJob can |
| // outlive PreresolveInfo. It's only accessed on PreconnectManager class |
| // context and PreresolveInfo lifetime is tied to PreconnectManager. |
| // May be equal to nullptr in case of detached job. |
| raw_ptr<PreresolveInfo, DanglingUntriaged> info; |
| std::unique_ptr<ResolveHostClientImpl> resolve_host_client; |
| std::unique_ptr<ProxyLookupClientImpl> proxy_lookup_client; |
| base::TimeTicks creation_time; |
| }; |
| |
| class CONTENT_EXPORT PreconnectManagerImpl : public PreconnectManager { |
| public: |
| static const size_t kMaxInflightPreresolves = 3; |
| |
| PreconnectManagerImpl(base::WeakPtr<PreconnectManager::Delegate> delegate, |
| content::BrowserContext* browser_context); |
| |
| PreconnectManagerImpl(const PreconnectManagerImpl&) = delete; |
| PreconnectManagerImpl& operator=(const PreconnectManagerImpl&) = delete; |
| |
| ~PreconnectManagerImpl() override; |
| |
| void Start(const GURL& url, |
| std::vector<content::PreconnectRequest> requests, |
| net::NetworkTrafficAnnotationTag traffic_annotation) override; |
| |
| void StartPreresolveHost( |
| const GURL& url, |
| const net::NetworkAnonymizationKey& network_anonymization_key, |
| net::NetworkTrafficAnnotationTag traffic_annotation, |
| const content::StoragePartitionConfig* storage_partition_config) override; |
| void StartPreresolveHosts( |
| const std::vector<GURL>& urls, |
| const net::NetworkAnonymizationKey& network_anonymization_key, |
| net::NetworkTrafficAnnotationTag traffic_annotation, |
| const content::StoragePartitionConfig* storage_partition_config) override; |
| void StartPreconnectUrl( |
| const GURL& url, |
| bool allow_credentials, |
| net::NetworkAnonymizationKey network_anonymization_key, |
| net::NetworkTrafficAnnotationTag traffic_annotation, |
| const content::StoragePartitionConfig* storage_partition_config, |
| std::optional<net::ConnectionKeepAliveConfig> keepalive_config, |
| mojo::PendingRemote<network::mojom::ConnectionChangeObserverClient> |
| connection_change_observer_client) override; |
| |
| void Stop(const GURL& url) override; |
| |
| base::WeakPtr<PreconnectManager> GetWeakPtr() override; |
| |
| void SetNetworkContextForTesting( |
| network::mojom::NetworkContext* network_context) override; |
| void SetObserverForTesting(Observer* observer) override; |
| |
| private: |
| using PreresolveJobMap = base::IDMap<std::unique_ptr<PreresolveJob>>; |
| using PreresolveJobId = PreresolveJobMap::KeyType; |
| friend class PreconnectManagerImplTest; |
| |
| void PreconnectUrl( |
| const GURL& url, |
| int num_sockets, |
| bool allow_credentials, |
| const net::NetworkAnonymizationKey& network_anonymization_key, |
| const net::NetworkTrafficAnnotationTag& traffic_annotation, |
| const content::StoragePartitionConfig* storage_partition_config, |
| std::optional<net::ConnectionKeepAliveConfig> keepalive_config, |
| mojo::PendingRemote<network::mojom::ConnectionChangeObserverClient> |
| connection_change_observer_client) const; |
| std::unique_ptr<ResolveHostClientImpl> PreresolveUrl( |
| const GURL& url, |
| const net::NetworkAnonymizationKey& network_anonymization_key, |
| const content::StoragePartitionConfig* storage_partition_config, |
| ResolveHostCallback callback) const; |
| std::unique_ptr<ProxyLookupClientImpl> LookupProxyForUrl( |
| const GURL& url, |
| const net::NetworkAnonymizationKey& network_anonymization_key, |
| const content::StoragePartitionConfig* storage_partition_config, |
| ProxyLookupClientImpl::ProxyLookupCallback callback) const; |
| |
| void TryToLaunchPreresolveJobs(); |
| void OnPreresolveFinished(PreresolveJobId job_id, bool success); |
| void OnProxyLookupFinished(PreresolveJobId job_id, bool success); |
| void FinishPreresolveJob(PreresolveJobId job_id, bool success); |
| void AllPreresolvesForUrlFinished(PreresolveInfo* info); |
| |
| // NOTE: Returns a non-null pointer outside of unittesting contexts. |
| network::mojom::NetworkContext* GetNetworkContext( |
| const content::StoragePartitionConfig* storage_partition_config) const; |
| |
| base::WeakPtr<Delegate> delegate_; |
| const raw_ptr<content::BrowserContext> browser_context_; |
| std::list<PreresolveJobId> queued_jobs_; |
| PreresolveJobMap preresolve_jobs_; |
| std::map<GURL, std::unique_ptr<PreresolveInfo>> preresolve_info_; |
| size_t inflight_preresolves_count_ = 0; |
| |
| // Only used in tests. |
| raw_ptr<network::mojom::NetworkContext> network_context_ = nullptr; |
| raw_ptr<Observer> observer_ = nullptr; |
| |
| base::WeakPtrFactory<PreconnectManagerImpl> weak_factory_{this}; |
| }; |
| |
| } // namespace content |
| |
| #endif // CONTENT_BROWSER_PRELOADING_PRECONNECT_PRECONNECT_MANAGER_IMPL_H_ |