OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/tab_contents/tab_contents.h" | 5 #include "content/browser/tab_contents/tab_contents.h" |
6 | 6 |
7 #include <cmath> | 7 #include <cmath> |
8 | 8 |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 // pending cross-site request, and then installs a CrossSiteEventHandler. | 100 // pending cross-site request, and then installs a CrossSiteEventHandler. |
101 // - When RDH receives a response, the BufferedEventHandler determines whether | 101 // - When RDH receives a response, the BufferedEventHandler determines whether |
102 // it is a download. If so, it sends a message to the new renderer causing | 102 // it is a download. If so, it sends a message to the new renderer causing |
103 // it to cancel the request, and the download proceeds in the download | 103 // it to cancel the request, and the download proceeds in the download |
104 // thread. For now, we stay in a PENDING state (with a pending RVH) until | 104 // thread. For now, we stay in a PENDING state (with a pending RVH) until |
105 // the next DidNavigate event for this TabContents. This isn't ideal, but it | 105 // the next DidNavigate event for this TabContents. This isn't ideal, but it |
106 // doesn't affect any functionality. | 106 // doesn't affect any functionality. |
107 // - After RDH receives a response and determines that it is safe and not a | 107 // - After RDH receives a response and determines that it is safe and not a |
108 // download, it pauses the response to first run the old page's onunload | 108 // download, it pauses the response to first run the old page's onunload |
109 // handler. It does this by asynchronously calling the OnCrossSiteResponse | 109 // handler. It does this by asynchronously calling the OnCrossSiteResponse |
110 // method of TabContents on the UI thread, which sends a ClosePage message | 110 // method of TabContents on the UI thread, which sends a SwapOut message |
111 // to the current RVH. | 111 // to the current RVH. |
112 // - Once the onunload handler is finished, a ClosePage_ACK message is sent to | 112 // - Once the onunload handler is finished, a SwapOut_ACK message is sent to |
113 // the ResourceDispatcherHost, who unpauses the response. Data is then sent | 113 // the ResourceDispatcherHost, who unpauses the response. Data is then sent |
114 // to the pending RVH. | 114 // to the pending RVH. |
115 // - The pending renderer sends a FrameNavigate message that invokes the | 115 // - The pending renderer sends a FrameNavigate message that invokes the |
116 // DidNavigate method. This replaces the current RVH with the | 116 // DidNavigate method. This replaces the current RVH with the |
117 // pending RVH and goes back to the NORMAL RendererState. | 117 // pending RVH and goes back to the NORMAL RendererState. |
| 118 // - The previous renderer is kept swapped out in RenderViewHostManager in case |
| 119 // the user goes back. The process only stays live if another tab is using |
| 120 // it, but if so, the existing frame relationships will be maintained. |
118 | 121 |
119 namespace { | 122 namespace { |
120 | 123 |
121 // Amount of time we wait between when a key event is received and the renderer | 124 // Amount of time we wait between when a key event is received and the renderer |
122 // is queried for its state and pushed to the NavigationEntry. | 125 // is queried for its state and pushed to the NavigationEntry. |
123 const int kQueryStateDelay = 5000; | 126 const int kQueryStateDelay = 5000; |
124 | 127 |
125 const int kSyncWaitDelay = 40; | 128 const int kSyncWaitDelay = 40; |
126 | 129 |
127 // The list of prefs we want to observe. | 130 // The list of prefs we want to observe. |
(...skipping 1568 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1696 | 1699 |
1697 // Run post-commit tasks. | 1700 // Run post-commit tasks. |
1698 if (details.is_main_frame) | 1701 if (details.is_main_frame) |
1699 DidNavigateMainFramePostCommit(details, params); | 1702 DidNavigateMainFramePostCommit(details, params); |
1700 DidNavigateAnyFramePostCommit(rvh, details, params); | 1703 DidNavigateAnyFramePostCommit(rvh, details, params); |
1701 } | 1704 } |
1702 | 1705 |
1703 void TabContents::UpdateState(RenderViewHost* rvh, | 1706 void TabContents::UpdateState(RenderViewHost* rvh, |
1704 int32 page_id, | 1707 int32 page_id, |
1705 const std::string& state) { | 1708 const std::string& state) { |
1706 DCHECK(rvh == render_view_host()); | 1709 // Ensure that this state update comes from either the active RVH or one of |
| 1710 // the swapped out RVHs. We don't expect to hear from any other RVHs. |
| 1711 DCHECK(rvh == render_view_host() || render_manager_.IsSwappedOut(rvh)); |
1707 | 1712 |
1708 // We must be prepared to handle state updates for any page, these occur | 1713 // We must be prepared to handle state updates for any page, these occur |
1709 // when the user is scrolling and entering form data, as well as when we're | 1714 // when the user is scrolling and entering form data, as well as when we're |
1710 // leaving a page, in which case our state may have already been moved to | 1715 // leaving a page, in which case our state may have already been moved to |
1711 // the next page. The navigation controller will look up the appropriate | 1716 // the next page. The navigation controller will look up the appropriate |
1712 // NavigationEntry and update it when it is notified via the delegate. | 1717 // NavigationEntry and update it when it is notified via the delegate. |
1713 | 1718 |
1714 int entry_index = controller_.GetEntryIndexWithPageID( | 1719 int entry_index = controller_.GetEntryIndexWithPageID( |
1715 GetSiteInstance(), page_id); | 1720 rvh->site_instance(), page_id); |
1716 if (entry_index < 0) | 1721 if (entry_index < 0) |
1717 return; | 1722 return; |
1718 NavigationEntry* entry = controller_.GetEntryAtIndex(entry_index); | 1723 NavigationEntry* entry = controller_.GetEntryAtIndex(entry_index); |
1719 | 1724 |
1720 if (state == entry->content_state()) | 1725 if (state == entry->content_state()) |
1721 return; // Nothing to update. | 1726 return; // Nothing to update. |
1722 entry->set_content_state(state); | 1727 entry->set_content_state(state); |
1723 controller_.NotifyEntryChanged(entry, entry_index); | 1728 controller_.NotifyEntryChanged(entry, entry_index); |
1724 } | 1729 } |
1725 | 1730 |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1867 } | 1872 } |
1868 | 1873 |
1869 void TabContents::ProcessExternalHostMessage(const std::string& message, | 1874 void TabContents::ProcessExternalHostMessage(const std::string& message, |
1870 const std::string& origin, | 1875 const std::string& origin, |
1871 const std::string& target) { | 1876 const std::string& target) { |
1872 if (delegate()) | 1877 if (delegate()) |
1873 delegate()->ForwardMessageToExternalHost(message, origin, target); | 1878 delegate()->ForwardMessageToExternalHost(message, origin, target); |
1874 } | 1879 } |
1875 | 1880 |
1876 void TabContents::RunJavaScriptMessage( | 1881 void TabContents::RunJavaScriptMessage( |
| 1882 const RenderViewHost* rvh, |
1877 const std::wstring& message, | 1883 const std::wstring& message, |
1878 const std::wstring& default_prompt, | 1884 const std::wstring& default_prompt, |
1879 const GURL& frame_url, | 1885 const GURL& frame_url, |
1880 const int flags, | 1886 const int flags, |
1881 IPC::Message* reply_msg, | 1887 IPC::Message* reply_msg, |
1882 bool* did_suppress_message) { | 1888 bool* did_suppress_message) { |
1883 // Suppress javascript messages when requested and when inside a constrained | 1889 // Suppress javascript messages when requested and when inside a constrained |
1884 // popup window (because that activates them and breaks them out of the | 1890 // popup window (because that activates them and breaks them out of the |
1885 // constrained window jail). | 1891 // constrained window jail). |
1886 // Also suppress messages when showing an interstitial. The interstitial is | 1892 // Also suppress messages when showing an interstitial. The interstitial is |
1887 // shown over the previous page, we don't want the hidden page dialogs to | 1893 // shown over the previous page, we don't want the hidden page dialogs to |
1888 // interfere with the interstitial. | 1894 // interfere with the interstitial. |
1889 bool suppress_this_message = | 1895 bool suppress_this_message = |
| 1896 rvh->is_swapped_out() || |
1890 suppress_javascript_messages_ || | 1897 suppress_javascript_messages_ || |
1891 showing_interstitial_page() || | 1898 showing_interstitial_page() || |
1892 (delegate() && delegate()->ShouldSuppressDialogs()); | 1899 (delegate() && delegate()->ShouldSuppressDialogs()); |
1893 if (delegate()) | 1900 if (delegate()) |
1894 suppress_this_message |= | 1901 suppress_this_message |= |
1895 (delegate()->GetConstrainingContents(this) != this); | 1902 (delegate()->GetConstrainingContents(this) != this); |
1896 | 1903 |
1897 *did_suppress_message = suppress_this_message; | 1904 *did_suppress_message = suppress_this_message; |
1898 | 1905 |
1899 if (!suppress_this_message) { | 1906 if (!suppress_this_message) { |
1900 base::TimeDelta time_since_last_message( | 1907 base::TimeDelta time_since_last_message( |
1901 base::TimeTicks::Now() - last_javascript_message_dismissal_); | 1908 base::TimeTicks::Now() - last_javascript_message_dismissal_); |
1902 bool show_suppress_checkbox = false; | 1909 bool show_suppress_checkbox = false; |
1903 // Show a checkbox offering to suppress further messages if this message is | 1910 // Show a checkbox offering to suppress further messages if this message is |
1904 // being displayed within kJavascriptMessageExpectedDelay of the last one. | 1911 // being displayed within kJavascriptMessageExpectedDelay of the last one. |
1905 if (time_since_last_message < | 1912 if (time_since_last_message < |
1906 base::TimeDelta::FromMilliseconds( | 1913 base::TimeDelta::FromMilliseconds( |
1907 chrome::kJavascriptMessageExpectedDelay)) | 1914 chrome::kJavascriptMessageExpectedDelay)) |
1908 show_suppress_checkbox = true; | 1915 show_suppress_checkbox = true; |
1909 | 1916 |
1910 RunJavascriptMessageBox(profile(), this, frame_url, flags, message, | 1917 RunJavascriptMessageBox(profile(), this, frame_url, flags, message, |
1911 default_prompt, show_suppress_checkbox, reply_msg); | 1918 default_prompt, show_suppress_checkbox, reply_msg); |
1912 } else { | 1919 } else { |
1913 // If we are suppressing messages, just reply as is if the user immediately | 1920 // If we are suppressing messages, just reply as is if the user immediately |
1914 // pressed "Cancel". | 1921 // pressed "Cancel". |
1915 OnMessageBoxClosed(reply_msg, false, std::wstring()); | 1922 OnMessageBoxClosed(reply_msg, false, std::wstring()); |
1916 } | 1923 } |
1917 } | 1924 } |
1918 | 1925 |
1919 void TabContents::RunBeforeUnloadConfirm(const std::wstring& message, | 1926 void TabContents::RunBeforeUnloadConfirm(const RenderViewHost* rvh, |
| 1927 const std::wstring& message, |
1920 IPC::Message* reply_msg) { | 1928 IPC::Message* reply_msg) { |
1921 if (delegate()) | 1929 if (delegate()) |
1922 delegate()->WillRunBeforeUnloadConfirm(); | 1930 delegate()->WillRunBeforeUnloadConfirm(); |
1923 if (delegate() && delegate()->ShouldSuppressDialogs()) { | 1931 bool suppress_this_message = rvh->is_swapped_out() || |
| 1932 (delegate() && delegate()->ShouldSuppressDialogs()); |
| 1933 if (suppress_this_message) { |
1924 render_view_host()->JavaScriptMessageBoxClosed(reply_msg, true, | 1934 render_view_host()->JavaScriptMessageBoxClosed(reply_msg, true, |
1925 std::wstring()); | 1935 std::wstring()); |
1926 return; | 1936 return; |
1927 } | 1937 } |
1928 is_showing_before_unload_dialog_ = true; | 1938 is_showing_before_unload_dialog_ = true; |
1929 RunBeforeUnloadDialog(this, message, reply_msg); | 1939 RunBeforeUnloadDialog(this, message, reply_msg); |
1930 } | 1940 } |
1931 | 1941 |
1932 GURL TabContents::GetAlternateErrorPageURL() const { | 1942 GURL TabContents::GetAlternateErrorPageURL() const { |
1933 return content::GetContentClient()->browser()->GetAlternateErrorPageURL(this); | 1943 return content::GetContentClient()->browser()->GetAlternateErrorPageURL(this); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1977 int new_request_id) { | 1987 int new_request_id) { |
1978 // Allows the TabContents to react when a cross-site response is ready to be | 1988 // Allows the TabContents to react when a cross-site response is ready to be |
1979 // delivered to a pending RenderViewHost. We must first run the onunload | 1989 // delivered to a pending RenderViewHost. We must first run the onunload |
1980 // handler of the old RenderViewHost before we can allow it to proceed. | 1990 // handler of the old RenderViewHost before we can allow it to proceed. |
1981 render_manager_.OnCrossSiteResponse(new_render_process_host_id, | 1991 render_manager_.OnCrossSiteResponse(new_render_process_host_id, |
1982 new_request_id); | 1992 new_request_id); |
1983 } | 1993 } |
1984 | 1994 |
1985 void TabContents::RendererUnresponsive(RenderViewHost* rvh, | 1995 void TabContents::RendererUnresponsive(RenderViewHost* rvh, |
1986 bool is_during_unload) { | 1996 bool is_during_unload) { |
| 1997 // Don't show hung renderer dialog for a swapped out RVH. |
| 1998 if (rvh != render_view_host()) |
| 1999 return; |
| 2000 |
1987 if (is_during_unload) { | 2001 if (is_during_unload) { |
1988 // Hang occurred while firing the beforeunload/unload handler. | 2002 // Hang occurred while firing the beforeunload/unload handler. |
1989 // Pretend the handler fired so tab closing continues as if it had. | 2003 // Pretend the handler fired so tab closing continues as if it had. |
1990 rvh->set_sudden_termination_allowed(true); | 2004 rvh->set_sudden_termination_allowed(true); |
1991 | 2005 |
1992 if (!render_manager_.ShouldCloseTabOnUnresponsiveRenderer()) | 2006 if (!render_manager_.ShouldCloseTabOnUnresponsiveRenderer()) |
1993 return; | 2007 return; |
1994 | 2008 |
1995 // If the tab hangs in the beforeunload/unload handler there's really | 2009 // If the tab hangs in the beforeunload/unload handler there's really |
1996 // nothing we can do to recover. Pretend the unload listeners have | 2010 // nothing we can do to recover. Pretend the unload listeners have |
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2241 | 2255 |
2242 void TabContents::CreateViewAndSetSizeForRVH(RenderViewHost* rvh) { | 2256 void TabContents::CreateViewAndSetSizeForRVH(RenderViewHost* rvh) { |
2243 RenderWidgetHostView* rwh_view = view()->CreateViewForWidget(rvh); | 2257 RenderWidgetHostView* rwh_view = view()->CreateViewForWidget(rvh); |
2244 rwh_view->SetSize(view()->GetContainerSize()); | 2258 rwh_view->SetSize(view()->GetContainerSize()); |
2245 } | 2259 } |
2246 | 2260 |
2247 void TabContents::OnOnlineStateChanged(bool online) { | 2261 void TabContents::OnOnlineStateChanged(bool online) { |
2248 render_view_host()->Send(new ViewMsg_NetworkStateChanged( | 2262 render_view_host()->Send(new ViewMsg_NetworkStateChanged( |
2249 render_view_host()->routing_id(), online)); | 2263 render_view_host()->routing_id(), online)); |
2250 } | 2264 } |
OLD | NEW |