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

Side by Side Diff: trunk/src/content/browser/web_contents/navigation_controller_impl.cc

Issue 13966012: Revert 195553 "Allow showing pending URL for new tab navigations..." (Closed) Base URL: svn://svn.chromium.org/chrome/
Patch Set: Created 7 years, 8 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/web_contents/navigation_controller_impl.h" 5 #include "content/browser/web_contents/navigation_controller_impl.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/command_line.h" 8 #include "base/command_line.h"
9 #include "base/file_util.h" 9 #include "base/file_util.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after
285 NavigationEntryImpl::FromNavigationEntry(GetActiveEntry()); 285 NavigationEntryImpl::FromNavigationEntry(GetActiveEntry());
286 if (!active_entry) 286 if (!active_entry)
287 return; 287 return;
288 LoadURL(active_entry->GetURL(), 288 LoadURL(active_entry->GetURL(),
289 Referrer(), 289 Referrer(),
290 PAGE_TRANSITION_RELOAD, 290 PAGE_TRANSITION_RELOAD,
291 active_entry->extra_headers()); 291 active_entry->extra_headers());
292 return; 292 return;
293 } 293 }
294 294
295 NavigationEntryImpl* entry = NULL; 295 DiscardNonCommittedEntriesInternal();
296 int current_index = -1; 296 int current_index = GetCurrentEntryIndex();
297 297 // If we are no where, then we can't reload. TODO(darin): We should add a
298 // If we are reloading the initial navigation, just use the current 298 // CanReload method.
299 // pending entry. Otherwise look up the current entry. 299 if (current_index == -1) {
300 if (IsInitialNavigation() && pending_entry_) { 300 return;
301 entry = pending_entry_;
302 } else {
303 DiscardNonCommittedEntriesInternal();
304 current_index = GetCurrentEntryIndex();
305 if (current_index != -1) {
306 entry = NavigationEntryImpl::FromNavigationEntry(
307 GetEntryAtIndex(current_index));
308 }
309 } 301 }
310 302
311 // If we are no where, then we can't reload. TODO(darin): We should add a
312 // CanReload method.
313 if (!entry)
314 return;
315
316 if (g_check_for_repost && check_for_repost && 303 if (g_check_for_repost && check_for_repost &&
317 entry->GetHasPostData()) { 304 GetEntryAtIndex(current_index)->GetHasPostData()) {
318 // The user is asking to reload a page with POST data. Prompt to make sure 305 // The user is asking to reload a page with POST data. Prompt to make sure
319 // they really want to do this. If they do, the dialog will call us back 306 // they really want to do this. If they do, the dialog will call us back
320 // with check_for_repost = false. 307 // with check_for_repost = false.
321 web_contents_->NotifyBeforeFormRepostWarningShow(); 308 web_contents_->NotifyBeforeFormRepostWarningShow();
322 309
323 pending_reload_ = reload_type; 310 pending_reload_ = reload_type;
324 web_contents_->Activate(); 311 web_contents_->Activate();
325 web_contents_->GetDelegate()->ShowRepostFormWarningDialog(web_contents_); 312 web_contents_->GetDelegate()->ShowRepostFormWarningDialog(web_contents_);
326 } else { 313 } else {
327 if (!IsInitialNavigation()) 314 DiscardNonCommittedEntriesInternal();
328 DiscardNonCommittedEntriesInternal(); 315
316 NavigationEntryImpl* entry = entries_[current_index].get();
317 SiteInstanceImpl* site_instance = entry->site_instance();
318 DCHECK(site_instance);
329 319
330 // If we are reloading an entry that no longer belongs to the current 320 // If we are reloading an entry that no longer belongs to the current
331 // site instance (for example, refreshing a page for just installed app), 321 // site instance (for example, refreshing a page for just installed app),
332 // the reload must happen in a new process. 322 // the reload must happen in a new process.
333 // The new entry must have a new page_id and site instance, so it behaves 323 // The new entry must have a new page_id and site instance, so it behaves
334 // as new navigation (which happens to clear forward history). 324 // as new navigation (which happens to clear forward history).
335 // Tabs that are discarded due to low memory conditions may not have a site 325 // Tabs that are discarded due to low memory conditions may not have a site
336 // instance, and should not be treated as a cross-site reload. 326 // instance, and should not be treated as a cross-site reload.
337 SiteInstanceImpl* site_instance = entry->site_instance();
338 if (site_instance && 327 if (site_instance &&
339 site_instance->HasWrongProcessForURL(entry->GetURL())) { 328 site_instance->HasWrongProcessForURL(entry->GetURL())) {
340 // Create a navigation entry that resembles the current one, but do not 329 // Create a navigation entry that resembles the current one, but do not
341 // copy page id, site instance, content state, or timestamp. 330 // copy page id, site instance, content state, or timestamp.
342 NavigationEntryImpl* nav_entry = NavigationEntryImpl::FromNavigationEntry( 331 NavigationEntryImpl* nav_entry = NavigationEntryImpl::FromNavigationEntry(
343 CreateNavigationEntry( 332 CreateNavigationEntry(
344 entry->GetURL(), entry->GetReferrer(), entry->GetTransitionType(), 333 entry->GetURL(), entry->GetReferrer(), entry->GetTransitionType(),
345 false, entry->extra_headers(), browser_context_)); 334 false, entry->extra_headers(), browser_context_));
346 335
347 // Mark the reload type as NO_RELOAD, so navigation will not be considered 336 // Mark the reload type as NO_RELOAD, so navigation will not be considered
348 // a reload in the renderer. 337 // a reload in the renderer.
349 reload_type = NavigationController::NO_RELOAD; 338 reload_type = NavigationController::NO_RELOAD;
350 339
351 nav_entry->set_should_replace_entry(true); 340 nav_entry->set_should_replace_entry(true);
352 pending_entry_ = nav_entry; 341 pending_entry_ = nav_entry;
353 } else { 342 } else {
354 pending_entry_ = entry;
355 pending_entry_index_ = current_index; 343 pending_entry_index_ = current_index;
356 344
357 // The title of the page being reloaded might have been removed in the 345 // The title of the page being reloaded might have been removed in the
358 // meanwhile, so we need to revert to the default title upon reload and 346 // meanwhile, so we need to revert to the default title upon reload and
359 // invalidate the previously cached title (SetTitle will do both). 347 // invalidate the previously cached title (SetTitle will do both).
360 // See Chromium issue 96041. 348 // See Chromium issue 96041.
361 pending_entry_->SetTitle(string16()); 349 entries_[pending_entry_index_]->SetTitle(string16());
362 350
363 pending_entry_->SetTransitionType(PAGE_TRANSITION_RELOAD); 351 entries_[pending_entry_index_]->SetTransitionType(PAGE_TRANSITION_RELOAD);
364 } 352 }
365 353
366 NavigateToPendingEntry(reload_type); 354 NavigateToPendingEntry(reload_type);
367 } 355 }
368 } 356 }
369 357
370 void NavigationControllerImpl::CancelPendingReload() { 358 void NavigationControllerImpl::CancelPendingReload() {
371 DCHECK(pending_reload_ != NO_RELOAD); 359 DCHECK(pending_reload_ != NO_RELOAD);
372 pending_reload_ = NO_RELOAD; 360 pending_reload_ = NO_RELOAD;
373 } 361 }
(...skipping 27 matching lines...) Expand all
401 policy->IsDisabledScheme(entry->GetVirtualURL().scheme())) { 389 policy->IsDisabledScheme(entry->GetVirtualURL().scheme())) {
402 VLOG(1) << "URL not loaded because the scheme is blocked by policy: " 390 VLOG(1) << "URL not loaded because the scheme is blocked by policy: "
403 << entry->GetURL(); 391 << entry->GetURL();
404 delete entry; 392 delete entry;
405 return; 393 return;
406 } 394 }
407 395
408 // When navigating to a new page, we don't know for sure if we will actually 396 // When navigating to a new page, we don't know for sure if we will actually
409 // end up leaving the current page. The new page load could for example 397 // end up leaving the current page. The new page load could for example
410 // result in a download or a 'no content' response (e.g., a mailto: URL). 398 // result in a download or a 'no content' response (e.g., a mailto: URL).
411 SetPendingEntry(entry);
412 NavigateToPendingEntry(NO_RELOAD);
413 }
414
415 void NavigationControllerImpl::SetPendingEntry(NavigationEntryImpl* entry) {
416 DiscardNonCommittedEntriesInternal(); 399 DiscardNonCommittedEntriesInternal();
417 pending_entry_ = entry; 400 pending_entry_ = entry;
418 NotificationService::current()->Notify( 401 NotificationService::current()->Notify(
419 NOTIFICATION_NAV_ENTRY_PENDING, 402 NOTIFICATION_NAV_ENTRY_PENDING,
420 Source<NavigationController>(this), 403 Source<NavigationController>(this),
421 Details<NavigationEntry>(entry)); 404 Details<NavigationEntry>(entry));
405 NavigateToPendingEntry(NO_RELOAD);
422 } 406 }
423 407
424 NavigationEntry* NavigationControllerImpl::GetActiveEntry() const { 408 NavigationEntry* NavigationControllerImpl::GetActiveEntry() const {
425 if (transient_entry_index_ != -1) 409 if (transient_entry_index_ != -1)
426 return entries_[transient_entry_index_].get(); 410 return entries_[transient_entry_index_].get();
427 if (pending_entry_) 411 if (pending_entry_)
428 return pending_entry_; 412 return pending_entry_;
429 return GetLastCommittedEntry(); 413 return GetLastCommittedEntry();
430 } 414 }
431 415
432 NavigationEntry* NavigationControllerImpl::GetVisibleEntry() const { 416 NavigationEntry* NavigationControllerImpl::GetVisibleEntry() const {
433 if (transient_entry_index_ != -1) 417 if (transient_entry_index_ != -1)
434 return entries_[transient_entry_index_].get(); 418 return entries_[transient_entry_index_].get();
435 // The pending entry is safe to return for new (non-history), browser- 419 // Only return the pending_entry for new (non-history), browser-initiated
436 // initiated navigations. Most renderer-initiated navigations should not 420 // navigations, in order to prevent URL spoof attacks.
437 // show the pending entry, to prevent URL spoof attacks. 421 // Ideally we would also show the pending entry's URL for new renderer-
438 // 422 // initiated navigations with no last committed entry (e.g., a link opening
439 // We make an exception for renderer-initiated navigations in new tabs, as 423 // in a new tab), but an attacker can insert content into the about:blank
440 // long as no other page has tried to access the initial empty document in 424 // page while the pending URL loads in that case.
441 // the new tab. If another page modifies this blank page, a URL spoof is 425 if (pending_entry_ &&
442 // possible, so we must stop showing the pending entry.
443 RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
444 web_contents_->GetRenderViewHost());
445 bool safe_to_show_pending =
446 pending_entry_ &&
447 // Require a new navigation.
448 pending_entry_->GetPageID() == -1 && 426 pending_entry_->GetPageID() == -1 &&
449 // Require either browser-initiated or an unmodified new tab.
450 (!pending_entry_->is_renderer_initiated() ||
451 (IsInitialNavigation() &&
452 !GetLastCommittedEntry() &&
453 !rvh->has_accessed_initial_document()));
454
455 // Also allow showing the pending entry for history navigations in a new tab,
456 // such as Ctrl+Back. In this case, no existing page is visible and no one
457 // can script the new tab before it commits.
458 if (!safe_to_show_pending &&
459 pending_entry_ &&
460 pending_entry_->GetPageID() != -1 &&
461 IsInitialNavigation() &&
462 !pending_entry_->is_renderer_initiated()) 427 !pending_entry_->is_renderer_initiated())
463 safe_to_show_pending = true;
464
465 if (safe_to_show_pending)
466 return pending_entry_; 428 return pending_entry_;
467 return GetLastCommittedEntry(); 429 return GetLastCommittedEntry();
468 } 430 }
469 431
470 int NavigationControllerImpl::GetCurrentEntryIndex() const { 432 int NavigationControllerImpl::GetCurrentEntryIndex() const {
471 if (transient_entry_index_ != -1) 433 if (transient_entry_index_ != -1)
472 return transient_entry_index_; 434 return transient_entry_index_;
473 if (pending_entry_index_ != -1) 435 if (pending_entry_index_ != -1)
474 return pending_entry_index_; 436 return pending_entry_index_;
475 return last_committed_entry_index_; 437 return last_committed_entry_index_;
(...skipping 609 matching lines...) Expand 10 before | Expand all | Expand 10 after
1085 if (!PageTransitionIsMainFrame(params.transition)) { 1047 if (!PageTransitionIsMainFrame(params.transition)) {
1086 // All manual subframes would get new IDs and were handled above, so we 1048 // All manual subframes would get new IDs and were handled above, so we
1087 // know this is auto. Since the current page was found in the navigation 1049 // know this is auto. Since the current page was found in the navigation
1088 // entry list, we're guaranteed to have a last committed entry. 1050 // entry list, we're guaranteed to have a last committed entry.
1089 DCHECK(GetLastCommittedEntry()); 1051 DCHECK(GetLastCommittedEntry());
1090 return NAVIGATION_TYPE_AUTO_SUBFRAME; 1052 return NAVIGATION_TYPE_AUTO_SUBFRAME;
1091 } 1053 }
1092 1054
1093 // Anything below here we know is a main frame navigation. 1055 // Anything below here we know is a main frame navigation.
1094 if (pending_entry_ && 1056 if (pending_entry_ &&
1095 !pending_entry_->is_renderer_initiated() &&
1096 existing_entry != pending_entry_ && 1057 existing_entry != pending_entry_ &&
1097 pending_entry_->GetPageID() == -1 && 1058 pending_entry_->GetPageID() == -1 &&
1098 existing_entry == GetLastCommittedEntry()) { 1059 existing_entry == GetLastCommittedEntry()) {
1099 // In this case, we have a pending entry for a URL but WebCore didn't do a 1060 // In this case, we have a pending entry for a URL but WebCore didn't do a
1100 // new navigation. This happens when you press enter in the URL bar to 1061 // new navigation. This happens when you press enter in the URL bar to
1101 // reload. We will create a pending entry, but WebKit will convert it to 1062 // reload. We will create a pending entry, but WebKit will convert it to
1102 // a reload since it's the same page and not create a new entry for it 1063 // a reload since it's the same page and not create a new entry for it
1103 // (the user doesn't want to have a new back/forward entry when they do 1064 // (the user doesn't want to have a new back/forward entry when they do
1104 // this). If this matches the last committed entry, we want to just ignore 1065 // this). If this matches the last committed entry, we want to just ignore
1105 // the pending entry and go back to where we were (the "existing entry"). 1066 // the pending entry and go back to where we were (the "existing entry").
(...skipping 757 matching lines...) Expand 10 before | Expand all | Expand 10 after
1863 const base::Callback<base::Time()>& get_timestamp_callback) { 1824 const base::Callback<base::Time()>& get_timestamp_callback) {
1864 get_timestamp_callback_ = get_timestamp_callback; 1825 get_timestamp_callback_ = get_timestamp_callback;
1865 } 1826 }
1866 1827
1867 void NavigationControllerImpl::SetTakeScreenshotCallbackForTest( 1828 void NavigationControllerImpl::SetTakeScreenshotCallbackForTest(
1868 const base::Callback<void(RenderViewHost*)>& take_screenshot_callback) { 1829 const base::Callback<void(RenderViewHost*)>& take_screenshot_callback) {
1869 take_screenshot_callback_ = take_screenshot_callback; 1830 take_screenshot_callback_ = take_screenshot_callback;
1870 } 1831 }
1871 1832
1872 } // namespace content 1833 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698