Index: content/browser/frame_host/navigation_entry_impl.cc |
diff --git a/content/browser/frame_host/navigation_entry_impl.cc b/content/browser/frame_host/navigation_entry_impl.cc |
index 694985aca8d0ad0a52054082f2eea5f4edd0f5db..44e479ec33c9550a3d11840cc65537753df94395 100644 |
--- a/content/browser/frame_host/navigation_entry_impl.cc |
+++ b/content/browser/frame_host/navigation_entry_impl.cc |
@@ -17,6 +17,12 @@ |
#include "content/public/common/url_constants.h" |
#include "ui/gfx/text_elider.h" |
+using base::UTF16ToUTF8; |
+ |
+namespace content { |
+ |
+namespace { |
+ |
// Use this to get a new unique ID for a NavigationEntry during construction. |
// The returned ID is guaranteed to be nonzero (which is the "no ID" indicator). |
static int GetUniqueIDInConstructor() { |
@@ -24,7 +30,43 @@ static int GetUniqueIDInConstructor() { |
return ++unique_id_counter; |
} |
-namespace content { |
+void RecursivelyGenerateFrameEntries(const ExplodedFrameState& state, |
+ NavigationEntryImpl::TreeNode* node) { |
+ node->frame_entry = new FrameNavigationEntry( |
+ -1, UTF16ToUTF8(state.target.string()), state.item_sequence_number, |
+ state.document_sequence_number, nullptr, GURL(state.url_string.string()), |
+ Referrer(GURL(state.referrer.string()), state.referrer_policy)); |
+ |
+ node->frame_entry->set_frame_state(state); |
+ |
+ for (const ExplodedFrameState& child_state : state.children) { |
+ NavigationEntryImpl::TreeNode* child_node = |
+ new NavigationEntryImpl::TreeNode(nullptr); |
+ node->children.push_back(child_node); |
+ RecursivelyGenerateFrameEntries(child_state, child_node); |
+ } |
+} |
+ |
+void RecursivelyGenerateFrameState( |
+ NavigationEntryImpl::TreeNode* node, |
+ ExplodedFrameState* state, |
+ std::vector<base::NullableString16>* referenced_files) { |
+ // Copy the FrameNavigationEntry's frame state into the destination state. |
+ *state = node->frame_entry->frame_state(); |
+ |
+ // TODO(creis): Copy the referenced files from frame_entry into |
+ // referenced_files (which is from PageState). Need to implement helper. |
+ // ToNullableString16Vector(node->frame_entry->referenced_files(), |
+ // referenced_files); |
+ |
+ state->children.resize(node->children.size()); |
+ for (size_t i = 0; i < node->children.size(); ++i) { |
+ RecursivelyGenerateFrameState(node->children[i], &state->children[i], |
+ referenced_files); |
+ } |
+} |
+ |
+} // namespace |
int NavigationEntryImpl::kInvalidBindings = -1; |
@@ -180,22 +222,45 @@ const base::string16& NavigationEntryImpl::GetTitle() const { |
} |
void NavigationEntryImpl::SetPageState(const PageState& state) { |
- frame_tree_->frame_entry->set_page_state(state); |
+ page_state_ = state; |
- if (SiteIsolationPolicy::UseSubframeNavigationEntries()) { |
- // Also get the root ISN and DSN out of the PageState. |
- ExplodedPageState exploded_state; |
- if (!DecodePageState(state.ToEncodedData(), &exploded_state)) |
- return; |
- frame_tree_->frame_entry->set_item_sequence_number( |
- exploded_state.top.item_sequence_number); |
- frame_tree_->frame_entry->set_document_sequence_number( |
- exploded_state.top.document_sequence_number); |
+ if (!SiteIsolationPolicy::UseSubframeNavigationEntries()) |
+ return; |
+ |
+ // This should only be called when restoring a NavigationEntry, so there |
+ // should be no subframe FrameNavigationEntries yet. |
+ DCHECK_EQ(0U, frame_tree_->children.size()); |
+ |
+ ExplodedPageState exploded_state; |
+ if (!DecodePageState(state.ToEncodedData(), &exploded_state)) { |
+ // Give up and set an empty ExplodedFrameState on the main frame. |
+ frame_tree_->frame_entry->set_frame_state(ExplodedFrameState()); |
+ return; |
} |
+ |
+ RecursivelyGenerateFrameEntries(exploded_state.top, frame_tree_.get()); |
} |
const PageState& NavigationEntryImpl::GetPageState() const { |
- return frame_tree_->frame_entry->page_state(); |
+ return page_state_; |
+} |
+ |
+void NavigationEntryImpl::UpdatePageState() { |
+ // When we're using subframe entries, each FrameNavigationEntry has a |
+ // frame-specific PageState. We combine these into an ExplodedPageState tree |
+ // and generate a full PageState from it. |
+ DCHECK(SiteIsolationPolicy::UseSubframeNavigationEntries()); |
+ ExplodedPageState exploded_state; |
+ RecursivelyGenerateFrameState(frame_tree_.get(), &exploded_state.top, |
+ &exploded_state.referenced_files); |
+ |
+ std::string encoded_data; |
+ if (!EncodePageState(exploded_state, &encoded_data)) { |
+ page_state_ = PageState(); |
+ return; |
+ } |
+ |
+ page_state_ = PageState::CreateFromEncodedData(encoded_data); |
} |
void NavigationEntryImpl::SetPageID(int page_id) { |
@@ -518,10 +583,17 @@ RequestNavigationParams NavigationEntryImpl::ConstructRequestNavigationParams( |
current_offset_to_send = -1; |
current_length_to_send = 0; |
} |
+ |
+ // Use the actual PageState in default Chrome, and only send the frame state |
+ // in OOPIF modes. |
+ PageState page_state = SiteIsolationPolicy::UseSubframeNavigationEntries() |
+ ? PageState() |
+ : GetPageState(); |
+ |
return RequestNavigationParams( |
GetIsOverridingUserAgent(), redirects, GetCanLoadLocalResources(), |
- base::Time::Now(), frame_entry.page_state(), GetPageID(), GetUniqueID(), |
- is_same_document_history_load, has_committed_real_load, |
+ base::Time::Now(), page_state, frame_entry.frame_state(), GetPageID(), |
+ GetUniqueID(), is_same_document_history_load, has_committed_real_load, |
intended_as_new_entry, pending_offset_to_send, current_offset_to_send, |
current_length_to_send, should_clear_history_list()); |
} |
@@ -555,7 +627,7 @@ void NavigationEntryImpl::AddOrUpdateFrameEntry( |
SiteInstanceImpl* site_instance, |
const GURL& url, |
const Referrer& referrer, |
- const PageState& page_state) { |
+ const ExplodedFrameState& frame_state) { |
// We should already have a TreeNode for the parent node by the time this node |
// commits. Find it first. |
DCHECK(frame_tree_node->parent()); |
@@ -574,7 +646,7 @@ void NavigationEntryImpl::AddOrUpdateFrameEntry( |
// Update the existing FrameNavigationEntry (e.g., for replaceState). |
child->frame_entry->UpdateEntry(frame_unique_name, item_sequence_number, |
document_sequence_number, site_instance, |
- url, referrer, page_state); |
+ url, referrer, frame_state); |
return; |
} |
} |
@@ -585,7 +657,7 @@ void NavigationEntryImpl::AddOrUpdateFrameEntry( |
FrameNavigationEntry* frame_entry = new FrameNavigationEntry( |
frame_tree_node_id, frame_unique_name, item_sequence_number, |
document_sequence_number, site_instance, url, referrer); |
- frame_entry->set_page_state(page_state); |
+ frame_entry->set_frame_state(frame_state); |
parent_node->children.push_back( |
new NavigationEntryImpl::TreeNode(frame_entry)); |
} |