summaryrefslogtreecommitdiffstats
path: root/chromium/content/browser/frame_host/frame_tree.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/content/browser/frame_host/frame_tree.cc')
-rw-r--r--chromium/content/browser/frame_host/frame_tree.cc250
1 files changed, 165 insertions, 85 deletions
diff --git a/chromium/content/browser/frame_host/frame_tree.cc b/chromium/content/browser/frame_host/frame_tree.cc
index fef82eebab8..1accb0e9d1b 100644
--- a/chromium/content/browser/frame_host/frame_tree.cc
+++ b/chromium/content/browser/frame_host/frame_tree.cc
@@ -12,6 +12,8 @@
#include "content/browser/frame_host/navigator.h"
#include "content/browser/frame_host/render_frame_host_factory.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/browser/renderer_host/render_view_host_factory.h"
+#include "content/browser/renderer_host/render_view_host_impl.h"
namespace content {
@@ -29,11 +31,13 @@ bool FrameTreeNodeForId(int64 frame_tree_node_id,
return true;
}
-// TODO(creis): Remove this version along with FrameTreeNode::frame_id().
-bool FrameTreeNodeForFrameId(int64 frame_id,
- FrameTreeNode** out_node,
- FrameTreeNode* node) {
- if (node->frame_id() == frame_id) {
+bool FrameTreeNodeForRoutingId(int routing_id,
+ int process_id,
+ FrameTreeNode** out_node,
+ FrameTreeNode* node) {
+ // TODO(creis): Look through the swapped out RFHs as well.
+ if (node->current_frame_host()->GetProcess()->GetID() == process_id &&
+ node->current_frame_host()->GetRoutingID() == routing_id) {
*out_node = node;
// Terminate iteration once the node has been found.
return false;
@@ -41,6 +45,15 @@ bool FrameTreeNodeForFrameId(int64 frame_id,
return true;
}
+// Iterate over the FrameTree to reset any node affected by the loss of the
+// given RenderViewHost's process.
+bool ResetNodesForNewProcess(RenderViewHost* render_view_host,
+ FrameTreeNode* node) {
+ if (render_view_host == node->current_frame_host()->render_view_host())
+ node->ResetForNewProcess();
+ return true;
+}
+
} // namespace
FrameTree::FrameTree(Navigator* navigator,
@@ -52,13 +65,14 @@ FrameTree::FrameTree(Navigator* navigator,
render_view_delegate_(render_view_delegate),
render_widget_delegate_(render_widget_delegate),
manager_delegate_(manager_delegate),
- root_(new FrameTreeNode(navigator,
+ root_(new FrameTreeNode(this,
+ navigator,
render_frame_delegate,
render_view_delegate,
render_widget_delegate,
manager_delegate,
- FrameTreeNode::kInvalidFrameId,
- std::string())) {
+ std::string())),
+ focused_frame_tree_node_id_(-1) {
}
FrameTree::~FrameTree() {
@@ -70,6 +84,13 @@ FrameTreeNode* FrameTree::FindByID(int64 frame_tree_node_id) {
return node;
}
+FrameTreeNode* FrameTree::FindByRoutingID(int routing_id, int process_id) {
+ FrameTreeNode* node = NULL;
+ ForEach(
+ base::Bind(&FrameTreeNodeForRoutingId, routing_id, process_id, &node));
+ return node;
+}
+
void FrameTree::ForEach(
const base::Callback<bool(FrameTreeNode*)>& on_node) const {
std::queue<FrameTreeNode*> queue;
@@ -86,106 +107,165 @@ void FrameTree::ForEach(
}
}
-bool FrameTree::IsFirstNavigationAfterSwap() const {
- return root_->frame_id() == FrameTreeNode::kInvalidFrameId;
-}
-
-void FrameTree::OnFirstNavigationAfterSwap(int main_frame_id) {
- root_->set_frame_id(main_frame_id);
+RenderFrameHostImpl* FrameTree::AddFrame(FrameTreeNode* parent,
+ int new_routing_id,
+ const std::string& frame_name) {
+ scoped_ptr<FrameTreeNode> node(new FrameTreeNode(
+ this, parent->navigator(), render_frame_delegate_, render_view_delegate_,
+ render_widget_delegate_, manager_delegate_, frame_name));
+ FrameTreeNode* node_ptr = node.get();
+ // AddChild is what creates the RenderFrameHost.
+ parent->AddChild(node.Pass(), new_routing_id);
+ return node_ptr->current_frame_host();
}
-RenderFrameHostImpl* FrameTree::AddFrame(int render_frame_host_id,
- int64 parent_frame_id,
- int64 frame_id,
- const std::string& frame_name) {
- FrameTreeNode* parent = FindByFrameID(parent_frame_id);
- // TODO(ajwong): Should the renderer be killed here? Would there be a race on
- // shutdown that might make this case possible?
- if (!parent)
- return NULL;
+void FrameTree::RemoveFrame(FrameTreeNode* child) {
+ FrameTreeNode* parent = child->parent();
+ if (!parent) {
+ NOTREACHED() << "Unexpected RemoveFrame call for main frame.";
+ return;
+ }
- scoped_ptr<FrameTreeNode> node(CreateNode(
- frame_id, frame_name, render_frame_host_id, parent));
- RenderFrameHostImpl* render_frame = node->render_frame_host();
- parent->AddChild(node.Pass());
- return render_frame;
-}
-
-void FrameTree::RemoveFrame(RenderFrameHostImpl* render_frame_host,
- int64 parent_frame_id,
- int64 frame_id) {
- // If switches::kSitePerProcess is not specified, then the FrameTree only
- // contains a node for the root element. However, even in this case
- // frame detachments need to be broadcast outwards.
- //
- // TODO(ajwong): Move this below the |parent| check after the FrameTree is
- // guaranteed to be correctly populated even without the
- // switches::kSitePerProcess flag.
- FrameTreeNode* parent = FindByFrameID(parent_frame_id);
- FrameTreeNode* child = FindByFrameID(frame_id);
+ // Notify observers of the frame removal.
+ RenderFrameHostImpl* render_frame_host = child->current_frame_host();
if (!on_frame_removed_.is_null()) {
on_frame_removed_.Run(
- render_frame_host->render_view_host(), frame_id);
+ render_frame_host->render_view_host(),
+ render_frame_host->GetRoutingID());
}
- // TODO(ajwong): Should the renderer be killed here? Would there be a race on
- // shutdown that might make this case possible?
- if (!parent || !child)
- return;
-
parent->RemoveChild(child);
}
-void FrameTree::SetFrameUrl(int64 frame_id, const GURL& url) {
- FrameTreeNode* node = FindByFrameID(frame_id);
- // TODO(ajwong): Should the renderer be killed here? Would there be a race on
- // shutdown that might make this case possible?
- if (!node)
- return;
-
- if (node)
- node->set_current_url(url);
+void FrameTree::ResetForMainFrameSwap() {
+ root_->ResetForNewProcess();
+ focused_frame_tree_node_id_ = -1;
}
-void FrameTree::SwapMainFrame(RenderFrameHostImpl* render_frame_host) {
- return root_->ResetForMainFrame(render_frame_host);
+void FrameTree::RenderProcessGone(RenderViewHost* render_view_host) {
+ // Walk the full tree looking for nodes that may be affected. Once a frame
+ // crashes, all of its child FrameTreeNodes go away.
+ // Note that the helper function may call ResetForNewProcess on a node, which
+ // clears its children before we iterate over them. That's ok, because
+ // ForEach does not add a node's children to the queue until after visiting
+ // the node itself.
+ ForEach(base::Bind(&ResetNodesForNewProcess, render_view_host));
}
RenderFrameHostImpl* FrameTree::GetMainFrame() const {
- return root_->render_frame_host();
+ return root_->current_frame_host();
+}
+
+FrameTreeNode* FrameTree::GetFocusedFrame() {
+ return FindByID(focused_frame_tree_node_id_);
+}
+
+void FrameTree::SetFocusedFrame(FrameTreeNode* node) {
+ focused_frame_tree_node_id_ = node->frame_tree_node_id();
}
void FrameTree::SetFrameRemoveListener(
- const base::Callback<void(RenderViewHostImpl*, int64)>& on_frame_removed) {
+ const base::Callback<void(RenderViewHostImpl*, int)>& on_frame_removed) {
on_frame_removed_ = on_frame_removed;
}
-FrameTreeNode* FrameTree::FindByFrameID(int64 frame_id) {
- FrameTreeNode* node = NULL;
- ForEach(base::Bind(&FrameTreeNodeForFrameId, frame_id, &node));
- return node;
+RenderViewHostImpl* FrameTree::CreateRenderViewHostForMainFrame(
+ SiteInstance* site_instance,
+ int routing_id,
+ int main_frame_routing_id,
+ bool swapped_out,
+ bool hidden) {
+ DCHECK(main_frame_routing_id != MSG_ROUTING_NONE);
+ RenderViewHostMap::iterator iter =
+ render_view_host_map_.find(site_instance->GetId());
+ if (iter != render_view_host_map_.end()) {
+ // If a RenderViewHost is pending shutdown for this |site_instance|, put it
+ // in the map of RenderViewHosts pending shutdown. Otherwise there should
+ // not be a RenderViewHost for the SiteInstance.
+ CHECK_EQ(RenderViewHostImpl::STATE_PENDING_SHUTDOWN,
+ iter->second->rvh_state());
+ render_view_host_pending_shutdown_map_.insert(
+ std::pair<int, RenderViewHostImpl*>(site_instance->GetId(),
+ iter->second));
+ render_view_host_map_.erase(iter);
+ }
+ RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
+ RenderViewHostFactory::Create(site_instance,
+ render_view_delegate_,
+ render_widget_delegate_,
+ routing_id,
+ main_frame_routing_id,
+ swapped_out,
+ hidden));
+
+ render_view_host_map_[site_instance->GetId()] = rvh;
+ return rvh;
}
-scoped_ptr<FrameTreeNode> FrameTree::CreateNode(
- int64 frame_id,
- const std::string& frame_name,
- int render_frame_host_id,
- FrameTreeNode* parent_node) {
- scoped_ptr<FrameTreeNode> frame_tree_node(new FrameTreeNode(
- parent_node->navigator(), render_frame_delegate_, render_view_delegate_,
- render_widget_delegate_, manager_delegate_, frame_id, frame_name));
-
- scoped_ptr<RenderFrameHostImpl> render_frame_host(
- RenderFrameHostFactory::Create(
- parent_node->render_frame_host()->render_view_host(),
- parent_node->render_frame_host()->delegate(),
- this,
- frame_tree_node.get(),
- render_frame_host_id,
- false));
-
- frame_tree_node->set_render_frame_host(render_frame_host.release(), true);
- return frame_tree_node.Pass();
+RenderViewHostImpl* FrameTree::GetRenderViewHostForSubFrame(
+ SiteInstance* site_instance) {
+ RenderViewHostMap::iterator iter =
+ render_view_host_map_.find(site_instance->GetId());
+ // TODO(creis): Mirror the frame tree so this check can't fail.
+ if (iter == render_view_host_map_.end())
+ return NULL;
+ return iter->second;
+}
+
+void FrameTree::RegisterRenderFrameHost(
+ RenderFrameHostImpl* render_frame_host) {
+ SiteInstance* site_instance =
+ render_frame_host->render_view_host()->GetSiteInstance();
+ RenderViewHostMap::iterator iter =
+ render_view_host_map_.find(site_instance->GetId());
+ CHECK(iter != render_view_host_map_.end());
+
+ iter->second->increment_ref_count();
+}
+
+void FrameTree::UnregisterRenderFrameHost(
+ RenderFrameHostImpl* render_frame_host) {
+ SiteInstance* site_instance =
+ render_frame_host->render_view_host()->GetSiteInstance();
+ int32 site_instance_id = site_instance->GetId();
+ RenderViewHostMap::iterator iter =
+ render_view_host_map_.find(site_instance_id);
+ if (iter != render_view_host_map_.end() &&
+ iter->second == render_frame_host->render_view_host()) {
+ // Decrement the refcount and shutdown the RenderViewHost if no one else is
+ // using it.
+ CHECK_GT(iter->second->ref_count(), 0);
+ iter->second->decrement_ref_count();
+ if (iter->second->ref_count() == 0) {
+ iter->second->Shutdown();
+ render_view_host_map_.erase(iter);
+ }
+ } else {
+ // The RenderViewHost should be in the list of RenderViewHosts pending
+ // shutdown.
+ bool render_view_host_found = false;
+ std::pair<RenderViewHostMultiMap::iterator,
+ RenderViewHostMultiMap::iterator> result =
+ render_view_host_pending_shutdown_map_.equal_range(site_instance_id);
+ for (RenderViewHostMultiMap::iterator multi_iter = result.first;
+ multi_iter != result.second;
+ ++multi_iter) {
+ if (multi_iter->second != render_frame_host->render_view_host())
+ continue;
+ render_view_host_found = true;
+ RenderViewHostImpl* rvh = multi_iter->second;
+ // Decrement the refcount and shutdown the RenderViewHost if no one else
+ // is using it.
+ CHECK_GT(rvh->ref_count(), 0);
+ rvh->decrement_ref_count();
+ if (rvh->ref_count() == 0) {
+ rvh->Shutdown();
+ render_view_host_pending_shutdown_map_.erase(multi_iter);
+ }
+ break;
+ }
+ CHECK(render_view_host_found);
+ }
}
} // namespace content