| 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 |