Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(767)

Side by Side Diff: content/browser/frame_host/render_frame_host_impl.cc

Issue 2475693002: Do not reset NavigationHandle when navigating same-page (Closed)
Patch Set: Rebase Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/render_frame_host_impl.h" 5 #include "content/browser/frame_host/render_frame_host_impl.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/command_line.h" 10 #include "base/command_line.h"
(...skipping 1171 matching lines...) Expand 10 before | Expand all | Expand 10 after
1182 process->FilterURL(true, &validated_params.searchable_form_url); 1182 process->FilterURL(true, &validated_params.searchable_form_url);
1183 1183
1184 // Without this check, the renderer can trick the browser into using 1184 // Without this check, the renderer can trick the browser into using
1185 // filenames it can't access in a future session restore. 1185 // filenames it can't access in a future session restore.
1186 if (!CanAccessFilesOfPageState(validated_params.page_state)) { 1186 if (!CanAccessFilesOfPageState(validated_params.page_state)) {
1187 bad_message::ReceivedBadMessage( 1187 bad_message::ReceivedBadMessage(
1188 GetProcess(), bad_message::RFH_CAN_ACCESS_FILES_OF_PAGE_STATE); 1188 GetProcess(), bad_message::RFH_CAN_ACCESS_FILES_OF_PAGE_STATE);
1189 return; 1189 return;
1190 } 1190 }
1191 1191
1192 // If the URL or |was_within_same_page| does not match what the 1192 // PlzNavigate
1193 // NavigationHandle expects, treat the commit as a new navigation. This can 1193 if (!navigation_handle_ && IsBrowserSideNavigationEnabled()) {
1194 // happen if an ongoing slow same-process navigation is interwoven with a 1194 // PlzNavigate: the browser has not been notified about the start of the
1195 // synchronous renderer-initiated navigation. 1195 // load in this renderer yet (e.g., for same-page navigations that start in
1196 // TODO(csharrison): Data navigations loaded with LoadDataWithBaseURL get 1196 // the renderer). Do it now.
1197 // reset here, because the NavigationHandle tracks the URL but the 1197 if (!is_loading()) {
1198 // validated_params.url tracks the data. The trick of saving the old entry ids 1198 bool was_loading = frame_tree_node()->frame_tree()->IsLoading();
1199 // for these navigations should go away when this is properly handled. See 1199 is_loading_ = true;
1200 // crbug.com/588317. 1200 frame_tree_node()->DidStartLoading(true, was_loading);
1201 int entry_id_for_data_nav = 0;
1202 bool is_renderer_initiated = true;
1203 if (navigation_handle_ &&
1204 ((navigation_handle_->GetURL() != validated_params.url) ||
1205 navigation_handle_->IsSamePage() !=
1206 validated_params.was_within_same_page)) {
1207 // Make sure that the pending entry was really loaded via
1208 // LoadDataWithBaseURL and that it matches this handle.
1209 NavigationEntryImpl* pending_entry =
1210 NavigationEntryImpl::FromNavigationEntry(
1211 frame_tree_node()->navigator()->GetController()->GetPendingEntry());
1212 bool pending_entry_matches_handle =
1213 pending_entry &&
1214 pending_entry->GetUniqueID() ==
1215 navigation_handle_->pending_nav_entry_id();
1216 // TODO(csharrison): The pending entry's base url should equal
1217 // |validated_params.base_url|. This is not the case for loads with invalid
1218 // base urls.
1219 if (navigation_handle_->GetURL() == validated_params.base_url &&
1220 pending_entry_matches_handle &&
1221 !pending_entry->GetBaseURLForDataURL().is_empty()) {
1222 entry_id_for_data_nav = navigation_handle_->pending_nav_entry_id();
1223 is_renderer_initiated = pending_entry->is_renderer_initiated();
1224 } 1201 }
1225 navigation_handle_.reset(); 1202 pending_commit_ = false;
1226 } 1203 }
1227 1204
1228 // Synchronous renderer-initiated navigations will send a 1205 // Find the appropriate NavigationHandle for this navigation.
1229 // DidCommitProvisionalLoad IPC without a prior DidStartProvisionalLoad 1206 std::unique_ptr<NavigationHandleImpl> navigation_handle =
1230 // message. Or in addition, the if block above can reset the NavigationHandle 1207 TakeNavigationHandleForCommit(validated_params);
1231 // in cases it doesn't match the expected commit. 1208 DCHECK(navigation_handle);
1232 if (!navigation_handle_) {
1233 // There is no pending NavigationEntry in these cases, so pass 0 as the
1234 // nav_id. If the previous handle was a prematurely aborted navigation
1235 // loaded via LoadDataWithBaseURL, propogate the entry id.
1236 navigation_handle_ = NavigationHandleImpl::Create(
1237 validated_params.url, frame_tree_node_, is_renderer_initiated,
1238 validated_params.was_within_same_page, validated_params.is_srcdoc,
1239 base::TimeTicks::Now(), entry_id_for_data_nav,
1240 false); // started_from_context_menu
1241 // PlzNavigate
1242 if (IsBrowserSideNavigationEnabled()) {
1243 // PlzNavigate: synchronous loads happen in the renderer, and the browser
1244 // has not been notified about the start of the load yet. Do it now.
1245 if (!is_loading()) {
1246 bool was_loading = frame_tree_node()->frame_tree()->IsLoading();
1247 is_loading_ = true;
1248 frame_tree_node()->DidStartLoading(true, was_loading);
1249 }
1250 pending_commit_ = false;
1251 }
1252 }
1253 1209
1254 accessibility_reset_count_ = 0; 1210 accessibility_reset_count_ = 0;
1255 frame_tree_node()->navigator()->DidNavigate(this, validated_params); 1211 frame_tree_node()->navigator()->DidNavigate(this, validated_params,
1212 std::move(navigation_handle));
1256 1213
1257 // Since we didn't early return, it's safe to keep the commit state. 1214 // Since we didn't early return, it's safe to keep the commit state.
1258 commit_state_resetter.disable(); 1215 commit_state_resetter.disable();
1259 1216
1260 // For a top-level frame, there are potential security concerns associated 1217 // For a top-level frame, there are potential security concerns associated
1261 // with displaying graphics from a previously loaded page after the URL in 1218 // with displaying graphics from a previously loaded page after the URL in
1262 // the omnibar has been changed. It is unappealing to clear the page 1219 // the omnibar has been changed. It is unappealing to clear the page
1263 // immediately, but if the renderer is taking a long time to issue any 1220 // immediately, but if the renderer is taking a long time to issue any
1264 // compositor output (possibly because of script deliberately creating this 1221 // compositor output (possibly because of script deliberately creating this
1265 // situation) then we clear it after a while anyway. 1222 // situation) then we clear it after a while anyway.
(...skipping 1912 matching lines...) Expand 10 before | Expand all | Expand 10 after
3178 // handler after it's destroyed so it can't run after the RFHI is destroyed. 3135 // handler after it's destroyed so it can't run after the RFHI is destroyed.
3179 web_bluetooth_service_->SetClientConnectionErrorHandler(base::Bind( 3136 web_bluetooth_service_->SetClientConnectionErrorHandler(base::Bind(
3180 &RenderFrameHostImpl::DeleteWebBluetoothService, base::Unretained(this))); 3137 &RenderFrameHostImpl::DeleteWebBluetoothService, base::Unretained(this)));
3181 return web_bluetooth_service_.get(); 3138 return web_bluetooth_service_.get();
3182 } 3139 }
3183 3140
3184 void RenderFrameHostImpl::DeleteWebBluetoothService() { 3141 void RenderFrameHostImpl::DeleteWebBluetoothService() {
3185 web_bluetooth_service_.reset(); 3142 web_bluetooth_service_.reset();
3186 } 3143 }
3187 3144
3145 std::unique_ptr<NavigationHandleImpl>
3146 RenderFrameHostImpl::TakeNavigationHandleForCommit(
3147 const FrameHostMsg_DidCommitProvisionalLoad_Params& params) {
3148 // If this is a same-page navigation, there isn't an existing NavigationHandle
3149 // to use for the navigation. Create one, but don't reset any NavigationHandle
3150 // tracking an ongoing navigation, since this may lead to the cancellation of
3151 // the navigation.
3152 if (params.was_within_same_page) {
3153 // First, determine if the navigation corresponds to the pending navigation
3154 // entry. This is the case for a browser-initiated same-page navigation.
Charlie Reis 2016/11/04 17:30:53 nit: Please add: ", which does not cause a Navigat
clamy 2016/11/07 14:10:51 Done.
3155 bool is_renderer_initiated = true;
3156 int pending_nav_entry_id = 0;
3157 NavigationEntryImpl* pending_entry =
3158 NavigationEntryImpl::FromNavigationEntry(
3159 frame_tree_node()->navigator()->GetController()->GetPendingEntry());
3160 if (pending_entry && pending_entry->GetUniqueID() == params.nav_entry_id) {
3161 pending_nav_entry_id = params.nav_entry_id;
3162 is_renderer_initiated = pending_entry->is_renderer_initiated();
3163 }
3164
3165 return NavigationHandleImpl::Create(
Charlie Reis 2016/11/04 17:30:53 I agree with your reasoning about this case, but i
clamy 2016/11/07 14:10:51 Done. I didn't add the url check because of the Pu
3166 params.url, frame_tree_node_, is_renderer_initiated,
3167 params.was_within_same_page, params.is_srcdoc, base::TimeTicks::Now(),
3168 pending_nav_entry_id, false); // started_from_context_menu
3169 }
3170
3171 // Determine if the current NavigationHandle can be used.
3172 if (navigation_handle_ && navigation_handle_->GetURL() == params.url) {
3173 return std::move(navigation_handle_);
3174 }
3175
3176 // If the URL does not match what the NavigationHandle expects, treat the
3177 // commit as a new navigation. This can happen when loading a Data
3178 // navigation with LoadDataWithBaseURL.
3179 //
3180 // TODO(csharrison): Data navigations loaded with LoadDataWithBaseURL get
3181 // reset here, because the NavigationHandle tracks the URL but the params.url
3182 // tracks the data. The trick of saving the old entry ids for these
3183 // navigations should go away when this is properly handled.
3184 // See crbug.com/588317.
3185 int entry_id_for_data_nav = 0;
3186 bool is_renderer_initiated = true;
3187
3188 // Make sure that the pending entry was really loaded via LoadDataWithBaseURL
3189 // and that it matches this handle. TODO(csharrison): The pending entry's
3190 // base url should equal |params.base_url|. This is not the case for loads
3191 // with invalid base urls.
3192 if (navigation_handle_) {
3193 NavigationEntryImpl* pending_entry =
3194 NavigationEntryImpl::FromNavigationEntry(
3195 frame_tree_node()->navigator()->GetController()->GetPendingEntry());
3196 bool pending_entry_matches_handle =
3197 pending_entry &&
3198 pending_entry->GetUniqueID() ==
3199 navigation_handle_->pending_nav_entry_id();
3200 // TODO(csharrison): The pending entry's base url should equal
3201 // |validated_params.base_url|. This is not the case for loads with invalid
3202 // base urls.
3203 if (navigation_handle_->GetURL() == params.base_url &&
3204 pending_entry_matches_handle &&
3205 !pending_entry->GetBaseURLForDataURL().is_empty()) {
3206 entry_id_for_data_nav = navigation_handle_->pending_nav_entry_id();
3207 is_renderer_initiated = pending_entry->is_renderer_initiated();
3208 }
3209
3210 // Reset any existing NavigationHandle.
3211 navigation_handle_.reset();
3212 }
3213
3214 // There is no pending NavigationEntry in these cases, so pass 0 as the
3215 // pending_nav_entry_id. If the previous handle was a prematurely aborted
3216 // navigation loaded via LoadDataWithBaseURL, propagate the entry id.
3217 return NavigationHandleImpl::Create(
3218 params.url, frame_tree_node_, is_renderer_initiated,
3219 params.was_within_same_page, params.is_srcdoc, base::TimeTicks::Now(),
3220 entry_id_for_data_nav, false); // started_from_context_menu
3221 }
3222
3188 } // namespace content 3223 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698