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 |