Chromium Code Reviews| 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/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
| 10 #include "base/time/time.h" | 10 #include "base/time/time.h" |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 144 render_frame_host->navigation_handle()->set_is_transferring(false); | 144 render_frame_host->navigation_handle()->set_is_transferring(false); |
| 145 return; | 145 return; |
| 146 } | 146 } |
| 147 | 147 |
| 148 // This ensures that notifications about the end of the previous | 148 // This ensures that notifications about the end of the previous |
| 149 // navigation are sent before notifications about the start of the | 149 // navigation are sent before notifications about the start of the |
| 150 // new navigation. | 150 // new navigation. |
| 151 render_frame_host->SetNavigationHandle(scoped_ptr<NavigationHandleImpl>()); | 151 render_frame_host->SetNavigationHandle(scoped_ptr<NavigationHandleImpl>()); |
| 152 } | 152 } |
| 153 | 153 |
| 154 NavigationEntry* pending_entry = controller_->GetPendingEntry(); | |
| 154 render_frame_host->SetNavigationHandle(NavigationHandleImpl::Create( | 155 render_frame_host->SetNavigationHandle(NavigationHandleImpl::Create( |
| 155 validated_url, render_frame_host->frame_tree_node(), | 156 validated_url, render_frame_host->frame_tree_node(), |
| 156 false, // is_synchronous | 157 false, // is_synchronous |
| 157 is_iframe_srcdoc, // is_srcdoc | 158 is_iframe_srcdoc, // is_srcdoc |
| 158 navigation_start)); | 159 navigation_start, pending_entry ? pending_entry->GetUniqueID() : 0)); |
|
clamy
2016/02/26 14:08:13
Can the pending entry ever be null here except in
Charlie Harrison
2016/02/26 17:39:51
It can be null for subframes. Good catch.
| |
| 159 } | 160 } |
| 160 | 161 |
| 161 void NavigatorImpl::DidFailProvisionalLoadWithError( | 162 void NavigatorImpl::DidFailProvisionalLoadWithError( |
| 162 RenderFrameHostImpl* render_frame_host, | 163 RenderFrameHostImpl* render_frame_host, |
| 163 const FrameHostMsg_DidFailProvisionalLoadWithError_Params& params) { | 164 const FrameHostMsg_DidFailProvisionalLoadWithError_Params& params) { |
| 164 VLOG(1) << "Failed Provisional Load: " << params.url.possibly_invalid_spec() | 165 VLOG(1) << "Failed Provisional Load: " << params.url.possibly_invalid_spec() |
| 165 << ", error_code: " << params.error_code | 166 << ", error_code: " << params.error_code |
| 166 << ", error_description: " << params.error_description | 167 << ", error_description: " << params.error_description |
| 167 << ", showing_repost_interstitial: " << | 168 << ", showing_repost_interstitial: " << |
| 168 params.showing_repost_interstitial | 169 params.showing_repost_interstitial |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 188 // commits of the interstitial page. | 189 // commits of the interstitial page. |
| 189 FrameTreeNode* root = | 190 FrameTreeNode* root = |
| 190 render_frame_host->frame_tree_node()->frame_tree()->root(); | 191 render_frame_host->frame_tree_node()->frame_tree()->root(); |
| 191 if (root->render_manager()->interstitial_page() != NULL) { | 192 if (root->render_manager()->interstitial_page() != NULL) { |
| 192 LOG(WARNING) << "Discarding message during interstitial."; | 193 LOG(WARNING) << "Discarding message during interstitial."; |
| 193 return; | 194 return; |
| 194 } | 195 } |
| 195 | 196 |
| 196 // We used to cancel the pending renderer here for cross-site downloads. | 197 // We used to cancel the pending renderer here for cross-site downloads. |
| 197 // However, it's not safe to do that because the download logic repeatedly | 198 // However, it's not safe to do that because the download logic repeatedly |
| 198 // looks for this WebContents based on a render ID. Instead, we just | 199 // looks for this WebContents based on a render ID. Instead, we just |
| 199 // leave the pending renderer around until the next navigation event | 200 // leave the pending renderer around until the next navigation event |
| 200 // (Navigate, DidNavigate, etc), which will clean it up properly. | 201 // (Navigate, DidNavigate, etc), which will clean it up properly. |
| 201 // | 202 // |
| 202 // TODO(creis): Find a way to cancel any pending RFH here. | 203 // TODO(creis): Find a way to cancel any pending RFH here. |
| 203 } | 204 } |
| 204 | 205 |
| 205 // We usually clear the pending entry when it fails, so that an arbitrary URL | 206 // Racy conditions can cause a fail message to arrive after its corresponding |
| 206 // isn't left visible above a committed page. This must be enforced when | 207 // pending entry has been replaced by another navigation. If |
| 207 // the pending entry isn't visible (e.g., renderer-initiated navigations) to | 208 // |DiscardPendingEntry| is called in this case, then the completely valid |
| 208 // prevent URL spoofs for in-page navigations that don't go through | 209 // entry for the new navigation would be discarded. See crbug.com/513742. To |
| 209 // DidStartProvisionalLoadForFrame. | 210 // catch this case, the current pending entry is compared against the current |
| 210 // | 211 // navigation handle's entry id, which should correspond to the failed load. |
| 211 // However, we do preserve the pending entry in some cases, such as on the | 212 NavigationHandleImpl* handle = render_frame_host->navigation_handle(); |
| 212 // initial navigation of an unmodified blank tab. We also allow the delegate | 213 NavigationEntry* pending_entry = controller_->GetPendingEntry(); |
| 213 // to say when it's safe to leave aborted URLs in the omnibox, to let the user | 214 bool pending_matches_fail_msg = |
| 214 // edit the URL and try again. This may be useful in cases that the committed | 215 handle && pending_entry && |
| 215 // page cannot be attacker-controlled. In these cases, we still allow the | 216 handle->pending_nav_entry_id() == pending_entry->GetUniqueID(); |
| 216 // view to clear the pending entry and typed URL if the user requests | 217 if (pending_matches_fail_msg) { |
| 217 // (e.g., hitting Escape with focus in the address bar). | 218 // We usually clear the pending entry when it fails, so that an arbitrary |
| 218 // | 219 // URL isn't left visible above a committed page. This must be enforced |
| 219 // Note: don't touch the transient entry, since an interstitial may exist. | 220 // when the pending entry isn't visible (e.g., renderer-initiated |
| 220 bool should_preserve_entry = controller_->IsUnmodifiedBlankTab() || | 221 // navigations) to prevent URL spoofs for in-page navigations that don't go |
| 221 delegate_->ShouldPreserveAbortedURLs(); | 222 // through DidStartProvisionalLoadForFrame. |
| 222 if (controller_->GetPendingEntry() != controller_->GetVisibleEntry() || | 223 // |
| 223 !should_preserve_entry) { | 224 // However, we do preserve the pending entry in some cases, such as on the |
| 224 controller_->DiscardPendingEntry(true); | 225 // initial navigation of an unmodified blank tab. We also allow the |
| 226 // delegate to say when it's safe to leave aborted URLs in the omnibox, to | |
| 227 // let the user edit the URL and try again. This may be useful in cases | |
| 228 // that the committed page cannot be attacker-controlled. In these cases, | |
| 229 // we still allow the view to clear the pending entry and typed URL if the | |
| 230 // user requests (e.g., hitting Escape with focus in the address bar). | |
| 231 // | |
| 232 // Note: don't touch the transient entry, since an interstitial may exist. | |
| 233 bool should_preserve_entry = controller_->IsUnmodifiedBlankTab() || | |
| 234 delegate_->ShouldPreserveAbortedURLs(); | |
| 235 if (pending_entry != controller_->GetVisibleEntry() || | |
| 236 !should_preserve_entry) { | |
| 237 controller_->DiscardPendingEntry(true); | |
| 225 | 238 |
| 226 // Also force the UI to refresh. | 239 // Also force the UI to refresh. |
| 227 controller_->delegate()->NotifyNavigationStateChanged(INVALIDATE_TYPE_URL); | 240 controller_->delegate()->NotifyNavigationStateChanged( |
| 241 INVALIDATE_TYPE_URL); | |
| 242 } | |
| 228 } | 243 } |
| 229 | 244 |
| 230 if (delegate_) | 245 if (delegate_) |
| 231 delegate_->DidFailProvisionalLoadWithError(render_frame_host, params); | 246 delegate_->DidFailProvisionalLoadWithError(render_frame_host, params); |
| 232 } | 247 } |
| 233 | 248 |
| 234 void NavigatorImpl::DidFailLoadWithError( | 249 void NavigatorImpl::DidFailLoadWithError( |
| 235 RenderFrameHostImpl* render_frame_host, | 250 RenderFrameHostImpl* render_frame_host, |
| 236 const GURL& url, | 251 const GURL& url, |
| 237 int error_code, | 252 int error_code, |
| (...skipping 554 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 792 } | 807 } |
| 793 | 808 |
| 794 // In all other cases the current navigation, if any, is canceled and a new | 809 // In all other cases the current navigation, if any, is canceled and a new |
| 795 // NavigationRequest is created for the node. | 810 // NavigationRequest is created for the node. |
| 796 frame_tree_node->CreatedNavigationRequest( | 811 frame_tree_node->CreatedNavigationRequest( |
| 797 NavigationRequest::CreateRendererInitiated( | 812 NavigationRequest::CreateRendererInitiated( |
| 798 frame_tree_node, common_params, begin_params, body, | 813 frame_tree_node, common_params, begin_params, body, |
| 799 controller_->GetLastCommittedEntryIndex(), | 814 controller_->GetLastCommittedEntryIndex(), |
| 800 controller_->GetEntryCount())); | 815 controller_->GetEntryCount())); |
| 801 NavigationRequest* navigation_request = frame_tree_node->navigation_request(); | 816 NavigationRequest* navigation_request = frame_tree_node->navigation_request(); |
| 802 navigation_request->CreateNavigationHandle(); | |
| 803 | |
| 804 if (frame_tree_node->IsMainFrame()) { | 817 if (frame_tree_node->IsMainFrame()) { |
| 805 // Renderer-initiated main-frame navigations that need to swap processes | 818 // Renderer-initiated main-frame navigations that need to swap processes |
| 806 // will go to the browser via a OpenURL call, and then be handled by the | 819 // will go to the browser via a OpenURL call, and then be handled by the |
| 807 // same code path as browser-initiated navigations. For renderer-initiated | 820 // same code path as browser-initiated navigations. For renderer-initiated |
| 808 // main frame navigation that start via a BeginNavigation IPC, the | 821 // main frame navigation that start via a BeginNavigation IPC, the |
| 809 // RenderFrameHost will not be swapped. Therefore it is safe to call | 822 // RenderFrameHost will not be swapped. Therefore it is safe to call |
| 810 // DidStartMainFrameNavigation with the SiteInstance from the current | 823 // DidStartMainFrameNavigation with the SiteInstance from the current |
| 811 // RenderFrameHost. | 824 // RenderFrameHost. |
| 812 DidStartMainFrameNavigation( | 825 DidStartMainFrameNavigation( |
| 813 common_params.url, | 826 common_params.url, |
| 814 frame_tree_node->current_frame_host()->GetSiteInstance()); | 827 frame_tree_node->current_frame_host()->GetSiteInstance()); |
| 815 navigation_data_.reset(); | 828 navigation_data_.reset(); |
| 816 } | 829 } |
| 817 | 830 |
| 831 // The NavigationHandle must be created after the call to | |
| 832 // |DidStartMainFrameNavigation|, so it receives the most up to date pending | |
| 833 // entry from the NavigationController. The pending entry is guaranteed to be | |
| 834 // non null at this point. | |
| 835 DCHECK(controller_->GetPendingEntry()); | |
|
clamy
2016/02/26 14:08:13
Is it always the case with subframes? Subframes wi
Charlie Harrison
2016/02/26 17:39:51
You've caught an error. I don't believe that subfr
| |
| 836 navigation_request->CreateNavigationHandle( | |
| 837 controller_->GetPendingEntry()->GetUniqueID()); | |
| 818 navigation_request->BeginNavigation(); | 838 navigation_request->BeginNavigation(); |
| 819 } | 839 } |
| 820 | 840 |
| 821 // PlzNavigate | 841 // PlzNavigate |
| 822 void NavigatorImpl::CommitNavigation(FrameTreeNode* frame_tree_node, | 842 void NavigatorImpl::CommitNavigation(FrameTreeNode* frame_tree_node, |
| 823 ResourceResponse* response, | 843 ResourceResponse* response, |
| 824 scoped_ptr<StreamHandle> body) { | 844 scoped_ptr<StreamHandle> body) { |
| 825 CHECK(IsBrowserSideNavigationEnabled()); | 845 CHECK(IsBrowserSideNavigationEnabled()); |
| 826 | 846 |
| 827 NavigationRequest* navigation_request = frame_tree_node->navigation_request(); | 847 NavigationRequest* navigation_request = frame_tree_node->navigation_request(); |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 961 bool should_dispatch_beforeunload = | 981 bool should_dispatch_beforeunload = |
| 962 frame_tree_node->current_frame_host()->ShouldDispatchBeforeUnload(); | 982 frame_tree_node->current_frame_host()->ShouldDispatchBeforeUnload(); |
| 963 FrameMsg_Navigate_Type::Value navigation_type = | 983 FrameMsg_Navigate_Type::Value navigation_type = |
| 964 GetNavigationType(controller_->GetBrowserContext(), entry, reload_type); | 984 GetNavigationType(controller_->GetBrowserContext(), entry, reload_type); |
| 965 frame_tree_node->CreatedNavigationRequest( | 985 frame_tree_node->CreatedNavigationRequest( |
| 966 NavigationRequest::CreateBrowserInitiated( | 986 NavigationRequest::CreateBrowserInitiated( |
| 967 frame_tree_node, dest_url, dest_referrer, frame_entry, entry, | 987 frame_tree_node, dest_url, dest_referrer, frame_entry, entry, |
| 968 navigation_type, lofi_state, is_same_document_history_load, | 988 navigation_type, lofi_state, is_same_document_history_load, |
| 969 navigation_start, controller_)); | 989 navigation_start, controller_)); |
| 970 NavigationRequest* navigation_request = frame_tree_node->navigation_request(); | 990 NavigationRequest* navigation_request = frame_tree_node->navigation_request(); |
| 971 navigation_request->CreateNavigationHandle(); | 991 navigation_request->CreateNavigationHandle(entry.GetUniqueID()); |
| 972 | 992 |
| 973 // Have the current renderer execute its beforeunload event if needed. If it | 993 // Have the current renderer execute its beforeunload event if needed. If it |
| 974 // is not needed (when beforeunload dispatch is not needed or this navigation | 994 // is not needed (when beforeunload dispatch is not needed or this navigation |
| 975 // is synchronous and same-site) then NavigationRequest::BeginNavigation | 995 // is synchronous and same-site) then NavigationRequest::BeginNavigation |
| 976 // should be directly called instead. | 996 // should be directly called instead. |
| 977 if (should_dispatch_beforeunload && | 997 if (should_dispatch_beforeunload && |
| 978 ShouldMakeNetworkRequestForURL( | 998 ShouldMakeNetworkRequestForURL( |
| 979 navigation_request->common_params().url)) { | 999 navigation_request->common_params().url)) { |
| 980 navigation_request->SetWaitingForRendererResponse(); | 1000 navigation_request->SetWaitingForRendererResponse(); |
| 981 frame_tree_node->current_frame_host()->DispatchBeforeUnload(true); | 1001 frame_tree_node->current_frame_host()->DispatchBeforeUnload(true); |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1065 entry->set_should_replace_entry(pending_entry->should_replace_entry()); | 1085 entry->set_should_replace_entry(pending_entry->should_replace_entry()); |
| 1066 entry->SetRedirectChain(pending_entry->GetRedirectChain()); | 1086 entry->SetRedirectChain(pending_entry->GetRedirectChain()); |
| 1067 } | 1087 } |
| 1068 controller_->SetPendingEntry(std::move(entry)); | 1088 controller_->SetPendingEntry(std::move(entry)); |
| 1069 if (delegate_) | 1089 if (delegate_) |
| 1070 delegate_->NotifyChangedNavigationState(content::INVALIDATE_TYPE_URL); | 1090 delegate_->NotifyChangedNavigationState(content::INVALIDATE_TYPE_URL); |
| 1071 } | 1091 } |
| 1072 } | 1092 } |
| 1073 | 1093 |
| 1074 } // namespace content | 1094 } // namespace content |
| OLD | NEW |