Home | History | Annotate | Download | only in frame_host
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "content/browser/frame_host/render_frame_proxy_host.h"
      6 
      7 #include "base/lazy_instance.h"
      8 #include "content/browser/frame_host/cross_process_frame_connector.h"
      9 #include "content/browser/frame_host/frame_tree.h"
     10 #include "content/browser/frame_host/frame_tree_node.h"
     11 #include "content/browser/frame_host/render_frame_host_impl.h"
     12 #include "content/browser/frame_host/render_widget_host_view_child_frame.h"
     13 #include "content/browser/renderer_host/render_view_host_impl.h"
     14 #include "content/browser/renderer_host/render_widget_host_view_base.h"
     15 #include "content/browser/site_instance_impl.h"
     16 #include "content/common/frame_messages.h"
     17 #include "content/public/browser/browser_thread.h"
     18 #include "ipc/ipc_message.h"
     19 
     20 namespace content {
     21 
     22 namespace {
     23 
     24 // The (process id, routing id) pair that identifies one RenderFrameProxy.
     25 typedef std::pair<int32, int32> RenderFrameProxyHostID;
     26 typedef base::hash_map<RenderFrameProxyHostID, RenderFrameProxyHost*>
     27     RoutingIDFrameProxyMap;
     28 base::LazyInstance<RoutingIDFrameProxyMap> g_routing_id_frame_proxy_map =
     29   LAZY_INSTANCE_INITIALIZER;
     30 
     31 }
     32 
     33 // static
     34 RenderFrameProxyHost* RenderFrameProxyHost::FromID(int process_id,
     35                                                    int routing_id) {
     36   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     37   RoutingIDFrameProxyMap* frames = g_routing_id_frame_proxy_map.Pointer();
     38   RoutingIDFrameProxyMap::iterator it = frames->find(
     39       RenderFrameProxyHostID(process_id, routing_id));
     40   return it == frames->end() ? NULL : it->second;
     41 }
     42 
     43 RenderFrameProxyHost::RenderFrameProxyHost(SiteInstance* site_instance,
     44                                            FrameTreeNode* frame_tree_node)
     45     : routing_id_(site_instance->GetProcess()->GetNextRoutingID()),
     46       site_instance_(site_instance),
     47       frame_tree_node_(frame_tree_node) {
     48   GetProcess()->AddRoute(routing_id_, this);
     49   CHECK(g_routing_id_frame_proxy_map.Get().insert(
     50       std::make_pair(
     51           RenderFrameProxyHostID(GetProcess()->GetID(), routing_id_),
     52           this)).second);
     53 
     54   if (!frame_tree_node_->IsMainFrame() &&
     55       frame_tree_node_->parent()
     56               ->render_manager()
     57               ->current_frame_host()
     58               ->GetSiteInstance() == site_instance) {
     59     // The RenderFrameHost navigating cross-process is destroyed and a proxy for
     60     // it is created in the parent's process. CrossProcessFrameConnector
     61     // initialization only needs to happen on an initial cross-process
     62     // navigation, when the RenderFrameHost leaves the same process as its
     63     // parent. The same CrossProcessFrameConnector is used for subsequent cross-
     64     // process navigations, but it will be destroyed if the frame is
     65     // navigated back to the same SiteInstance as its parent.
     66     cross_process_frame_connector_.reset(new CrossProcessFrameConnector(this));
     67   }
     68 }
     69 
     70 RenderFrameProxyHost::~RenderFrameProxyHost() {
     71   if (GetProcess()->HasConnection())
     72     Send(new FrameMsg_DeleteProxy(routing_id_));
     73 
     74   GetProcess()->RemoveRoute(routing_id_);
     75   g_routing_id_frame_proxy_map.Get().erase(
     76       RenderFrameProxyHostID(GetProcess()->GetID(), routing_id_));
     77 }
     78 
     79 void RenderFrameProxyHost::SetChildRWHView(RenderWidgetHostView* view) {
     80   cross_process_frame_connector_->set_view(
     81       static_cast<RenderWidgetHostViewChildFrame*>(view));
     82 }
     83 
     84 RenderViewHostImpl* RenderFrameProxyHost::GetRenderViewHost() {
     85   return frame_tree_node_->frame_tree()->GetRenderViewHost(
     86       site_instance_.get());
     87 }
     88 
     89 scoped_ptr<RenderFrameHostImpl> RenderFrameProxyHost::PassFrameHostOwnership() {
     90   render_frame_host_->set_render_frame_proxy_host(NULL);
     91   return render_frame_host_.Pass();
     92 }
     93 
     94 bool RenderFrameProxyHost::Send(IPC::Message *msg) {
     95   // TODO(nasko): For now, RenderFrameHost uses this object to send IPC messages
     96   // while swapped out. This can be removed once we don't have a swapped out
     97   // state on RenderFrameHosts. See https://crbug.com/357747.
     98   msg->set_routing_id(routing_id_);
     99   return GetProcess()->Send(msg);
    100 }
    101 
    102 bool RenderFrameProxyHost::OnMessageReceived(const IPC::Message& msg) {
    103   if (cross_process_frame_connector_.get() &&
    104       cross_process_frame_connector_->OnMessageReceived(msg))
    105     return true;
    106 
    107   // TODO(nasko): This can be removed once we don't have a swapped out state on
    108   // RenderFrameHosts. See https://crbug.com/357747.
    109   if (render_frame_host_.get())
    110     return render_frame_host_->OnMessageReceived(msg);
    111 
    112   return false;
    113 }
    114 
    115 bool RenderFrameProxyHost::InitRenderFrameProxy() {
    116   // The process may (if we're sharing a process with another host that already
    117   // initialized it) or may not (we have our own process or the old process
    118   // crashed) have been initialized. Calling Init multiple times will be
    119   // ignored, so this is safe.
    120   if (!site_instance_->GetProcess()->Init())
    121     return false;
    122 
    123   DCHECK(GetProcess()->HasConnection());
    124 
    125   int parent_routing_id = MSG_ROUTING_NONE;
    126   if (frame_tree_node_->parent()) {
    127     parent_routing_id = frame_tree_node_->parent()
    128                             ->render_manager()
    129                             ->GetRoutingIdForSiteInstance(site_instance_.get());
    130     CHECK_NE(parent_routing_id, MSG_ROUTING_NONE);
    131   }
    132 
    133   Send(new FrameMsg_NewFrameProxy(routing_id_,
    134                                   parent_routing_id,
    135                                   frame_tree_node_->frame_tree()
    136                                       ->GetRenderViewHost(site_instance_.get())
    137                                       ->GetRoutingID()));
    138 
    139   return true;
    140 }
    141 
    142 void RenderFrameProxyHost::DisownOpener() {
    143   Send(new FrameMsg_DisownOpener(GetRoutingID()));
    144 }
    145 
    146 }  // namespace content
    147