| 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..c2b7675519eedc753a6aaa720c64f54fb45f489f 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,7 @@ NavigationEntryImpl::NavigationEntryImpl(SiteInstanceImpl* instance,
|
| ui::PageTransition transition_type,
|
| bool is_renderer_initiated)
|
| : frame_tree_(
|
| - new TreeNode(new FrameNavigationEntry(instance, url, referrer))),
|
| + new TreeNode(new FrameNavigationEntry(-1, instance, url, referrer))),
|
| unique_id_(GetUniqueIDInConstructor()),
|
| bindings_(kInvalidBindings),
|
| page_type_(PAGE_TYPE_NORMAL),
|
| @@ -463,15 +465,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 (auto& child : parent_node->children)
|
| + work_queue.push(child);
|
| + }
|
| + 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));
|
| }
|
|
|
|
|