Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / content / browser / frame_host / frame_tree.cc
index 1accb0e..c8b5d2d 100644 (file)
@@ -8,18 +8,29 @@
 
 #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) {
@@ -54,6 +65,17 @@ bool ResetNodesForNewProcess(RenderViewHost* render_view_host,
   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,
@@ -73,9 +95,22 @@ 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) {
@@ -113,6 +148,10 @@ RenderFrameHostImpl* FrameTree::AddFrame(FrameTreeNode* parent,
   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);
@@ -129,14 +168,34 @@ void FrameTree::RemoveFrame(FrameTreeNode* child) {
   // 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;
@@ -165,29 +224,31 @@ void FrameTree::SetFocusedFrame(FrameTreeNode* node) {
 }
 
 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,
@@ -202,8 +263,7 @@ RenderViewHostImpl* FrameTree::CreateRenderViewHostForMainFrame(
   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.