Index: content/renderer/history_controller.cc |
diff --git a/content/renderer/history_controller.cc b/content/renderer/history_controller.cc |
index 8f1bc3462f72bd98e69822ffddff0db57b4e1350..5f0f28b4f6da89f25393c62075aa1db914f1b331 100644 |
--- a/content/renderer/history_controller.cc |
+++ b/content/renderer/history_controller.cc |
@@ -196,8 +196,29 @@ void HistoryController::UpdateForCommit(RenderFrameImpl* frame, |
bool navigation_within_page) { |
switch (commit_type) { |
case blink::WebBackForwardCommit: |
- if (!provisional_entry_) |
+ if (!provisional_entry_) { |
+ // The provisional entry may have been discarded due to a navigation in |
+ // a different frame. For main frames, it is not safe to leave the |
+ // current_entry_ in place, which may have a cross-site page and will be |
+ // included in the PageState for this commit. Replace it with a new |
+ // HistoryEntry corresponding to the commit. |
+ // |
+ // This will lack any subframe history items that were in the original |
+ // provisional entry, but we don't know what those were after discarding |
+ // it. We'll load the default URL in those subframes instead. |
+ // |
+ // TODO(creis): It's also possible to get here for subframe commits. |
+ // We'll leave a stale current_entry_ in that case, but that only causes |
+ // an earlier URL to load in the subframe when leaving and coming back, |
+ // and only in rare cases. It does not risk a URL spoof, unlike the |
+ // main frame case. Since this bug is not present in the new |
+ // FrameNavigationEntry-based navigation path (https://crbug.com/236848) |
+ // we'll wait for that to fix the subframe case. |
+ if (frame->IsMainFrame()) |
+ current_entry_.reset(new HistoryEntry(item)); |
+ |
return; |
+ } |
// If the current entry is null, this must be a main frame commit. |
DCHECK(current_entry_ || frame->IsMainFrame()); |