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