| Index: content/renderer/render_frame_impl.cc
|
| diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
|
| index 5007f28f5c19f40d05bae2cdb26a00a3940ca5de..6579a3e86b128597283d52d154f0eddb413ee837 100644
|
| --- a/content/renderer/render_frame_impl.cc
|
| +++ b/content/renderer/render_frame_impl.cc
|
| @@ -3244,10 +3244,31 @@ void RenderFrameImpl::loadURLExternally(const blink::WebURLRequest& request,
|
| }
|
|
|
| blink::WebHistoryItem RenderFrameImpl::historyItemForNewChildFrame() {
|
| - // OOPIF enabled modes will punt this navigation to the browser in
|
| - // decidePolicyForNavigation.
|
| - if (SiteIsolationPolicy::UseSubframeNavigationEntries())
|
| + if (SiteIsolationPolicy::UseSubframeNavigationEntries()) {
|
| + // Check whether the browser process provided a history item to use for this
|
| + // new frame. If not, return an empty WebHistoryItem and check with the
|
| + // browser process in decidePolicyForNavigation.
|
| + const std::string& unique_name = frame_->uniqueName().utf8();
|
| + const auto& iter = render_view_->history_page_states_.find(unique_name);
|
| + if (iter != render_view_->history_page_states_.end()) {
|
| + const PageState& page_state = iter->second;
|
| + // If the PageState is non-empty, use it as the history item to load. If
|
| + // it is empty, it represents a cross-process history item. We'll ask the
|
| + // browser process to handle it in decidePolicyForNavigation.
|
| + if (page_state.IsValid()) {
|
| + std::unique_ptr<HistoryEntry> entry =
|
| + PageStateToHistoryEntry(page_state);
|
| +
|
| + // Erase the entry now that we've used it (unlike the empty PageState
|
| + // case).
|
| + render_view_->history_page_states_.erase(unique_name);
|
| +
|
| + return entry->root();
|
| + }
|
| + }
|
| +
|
| return WebHistoryItem();
|
| + }
|
|
|
| return render_view_->history_controller()->GetItemForNewChildFrame(this);
|
| }
|
| @@ -4983,11 +5004,6 @@ void RenderFrameImpl::didStopLoading() {
|
| TRACE_EVENT1("navigation,rail", "RenderFrameImpl::didStopLoading",
|
| "id", routing_id_);
|
|
|
| - // Any subframes created after this point won't be considered part of the
|
| - // current history navigation (if this was one), so we don't need to track
|
| - // this state anymore.
|
| - history_subframe_unique_names_.clear();
|
| -
|
| render_view_->FrameDidStopLoading(frame_);
|
| Send(new FrameHostMsg_DidStopLoading(routing_id_));
|
| }
|
| @@ -5154,27 +5170,34 @@ WebNavigationPolicy RenderFrameImpl::decidePolicyForNavigation(
|
| return blink::WebNavigationPolicyIgnore; // Suppress the load here.
|
| }
|
|
|
| - // In OOPIF-enabled modes, back/forward navigations in newly created subframes
|
| - // should be sent to the browser if there is a matching FrameNavigationEntry,
|
| - // and if it isn't just staying at about:blank. If this frame isn't in the
|
| - // map of unique names that have history items, or if it's staying at the
|
| - // initial about:blank URL, fall back to loading the default url. (We remove
|
| - // each name as we encounter it, because it will only be used once as the
|
| - // frame is created.)
|
| + // Back/forward navigations in newly created subframes should be sent to the
|
| + // browser process if there is a matching unique name in the PageState map but
|
| + // the PageState is empty. This is a signal that the browser process has a
|
| + // FrameNavigationEntry for it but that it will load in a different process.
|
| + // We remove each name as we encounter it, because it will only be used once
|
| + // as the frame is created.
|
| + //
|
| + // If this frame isn't in the map (or has already been removed during
|
| + // historyItemForNewChildFrame), allow the navigation to continue. For frames
|
| + // that were never in the map, this effectively falls back to loading the
|
| + // default URL for the frame.
|
| if (SiteIsolationPolicy::UseSubframeNavigationEntries() &&
|
| info.isHistoryNavigationInNewChildFrame && is_content_initiated &&
|
| frame_->parent()) {
|
| - // Check whether the browser has a history item for this frame that isn't
|
| - // just staying at the initial about:blank document.
|
| + // Check whether the browser process sent an empty PageState for this frame,
|
| + // indicating that it should load in a different process.
|
| bool should_ask_browser = false;
|
| - RenderFrameImpl* parent = RenderFrameImpl::FromWebFrame(frame_->parent());
|
| - const auto& iter = parent->history_subframe_unique_names_.find(
|
| - frame_->uniqueName().utf8());
|
| - if (iter != parent->history_subframe_unique_names_.end()) {
|
| - bool history_item_is_about_blank = iter->second;
|
| - should_ask_browser =
|
| - !history_item_is_about_blank || url != url::kAboutBlankURL;
|
| - parent->history_subframe_unique_names_.erase(frame_->uniqueName().utf8());
|
| + const std::string& unique_name = frame_->uniqueName().utf8();
|
| + const auto& iter = render_view_->history_page_states_.find(unique_name);
|
| + if (iter != render_view_->history_page_states_.end()) {
|
| + const PageState& page_state = iter->second;
|
| +
|
| + // If the PageState were valid, we should have used and removed it in
|
| + // historyItemForNewChildFrame.
|
| + DCHECK(!page_state.IsValid());
|
| +
|
| + should_ask_browser = !page_state.IsValid();
|
| + render_view_->history_page_states_.erase(unique_name);
|
| }
|
|
|
| if (should_ask_browser) {
|
| @@ -5827,8 +5850,10 @@ void RenderFrameImpl::NavigateInternal(
|
| should_load_request = true;
|
|
|
| // Keep track of which subframes the browser process has history items
|
| - // for during a history navigation.
|
| - history_subframe_unique_names_ = request_params.subframe_unique_names;
|
| + // for during a history navigation (in addition to any existing ones,
|
| + // overwriting any stale entries).
|
| + for (const auto& iter : request_params.subtree_page_states)
|
| + render_view_->history_page_states_[iter.first] = iter.second;
|
|
|
| if (history_load_type == blink::WebHistorySameDocumentLoad) {
|
| // If this is marked as a same document load but we haven't committed
|
|
|