Chromium Code Reviews| Index: content/renderer/render_view.cc |
| diff --git a/content/renderer/render_view.cc b/content/renderer/render_view.cc |
| index 4eea883eba10f8cfb8c037525c14b427422a00e0..ccc4b70f1d5d5cc6148b19c05ad8ec8c0dd88fb0 100644 |
| --- a/content/renderer/render_view.cc |
| +++ b/content/renderer/render_view.cc |
| @@ -481,6 +481,7 @@ RenderView::RenderView(RenderThreadBase* render_thread, |
| opened_by_user_gesture_(true), |
| opener_suppressed_(false), |
| is_prerendering_(false), |
| + is_swapped_out_(false), |
| page_id_(-1), |
| last_page_id_sent_to_browser_(-1), |
| last_indexed_page_id_(-1), |
| @@ -663,6 +664,15 @@ void RenderView::RemoveObserver(RenderViewObserver* observer) { |
| observers_.RemoveObserver(observer); |
| } |
| +void RenderView::SwapIn() { |
| + DCHECK(is_swapped_out_); |
| + is_swapped_out_ = false; |
| + |
| + // Increment the ChildProcess's ref count now that this RenderView is active |
| + // again. This prevents the process from exiting. |
| + RenderProcess::current()->AddRefProcess(); |
| +} |
| + |
| bool RenderView::RendererAccessibilityNotification::ShouldIncludeChildren() { |
| typedef ViewHostMsg_AccessibilityNotification_Params params; |
| if (type == WebKit::WebAccessibilityNotificationChildrenChanged || |
| @@ -945,6 +955,7 @@ bool RenderView::OnMessageReceived(const IPC::Message& message) { |
| OnGetSerializedHtmlDataForCurrentPageWithLocalLinks) |
| IPC_MESSAGE_HANDLER(ExtensionMsg_GetApplicationInfo, OnGetApplicationInfo) |
| 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_HandleMessageFromExternalHost, |
| @@ -1233,6 +1244,11 @@ void RenderView::OnNavigate(const ViewMsg_Navigate_Params& params) { |
| if (!webview()) |
| return; |
| + // Swap this renderer back in if necessary. |
| + if (is_swapped_out_) { |
| + SwapIn(); |
| + } |
| + |
| history_list_offset_ = params.current_history_list_offset; |
| history_list_length_ = params.current_history_list_length; |
| @@ -1487,6 +1503,14 @@ void RenderView::UpdateURL(WebFrame* frame) { |
| const WebURLRequest& original_request = ds->originalRequest(); |
| const WebURLResponse& response = ds->response(); |
| + // Don't send an update if this renderer is swapped out. |
| + // TODO(creis): This won't be necessary once OnSwapOut is fixed to clear |
| + // the frame without a full navigation. |
| + if (is_swapped_out_) { |
| + DCHECK(request.url() == GURL(chrome::kAboutBlankURL)); |
| + return; |
| + } |
| + |
| NavigationState* navigation_state = NavigationState::FromDataSource(ds); |
| DCHECK(navigation_state); |
| @@ -2176,6 +2200,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. |
| @@ -4427,7 +4457,39 @@ 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) { |
| + // Swap this RenderView out so the tab can navigate to a page rendered by a |
| + // different process. This involves running the unload handler, clearing |
| + // the page, and allowing the process to exit if there are no other active |
| + // RenderViews in it. |
| + DCHECK(!is_swapped_out_); |
| + is_swapped_out_ = true; |
| + |
| + // TODO(davemoore) This code should be removed once willClose() gets |
| + // called when a page is destroyed. page_load_histograms_.Dump() is safe |
| + // to call multiple times for the same frame, but it will simplify things. |
| + page_load_histograms_.Dump(webview()->mainFrame()); |
| + page_load_histograms_.ResetCrossFramePropertyAccess(); |
| + |
| + // Send an UpdateState message before we get swapped out. |
| + SyncNavigationState(); |
| + |
| + // 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 and that can't match an existing URL. |
| + WebURLRequest request(GURL(chrome::kAboutBlankURL)); |
| + webview()->mainFrame()->loadRequest(request); |
|
Charlie Reis
2011/04/13 22:57:21
This is the main sticking point right now. We nee
|
| + |
| + // Just echo back the params in the ACK. |
| + Send(new ViewHostMsg_SwapOut_ACK(routing_id_, params)); |
| + |
| + // Remove this RenderView from the ChildProcess's ref count, allowing the |
| + // process to exit if all of the RenderViews are swapped out. We will |
| + // increment the count if this RenderView is swapped back in. |
| + RenderProcess::current()->ReleaseProcess(); |
| +} |
| + |
| +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 |
| @@ -4442,8 +4504,7 @@ void RenderView::OnClosePage(const ViewMsg_ClosePage_Params& params) { |
| page_load_histograms_.ResetCrossFramePropertyAccess(); |
| 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() { |