Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(487)

Side by Side Diff: content/browser/frame_host/navigator_impl.cc

Issue 1255103003: Fix race when reloading original URL. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@2454
Patch Set: Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « content/browser/frame_host/navigator_impl.h ('k') | content/browser/frame_host/render_frame_host_manager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698