Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / content / browser / renderer_host / render_view_host_impl.cc
index d485fd9..e87aa72 100644 (file)
@@ -34,7 +34,9 @@
 #include "content/browser/gpu/gpu_surface_tracker.h"
 #include "content/browser/host_zoom_map_impl.h"
 #include "content/browser/loader/resource_dispatcher_host_impl.h"
+#include "content/browser/renderer_host/cross_site_transferring_request.h"
 #include "content/browser/renderer_host/dip_util.h"
+#include "content/browser/renderer_host/input/timeout_monitor.h"
 #include "content/browser/renderer_host/media/audio_renderer_host.h"
 #include "content/browser/renderer_host/render_process_host_impl.h"
 #include "content/browser/renderer_host/render_view_host_delegate.h"
@@ -43,6 +45,7 @@
 #include "content/common/content_switches_internal.h"
 #include "content/common/desktop_notification_messages.h"
 #include "content/common/drag_messages.h"
+#include "content/common/frame_messages.h"
 #include "content/common/input_messages.h"
 #include "content/common/inter_process_time_ticks_converter.h"
 #include "content/common/speech_recognition_messages.h"
@@ -150,6 +153,16 @@ void DismissVirtualKeyboardTask() {
 // RenderViewHost, public:
 
 // static
+bool RenderViewHostImpl::IsRVHStateActive(RenderViewHostImplState rvh_state) {
+  if (rvh_state == STATE_DEFAULT ||
+      rvh_state == STATE_WAITING_FOR_UNLOAD_ACK ||
+      rvh_state == STATE_WAITING_FOR_COMMIT ||
+      rvh_state == STATE_WAITING_FOR_CLOSE)
+    return true;
+  return false;
+}
+
+// static
 RenderViewHost* RenderViewHost::FromID(int render_process_id,
                                        int render_view_id) {
   return RenderViewHostImpl::FromID(render_process_id, render_view_id);
@@ -186,32 +199,35 @@ RenderViewHostImpl::RenderViewHostImpl(
                            instance->GetProcess(),
                            routing_id,
                            hidden),
+      frames_ref_count_(0),
       delegate_(delegate),
       instance_(static_cast<SiteInstanceImpl*>(instance)),
       waiting_for_drag_context_response_(false),
       enabled_bindings_(0),
       navigations_suspended_(false),
       has_accessed_initial_document_(false),
-      is_swapped_out_(swapped_out),
       main_frame_id_(-1),
       main_frame_routing_id_(main_frame_routing_id),
       run_modal_reply_msg_(NULL),
       run_modal_opener_id_(MSG_ROUTING_NONE),
       is_waiting_for_beforeunload_ack_(false),
-      is_waiting_for_unload_ack_(false),
-      has_timed_out_on_unload_(false),
       unload_ack_is_for_cross_site_transition_(false),
       are_javascript_messages_suppressed_(false),
       sudden_termination_allowed_(false),
       render_view_termination_status_(base::TERMINATION_STATUS_STILL_RUNNING),
-      virtual_keyboard_requested_(false) {
+      virtual_keyboard_requested_(false),
+      weak_factory_(this) {
   DCHECK(instance_.get());
   CHECK(delegate_);  // http://crbug.com/82827
 
   GetProcess()->EnableSendQueue();
 
-  if (!swapped_out)
+  if (swapped_out) {
+    rvh_state_ = STATE_SWAPPED_OUT;
+  } else {
+    rvh_state_ = STATE_DEFAULT;
     instance_->increment_active_view_count();
+  }
 
   if (ResourceDispatcherHostImpl::Get()) {
     BrowserThread::PostTask(
@@ -224,6 +240,9 @@ RenderViewHostImpl::RenderViewHostImpl(
 #if defined(OS_ANDROID)
   media_player_manager_.reset(BrowserMediaPlayerManager::Create(this));
 #endif
+
+  unload_event_monitor_timeout_.reset(new TimeoutMonitor(base::Bind(
+      &RenderViewHostImpl::OnSwappedOut, weak_factory_.GetWeakPtr(), true)));
 }
 
 RenderViewHostImpl::~RenderViewHostImpl() {
@@ -243,7 +262,7 @@ RenderViewHostImpl::~RenderViewHostImpl() {
 
   // If this was swapped out, it already decremented the active view
   // count of the SiteInstance it belongs to.
-  if (!is_swapped_out_)
+  if (IsRVHStateActive(rvh_state_))
     instance_->decrement_active_view_count();
 }
 
@@ -294,7 +313,7 @@ bool RenderViewHostImpl::CreateRenderView(
   params.frame_name = frame_name;
   // Ensure the RenderView sets its opener correctly.
   params.opener_route_id = opener_route_id;
-  params.swapped_out = is_swapped_out_;
+  params.swapped_out = !IsRVHStateActive(rvh_state_);
   params.hidden = is_hidden();
   params.next_page_id = next_page_id;
   GetWebScreenInfo(&params.screen_info);
@@ -512,9 +531,8 @@ WebPreferences RenderViewHostImpl::GetWebkitPrefs(const GURL& url) {
 #if !defined(USE_AURA)
   // Force accelerated compositing and 2d canvas off for chrome: and about:
   // pages (unless it's specifically allowed).
-  if ((url.SchemeIs(chrome::kChromeUIScheme) ||
-      (url.SchemeIs(chrome::kAboutScheme) &&
-       url.spec() != kAboutBlankURL)) &&
+  if ((url.SchemeIs(kChromeUIScheme) ||
+       (url.SchemeIs(chrome::kAboutScheme) && url.spec() != kAboutBlankURL)) &&
       !command_line.HasSwitch(switches::kAllowWebUICompositing)) {
     prefs.accelerated_compositing_enabled = false;
     prefs.accelerated_2d_canvas_enabled = false;
@@ -565,64 +583,13 @@ WebPreferences RenderViewHostImpl::GetWebkitPrefs(const GURL& url) {
   return prefs;
 }
 
-void RenderViewHostImpl::Navigate(const ViewMsg_Navigate_Params& params) {
+void RenderViewHostImpl::Navigate(const FrameMsg_Navigate_Params& params) {
   TRACE_EVENT0("renderer_host", "RenderViewHostImpl::Navigate");
-  // Browser plugin guests are not allowed to navigate outside web-safe schemes,
-  // so do not grant them the ability to request additional URLs.
-  if (!GetProcess()->IsGuest()) {
-    ChildProcessSecurityPolicyImpl::GetInstance()->GrantRequestURL(
-        GetProcess()->GetID(), params.url);
-    if (params.url.SchemeIs(kDataScheme) &&
-        params.base_url_for_data_url.SchemeIs(kFileScheme)) {
-      // If 'data:' is used, and we have a 'file:' base url, grant access to
-      // local files.
-      ChildProcessSecurityPolicyImpl::GetInstance()->GrantRequestURL(
-          GetProcess()->GetID(), params.base_url_for_data_url);
-    }
-  }
-
-  // Only send the message if we aren't suspended at the start of a cross-site
-  // request.
-  if (navigations_suspended_) {
-    // Shouldn't be possible to have a second navigation while suspended, since
-    // navigations will only be suspended during a cross-site request.  If a
-    // second navigation occurs, WebContentsImpl will cancel this pending RVH
-    // create a new pending RVH.
-    DCHECK(!suspended_nav_params_.get());
-    suspended_nav_params_.reset(new ViewMsg_Navigate_Params(params));
-  } else {
-    // Get back to a clean state, in case we start a new navigation without
-    // completing a RVH swap or unload handler.
-    SetSwappedOut(false);
-
-    Send(new ViewMsg_Navigate(GetRoutingID(), params));
-  }
-
-  // Force the throbber to start. We do this because WebKit's "started
-  // loading" message will be received asynchronously from the UI of the
-  // browser. But we want to keep the throbber in sync with what's happening
-  // in the UI. For example, we want to start throbbing immediately when the
-  // user naivgates even if the renderer is delayed. There is also an issue
-  // with the throbber starting because the WebUI (which controls whether the
-  // favicon is displayed) happens synchronously. If the start loading
-  // messages was asynchronous, then the default favicon would flash in.
-  //
-  // WebKit doesn't send throb notifications for JavaScript URLs, so we
-  // don't want to either.
-  if (!params.url.SchemeIs(kJavaScriptScheme))
-    delegate_->DidStartLoading(this);
+  delegate_->GetFrameTree()->GetMainFrame()->Navigate(params);
 }
 
 void RenderViewHostImpl::NavigateToURL(const GURL& url) {
-  ViewMsg_Navigate_Params params;
-  params.page_id = -1;
-  params.pending_history_list_offset = -1;
-  params.current_history_list_offset = -1;
-  params.current_history_list_length = 0;
-  params.url = url;
-  params.transition = PAGE_TRANSITION_LINK;
-  params.navigation_type = ViewMsg_Navigate_Type::NORMAL;
-  Navigate(params);
+  delegate_->GetFrameTree()->GetMainFrame()->NavigateToURL(url);
 }
 
 void RenderViewHostImpl::SetNavigationsSuspended(
@@ -636,11 +603,12 @@ void RenderViewHostImpl::SetNavigationsSuspended(
     // There's navigation message params waiting to be sent.  Now that we're not
     // suspended anymore, resume navigation by sending them.  If we were swapped
     // out, we should also stop filtering out the IPC messages now.
-    SetSwappedOut(false);
+    SetState(STATE_DEFAULT);
 
     DCHECK(!proceed_time.is_null());
     suspended_nav_params_->browser_navigation_start = proceed_time;
-    Send(new ViewMsg_Navigate(GetRoutingID(), *suspended_nav_params_.get()));
+    Send(new FrameMsg_Navigate(
+        main_frame_routing_id_, *suspended_nav_params_.get()));
     suspended_nav_params_.reset();
   }
 }
@@ -691,7 +659,7 @@ void RenderViewHostImpl::FirePageBeforeUnload(bool for_cross_site_transition) {
 
 void RenderViewHostImpl::OnCrossSiteResponse(
     const GlobalRequestID& global_request_id,
-    bool is_transfer,
+    scoped_ptr<CrossSiteTransferringRequest> cross_site_transferring_request,
     const std::vector<GURL>& transfer_url_chain,
     const Referrer& referrer,
     PageTransition page_transition,
@@ -707,7 +675,8 @@ void RenderViewHostImpl::OnCrossSiteResponse(
   // but today the frame_id is -1 for the main frame.
   RenderViewHostDelegate::RendererManagement* manager = node ?
       node->render_manager() : delegate_->GetRendererManagementDelegate();
-  manager->OnCrossSiteResponse(this, global_request_id, is_transfer,
+  manager->OnCrossSiteResponse(this, global_request_id,
+                               cross_site_transferring_request.Pass(),
                                transfer_url_chain, referrer, page_transition,
                                frame_id, should_replace_current_entry);
 }
@@ -717,22 +686,14 @@ void RenderViewHostImpl::SuppressDialogsUntilSwapOut() {
 }
 
 void RenderViewHostImpl::SwapOut() {
-  // This will be set back to false in OnSwapOutACK, just before we replace
-  // this RVH with the pending RVH.
-  is_waiting_for_unload_ack_ = true;
-  // Start the hang monitor in case the renderer hangs in the unload handler.
-  // Increment the in-flight event count, to ensure that input events won't
-  // cancel the timeout timer.
-  increment_in_flight_event_count();
-  StartHangMonitorTimeout(TimeDelta::FromMilliseconds(kUnloadTimeoutMS));
+  SetState(STATE_WAITING_FOR_UNLOAD_ACK);
+  unload_event_monitor_timeout_->Start(
+      base::TimeDelta::FromMilliseconds(kUnloadTimeoutMS));
 
   if (IsRenderViewLive()) {
     Send(new ViewMsg_SwapOut(GetRoutingID()));
-  } else {
-    // This RenderViewHost doesn't have a live renderer, so just skip the unload
-    // event.
-    OnSwappedOut(true);
   }
+  delegate_->SwappedOut(this);
 }
 
 void RenderViewHostImpl::OnSwapOutACK() {
@@ -740,36 +701,11 @@ void RenderViewHostImpl::OnSwapOutACK() {
 }
 
 void RenderViewHostImpl::OnSwappedOut(bool timed_out) {
-  // Stop the hang monitor now that the unload handler has finished.
-  decrement_in_flight_event_count();
-  StopHangMonitorTimeout();
-  is_waiting_for_unload_ack_ = false;
-  has_timed_out_on_unload_ = timed_out;
-  delegate_->SwappedOut(this);
-}
-
-void RenderViewHostImpl::WasSwappedOut() {
-  // Don't bother reporting hung state anymore.
-  StopHangMonitorTimeout();
-
-  // If we have timed out on running the unload handler, we consider
-  // the process hung and we should terminate it if there are no other tabs
-  // using the process. If there are other views using this process, the
-  // unresponsive renderer timeout will catch it.
-  bool hung = has_timed_out_on_unload_;
-
-  // Now that we're no longer the active RVH in the tab, start filtering out
-  // most IPC messages.  Usually the renderer will have stopped sending
-  // messages as of OnSwapOutACK.  However, we may have timed out waiting
-  // for that message, and additional IPC messages may keep streaming in.
-  // We filter them out, as long as that won't cause problems (e.g., we
-  // still allow synchronous messages through).
-  SetSwappedOut(true);
-
-  // If we are not running the renderer in process and no other tab is using
-  // the hung process, consider it eligible to be killed, assuming it is a real
-  // process (unit tests don't have real processes).
-  if (hung) {
+  // Ignore spurious swap out ack.
+  if (!IsWaitingForUnloadACK())
+    return;
+  unload_event_monitor_timeout_->Stop();
+  if (timed_out) {
     base::ProcessHandle process_handle = GetProcess()->GetHandle();
     int views = 0;
 
@@ -806,13 +742,50 @@ void RenderViewHostImpl::WasSwappedOut() {
     }
   }
 
-  // Inform the renderer that it can exit if no one else is using it.
+  switch (rvh_state_) {
+    case STATE_WAITING_FOR_UNLOAD_ACK:
+      SetState(STATE_WAITING_FOR_COMMIT);
+      break;
+    case STATE_PENDING_SWAP_OUT:
+      SetState(STATE_SWAPPED_OUT);
+      break;
+    case STATE_PENDING_SHUTDOWN:
+      DCHECK(!pending_shutdown_on_swap_out_.is_null());
+      pending_shutdown_on_swap_out_.Run();
+      break;
+    default:
+      NOTREACHED();
+  }
+}
+
+void RenderViewHostImpl::WasSwappedOut(
+    const base::Closure& pending_delete_on_swap_out) {
   Send(new ViewMsg_WasSwappedOut(GetRoutingID()));
+  if (rvh_state_ == STATE_WAITING_FOR_UNLOAD_ACK) {
+    if (instance_->active_view_count())
+      SetState(STATE_PENDING_SWAP_OUT);
+    else
+      SetPendingShutdown(pending_delete_on_swap_out);
+  } else if (rvh_state_ == STATE_WAITING_FOR_COMMIT) {
+    SetState(STATE_SWAPPED_OUT);
+  } else if (rvh_state_ == STATE_DEFAULT) {
+    // When the RenderView is not live, the RenderFrameHostManager will call
+    // CommitPending directly, without calling SwapOut on the old RVH. This will
+    // cause WasSwappedOut to be called directly on the live old RVH.
+    DCHECK(!IsRenderViewLive());
+    SetState(STATE_SWAPPED_OUT);
+  } else {
+    NOTREACHED();
+  }
+}
+
+void RenderViewHostImpl::SetPendingShutdown(const base::Closure& on_swap_out) {
+  pending_shutdown_on_swap_out_ = on_swap_out;
+  SetState(STATE_PENDING_SHUTDOWN);
 }
 
 void RenderViewHostImpl::ClosePage() {
-  // Start the hang monitor in case the renderer hangs in the unload handler.
-  is_waiting_for_unload_ack_ = true;
+  SetState(STATE_WAITING_FOR_CLOSE);
   StartHangMonitorTimeout(TimeDelta::FromMilliseconds(kUnloadTimeoutMS));
 
   if (IsRenderViewLive()) {
@@ -839,7 +812,6 @@ void RenderViewHostImpl::ClosePage() {
 void RenderViewHostImpl::ClosePageIgnoringUnloadEvents() {
   StopHangMonitorTimeout();
   is_waiting_for_beforeunload_ack_ = false;
-  is_waiting_for_unload_ack_ = false;
 
   sudden_termination_allowed_ = true;
   delegate_->Close(this);
@@ -1012,8 +984,7 @@ void RenderViewHostImpl::JavaScriptDialogClosed(
     bool success,
     const base::string16& user_input) {
   GetProcess()->SetIgnoreInputEvents(false);
-  bool is_waiting =
-      is_waiting_for_beforeunload_ack_ || is_waiting_for_unload_ack_;
+  bool is_waiting = is_waiting_for_beforeunload_ack_ || IsWaitingForUnloadACK();
 
   // If we are executing as part of (before)unload event handling, we don't
   // want to use the regular hung_renderer_delay_ms_ if the user has agreed to
@@ -1036,7 +1007,7 @@ void RenderViewHostImpl::JavaScriptDialogClosed(
   // correctly while waiting for a response.
   if (is_waiting && are_javascript_messages_suppressed_)
     delegate_->RendererUnresponsive(
-        this, is_waiting_for_beforeunload_ack_, is_waiting_for_unload_ack_);
+        this, is_waiting_for_beforeunload_ack_, IsWaitingForUnloadACK());
 }
 
 void RenderViewHostImpl::DragSourceEndedAt(
@@ -1192,7 +1163,7 @@ bool RenderViewHostImpl::OnMessageReceived(const IPC::Message& msg) {
 
   // Filter out most IPC messages if this renderer is swapped out.
   // We still want to handle certain ACKs to keep our state consistent.
-  if (is_swapped_out_) {
+  if (IsSwappedOut()) {
     if (!SwappedOutMessages::CanHandleWhileSwappedOut(msg)) {
       // If this is a synchronous message and we decided not to handle it,
       // we must send an error reply, or else the renderer will be stuck
@@ -1220,7 +1191,6 @@ bool RenderViewHostImpl::OnMessageReceived(const IPC::Message& msg) {
     IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_RunModal, OnRunModal)
     IPC_MESSAGE_HANDLER(ViewHostMsg_RenderViewReady, OnRenderViewReady)
     IPC_MESSAGE_HANDLER(ViewHostMsg_RenderProcessGone, OnRenderProcessGone)
-    IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_FrameNavigate, OnNavigate(msg))
     IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateState, OnUpdateState)
     IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateTitle, OnUpdateTitle)
     IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateEncoding, OnUpdateEncoding)
@@ -1229,8 +1199,6 @@ bool RenderViewHostImpl::OnMessageReceived(const IPC::Message& msg) {
                         OnUpdateInspectorSetting)
     IPC_MESSAGE_HANDLER(ViewHostMsg_Close, OnClose)
     IPC_MESSAGE_HANDLER(ViewHostMsg_RequestMove, OnRequestMove)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_DidStartLoading, OnDidStartLoading)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_DidStopLoading, OnDidStopLoading)
     IPC_MESSAGE_HANDLER(ViewHostMsg_DidChangeLoadProgress,
                         OnDidChangeLoadProgress)
     IPC_MESSAGE_HANDLER(ViewHostMsg_DidDisownOpener, OnDidDisownOpener)
@@ -1238,7 +1206,6 @@ bool RenderViewHostImpl::OnMessageReceived(const IPC::Message& msg) {
                         OnDocumentAvailableInMainFrame)
     IPC_MESSAGE_HANDLER(ViewHostMsg_DocumentOnLoadCompletedInMainFrame,
                         OnDocumentOnLoadCompletedInMainFrame)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_ContextMenu, OnContextMenu)
     IPC_MESSAGE_HANDLER(ViewHostMsg_ToggleFullscreen, OnToggleFullscreen)
     IPC_MESSAGE_HANDLER(ViewHostMsg_OpenURL, OnOpenURL)
     IPC_MESSAGE_HANDLER(ViewHostMsg_DidContentsPreferredSizeChange,
@@ -1360,7 +1327,7 @@ void RenderViewHostImpl::OnShowView(int route_id,
                                     WindowOpenDisposition disposition,
                                     const gfx::Rect& initial_pos,
                                     bool user_gesture) {
-  if (!is_swapped_out_) {
+  if (IsRVHStateActive(rvh_state_)) {
     delegate_->ShowCreatedWindow(
         route_id, disposition, initial_pos, user_gesture);
   }
@@ -1369,13 +1336,13 @@ void RenderViewHostImpl::OnShowView(int route_id,
 
 void RenderViewHostImpl::OnShowWidget(int route_id,
                                       const gfx::Rect& initial_pos) {
-  if (!is_swapped_out_)
+  if (IsRVHStateActive(rvh_state_))
     delegate_->ShowCreatedWidget(route_id, initial_pos);
   Send(new ViewMsg_Move_ACK(route_id));
 }
 
 void RenderViewHostImpl::OnShowFullscreenWidget(int route_id) {
-  if (!is_swapped_out_)
+  if (IsRVHStateActive(rvh_state_))
     delegate_->ShowCreatedFullscreenWidget(route_id);
   Send(new ViewMsg_Move_ACK(route_id));
 }
@@ -1413,11 +1380,9 @@ void RenderViewHostImpl::OnRenderProcessGone(int status, int exit_code) {
   render_view_termination_status_ =
       static_cast<base::TerminationStatus>(status);
 
-  // Reset frame tree state.
-  // TODO(creis): Once subframes can be in different processes, we'll need to
-  // clear just the FrameTreeNodes affected by the crash (and their subtrees).
+  // Reset frame tree state associated with this process.
   main_frame_id_ = -1;
-  delegate_->GetFrameTree()->ResetForMainFrameSwap();
+  delegate_->GetFrameTree()->RenderProcessGone(this);
 
   // Our base class RenderWidgetHost needs to reset some stuff.
   RendererExited(render_view_termination_status_, exit_code);
@@ -1435,97 +1400,10 @@ void RenderViewHostImpl::OnDidStartProvisionalLoadForFrame(
   NOTREACHED();
 }
 
-// Called when the renderer navigates.  For every frame loaded, we'll get this
-// notification containing parameters identifying the navigation.
-//
-// Subframes are identified by the page transition type.  For subframes loaded
-// as part of a wider page load, the page_id will be the same as for the top
-// level frame.  If the user explicitly requests a subframe navigation, we will
-// get a new page_id because we need to create a new navigation entry for that
-// action.
 void RenderViewHostImpl::OnNavigate(const IPC::Message& msg) {
-  // Read the parameters out of the IPC message directly to avoid making another
-  // copy when we filter the URLs.
-  PickleIterator iter(msg);
-  ViewHostMsg_FrameNavigate_Params validated_params;
-  if (!IPC::ParamTraits<ViewHostMsg_FrameNavigate_Params>::
-      Read(&msg, &iter, &validated_params))
-    return;
-
-  // If we're waiting for a cross-site beforeunload ack from this renderer and
-  // we receive a Navigate message from the main frame, then the renderer was
-  // navigating already and sent it before hearing the ViewMsg_Stop message.
-  // We do not want to cancel the pending navigation in this case, since the
-  // old page will soon be stopped.  Instead, treat this as a beforeunload ack
-  // to allow the pending navigation to continue.
-  if (is_waiting_for_beforeunload_ack_ &&
-      unload_ack_is_for_cross_site_transition_ &&
-      PageTransitionIsMainFrame(validated_params.transition)) {
-    OnShouldCloseACK(true, send_should_close_start_time_,
-                        base::TimeTicks::Now());
-    return;
-  }
-
-  // If we're waiting for an unload ack from this renderer and we receive a
-  // Navigate message, then the renderer was navigating before it received the
-  // unload request.  It will either respond to the unload request soon or our
-  // timer will expire.  Either way, we should ignore this message, because we
-  // have already committed to closing this renderer.
-  if (is_waiting_for_unload_ack_)
-    return;
-
-  // Cache the main frame id, so we can use it for creating the frame tree
-  // root node when needed.
-  if (PageTransitionIsMainFrame(validated_params.transition)) {
-    if (main_frame_id_ == -1) {
-      main_frame_id_ = validated_params.frame_id;
-    } else {
-      // TODO(nasko): We plan to remove the usage of frame_id in navigation
-      // and move to routing ids. This is in place to ensure that a
-      // renderer is not misbehaving and sending us incorrect data.
-      DCHECK_EQ(main_frame_id_, validated_params.frame_id);
-    }
-  }
-  RenderProcessHost* process = GetProcess();
-
-  // Attempts to commit certain off-limits URL should be caught more strictly
-  // than our FilterURL checks below.  If a renderer violates this policy, it
-  // should be killed.
-  if (!CanCommitURL(validated_params.url)) {
-    VLOG(1) << "Blocked URL " << validated_params.url.spec();
-    validated_params.url = GURL(kAboutBlankURL);
-    RecordAction(base::UserMetricsAction("CanCommitURL_BlockedAndKilled"));
-    // Kills the process.
-    process->ReceivedBadMessage();
-  }
-
-  // Now that something has committed, we don't need to track whether the
-  // initial page has been accessed.
-  has_accessed_initial_document_ = false;
-
-  // Without this check, an evil renderer can trick the browser into creating
-  // a navigation entry for a banned URL.  If the user clicks the back button
-  // followed by the forward button (or clicks reload, or round-trips through
-  // session restore, etc), we'll think that the browser commanded the
-  // renderer to load the URL and grant the renderer the privileges to request
-  // the URL.  To prevent this attack, we block the renderer from inserting
-  // banned URLs into the navigation controller in the first place.
-  process->FilterURL(false, &validated_params.url);
-  process->FilterURL(true, &validated_params.referrer.url);
-  for (std::vector<GURL>::iterator it(validated_params.redirects.begin());
-      it != validated_params.redirects.end(); ++it) {
-    process->FilterURL(false, &(*it));
-  }
-  process->FilterURL(true, &validated_params.searchable_form_url);
-
-  // Without this check, the renderer can trick the browser into using
-  // filenames it can't access in a future session restore.
-  if (!CanAccessFilesOfPageState(validated_params.page_state)) {
-    GetProcess()->ReceivedBadMessage();
-    return;
-  }
-
-  delegate_->DidNavigate(this, validated_params);
+  // TODO(nasko): Forward calls to the top level RenderFrameHost until all
+  // callers of this method on RenderViewHost are removed.
+  delegate_->GetFrameTree()->GetMainFrame()->OnMessageReceived(msg);
 }
 
 void RenderViewHostImpl::OnUpdateState(int32 page_id, const PageState& state) {
@@ -1558,7 +1436,7 @@ void RenderViewHostImpl::OnUpdateEncoding(const std::string& encoding_name) {
 }
 
 void RenderViewHostImpl::OnUpdateTargetURL(int32 page_id, const GURL& url) {
-  if (!is_swapped_out_)
+  if (IsRVHStateActive(rvh_state_))
     delegate_->UpdateTargetURL(page_id, url);
 
   // Send a notification back to the renderer that we are ready to
@@ -1579,19 +1457,11 @@ void RenderViewHostImpl::OnClose() {
 }
 
 void RenderViewHostImpl::OnRequestMove(const gfx::Rect& pos) {
-  if (!is_swapped_out_)
+  if (IsRVHStateActive(rvh_state_))
     delegate_->RequestMove(pos);
   Send(new ViewMsg_Move_ACK(GetRoutingID()));
 }
 
-void RenderViewHostImpl::OnDidStartLoading() {
-  delegate_->DidStartLoading(this);
-}
-
-void RenderViewHostImpl::OnDidStopLoading() {
-  delegate_->DidStopLoading(this);
-}
-
 void RenderViewHostImpl::OnDidChangeLoadProgress(double load_progress) {
   delegate_->DidChangeLoadProgress(load_progress);
 }
@@ -1609,22 +1479,6 @@ void RenderViewHostImpl::OnDocumentOnLoadCompletedInMainFrame(
   delegate_->DocumentOnLoadCompletedInMainFrame(this, page_id);
 }
 
-void RenderViewHostImpl::OnContextMenu(const ContextMenuParams& params) {
-  // Validate the URLs in |params|.  If the renderer can't request the URLs
-  // directly, don't show them in the context menu.
-  ContextMenuParams validated_params(params);
-  RenderProcessHost* process = GetProcess();
-
-  // We don't validate |unfiltered_link_url| so that this field can be used
-  // when users want to copy the original link URL.
-  process->FilterURL(true, &validated_params.link_url);
-  process->FilterURL(true, &validated_params.src_url);
-  process->FilterURL(false, &validated_params.page_url);
-  process->FilterURL(true, &validated_params.frame_url);
-
-  delegate_->ShowContextMenu(validated_params);
-}
-
 void RenderViewHostImpl::OnToggleFullscreen(bool enter_fullscreen) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   delegate_->ToggleFullscreenMode(enter_fullscreen);
@@ -1832,7 +1686,7 @@ void RenderViewHostImpl::OnShouldCloseACK(
   // If this renderer navigated while the beforeunload request was in flight, we
   // may have cleared this state in OnNavigate, in which case we can ignore
   // this message.
-  if (!is_waiting_for_beforeunload_ack_ || is_swapped_out_)
+  if (!is_waiting_for_beforeunload_ack_ || rvh_state_ != STATE_DEFAULT)
     return;
 
   is_waiting_for_beforeunload_ack_ = false;
@@ -1875,7 +1729,7 @@ void RenderViewHostImpl::OnClosePageACK() {
 
 void RenderViewHostImpl::NotifyRendererUnresponsive() {
   delegate_->RendererUnresponsive(
-      this, is_waiting_for_beforeunload_ack_, is_waiting_for_unload_ack_);
+      this, is_waiting_for_beforeunload_ack_, IsWaitingForUnloadACK());
 }
 
 void RenderViewHostImpl::NotifyRendererResponsive() {
@@ -1980,13 +1834,11 @@ void RenderViewHostImpl::ToggleSpeechInput() {
   Send(new InputTagSpeechMsg_ToggleSpeechInput(GetRoutingID()));
 }
 
-bool RenderViewHostImpl::CanCommitURL(const GURL& url) {
-  // TODO(creis): We should also check for WebUI pages here.  Also, when the
-  // out-of-process iframes implementation is ready, we should check for
-  // cross-site URLs that are not allowed to commit in this process.
-
-  // Give the client a chance to disallow URLs from committing.
-  return GetContentClient()->browser()->CanCommitURL(GetProcess(), url);
+bool RenderViewHostImpl::IsWaitingForUnloadACK() const {
+  return rvh_state_ == STATE_WAITING_FOR_UNLOAD_ACK ||
+         rvh_state_ == STATE_WAITING_FOR_CLOSE ||
+         rvh_state_ == STATE_PENDING_SHUTDOWN ||
+         rvh_state_ == STATE_PENDING_SWAP_OUT;
 }
 
 void RenderViewHostImpl::ExitFullscreen() {
@@ -2001,7 +1853,7 @@ WebPreferences RenderViewHostImpl::GetWebkitPreferences() {
 
 void RenderViewHostImpl::DisownOpener() {
   // This should only be called when swapped out.
-  DCHECK(is_swapped_out_);
+  DCHECK(IsSwappedOut());
 
   Send(new ViewMsg_DisownOpener(GetRoutingID()));
 }
@@ -2062,16 +1914,6 @@ void RenderViewHostImpl::DisableAutoResize(const gfx::Size& new_size) {
   Send(new ViewMsg_DisableAutoResize(GetRoutingID(), new_size));
 }
 
-void RenderViewHostImpl::ExecuteCustomContextMenuCommand(
-    int action, const CustomContextMenuContext& context) {
-  Send(new ViewMsg_CustomContextMenuAction(GetRoutingID(), context, action));
-}
-
-void RenderViewHostImpl::NotifyContextMenuClosed(
-    const CustomContextMenuContext& context) {
-  Send(new ViewMsg_ContextMenuClosed(GetRoutingID(), context));
-}
-
 void RenderViewHostImpl::CopyImageAt(int x, int y) {
   Send(new ViewMsg_CopyImageAt(GetRoutingID(), x, y));
 }
@@ -2092,7 +1934,8 @@ void RenderViewHostImpl::NotifyMoveOrResizeStarted() {
 
 void RenderViewHostImpl::OnAccessibilityEvents(
     const std::vector<AccessibilityHostMsg_EventParams>& params) {
-  if (view_ && !is_swapped_out_) {
+  if ((accessibility_mode() & AccessibilityModeFlagPlatform) && view_ &&
+      IsRVHStateActive(rvh_state_)) {
     view_->CreateBrowserAccessibilityManagerIfNeeded();
     BrowserAccessibilityManager* manager =
         view_->GetBrowserAccessibilityManager();
@@ -2124,7 +1967,7 @@ void RenderViewHostImpl::OnAccessibilityEvents(
 
 void RenderViewHostImpl::OnAccessibilityLocationChanges(
     const std::vector<AccessibilityHostMsg_LocationChangeParams>& params) {
-  if (view_ && !is_swapped_out_) {
+  if (view_ && IsRVHStateActive(rvh_state_)) {
     view_->CreateBrowserAccessibilityManagerIfNeeded();
     BrowserAccessibilityManager* manager =
         view_->GetBrowserAccessibilityManager();
@@ -2229,22 +2072,25 @@ void RenderViewHostImpl::OnShowPopup(
 }
 #endif
 
-void RenderViewHostImpl::SetSwappedOut(bool is_swapped_out) {
+void RenderViewHostImpl::SetState(RenderViewHostImplState rvh_state) {
   // We update the number of RenderViews in a SiteInstance when the
-  // swapped out status of this RenderView gets flipped.
-  if (is_swapped_out_ && !is_swapped_out)
+  // swapped out status of this RenderView gets flipped to/from live.
+  if (!IsRVHStateActive(rvh_state_) && IsRVHStateActive(rvh_state))
     instance_->increment_active_view_count();
-  else if (!is_swapped_out_ && is_swapped_out)
+  else if (IsRVHStateActive(rvh_state_) && !IsRVHStateActive(rvh_state))
     instance_->decrement_active_view_count();
 
-  is_swapped_out_ = is_swapped_out;
+  // Whenever we change the RVH state to and from live or swapped out state, we
+  // should not be waiting for beforeunload or unload acks.  We clear them here
+  // to be safe, since they can cause navigations to be ignored in OnNavigate.
+  if (rvh_state == STATE_DEFAULT ||
+      rvh_state == STATE_SWAPPED_OUT ||
+      rvh_state_ == STATE_DEFAULT ||
+      rvh_state_ == STATE_SWAPPED_OUT) {
+    is_waiting_for_beforeunload_ack_ = false;
+  }
+  rvh_state_ = rvh_state;
 
-  // Whenever we change swap out state, we should not be waiting for
-  // beforeunload or unload acks.  We clear them here to be safe, since they
-  // can cause navigations to be ignored in OnNavigate.
-  is_waiting_for_beforeunload_ack_ = false;
-  is_waiting_for_unload_ack_ = false;
-  has_timed_out_on_unload_ = false;
 }
 
 bool RenderViewHostImpl::CanAccessFilesOfPageState(