| 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 |