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 <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <queue> | 9 #include <queue> |
10 #include <utility> | 10 #include <utility> |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
109 if (is_root_tree_node) | 109 if (is_root_tree_node) |
110 return frame_tree_node->IsMainFrame(); | 110 return frame_tree_node->IsMainFrame(); |
111 | 111 |
112 // Otherwise check the unique name for subframes. | 112 // Otherwise check the unique name for subframes. |
113 return !frame_tree_node->IsMainFrame() && | 113 return !frame_tree_node->IsMainFrame() && |
114 frame_tree_node->unique_name() == frame_entry->frame_unique_name(); | 114 frame_tree_node->unique_name() == frame_entry->frame_unique_name(); |
115 } | 115 } |
116 | 116 |
117 std::unique_ptr<NavigationEntryImpl::TreeNode> | 117 std::unique_ptr<NavigationEntryImpl::TreeNode> |
118 NavigationEntryImpl::TreeNode::CloneAndReplace( | 118 NavigationEntryImpl::TreeNode::CloneAndReplace( |
119 FrameTreeNode* frame_tree_node, | |
120 FrameNavigationEntry* frame_navigation_entry, | 119 FrameNavigationEntry* frame_navigation_entry, |
120 bool clone_children_of_target, | |
121 FrameTreeNode* target_frame_tree_node, | |
122 FrameTreeNode* current_frame_tree_node, | |
121 bool is_root_tree_node) const { | 123 bool is_root_tree_node) const { |
122 if (frame_tree_node && MatchesFrame(frame_tree_node, is_root_tree_node)) { | 124 // Clone this TreeNode, possibly replacing its FrameNavigationEntry. |
123 // Replace this node in the cloned tree and prune its children. | 125 bool is_target_frame = |
124 return base::WrapUnique( | 126 target_frame_tree_node && |
125 new NavigationEntryImpl::TreeNode(frame_navigation_entry)); | 127 MatchesFrame(target_frame_tree_node, is_root_tree_node); |
126 } | 128 std::unique_ptr<NavigationEntryImpl::TreeNode> copy( |
129 new NavigationEntryImpl::TreeNode( | |
130 is_target_frame ? frame_navigation_entry : frame_entry->Clone())); | |
127 | 131 |
128 // Clone the tree using a copy of the FrameNavigationEntry, without sharing. | 132 // Recursively clone the children if needed. |
129 // TODO(creis): Share FNEs unless it's for another tab. | 133 if (!is_target_frame || clone_children_of_target) { |
130 std::unique_ptr<NavigationEntryImpl::TreeNode> copy( | 134 for (size_t i = 0; i < children.size(); i++) { |
131 new NavigationEntryImpl::TreeNode(frame_entry->Clone())); | 135 NavigationEntryImpl::TreeNode* child = children[i]; |
132 | 136 |
133 // Recursively clone the children. | 137 // Don't check whether it's still in the tree if |current_frame_tree_node| |
134 for (auto* child : children) { | 138 // is null. |
135 copy->children.push_back( | 139 if (!current_frame_tree_node) { |
136 child->CloneAndReplace(frame_tree_node, frame_navigation_entry, false)); | 140 copy->children.push_back(child->CloneAndReplace( |
141 frame_navigation_entry, clone_children_of_target, | |
142 target_frame_tree_node, nullptr, false)); | |
143 continue; | |
144 } | |
145 | |
146 // Otherwise, make sure the frame is still in the tree before cloning it. | |
147 // This is O(N^2) in the worst case because we need to look up each frame | |
148 // (and since we want to avoid a map of unique names, which can be very | |
149 // long). To partly mitigate this, we add an optimization for the common | |
150 // case that the two child lists are the same length and are likely in the | |
151 // same order: we pick the starting offset of the inner loop to get O(N). | |
152 size_t ftn_child_count = current_frame_tree_node->child_count(); | |
153 for (size_t j = 0; j < ftn_child_count; j++) { | |
154 size_t index = j; | |
155 // If the two lists of children are the same length, start looking at | |
156 // the same index as |child|. | |
157 if (children.size() == ftn_child_count) | |
158 index = (i + j) % ftn_child_count; | |
Avi (use Gerrit)
2016/07/26 15:03:58
Cute, and actually decently easy to reason about.
| |
159 | |
160 if (current_frame_tree_node->child_at(index)->unique_name() == | |
161 child->frame_entry->frame_unique_name()) { | |
162 // Found |child| in the tree. Clone it and break out of inner loop. | |
163 copy->children.push_back(child->CloneAndReplace( | |
164 frame_navigation_entry, clone_children_of_target, | |
165 target_frame_tree_node, current_frame_tree_node->child_at(index), | |
166 false)); | |
167 break; | |
168 } | |
169 } | |
170 } | |
137 } | 171 } |
138 | 172 |
139 return copy; | 173 return copy; |
140 } | 174 } |
141 | 175 |
142 std::unique_ptr<NavigationEntry> NavigationEntry::Create() { | 176 std::unique_ptr<NavigationEntry> NavigationEntry::Create() { |
143 return base::WrapUnique(new NavigationEntryImpl()); | 177 return base::WrapUnique(new NavigationEntryImpl()); |
144 } | 178 } |
145 | 179 |
146 NavigationEntryImpl* NavigationEntryImpl::FromNavigationEntry( | 180 NavigationEntryImpl* NavigationEntryImpl::FromNavigationEntry( |
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
509 return false; | 543 return false; |
510 *data = iter->second; | 544 *data = iter->second; |
511 return true; | 545 return true; |
512 } | 546 } |
513 | 547 |
514 void NavigationEntryImpl::ClearExtraData(const std::string& key) { | 548 void NavigationEntryImpl::ClearExtraData(const std::string& key) { |
515 extra_data_.erase(key); | 549 extra_data_.erase(key); |
516 } | 550 } |
517 | 551 |
518 std::unique_ptr<NavigationEntryImpl> NavigationEntryImpl::Clone() const { | 552 std::unique_ptr<NavigationEntryImpl> NavigationEntryImpl::Clone() const { |
519 return NavigationEntryImpl::CloneAndReplace(nullptr, nullptr); | 553 return NavigationEntryImpl::CloneAndReplace(nullptr, false, nullptr, nullptr); |
520 } | 554 } |
521 | 555 |
522 std::unique_ptr<NavigationEntryImpl> NavigationEntryImpl::CloneAndReplace( | 556 std::unique_ptr<NavigationEntryImpl> NavigationEntryImpl::CloneAndReplace( |
523 FrameTreeNode* frame_tree_node, | 557 FrameNavigationEntry* frame_navigation_entry, |
524 FrameNavigationEntry* frame_navigation_entry) const { | 558 bool clone_children_of_target, |
559 FrameTreeNode* target_frame_tree_node, | |
560 FrameTreeNode* root_frame_tree_node) const { | |
525 std::unique_ptr<NavigationEntryImpl> copy = | 561 std::unique_ptr<NavigationEntryImpl> copy = |
526 base::WrapUnique(new NavigationEntryImpl()); | 562 base::WrapUnique(new NavigationEntryImpl()); |
527 | 563 |
528 // TODO(creis): Only share the same FrameNavigationEntries if cloning within | 564 // TODO(creis): Only share the same FrameNavigationEntries if cloning within |
529 // the same tab. | 565 // the same tab. |
530 copy->frame_tree_ = frame_tree_->CloneAndReplace( | 566 copy->frame_tree_ = frame_tree_->CloneAndReplace( |
531 frame_tree_node, frame_navigation_entry, true); | 567 frame_navigation_entry, clone_children_of_target, target_frame_tree_node, |
568 root_frame_tree_node, true); | |
532 | 569 |
533 // Copy most state over, unless cleared in ResetForCommit. | 570 // Copy most state over, unless cleared in ResetForCommit. |
534 // Don't copy unique_id_, otherwise it won't be unique. | 571 // Don't copy unique_id_, otherwise it won't be unique. |
535 copy->bindings_ = bindings_; | 572 copy->bindings_ = bindings_; |
536 copy->page_type_ = page_type_; | 573 copy->page_type_ = page_type_; |
537 copy->virtual_url_ = virtual_url_; | 574 copy->virtual_url_ = virtual_url_; |
538 copy->update_virtual_url_with_url_ = update_virtual_url_with_url_; | 575 copy->update_virtual_url_with_url_ = update_virtual_url_with_url_; |
539 copy->title_ = title_; | 576 copy->title_ = title_; |
540 copy->favicon_ = favicon_; | 577 copy->favicon_ = favicon_; |
541 copy->page_id_ = page_id_; | 578 copy->page_id_ = page_id_; |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
774 return node; | 811 return node; |
775 | 812 |
776 // Enqueue any children and keep looking. | 813 // Enqueue any children and keep looking. |
777 for (auto* child : node->children) | 814 for (auto* child : node->children) |
778 work_queue.push(child); | 815 work_queue.push(child); |
779 } | 816 } |
780 return nullptr; | 817 return nullptr; |
781 } | 818 } |
782 | 819 |
783 } // namespace content | 820 } // namespace content |
OLD | NEW |