| 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/navigator_impl.h" | 5 #include "content/browser/frame_host/navigator_impl.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/metrics/histogram_macros.h" | 10 #include "base/metrics/histogram_macros.h" |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 273 // We used to cancel the pending renderer here for cross-site downloads. | 273 // We used to cancel the pending renderer here for cross-site downloads. |
| 274 // However, it's not safe to do that because the download logic repeatedly | 274 // However, it's not safe to do that because the download logic repeatedly |
| 275 // looks for this WebContents based on a render ID. Instead, we just | 275 // looks for this WebContents based on a render ID. Instead, we just |
| 276 // leave the pending renderer around until the next navigation event | 276 // leave the pending renderer around until the next navigation event |
| 277 // (Navigate, DidNavigate, etc), which will clean it up properly. | 277 // (Navigate, DidNavigate, etc), which will clean it up properly. |
| 278 // | 278 // |
| 279 // TODO(creis): Find a way to cancel any pending RFH here. | 279 // TODO(creis): Find a way to cancel any pending RFH here. |
| 280 } | 280 } |
| 281 | 281 |
| 282 // Discard the pending navigation entry if needed. | 282 // Discard the pending navigation entry if needed. |
| 283 DiscardPendingEntryIfNeeded(render_frame_host->navigation_handle()); | 283 int expected_pending_entry_id = |
| 284 render_frame_host->navigation_handle() |
| 285 ? render_frame_host->navigation_handle()->pending_nav_entry_id() |
| 286 : 0; |
| 287 DiscardPendingEntryIfNeeded(expected_pending_entry_id); |
| 284 } | 288 } |
| 285 | 289 |
| 286 void NavigatorImpl::DidFailLoadWithError( | 290 void NavigatorImpl::DidFailLoadWithError( |
| 287 RenderFrameHostImpl* render_frame_host, | 291 RenderFrameHostImpl* render_frame_host, |
| 288 const GURL& url, | 292 const GURL& url, |
| 289 int error_code, | 293 int error_code, |
| 290 const base::string16& error_description, | 294 const base::string16& error_description, |
| 291 bool was_ignored_by_handler) { | 295 bool was_ignored_by_handler) { |
| 292 if (delegate_) { | 296 if (delegate_) { |
| 293 delegate_->DidFailLoadWithError( | 297 delegate_->DidFailLoadWithError( |
| (...skipping 635 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 929 node->unique_name(), -1, -1, nullptr, | 933 node->unique_name(), -1, -1, nullptr, |
| 930 static_cast<SiteInstanceImpl*>(source_site_instance), dest_url, | 934 static_cast<SiteInstanceImpl*>(source_site_instance), dest_url, |
| 931 referrer_to_use, method, -1); | 935 referrer_to_use, method, -1); |
| 932 } | 936 } |
| 933 NavigateToEntry(node, *frame_entry, *entry.get(), ReloadType::NONE, false, | 937 NavigateToEntry(node, *frame_entry, *entry.get(), ReloadType::NONE, false, |
| 934 false, false, post_body); | 938 false, false, post_body); |
| 935 } | 939 } |
| 936 | 940 |
| 937 // PlzNavigate | 941 // PlzNavigate |
| 938 void NavigatorImpl::OnBeforeUnloadACK(FrameTreeNode* frame_tree_node, | 942 void NavigatorImpl::OnBeforeUnloadACK(FrameTreeNode* frame_tree_node, |
| 939 bool proceed) { | 943 bool proceed, |
| 944 const base::TimeTicks& proceed_time) { |
| 940 CHECK(IsBrowserSideNavigationEnabled()); | 945 CHECK(IsBrowserSideNavigationEnabled()); |
| 941 DCHECK(frame_tree_node); | 946 DCHECK(frame_tree_node); |
| 942 | 947 |
| 943 NavigationRequest* navigation_request = frame_tree_node->navigation_request(); | 948 NavigationRequest* navigation_request = frame_tree_node->navigation_request(); |
| 944 | 949 |
| 945 // The NavigationRequest may have been canceled while the renderer was | 950 // The NavigationRequest may have been canceled while the renderer was |
| 946 // executing the BeforeUnload event. | 951 // executing the BeforeUnload event. |
| 947 if (!navigation_request) | 952 if (!navigation_request) |
| 948 return; | 953 return; |
| 949 | 954 |
| 955 // Update the navigation start: it should be when it was determined that the |
| 956 // navigation will proceed. |
| 957 navigation_request->set_navigation_start_time(proceed_time); |
| 958 |
| 950 DCHECK_EQ(NavigationRequest::WAITING_FOR_RENDERER_RESPONSE, | 959 DCHECK_EQ(NavigationRequest::WAITING_FOR_RENDERER_RESPONSE, |
| 951 navigation_request->state()); | 960 navigation_request->state()); |
| 952 | 961 |
| 953 // If the navigation is allowed to proceed, send the request to the IO thread. | 962 // If the navigation is allowed to proceed, send the request to the IO thread. |
| 954 if (proceed) | 963 if (proceed) |
| 955 navigation_request->BeginNavigation(); | 964 navigation_request->BeginNavigation(); |
| 956 else | 965 else |
| 957 CancelNavigation(frame_tree_node, true); | 966 CancelNavigation(frame_tree_node, true); |
| 958 } | 967 } |
| 959 | 968 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 991 !begin_params.has_user_gesture) { | 1000 !begin_params.has_user_gesture) { |
| 992 RenderFrameHost* current_frame_host = | 1001 RenderFrameHost* current_frame_host = |
| 993 frame_tree_node->render_manager()->current_frame_host(); | 1002 frame_tree_node->render_manager()->current_frame_host(); |
| 994 current_frame_host->Send( | 1003 current_frame_host->Send( |
| 995 new FrameMsg_Stop(current_frame_host->GetRoutingID())); | 1004 new FrameMsg_Stop(current_frame_host->GetRoutingID())); |
| 996 return; | 1005 return; |
| 997 } | 1006 } |
| 998 | 1007 |
| 999 // In all other cases the current navigation, if any, is canceled and a new | 1008 // In all other cases the current navigation, if any, is canceled and a new |
| 1000 // NavigationRequest is created for the node. | 1009 // NavigationRequest is created for the node. |
| 1001 frame_tree_node->CreatedNavigationRequest( | |
| 1002 NavigationRequest::CreateRendererInitiated( | |
| 1003 frame_tree_node, common_params, begin_params, | |
| 1004 controller_->GetLastCommittedEntryIndex(), | |
| 1005 controller_->GetEntryCount())); | |
| 1006 NavigationRequest* navigation_request = frame_tree_node->navigation_request(); | |
| 1007 if (frame_tree_node->IsMainFrame()) { | 1010 if (frame_tree_node->IsMainFrame()) { |
| 1008 // Renderer-initiated main-frame navigations that need to swap processes | 1011 // Renderer-initiated main-frame navigations that need to swap processes |
| 1009 // will go to the browser via a OpenURL call, and then be handled by the | 1012 // will go to the browser via a OpenURL call, and then be handled by the |
| 1010 // same code path as browser-initiated navigations. For renderer-initiated | 1013 // same code path as browser-initiated navigations. For renderer-initiated |
| 1011 // main frame navigation that start via a BeginNavigation IPC, the | 1014 // main frame navigation that start via a BeginNavigation IPC, the |
| 1012 // RenderFrameHost will not be swapped. Therefore it is safe to call | 1015 // RenderFrameHost will not be swapped. Therefore it is safe to call |
| 1013 // DidStartMainFrameNavigation with the SiteInstance from the current | 1016 // DidStartMainFrameNavigation with the SiteInstance from the current |
| 1014 // RenderFrameHost. | 1017 // RenderFrameHost. |
| 1015 DidStartMainFrameNavigation( | 1018 DidStartMainFrameNavigation( |
| 1016 common_params.url, | 1019 common_params.url, |
| 1017 frame_tree_node->current_frame_host()->GetSiteInstance(), nullptr); | 1020 frame_tree_node->current_frame_host()->GetSiteInstance(), nullptr); |
| 1018 navigation_data_.reset(); | 1021 navigation_data_.reset(); |
| 1019 } | 1022 } |
| 1023 NavigationEntryImpl* pending_entry = controller_->GetPendingEntry(); |
| 1024 frame_tree_node->CreatedNavigationRequest( |
| 1025 NavigationRequest::CreateRendererInitiated( |
| 1026 frame_tree_node, pending_entry, common_params, begin_params, |
| 1027 controller_->GetLastCommittedEntryIndex(), |
| 1028 controller_->GetEntryCount())); |
| 1029 NavigationRequest* navigation_request = frame_tree_node->navigation_request(); |
| 1020 | 1030 |
| 1021 // For main frames, NavigationHandle will be created after the call to | 1031 // For main frames, NavigationHandle will be created after the call to |
| 1022 // |DidStartMainFrameNavigation|, so it receives the most up to date pending | 1032 // |DidStartMainFrameNavigation|, so it receives the most up to date pending |
| 1023 // entry from the NavigationController. | 1033 // entry from the NavigationController. |
| 1024 NavigationEntry* pending_entry = controller_->GetPendingEntry(); | |
| 1025 navigation_request->CreateNavigationHandle( | |
| 1026 pending_entry ? pending_entry->GetUniqueID() : 0); | |
| 1027 navigation_request->BeginNavigation(); | 1034 navigation_request->BeginNavigation(); |
| 1028 } | 1035 } |
| 1029 | 1036 |
| 1030 void NavigatorImpl::OnAbortNavigation(FrameTreeNode* frame_tree_node) { | 1037 void NavigatorImpl::OnAbortNavigation(FrameTreeNode* frame_tree_node) { |
| 1031 NavigationRequest* ongoing_navigation_request = | 1038 NavigationRequest* ongoing_navigation_request = |
| 1032 frame_tree_node->navigation_request(); | 1039 frame_tree_node->navigation_request(); |
| 1033 if (!ongoing_navigation_request || | 1040 if (!ongoing_navigation_request || |
| 1034 ongoing_navigation_request->browser_initiated()) { | 1041 ongoing_navigation_request->browser_initiated()) { |
| 1035 return; | 1042 return; |
| 1036 } | 1043 } |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1069 const base::TimeTicks& renderer_before_unload_end_time) { | 1076 const base::TimeTicks& renderer_before_unload_end_time) { |
| 1070 // Only stores the beforeunload delay if we're tracking a browser initiated | 1077 // Only stores the beforeunload delay if we're tracking a browser initiated |
| 1071 // navigation and it happened later than the navigation request. | 1078 // navigation and it happened later than the navigation request. |
| 1072 if (navigation_data_ && | 1079 if (navigation_data_ && |
| 1073 renderer_before_unload_start_time > navigation_data_->start_time_) { | 1080 renderer_before_unload_start_time > navigation_data_->start_time_) { |
| 1074 navigation_data_->before_unload_delay_ = | 1081 navigation_data_->before_unload_delay_ = |
| 1075 renderer_before_unload_end_time - renderer_before_unload_start_time; | 1082 renderer_before_unload_end_time - renderer_before_unload_start_time; |
| 1076 } | 1083 } |
| 1077 } | 1084 } |
| 1078 | 1085 |
| 1079 void NavigatorImpl::DiscardPendingEntryIfNeeded(NavigationHandleImpl* handle) { | 1086 void NavigatorImpl::DiscardPendingEntryIfNeeded(int expected_pending_entry_id) { |
| 1080 // Racy conditions can cause a fail message to arrive after its corresponding | 1087 // Racy conditions can cause a fail message to arrive after its corresponding |
| 1081 // pending entry has been replaced by another navigation. If | 1088 // pending entry has been replaced by another navigation. If |
| 1082 // |DiscardPendingEntry| is called in this case, then the completely valid | 1089 // |DiscardPendingEntry| is called in this case, then the completely valid |
| 1083 // entry for the new navigation would be discarded. See crbug.com/513742. To | 1090 // entry for the new navigation would be discarded. See crbug.com/513742. To |
| 1084 // catch this case, the current pending entry is compared against the current | 1091 // catch this case, the current pending entry is compared against the current |
| 1085 // navigation handle's entry id, which should correspond to the failed load. | 1092 // navigation handle's entry id, which should correspond to the failed load. |
| 1086 NavigationEntry* pending_entry = controller_->GetPendingEntry(); | 1093 NavigationEntry* pending_entry = controller_->GetPendingEntry(); |
| 1087 bool pending_matches_fail_msg = | 1094 bool pending_matches_fail_msg = |
| 1088 handle && pending_entry && | 1095 pending_entry && |
| 1089 handle->pending_nav_entry_id() == pending_entry->GetUniqueID(); | 1096 expected_pending_entry_id == pending_entry->GetUniqueID(); |
| 1090 if (!pending_matches_fail_msg) | 1097 if (!pending_matches_fail_msg) |
| 1091 return; | 1098 return; |
| 1092 | 1099 |
| 1093 // We usually clear the pending entry when it fails, so that an arbitrary URL | 1100 // We usually clear the pending entry when it fails, so that an arbitrary URL |
| 1094 // isn't left visible above a committed page. This must be enforced when the | 1101 // isn't left visible above a committed page. This must be enforced when the |
| 1095 // pending entry isn't visible (e.g., renderer-initiated navigations) to | 1102 // pending entry isn't visible (e.g., renderer-initiated navigations) to |
| 1096 // prevent URL spoofs for same-document navigations that don't go through | 1103 // prevent URL spoofs for same-document navigations that don't go through |
| 1097 // DidStartProvisionalLoadForFrame. | 1104 // DidStartProvisionalLoadForFrame. |
| 1098 // | 1105 // |
| 1099 // However, we do preserve the pending entry in some cases, such as on the | 1106 // However, we do preserve the pending entry in some cases, such as on the |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1167 render_frame_host->CommitNavigation( | 1174 render_frame_host->CommitNavigation( |
| 1168 nullptr, // response | 1175 nullptr, // response |
| 1169 nullptr, // body | 1176 nullptr, // body |
| 1170 mojo::ScopedDataPipeConsumerHandle(), scoped_request->common_params(), | 1177 mojo::ScopedDataPipeConsumerHandle(), scoped_request->common_params(), |
| 1171 scoped_request->request_params(), scoped_request->is_view_source()); | 1178 scoped_request->request_params(), scoped_request->is_view_source()); |
| 1172 return; | 1179 return; |
| 1173 } | 1180 } |
| 1174 | 1181 |
| 1175 frame_tree_node->CreatedNavigationRequest(std::move(scoped_request)); | 1182 frame_tree_node->CreatedNavigationRequest(std::move(scoped_request)); |
| 1176 | 1183 |
| 1177 frame_tree_node->navigation_request()->CreateNavigationHandle( | |
| 1178 entry.GetUniqueID()); | |
| 1179 | |
| 1180 NavigationRequest* navigation_request = frame_tree_node->navigation_request(); | 1184 NavigationRequest* navigation_request = frame_tree_node->navigation_request(); |
| 1181 if (!navigation_request) | 1185 if (!navigation_request) |
| 1182 return; // Navigation was synchronously stopped. | 1186 return; // Navigation was synchronously stopped. |
| 1183 | 1187 |
| 1184 navigation_request->navigation_handle()->set_base_url_for_data_url( | |
| 1185 entry.GetBaseURLForDataURL()); | |
| 1186 | |
| 1187 // Have the current renderer execute its beforeunload event if needed. If it | 1188 // Have the current renderer execute its beforeunload event if needed. If it |
| 1188 // is not needed then NavigationRequest::BeginNavigation should be directly | 1189 // is not needed then NavigationRequest::BeginNavigation should be directly |
| 1189 // called instead. | 1190 // called instead. |
| 1190 if (should_dispatch_beforeunload && !IsRendererDebugURL(dest_url)) { | 1191 if (should_dispatch_beforeunload && !IsRendererDebugURL(dest_url)) { |
| 1191 navigation_request->SetWaitingForRendererResponse(); | 1192 navigation_request->SetWaitingForRendererResponse(); |
| 1192 frame_tree_node->current_frame_host()->DispatchBeforeUnload( | 1193 frame_tree_node->current_frame_host()->DispatchBeforeUnload( |
| 1193 true, reload_type != ReloadType::NONE); | 1194 true, reload_type != ReloadType::NONE); |
| 1194 } else { | 1195 } else { |
| 1195 navigation_request->BeginNavigation(); | 1196 navigation_request->BeginNavigation(); |
| 1196 } | 1197 } |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1297 if (navigation_handle) | 1298 if (navigation_handle) |
| 1298 navigation_handle->update_entry_id_for_transfer(entry->GetUniqueID()); | 1299 navigation_handle->update_entry_id_for_transfer(entry->GetUniqueID()); |
| 1299 | 1300 |
| 1300 controller_->SetPendingEntry(std::move(entry)); | 1301 controller_->SetPendingEntry(std::move(entry)); |
| 1301 if (delegate_) | 1302 if (delegate_) |
| 1302 delegate_->NotifyChangedNavigationState(content::INVALIDATE_TYPE_URL); | 1303 delegate_->NotifyChangedNavigationState(content::INVALIDATE_TYPE_URL); |
| 1303 } | 1304 } |
| 1304 } | 1305 } |
| 1305 | 1306 |
| 1306 } // namespace content | 1307 } // namespace content |
| OLD | NEW |