| Index: content/renderer/render_view.cc
|
| diff --git a/content/renderer/render_view.cc b/content/renderer/render_view.cc
|
| index 63c36b4f21837c3273be066e88f452dd857feadf..3f5882e6e7264ff21ad420244e0e704508275291 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,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;
|
|
|
| @@ -1484,6 +1490,31 @@ void RenderView::SendPendingAccessibilityNotifications() {
|
| accessibility_ack_pending_ = true;
|
| }
|
|
|
| +bool RenderView::CanSendWhileSwappedOut(IPC::Message* message) {
|
| + // We filter out most IPC messages when swapped out. However, some are
|
| + // important (e.g., ACKs) for keeping the browser and renderer state
|
| + // consistent in case we later return to this renderer.
|
| + switch (message->type()) {
|
| + // RenderView
|
| + case ViewHostMsg_RenderViewGone::ID:
|
| + case ViewHostMsg_ShouldClose_ACK::ID:
|
| + case ViewHostMsg_SwapOut_ACK::ID:
|
| + case ViewHostMsg_ClosePage_ACK::ID:
|
| + return true;
|
| + default:
|
| + break;
|
| + }
|
| +
|
| + // Check with our observers, in case they need to let messages through.
|
| + ObserverListBase<RenderViewObserver>::Iterator it(observers_);
|
| + RenderViewObserver* observer;
|
| + while ((observer = it.GetNext()) != NULL)
|
| + if (observer->CanSendWhileSwappedOut(message))
|
| + return true;
|
| +
|
| + return RenderWidget::CanSendWhileSwappedOut(message);
|
| +}
|
| +
|
| bool RenderView::handleCurrentKeyboardEvent() {
|
| if (edit_commands_.empty())
|
| return false;
|
| @@ -1564,6 +1595,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 +1963,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 +3553,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 +3594,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() {
|
|
|