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