Index: content/renderer/render_view.cc |
diff --git a/content/renderer/render_view.cc b/content/renderer/render_view.cc |
index 63c36b4f21837c3273be066e88f452dd857feadf..62b1e999905dfcde2407663a181ed1b4a5900e12 100644 |
--- a/content/renderer/render_view.cc |
+++ b/content/renderer/render_view.cc |
@@ -632,6 +632,7 @@ bool RenderView::OnMessageReceived(const IPC::Message& message) { |
OnEnumerateDirectoryResponse) |
IPC_MESSAGE_HANDLER(ViewMsg_RunFileChooserResponse, OnFileChooserResponse) |
IPC_MESSAGE_HANDLER(ViewMsg_ShouldClose, OnShouldClose) |
+ IPC_MESSAGE_HANDLER(ViewMsg_SwapOut, OnSwapOut) |
IPC_MESSAGE_HANDLER(ViewMsg_ClosePage, OnClosePage) |
IPC_MESSAGE_HANDLER(ViewMsg_ThemeChanged, OnThemeChanged) |
IPC_MESSAGE_HANDLER(ViewMsg_DisassociateFromPopupCount, |
@@ -685,6 +686,10 @@ void RenderView::OnNavigate(const ViewMsg_Navigate_Params& params) { |
if (!webview()) |
return; |
+ // Swap this renderer back in if necessary. |
+ if (is_swapped_out_) |
+ SetSwappedOut(false); |
+ |
history_list_offset_ = params.current_history_list_offset; |
history_list_length_ = params.current_history_list_length; |
@@ -1564,6 +1569,12 @@ bool RenderView::runModalPromptDialog( |
bool RenderView::runModalBeforeUnloadDialog( |
WebFrame* frame, const WebString& message) { |
+ // If we are swapping out, we have already run the beforeunload handler. |
+ // TODO(creis): Fix OnSwapOut to clear the frame without running beforeunload |
+ // at all, to avoid running it twice. |
+ if (is_swapped_out_) |
+ return true; |
+ |
bool success = false; |
// This is an ignored return value, but is included so we can accept the same |
// response as RunJavaScriptMessage. |
@@ -1926,6 +1937,12 @@ void RenderView::loadURLExternally( |
WebNavigationPolicy RenderView::decidePolicyForNavigation( |
WebFrame* frame, const WebURLRequest& request, WebNavigationType type, |
const WebNode&, WebNavigationPolicy default_policy, bool is_redirect) { |
+ // TODO(creis): Remove this when we fix OnSwapOut to not need a navigation. |
+ if (is_swapped_out_) { |
+ DCHECK(request.url() == GURL("about:swappedout")); |
+ return default_policy; |
+ } |
+ |
// Webkit is asking whether to navigate to a new URL. |
// This is fine normally, except if we're showing UI from one security |
// context and they're trying to navigate to a different context. |
@@ -3510,7 +3527,38 @@ void RenderView::OnShouldClose() { |
Send(new ViewHostMsg_ShouldClose_ACK(routing_id_, should_close)); |
} |
-void RenderView::OnClosePage(const ViewMsg_ClosePage_Params& params) { |
+void RenderView::OnSwapOut(const ViewMsg_SwapOut_Params& params) { |
+ if (is_swapped_out_) |
+ return; |
+ |
+ // 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); |
+ |
+ // 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. |
+ webview()->mainFrame()->loadHTMLString(std::string(), |
+ GURL("about:swappedout"), |
+ GURL("about:swappedout"), |
+ false); |
+ |
+ // Just echo back the params in the ACK. |
+ Send(new ViewHostMsg_SwapOut_ACK(routing_id_, params)); |
+} |
+ |
+void RenderView::OnClosePage() { |
// TODO(creis): We'd rather use webview()->Close() here, but that currently |
// sets the WebView's delegate_ to NULL, preventing any JavaScript dialogs |
// in the onunload handler from appearing. For now, we're bypassing that and |
@@ -3520,8 +3568,7 @@ void RenderView::OnClosePage(const ViewMsg_ClosePage_Params& params) { |
// http://b/issue?id=753080. |
webview()->dispatchUnloadEvent(); |
- // Just echo back the params in the ACK. |
- Send(new ViewHostMsg_ClosePage_ACK(routing_id_, params)); |
+ Send(new ViewHostMsg_ClosePage_ACK(routing_id_)); |
} |
void RenderView::OnThemeChanged() { |