| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 "chrome/browser/tab_contents/navigation_controller.h" | 5 #include "chrome/browser/tab_contents/navigation_controller.h" |
| 6 | 6 |
| 7 #include "app/resource_bundle.h" | 7 #include "app/resource_bundle.h" |
| 8 #include "base/file_util.h" | 8 #include "base/file_util.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 83 bool AreURLsInPageNavigation(const GURL& existing_url, const GURL& new_url) { | 83 bool AreURLsInPageNavigation(const GURL& existing_url, const GURL& new_url) { |
| 84 if (existing_url == new_url || !new_url.has_ref()) | 84 if (existing_url == new_url || !new_url.has_ref()) |
| 85 return false; | 85 return false; |
| 86 | 86 |
| 87 url_canon::Replacements<char> replacements; | 87 url_canon::Replacements<char> replacements; |
| 88 replacements.ClearRef(); | 88 replacements.ClearRef(); |
| 89 return existing_url.ReplaceComponents(replacements) == | 89 return existing_url.ReplaceComponents(replacements) == |
| 90 new_url.ReplaceComponents(replacements); | 90 new_url.ReplaceComponents(replacements); |
| 91 } | 91 } |
| 92 | 92 |
| 93 // Navigation within this limit since the last document load is considered to |
| 94 // be automatic (i.e., machine-initiated) rather than user-initiated unless |
| 95 // a user gesture has been observed. |
| 96 const base::TimeDelta kMaxAutoNavigationTimeDelta = |
| 97 base::TimeDelta::FromSeconds(5); |
| 98 |
| 93 } // namespace | 99 } // namespace |
| 94 | 100 |
| 95 // NavigationController --------------------------------------------------- | 101 // NavigationController --------------------------------------------------- |
| 96 | 102 |
| 97 // static | 103 // static |
| 98 size_t NavigationController::max_entry_count_ = 50; | 104 size_t NavigationController::max_entry_count_ = 50; |
| 99 | 105 |
| 100 // static | 106 // static |
| 101 bool NavigationController::check_for_repost_ = true; | 107 bool NavigationController::check_for_repost_ = true; |
| 102 | 108 |
| (...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 417 | 423 |
| 418 const SkBitmap& NavigationController::GetLazyFavIcon() const { | 424 const SkBitmap& NavigationController::GetLazyFavIcon() const { |
| 419 if (pending_entry_) { | 425 if (pending_entry_) { |
| 420 return pending_entry_->favicon().bitmap(); | 426 return pending_entry_->favicon().bitmap(); |
| 421 } else { | 427 } else { |
| 422 ResourceBundle &rb = ResourceBundle::GetSharedInstance(); | 428 ResourceBundle &rb = ResourceBundle::GetSharedInstance(); |
| 423 return *rb.GetBitmapNamed(IDR_DEFAULT_FAVICON); | 429 return *rb.GetBitmapNamed(IDR_DEFAULT_FAVICON); |
| 424 } | 430 } |
| 425 } | 431 } |
| 426 | 432 |
| 433 void NavigationController::DocumentLoadedInFrame() { |
| 434 last_document_loaded_ = base::TimeTicks::Now(); |
| 435 } |
| 436 |
| 437 void NavigationController::OnUserGesture() { |
| 438 user_gesture_observed_ = true; |
| 439 } |
| 440 |
| 427 bool NavigationController::RendererDidNavigate( | 441 bool NavigationController::RendererDidNavigate( |
| 428 const ViewHostMsg_FrameNavigate_Params& params, | 442 const ViewHostMsg_FrameNavigate_Params& params, |
| 429 LoadCommittedDetails* details) { | 443 LoadCommittedDetails* details) { |
| 430 // Save the previous state before we clobber it. | 444 // Save the previous state before we clobber it. |
| 431 if (GetLastCommittedEntry()) { | 445 if (GetLastCommittedEntry()) { |
| 432 details->previous_url = GetLastCommittedEntry()->url(); | 446 details->previous_url = GetLastCommittedEntry()->url(); |
| 433 details->previous_entry_index = last_committed_entry_index(); | 447 details->previous_entry_index = last_committed_entry_index(); |
| 434 } else { | 448 } else { |
| 435 details->previous_url = GURL(); | 449 details->previous_url = GURL(); |
| 436 details->previous_entry_index = -1; | 450 details->previous_entry_index = -1; |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 498 | 512 |
| 499 // Now prep the rest of the details for the notification and broadcast. | 513 // Now prep the rest of the details for the notification and broadcast. |
| 500 details->entry = GetActiveEntry(); | 514 details->entry = GetActiveEntry(); |
| 501 details->is_in_page = IsURLInPageNavigation(params.url); | 515 details->is_in_page = IsURLInPageNavigation(params.url); |
| 502 details->is_main_frame = PageTransition::IsMainFrame(params.transition); | 516 details->is_main_frame = PageTransition::IsMainFrame(params.transition); |
| 503 details->serialized_security_info = params.security_info; | 517 details->serialized_security_info = params.security_info; |
| 504 details->is_content_filtered = params.is_content_filtered; | 518 details->is_content_filtered = params.is_content_filtered; |
| 505 details->http_status_code = params.http_status_code; | 519 details->http_status_code = params.http_status_code; |
| 506 NotifyNavigationEntryCommitted(details); | 520 NotifyNavigationEntryCommitted(details); |
| 507 | 521 |
| 522 user_gesture_observed_ = false; |
| 523 |
| 508 return true; | 524 return true; |
| 509 } | 525 } |
| 510 | 526 |
| 511 NavigationType::Type NavigationController::ClassifyNavigation( | 527 NavigationType::Type NavigationController::ClassifyNavigation( |
| 512 const ViewHostMsg_FrameNavigate_Params& params) const { | 528 const ViewHostMsg_FrameNavigate_Params& params) const { |
| 513 // If a page makes a popup navigated to about blank, and then writes stuff | 529 // If a page makes a popup navigated to about blank, and then writes stuff |
| 514 // like a subframe navigated to a real site, we'll get a notification with an | 530 // like a subframe navigated to a real site, we'll get a notification with an |
| 515 // invalid page ID. There's nothing we can do with these, so just ignore them. | 531 // invalid page ID. There's nothing we can do with these, so just ignore them. |
| 516 if (params.page_id == -1) { | 532 if (params.page_id == -1) { |
| 517 DCHECK(!GetActiveEntry()) << "Got an invalid page ID but we seem to be " | 533 DCHECK(!GetActiveEntry()) << "Got an invalid page ID but we seem to be " |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 578 // navigations that don't actually navigate, but it can happen when there is | 594 // navigations that don't actually navigate, but it can happen when there is |
| 579 // an encoding override (it always sends a navigation request). | 595 // an encoding override (it always sends a navigation request). |
| 580 if (AreURLsInPageNavigation(existing_entry->url(), params.url)) | 596 if (AreURLsInPageNavigation(existing_entry->url(), params.url)) |
| 581 return NavigationType::IN_PAGE; | 597 return NavigationType::IN_PAGE; |
| 582 | 598 |
| 583 // Since we weeded out "new" navigations above, we know this is an existing | 599 // Since we weeded out "new" navigations above, we know this is an existing |
| 584 // (back/forward) navigation. | 600 // (back/forward) navigation. |
| 585 return NavigationType::EXISTING_PAGE; | 601 return NavigationType::EXISTING_PAGE; |
| 586 } | 602 } |
| 587 | 603 |
| 604 bool NavigationController::IsRedirect( |
| 605 const ViewHostMsg_FrameNavigate_Params& params) { |
| 606 // For main frame transition, we judge by params.transition. |
| 607 // Otherwise, by params.redirects. |
| 608 if (PageTransition::IsMainFrame(params.transition)) { |
| 609 return PageTransition::IsRedirect(params.transition); |
| 610 } |
| 611 return params.redirects.size() > 1; |
| 612 } |
| 613 |
| 614 bool NavigationController::IsLikelyAutoNavigation(base::TimeTicks now) { |
| 615 return !user_gesture_observed_ && |
| 616 (now - last_document_loaded_) < kMaxAutoNavigationTimeDelta; |
| 617 } |
| 618 |
| 588 void NavigationController::RendererDidNavigateToNewPage( | 619 void NavigationController::RendererDidNavigateToNewPage( |
| 589 const ViewHostMsg_FrameNavigate_Params& params) { | 620 const ViewHostMsg_FrameNavigate_Params& params) { |
| 590 NavigationEntry* new_entry; | 621 NavigationEntry* new_entry; |
| 591 if (pending_entry_) { | 622 if (pending_entry_) { |
| 592 // TODO(brettw) this assumes that the pending entry is appropriate for the | 623 // TODO(brettw) this assumes that the pending entry is appropriate for the |
| 593 // new page that was just loaded. I don't think this is necessarily the | 624 // new page that was just loaded. I don't think this is necessarily the |
| 594 // case! We should have some more tracking to know for sure. This goes along | 625 // case! We should have some more tracking to know for sure. This goes along |
| 595 // with a similar TODO at the top of RendererDidNavigate where we blindly | 626 // with a similar TODO at the top of RendererDidNavigate where we blindly |
| 596 // set the site instance on the pending entry. | 627 // set the site instance on the pending entry. |
| 597 new_entry = new NavigationEntry(*pending_entry_); | 628 new_entry = new NavigationEntry(*pending_entry_); |
| 598 | 629 |
| 599 // Don't use the page type from the pending entry. Some interstitial page | 630 // Don't use the page type from the pending entry. Some interstitial page |
| 600 // may have set the type to interstitial. Once we commit, however, the page | 631 // may have set the type to interstitial. Once we commit, however, the page |
| 601 // type must always be normal. | 632 // type must always be normal. |
| 602 new_entry->set_page_type(NavigationEntry::NORMAL_PAGE); | 633 new_entry->set_page_type(NavigationEntry::NORMAL_PAGE); |
| 603 } else { | 634 } else { |
| 604 new_entry = new NavigationEntry; | 635 new_entry = new NavigationEntry; |
| 605 } | 636 } |
| 606 | 637 |
| 607 new_entry->set_url(params.url); | 638 new_entry->set_url(params.url); |
| 608 new_entry->set_referrer(params.referrer); | 639 new_entry->set_referrer(params.referrer); |
| 609 new_entry->set_page_id(params.page_id); | 640 new_entry->set_page_id(params.page_id); |
| 610 new_entry->set_transition_type(params.transition); | 641 new_entry->set_transition_type(params.transition); |
| 611 new_entry->set_site_instance(tab_contents_->GetSiteInstance()); | 642 new_entry->set_site_instance(tab_contents_->GetSiteInstance()); |
| 612 new_entry->set_has_post_data(params.is_post); | 643 new_entry->set_has_post_data(params.is_post); |
| 613 | 644 |
| 614 // If the current entry is a redirection source, it needs to be replaced with | 645 // If the current entry is a redirection source and the redirection has |
| 615 // the new entry to avoid unwanted redirections in navigating backward / | 646 // occurred within kMaxAutoNavigationTimeDelta since the last document load, |
| 616 // forward. Otherwise, just insert the new entry. | 647 // this is likely to be machine-initiated redirect and the entry needs to be |
| 648 // replaced with the new entry to avoid unwanted redirections in navigating |
| 649 // backward/forward. |
| 650 // Otherwise, just insert the new entry. |
| 617 InsertOrReplaceEntry(new_entry, | 651 InsertOrReplaceEntry(new_entry, |
| 618 PageTransition::IsRedirect(new_entry->transition_type())); | 652 IsRedirect(params) && IsLikelyAutoNavigation(base::TimeTicks::Now())); |
| 619 } | 653 } |
| 620 | 654 |
| 621 void NavigationController::RendererDidNavigateToExistingPage( | 655 void NavigationController::RendererDidNavigateToExistingPage( |
| 622 const ViewHostMsg_FrameNavigate_Params& params) { | 656 const ViewHostMsg_FrameNavigate_Params& params) { |
| 623 // We should only get here for main frame navigations. | 657 // We should only get here for main frame navigations. |
| 624 DCHECK(PageTransition::IsMainFrame(params.transition)); | 658 DCHECK(PageTransition::IsMainFrame(params.transition)); |
| 625 | 659 |
| 626 // This is a back/forward navigation. The existing page for the ID is | 660 // This is a back/forward navigation. The existing page for the ID is |
| 627 // guaranteed to exist by ClassifyNavigation, and we just need to update it | 661 // guaranteed to exist by ClassifyNavigation, and we just need to update it |
| 628 // with new information from the renderer. | 662 // with new information from the renderer. |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 680 NavigationEntry* existing_entry = GetEntryWithPageID( | 714 NavigationEntry* existing_entry = GetEntryWithPageID( |
| 681 tab_contents_->GetSiteInstance(), | 715 tab_contents_->GetSiteInstance(), |
| 682 params.page_id); | 716 params.page_id); |
| 683 | 717 |
| 684 // Reference fragment navigation. We're guaranteed to have the last_committed | 718 // Reference fragment navigation. We're guaranteed to have the last_committed |
| 685 // entry and it will be the same page as the new navigation (minus the | 719 // entry and it will be the same page as the new navigation (minus the |
| 686 // reference fragments, of course). | 720 // reference fragments, of course). |
| 687 NavigationEntry* new_entry = new NavigationEntry(*existing_entry); | 721 NavigationEntry* new_entry = new NavigationEntry(*existing_entry); |
| 688 new_entry->set_page_id(params.page_id); | 722 new_entry->set_page_id(params.page_id); |
| 689 new_entry->set_url(params.url); | 723 new_entry->set_url(params.url); |
| 690 InsertOrReplaceEntry(new_entry, false); | 724 InsertOrReplaceEntry(new_entry, |
| 725 IsRedirect(params) && IsLikelyAutoNavigation(base::TimeTicks::Now())); |
| 691 } | 726 } |
| 692 | 727 |
| 693 void NavigationController::RendererDidNavigateNewSubframe( | 728 void NavigationController::RendererDidNavigateNewSubframe( |
| 694 const ViewHostMsg_FrameNavigate_Params& params) { | 729 const ViewHostMsg_FrameNavigate_Params& params) { |
| 730 if (PageTransition::StripQualifier(params.transition) == |
| 731 PageTransition::AUTO_SUBFRAME) { |
| 732 // This is not user-initiated. Ignore. |
| 733 return; |
| 734 } |
| 735 if (IsRedirect(params)) { |
| 736 // This is redirect. Ignore. |
| 737 return; |
| 738 } |
| 739 |
| 695 // Manual subframe navigations just get the current entry cloned so the user | 740 // Manual subframe navigations just get the current entry cloned so the user |
| 696 // can go back or forward to it. The actual subframe information will be | 741 // can go back or forward to it. The actual subframe information will be |
| 697 // stored in the page state for each of those entries. This happens out of | 742 // stored in the page state for each of those entries. This happens out of |
| 698 // band with the actual navigations. | 743 // band with the actual navigations. |
| 699 DCHECK(GetLastCommittedEntry()) << "ClassifyNavigation should guarantee " | 744 DCHECK(GetLastCommittedEntry()) << "ClassifyNavigation should guarantee " |
| 700 << "that a last committed entry exists."; | 745 << "that a last committed entry exists."; |
| 701 NavigationEntry* new_entry = new NavigationEntry(*GetLastCommittedEntry()); | 746 NavigationEntry* new_entry = new NavigationEntry(*GetLastCommittedEntry()); |
| 702 new_entry->set_page_id(params.page_id); | 747 new_entry->set_page_id(params.page_id); |
| 703 InsertOrReplaceEntry(new_entry, false); | 748 InsertOrReplaceEntry(new_entry, false); |
| 704 } | 749 } |
| (...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 974 return i; | 1019 return i; |
| 975 } | 1020 } |
| 976 return -1; | 1021 return -1; |
| 977 } | 1022 } |
| 978 | 1023 |
| 979 NavigationEntry* NavigationController::GetTransientEntry() const { | 1024 NavigationEntry* NavigationController::GetTransientEntry() const { |
| 980 if (transient_entry_index_ == -1) | 1025 if (transient_entry_index_ == -1) |
| 981 return NULL; | 1026 return NULL; |
| 982 return entries_[transient_entry_index_].get(); | 1027 return entries_[transient_entry_index_].get(); |
| 983 } | 1028 } |
| OLD | NEW |