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/navigation_controller_impl.h" | 5 #include "content/browser/frame_host/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/logging.h" | 9 #include "base/logging.h" |
10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
11 #include "base/strings/string_number_conversions.h" // Temporary | 11 #include "base/strings/string_number_conversions.h" // Temporary |
12 #include "base/strings/string_util.h" | 12 #include "base/strings/string_util.h" |
13 #include "base/strings/utf_string_conversions.h" | 13 #include "base/strings/utf_string_conversions.h" |
14 #include "base/time/time.h" | 14 #include "base/time/time.h" |
15 #include "base/trace_event/trace_event.h" | 15 #include "base/trace_event/trace_event.h" |
16 #include "cc/base/switches.h" | 16 #include "cc/base/switches.h" |
17 #include "content/browser/browser_url_handler_impl.h" | 17 #include "content/browser/browser_url_handler_impl.h" |
18 #include "content/browser/dom_storage/dom_storage_context_wrapper.h" | 18 #include "content/browser/dom_storage/dom_storage_context_wrapper.h" |
19 #include "content/browser/dom_storage/session_storage_namespace_impl.h" | 19 #include "content/browser/dom_storage/session_storage_namespace_impl.h" |
20 #include "content/browser/frame_host/debug_urls.h" | 20 #include "content/browser/frame_host/debug_urls.h" |
| 21 #include "content/browser/frame_host/frame_navigation_entry.h" |
21 #include "content/browser/frame_host/interstitial_page_impl.h" | 22 #include "content/browser/frame_host/interstitial_page_impl.h" |
22 #include "content/browser/frame_host/navigation_entry_impl.h" | 23 #include "content/browser/frame_host/navigation_entry_impl.h" |
23 #include "content/browser/frame_host/navigation_entry_screenshot_manager.h" | 24 #include "content/browser/frame_host/navigation_entry_screenshot_manager.h" |
| 25 #include "content/browser/frame_host/navigator_impl.h" |
24 #include "content/browser/renderer_host/render_view_host_impl.h" // Temporary | 26 #include "content/browser/renderer_host/render_view_host_impl.h" // Temporary |
25 #include "content/browser/site_instance_impl.h" | 27 #include "content/browser/site_instance_impl.h" |
26 #include "content/common/frame_messages.h" | 28 #include "content/common/frame_messages.h" |
27 #include "content/common/view_messages.h" | 29 #include "content/common/view_messages.h" |
28 #include "content/public/browser/browser_context.h" | 30 #include "content/public/browser/browser_context.h" |
29 #include "content/public/browser/content_browser_client.h" | 31 #include "content/public/browser/content_browser_client.h" |
30 #include "content/public/browser/invalidate_type.h" | 32 #include "content/public/browser/invalidate_type.h" |
31 #include "content/public/browser/navigation_details.h" | 33 #include "content/public/browser/navigation_details.h" |
32 #include "content/public/browser/notification_service.h" | 34 #include "content/public/browser/notification_service.h" |
33 #include "content/public/browser/notification_types.h" | 35 #include "content/public/browser/notification_types.h" |
(...skipping 29 matching lines...) Expand all Loading... |
63 } | 65 } |
64 | 66 |
65 // Ensure the given NavigationEntry has a valid state, so that WebKit does not | 67 // Ensure the given NavigationEntry has a valid state, so that WebKit does not |
66 // get confused if we navigate back to it. | 68 // get confused if we navigate back to it. |
67 // | 69 // |
68 // An empty state is treated as a new navigation by WebKit, which would mean | 70 // An empty state is treated as a new navigation by WebKit, which would mean |
69 // losing the navigation entries and generating a new navigation entry after | 71 // losing the navigation entries and generating a new navigation entry after |
70 // this one. We don't want that. To avoid this we create a valid state which | 72 // this one. We don't want that. To avoid this we create a valid state which |
71 // WebKit will not treat as a new navigation. | 73 // WebKit will not treat as a new navigation. |
72 void SetPageStateIfEmpty(NavigationEntryImpl* entry) { | 74 void SetPageStateIfEmpty(NavigationEntryImpl* entry) { |
| 75 // TODO(creis): Do this for FrameNavigationEntries instead. |
73 if (!entry->GetPageState().IsValid()) | 76 if (!entry->GetPageState().IsValid()) |
74 entry->SetPageState(PageState::CreateFromURL(entry->GetURL())); | 77 entry->SetPageState(PageState::CreateFromURL(entry->GetURL())); |
75 } | 78 } |
76 | 79 |
77 NavigationEntryImpl::RestoreType ControllerRestoreTypeToEntryType( | 80 NavigationEntryImpl::RestoreType ControllerRestoreTypeToEntryType( |
78 NavigationController::RestoreType type) { | 81 NavigationController::RestoreType type) { |
79 switch (type) { | 82 switch (type) { |
80 case NavigationController::RESTORE_CURRENT_SESSION: | 83 case NavigationController::RESTORE_CURRENT_SESSION: |
81 return NavigationEntryImpl::RESTORE_CURRENT_SESSION; | 84 return NavigationEntryImpl::RESTORE_CURRENT_SESSION; |
82 case NavigationController::RESTORE_LAST_SESSION_EXITED_CLEANLY: | 85 case NavigationController::RESTORE_LAST_SESSION_EXITED_CLEANLY: |
83 return NavigationEntryImpl::RESTORE_LAST_SESSION_EXITED_CLEANLY; | 86 return NavigationEntryImpl::RESTORE_LAST_SESSION_EXITED_CLEANLY; |
84 case NavigationController::RESTORE_LAST_SESSION_CRASHED: | 87 case NavigationController::RESTORE_LAST_SESSION_CRASHED: |
85 return NavigationEntryImpl::RESTORE_LAST_SESSION_CRASHED; | 88 return NavigationEntryImpl::RESTORE_LAST_SESSION_CRASHED; |
86 } | 89 } |
87 NOTREACHED(); | 90 NOTREACHED(); |
88 return NavigationEntryImpl::RESTORE_CURRENT_SESSION; | 91 return NavigationEntryImpl::RESTORE_CURRENT_SESSION; |
89 } | 92 } |
90 | 93 |
91 // Configure all the NavigationEntries in entries for restore. This resets | 94 // Configure all the NavigationEntries in entries for restore. This resets |
92 // the transition type to reload and makes sure the content state isn't empty. | 95 // the transition type to reload and makes sure the content state isn't empty. |
| 96 // TODO(creis): Take in a vector of FrameNavigationEntries instead. |
93 void ConfigureEntriesForRestore( | 97 void ConfigureEntriesForRestore( |
94 std::vector<linked_ptr<NavigationEntryImpl> >* entries, | 98 std::vector<linked_ptr<NavigationEntryImpl> >* entries, |
95 NavigationController::RestoreType type) { | 99 NavigationController::RestoreType type) { |
96 for (size_t i = 0; i < entries->size(); ++i) { | 100 for (size_t i = 0; i < entries->size(); ++i) { |
97 // Use a transition type of reload so that we don't incorrectly increase | 101 // Use a transition type of reload so that we don't incorrectly increase |
98 // the typed count. | 102 // the typed count. |
99 (*entries)[i]->SetTransitionType(ui::PAGE_TRANSITION_RELOAD); | 103 (*entries)[i]->SetTransitionType(ui::PAGE_TRANSITION_RELOAD); |
100 (*entries)[i]->set_restore_type(ControllerRestoreTypeToEntryType(type)); | 104 (*entries)[i]->set_restore_type(ControllerRestoreTypeToEntryType(type)); |
101 // NOTE(darin): This code is only needed for backwards compat. | 105 // NOTE(darin): This code is only needed for backwards compat. |
102 SetPageStateIfEmpty((*entries)[i].get()); | 106 SetPageStateIfEmpty((*entries)[i].get()); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
174 | 178 |
175 // Allow the browser URL handler to rewrite the URL. This will, for example, | 179 // Allow the browser URL handler to rewrite the URL. This will, for example, |
176 // remove "view-source:" from the beginning of the URL to get the URL that | 180 // remove "view-source:" from the beginning of the URL to get the URL that |
177 // will actually be loaded. This real URL won't be shown to the user, just | 181 // will actually be loaded. This real URL won't be shown to the user, just |
178 // used internally. | 182 // used internally. |
179 GURL loaded_url(dest_url); | 183 GURL loaded_url(dest_url); |
180 bool reverse_on_redirect = false; | 184 bool reverse_on_redirect = false; |
181 BrowserURLHandlerImpl::GetInstance()->RewriteURLIfNecessary( | 185 BrowserURLHandlerImpl::GetInstance()->RewriteURLIfNecessary( |
182 &loaded_url, browser_context, &reverse_on_redirect); | 186 &loaded_url, browser_context, &reverse_on_redirect); |
183 | 187 |
| 188 // Common case: Navigate the top-level frame. |
184 NavigationEntryImpl* entry = new NavigationEntryImpl( | 189 NavigationEntryImpl* entry = new NavigationEntryImpl( |
185 NULL, // The site instance for tabs is sent on navigation | 190 NULL, // The site instance for tabs is sent on navigation |
186 // (WebContents::GetSiteInstance). | 191 // (WebContents::GetSiteInstance). |
187 -1, | 192 -1, |
188 loaded_url, | 193 loaded_url, |
189 referrer, | 194 referrer, |
190 base::string16(), | 195 base::string16(), |
191 transition, | 196 transition, |
192 is_renderer_initiated); | 197 is_renderer_initiated); |
193 entry->SetVirtualURL(dest_url); | 198 entry->SetVirtualURL(dest_url); |
194 entry->set_user_typed_url(dest_url); | 199 entry->set_user_typed_url(dest_url); |
195 entry->set_update_virtual_url_with_url(reverse_on_redirect); | 200 entry->set_update_virtual_url_with_url(reverse_on_redirect); |
196 entry->set_extra_headers(extra_headers); | 201 entry->set_extra_headers(extra_headers); |
197 return entry; | 202 return entry; |
198 } | 203 } |
199 | 204 |
| 205 // TODO(creis): Share code with CreateNavigationEntry. |
| 206 NavigationEntryImpl* NavigationControllerImpl::CreateSubframeNavigationEntry( |
| 207 int64 frame_tree_node_id, |
| 208 const GURL& url, |
| 209 const Referrer& referrer, |
| 210 ui::PageTransition transition, |
| 211 bool is_renderer_initiated, |
| 212 const std::string& extra_headers, |
| 213 BrowserContext* browser_context) { |
| 214 // Allow the browser URL handler to rewrite the URL. This will, for example, |
| 215 // remove "view-source:" from the beginning of the URL to get the URL that |
| 216 // will actually be loaded. This real URL won't be shown to the user, just |
| 217 // used internally. |
| 218 GURL loaded_url(url); |
| 219 bool reverse_on_redirect = false; |
| 220 BrowserURLHandlerImpl::GetInstance()->RewriteURLIfNecessary( |
| 221 &loaded_url, browser_context, &reverse_on_redirect); |
| 222 |
| 223 FrameTreeNode* main_frame = delegate_->GetFrameTreeRoot(); |
| 224 |
| 225 // Subframe navigation: Clone the current tree, then create a FrameNavEntry |
| 226 // for the specified frame, clearing its subtree. |
| 227 // TODO(creis): Don't clear subtree for in-page navigations. |
| 228 NavigationEntryImpl* entry = new NavigationEntryImpl(); |
| 229 AddFramesToNavigationEntry(entry->root_node(), main_frame); |
| 230 NavigationEntryImpl::TreeNode* node = |
| 231 entry->GetTreeNodeForFrame( |
| 232 main_frame->frame_tree()->FindByID(frame_tree_node_id)); |
| 233 DCHECK(node) << "Couldn't find TreeNode for " << frame_tree_node_id; |
| 234 node->frame_entry = new FrameNavigationEntry(NULL, loaded_url, referrer); |
| 235 node->frame_entry->set_frame_tree_node_id(frame_tree_node_id); |
| 236 node->children.clear(); |
| 237 |
| 238 entry->SetVirtualURL(url); |
| 239 entry->set_user_typed_url(url); |
| 240 entry->set_update_virtual_url_with_url(reverse_on_redirect); |
| 241 entry->set_extra_headers(extra_headers); |
| 242 return entry; |
| 243 } |
| 244 |
200 // static | 245 // static |
201 void NavigationController::DisablePromptOnRepost() { | 246 void NavigationController::DisablePromptOnRepost() { |
202 g_check_for_repost = false; | 247 g_check_for_repost = false; |
203 } | 248 } |
204 | 249 |
205 base::Time NavigationControllerImpl::TimeSmoother::GetSmoothedTime( | 250 base::Time NavigationControllerImpl::TimeSmoother::GetSmoothedTime( |
206 base::Time t) { | 251 base::Time t) { |
207 // If |t| is between the water marks, we're in a run of duplicates | 252 // If |t| is between the water marks, we're in a run of duplicates |
208 // or just getting out of it, so increase the high-water mark to get | 253 // or just getting out of it, so increase the high-water mark to get |
209 // a time that probably hasn't been used before and return it. | 254 // a time that probably hasn't been used before and return it. |
(...skipping 10 matching lines...) Expand all Loading... |
220 | 265 |
221 NavigationControllerImpl::NavigationControllerImpl( | 266 NavigationControllerImpl::NavigationControllerImpl( |
222 NavigationControllerDelegate* delegate, | 267 NavigationControllerDelegate* delegate, |
223 BrowserContext* browser_context) | 268 BrowserContext* browser_context) |
224 : browser_context_(browser_context), | 269 : browser_context_(browser_context), |
225 pending_entry_(NULL), | 270 pending_entry_(NULL), |
226 last_committed_entry_index_(-1), | 271 last_committed_entry_index_(-1), |
227 pending_entry_index_(-1), | 272 pending_entry_index_(-1), |
228 transient_entry_index_(-1), | 273 transient_entry_index_(-1), |
229 delegate_(delegate), | 274 delegate_(delegate), |
| 275 next_page_id_(1), |
230 max_restored_page_id_(-1), | 276 max_restored_page_id_(-1), |
231 ssl_manager_(this), | 277 ssl_manager_(this), |
232 needs_reload_(false), | 278 needs_reload_(false), |
233 is_initial_navigation_(true), | 279 is_initial_navigation_(true), |
234 in_navigate_to_pending_entry_(false), | 280 in_navigate_to_pending_entry_(false), |
235 pending_reload_(NO_RELOAD), | 281 pending_reload_(NO_RELOAD), |
236 get_timestamp_callback_(base::Bind(&base::Time::Now)), | 282 get_timestamp_callback_(base::Bind(&base::Time::Now)), |
237 screenshot_manager_(new NavigationEntryScreenshotManager(this)) { | 283 screenshot_manager_(new NavigationEntryScreenshotManager(this)) { |
238 DCHECK(browser_context_); | 284 DCHECK(browser_context_); |
239 } | 285 } |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
402 ReloadInternal(false, pending_reload_); | 448 ReloadInternal(false, pending_reload_); |
403 pending_reload_ = NO_RELOAD; | 449 pending_reload_ = NO_RELOAD; |
404 } | 450 } |
405 } | 451 } |
406 | 452 |
407 bool NavigationControllerImpl::IsInitialNavigation() const { | 453 bool NavigationControllerImpl::IsInitialNavigation() const { |
408 return is_initial_navigation_; | 454 return is_initial_navigation_; |
409 } | 455 } |
410 | 456 |
411 NavigationEntryImpl* NavigationControllerImpl::GetEntryWithPageID( | 457 NavigationEntryImpl* NavigationControllerImpl::GetEntryWithPageID( |
412 SiteInstance* instance, int32 page_id) const { | 458 int32 page_id) const { |
413 int index = GetEntryIndexWithPageID(instance, page_id); | 459 int index = GetEntryIndexWithPageID(page_id); |
414 return (index != -1) ? entries_[index].get() : NULL; | 460 return (index != -1) ? entries_[index].get() : NULL; |
415 } | 461 } |
416 | 462 |
417 void NavigationControllerImpl::LoadEntry(NavigationEntryImpl* entry) { | 463 void NavigationControllerImpl::LoadEntry(NavigationEntryImpl* entry) { |
418 // When navigating to a new page, we don't know for sure if we will actually | 464 // When navigating to a new page, we don't know for sure if we will actually |
419 // end up leaving the current page. The new page load could for example | 465 // end up leaving the current page. The new page load could for example |
420 // result in a download or a 'no content' response (e.g., a mailto: URL). | 466 // result in a download or a 'no content' response (e.g., a mailto: URL). |
421 SetPendingEntry(entry); | 467 SetPendingEntry(entry); |
422 NavigateToPendingEntry(NO_RELOAD); | 468 NavigateToPendingEntry(NO_RELOAD); |
423 } | 469 } |
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
712 break; | 758 break; |
713 case UA_OVERRIDE_FALSE: | 759 case UA_OVERRIDE_FALSE: |
714 override = false; | 760 override = false; |
715 break; | 761 break; |
716 default: | 762 default: |
717 NOTREACHED(); | 763 NOTREACHED(); |
718 break; | 764 break; |
719 } | 765 } |
720 | 766 |
721 NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry( | 767 NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry( |
722 CreateNavigationEntry( | 768 params.frame_tree_node_id == -1 ? |
723 params.url, | 769 CreateNavigationEntry( |
724 params.referrer, | 770 params.url, |
725 params.transition_type, | 771 params.referrer, |
726 params.is_renderer_initiated, | 772 params.transition_type, |
727 params.extra_headers, | 773 params.is_renderer_initiated, |
728 browser_context_)); | 774 params.extra_headers, |
729 if (params.frame_tree_node_id != -1) | 775 browser_context_) : |
730 entry->set_frame_tree_node_id(params.frame_tree_node_id); | 776 CreateSubframeNavigationEntry( |
| 777 params.frame_tree_node_id, |
| 778 params.url, |
| 779 params.referrer, |
| 780 params.transition_type, |
| 781 params.is_renderer_initiated, |
| 782 params.extra_headers, |
| 783 browser_context_)); |
| 784 // TODO(creis): Move source_site_instance to FNE. |
731 entry->set_source_site_instance( | 785 entry->set_source_site_instance( |
732 static_cast<SiteInstanceImpl*>(params.source_site_instance.get())); | 786 static_cast<SiteInstanceImpl*>(params.source_site_instance.get())); |
733 if (params.redirect_chain.size() > 0) | 787 if (params.redirect_chain.size() > 0) |
734 entry->SetRedirectChain(params.redirect_chain); | 788 entry->SetRedirectChain(params.redirect_chain); |
735 // Don't allow an entry replacement if there is no entry to replace. | 789 // Don't allow an entry replacement if there is no entry to replace. |
736 // http://crbug.com/457149 | 790 // http://crbug.com/457149 |
737 if (params.should_replace_current_entry && entries_.size() > 0) | 791 if (params.should_replace_current_entry && entries_.size() > 0) |
738 entry->set_should_replace_entry(true); | 792 entry->set_should_replace_entry(true); |
739 entry->set_should_clear_history_list(params.should_clear_history_list); | 793 entry->set_should_clear_history_list(params.should_clear_history_list); |
740 entry->SetIsOverridingUserAgent(override); | 794 entry->SetIsOverridingUserAgent(override); |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
853 // We should not have a pending entry anymore. Clear it again in case any | 907 // We should not have a pending entry anymore. Clear it again in case any |
854 // error cases above forgot to do so. | 908 // error cases above forgot to do so. |
855 DiscardNonCommittedEntriesInternal(); | 909 DiscardNonCommittedEntriesInternal(); |
856 | 910 |
857 // All committed entries should have nonempty content state so WebKit doesn't | 911 // All committed entries should have nonempty content state so WebKit doesn't |
858 // get confused when we go back to them (see the function for details). | 912 // get confused when we go back to them (see the function for details). |
859 DCHECK(params.page_state.IsValid()); | 913 DCHECK(params.page_state.IsValid()); |
860 NavigationEntryImpl* active_entry = GetLastCommittedEntry(); | 914 NavigationEntryImpl* active_entry = GetLastCommittedEntry(); |
861 active_entry->SetTimestamp(timestamp); | 915 active_entry->SetTimestamp(timestamp); |
862 active_entry->SetHttpStatusCode(params.http_status_code); | 916 active_entry->SetHttpStatusCode(params.http_status_code); |
863 active_entry->SetPageState(params.page_state); | |
864 active_entry->SetRedirectChain(params.redirects); | 917 active_entry->SetRedirectChain(params.redirects); |
| 918 FrameNavigationEntry* frame_entry = |
| 919 active_entry->GetFrameEntryForFrame(rfh->frame_tree_node()); |
| 920 frame_entry->set_page_state(params.page_state); |
865 | 921 |
866 // Use histogram to track memory impact of redirect chain because it's now | 922 // Use histogram to track memory impact of redirect chain because it's now |
867 // not cleared for committed entries. | 923 // not cleared for committed entries. |
868 size_t redirect_chain_size = 0; | 924 size_t redirect_chain_size = 0; |
869 for (size_t i = 0; i < params.redirects.size(); ++i) { | 925 for (size_t i = 0; i < params.redirects.size(); ++i) { |
870 redirect_chain_size += params.redirects[i].spec().length(); | 926 redirect_chain_size += params.redirects[i].spec().length(); |
871 } | 927 } |
872 UMA_HISTOGRAM_COUNTS("Navigation.RedirectChainSize", redirect_chain_size); | 928 UMA_HISTOGRAM_COUNTS("Navigation.RedirectChainSize", redirect_chain_size); |
873 | 929 |
874 // Once it is committed, we no longer need to track several pieces of state on | 930 // Once it is committed, we no longer need to track several pieces of state on |
875 // the entry. | 931 // the entry. |
876 active_entry->ResetForCommit(); | 932 active_entry->ResetForCommit(); |
877 | 933 |
878 // The active entry's SiteInstance should match our SiteInstance. | 934 // The active entry's SiteInstance should match our SiteInstance. |
879 // TODO(creis): This check won't pass for subframes until we create entries | 935 CHECK(frame_entry->site_instance() == rfh->GetSiteInstance()); |
880 // for subframe navigations. | |
881 if (ui::PageTransitionIsMainFrame(params.transition)) | |
882 CHECK(active_entry->site_instance() == rfh->GetSiteInstance()); | |
883 | 936 |
884 // Remember the bindings the renderer process has at this point, so that | 937 // Remember the bindings the renderer process has at this point, so that |
885 // we do not grant this entry additional bindings if we come back to it. | 938 // we do not grant this entry additional bindings if we come back to it. |
886 active_entry->SetBindings(rfh->GetEnabledBindings()); | 939 active_entry->SetBindings(rfh->GetEnabledBindings()); |
887 | 940 |
888 // Now prep the rest of the details for the notification and broadcast. | 941 // Now prep the rest of the details for the notification and broadcast. |
889 details->entry = active_entry; | 942 details->entry = active_entry; |
890 details->is_main_frame = | 943 details->is_main_frame = |
891 ui::PageTransitionIsMainFrame(params.transition); | 944 ui::PageTransitionIsMainFrame(params.transition); |
892 details->serialized_security_info = params.security_info; | 945 details->serialized_security_info = params.security_info; |
893 details->http_status_code = params.http_status_code; | 946 details->http_status_code = params.http_status_code; |
894 NotifyNavigationEntryCommitted(details); | 947 NotifyNavigationEntryCommitted(details); |
895 | 948 |
896 return true; | 949 return true; |
897 } | 950 } |
898 | 951 |
899 NavigationType NavigationControllerImpl::ClassifyNavigation( | 952 NavigationType NavigationControllerImpl::ClassifyNavigation( |
900 RenderFrameHostImpl* rfh, | 953 RenderFrameHostImpl* rfh, |
901 const FrameHostMsg_DidCommitProvisionalLoad_Params& params) const { | 954 const FrameHostMsg_DidCommitProvisionalLoad_Params& params) const { |
902 if (params.page_id == -1) { | 955 // TODO(creis): Can this go away? We now have page_id == -1 for all new navs. |
903 // TODO(nasko, creis): An out-of-process child frame has no way of | 956 if (params.item_sequence_number == -1) { |
904 // knowing the page_id of its parent, so it is passing back -1. The | |
905 // semantics here should be re-evaluated during session history refactor | |
906 // (see http://crbug.com/236848). For now, we assume this means the | |
907 // child frame loaded and proceed. Note that this may do the wrong thing | |
908 // for cross-process AUTO_SUBFRAME navigations. | |
909 if (rfh->IsCrossProcessSubframe()) | |
910 return NAVIGATION_TYPE_NEW_SUBFRAME; | |
911 | |
912 // The renderer generates the page IDs, and so if it gives us the invalid | 957 // The renderer generates the page IDs, and so if it gives us the invalid |
913 // page ID (-1) we know it didn't actually navigate. This happens in a few | 958 // page ID (-1) we know it didn't actually navigate. This happens in a few |
914 // cases: | 959 // cases: |
915 // | 960 // |
916 // - If a page makes a popup navigated to about blank, and then writes | 961 // - If a page makes a popup navigated to about blank, and then writes |
917 // stuff like a subframe navigated to a real page. We'll get the commit | 962 // stuff like a subframe navigated to a real page. We'll get the commit |
918 // for the subframe, but there won't be any commit for the outer page. | 963 // for the subframe, but there won't be any commit for the outer page. |
919 // | 964 // |
920 // - We were also getting these for failed loads (for example, bug 21849). | 965 // - We were also getting these for failed loads (for example, bug 21849). |
921 // The guess is that we get a "load commit" for the alternate error page, | 966 // The guess is that we get a "load commit" for the alternate error page, |
922 // but that doesn't affect the page ID, so we get the "old" one, which | 967 // but that doesn't affect the page ID, so we get the "old" one, which |
923 // could be invalid. This can also happen for a cross-site transition | 968 // could be invalid. This can also happen for a cross-site transition |
924 // that causes us to swap processes. Then the error page load will be in | 969 // that causes us to swap processes. Then the error page load will be in |
925 // a new process with no page IDs ever assigned (and hence a -1 value), | 970 // a new process with no page IDs ever assigned (and hence a -1 value), |
926 // yet the navigation controller still might have previous pages in its | 971 // yet the navigation controller still might have previous pages in its |
927 // list. | 972 // list. |
928 // | 973 // |
929 // In these cases, there's nothing we can do with them, so ignore. | 974 // In these cases, there's nothing we can do with them, so ignore. |
930 return NAVIGATION_TYPE_NAV_IGNORE; | 975 return NAVIGATION_TYPE_NAV_IGNORE; |
931 } | 976 } |
932 | 977 |
933 if (params.page_id > delegate_->GetMaxPageIDForSiteInstance( | 978 if (params.page_id == -1) { |
934 rfh->GetSiteInstance())) { | 979 // A page ID of -1 means this is a new navigation of some kind. |
| 980 // TODO(creis): update comment below. |
935 // Greater page IDs than we've ever seen before are new pages. We may or may | 981 // Greater page IDs than we've ever seen before are new pages. We may or may |
936 // not have a pending entry for the page, and this may or may not be the | 982 // not have a pending entry for the page, and this may or may not be the |
937 // main frame. | 983 // main frame. |
938 if (ui::PageTransitionIsMainFrame(params.transition)) | 984 if (ui::PageTransitionIsMainFrame(params.transition)) |
939 return NAVIGATION_TYPE_NEW_PAGE; | 985 return NAVIGATION_TYPE_NEW_PAGE; |
940 | 986 |
941 // When this is a new subframe navigation, we should have a committed page | 987 // When this is a new subframe navigation, we should have a committed page |
942 // for which it's a suframe in. This may not be the case when an iframe is | 988 // for which it's a suframe in. This may not be the case when an iframe is |
943 // navigated on a popup navigated to about:blank (the iframe would be | 989 // navigated on a popup navigated to about:blank (the iframe would be |
944 // written into the popup by script on the main page). For these cases, | 990 // written into the popup by script on the main page). For these cases, |
945 // there isn't any navigation stuff we can do, so just ignore it. | 991 // there isn't any navigation stuff we can do, so just ignore it. |
946 if (!GetLastCommittedEntry()) | 992 if (!GetLastCommittedEntry()) |
947 return NAVIGATION_TYPE_NAV_IGNORE; | 993 return NAVIGATION_TYPE_NAV_IGNORE; |
948 | 994 |
949 // Valid subframe navigation. | 995 // Valid subframe navigation. |
| 996 // TODO(creis): Do this once 464014 is fixed. |
| 997 //if (ui::PageTransitionCoreTypeIs(params.transition, |
| 998 // ui::PAGE_TRANSITION_AUTO_SUBFRAME)) |
| 999 // return NAVIGATION_TYPE_AUTO_SUBFRAME; |
950 return NAVIGATION_TYPE_NEW_SUBFRAME; | 1000 return NAVIGATION_TYPE_NEW_SUBFRAME; |
951 } | 1001 } |
952 | 1002 |
953 // We only clear the session history when navigating to a new page. | 1003 // We only clear the session history when navigating to a new page. |
954 DCHECK(!params.history_list_was_cleared); | 1004 DCHECK(!params.history_list_was_cleared); |
955 | 1005 |
956 // Now we know that the notification is for an existing page. Find that entry. | 1006 // Now we know that the notification is for an existing page. Find that entry. |
957 int existing_entry_index = GetEntryIndexWithPageID( | 1007 int existing_entry_index = GetEntryIndexWithPageID(params.page_id); |
958 rfh->GetSiteInstance(), | |
959 params.page_id); | |
960 if (existing_entry_index == -1) { | 1008 if (existing_entry_index == -1) { |
961 // The page was not found. It could have been pruned because of the limit on | 1009 // The page was not found. It could have been pruned because of the limit on |
962 // back/forward entries (not likely since we'll usually tell it to navigate | 1010 // back/forward entries (not likely since we'll usually tell it to navigate |
963 // to such entries). It could also mean that the renderer is smoking crack. | 1011 // to such entries). It could also mean that the renderer is smoking crack. |
964 NOTREACHED(); | 1012 NOTREACHED(); |
965 | 1013 |
966 // Because the unknown entry has committed, we risk showing the wrong URL in | 1014 // Because the unknown entry has committed, we risk showing the wrong URL in |
967 // release builds. Instead, we'll kill the renderer process to be safe. | 1015 // release builds. Instead, we'll kill the renderer process to be safe. |
968 LOG(ERROR) << "terminating renderer for bad navigation: " << params.url; | 1016 LOG(ERROR) << "terminating renderer for bad navigation: " << params.url; |
969 RecordAction(base::UserMetricsAction("BadMessageTerminate_NC")); | 1017 RecordAction(base::UserMetricsAction("BadMessageTerminate_NC")); |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1036 // Since we weeded out "new" navigations above, we know this is an existing | 1084 // Since we weeded out "new" navigations above, we know this is an existing |
1037 // (back/forward) navigation. | 1085 // (back/forward) navigation. |
1038 return NAVIGATION_TYPE_EXISTING_PAGE; | 1086 return NAVIGATION_TYPE_EXISTING_PAGE; |
1039 } | 1087 } |
1040 | 1088 |
1041 void NavigationControllerImpl::RendererDidNavigateToNewPage( | 1089 void NavigationControllerImpl::RendererDidNavigateToNewPage( |
1042 RenderFrameHostImpl* rfh, | 1090 RenderFrameHostImpl* rfh, |
1043 const FrameHostMsg_DidCommitProvisionalLoad_Params& params, | 1091 const FrameHostMsg_DidCommitProvisionalLoad_Params& params, |
1044 bool replace_entry) { | 1092 bool replace_entry) { |
1045 NavigationEntryImpl* new_entry; | 1093 NavigationEntryImpl* new_entry; |
| 1094 FrameNavigationEntry* new_frame_entry; |
1046 bool update_virtual_url; | 1095 bool update_virtual_url; |
1047 // Only make a copy of the pending entry if it is appropriate for the new page | 1096 // Only make a copy of the pending entry if it is appropriate for the new page |
1048 // that was just loaded. We verify this at a coarse grain by checking that | 1097 // that was just loaded. We verify this at a coarse grain by checking that |
1049 // the SiteInstance hasn't been assigned to something else. | 1098 // the SiteInstance hasn't been assigned to something else. |
1050 if (pending_entry_ && | 1099 // TODO(creis): Copy over details from pending entry when appropriate. |
1051 (!pending_entry_->site_instance() || | 1100 // (Do we need a pending entry for each frame?) |
1052 pending_entry_->site_instance() == rfh->GetSiteInstance())) { | 1101 /*FrameNavigationEntryImpl* pending_entry = ...; |
1053 new_entry = pending_entry_->Clone(); | 1102 if (pending_entry && |
| 1103 (!pending_entry_>site_instance() || |
| 1104 pending_entry->site_instance() == rfh->GetSiteInstance())) { |
| 1105 new_entry = new FrameNavigationEntryImpl(*pending_entry); |
1054 | 1106 |
1055 update_virtual_url = new_entry->update_virtual_url_with_url(); | 1107 update_virtual_url = new_entry->update_virtual_url_with_url(); |
1056 } else { | 1108 } else { */ |
1057 new_entry = new NavigationEntryImpl; | 1109 new_entry = new NavigationEntryImpl; |
| 1110 new_frame_entry = new FrameNavigationEntry; |
| 1111 int64 frame_tree_node_id = rfh->frame_tree_node()->frame_tree_node_id(); |
| 1112 new_frame_entry->set_frame_tree_node_id(frame_tree_node_id); |
1058 | 1113 |
1059 // Find out whether the new entry needs to update its virtual URL on URL | 1114 // Find out whether the new entry needs to update its virtual URL on URL |
1060 // change and set up the entry accordingly. This is needed to correctly | 1115 // change and set up the entry accordingly. This is needed to correctly |
1061 // update the virtual URL when replaceState is called after a pushState. | 1116 // update the virtual URL when replaceState is called after a pushState. |
1062 GURL url = params.url; | 1117 GURL url = params.url; |
1063 bool needs_update = false; | 1118 bool needs_update = false; |
1064 BrowserURLHandlerImpl::GetInstance()->RewriteURLIfNecessary( | 1119 BrowserURLHandlerImpl::GetInstance()->RewriteURLIfNecessary( |
1065 &url, browser_context_, &needs_update); | 1120 &url, browser_context_, &needs_update); |
1066 new_entry->set_update_virtual_url_with_url(needs_update); | 1121 new_entry->set_update_virtual_url_with_url(needs_update); |
1067 | 1122 |
1068 // When navigating to a new page, give the browser URL handler a chance to | 1123 // When navigating to a new page, give the browser URL handler a chance to |
1069 // update the virtual URL based on the new URL. For example, this is needed | 1124 // update the virtual URL based on the new URL. For example, this is needed |
1070 // to show chrome://bookmarks/#1 when the bookmarks webui extension changes | 1125 // to show chrome://bookmarks/#1 when the bookmarks webui extension changes |
1071 // the URL. | 1126 // the URL. |
1072 update_virtual_url = needs_update; | 1127 update_virtual_url = needs_update; |
1073 } | 1128 //} |
1074 | 1129 |
1075 // Don't use the page type from the pending entry. Some interstitial page | 1130 // Don't use the page type from the pending entry. Some interstitial page |
1076 // may have set the type to interstitial. Once we commit, however, the page | 1131 // may have set the type to interstitial. Once we commit, however, the page |
1077 // type must always be normal or error. | 1132 // type must always be normal or error. |
| 1133 // TODO(creis): Move page type to FNE. |
1078 new_entry->set_page_type(params.url_is_unreachable ? PAGE_TYPE_ERROR | 1134 new_entry->set_page_type(params.url_is_unreachable ? PAGE_TYPE_ERROR |
1079 : PAGE_TYPE_NORMAL); | 1135 : PAGE_TYPE_NORMAL); |
1080 new_entry->SetURL(params.url); | 1136 new_frame_entry->set_url(params.url); |
1081 if (update_virtual_url) | 1137 if (update_virtual_url) |
1082 UpdateVirtualURLToURL(new_entry, params.url); | 1138 UpdateVirtualURLToURL(new_entry, params.url); |
1083 new_entry->SetReferrer(params.referrer); | 1139 new_frame_entry->set_referrer(params.referrer); |
1084 new_entry->SetPageID(params.page_id); | 1140 new_frame_entry->set_site_instance(rfh->GetSiteInstance()); |
| 1141 new_frame_entry->set_item_sequence_number(params.item_sequence_number); |
| 1142 new_frame_entry->set_document_sequence_number( |
| 1143 params.document_sequence_number); |
| 1144 |
| 1145 // Use a new page ID for this entry. |
| 1146 CHECK_EQ(-1, params.page_id); |
| 1147 new_entry->SetPageID(next_page_id_++); |
| 1148 |
1085 new_entry->SetTransitionType(params.transition); | 1149 new_entry->SetTransitionType(params.transition); |
1086 new_entry->set_site_instance( | |
1087 static_cast<SiteInstanceImpl*>(rfh->GetSiteInstance())); | |
1088 new_entry->SetHasPostData(params.is_post); | 1150 new_entry->SetHasPostData(params.is_post); |
1089 new_entry->SetPostID(params.post_id); | 1151 new_entry->SetPostID(params.post_id); |
1090 new_entry->SetOriginalRequestURL(params.original_request_url); | 1152 new_entry->SetOriginalRequestURL(params.original_request_url); |
1091 new_entry->SetIsOverridingUserAgent(params.is_overriding_user_agent); | 1153 new_entry->SetIsOverridingUserAgent(params.is_overriding_user_agent); |
1092 | 1154 |
1093 // history.pushState() is classified as a navigation to a new page, but | 1155 // history.pushState() is classified as a navigation to a new page, but |
1094 // sets was_within_same_page to true. In this case, we already have the | 1156 // sets was_within_same_page to true. In this case, we already have the |
1095 // title and favicon available, so set them immediately. | 1157 // title and favicon available, so set them immediately. |
1096 if (params.was_within_same_page && GetLastCommittedEntry()) { | 1158 if (params.was_within_same_page && GetLastCommittedEntry()) { |
1097 new_entry->SetTitle(GetLastCommittedEntry()->GetTitle()); | 1159 new_entry->SetTitle(GetLastCommittedEntry()->GetTitle()); |
1098 new_entry->GetFavicon() = GetLastCommittedEntry()->GetFavicon(); | 1160 new_entry->GetFavicon() = GetLastCommittedEntry()->GetFavicon(); |
1099 } | 1161 } |
1100 | 1162 |
1101 DCHECK(!params.history_list_was_cleared || !replace_entry); | 1163 DCHECK(!params.history_list_was_cleared || !replace_entry); |
1102 // The browser requested to clear the session history when it initiated the | 1164 // The browser requested to clear the session history when it initiated the |
1103 // navigation. Now we know that the renderer has updated its state accordingly | 1165 // navigation. Now we know that the renderer has updated its state accordingly |
1104 // and it is safe to also clear the browser side history. | 1166 // and it is safe to also clear the browser side history. |
1105 if (params.history_list_was_cleared) { | 1167 if (params.history_list_was_cleared) { |
1106 DiscardNonCommittedEntriesInternal(); | 1168 DiscardNonCommittedEntriesInternal(); |
1107 entries_.clear(); | 1169 entries_.clear(); |
1108 last_committed_entry_index_ = -1; | 1170 last_committed_entry_index_ = -1; |
| 1171 rfh->frame_tree_node()->set_last_committed_frame_entry(nullptr); |
1109 } | 1172 } |
1110 | 1173 |
1111 InsertOrReplaceEntry(new_entry, replace_entry); | 1174 InsertOrReplaceEntry(rfh, new_entry, new_frame_entry, replace_entry); |
1112 } | 1175 } |
1113 | 1176 |
1114 void NavigationControllerImpl::RendererDidNavigateToExistingPage( | 1177 void NavigationControllerImpl::RendererDidNavigateToExistingPage( |
1115 RenderFrameHostImpl* rfh, | 1178 RenderFrameHostImpl* rfh, |
1116 const FrameHostMsg_DidCommitProvisionalLoad_Params& params) { | 1179 const FrameHostMsg_DidCommitProvisionalLoad_Params& params) { |
1117 // We should only get here for main frame navigations. | 1180 // We should only get here for main frame navigations. |
1118 DCHECK(ui::PageTransitionIsMainFrame(params.transition)); | 1181 DCHECK(ui::PageTransitionIsMainFrame(params.transition)); |
1119 | 1182 |
1120 // This is a back/forward navigation. The existing page for the ID is | 1183 // This is a back/forward navigation. The existing page for the ID is |
1121 // guaranteed to exist by ClassifyNavigation, and we just need to update it | 1184 // guaranteed to exist by ClassifyNavigation, and we just need to update it |
1122 // with new information from the renderer. | 1185 // with new information from the renderer. |
1123 int entry_index = GetEntryIndexWithPageID(rfh->GetSiteInstance(), | 1186 int entry_index = GetEntryIndexWithPageID(params.page_id); |
1124 params.page_id); | |
1125 DCHECK(entry_index >= 0 && | 1187 DCHECK(entry_index >= 0 && |
1126 entry_index < static_cast<int>(entries_.size())); | 1188 entry_index < static_cast<int>(entries_.size())); |
1127 NavigationEntryImpl* entry = entries_[entry_index].get(); | 1189 NavigationEntryImpl* entry = entries_[entry_index].get(); |
1128 | 1190 |
| 1191 // TODO(creis): Do these operations directly on the FNE. |
1129 // The URL may have changed due to redirects. | 1192 // The URL may have changed due to redirects. |
1130 entry->set_page_type(params.url_is_unreachable ? PAGE_TYPE_ERROR | 1193 entry->set_page_type(params.url_is_unreachable ? PAGE_TYPE_ERROR |
1131 : PAGE_TYPE_NORMAL); | 1194 : PAGE_TYPE_NORMAL); |
1132 entry->SetURL(params.url); | 1195 entry->SetURL(params.url); |
1133 entry->SetReferrer(params.referrer); | 1196 entry->SetReferrer(params.referrer); |
1134 if (entry->update_virtual_url_with_url()) | 1197 if (entry->update_virtual_url_with_url()) |
1135 UpdateVirtualURLToURL(entry, params.url); | 1198 UpdateVirtualURLToURL(entry, params.url); |
1136 | 1199 |
1137 // The redirected to page should not inherit the favicon from the previous | 1200 // The redirected to page should not inherit the favicon from the previous |
1138 // page. | 1201 // page. |
1139 if (ui::PageTransitionIsRedirect(params.transition)) | 1202 if (ui::PageTransitionIsRedirect(params.transition)) |
1140 entry->GetFavicon() = FaviconStatus(); | 1203 entry->GetFavicon() = FaviconStatus(); |
1141 | 1204 |
1142 // The site instance will normally be the same except during session restore, | 1205 // The site instance will normally be the same except during session restore, |
1143 // when no site instance will be assigned. | 1206 // when no site instance will be assigned. |
1144 DCHECK(entry->site_instance() == NULL || | 1207 DCHECK(entry->site_instance() == NULL || |
1145 entry->site_instance() == rfh->GetSiteInstance()); | 1208 entry->site_instance() == rfh->GetSiteInstance()); |
1146 entry->set_site_instance( | 1209 entry->set_site_instance(rfh->GetSiteInstance()); |
1147 static_cast<SiteInstanceImpl*>(rfh->GetSiteInstance())); | |
1148 | 1210 |
1149 entry->SetHasPostData(params.is_post); | 1211 entry->SetHasPostData(params.is_post); |
1150 entry->SetPostID(params.post_id); | 1212 entry->SetPostID(params.post_id); |
1151 | 1213 |
1152 // The entry we found in the list might be pending if the user hit | 1214 // The entry we found in the list might be pending if the user hit |
1153 // back/forward/reload. This load should commit it (since it's already in the | 1215 // back/forward/reload. This load should commit it (since it's already in the |
1154 // list, we can just discard the pending pointer). We should also discard the | 1216 // list, we can just discard the pending pointer). We should also discard the |
1155 // pending entry if it corresponds to a different navigation, since that one | 1217 // pending entry if it corresponds to a different navigation, since that one |
1156 // is now likely canceled. If it is not canceled, we will treat it as a new | 1218 // is now likely canceled. If it is not canceled, we will treat it as a new |
1157 // navigation when it arrives, which is also ok. | 1219 // navigation when it arrives, which is also ok. |
1158 // | 1220 // |
1159 // Note that we need to use the "internal" version since we don't want to | 1221 // Note that we need to use the "internal" version since we don't want to |
1160 // actually change any other state, just kill the pointer. | 1222 // actually change any other state, just kill the pointer. |
1161 DiscardNonCommittedEntriesInternal(); | 1223 DiscardNonCommittedEntriesInternal(); |
1162 | 1224 |
1163 // If a transient entry was removed, the indices might have changed, so we | 1225 // If a transient entry was removed, the indices might have changed, so we |
1164 // have to query the entry index again. | 1226 // have to query the entry index again. |
1165 last_committed_entry_index_ = | 1227 last_committed_entry_index_ = GetEntryIndexWithPageID(params.page_id); |
1166 GetEntryIndexWithPageID(rfh->GetSiteInstance(), params.page_id); | 1228 rfh->frame_tree_node()->set_last_committed_frame_entry( |
| 1229 entry->GetFrameEntryForFrame(rfh->frame_tree_node())); |
1167 } | 1230 } |
1168 | 1231 |
1169 void NavigationControllerImpl::RendererDidNavigateToSamePage( | 1232 void NavigationControllerImpl::RendererDidNavigateToSamePage( |
1170 RenderFrameHostImpl* rfh, | 1233 RenderFrameHostImpl* rfh, |
1171 const FrameHostMsg_DidCommitProvisionalLoad_Params& params) { | 1234 const FrameHostMsg_DidCommitProvisionalLoad_Params& params) { |
1172 // This mode implies we have a pending entry that's the same as an existing | 1235 // This mode implies we have a pending entry that's the same as an existing |
1173 // entry for this page ID. This entry is guaranteed to exist by | 1236 // entry for this page ID. This entry is guaranteed to exist by |
1174 // ClassifyNavigation. All we need to do is update the existing entry. | 1237 // ClassifyNavigation. All we need to do is update the existing entry. |
1175 NavigationEntryImpl* existing_entry = GetEntryWithPageID( | 1238 NavigationEntryImpl* existing_entry = GetEntryWithPageID(params.page_id); |
1176 rfh->GetSiteInstance(), params.page_id); | |
1177 | 1239 |
1178 // We assign the entry's unique ID to be that of the new one. Since this is | 1240 // We assign the entry's unique ID to be that of the new one. Since this is |
1179 // always the result of a user action, we want to dismiss infobars, etc. like | 1241 // always the result of a user action, we want to dismiss infobars, etc. like |
1180 // a regular user-initiated navigation. | 1242 // a regular user-initiated navigation. |
1181 existing_entry->set_unique_id(pending_entry_->GetUniqueID()); | 1243 existing_entry->set_unique_id(pending_entry_->GetUniqueID()); |
1182 | 1244 |
1183 // The URL may have changed due to redirects. | 1245 // The URL may have changed due to redirects. |
1184 existing_entry->set_page_type(params.url_is_unreachable ? PAGE_TYPE_ERROR | 1246 existing_entry->set_page_type(params.url_is_unreachable ? PAGE_TYPE_ERROR |
1185 : PAGE_TYPE_NORMAL); | 1247 : PAGE_TYPE_NORMAL); |
1186 if (existing_entry->update_virtual_url_with_url()) | 1248 if (existing_entry->update_virtual_url_with_url()) |
1187 UpdateVirtualURLToURL(existing_entry, params.url); | 1249 UpdateVirtualURLToURL(existing_entry, params.url); |
1188 existing_entry->SetURL(params.url); | 1250 existing_entry->SetURL(params.url); |
1189 existing_entry->SetReferrer(params.referrer); | 1251 existing_entry->SetReferrer(params.referrer); |
1190 | 1252 |
1191 // The page may have been requested with a different HTTP method. | 1253 // The page may have been requested with a different HTTP method. |
1192 existing_entry->SetHasPostData(params.is_post); | 1254 existing_entry->SetHasPostData(params.is_post); |
1193 existing_entry->SetPostID(params.post_id); | 1255 existing_entry->SetPostID(params.post_id); |
1194 | 1256 |
1195 DiscardNonCommittedEntries(); | 1257 DiscardNonCommittedEntries(); |
1196 } | 1258 } |
1197 | 1259 |
1198 void NavigationControllerImpl::RendererDidNavigateInPage( | 1260 void NavigationControllerImpl::RendererDidNavigateInPage( |
1199 RenderFrameHostImpl* rfh, | 1261 RenderFrameHostImpl* rfh, |
1200 const FrameHostMsg_DidCommitProvisionalLoad_Params& params, | 1262 const FrameHostMsg_DidCommitProvisionalLoad_Params& params, |
1201 bool* did_replace_entry) { | 1263 bool* did_replace_entry) { |
| 1264 // TODO(creis): Why? Is this by spec? |
1202 DCHECK(ui::PageTransitionIsMainFrame(params.transition)) << | 1265 DCHECK(ui::PageTransitionIsMainFrame(params.transition)) << |
1203 "WebKit should only tell us about in-page navs for the main frame."; | 1266 "WebKit should only tell us about in-page navs for the main frame."; |
1204 // We're guaranteed to have an entry for this one. | 1267 // We're guaranteed to have an entry for this one. |
1205 NavigationEntryImpl* existing_entry = GetEntryWithPageID( | 1268 NavigationEntryImpl* existing_entry = GetEntryWithPageID(params.page_id); |
1206 rfh->GetSiteInstance(), params.page_id); | |
1207 | 1269 |
1208 // Reference fragment navigation. We're guaranteed to have the last_committed | 1270 // Reference fragment navigation. We're guaranteed to have the last_committed |
1209 // entry and it will be the same page as the new navigation (minus the | 1271 // entry and it will be the same page as the new navigation (minus the |
1210 // reference fragments, of course). We'll update the URL of the existing | 1272 // reference fragments, of course). We'll update the URL of the existing |
1211 // entry without pruning the forward history. | 1273 // entry without pruning the forward history. |
1212 existing_entry->set_page_type(params.url_is_unreachable ? PAGE_TYPE_ERROR | 1274 existing_entry->set_page_type(params.url_is_unreachable ? PAGE_TYPE_ERROR |
1213 : PAGE_TYPE_NORMAL); | 1275 : PAGE_TYPE_NORMAL); |
1214 existing_entry->SetURL(params.url); | 1276 existing_entry->SetURL(params.url); |
1215 if (existing_entry->update_virtual_url_with_url()) | 1277 if (existing_entry->update_virtual_url_with_url()) |
1216 UpdateVirtualURLToURL(existing_entry, params.url); | 1278 UpdateVirtualURLToURL(existing_entry, params.url); |
1217 | 1279 |
1218 existing_entry->SetHasPostData(params.is_post); | 1280 existing_entry->SetHasPostData(params.is_post); |
1219 existing_entry->SetPostID(params.post_id); | 1281 existing_entry->SetPostID(params.post_id); |
1220 | 1282 |
1221 // This replaces the existing entry since the page ID didn't change. | 1283 // This replaces the existing entry since the page ID didn't change. |
1222 *did_replace_entry = true; | 1284 *did_replace_entry = true; |
1223 | 1285 |
1224 DiscardNonCommittedEntriesInternal(); | 1286 DiscardNonCommittedEntriesInternal(); |
1225 | 1287 |
1226 // If a transient entry was removed, the indices might have changed, so we | 1288 // If a transient entry was removed, the indices might have changed, so we |
1227 // have to query the entry index again. | 1289 // have to query the entry index again. |
1228 last_committed_entry_index_ = | 1290 last_committed_entry_index_ = GetEntryIndexWithPageID(params.page_id); |
1229 GetEntryIndexWithPageID(rfh->GetSiteInstance(), params.page_id); | 1291 rfh->frame_tree_node()->set_last_committed_frame_entry( |
| 1292 existing_entry->GetFrameEntryForFrame(rfh->frame_tree_node())); |
1230 } | 1293 } |
1231 | 1294 |
1232 void NavigationControllerImpl::RendererDidNavigateNewSubframe( | 1295 void NavigationControllerImpl::RendererDidNavigateNewSubframe( |
1233 RenderFrameHostImpl* rfh, | 1296 RenderFrameHostImpl* rfh, |
1234 const FrameHostMsg_DidCommitProvisionalLoad_Params& params) { | 1297 const FrameHostMsg_DidCommitProvisionalLoad_Params& params) { |
1235 if (!ui::PageTransitionCoreTypeIs(params.transition, | 1298 int64 frame_tree_node_id = rfh->frame_tree_node()->frame_tree_node_id(); |
1236 ui::PAGE_TRANSITION_MANUAL_SUBFRAME)) { | 1299 // TODO(creis): Is this equivalent to checking PAGE_TRANSITION_AUTO_SUBFRAME? |
| 1300 if (!rfh->frame_tree_node()->last_committed_frame_entry()) { |
| 1301 DCHECK(ui::PageTransitionCoreTypeIs(params.transition, |
| 1302 ui::PAGE_TRANSITION_AUTO_SUBFRAME)); |
1237 // There was a comment here that said, "This is not user-initiated. Ignore." | 1303 // There was a comment here that said, "This is not user-initiated. Ignore." |
1238 // But this makes no sense; non-user-initiated navigations should be | 1304 // But this makes no sense; non-user-initiated navigations should be |
1239 // determined to be of type NAVIGATION_TYPE_AUTO_SUBFRAME and sent to | 1305 // determined to be of type NAVIGATION_TYPE_AUTO_SUBFRAME and sent to |
1240 // RendererDidNavigateAutoSubframe below. | 1306 // RendererDidNavigateAutoSubframe below. |
1241 // | 1307 // |
1242 // This if clause dates back to https://codereview.chromium.org/115919 and | 1308 // This if clause dates back to https://codereview.chromium.org/115919 and |
1243 // the handling of immediate redirects. TODO(avi): Is this still valid? I'm | 1309 // the handling of immediate redirects. TODO(avi): Is this still valid? I'm |
1244 // pretty sure that's there's nothing left of that code and that we should | 1310 // pretty sure that's there's nothing left of that code and that we should |
1245 // take this out. | 1311 // take this out. |
1246 // | 1312 // |
1247 // Except for cross-process iframes; this doesn't work yet for them. | 1313 // Except for cross-process iframes; this doesn't work yet for them. |
1248 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( | 1314 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( |
1249 switches::kSitePerProcess)) { | 1315 switches::kSitePerProcess)) { |
1250 NOTREACHED(); | 1316 NOTREACHED(); |
1251 } | 1317 } |
1252 | 1318 |
1253 DiscardNonCommittedEntriesInternal(); | 1319 DiscardNonCommittedEntriesInternal(); |
| 1320 |
| 1321 // New: We do need to add a FrameNavigationEntry. |
| 1322 // TODO(creis): Refactor this method to avoid duplication. |
| 1323 FrameNavigationEntry* frame_entry = new FrameNavigationEntry( |
| 1324 rfh->GetSiteInstance(), params.url, params.referrer); |
| 1325 frame_entry->set_frame_tree_node_id(frame_tree_node_id); |
| 1326 frame_entry->set_item_sequence_number(params.item_sequence_number); |
| 1327 frame_entry->set_document_sequence_number(params.document_sequence_number); |
| 1328 rfh->frame_tree_node()->set_last_committed_frame_entry(frame_entry); |
| 1329 |
| 1330 // Reset the frame tree pointers for the last committed entry. |
| 1331 NavigationEntryImpl* last_committed = |
| 1332 NavigationEntryImpl::FromNavigationEntry(GetLastCommittedEntry()); |
| 1333 // TODO(creis): Just add this one; don't try to reset the whole tree. |
| 1334 last_committed->ResetFrameTree(); |
| 1335 AddFramesToNavigationEntry(last_committed->root_node(), |
| 1336 delegate_->GetFrameTreeRoot()); |
| 1337 |
1254 return; | 1338 return; |
1255 } | 1339 } |
1256 | 1340 |
1257 // Manual subframe navigations just get the current entry cloned so the user | 1341 // Manual subframe navigations just get the current entry cloned so the user |
1258 // can go back or forward to it. The actual subframe information will be | 1342 // can go back or forward to it. The actual subframe information will be |
1259 // stored in the page state for each of those entries. This happens out of | 1343 // stored in the page state for each of those entries. This happens out of |
1260 // band with the actual navigations. | 1344 // band with the actual navigations. |
1261 DCHECK(GetLastCommittedEntry()) << "ClassifyNavigation should guarantee " | 1345 DCHECK(GetLastCommittedEntry()) << "ClassifyNavigation should guarantee " |
1262 << "that a last committed entry exists."; | 1346 << "that a last committed entry exists."; |
1263 NavigationEntryImpl* new_entry = GetLastCommittedEntry()->Clone(); | 1347 NavigationEntryImpl* new_entry = GetLastCommittedEntry()->Clone(); |
1264 new_entry->SetPageID(params.page_id); | 1348 |
1265 InsertOrReplaceEntry(new_entry, false); | 1349 // Use a new page ID for this entry. |
| 1350 CHECK_EQ(-1, params.page_id); |
| 1351 new_entry->SetPageID(next_page_id_++); |
| 1352 |
| 1353 // Create an appropriate subframe entry for it. |
| 1354 FrameNavigationEntry* frame_entry = new FrameNavigationEntry( |
| 1355 rfh->GetSiteInstance(), params.url, params.referrer); |
| 1356 frame_entry->set_frame_tree_node_id(frame_tree_node_id); |
| 1357 frame_entry->set_item_sequence_number(params.item_sequence_number); |
| 1358 frame_entry->set_document_sequence_number(params.document_sequence_number); |
| 1359 |
| 1360 InsertOrReplaceEntry(rfh, new_entry, frame_entry, false); |
1266 } | 1361 } |
1267 | 1362 |
1268 bool NavigationControllerImpl::RendererDidNavigateAutoSubframe( | 1363 bool NavigationControllerImpl::RendererDidNavigateAutoSubframe( |
1269 RenderFrameHostImpl* rfh, | 1364 RenderFrameHostImpl* rfh, |
1270 const FrameHostMsg_DidCommitProvisionalLoad_Params& params) { | 1365 const FrameHostMsg_DidCommitProvisionalLoad_Params& params) { |
1271 DCHECK(ui::PageTransitionCoreTypeIs(params.transition, | 1366 DCHECK(ui::PageTransitionCoreTypeIs(params.transition, |
1272 ui::PAGE_TRANSITION_AUTO_SUBFRAME)); | 1367 ui::PAGE_TRANSITION_AUTO_SUBFRAME)); |
1273 | 1368 |
1274 // We're guaranteed to have a previously committed entry, and we now need to | 1369 // We're guaranteed to have a previously committed entry, and we now need to |
1275 // handle navigation inside of a subframe in it without creating a new entry. | 1370 // handle navigation inside of a subframe in it without creating a new entry. |
1276 DCHECK(GetLastCommittedEntry()); | 1371 DCHECK(GetLastCommittedEntry()); |
1277 | 1372 |
1278 // Handle the case where we're navigating back/forward to a previous subframe | 1373 // TODO(creis): Split this out into ExistingSubframe. |
1279 // navigation entry. This is case "2." in NAV_AUTO_SUBFRAME comment in the | 1374 // Handle the case where we're navigating back/forward to a previous |
1280 // header file. In case "1." this will be a NOP. | 1375 // subframe navigation entry. This is case "2." in NAV_AUTO_SUBFRAME comment |
1281 int entry_index = GetEntryIndexWithPageID( | 1376 // in the header file. In case "1." this will be a NOP. |
1282 rfh->GetSiteInstance(), | 1377 int entry_index = GetEntryIndexWithPageID(params.page_id); |
1283 params.page_id); | 1378 if (entry_index < 0 || entry_index >= static_cast<int>(entries_.size())) { |
1284 if (entry_index < 0 || | |
1285 entry_index >= static_cast<int>(entries_.size())) { | |
1286 NOTREACHED(); | 1379 NOTREACHED(); |
1287 return false; | 1380 return false; |
1288 } | 1381 } |
1289 | 1382 |
1290 // Update the current navigation entry in case we're going back/forward. | 1383 // Update the current navigation entry in case we're going back/forward. |
1291 if (entry_index != last_committed_entry_index_) { | 1384 if (entry_index != last_committed_entry_index_) { |
1292 last_committed_entry_index_ = entry_index; | 1385 last_committed_entry_index_ = entry_index; |
1293 DiscardNonCommittedEntriesInternal(); | 1386 DiscardNonCommittedEntriesInternal(); |
| 1387 |
| 1388 // New: Find the FrameNavigationEntry this corresponds to and update our |
| 1389 // index for that frame. |
| 1390 // TODO(creis): Update the FNE, similar to ExistingPage. |
| 1391 NavigationEntryImpl* entry = GetEntryAtIndex(entry_index); |
| 1392 FrameNavigationEntry* frame_entry = |
| 1393 entry->GetFrameEntryForFrame(rfh->frame_tree_node()); |
| 1394 rfh->frame_tree_node()->set_last_committed_frame_entry(frame_entry); |
| 1395 |
1294 return true; | 1396 return true; |
1295 } | 1397 } |
1296 | 1398 |
| 1399 // If we get here without returning, then this was a second (or greater) |
| 1400 // subframe committing as part of a back/forward. Only the first one causes |
| 1401 // us to change the last_committed_entry_index_. |
| 1402 |
| 1403 // New: We do need to add a FrameNavigationEntry. |
| 1404 FrameNavigationEntry* frame_entry = new FrameNavigationEntry( |
| 1405 rfh->GetSiteInstance(), params.url, params.referrer); |
| 1406 int64 frame_tree_node_id = rfh->frame_tree_node()->frame_tree_node_id(); |
| 1407 frame_entry->set_frame_tree_node_id(frame_tree_node_id); |
| 1408 frame_entry->set_item_sequence_number(params.item_sequence_number); |
| 1409 frame_entry->set_document_sequence_number(params.document_sequence_number); |
| 1410 |
| 1411 // TODO(creis): This was missing in the case of going forward from an old main |
| 1412 // frame to one with a subframe. We don't give the re-created subframe the |
| 1413 // same FTN ID, so we don't find it in our array. (That's a bug on its own.) |
| 1414 // But when we do get here legitimately, don't we need to assign page state? |
| 1415 // What else? |
| 1416 frame_entry->set_page_state(params.page_state); |
| 1417 |
| 1418 rfh->frame_tree_node()->set_last_committed_frame_entry(frame_entry); |
| 1419 |
| 1420 // Reset the frame tree pointers for the last committed entry. |
| 1421 NavigationEntryImpl* last_committed = |
| 1422 NavigationEntryImpl::FromNavigationEntry(GetLastCommittedEntry()); |
| 1423 // TODO(creis): Just add this one; don't try to reset the whole tree. |
| 1424 last_committed->ResetFrameTree(); |
| 1425 AddFramesToNavigationEntry(last_committed->root_node(), |
| 1426 delegate_->GetFrameTreeRoot()); |
| 1427 |
1297 // We do not need to discard the pending entry in this case, since we will | 1428 // We do not need to discard the pending entry in this case, since we will |
1298 // not generate commit notifications for this auto-subframe navigation. | 1429 // not generate commit notifications for this auto-subframe navigation. |
1299 return false; | 1430 return false; |
1300 } | 1431 } |
1301 | 1432 |
1302 int NavigationControllerImpl::GetIndexOfEntry( | 1433 int NavigationControllerImpl::GetIndexOfEntry( |
1303 const NavigationEntryImpl* entry) const { | 1434 const NavigationEntryImpl* entry) const { |
1304 const NavigationEntries::const_iterator i(std::find( | 1435 const NavigationEntries::const_iterator i(std::find( |
1305 entries_.begin(), | 1436 entries_.begin(), |
1306 entries_.end(), | 1437 entries_.end(), |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1434 void NavigationControllerImpl::PruneAllButLastCommittedInternal() { | 1565 void NavigationControllerImpl::PruneAllButLastCommittedInternal() { |
1435 // It is up to callers to check the invariants before calling this. | 1566 // It is up to callers to check the invariants before calling this. |
1436 CHECK(CanPruneAllButLastCommitted()); | 1567 CHECK(CanPruneAllButLastCommitted()); |
1437 | 1568 |
1438 // Erase all entries but the last committed entry. There may still be a | 1569 // Erase all entries but the last committed entry. There may still be a |
1439 // new pending entry after this. | 1570 // new pending entry after this. |
1440 entries_.erase(entries_.begin(), | 1571 entries_.erase(entries_.begin(), |
1441 entries_.begin() + last_committed_entry_index_); | 1572 entries_.begin() + last_committed_entry_index_); |
1442 entries_.erase(entries_.begin() + 1, entries_.end()); | 1573 entries_.erase(entries_.begin() + 1, entries_.end()); |
1443 last_committed_entry_index_ = 0; | 1574 last_committed_entry_index_ = 0; |
| 1575 // TODO(creis): Update last committed FNE?. |
1444 } | 1576 } |
1445 | 1577 |
1446 void NavigationControllerImpl::ClearAllScreenshots() { | 1578 void NavigationControllerImpl::ClearAllScreenshots() { |
1447 screenshot_manager_->ClearAllScreenshots(); | 1579 screenshot_manager_->ClearAllScreenshots(); |
1448 } | 1580 } |
1449 | 1581 |
1450 void NavigationControllerImpl::SetSessionStorageNamespace( | 1582 void NavigationControllerImpl::SetSessionStorageNamespace( |
1451 const std::string& partition_id, | 1583 const std::string& partition_id, |
1452 SessionStorageNamespace* session_storage_namespace) { | 1584 SessionStorageNamespace* session_storage_namespace) { |
1453 if (!session_storage_namespace) | 1585 if (!session_storage_namespace) |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1556 } | 1688 } |
1557 | 1689 |
1558 NavigationEntryImpl* NavigationControllerImpl::GetPendingEntry() const { | 1690 NavigationEntryImpl* NavigationControllerImpl::GetPendingEntry() const { |
1559 return pending_entry_; | 1691 return pending_entry_; |
1560 } | 1692 } |
1561 | 1693 |
1562 int NavigationControllerImpl::GetPendingEntryIndex() const { | 1694 int NavigationControllerImpl::GetPendingEntryIndex() const { |
1563 return pending_entry_index_; | 1695 return pending_entry_index_; |
1564 } | 1696 } |
1565 | 1697 |
1566 void NavigationControllerImpl::InsertOrReplaceEntry(NavigationEntryImpl* entry, | 1698 void NavigationControllerImpl::InsertOrReplaceEntry( |
1567 bool replace) { | 1699 RenderFrameHostImpl* rfh, |
| 1700 NavigationEntryImpl* entry, |
| 1701 FrameNavigationEntry* frame_entry, |
| 1702 bool replace) { |
1568 DCHECK(entry->GetTransitionType() != ui::PAGE_TRANSITION_AUTO_SUBFRAME); | 1703 DCHECK(entry->GetTransitionType() != ui::PAGE_TRANSITION_AUTO_SUBFRAME); |
1569 | 1704 |
1570 // Copy the pending entry's unique ID to the committed entry. | 1705 // Copy the pending entry's unique ID to the committed entry. |
1571 // I don't know if pending_entry_index_ can be other than -1 here. | 1706 // I don't know if pending_entry_index_ can be other than -1 here. |
1572 const NavigationEntryImpl* const pending_entry = | 1707 const NavigationEntryImpl* const pending_entry = |
1573 (pending_entry_index_ == -1) ? | 1708 (pending_entry_index_ == -1) ? |
1574 pending_entry_ : entries_[pending_entry_index_].get(); | 1709 pending_entry_ : entries_[pending_entry_index_].get(); |
1575 if (pending_entry) | 1710 if (pending_entry) |
1576 entry->set_unique_id(pending_entry->GetUniqueID()); | 1711 entry->set_unique_id(pending_entry->GetUniqueID()); |
1577 | 1712 |
(...skipping 16 matching lines...) Expand all Loading... |
1594 num_pruned++; | 1729 num_pruned++; |
1595 entries_.pop_back(); | 1730 entries_.pop_back(); |
1596 current_size--; | 1731 current_size--; |
1597 } | 1732 } |
1598 if (num_pruned > 0) // Only notify if we did prune something. | 1733 if (num_pruned > 0) // Only notify if we did prune something. |
1599 NotifyPrunedEntries(this, false, num_pruned); | 1734 NotifyPrunedEntries(this, false, num_pruned); |
1600 } | 1735 } |
1601 | 1736 |
1602 PruneOldestEntryIfFull(); | 1737 PruneOldestEntryIfFull(); |
1603 | 1738 |
| 1739 // New: Set the last committed frame entry for this frame. |
| 1740 // TODO(creis): This breaks in the replace case. We need to update the |
| 1741 // existing FNE with all the data from frame_entry in that case, since many |
| 1742 // NE's might already have references to the existing one. |
| 1743 rfh->frame_tree_node()->set_last_committed_frame_entry(frame_entry); |
| 1744 |
| 1745 // New: Give the entry a fresh tree of pointers to the current frame entry for |
| 1746 // each current frame, starting from the root. |
| 1747 // TODO(creis): How can we clear it without deleting the refcounted FNEs? |
| 1748 // I think we want to verify that it's empty here, and have a different way to |
| 1749 // append a new frame to an existing NE. |
| 1750 entry->ResetFrameTree(); |
| 1751 AddFramesToNavigationEntry(entry->root_node(), delegate_->GetFrameTreeRoot()); |
| 1752 |
| 1753 // Finally, add the entry to the joint session history. |
1604 entries_.push_back(linked_ptr<NavigationEntryImpl>(entry)); | 1754 entries_.push_back(linked_ptr<NavigationEntryImpl>(entry)); |
1605 last_committed_entry_index_ = static_cast<int>(entries_.size()) - 1; | 1755 last_committed_entry_index_ = static_cast<int>(entries_.size()) - 1; |
1606 | 1756 |
1607 // This is a new page ID, so we need everybody to know about it. | 1757 // This is a new page ID, so we need everybody to know about it. |
| 1758 // TODO(creis): Is this still necessary? |
1608 delegate_->UpdateMaxPageID(entry->GetPageID()); | 1759 delegate_->UpdateMaxPageID(entry->GetPageID()); |
1609 } | 1760 } |
1610 | 1761 |
| 1762 void NavigationControllerImpl::AddFramesToNavigationEntry( |
| 1763 NavigationEntryImpl::TreeNode* entry_node, |
| 1764 FrameTreeNode* frame_tree_node) { |
| 1765 // TODO(creis): Remove this once auto-subframe case is fixed. // ? |
| 1766 if (!frame_tree_node->last_committed_frame_entry()) |
| 1767 return; |
| 1768 |
| 1769 // Put the last committed FrameNavigationEntry for this frame into the |
| 1770 // corresponding spot of the top-level NavigationEntry. |
| 1771 entry_node->SetFrameEntry(frame_tree_node->last_committed_frame_entry()); |
| 1772 CHECK(entry_node->frame_entry); |
| 1773 |
| 1774 // Repeat for all the child frames. |
| 1775 for (size_t i=0; i < frame_tree_node->child_count(); i++) { |
| 1776 entry_node->children.push_back( |
| 1777 new NavigationEntryImpl::TreeNode(entry_node->entry, nullptr)); |
| 1778 CHECK_EQ(i + 1, entry_node->children.size()); |
| 1779 AddFramesToNavigationEntry(entry_node->children[i], |
| 1780 frame_tree_node->child_at(i)); |
| 1781 } |
| 1782 } |
| 1783 |
1611 void NavigationControllerImpl::PruneOldestEntryIfFull() { | 1784 void NavigationControllerImpl::PruneOldestEntryIfFull() { |
1612 if (entries_.size() >= max_entry_count()) { | 1785 if (entries_.size() >= max_entry_count()) { |
1613 DCHECK_EQ(max_entry_count(), entries_.size()); | 1786 DCHECK_EQ(max_entry_count(), entries_.size()); |
1614 DCHECK_GT(last_committed_entry_index_, 0); | 1787 DCHECK_GT(last_committed_entry_index_, 0); |
1615 RemoveEntryAtIndex(0); | 1788 RemoveEntryAtIndex(0); |
1616 NotifyPrunedEntries(this, true, 1); | 1789 NotifyPrunedEntries(this, true, 1); |
1617 } | 1790 } |
1618 } | 1791 } |
1619 | 1792 |
1620 void NavigationControllerImpl::NavigateToPendingEntry(ReloadType reload_type) { | 1793 void NavigationControllerImpl::NavigateToPendingEntry(ReloadType reload_type) { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1654 | 1827 |
1655 // For session history navigations only the pending_entry_index_ is set. | 1828 // For session history navigations only the pending_entry_index_ is set. |
1656 if (!pending_entry_) { | 1829 if (!pending_entry_) { |
1657 DCHECK_NE(pending_entry_index_, -1); | 1830 DCHECK_NE(pending_entry_index_, -1); |
1658 pending_entry_ = entries_[pending_entry_index_].get(); | 1831 pending_entry_ = entries_[pending_entry_index_].get(); |
1659 } | 1832 } |
1660 | 1833 |
1661 // This call does not support re-entrancy. See http://crbug.com/347742. | 1834 // This call does not support re-entrancy. See http://crbug.com/347742. |
1662 CHECK(!in_navigate_to_pending_entry_); | 1835 CHECK(!in_navigate_to_pending_entry_); |
1663 in_navigate_to_pending_entry_ = true; | 1836 in_navigate_to_pending_entry_ = true; |
1664 bool success = delegate_->NavigateToPendingEntry(reload_type); | 1837 bool success = NavigateToPendingEntryInternal(reload_type); |
1665 in_navigate_to_pending_entry_ = false; | 1838 in_navigate_to_pending_entry_ = false; |
1666 | 1839 |
1667 if (!success) | 1840 if (!success) |
1668 DiscardNonCommittedEntries(); | 1841 DiscardNonCommittedEntries(); |
1669 | 1842 |
1670 // If the entry is being restored and doesn't have a SiteInstance yet, fill | 1843 // If the entry is being restored and doesn't have a SiteInstance yet, fill |
1671 // it in now that we know. This allows us to find the entry when it commits. | 1844 // it in now that we know. This allows us to find the entry when it commits. |
1672 if (pending_entry_ && !pending_entry_->site_instance() && | 1845 if (pending_entry_ && !pending_entry_->site_instance() && |
1673 pending_entry_->restore_type() != NavigationEntryImpl::RESTORE_NONE) { | 1846 pending_entry_->restore_type() != NavigationEntryImpl::RESTORE_NONE) { |
1674 pending_entry_->set_site_instance(static_cast<SiteInstanceImpl*>( | 1847 pending_entry_->set_site_instance(static_cast<SiteInstanceImpl*>( |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1733 } | 1906 } |
1734 | 1907 |
1735 void NavigationControllerImpl::FinishRestore(int selected_index, | 1908 void NavigationControllerImpl::FinishRestore(int selected_index, |
1736 RestoreType type) { | 1909 RestoreType type) { |
1737 DCHECK(selected_index >= 0 && selected_index < GetEntryCount()); | 1910 DCHECK(selected_index >= 0 && selected_index < GetEntryCount()); |
1738 ConfigureEntriesForRestore(&entries_, type); | 1911 ConfigureEntriesForRestore(&entries_, type); |
1739 | 1912 |
1740 SetMaxRestoredPageID(static_cast<int32>(GetEntryCount())); | 1913 SetMaxRestoredPageID(static_cast<int32>(GetEntryCount())); |
1741 | 1914 |
1742 last_committed_entry_index_ = selected_index; | 1915 last_committed_entry_index_ = selected_index; |
| 1916 // TODO(creis): Update last committed FNE. |
1743 } | 1917 } |
1744 | 1918 |
1745 void NavigationControllerImpl::DiscardNonCommittedEntriesInternal() { | 1919 void NavigationControllerImpl::DiscardNonCommittedEntriesInternal() { |
1746 DiscardPendingEntry(); | 1920 DiscardPendingEntry(); |
1747 DiscardTransientEntry(); | 1921 DiscardTransientEntry(); |
1748 } | 1922 } |
1749 | 1923 |
1750 void NavigationControllerImpl::DiscardPendingEntry() { | 1924 void NavigationControllerImpl::DiscardPendingEntry() { |
1751 // It is not safe to call DiscardPendingEntry while NavigateToEntry is in | 1925 // It is not safe to call DiscardPendingEntry while NavigateToEntry is in |
1752 // progress, since this will cause a use-after-free. (We only allow this | 1926 // progress, since this will cause a use-after-free. (We only allow this |
1753 // when the tab is being destroyed for shutdown, since it won't return to | 1927 // when the tab is being destroyed for shutdown, since it won't return to |
1754 // NavigateToEntry in that case.) http://crbug.com/347742. | 1928 // NavigateToEntry in that case.) http://crbug.com/347742. |
1755 CHECK(!in_navigate_to_pending_entry_ || delegate_->IsBeingDestroyed()); | 1929 CHECK(!in_navigate_to_pending_entry_ || delegate_->IsBeingDestroyed()); |
1756 | 1930 |
1757 if (pending_entry_index_ == -1) | 1931 if (pending_entry_index_ == -1) |
1758 delete pending_entry_; | 1932 delete pending_entry_; |
1759 pending_entry_ = NULL; | 1933 pending_entry_ = NULL; |
1760 pending_entry_index_ = -1; | 1934 pending_entry_index_ = -1; |
1761 } | 1935 } |
1762 | 1936 |
1763 void NavigationControllerImpl::DiscardTransientEntry() { | 1937 void NavigationControllerImpl::DiscardTransientEntry() { |
1764 if (transient_entry_index_ == -1) | 1938 if (transient_entry_index_ == -1) |
1765 return; | 1939 return; |
1766 entries_.erase(entries_.begin() + transient_entry_index_); | 1940 entries_.erase(entries_.begin() + transient_entry_index_); |
1767 if (last_committed_entry_index_ > transient_entry_index_) | 1941 if (last_committed_entry_index_ > transient_entry_index_) |
1768 last_committed_entry_index_--; | 1942 last_committed_entry_index_--; |
1769 transient_entry_index_ = -1; | 1943 transient_entry_index_ = -1; |
1770 } | 1944 } |
1771 | 1945 |
1772 int NavigationControllerImpl::GetEntryIndexWithPageID( | 1946 int NavigationControllerImpl::GetEntryIndexWithPageID(int32 page_id) const { |
1773 SiteInstance* instance, int32 page_id) const { | |
1774 for (int i = static_cast<int>(entries_.size()) - 1; i >= 0; --i) { | 1947 for (int i = static_cast<int>(entries_.size()) - 1; i >= 0; --i) { |
1775 if ((entries_[i]->site_instance() == instance) && | 1948 if (entries_[i]->GetPageID() == page_id) |
1776 (entries_[i]->GetPageID() == page_id)) | |
1777 return i; | 1949 return i; |
1778 } | 1950 } |
1779 return -1; | 1951 return -1; |
1780 } | 1952 } |
1781 | 1953 |
1782 NavigationEntryImpl* NavigationControllerImpl::GetTransientEntry() const { | 1954 NavigationEntryImpl* NavigationControllerImpl::GetTransientEntry() const { |
1783 if (transient_entry_index_ == -1) | 1955 if (transient_entry_index_ == -1) |
1784 return NULL; | 1956 return NULL; |
1785 return entries_[transient_entry_index_].get(); | 1957 return entries_[transient_entry_index_].get(); |
1786 } | 1958 } |
(...skipping 27 matching lines...) Expand all Loading... |
1814 source.entries_[i]->Clone())); | 1986 source.entries_[i]->Clone())); |
1815 } | 1987 } |
1816 } | 1988 } |
1817 } | 1989 } |
1818 | 1990 |
1819 void NavigationControllerImpl::SetGetTimestampCallbackForTest( | 1991 void NavigationControllerImpl::SetGetTimestampCallbackForTest( |
1820 const base::Callback<base::Time()>& get_timestamp_callback) { | 1992 const base::Callback<base::Time()>& get_timestamp_callback) { |
1821 get_timestamp_callback_ = get_timestamp_callback; | 1993 get_timestamp_callback_ = get_timestamp_callback; |
1822 } | 1994 } |
1823 | 1995 |
| 1996 bool NavigationControllerImpl::NavigateToPendingEntryInternal( |
| 1997 ReloadType reload_type) { |
| 1998 FrameLoadVector same_document_loads; |
| 1999 FrameLoadVector different_document_loads; |
| 2000 DCHECK(pending_entry_); |
| 2001 |
| 2002 FrameTreeNode* main_frame = delegate_->GetFrameTreeRoot(); |
| 2003 if (GetLastCommittedEntry()) { |
| 2004 RecursiveNavigateToPendingEntry( |
| 2005 main_frame, &same_document_loads, &different_document_loads); |
| 2006 } |
| 2007 |
| 2008 if (same_document_loads.empty() && different_document_loads.empty()) { |
| 2009 // If we don't have any frames to navigate at this point, either |
| 2010 // (1) there is no previous history entry to compare against, or |
| 2011 // (2) we were unable to match any frames by name. In the first case, |
| 2012 // doing a different document navigation to the root item is the only valid |
| 2013 // thing to do. In the second case, we should have been able to find a |
| 2014 // frame to navigate based on names if this were a same document |
| 2015 // navigation, so we can safely assume this is the different document case. |
| 2016 // TODO(creis): Is it safe to use a raw pointer for the FNE here? |
| 2017 different_document_loads.push_back( |
| 2018 std::make_pair(main_frame, |
| 2019 pending_entry_->root_node()->frame_entry.get())); |
| 2020 } |
| 2021 |
| 2022 // If all the frame loads fail, we will discard the pending entry. |
| 2023 bool success = false; |
| 2024 |
| 2025 // Send all the same document frame loads before the different document loads. |
| 2026 for (size_t i = 0; i < same_document_loads.size(); ++i) { |
| 2027 FrameTreeNode* frame = same_document_loads[i].first; |
| 2028 success |= frame->navigator()->NavigateToPendingEntry( |
| 2029 frame, *same_document_loads[i].second, reload_type); |
| 2030 } |
| 2031 for (size_t i = 0; i < different_document_loads.size(); ++i) { |
| 2032 FrameTreeNode* frame = different_document_loads[i].first; |
| 2033 success |= frame->navigator()->NavigateToPendingEntry( |
| 2034 frame, *different_document_loads[i].second, reload_type); |
| 2035 } |
| 2036 return success; |
| 2037 } |
| 2038 |
| 2039 void NavigationControllerImpl::RecursiveNavigateToPendingEntry( |
| 2040 FrameTreeNode* frame, |
| 2041 FrameLoadVector* same_document_loads, |
| 2042 FrameLoadVector* different_document_loads) { |
| 2043 DCHECK(pending_entry_); |
| 2044 DCHECK_GE(last_committed_entry_index_, 0); |
| 2045 FrameNavigationEntry* new_item = pending_entry_->GetFrameEntryForFrame(frame); |
| 2046 FrameNavigationEntry* old_item = |
| 2047 GetLastCommittedEntry()->GetFrameEntryForFrame(frame); |
| 2048 if (!new_item) |
| 2049 return; |
| 2050 |
| 2051 if (!old_item || |
| 2052 new_item->item_sequence_number() != old_item->item_sequence_number()) { |
| 2053 if (old_item && |
| 2054 new_item->document_sequence_number() == |
| 2055 old_item->document_sequence_number()) { |
| 2056 same_document_loads->push_back(std::make_pair(frame, new_item)); |
| 2057 } else { |
| 2058 different_document_loads->push_back(std::make_pair(frame, new_item)); |
| 2059 } |
| 2060 return; |
| 2061 } |
| 2062 |
| 2063 for (size_t i = 0; i < frame->child_count(); i++) { |
| 2064 RecursiveNavigateToPendingEntry(frame->child_at(i), same_document_loads, |
| 2065 different_document_loads); |
| 2066 } |
| 2067 } |
| 2068 |
1824 } // namespace content | 2069 } // namespace content |
OLD | NEW |