OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/frame_host/navigator_impl.h" | 5 #include "content/browser/frame_host/navigator_impl.h" |
6 | 6 |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/metrics/histogram.h" | 8 #include "base/metrics/histogram.h" |
9 #include "base/time/time.h" | 9 #include "base/time/time.h" |
10 #include "content/browser/frame_host/frame_tree.h" | 10 #include "content/browser/frame_host/frame_tree.h" |
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
224 } | 224 } |
225 | 225 |
226 bool NavigatorImpl::NavigateToEntry( | 226 bool NavigatorImpl::NavigateToEntry( |
227 FrameTreeNode* frame_tree_node, | 227 FrameTreeNode* frame_tree_node, |
228 const FrameNavigationEntry& frame_entry, | 228 const FrameNavigationEntry& frame_entry, |
229 const NavigationEntryImpl& entry, | 229 const NavigationEntryImpl& entry, |
230 NavigationController::ReloadType reload_type, | 230 NavigationController::ReloadType reload_type, |
231 bool is_same_document_history_load) { | 231 bool is_same_document_history_load) { |
232 TRACE_EVENT0("browser,navigation", "NavigatorImpl::NavigateToEntry"); | 232 TRACE_EVENT0("browser,navigation", "NavigatorImpl::NavigateToEntry"); |
233 | 233 |
| 234 GURL dest_url = frame_entry.url(); |
| 235 Referrer dest_referrer = frame_entry.referrer(); |
| 236 if (reload_type == |
| 237 NavigationController::ReloadType::RELOAD_ORIGINAL_REQUEST_URL && |
| 238 entry.GetOriginalRequestURL().is_valid() && !entry.GetHasPostData()) { |
| 239 // We may have been redirected when navigating to the current URL. |
| 240 // Use the URL the user originally intended to visit, if it's valid and if a |
| 241 // POST wasn't involved; the latter case avoids issues with sending data to |
| 242 // the wrong page. |
| 243 dest_url = entry.GetOriginalRequestURL(); |
| 244 dest_referrer = Referrer(); |
| 245 } |
| 246 |
234 // The renderer will reject IPC messages with URLs longer than | 247 // The renderer will reject IPC messages with URLs longer than |
235 // this limit, so don't attempt to navigate with a longer URL. | 248 // this limit, so don't attempt to navigate with a longer URL. |
236 if (frame_entry.url().spec().size() > GetMaxURLChars()) { | 249 if (dest_url.spec().size() > GetMaxURLChars()) { |
237 LOG(WARNING) << "Refusing to load URL as it exceeds " << GetMaxURLChars() | 250 LOG(WARNING) << "Refusing to load URL as it exceeds " << GetMaxURLChars() |
238 << " characters."; | 251 << " characters."; |
239 return false; | 252 return false; |
240 } | 253 } |
241 | 254 |
242 // This will be used to set the Navigation Timing API navigationStart | 255 // This will be used to set the Navigation Timing API navigationStart |
243 // parameter for browser navigations in new tabs (intents, tabs opened through | 256 // parameter for browser navigations in new tabs (intents, tabs opened through |
244 // "Open link in new tab"). We need to keep it above RFHM::Navigate() call to | 257 // "Open link in new tab"). We need to keep it above RFHM::Navigate() call to |
245 // capture the time needed for the RenderFrameHost initialization. | 258 // capture the time needed for the RenderFrameHost initialization. |
246 base::TimeTicks navigation_start = base::TimeTicks::Now(); | 259 base::TimeTicks navigation_start = base::TimeTicks::Now(); |
247 | 260 |
248 RenderFrameHostManager* manager = frame_tree_node->render_manager(); | 261 RenderFrameHostManager* manager = frame_tree_node->render_manager(); |
249 | 262 |
250 // PlzNavigate: the RenderFrameHosts are no longer asked to navigate. | 263 // PlzNavigate: the RenderFrameHosts are no longer asked to navigate. |
251 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 264 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
252 switches::kEnableBrowserSideNavigation)) { | 265 switches::kEnableBrowserSideNavigation)) { |
253 navigation_data_.reset(new NavigationMetricsData( | 266 navigation_data_.reset(new NavigationMetricsData(navigation_start, dest_url, |
254 navigation_start, frame_entry.url(), entry.restore_type())); | 267 entry.restore_type())); |
255 RequestNavigation(frame_tree_node, frame_entry, entry, reload_type, | 268 RequestNavigation(frame_tree_node, dest_url, dest_referrer, frame_entry, |
256 is_same_document_history_load, navigation_start); | 269 entry, reload_type, is_same_document_history_load, |
| 270 navigation_start); |
257 | 271 |
258 // Notify observers about navigation. | 272 // Notify observers about navigation. |
259 if (delegate_) { | 273 if (delegate_) |
260 delegate_->DidStartNavigationToPendingEntry(frame_entry.url(), | 274 delegate_->DidStartNavigationToPendingEntry(dest_url, reload_type); |
261 reload_type); | |
262 } | |
263 | 275 |
264 return true; | 276 return true; |
265 } | 277 } |
266 | 278 |
267 RenderFrameHostImpl* dest_render_frame_host = | 279 RenderFrameHostImpl* dest_render_frame_host = |
268 manager->Navigate(frame_entry, entry); | 280 manager->Navigate(dest_url, frame_entry, entry); |
269 if (!dest_render_frame_host) | 281 if (!dest_render_frame_host) |
270 return false; // Unable to create the desired RenderFrameHost. | 282 return false; // Unable to create the desired RenderFrameHost. |
271 | 283 |
272 // Make sure no code called via RFHM::Navigate clears the pending entry. | 284 // Make sure no code called via RFHM::Navigate clears the pending entry. |
273 CHECK_EQ(controller_->GetPendingEntry(), &entry); | 285 CHECK_EQ(controller_->GetPendingEntry(), &entry); |
274 | 286 |
275 // For security, we should never send non-Web-UI URLs to a Web UI renderer. | 287 // For security, we should never send non-Web-UI URLs to a Web UI renderer. |
276 // Double check that here. | 288 // Double check that here. |
277 CheckWebUIRendererDoesNotDisplayNormalURL(dest_render_frame_host, | 289 CheckWebUIRendererDoesNotDisplayNormalURL(dest_render_frame_host, dest_url); |
278 frame_entry.url()); | |
279 | 290 |
280 // Notify observers that we will navigate in this RenderFrame. | 291 // Notify observers that we will navigate in this RenderFrame. |
281 if (delegate_) { | 292 if (delegate_) { |
282 delegate_->AboutToNavigateRenderFrame(frame_tree_node->current_frame_host(), | 293 delegate_->AboutToNavigateRenderFrame(frame_tree_node->current_frame_host(), |
283 dest_render_frame_host); | 294 dest_render_frame_host); |
284 } | 295 } |
285 | 296 |
286 // Navigate in the desired RenderFrameHost. | 297 // Navigate in the desired RenderFrameHost. |
287 // We can skip this step in the rare case that this is a transfer navigation | 298 // We can skip this step in the rare case that this is a transfer navigation |
288 // which began in the chosen RenderFrameHost, since the request has already | 299 // which began in the chosen RenderFrameHost, since the request has already |
289 // been issued. In that case, simply resume the response. | 300 // been issued. In that case, simply resume the response. |
290 bool is_transfer_to_same = | 301 bool is_transfer_to_same = |
291 entry.transferred_global_request_id().child_id != -1 && | 302 entry.transferred_global_request_id().child_id != -1 && |
292 entry.transferred_global_request_id().child_id == | 303 entry.transferred_global_request_id().child_id == |
293 dest_render_frame_host->GetProcess()->GetID(); | 304 dest_render_frame_host->GetProcess()->GetID(); |
294 if (!is_transfer_to_same) { | 305 if (!is_transfer_to_same) { |
295 navigation_data_.reset(new NavigationMetricsData( | 306 navigation_data_.reset(new NavigationMetricsData(navigation_start, dest_url, |
296 navigation_start, frame_entry.url(), entry.restore_type())); | 307 entry.restore_type())); |
297 // Create the navigation parameters. | 308 // Create the navigation parameters. |
298 FrameMsg_Navigate_Type::Value navigation_type = | 309 FrameMsg_Navigate_Type::Value navigation_type = |
299 GetNavigationType(controller_->GetBrowserContext(), entry, reload_type); | 310 GetNavigationType(controller_->GetBrowserContext(), entry, reload_type); |
300 dest_render_frame_host->Navigate( | 311 dest_render_frame_host->Navigate( |
301 entry.ConstructCommonNavigationParams(frame_entry, navigation_type), | 312 entry.ConstructCommonNavigationParams(dest_url, dest_referrer, |
| 313 frame_entry, navigation_type), |
302 entry.ConstructStartNavigationParams(), | 314 entry.ConstructStartNavigationParams(), |
303 entry.ConstructRequestNavigationParams( | 315 entry.ConstructRequestNavigationParams( |
304 frame_entry, navigation_start, is_same_document_history_load, | 316 frame_entry, navigation_start, is_same_document_history_load, |
305 controller_->HasCommittedRealLoad(frame_tree_node), | 317 controller_->HasCommittedRealLoad(frame_tree_node), |
306 controller_->GetPendingEntryIndex() == -1, | 318 controller_->GetPendingEntryIndex() == -1, |
307 controller_->GetIndexOfEntry(&entry), | 319 controller_->GetIndexOfEntry(&entry), |
308 controller_->GetLastCommittedEntryIndex(), | 320 controller_->GetLastCommittedEntryIndex(), |
309 controller_->GetEntryCount())); | 321 controller_->GetEntryCount())); |
310 } else { | 322 } else { |
311 // No need to navigate again. Just resume the deferred request. | 323 // No need to navigate again. Just resume the deferred request. |
312 dest_render_frame_host->GetProcess()->ResumeDeferredNavigation( | 324 dest_render_frame_host->GetProcess()->ResumeDeferredNavigation( |
313 entry.transferred_global_request_id()); | 325 entry.transferred_global_request_id()); |
314 } | 326 } |
315 | 327 |
316 // Make sure no code called via RFH::Navigate clears the pending entry. | 328 // Make sure no code called via RFH::Navigate clears the pending entry. |
317 CHECK_EQ(controller_->GetPendingEntry(), &entry); | 329 CHECK_EQ(controller_->GetPendingEntry(), &entry); |
318 | 330 |
319 if (controller_->GetPendingEntryIndex() == -1 && | 331 if (controller_->GetPendingEntryIndex() == -1 && |
320 frame_entry.url().SchemeIs(url::kJavaScriptScheme)) { | 332 dest_url.SchemeIs(url::kJavaScriptScheme)) { |
321 // If the pending entry index is -1 (which means a new navigation rather | 333 // If the pending entry index is -1 (which means a new navigation rather |
322 // than a history one), and the user typed in a javascript: URL, don't add | 334 // than a history one), and the user typed in a javascript: URL, don't add |
323 // it to the session history. | 335 // it to the session history. |
324 // | 336 // |
325 // This is a hack. What we really want is to avoid adding to the history any | 337 // This is a hack. What we really want is to avoid adding to the history any |
326 // URL that doesn't generate content, and what would be great would be if we | 338 // URL that doesn't generate content, and what would be great would be if we |
327 // had a message from the renderer telling us that a new page was not | 339 // had a message from the renderer telling us that a new page was not |
328 // created. The same message could be used for mailto: URLs and the like. | 340 // created. The same message could be used for mailto: URLs and the like. |
329 return false; | 341 return false; |
330 } | 342 } |
331 | 343 |
332 // Notify observers about navigation. | 344 // Notify observers about navigation. |
333 if (delegate_) { | 345 if (delegate_) { |
334 delegate_->DidStartNavigationToPendingEntry(frame_entry.url(), reload_type); | 346 delegate_->DidStartNavigationToPendingEntry(dest_url, reload_type); |
335 } | 347 } |
336 | 348 |
337 return true; | 349 return true; |
338 } | 350 } |
339 | 351 |
340 bool NavigatorImpl::NavigateToPendingEntry( | 352 bool NavigatorImpl::NavigateToPendingEntry( |
341 FrameTreeNode* frame_tree_node, | 353 FrameTreeNode* frame_tree_node, |
342 const FrameNavigationEntry& frame_entry, | 354 const FrameNavigationEntry& frame_entry, |
343 NavigationController::ReloadType reload_type, | 355 NavigationController::ReloadType reload_type, |
344 bool is_same_document_history_load) { | 356 bool is_same_document_history_load) { |
(...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
781 !is_allowed_in_web_ui_renderer) { | 793 !is_allowed_in_web_ui_renderer) { |
782 // Log the URL to help us diagnose any future failures of this CHECK. | 794 // Log the URL to help us diagnose any future failures of this CHECK. |
783 GetContentClient()->SetActiveURL(url); | 795 GetContentClient()->SetActiveURL(url); |
784 CHECK(0); | 796 CHECK(0); |
785 } | 797 } |
786 } | 798 } |
787 | 799 |
788 // PlzNavigate | 800 // PlzNavigate |
789 void NavigatorImpl::RequestNavigation( | 801 void NavigatorImpl::RequestNavigation( |
790 FrameTreeNode* frame_tree_node, | 802 FrameTreeNode* frame_tree_node, |
| 803 const GURL& dest_url, |
| 804 const Referrer& dest_referrer, |
791 const FrameNavigationEntry& frame_entry, | 805 const FrameNavigationEntry& frame_entry, |
792 const NavigationEntryImpl& entry, | 806 const NavigationEntryImpl& entry, |
793 NavigationController::ReloadType reload_type, | 807 NavigationController::ReloadType reload_type, |
794 bool is_same_document_history_load, | 808 bool is_same_document_history_load, |
795 base::TimeTicks navigation_start) { | 809 base::TimeTicks navigation_start) { |
796 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( | 810 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( |
797 switches::kEnableBrowserSideNavigation)); | 811 switches::kEnableBrowserSideNavigation)); |
798 DCHECK(frame_tree_node); | 812 DCHECK(frame_tree_node); |
799 | 813 |
800 // This value must be set here because creating a NavigationRequest might | 814 // This value must be set here because creating a NavigationRequest might |
801 // change the renderer live/non-live status and change this result. | 815 // change the renderer live/non-live status and change this result. |
802 bool should_dispatch_beforeunload = | 816 bool should_dispatch_beforeunload = |
803 frame_tree_node->current_frame_host()->ShouldDispatchBeforeUnload(); | 817 frame_tree_node->current_frame_host()->ShouldDispatchBeforeUnload(); |
804 FrameMsg_Navigate_Type::Value navigation_type = | 818 FrameMsg_Navigate_Type::Value navigation_type = |
805 GetNavigationType(controller_->GetBrowserContext(), entry, reload_type); | 819 GetNavigationType(controller_->GetBrowserContext(), entry, reload_type); |
806 frame_tree_node->CreatedNavigationRequest( | 820 frame_tree_node->CreatedNavigationRequest( |
807 NavigationRequest::CreateBrowserInitiated( | 821 NavigationRequest::CreateBrowserInitiated( |
808 frame_tree_node, frame_entry, entry, navigation_type, | 822 frame_tree_node, dest_url, dest_referrer, frame_entry, entry, |
809 is_same_document_history_load, navigation_start, controller_)); | 823 navigation_type, is_same_document_history_load, navigation_start, |
| 824 controller_)); |
810 NavigationRequest* navigation_request = frame_tree_node->navigation_request(); | 825 NavigationRequest* navigation_request = frame_tree_node->navigation_request(); |
811 | 826 |
812 // Have the current renderer execute its beforeunload event if needed. If it | 827 // Have the current renderer execute its beforeunload event if needed. If it |
813 // is not needed (when beforeunload dispatch is not needed or this navigation | 828 // is not needed (when beforeunload dispatch is not needed or this navigation |
814 // is synchronous and same-site) then NavigationRequest::BeginNavigation | 829 // is synchronous and same-site) then NavigationRequest::BeginNavigation |
815 // should be directly called instead. | 830 // should be directly called instead. |
816 if (should_dispatch_beforeunload && | 831 if (should_dispatch_beforeunload && |
817 ShouldMakeNetworkRequestForURL( | 832 ShouldMakeNetworkRequestForURL( |
818 navigation_request->common_params().url)) { | 833 navigation_request->common_params().url)) { |
819 navigation_request->SetWaitingForRendererResponse(); | 834 navigation_request->SetWaitingForRendererResponse(); |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
904 entry->set_should_replace_entry(pending_entry->should_replace_entry()); | 919 entry->set_should_replace_entry(pending_entry->should_replace_entry()); |
905 entry->SetRedirectChain(pending_entry->GetRedirectChain()); | 920 entry->SetRedirectChain(pending_entry->GetRedirectChain()); |
906 } | 921 } |
907 controller_->SetPendingEntry(entry.Pass()); | 922 controller_->SetPendingEntry(entry.Pass()); |
908 if (delegate_) | 923 if (delegate_) |
909 delegate_->NotifyChangedNavigationState(content::INVALIDATE_TYPE_URL); | 924 delegate_->NotifyChangedNavigationState(content::INVALIDATE_TYPE_URL); |
910 } | 925 } |
911 } | 926 } |
912 | 927 |
913 } // namespace content | 928 } // namespace content |
OLD | NEW |