Move SwapOut methods to RenderFrameHost.

This leaves the state in RenderViewHost for now, to make this an easier
first step.

BUG=304341
TEST=No behavior change.
[email protected]

Review URL: https://codereview.chromium.org/208243019

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@260155 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/content/renderer/accessibility/renderer_accessibility_browsertest.cc b/content/renderer/accessibility/renderer_accessibility_browsertest.cc
index 9916052..95f2c42 100644
--- a/content/renderer/accessibility/renderer_accessibility_browsertest.cc
+++ b/content/renderer/accessibility/renderer_accessibility_browsertest.cc
@@ -350,7 +350,7 @@
   accessibility->HandleAXEvent(
       root_obj,
       ui::AX_EVENT_VALUE_CHANGED);
-  view()->OnSwapOut();
+  view()->main_render_frame()->OnSwapOut();
   accessibility->SendPendingAccessibilityEvents();
   EXPECT_FALSE(sink_->GetUniqueMessageMatching(
       AccessibilityHostMsg_Events::ID));
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 6ec073c..9f3f8eb 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -794,19 +794,24 @@
 
 void RenderFrameImpl::OnSwapOut() {
   // Only run unload if we're not swapped out yet, but send the ack either way.
-  if (!is_swapped_out_) {
-    // Swap this RenderView out so the tab can navigate to a page rendered by a
-    // different process.  This involves running the unload handler and clearing
-    // the page.  Once WasSwappedOut is called, we also allow this process to
-    // exit if there are no other active RenderViews in it.
+  if (!is_swapped_out_ || !render_view_->is_swapped_out_) {
+    // Swap this RenderFrame out so the frame can navigate to a page rendered by
+    // a different process.  This involves running the unload handler and
+    // clearing the page.  Once WasSwappedOut is called, we also allow this
+    // process to exit if there are no other active RenderFrames in it.
 
     // Send an UpdateState message before we get swapped out.
     render_view_->SyncNavigationState();
 
     // Synchronously run the unload handler before sending the ACK.
-    // TODO(creis): Add a WebFrame::dispatchUnloadEvent and call it here.
+    // TODO(creis): Move WebView::dispatchUnloadEvent to WebFrame and call it
+    // here to support unload on subframes as well.
+    if (!frame_->parent())
+      render_view_->webview()->dispatchUnloadEvent();
 
     // Swap out and stop sending any IPC messages that are not ACKs.
+    if (!frame_->parent())
+      render_view_->SetSwappedOut(true);
     is_swapped_out_ = true;
 
     // Now that we're swapped out and filtering IPC messages, stop loading to
@@ -815,9 +820,15 @@
     // TODO(creis): Should we be stopping all frames here and using
     // StopAltErrorPageFetcher with RenderView::OnStop, or just stopping this
     // frame?
-    frame_->stopLoading();
+    if (!frame_->parent())
+      render_view_->OnStop();
+    else
+      frame_->stopLoading();
 
-    frame_->setIsRemote(true);
+    // Let subframes know that the frame is now rendered remotely, for the
+    // purposes of compositing and input events.
+    if (frame_->parent())
+      frame_->setIsRemote(true);
 
     // Replace the page with a blank dummy URL. The unload handler will not be
     // run a second time, thanks to a check in FrameLoader::stopLoading.
@@ -825,9 +836,23 @@
     // beforeunload handler. For now, we just run it a second time silently.
     render_view_->NavigateToSwappedOutURL(frame_);
 
-    render_view_->RegisterSwappedOutChildFrame(this);
+    if (frame_->parent())
+      render_view_->RegisterSwappedOutChildFrame(this);
+
+    // Let WebKit know that this view is hidden so it can drop resources and
+    // stop compositing.
+    // TODO(creis): Support this for subframes as well.
+    if (!frame_->parent()) {
+      render_view_->webview()->setVisibilityState(
+          blink::WebPageVisibilityStateHidden, false);
+    }
   }
 
+  // It is now safe to show modal dialogs again.
+  // TODO(creis): Deal with modal dialogs from subframes.
+  if (!frame_->parent())
+    render_view_->suppress_dialogs_until_swap_out_ = false;
+
   Send(new FrameHostMsg_SwapOut_ACK(routing_id_));
 }
 
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index a032b57..e8abca1 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -350,10 +350,14 @@
 
  private:
   friend class RenderFrameObserver;
-  FRIEND_TEST_ALL_PREFIXES(RenderFrameImplTest,
+  FRIEND_TEST_ALL_PREFIXES(RendererAccessibilityTest,
+                           AccessibilityMessagesQueueWhileSwappedOut);
+    FRIEND_TEST_ALL_PREFIXES(RenderFrameImplTest,
                            ShouldUpdateSelectionTextFromContextMenuParams);
   FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest,
                            OnExtendSelectionAndDelete);
+  FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, ReloadWhileSwappedOut);
+  FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, SendSwapOutACK);
   FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest,
                            SetEditableSelectionAndComposition);
 
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc
index 8c8af06..b26266f 100644
--- a/content/renderer/render_view_browsertest.cc
+++ b/content/renderer/render_view_browsertest.cc
@@ -522,22 +522,22 @@
   int initial_page_id = view()->GetPageId();
 
   // Respond to a swap out request.
-  view()->OnSwapOut();
+  view()->main_render_frame()->OnSwapOut();
 
   // Ensure the swap out commits synchronously.
   EXPECT_NE(initial_page_id, view()->GetPageId());
 
   // Check for a valid OnSwapOutACK.
   const IPC::Message* msg = render_thread_->sink().GetUniqueMessageMatching(
-      ViewHostMsg_SwapOut_ACK::ID);
+      FrameHostMsg_SwapOut_ACK::ID);
   ASSERT_TRUE(msg);
 
   // It is possible to get another swap out request.  Ensure that we send
   // an ACK, even if we don't have to do anything else.
   render_thread_->sink().ClearMessages();
-  view()->OnSwapOut();
+  view()->main_render_frame()->OnSwapOut();
   const IPC::Message* msg2 = render_thread_->sink().GetUniqueMessageMatching(
-      ViewHostMsg_SwapOut_ACK::ID);
+      FrameHostMsg_SwapOut_ACK::ID);
   ASSERT_TRUE(msg2);
 
   // If we navigate back to this RenderView, ensure we don't send a state
@@ -590,11 +590,11 @@
   ProcessPendingMessages();
 
   // Respond to a swap out request.
-  view()->OnSwapOut();
+  view()->main_render_frame()->OnSwapOut();
 
   // Check for a OnSwapOutACK.
   const IPC::Message* msg = render_thread_->sink().GetUniqueMessageMatching(
-      ViewHostMsg_SwapOut_ACK::ID);
+      FrameHostMsg_SwapOut_ACK::ID);
   ASSERT_TRUE(msg);
   render_thread_->sink().ClearMessages();
 
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index 7eb91442..40e05441 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -1111,7 +1111,6 @@
     IPC_MESSAGE_HANDLER(ViewMsg_RunFileChooserResponse, OnFileChooserResponse)
     IPC_MESSAGE_HANDLER(ViewMsg_SuppressDialogsUntilSwapOut,
                         OnSuppressDialogsUntilSwapOut)
-    IPC_MESSAGE_HANDLER(ViewMsg_SwapOut, OnSwapOut)
     IPC_MESSAGE_HANDLER(ViewMsg_ClosePage, OnClosePage)
     IPC_MESSAGE_HANDLER(ViewMsg_ThemeChanged, OnThemeChanged)
     IPC_MESSAGE_HANDLER(ViewMsg_MoveOrResizeStarted, OnMoveOrResizeStarted)
@@ -3792,45 +3791,6 @@
   suppress_dialogs_until_swap_out_ = true;
 }
 
-void RenderViewImpl::OnSwapOut() {
-  // Only run unload if we're not swapped out yet, but send the ack either way.
-  if (!is_swapped_out_) {
-    // Swap this RenderView out so the tab can navigate to a page rendered by a
-    // different process.  This involves running the unload handler and clearing
-    // the page.  Once WasSwappedOut is called, we also allow this process to
-    // exit if there are no other active RenderViews in it.
-
-    // Send an UpdateState message before we get swapped out.
-    SyncNavigationState();
-
-    // Synchronously run the unload handler before sending the ACK.
-    webview()->dispatchUnloadEvent();
-
-    // Swap out and stop sending any IPC messages that are not ACKs.
-    SetSwappedOut(true);
-
-    // Now that we're swapped out and filtering IPC messages, stop loading to
-    // ensure that no other in-progress navigation continues.  We do this here
-    // to avoid sending a DidStopLoading message to the browser process.
-    OnStop();
-
-    // Replace the page with a blank dummy URL. The unload handler will not be
-    // run a second time, thanks to a check in FrameLoader::stopLoading.
-    // TODO(creis): Need to add a better way to do this that avoids running the
-    // beforeunload handler. For now, we just run it a second time silently.
-    NavigateToSwappedOutURL(webview()->mainFrame());
-
-    // Let WebKit know that this view is hidden so it can drop resources and
-    // stop compositing.
-    webview()->setVisibilityState(blink::WebPageVisibilityStateHidden, false);
-  }
-
-  // It is now safe to show modal dialogs again.
-  suppress_dialogs_until_swap_out_ = false;
-
-  Send(new ViewHostMsg_SwapOut_ACK(routing_id_));
-}
-
 void RenderViewImpl::NavigateToSwappedOutURL(blink::WebFrame* frame) {
   // We use loadRequest instead of loadHTMLString because the former commits
   // synchronously.  Otherwise a new navigation can interrupt the navigation
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h
index fc89eba..7e5c632 100644
--- a/content/renderer/render_view_impl.h
+++ b/content/renderer/render_view_impl.h
@@ -765,8 +765,6 @@
   FRIEND_TEST_ALL_PREFIXES(ExternalPopupMenuRemoveTest, RemoveOnChange);
   FRIEND_TEST_ALL_PREFIXES(ExternalPopupMenuTest, NormalCase);
   FRIEND_TEST_ALL_PREFIXES(ExternalPopupMenuTest, ShowPopupThenNavigate);
-  FRIEND_TEST_ALL_PREFIXES(RendererAccessibilityTest,
-                           AccessibilityMessagesQueueWhileSwappedOut);
   FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, DecideNavigationPolicyForWebUI);
   FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest,
                            DidFailProvisionalLoadWithErrorForError);
@@ -784,8 +782,6 @@
   FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, OnSetAccessibilityMode);
   FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, OnSetTextDirection);
   FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, OnUpdateWebPreferences);
-  FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, SendSwapOutACK);
-  FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, ReloadWhileSwappedOut);
   FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest,
                            SetEditableSelectionAndComposition);
   FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, StaleNavigationsIgnored);
@@ -946,7 +942,6 @@
   void OnStop();
   void OnStopFinding(StopFindAction action);
   void OnSuppressDialogsUntilSwapOut();
-  void OnSwapOut();
   void OnThemeChanged();
   void OnUpdateTargetURLAck();
   void OnUpdateWebPreferences(const WebPreferences& prefs);
@@ -1019,7 +1014,8 @@
   // RenderFrameObserver.
   void OnNavigate(const FrameMsg_Navigate_Params& params);
 
-  // Make this RenderView show an empty, unscriptable page.
+  // Make the given |frame| show an empty, unscriptable page.
+  // TODO(creis): Move this to RenderFrame.
   void NavigateToSwappedOutURL(blink::WebFrame* frame);
 
   // If we initiated a navigation, this function will populate |document_state|