#include "base/bind.h"
#include "base/callback.h"
+#include "base/containers/hash_tables.h"
+#include "base/lazy_instance.h"
#include "content/browser/frame_host/frame_tree_node.h"
#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"
+#include "content/public/browser/browser_thread.h"
namespace content {
namespace {
+
+// This is a global map between frame_tree_node_ids and pointer to
+// FrameTreeNodes.
+typedef base::hash_map<int64, FrameTreeNode*> FrameTreeNodeIDMap;
+
+base::LazyInstance<FrameTreeNodeIDMap> g_frame_tree_node_id_map =
+ LAZY_INSTANCE_INITIALIZER;
+
// Used with FrameTree::ForEach() to search for the FrameTreeNode
-// corresponding to |frame_tree_node_id|.
+// corresponding to |frame_tree_node_id| whithin a specific FrameTree.
bool FrameTreeNodeForId(int64 frame_tree_node_id,
FrameTreeNode** out_node,
FrameTreeNode* node) {
return true;
}
+bool CreateProxyForSiteInstance(FrameTreeNode* source_node,
+ const scoped_refptr<SiteInstance>& instance,
+ FrameTreeNode* node) {
+ // Skip the node that initiated the creation.
+ if (source_node == node)
+ return true;
+
+ node->render_manager()->CreateRenderFrameProxy(instance);
+ return true;
+}
+
} // namespace
FrameTree::FrameTree(Navigator* navigator,
manager_delegate,
std::string())),
focused_frame_tree_node_id_(-1) {
+ std::pair<FrameTreeNodeIDMap::iterator, bool> result =
+ g_frame_tree_node_id_map.Get().insert(
+ std::make_pair(root_->frame_tree_node_id(), root_.get()));
+ CHECK(result.second);
}
FrameTree::~FrameTree() {
+ g_frame_tree_node_id_map.Get().erase(root_->frame_tree_node_id());
+}
+
+// static
+FrameTreeNode* FrameTree::GloballyFindByID(int64 frame_tree_node_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ FrameTreeNodeIDMap* nodes = g_frame_tree_node_id_map.Pointer();
+ FrameTreeNodeIDMap::iterator it = nodes->find(frame_tree_node_id);
+ return it == nodes->end() ? NULL : it->second;
}
FrameTreeNode* FrameTree::FindByID(int64 frame_tree_node_id) {
scoped_ptr<FrameTreeNode> node(new FrameTreeNode(
this, parent->navigator(), render_frame_delegate_, render_view_delegate_,
render_widget_delegate_, manager_delegate_, frame_name));
+ std::pair<FrameTreeNodeIDMap::iterator, bool> result =
+ g_frame_tree_node_id_map.Get().insert(
+ std::make_pair(node->frame_tree_node_id(), node.get()));
+ CHECK(result.second);
FrameTreeNode* node_ptr = node.get();
// AddChild is what creates the RenderFrameHost.
parent->AddChild(node.Pass(), new_routing_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(),
- render_frame_host->GetRoutingID());
+ on_frame_removed_.Run(render_frame_host);
}
-
+ g_frame_tree_node_id_map.Get().erase(child->frame_tree_node_id());
parent->RemoveChild(child);
}
+void FrameTree::CreateProxiesForSiteInstance(
+ FrameTreeNode* source,
+ SiteInstance* site_instance) {
+ // Create the swapped out RVH for the new SiteInstance. This will create
+ // a top-level swapped out RFH as well, which will then be wrapped by a
+ // RenderFrameProxyHost.
+ if (!source->IsMainFrame()) {
+ RenderViewHostImpl* render_view_host =
+ source->frame_tree()->GetRenderViewHost(site_instance);
+ if (!render_view_host) {
+ root()->render_manager()->CreateRenderFrame(site_instance,
+ MSG_ROUTING_NONE,
+ true,
+ false,
+ true);
+ }
+ }
+
+ scoped_refptr<SiteInstance> instance(site_instance);
+ ForEach(base::Bind(&CreateProxyForSiteInstance, source, instance));
+}
+
void FrameTree::ResetForMainFrameSwap() {
root_->ResetForNewProcess();
focused_frame_tree_node_id_ = -1;
}
void FrameTree::SetFrameRemoveListener(
- const base::Callback<void(RenderViewHostImpl*, int)>& on_frame_removed) {
+ const base::Callback<void(RenderFrameHost*)>& on_frame_removed) {
on_frame_removed_ = on_frame_removed;
}
-RenderViewHostImpl* FrameTree::CreateRenderViewHostForMainFrame(
- SiteInstance* site_instance,
- int routing_id,
- int main_frame_routing_id,
- bool swapped_out,
- bool hidden) {
+RenderViewHostImpl* FrameTree::CreateRenderViewHost(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);
+ // in the map of RenderViewHosts pending shutdown. Otherwise return the
+ // existing RenderViewHost for the SiteInstance.
+ if (iter->second->rvh_state() ==
+ RenderViewHostImpl::STATE_PENDING_SHUTDOWN) {
+ render_view_host_pending_shutdown_map_.insert(
+ std::pair<int, RenderViewHostImpl*>(site_instance->GetId(),
+ iter->second));
+ render_view_host_map_.erase(iter);
+ } else {
+ return iter->second;
+ }
}
RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
RenderViewHostFactory::Create(site_instance,
return rvh;
}
-RenderViewHostImpl* FrameTree::GetRenderViewHostForSubFrame(
- SiteInstance* site_instance) {
+RenderViewHostImpl* FrameTree::GetRenderViewHost(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.