| OLD | NEW |
| 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/navigation_entry_impl.h" | 5 #include "content/browser/frame_host/navigation_entry_impl.h" |
| 6 | 6 |
| 7 #include <queue> | 7 #include <queue> |
| 8 | 8 |
| 9 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
| 10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
| 11 #include "base/strings/utf_string_conversions.h" | 11 #include "base/strings/utf_string_conversions.h" |
| 12 #include "components/url_formatter/url_formatter.h" | 12 #include "components/url_formatter/url_formatter.h" |
| 13 #include "content/common/navigation_params.h" | 13 #include "content/common/navigation_params.h" |
| 14 #include "content/common/page_state_serialization.h" | 14 #include "content/common/page_state_serialization.h" |
| 15 #include "content/common/site_isolation_policy.h" | 15 #include "content/common/site_isolation_policy.h" |
| 16 #include "content/public/common/content_constants.h" | 16 #include "content/public/common/content_constants.h" |
| 17 #include "content/public/common/url_constants.h" | 17 #include "content/public/common/url_constants.h" |
| 18 #include "ui/gfx/text_elider.h" | 18 #include "ui/gfx/text_elider.h" |
| 19 | 19 |
| 20 using base::UTF16ToUTF8; |
| 21 |
| 22 namespace content { |
| 23 |
| 24 namespace { |
| 25 |
| 20 // Use this to get a new unique ID for a NavigationEntry during construction. | 26 // Use this to get a new unique ID for a NavigationEntry during construction. |
| 21 // The returned ID is guaranteed to be nonzero (which is the "no ID" indicator). | 27 // The returned ID is guaranteed to be nonzero (which is the "no ID" indicator). |
| 22 static int GetUniqueIDInConstructor() { | 28 static int GetUniqueIDInConstructor() { |
| 23 static int unique_id_counter = 0; | 29 static int unique_id_counter = 0; |
| 24 return ++unique_id_counter; | 30 return ++unique_id_counter; |
| 25 } | 31 } |
| 26 | 32 |
| 27 namespace content { | 33 void RecursivelyGenerateFrameEntries(const ExplodedFrameState& state, |
| 34 NavigationEntryImpl::TreeNode* node) { |
| 35 node->frame_entry = new FrameNavigationEntry( |
| 36 -1, UTF16ToUTF8(state.target.string()), state.item_sequence_number, |
| 37 state.document_sequence_number, nullptr, GURL(state.url_string.string()), |
| 38 Referrer(GURL(state.referrer.string()), state.referrer_policy)); |
| 39 |
| 40 node->frame_entry->set_frame_state(state); |
| 41 |
| 42 for (const ExplodedFrameState& child_state : state.children) { |
| 43 NavigationEntryImpl::TreeNode* child_node = |
| 44 new NavigationEntryImpl::TreeNode(nullptr); |
| 45 node->children.push_back(child_node); |
| 46 RecursivelyGenerateFrameEntries(child_state, child_node); |
| 47 } |
| 48 } |
| 49 |
| 50 void RecursivelyGenerateFrameState( |
| 51 NavigationEntryImpl::TreeNode* node, |
| 52 ExplodedFrameState* state, |
| 53 std::vector<base::NullableString16>* referenced_files) { |
| 54 // Copy the FrameNavigationEntry's frame state into the destination state. |
| 55 *state = node->frame_entry->frame_state(); |
| 56 |
| 57 // TODO(creis): Copy the referenced files from frame_entry into |
| 58 // referenced_files (which is from PageState). Need to implement helper. |
| 59 // ToNullableString16Vector(node->frame_entry->referenced_files(), |
| 60 // referenced_files); |
| 61 |
| 62 state->children.resize(node->children.size()); |
| 63 for (size_t i = 0; i < node->children.size(); ++i) { |
| 64 RecursivelyGenerateFrameState(node->children[i], &state->children[i], |
| 65 referenced_files); |
| 66 } |
| 67 } |
| 68 |
| 69 } // namespace |
| 28 | 70 |
| 29 int NavigationEntryImpl::kInvalidBindings = -1; | 71 int NavigationEntryImpl::kInvalidBindings = -1; |
| 30 | 72 |
| 31 NavigationEntryImpl::TreeNode::TreeNode(FrameNavigationEntry* frame_entry) | 73 NavigationEntryImpl::TreeNode::TreeNode(FrameNavigationEntry* frame_entry) |
| 32 : frame_entry(frame_entry) { | 74 : frame_entry(frame_entry) { |
| 33 } | 75 } |
| 34 | 76 |
| 35 NavigationEntryImpl::TreeNode::~TreeNode() { | 77 NavigationEntryImpl::TreeNode::~TreeNode() { |
| 36 } | 78 } |
| 37 | 79 |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 173 void NavigationEntryImpl::SetTitle(const base::string16& title) { | 215 void NavigationEntryImpl::SetTitle(const base::string16& title) { |
| 174 title_ = title; | 216 title_ = title; |
| 175 cached_display_title_.clear(); | 217 cached_display_title_.clear(); |
| 176 } | 218 } |
| 177 | 219 |
| 178 const base::string16& NavigationEntryImpl::GetTitle() const { | 220 const base::string16& NavigationEntryImpl::GetTitle() const { |
| 179 return title_; | 221 return title_; |
| 180 } | 222 } |
| 181 | 223 |
| 182 void NavigationEntryImpl::SetPageState(const PageState& state) { | 224 void NavigationEntryImpl::SetPageState(const PageState& state) { |
| 183 frame_tree_->frame_entry->set_page_state(state); | 225 page_state_ = state; |
| 184 | 226 |
| 185 if (SiteIsolationPolicy::UseSubframeNavigationEntries()) { | 227 if (!SiteIsolationPolicy::UseSubframeNavigationEntries()) |
| 186 // Also get the root ISN and DSN out of the PageState. | 228 return; |
| 187 ExplodedPageState exploded_state; | 229 |
| 188 if (!DecodePageState(state.ToEncodedData(), &exploded_state)) | 230 // This should only be called when restoring a NavigationEntry, so there |
| 189 return; | 231 // should be no subframe FrameNavigationEntries yet. |
| 190 frame_tree_->frame_entry->set_item_sequence_number( | 232 DCHECK_EQ(0U, frame_tree_->children.size()); |
| 191 exploded_state.top.item_sequence_number); | 233 |
| 192 frame_tree_->frame_entry->set_document_sequence_number( | 234 ExplodedPageState exploded_state; |
| 193 exploded_state.top.document_sequence_number); | 235 if (!DecodePageState(state.ToEncodedData(), &exploded_state)) { |
| 236 // Give up and set an empty ExplodedFrameState on the main frame. |
| 237 frame_tree_->frame_entry->set_frame_state(ExplodedFrameState()); |
| 238 return; |
| 194 } | 239 } |
| 240 |
| 241 RecursivelyGenerateFrameEntries(exploded_state.top, frame_tree_.get()); |
| 195 } | 242 } |
| 196 | 243 |
| 197 const PageState& NavigationEntryImpl::GetPageState() const { | 244 const PageState& NavigationEntryImpl::GetPageState() const { |
| 198 return frame_tree_->frame_entry->page_state(); | 245 return page_state_; |
| 246 } |
| 247 |
| 248 void NavigationEntryImpl::UpdatePageState() { |
| 249 // When we're using subframe entries, each FrameNavigationEntry has a |
| 250 // frame-specific PageState. We combine these into an ExplodedPageState tree |
| 251 // and generate a full PageState from it. |
| 252 DCHECK(SiteIsolationPolicy::UseSubframeNavigationEntries()); |
| 253 ExplodedPageState exploded_state; |
| 254 RecursivelyGenerateFrameState(frame_tree_.get(), &exploded_state.top, |
| 255 &exploded_state.referenced_files); |
| 256 |
| 257 std::string encoded_data; |
| 258 if (!EncodePageState(exploded_state, &encoded_data)) { |
| 259 page_state_ = PageState(); |
| 260 return; |
| 261 } |
| 262 |
| 263 page_state_ = PageState::CreateFromEncodedData(encoded_data); |
| 199 } | 264 } |
| 200 | 265 |
| 201 void NavigationEntryImpl::SetPageID(int page_id) { | 266 void NavigationEntryImpl::SetPageID(int page_id) { |
| 202 page_id_ = page_id; | 267 page_id_ = page_id; |
| 203 } | 268 } |
| 204 | 269 |
| 205 int32 NavigationEntryImpl::GetPageID() const { | 270 int32 NavigationEntryImpl::GetPageID() const { |
| 206 return page_id_; | 271 return page_id_; |
| 207 } | 272 } |
| 208 | 273 |
| (...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 511 int current_offset_to_send = current_history_list_offset; | 576 int current_offset_to_send = current_history_list_offset; |
| 512 int current_length_to_send = current_history_list_length; | 577 int current_length_to_send = current_history_list_length; |
| 513 if (should_clear_history_list()) { | 578 if (should_clear_history_list()) { |
| 514 // Set the history list related parameters to the same values a | 579 // Set the history list related parameters to the same values a |
| 515 // NavigationController would return before its first navigation. This will | 580 // NavigationController would return before its first navigation. This will |
| 516 // fully clear the RenderView's view of the session history. | 581 // fully clear the RenderView's view of the session history. |
| 517 pending_offset_to_send = -1; | 582 pending_offset_to_send = -1; |
| 518 current_offset_to_send = -1; | 583 current_offset_to_send = -1; |
| 519 current_length_to_send = 0; | 584 current_length_to_send = 0; |
| 520 } | 585 } |
| 586 |
| 587 // Use the actual PageState in default Chrome, and only send the frame state |
| 588 // in OOPIF modes. |
| 589 PageState page_state = SiteIsolationPolicy::UseSubframeNavigationEntries() |
| 590 ? PageState() |
| 591 : GetPageState(); |
| 592 |
| 521 return RequestNavigationParams( | 593 return RequestNavigationParams( |
| 522 GetIsOverridingUserAgent(), redirects, GetCanLoadLocalResources(), | 594 GetIsOverridingUserAgent(), redirects, GetCanLoadLocalResources(), |
| 523 base::Time::Now(), frame_entry.page_state(), GetPageID(), GetUniqueID(), | 595 base::Time::Now(), page_state, frame_entry.frame_state(), GetPageID(), |
| 524 is_same_document_history_load, has_committed_real_load, | 596 GetUniqueID(), is_same_document_history_load, has_committed_real_load, |
| 525 intended_as_new_entry, pending_offset_to_send, current_offset_to_send, | 597 intended_as_new_entry, pending_offset_to_send, current_offset_to_send, |
| 526 current_length_to_send, should_clear_history_list()); | 598 current_length_to_send, should_clear_history_list()); |
| 527 } | 599 } |
| 528 | 600 |
| 529 void NavigationEntryImpl::ResetForCommit() { | 601 void NavigationEntryImpl::ResetForCommit() { |
| 530 // Any state that only matters when a navigation entry is pending should be | 602 // Any state that only matters when a navigation entry is pending should be |
| 531 // cleared here. | 603 // cleared here. |
| 532 // TODO(creis): This state should be moved to NavigationRequest once | 604 // TODO(creis): This state should be moved to NavigationRequest once |
| 533 // PlzNavigate is enabled. | 605 // PlzNavigate is enabled. |
| 534 SetBrowserInitiatedPostData(nullptr); | 606 SetBrowserInitiatedPostData(nullptr); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 548 } | 620 } |
| 549 | 621 |
| 550 void NavigationEntryImpl::AddOrUpdateFrameEntry( | 622 void NavigationEntryImpl::AddOrUpdateFrameEntry( |
| 551 FrameTreeNode* frame_tree_node, | 623 FrameTreeNode* frame_tree_node, |
| 552 const std::string& frame_unique_name, | 624 const std::string& frame_unique_name, |
| 553 int64 item_sequence_number, | 625 int64 item_sequence_number, |
| 554 int64 document_sequence_number, | 626 int64 document_sequence_number, |
| 555 SiteInstanceImpl* site_instance, | 627 SiteInstanceImpl* site_instance, |
| 556 const GURL& url, | 628 const GURL& url, |
| 557 const Referrer& referrer, | 629 const Referrer& referrer, |
| 558 const PageState& page_state) { | 630 const ExplodedFrameState& frame_state) { |
| 559 // We should already have a TreeNode for the parent node by the time this node | 631 // We should already have a TreeNode for the parent node by the time this node |
| 560 // commits. Find it first. | 632 // commits. Find it first. |
| 561 DCHECK(frame_tree_node->parent()); | 633 DCHECK(frame_tree_node->parent()); |
| 562 NavigationEntryImpl::TreeNode* parent_node = | 634 NavigationEntryImpl::TreeNode* parent_node = |
| 563 FindFrameEntry(frame_tree_node->parent()); | 635 FindFrameEntry(frame_tree_node->parent()); |
| 564 if (!parent_node) { | 636 if (!parent_node) { |
| 565 // The renderer should not send a commit for a subframe before its parent. | 637 // The renderer should not send a commit for a subframe before its parent. |
| 566 // TODO(creis): Kill the renderer if we get here. | 638 // TODO(creis): Kill the renderer if we get here. |
| 567 return; | 639 return; |
| 568 } | 640 } |
| 569 | 641 |
| 570 // Now check whether we have a TreeNode for the node itself. | 642 // Now check whether we have a TreeNode for the node itself. |
| 571 int frame_tree_node_id = frame_tree_node->frame_tree_node_id(); | 643 int frame_tree_node_id = frame_tree_node->frame_tree_node_id(); |
| 572 for (TreeNode* child : parent_node->children) { | 644 for (TreeNode* child : parent_node->children) { |
| 573 if (child->frame_entry->frame_tree_node_id() == frame_tree_node_id) { | 645 if (child->frame_entry->frame_tree_node_id() == frame_tree_node_id) { |
| 574 // Update the existing FrameNavigationEntry (e.g., for replaceState). | 646 // Update the existing FrameNavigationEntry (e.g., for replaceState). |
| 575 child->frame_entry->UpdateEntry(frame_unique_name, item_sequence_number, | 647 child->frame_entry->UpdateEntry(frame_unique_name, item_sequence_number, |
| 576 document_sequence_number, site_instance, | 648 document_sequence_number, site_instance, |
| 577 url, referrer, page_state); | 649 url, referrer, frame_state); |
| 578 return; | 650 return; |
| 579 } | 651 } |
| 580 } | 652 } |
| 581 | 653 |
| 582 // No entry exists yet, so create a new one. | 654 // No entry exists yet, so create a new one. |
| 583 // Unordered list, since we expect to look up entries by frame sequence number | 655 // Unordered list, since we expect to look up entries by frame sequence number |
| 584 // or unique name. | 656 // or unique name. |
| 585 FrameNavigationEntry* frame_entry = new FrameNavigationEntry( | 657 FrameNavigationEntry* frame_entry = new FrameNavigationEntry( |
| 586 frame_tree_node_id, frame_unique_name, item_sequence_number, | 658 frame_tree_node_id, frame_unique_name, item_sequence_number, |
| 587 document_sequence_number, site_instance, url, referrer); | 659 document_sequence_number, site_instance, url, referrer); |
| 588 frame_entry->set_page_state(page_state); | 660 frame_entry->set_frame_state(frame_state); |
| 589 parent_node->children.push_back( | 661 parent_node->children.push_back( |
| 590 new NavigationEntryImpl::TreeNode(frame_entry)); | 662 new NavigationEntryImpl::TreeNode(frame_entry)); |
| 591 } | 663 } |
| 592 | 664 |
| 593 FrameNavigationEntry* NavigationEntryImpl::GetFrameEntry( | 665 FrameNavigationEntry* NavigationEntryImpl::GetFrameEntry( |
| 594 FrameTreeNode* frame_tree_node) const { | 666 FrameTreeNode* frame_tree_node) const { |
| 595 NavigationEntryImpl::TreeNode* tree_node = FindFrameEntry(frame_tree_node); | 667 NavigationEntryImpl::TreeNode* tree_node = FindFrameEntry(frame_tree_node); |
| 596 return tree_node ? tree_node->frame_entry.get() : nullptr; | 668 return tree_node ? tree_node->frame_entry.get() : nullptr; |
| 597 } | 669 } |
| 598 | 670 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 640 return node; | 712 return node; |
| 641 } | 713 } |
| 642 // Enqueue any children and keep looking. | 714 // Enqueue any children and keep looking. |
| 643 for (auto& child : node->children) | 715 for (auto& child : node->children) |
| 644 work_queue.push(child); | 716 work_queue.push(child); |
| 645 } | 717 } |
| 646 return nullptr; | 718 return nullptr; |
| 647 } | 719 } |
| 648 | 720 |
| 649 } // namespace content | 721 } // namespace content |
| OLD | NEW |