| // Copyright 2022 The Chromium Authors | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #ifndef CHROME_BROWSER_SSL_HTTPS_UPGRADES_INTERCEPTOR_H_ | 
 | #define CHROME_BROWSER_SSL_HTTPS_UPGRADES_INTERCEPTOR_H_ | 
 |  | 
 | #include <memory> | 
 | #include <optional> | 
 |  | 
 | #include "base/memory/raw_ptr.h" | 
 | #include "base/memory/weak_ptr.h" | 
 | #include "base/sequence_checker.h" | 
 | #include "chrome/browser/ssl/https_only_mode_tab_helper.h" | 
 | #include "components/security_interstitials/core/https_only_mode_metrics.h" | 
 | #include "content/public/browser/url_loader_request_interceptor.h" | 
 | #include "mojo/public/cpp/bindings/receiver.h" | 
 | #include "mojo/public/cpp/bindings/remote.h" | 
 | #include "mojo/public/cpp/system/data_pipe.h" | 
 | #include "net/base/request_priority.h" | 
 | #include "net/http/http_request_headers.h" | 
 | #include "services/network/public/cpp/resource_request.h" | 
 | #include "services/network/public/cpp/url_loader_completion_status.h" | 
 | #include "services/network/public/mojom/url_loader.mojom.h" | 
 | #include "url/gurl.h" | 
 |  | 
 | namespace blink { | 
 | class ThrottlingURLLoader; | 
 | }  // namespace blink | 
 |  | 
 | namespace content { | 
 | class BrowserContext; | 
 | class NavigationUIData; | 
 | class WebContents; | 
 | }  // namespace content | 
 |  | 
 | // A class that attempts to intercept HTTP navigation requests and redirect them | 
 | // to HTTPS, and then if the upgraded requests fail redirect them back to HTTP. | 
 | // Its lifetime matches that of the content/ navigation loader code. | 
 | // | 
 | // (Aside: An alternate implementation of this class would be as a | 
 | // NavigationLoaderInterceptor in content/, which could have a slightly simpler | 
 | // implementation, but by having this in chrome/ we don't need a Delegate | 
 | // interface for the embedder logic. If we move this into content/ in the future | 
 | // -- for example, in order to have a default HTTPS Upgrades implementation in | 
 | // the content/ platform -- then we can make that switch.) | 
 | class HttpsUpgradesInterceptor : public content::URLLoaderRequestInterceptor, | 
 |                                  public network::mojom::URLLoader { | 
 |  public: | 
 |   static std::unique_ptr<HttpsUpgradesInterceptor> MaybeCreateInterceptor( | 
 |       content::FrameTreeNodeId frame_tree_node_id, | 
 |       content::NavigationUIData* navigation_ui_data_); | 
 |  | 
 |   HttpsUpgradesInterceptor(content::FrameTreeNodeId frame_tree_node_id, | 
 |                            bool http_interstitial_enabled, | 
 |                            content::NavigationUIData* navigation_ui_data_); | 
 |   ~HttpsUpgradesInterceptor() override; | 
 |  | 
 |   HttpsUpgradesInterceptor(const HttpsUpgradesInterceptor&) = delete; | 
 |   HttpsUpgradesInterceptor& operator=(const HttpsUpgradesInterceptor&) = delete; | 
 |  | 
 |   // content::URLLoaderRequestInterceptor: | 
 |   void MaybeCreateLoader( | 
 |       const network::ResourceRequest& tentative_resource_request, | 
 |       content::BrowserContext* browser_context, | 
 |       content::URLLoaderRequestInterceptor::LoaderCallback callback) override; | 
 |   bool MaybeCreateLoaderForResponse( | 
 |       const network::URLLoaderCompletionStatus& status, | 
 |       const network::ResourceRequest& request, | 
 |       network::mojom::URLResponseHeadPtr* response_head, | 
 |       mojo::ScopedDataPipeConsumerHandle* response_body, | 
 |       mojo::PendingRemote<network::mojom::URLLoader>* loader, | 
 |       mojo::PendingReceiver<network::mojom::URLLoaderClient>* client_receiver, | 
 |       blink::ThrottlingURLLoader* url_loader) override; | 
 |  | 
 |   // Sets the ports used by the EmbeddedTestServer (which uses random ports) | 
 |   // to determine the correct port to upgrade/fallback to in tests. | 
 |   static void SetHttpsPortForTesting(int port); | 
 |   static void SetHttpPortForTesting(int port); | 
 |   static int GetHttpsPortForTesting(); | 
 |   static int GetHttpPortForTesting(); | 
 |  | 
 |  private: | 
 |   // Continuation of MaybeCreateLoader() after querying the network service for | 
 |   // the HSTS status for the hostname in the request. | 
 |   void MaybeCreateLoaderOnHstsQueryCompleted( | 
 |       GURL url, | 
 |       bool is_outermost_main_frame, | 
 |       std::string method, | 
 |       content::URLLoaderRequestInterceptor::LoaderCallback callback, | 
 |       bool is_hsts_active_for_host); | 
 |  | 
 |   // network::mojom::URLLoader: | 
 |   void FollowRedirect( | 
 |       const std::vector<std::string>& removed_headers, | 
 |       const net::HttpRequestHeaders& modified_headers, | 
 |       const net::HttpRequestHeaders& modified_cors_exempt_headers, | 
 |       const std::optional<GURL>& new_url) override {} | 
 |   void SetPriority(net::RequestPriority priority, | 
 |                    int intra_priority_value) override {} | 
 |  | 
 |   // Returns a RequestHandler callback that can be passed to the underlying | 
 |   // LoaderCallback to serve an artificial redirect to `new_url`. | 
 |   RequestHandler CreateRedirectHandler(const GURL& new_url); | 
 |  | 
 |   // Passed to the LoaderCallback as the ResponseHandler with `new_url` bound, | 
 |   // this method receives the receiver and client_remote from the | 
 |   // NavigationLoader, to bind against. Triggers a redirect to `new_url` using | 
 |   // `client`. | 
 |   void RedirectHandler( | 
 |       const GURL& new_url, | 
 |       const network::ResourceRequest& request, | 
 |       mojo::PendingReceiver<network::mojom::URLLoader> receiver, | 
 |       mojo::PendingRemote<network::mojom::URLLoaderClient> client); | 
 |  | 
 |   // Mojo error handling. Resets `receiver_` and `client_`. | 
 |   void OnConnectionClosed(); | 
 |  | 
 |   // Used to access the WebContents for the navigation. | 
 |   content::FrameTreeNodeId frame_tree_node_id_; | 
 |  | 
 |   // Controls whether we are upgrading and falling back with an interstitial | 
 |   // before proceeding with the HTTP navigation. This reflects the general | 
 |   // UI setting. Only used to set the values of interstitial_state_. | 
 |   bool http_interstitial_enabled_by_pref_ = false; | 
 |  | 
 |   // Parameters about whether the throttle should trigger the interstitial | 
 |   // warning before navigating to the HTTP fallback URL. Can be null if the | 
 |   // current load isn't eligible for an upgrade. | 
 |   std::unique_ptr< | 
 |       security_interstitials::https_only_mode::HttpInterstitialState> | 
 |       interstitial_state_; | 
 |  | 
 |   // URLs seen by the interceptor, used to detect a redirect loop. | 
 |   std::set<GURL> urls_seen_; | 
 |  | 
 |   // Receiver for the URLLoader interface. | 
 |   mojo::Receiver<network::mojom::URLLoader> receiver_{this}; | 
 |  | 
 |   // The owning client. Used for serving redirects. | 
 |   mojo::Remote<network::mojom::URLLoaderClient> client_; | 
 |  | 
 |   // Owned by NavigationURLLoaderImpl, which should outlive the interceptor. | 
 |   raw_ptr<content::NavigationUIData> navigation_ui_data_; | 
 |   SEQUENCE_CHECKER(sequence_checker_); | 
 |  | 
 |   base::WeakPtrFactory<HttpsUpgradesInterceptor> weak_factory_{this}; | 
 | }; | 
 |  | 
 | #endif  // CHROME_BROWSER_SSL_HTTPS_UPGRADES_INTERCEPTOR_H_ |