danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 1 | // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #ifndef CONTENT_BROWSER_RENDERER_HOST_NAVIGATOR_H_ |
| 6 | #define CONTENT_BROWSER_RENDERER_HOST_NAVIGATOR_H_ |
| 7 | |
| 8 | #include <memory> |
| 9 | |
| 10 | #include "base/macros.h" |
| 11 | #include "base/memory/ref_counted.h" |
| 12 | #include "content/common/content_export.h" |
| 13 | #include "content/common/navigation_client.mojom.h" |
| 14 | #include "content/common/navigation_params.h" |
| 15 | #include "content/common/navigation_params.mojom.h" |
| 16 | #include "content/public/browser/navigation_controller.h" |
| 17 | #include "content/public/common/impression.h" |
| 18 | #include "mojo/public/cpp/bindings/pending_associated_remote.h" |
| 19 | #include "mojo/public/cpp/bindings/pending_remote.h" |
| 20 | #include "third_party/blink/public/common/loader/previews_state.h" |
| 21 | #include "third_party/blink/public/common/navigation/triggering_event_info.h" |
| 22 | #include "third_party/blink/public/mojom/frame/navigation_initiator.mojom.h" |
| 23 | #include "ui/base/window_open_disposition.h" |
| 24 | |
| 25 | class GURL; |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 26 | |
| 27 | namespace base { |
| 28 | class TimeTicks; |
| 29 | } |
| 30 | |
| 31 | namespace network { |
| 32 | class ResourceRequestBody; |
| 33 | } |
| 34 | |
| 35 | namespace content { |
| 36 | |
| 37 | class FrameNavigationEntry; |
| 38 | class FrameTreeNode; |
| 39 | class NavigationControllerImpl; |
| 40 | class NavigatorDelegate; |
| 41 | class NavigationEntryImpl; |
| 42 | class NavigationRequest; |
| 43 | class PrefetchedSignedExchangeCache; |
| 44 | class RenderFrameHostImpl; |
| 45 | class WebBundleHandleTracker; |
| 46 | struct LoadCommittedDetails; |
W. James MacLean | 46cf2621 | 2020-10-01 16:43:37 | [diff] [blame] | 47 | struct UrlInfo; |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 48 | |
| 49 | // Navigator is responsible for performing navigations in nodes of the |
| 50 | // FrameTree. Its lifetime is bound to the FrameTree. |
| 51 | class CONTENT_EXPORT Navigator { |
| 52 | public: |
| 53 | Navigator(NavigationControllerImpl* navigation_controller, |
| 54 | NavigatorDelegate* delegate); |
| 55 | ~Navigator(); |
| 56 | |
| 57 | // This method verifies that a navigation to |url| doesn't commit into a WebUI |
| 58 | // process if it is not allowed to. Callers of this method should take one of |
| 59 | // two actions if the method returns false: |
| 60 | // * When called from browser process logic (e.g. NavigationRequest), this |
| 61 | // indicates issues with the navigation logic and the browser process must |
| 62 | // be terminated to avoid security issues. |
| 63 | // * If the codepath is processing an IPC message from a renderer process, |
| 64 | // then the renderer process is misbehaving and must be terminated. |
| 65 | // TODO(nasko): Remove the is_renderer_initiated_check parameter when callers |
| 66 | // of this method are migrated to use CHECK instead of DumpWithoutCrashing. |
| 67 | static WARN_UNUSED_RESULT bool CheckWebUIRendererDoesNotDisplayNormalURL( |
| 68 | RenderFrameHostImpl* render_frame_host, |
W. James MacLean | 46cf2621 | 2020-10-01 16:43:37 | [diff] [blame] | 69 | const UrlInfo& url_info, |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 70 | bool is_renderer_initiated_check); |
| 71 | |
| 72 | static bool ShouldIgnoreIncomingRendererRequest( |
| 73 | const NavigationRequest* ongoing_navigation_request, |
| 74 | bool has_user_gesture); |
| 75 | |
| 76 | // Returns the delegate of this Navigator. |
| 77 | NavigatorDelegate* GetDelegate(); |
| 78 | |
| 79 | // Returns the NavigationController associated with this Navigator. |
| 80 | NavigationController* GetController(); |
| 81 | |
| 82 | // Notifications coming from the RenderFrameHosts ---------------------------- |
| 83 | |
| 84 | // The RenderFrameHostImpl has failed to load the document. |
| 85 | void DidFailLoadWithError(RenderFrameHostImpl* render_frame_host, |
| 86 | const GURL& url, |
| 87 | int error_code); |
| 88 | |
| 89 | // The RenderFrameHostImpl has committed a navigation. The Navigator is |
| 90 | // responsible for resetting |navigation_request| at the end of this method |
| 91 | // and should not attempt to keep it alive. Note: it is possible that |
| 92 | // |navigation_request| is not the NavigationRequest stored in the |
| 93 | // RenderFrameHost that just committed. This happens for example when a |
| 94 | // same-page navigation commits while another navigation is ongoing. The |
| 95 | // Navigator should use the NavigationRequest provided by this method and not |
| 96 | // attempt to access the RenderFrameHost's NavigationsRequests. |
| 97 | void DidNavigate(RenderFrameHostImpl* render_frame_host, |
arthursonzogni | 73fe321 | 2020-11-17 13:24:07 | [diff] [blame^] | 98 | const mojom::DidCommitProvisionalLoadParams& params, |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 99 | std::unique_ptr<NavigationRequest> navigation_request, |
| 100 | bool was_within_same_document); |
| 101 | |
| 102 | // Called on a newly created subframe during a history navigation. The browser |
| 103 | // process looks up the corresponding FrameNavigationEntry for the new frame |
| 104 | // navigates it in the correct process. Returns false if the |
| 105 | // FrameNavigationEntry can't be found or the navigation fails. |
| 106 | bool StartHistoryNavigationInNewSubframe( |
| 107 | RenderFrameHostImpl* render_frame_host, |
| 108 | mojo::PendingAssociatedRemote<mojom::NavigationClient>* |
| 109 | navigation_client); |
| 110 | |
| 111 | // Navigation requests ------------------------------------------------------- |
| 112 | |
| 113 | // Called by the NavigationController to cause the Navigator to navigate to |
| 114 | // |navigation_request|. The NavigationController should be called back with |
| 115 | // RendererDidNavigate on success or DiscardPendingEntry on failure. The |
| 116 | // callbacks should be called in a future iteration of the message loop. |
| 117 | void Navigate(std::unique_ptr<NavigationRequest> request, |
| 118 | ReloadType reload_type, |
| 119 | RestoreType restore_type); |
| 120 | |
| 121 | // The RenderFrameHostImpl has received a request to open a URL with the |
| 122 | // specified |disposition|. |
| 123 | void RequestOpenURL( |
| 124 | RenderFrameHostImpl* render_frame_host, |
| 125 | const GURL& url, |
| 126 | const GlobalFrameRoutingId& initiator_routing_id, |
| 127 | const base::Optional<url::Origin>& initiator_origin, |
| 128 | const scoped_refptr<network::ResourceRequestBody>& post_body, |
| 129 | const std::string& extra_headers, |
| 130 | const Referrer& referrer, |
| 131 | WindowOpenDisposition disposition, |
| 132 | bool should_replace_current_entry, |
| 133 | bool user_gesture, |
| 134 | blink::TriggeringEventInfo triggering_event_info, |
| 135 | const std::string& href_translate, |
| 136 | scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory, |
| 137 | const base::Optional<Impression>& impression); |
| 138 | |
| 139 | // Called when a document requests a navigation in another document through a |
| 140 | // RenderFrameProxy. If |method| is "POST", then |post_body| needs to specify |
| 141 | // the request body, otherwise |post_body| should be null. |
| 142 | void NavigateFromFrameProxy( |
| 143 | RenderFrameHostImpl* render_frame_host, |
| 144 | const GURL& url, |
| 145 | const GlobalFrameRoutingId& initiator_routing_id, |
| 146 | const url::Origin& initiator_origin, |
| 147 | SiteInstance* source_site_instance, |
| 148 | const Referrer& referrer, |
| 149 | ui::PageTransition page_transition, |
| 150 | bool should_replace_current_entry, |
| 151 | NavigationDownloadPolicy download_policy, |
| 152 | const std::string& method, |
| 153 | scoped_refptr<network::ResourceRequestBody> post_body, |
| 154 | const std::string& extra_headers, |
| 155 | scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory, |
| 156 | bool has_user_gesture, |
| 157 | const base::Optional<Impression>& impression); |
| 158 | |
| 159 | // Called after BeforeUnloadCompleted callback is invoked from the renderer. |
| 160 | // If |frame_tree_node| has a NavigationRequest waiting for the renderer |
| 161 | // response, then the request is either started or canceled, depending on the |
| 162 | // value of |proceed|. |
| 163 | void BeforeUnloadCompleted(FrameTreeNode* frame_tree_node, |
| 164 | bool proceed, |
| 165 | const base::TimeTicks& proceed_time); |
| 166 | |
| 167 | // Used to start a new renderer-initiated navigation, following a |
| 168 | // BeginNavigation IPC from the renderer. |
| 169 | void OnBeginNavigation( |
| 170 | FrameTreeNode* frame_tree_node, |
| 171 | mojom::CommonNavigationParamsPtr common_params, |
| 172 | mojom::BeginNavigationParamsPtr begin_params, |
| 173 | scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory, |
| 174 | mojo::PendingAssociatedRemote<mojom::NavigationClient> navigation_client, |
| 175 | mojo::PendingRemote<blink::mojom::NavigationInitiator> |
| 176 | navigation_initiator, |
| 177 | scoped_refptr<PrefetchedSignedExchangeCache> |
| 178 | prefetched_signed_exchange_cache, |
| 179 | std::unique_ptr<WebBundleHandleTracker> web_bundle_handle_tracker); |
| 180 | |
| 181 | // Used to restart a navigation that was thought to be same-document in |
| 182 | // cross-document mode. |
| 183 | void RestartNavigationAsCrossDocument( |
| 184 | std::unique_ptr<NavigationRequest> navigation_request); |
| 185 | |
| 186 | // Cancel a NavigationRequest for |frame_tree_node|. |
| 187 | void CancelNavigation(FrameTreeNode* frame_tree_node); |
| 188 | |
| 189 | // Called when the network stack started handling the navigation request |
| 190 | // so that the |timestamp| when it happened can be recorded into an histogram. |
| 191 | // The |url| is used to verify we're tracking the correct navigation. |
| 192 | // TODO(carlosk): Remove the URL parameter and rename this method to better |
| 193 | // suit naming conventions. |
| 194 | void LogResourceRequestTime(base::TimeTicks timestamp, const GURL& url); |
| 195 | |
| 196 | // Called to record the time it took to execute the beforeunload hook for the |
| 197 | // current navigation. |
| 198 | void LogBeforeUnloadTime(base::TimeTicks renderer_before_unload_start_time, |
| 199 | base::TimeTicks renderer_before_unload_end_time, |
| 200 | base::TimeTicks before_unload_sent_time); |
| 201 | |
| 202 | NavigationControllerImpl* controller() { return controller_; } |
| 203 | |
| 204 | private: |
| 205 | friend class NavigatorTestWithBrowserSideNavigation; |
| 206 | |
| 207 | // Holds data used to track browser side navigation metrics. |
| 208 | struct NavigationMetricsData; |
| 209 | |
| 210 | void RecordNavigationMetrics( |
| 211 | const LoadCommittedDetails& details, |
arthursonzogni | 73fe321 | 2020-11-17 13:24:07 | [diff] [blame^] | 212 | const mojom::DidCommitProvisionalLoadParams& params, |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 213 | SiteInstance* site_instance); |
| 214 | |
| 215 | // Called when a renderer initiated navigation has started. Returns the |
| 216 | // pending NavigationEntry to be used. Either null or a new one owned |
| 217 | // NavigationController. |
| 218 | NavigationEntryImpl* GetNavigationEntryForRendererInitiatedNavigation( |
| 219 | const mojom::CommonNavigationParams& common_params, |
| 220 | FrameTreeNode* frame_tree_node); |
| 221 | |
| 222 | // Called to record the time it took to execute beforeunload handlers for |
| 223 | // renderer-inititated navigations. It records the time it took to execute |
| 224 | // beforeunload handlers in the renderer process before sending the |
| 225 | // BeginNavigation IPC. |
| 226 | void LogRendererInitiatedBeforeUnloadTime( |
| 227 | base::TimeTicks renderer_before_unload_start_time, |
| 228 | base::TimeTicks renderer_before_unload_end_time); |
| 229 | |
| 230 | // The NavigationController that will keep track of session history for all |
| 231 | // RenderFrameHost objects using this Navigator. |
| 232 | // TODO(nasko): Move ownership of the NavigationController from |
| 233 | // WebContentsImpl to this class. |
| 234 | NavigationControllerImpl* controller_; |
| 235 | |
| 236 | // Used to notify the object embedding this Navigator about navigation |
| 237 | // events. Can be nullptr in tests. |
| 238 | NavigatorDelegate* delegate_; |
| 239 | |
| 240 | std::unique_ptr<Navigator::NavigationMetricsData> navigation_data_; |
| 241 | |
| 242 | DISALLOW_COPY_AND_ASSIGN(Navigator); |
| 243 | }; |
| 244 | |
| 245 | } // namespace content |
| 246 | |
| 247 | #endif // CONTENT_BROWSER_RENDERER_HOST_NAVIGATOR_H_ |