| 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 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 244 const base::string16& error_description) { | 244 const base::string16& error_description) { |
| 245 if (delegate_) { | 245 if (delegate_) { |
| 246 delegate_->DidFailLoadWithError( | 246 delegate_->DidFailLoadWithError( |
| 247 render_frame_host, url, error_code, | 247 render_frame_host, url, error_code, |
| 248 error_description); | 248 error_description); |
| 249 } | 249 } |
| 250 } | 250 } |
| 251 | 251 |
| 252 bool NavigatorImpl::NavigateToEntry( | 252 bool NavigatorImpl::NavigateToEntry( |
| 253 FrameTreeNode* frame_tree_node, | 253 FrameTreeNode* frame_tree_node, |
| 254 const FrameNavigationEntry& frame_nav_entry, |
| 254 const NavigationEntryImpl& entry, | 255 const NavigationEntryImpl& entry, |
| 255 NavigationController::ReloadType reload_type) { | 256 NavigationController::ReloadType reload_type) { |
| 256 TRACE_EVENT0("browser,navigation", "NavigatorImpl::NavigateToEntry"); | 257 TRACE_EVENT0("browser,navigation", "NavigatorImpl::NavigateToEntry"); |
| 257 | 258 |
| 258 // The renderer will reject IPC messages with URLs longer than | 259 // The renderer will reject IPC messages with URLs longer than |
| 259 // this limit, so don't attempt to navigate with a longer URL. | 260 // this limit, so don't attempt to navigate with a longer URL. |
| 260 if (entry.GetURL().spec().size() > GetMaxURLChars()) { | 261 if (frame_nav_entry.url().spec().size() > GetMaxURLChars()) { |
| 261 LOG(WARNING) << "Refusing to load URL as it exceeds " << GetMaxURLChars() | 262 LOG(WARNING) << "Refusing to load URL as it exceeds " << GetMaxURLChars() |
| 262 << " characters."; | 263 << " characters."; |
| 263 return false; | 264 return false; |
| 264 } | 265 } |
| 265 | 266 |
| 266 // This will be used to set the Navigation Timing API navigationStart | 267 // This will be used to set the Navigation Timing API navigationStart |
| 267 // parameter for browser navigations in new tabs (intents, tabs opened through | 268 // parameter for browser navigations in new tabs (intents, tabs opened through |
| 268 // "Open link in new tab"). We need to keep it above RFHM::Navigate() call to | 269 // "Open link in new tab"). We need to keep it above RFHM::Navigate() call to |
| 269 // capture the time needed for the RenderFrameHost initialization. | 270 // capture the time needed for the RenderFrameHost initialization. |
| 270 base::TimeTicks navigation_start = base::TimeTicks::Now(); | 271 base::TimeTicks navigation_start = base::TimeTicks::Now(); |
| 271 | 272 |
| 272 RenderFrameHostManager* manager = frame_tree_node->render_manager(); | 273 RenderFrameHostManager* manager = frame_tree_node->render_manager(); |
| 273 | 274 |
| 274 // PlzNavigate: the RenderFrameHosts are no longer asked to navigate. | 275 // PlzNavigate: the RenderFrameHosts are no longer asked to navigate. |
| 275 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 276 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 276 switches::kEnableBrowserSideNavigation)) { | 277 switches::kEnableBrowserSideNavigation)) { |
| 277 navigation_data_.reset(new NavigationMetricsData( | 278 navigation_data_.reset(new NavigationMetricsData( |
| 278 navigation_start, entry.GetURL(), entry.restore_type())); | 279 navigation_start, frame_nav_entry.url(), entry.restore_type())); |
| 279 RequestNavigation(frame_tree_node, entry, reload_type, navigation_start); | 280 RequestNavigation(frame_tree_node, frame_nav_entry, entry, reload_type, |
| 281 navigation_start); |
| 280 return true; | 282 return true; |
| 281 } | 283 } |
| 282 | 284 |
| 283 RenderFrameHostImpl* dest_render_frame_host = manager->Navigate(entry); | 285 RenderFrameHostImpl* dest_render_frame_host = |
| 286 manager->Navigate(frame_nav_entry, entry); |
| 284 if (!dest_render_frame_host) | 287 if (!dest_render_frame_host) |
| 285 return false; // Unable to create the desired RenderFrameHost. | 288 return false; // Unable to create the desired RenderFrameHost. |
| 286 | 289 |
| 287 // Make sure no code called via RFHM::Navigate clears the pending entry. | 290 // Make sure no code called via RFHM::Navigate clears the pending entry. |
| 288 CHECK_EQ(controller_->GetPendingEntry(), &entry); | 291 CHECK_EQ(controller_->GetPendingEntry(), &entry); |
| 289 | 292 |
| 290 // For security, we should never send non-Web-UI URLs to a Web UI renderer. | 293 // For security, we should never send non-Web-UI URLs to a Web UI renderer. |
| 291 // Double check that here. | 294 // Double check that here. |
| 292 CheckWebUIRendererDoesNotDisplayNormalURL( | 295 CheckWebUIRendererDoesNotDisplayNormalURL( |
| 293 dest_render_frame_host, entry.GetURL()); | 296 dest_render_frame_host, frame_nav_entry.url()); |
| 294 | 297 |
| 295 // Notify observers that we will navigate in this RenderFrame. | 298 // Notify observers that we will navigate in this RenderFrame. |
| 296 if (delegate_) { | 299 if (delegate_) { |
| 300 // TODO(creis): Deprecate this API. We should not be accessing the current |
| 301 // RFH here. |
| 297 delegate_->AboutToNavigateRenderFrame(frame_tree_node->current_frame_host(), | 302 delegate_->AboutToNavigateRenderFrame(frame_tree_node->current_frame_host(), |
| 298 dest_render_frame_host); | 303 dest_render_frame_host); |
| 299 } | 304 } |
| 300 | 305 |
| 301 // Navigate in the desired RenderFrameHost. | 306 // Navigate in the desired RenderFrameHost. |
| 302 // We can skip this step in the rare case that this is a transfer navigation | 307 // We can skip this step in the rare case that this is a transfer navigation |
| 303 // which began in the chosen RenderFrameHost, since the request has already | 308 // which began in the chosen RenderFrameHost, since the request has already |
| 304 // been issued. In that case, simply resume the response. | 309 // been issued. In that case, simply resume the response. |
| 305 bool is_transfer_to_same = | 310 bool is_transfer_to_same = |
| 306 entry.transferred_global_request_id().child_id != -1 && | 311 entry.transferred_global_request_id().child_id != -1 && |
| 307 entry.transferred_global_request_id().child_id == | 312 entry.transferred_global_request_id().child_id == |
| 308 dest_render_frame_host->GetProcess()->GetID(); | 313 dest_render_frame_host->GetProcess()->GetID(); |
| 309 if (!is_transfer_to_same) { | 314 if (!is_transfer_to_same) { |
| 310 navigation_data_.reset(new NavigationMetricsData( | 315 navigation_data_.reset(new NavigationMetricsData( |
| 311 navigation_start, entry.GetURL(), entry.restore_type())); | 316 navigation_start, frame_nav_entry.url(), entry.restore_type())); |
| 312 // Create the navigation parameters. | 317 // Create the navigation parameters. |
| 313 // TODO(vitalybuka): Move this before AboutToNavigateRenderFrame once | 318 // TODO(vitalybuka): Move this before AboutToNavigateRenderFrame once |
| 314 // http://crbug.com/408684 is fixed. | 319 // http://crbug.com/408684 is fixed. |
| 315 FrameMsg_Navigate_Type::Value navigation_type = | 320 FrameMsg_Navigate_Type::Value navigation_type = |
| 316 GetNavigationType(controller_->GetBrowserContext(), entry, reload_type); | 321 GetNavigationType(controller_->GetBrowserContext(), entry, reload_type); |
| 317 dest_render_frame_host->Navigate( | 322 dest_render_frame_host->Navigate( |
| 318 entry.ConstructCommonNavigationParams(navigation_type), | 323 entry.ConstructCommonNavigationParams(frame_nav_entry, navigation_type), |
| 319 entry.ConstructStartNavigationParams(), | 324 entry.ConstructStartNavigationParams(), |
| 320 entry.ConstructCommitNavigationParams(navigation_start), | 325 entry.ConstructCommitNavigationParams(navigation_start), |
| 321 entry.ConstructHistoryNavigationParams(controller_)); | 326 entry.ConstructHistoryNavigationParams(frame_nav_entry, controller_)); |
| 322 } else { | 327 } else { |
| 323 // No need to navigate again. Just resume the deferred request. | 328 // No need to navigate again. Just resume the deferred request. |
| 324 dest_render_frame_host->GetProcess()->ResumeDeferredNavigation( | 329 dest_render_frame_host->GetProcess()->ResumeDeferredNavigation( |
| 325 entry.transferred_global_request_id()); | 330 entry.transferred_global_request_id()); |
| 326 } | 331 } |
| 327 | 332 |
| 328 // Make sure no code called via RFH::Navigate clears the pending entry. | 333 // Make sure no code called via RFH::Navigate clears the pending entry. |
| 329 CHECK_EQ(controller_->GetPendingEntry(), &entry); | 334 CHECK_EQ(controller_->GetPendingEntry(), &entry); |
| 330 | 335 |
| 331 if (entry.GetPageID() == -1) { | 336 if (entry.GetPageID() == -1) { |
| 332 // HACK!! This code suppresses javascript: URLs from being added to | 337 // HACK!! This code suppresses javascript: URLs from being added to |
| 333 // session history, which is what we want to do for javascript: URLs that | 338 // session history, which is what we want to do for javascript: URLs that |
| 334 // do not generate content. What we really need is a message from the | 339 // do not generate content. What we really need is a message from the |
| 335 // renderer telling us that a new page was not created. The same message | 340 // renderer telling us that a new page was not created. The same message |
| 336 // could be used for mailto: URLs and the like. | 341 // could be used for mailto: URLs and the like. |
| 337 if (entry.GetURL().SchemeIs(url::kJavaScriptScheme)) | 342 if (frame_nav_entry.url().SchemeIs(url::kJavaScriptScheme)) |
| 338 return false; | 343 return false; |
| 339 } | 344 } |
| 340 | 345 |
| 341 // Notify observers about navigation. | 346 // Notify observers about navigation. |
| 342 if (delegate_) | 347 if (delegate_) { |
| 343 delegate_->DidStartNavigationToPendingEntry(entry.GetURL(), reload_type); | 348 delegate_->DidStartNavigationToPendingEntry(frame_nav_entry.url(), |
| 349 reload_type); |
| 350 } |
| 344 | 351 |
| 345 return true; | 352 return true; |
| 346 } | 353 } |
| 347 | 354 |
| 348 bool NavigatorImpl::NavigateToPendingEntry( | 355 bool NavigatorImpl::NavigateToPendingEntry( |
| 349 FrameTreeNode* frame_tree_node, | 356 FrameTreeNode* frame_tree_node, |
| 357 const FrameNavigationEntry& frame_nav_entry, |
| 350 NavigationController::ReloadType reload_type) { | 358 NavigationController::ReloadType reload_type) { |
| 351 return NavigateToEntry(frame_tree_node, *controller_->GetPendingEntry(), | 359 return NavigateToEntry(frame_tree_node, frame_nav_entry, |
| 352 reload_type); | 360 *controller_->GetPendingEntry(), reload_type); |
| 353 } | 361 } |
| 354 | 362 |
| 355 void NavigatorImpl::DidNavigate( | 363 void NavigatorImpl::DidNavigate( |
| 356 RenderFrameHostImpl* render_frame_host, | 364 RenderFrameHostImpl* render_frame_host, |
| 357 const FrameHostMsg_DidCommitProvisionalLoad_Params& input_params) { | 365 const FrameHostMsg_DidCommitProvisionalLoad_Params& input_params) { |
| 358 // PlzNavigate | 366 // PlzNavigate |
| 359 // The navigation request has been committed so the browser process doesn't | 367 // The navigation request has been committed so the browser process doesn't |
| 360 // need to care about it anymore. | 368 // need to care about it anymore. |
| 361 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 369 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 362 switches::kEnableBrowserSideNavigation)) { | 370 switches::kEnableBrowserSideNavigation)) { |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 434 // TODO(nasko): Verify the correctness of the above comment, since some of the | 442 // TODO(nasko): Verify the correctness of the above comment, since some of the |
| 435 // code doesn't exist anymore. Also, move this code in the | 443 // code doesn't exist anymore. Also, move this code in the |
| 436 // PageTransitionIsMainFrame code block above. | 444 // PageTransitionIsMainFrame code block above. |
| 437 if (ui::PageTransitionIsMainFrame(params.transition) && delegate_) | 445 if (ui::PageTransitionIsMainFrame(params.transition) && delegate_) |
| 438 delegate_->SetMainFrameMimeType(params.contents_mime_type); | 446 delegate_->SetMainFrameMimeType(params.contents_mime_type); |
| 439 | 447 |
| 440 LoadCommittedDetails details; | 448 LoadCommittedDetails details; |
| 441 bool did_navigate = controller_->RendererDidNavigate(render_frame_host, | 449 bool did_navigate = controller_->RendererDidNavigate(render_frame_host, |
| 442 params, &details); | 450 params, &details); |
| 443 | 451 |
| 444 // For now, keep track of each frame's URL in its FrameTreeNode. This lets | |
| 445 // us estimate our process count for implementing OOP iframes. | |
| 446 // TODO(creis): Remove this when we track which pages commit in each frame. | |
| 447 render_frame_host->frame_tree_node()->set_current_url(params.url); | |
| 448 | |
| 449 // Send notification about committed provisional loads. This notification is | 452 // Send notification about committed provisional loads. This notification is |
| 450 // different from the NAV_ENTRY_COMMITTED notification which doesn't include | 453 // different from the NAV_ENTRY_COMMITTED notification which doesn't include |
| 451 // the actual URL navigated to and isn't sent for AUTO_SUBFRAME navigations. | 454 // the actual URL navigated to and isn't sent for AUTO_SUBFRAME navigations. |
| 452 if (details.type != NAVIGATION_TYPE_NAV_IGNORE && delegate_) { | 455 if (details.type != NAVIGATION_TYPE_NAV_IGNORE && delegate_) { |
| 453 DCHECK_EQ(!render_frame_host->GetParent(), | 456 DCHECK_EQ(!render_frame_host->GetParent(), |
| 454 did_navigate ? details.is_main_frame : false); | 457 did_navigate ? details.is_main_frame : false); |
| 455 ui::PageTransition transition_type = params.transition; | 458 ui::PageTransition transition_type = params.transition; |
| 456 // Whether or not a page transition was triggered by going backward or | 459 // Whether or not a page transition was triggered by going backward or |
| 457 // forward in the history is only stored in the navigation controller's | 460 // forward in the history is only stored in the navigation controller's |
| 458 // entry list. | 461 // entry list. |
| (...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 767 !is_allowed_in_web_ui_renderer) { | 770 !is_allowed_in_web_ui_renderer) { |
| 768 // Log the URL to help us diagnose any future failures of this CHECK. | 771 // Log the URL to help us diagnose any future failures of this CHECK. |
| 769 GetContentClient()->SetActiveURL(url); | 772 GetContentClient()->SetActiveURL(url); |
| 770 CHECK(0); | 773 CHECK(0); |
| 771 } | 774 } |
| 772 } | 775 } |
| 773 | 776 |
| 774 // PlzNavigate | 777 // PlzNavigate |
| 775 void NavigatorImpl::RequestNavigation( | 778 void NavigatorImpl::RequestNavigation( |
| 776 FrameTreeNode* frame_tree_node, | 779 FrameTreeNode* frame_tree_node, |
| 780 const FrameNavigationEntry& frame_entry, |
| 777 const NavigationEntryImpl& entry, | 781 const NavigationEntryImpl& entry, |
| 778 NavigationController::ReloadType reload_type, | 782 NavigationController::ReloadType reload_type, |
| 779 base::TimeTicks navigation_start) { | 783 base::TimeTicks navigation_start) { |
| 780 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( | 784 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 781 switches::kEnableBrowserSideNavigation)); | 785 switches::kEnableBrowserSideNavigation)); |
| 782 DCHECK(frame_tree_node); | 786 DCHECK(frame_tree_node); |
| 783 int64 frame_tree_node_id = frame_tree_node->frame_tree_node_id(); | 787 int64 frame_tree_node_id = frame_tree_node->frame_tree_node_id(); |
| 784 FrameMsg_Navigate_Type::Value navigation_type = | 788 FrameMsg_Navigate_Type::Value navigation_type = |
| 785 GetNavigationType(controller_->GetBrowserContext(), entry, reload_type); | 789 GetNavigationType(controller_->GetBrowserContext(), entry, reload_type); |
| 790 // TODO(creis): Pass frame_entry and get the URL and referrer from there. |
| 786 scoped_ptr<NavigationRequest> navigation_request = | 791 scoped_ptr<NavigationRequest> navigation_request = |
| 787 NavigationRequest::CreateBrowserInitiated(frame_tree_node, entry, | 792 NavigationRequest::CreateBrowserInitiated(frame_tree_node, entry, |
| 788 navigation_type, | 793 navigation_type, |
| 789 navigation_start, controller_); | 794 navigation_start, controller_); |
| 790 // TODO(clamy): Check if navigations are blocked and if so store the | 795 // TODO(clamy): Check if navigations are blocked and if so store the |
| 791 // parameters. | 796 // parameters. |
| 792 | 797 |
| 793 // If there is an ongoing request, cancel and replace it. | 798 // If there is an ongoing request, cancel and replace it. |
| 794 NavigationRequest* ongoing_request = | 799 NavigationRequest* ongoing_request = |
| 795 navigation_request_map_.get(frame_tree_node->frame_tree_node_id()); | 800 navigation_request_map_.get(frame_tree_node->frame_tree_node_id()); |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 873 "Navigation.TimeToCommit_ExistingRenderer_BeforeUnloadDiscounted", | 878 "Navigation.TimeToCommit_ExistingRenderer_BeforeUnloadDiscounted", |
| 874 time_to_commit); | 879 time_to_commit); |
| 875 UMA_HISTOGRAM_TIMES( | 880 UMA_HISTOGRAM_TIMES( |
| 876 "Navigation.TimeToURLJobStart_ExistingRenderer_BeforeUnloadDiscounted", | 881 "Navigation.TimeToURLJobStart_ExistingRenderer_BeforeUnloadDiscounted", |
| 877 time_to_network); | 882 time_to_network); |
| 878 } | 883 } |
| 879 navigation_data_.reset(); | 884 navigation_data_.reset(); |
| 880 } | 885 } |
| 881 | 886 |
| 882 } // namespace content | 887 } // namespace content |
| OLD | NEW |