Chromium Code Reviews| 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 |