Index: content/renderer/render_view.cc |
diff --git a/content/renderer/render_view.cc b/content/renderer/render_view.cc |
index 489ad2ba3077f6b1aad5ef8be03c7c9483dfa1d6..28860ee09a6355dba3618e45af7475fe21717c2f 100644 |
--- a/content/renderer/render_view.cc |
+++ b/content/renderer/render_view.cc |
@@ -635,6 +635,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, |
@@ -688,6 +689,11 @@ 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; |
@@ -1571,6 +1577,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. |
@@ -1935,6 +1947,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. |
@@ -3630,7 +3648,34 @@ 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 WasHidden 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(); |
+ |
+ // Swap out and stop sending any IPC messages that are not ACKs. |
+ SetSwappedOut(true); |
+ |
+ // Replace the page with a blank dummy URL, triggering the unload handler. |
+ // 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 |
@@ -3640,8 +3685,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() { |