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 5a93b0fe1c69f8dacd84519344c2dd47529ea369..7ea3a6e05ad3b732e1d7075a46e7ede222938423 100644 |
| --- a/content/browser/frame_host/navigation_entry_impl.cc |
| +++ b/content/browser/frame_host/navigation_entry_impl.cc |
| @@ -4,6 +4,8 @@ |
| #include "content/browser/frame_host/navigation_entry_impl.h" |
| +#include <queue> |
| + |
| #include "base/metrics/histogram.h" |
| #include "base/strings/string_util.h" |
| #include "base/strings/utf_string_conversions.h" |
| @@ -62,7 +64,8 @@ NavigationEntryImpl::NavigationEntryImpl(SiteInstanceImpl* instance, |
| ui::PageTransition transition_type, |
| bool is_renderer_initiated) |
| : frame_tree_( |
| - new TreeNode(new FrameNavigationEntry(instance, url, referrer))), |
| + // TODO(creis): Pass in FTN ID? How? |
|
Charlie Reis
2015/05/14 16:52:08
Oops, I'll remove this TODO, since it's covered el
|
| + new TreeNode(new FrameNavigationEntry(-1, instance, url, referrer))), |
| unique_id_(GetUniqueIDInConstructor()), |
| bindings_(kInvalidBindings), |
| page_type_(PAGE_TYPE_NORMAL), |
| @@ -463,15 +466,56 @@ void NavigationEntryImpl::ResetForCommit() { |
| #endif |
| } |
| -void NavigationEntryImpl::AddOrUpdateFrameEntry(int frame_tree_node_id, |
| +void NavigationEntryImpl::AddOrUpdateFrameEntry(FrameTreeNode* frame_tree_node, |
| SiteInstanceImpl* site_instance, |
| const GURL& url, |
| const Referrer& referrer) { |
| - // TODO(creis): Walk tree to find the node to update. |
| - // TODO(creis): Only create a new entry if one doesn't exist yet. |
| - FrameNavigationEntry* frame_entry = |
| - new FrameNavigationEntry(site_instance, url, referrer); |
| - root_node()->children.push_back( |
| + // We should already have a TreeNode for the parent node by the time this node |
| + // commits. Find it first. |
| + DCHECK(frame_tree_node->parent()); |
| + int parent_ftn_id = frame_tree_node->parent()->frame_tree_node_id(); |
| + bool found = false; |
| + NavigationEntryImpl::TreeNode* parent_node = nullptr; |
| + std::queue<NavigationEntryImpl::TreeNode*> work_queue; |
| + work_queue.push(root_node()); |
| + while (!found && !work_queue.empty()) { |
| + parent_node = work_queue.front(); |
| + work_queue.pop(); |
| + // The root FNE will have an ID of -1, so check for that as well. |
| + if (parent_node->frame_entry->frame_tree_node_id() == parent_ftn_id || |
| + (parent_node->frame_entry->frame_tree_node_id() == -1 && |
| + parent_node == root_node() && |
| + frame_tree_node->parent()->IsMainFrame())) { |
| + found = true; |
| + break; |
| + } |
| + // Enqueue any children and keep looking. |
| + for (size_t i = 0; i < parent_node->children.size(); i++) |
|
Avi (use Gerrit)
2015/05/14 18:01:11
for (auto& child : parent_node->children) ?
Charlie Reis
2015/05/14 19:00:37
Done.
|
| + work_queue.push(parent_node->children[i]); |
| + } |
| + if (!found) { |
| + // The renderer should not send a commit for a subframe before its parent. |
| + // TODO(creis): This can currently happen because we don't yet clone the |
| + // FrameNavigationEntry tree on manual subframe navigations. Once that's |
| + // added, we should kill the renderer if we get here. |
| + return; |
| + } |
| + |
| + // Now check whether we have a TreeNode for the node itself. |
| + int frame_tree_node_id = frame_tree_node->frame_tree_node_id(); |
| + for (TreeNode* child : parent_node->children) { |
| + if (child->frame_entry->frame_tree_node_id() == frame_tree_node_id) { |
| + // Update the existing FrameNavigationEntry. |
| + child->frame_entry->UpdateEntry(site_instance, url, referrer); |
| + return; |
| + } |
| + } |
| + |
| + // No entry exists yet, so create a new one. Unordered list, since we expect |
| + // to look up entries by frame sequence number or unique name. |
| + FrameNavigationEntry* frame_entry = new FrameNavigationEntry( |
| + frame_tree_node_id, site_instance, url, referrer); |
| + parent_node->children.push_back( |
| new NavigationEntryImpl::TreeNode(frame_entry)); |
| } |