Chromium Code Reviews| 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..95cdd4fcd0c34cb2f1adacfd1a23255f79ffeb66 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() { |
|
Avi (use Gerrit)
2015/12/02 19:17:43
Now that this is in an anonymous namespace, you ca
Charlie Reis
2015/12/02 20:44:14
Done.
|
| @@ -24,7 +30,59 @@ 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)); |
| + |
| + // Set a single-frame PageState on the entry. |
| + ExplodedPageState page_state; |
| + page_state.top = state; |
| + std::string data; |
| + if (EncodePageState(page_state, &data)) |
| + node->frame_entry->set_page_state(PageState::CreateFromEncodedData(data)); |
| + |
| + 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) { |
| + // The FrameNavigationEntry's PageState contains just the ExplodedFrameState |
| + // for that particular frame. |
| + ExplodedPageState exploded_page_state; |
| + if (!DecodePageState(node->frame_entry->page_state().ToEncodedData(), |
| + &exploded_page_state)) { |
| + NOTREACHED(); |
| + return; |
| + } |
| + ExplodedFrameState frame_state = exploded_page_state.top; |
| + |
| + // Copy the FrameNavigationEntry's frame state into the destination state. |
| + *state = frame_state; |
| + |
| + // Copy the frame's files into the PageState's |referenced_files|. |
| + referenced_files->reserve( |
| + referenced_files->size() + exploded_page_state.referenced_files.size()); |
| + for (auto& file : exploded_page_state.referenced_files) |
| + referenced_files->push_back(file); |
| + |
| + 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 +238,42 @@ 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)) |
| + 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) { |
| @@ -432,6 +510,7 @@ scoped_ptr<NavigationEntryImpl> NavigationEntryImpl::CloneAndReplace( |
| copy->is_overriding_user_agent_ = is_overriding_user_agent_; |
| copy->timestamp_ = timestamp_; |
| copy->http_status_code_ = http_status_code_; |
| + copy->page_state_ = page_state_; |
| // ResetForCommit: browser_initiated_post_data_ |
| copy->screenshot_ = screenshot_; |
| copy->extra_headers_ = extra_headers_; |
| @@ -518,9 +597,16 @@ RequestNavigationParams NavigationEntryImpl::ConstructRequestNavigationParams( |
| current_offset_to_send = -1; |
| current_length_to_send = 0; |
| } |
| + |
| + // Use the overall PageState in default Chrome, and send the frame's state in |
| + // OOPIF modes. |
| + PageState page_state = SiteIsolationPolicy::UseSubframeNavigationEntries() |
| + ? frame_entry.page_state() |
| + : GetPageState(); |
| + |
| return RequestNavigationParams( |
| GetIsOverridingUserAgent(), redirects, GetCanLoadLocalResources(), |
| - base::Time::Now(), frame_entry.page_state(), GetPageID(), GetUniqueID(), |
| + base::Time::Now(), page_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()); |