| 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 1565 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1693 | 1696 |
| 1694 // Run post-commit tasks. | 1697 // Run post-commit tasks. |
| 1695 if (details.is_main_frame) | 1698 if (details.is_main_frame) |
| 1696 DidNavigateMainFramePostCommit(details, params); | 1699 DidNavigateMainFramePostCommit(details, params); |
| 1697 DidNavigateAnyFramePostCommit(rvh, details, params); | 1700 DidNavigateAnyFramePostCommit(rvh, details, params); |
| 1698 } | 1701 } |
| 1699 | 1702 |
| 1700 void TabContents::UpdateState(RenderViewHost* rvh, | 1703 void TabContents::UpdateState(RenderViewHost* rvh, |
| 1701 int32 page_id, | 1704 int32 page_id, |
| 1702 const std::string& state) { | 1705 const std::string& state) { |
| 1703 DCHECK(rvh == render_view_host()); | 1706 // Ensure that this state update comes from either the active RVH or one of |
| 1707 // the swapped out RVHs. We don't expect to hear from any other RVHs. |
| 1708 DCHECK(rvh == render_view_host() || render_manager_.IsSwappedOut(rvh)); |
| 1704 | 1709 |
| 1705 // We must be prepared to handle state updates for any page, these occur | 1710 // We must be prepared to handle state updates for any page, these occur |
| 1706 // when the user is scrolling and entering form data, as well as when we're | 1711 // when the user is scrolling and entering form data, as well as when we're |
| 1707 // leaving a page, in which case our state may have already been moved to | 1712 // leaving a page, in which case our state may have already been moved to |
| 1708 // the next page. The navigation controller will look up the appropriate | 1713 // the next page. The navigation controller will look up the appropriate |
| 1709 // NavigationEntry and update it when it is notified via the delegate. | 1714 // NavigationEntry and update it when it is notified via the delegate. |
| 1710 | 1715 |
| 1711 int entry_index = controller_.GetEntryIndexWithPageID( | 1716 int entry_index = controller_.GetEntryIndexWithPageID( |
| 1712 GetSiteInstance(), page_id); | 1717 rvh->site_instance(), page_id); |
| 1713 if (entry_index < 0) | 1718 if (entry_index < 0) |
| 1714 return; | 1719 return; |
| 1715 NavigationEntry* entry = controller_.GetEntryAtIndex(entry_index); | 1720 NavigationEntry* entry = controller_.GetEntryAtIndex(entry_index); |
| 1716 | 1721 |
| 1717 if (state == entry->content_state()) | 1722 if (state == entry->content_state()) |
| 1718 return; // Nothing to update. | 1723 return; // Nothing to update. |
| 1719 entry->set_content_state(state); | 1724 entry->set_content_state(state); |
| 1720 controller_.NotifyEntryChanged(entry, entry_index); | 1725 controller_.NotifyEntryChanged(entry, entry_index); |
| 1721 } | 1726 } |
| 1722 | 1727 |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1864 } | 1869 } |
| 1865 | 1870 |
| 1866 void TabContents::ProcessExternalHostMessage(const std::string& message, | 1871 void TabContents::ProcessExternalHostMessage(const std::string& message, |
| 1867 const std::string& origin, | 1872 const std::string& origin, |
| 1868 const std::string& target) { | 1873 const std::string& target) { |
| 1869 if (delegate()) | 1874 if (delegate()) |
| 1870 delegate()->ForwardMessageToExternalHost(message, origin, target); | 1875 delegate()->ForwardMessageToExternalHost(message, origin, target); |
| 1871 } | 1876 } |
| 1872 | 1877 |
| 1873 void TabContents::RunJavaScriptMessage( | 1878 void TabContents::RunJavaScriptMessage( |
| 1879 const RenderViewHost* rvh, |
| 1874 const std::wstring& message, | 1880 const std::wstring& message, |
| 1875 const std::wstring& default_prompt, | 1881 const std::wstring& default_prompt, |
| 1876 const GURL& frame_url, | 1882 const GURL& frame_url, |
| 1877 const int flags, | 1883 const int flags, |
| 1878 IPC::Message* reply_msg, | 1884 IPC::Message* reply_msg, |
| 1879 bool* did_suppress_message) { | 1885 bool* did_suppress_message) { |
| 1880 // Suppress javascript messages when requested and when inside a constrained | 1886 // Suppress javascript messages when requested and when inside a constrained |
| 1881 // popup window (because that activates them and breaks them out of the | 1887 // popup window (because that activates them and breaks them out of the |
| 1882 // constrained window jail). | 1888 // constrained window jail). |
| 1883 // Also suppress messages when showing an interstitial. The interstitial is | 1889 // Also suppress messages when showing an interstitial. The interstitial is |
| 1884 // shown over the previous page, we don't want the hidden page dialogs to | 1890 // shown over the previous page, we don't want the hidden page dialogs to |
| 1885 // interfere with the interstitial. | 1891 // interfere with the interstitial. |
| 1886 bool suppress_this_message = | 1892 bool suppress_this_message = |
| 1893 rvh->is_swapped_out() || |
| 1887 suppress_javascript_messages_ || | 1894 suppress_javascript_messages_ || |
| 1888 showing_interstitial_page() || | 1895 showing_interstitial_page() || |
| 1889 (delegate() && delegate()->ShouldSuppressDialogs()); | 1896 (delegate() && delegate()->ShouldSuppressDialogs()); |
| 1890 if (delegate()) | 1897 if (delegate()) |
| 1891 suppress_this_message |= | 1898 suppress_this_message |= |
| 1892 (delegate()->GetConstrainingContents(this) != this); | 1899 (delegate()->GetConstrainingContents(this) != this); |
| 1893 | 1900 |
| 1894 *did_suppress_message = suppress_this_message; | 1901 *did_suppress_message = suppress_this_message; |
| 1895 | 1902 |
| 1896 if (!suppress_this_message) { | 1903 if (!suppress_this_message) { |
| 1897 base::TimeDelta time_since_last_message( | 1904 base::TimeDelta time_since_last_message( |
| 1898 base::TimeTicks::Now() - last_javascript_message_dismissal_); | 1905 base::TimeTicks::Now() - last_javascript_message_dismissal_); |
| 1899 bool show_suppress_checkbox = false; | 1906 bool show_suppress_checkbox = false; |
| 1900 // Show a checkbox offering to suppress further messages if this message is | 1907 // Show a checkbox offering to suppress further messages if this message is |
| 1901 // being displayed within kJavascriptMessageExpectedDelay of the last one. | 1908 // being displayed within kJavascriptMessageExpectedDelay of the last one. |
| 1902 if (time_since_last_message < | 1909 if (time_since_last_message < |
| 1903 base::TimeDelta::FromMilliseconds( | 1910 base::TimeDelta::FromMilliseconds( |
| 1904 chrome::kJavascriptMessageExpectedDelay)) | 1911 chrome::kJavascriptMessageExpectedDelay)) |
| 1905 show_suppress_checkbox = true; | 1912 show_suppress_checkbox = true; |
| 1906 | 1913 |
| 1907 RunJavascriptMessageBox(profile(), this, frame_url, flags, message, | 1914 RunJavascriptMessageBox(profile(), this, frame_url, flags, message, |
| 1908 default_prompt, show_suppress_checkbox, reply_msg); | 1915 default_prompt, show_suppress_checkbox, reply_msg); |
| 1909 } else { | 1916 } else { |
| 1910 // If we are suppressing messages, just reply as is if the user immediately | 1917 // If we are suppressing messages, just reply as is if the user immediately |
| 1911 // pressed "Cancel". | 1918 // pressed "Cancel". |
| 1912 OnMessageBoxClosed(reply_msg, false, std::wstring()); | 1919 OnMessageBoxClosed(reply_msg, false, std::wstring()); |
| 1913 } | 1920 } |
| 1914 } | 1921 } |
| 1915 | 1922 |
| 1916 void TabContents::RunBeforeUnloadConfirm(const std::wstring& message, | 1923 void TabContents::RunBeforeUnloadConfirm(const RenderViewHost* rvh, |
| 1924 const std::wstring& message, |
| 1917 IPC::Message* reply_msg) { | 1925 IPC::Message* reply_msg) { |
| 1918 if (delegate()) | 1926 if (delegate()) |
| 1919 delegate()->WillRunBeforeUnloadConfirm(); | 1927 delegate()->WillRunBeforeUnloadConfirm(); |
| 1920 if (delegate() && delegate()->ShouldSuppressDialogs()) { | 1928 bool suppress_this_message = rvh->is_swapped_out() || |
| 1929 (delegate() && delegate()->ShouldSuppressDialogs()); |
| 1930 if (suppress_this_message) { |
| 1921 render_view_host()->JavaScriptMessageBoxClosed(reply_msg, true, | 1931 render_view_host()->JavaScriptMessageBoxClosed(reply_msg, true, |
| 1922 std::wstring()); | 1932 std::wstring()); |
| 1923 return; | 1933 return; |
| 1924 } | 1934 } |
| 1925 is_showing_before_unload_dialog_ = true; | 1935 is_showing_before_unload_dialog_ = true; |
| 1926 RunBeforeUnloadDialog(this, message, reply_msg); | 1936 RunBeforeUnloadDialog(this, message, reply_msg); |
| 1927 } | 1937 } |
| 1928 | 1938 |
| 1929 GURL TabContents::GetAlternateErrorPageURL() const { | 1939 GURL TabContents::GetAlternateErrorPageURL() const { |
| 1930 return content::GetContentClient()->browser()->GetAlternateErrorPageURL(this); | 1940 return content::GetContentClient()->browser()->GetAlternateErrorPageURL(this); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1974 int new_request_id) { | 1984 int new_request_id) { |
| 1975 // Allows the TabContents to react when a cross-site response is ready to be | 1985 // Allows the TabContents to react when a cross-site response is ready to be |
| 1976 // delivered to a pending RenderViewHost. We must first run the onunload | 1986 // delivered to a pending RenderViewHost. We must first run the onunload |
| 1977 // handler of the old RenderViewHost before we can allow it to proceed. | 1987 // handler of the old RenderViewHost before we can allow it to proceed. |
| 1978 render_manager_.OnCrossSiteResponse(new_render_process_host_id, | 1988 render_manager_.OnCrossSiteResponse(new_render_process_host_id, |
| 1979 new_request_id); | 1989 new_request_id); |
| 1980 } | 1990 } |
| 1981 | 1991 |
| 1982 void TabContents::RendererUnresponsive(RenderViewHost* rvh, | 1992 void TabContents::RendererUnresponsive(RenderViewHost* rvh, |
| 1983 bool is_during_unload) { | 1993 bool is_during_unload) { |
| 1994 // Don't show hung renderer dialog for a swapped out RVH. |
| 1995 if (rvh != render_view_host()) |
| 1996 return; |
| 1997 |
| 1984 if (is_during_unload) { | 1998 if (is_during_unload) { |
| 1985 // Hang occurred while firing the beforeunload/unload handler. | 1999 // Hang occurred while firing the beforeunload/unload handler. |
| 1986 // Pretend the handler fired so tab closing continues as if it had. | 2000 // Pretend the handler fired so tab closing continues as if it had. |
| 1987 rvh->set_sudden_termination_allowed(true); | 2001 rvh->set_sudden_termination_allowed(true); |
| 1988 | 2002 |
| 1989 if (!render_manager_.ShouldCloseTabOnUnresponsiveRenderer()) | 2003 if (!render_manager_.ShouldCloseTabOnUnresponsiveRenderer()) |
| 1990 return; | 2004 return; |
| 1991 | 2005 |
| 1992 // If the tab hangs in the beforeunload/unload handler there's really | 2006 // If the tab hangs in the beforeunload/unload handler there's really |
| 1993 // nothing we can do to recover. Pretend the unload listeners have | 2007 // nothing we can do to recover. Pretend the unload listeners have |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2238 | 2252 |
| 2239 void TabContents::CreateViewAndSetSizeForRVH(RenderViewHost* rvh) { | 2253 void TabContents::CreateViewAndSetSizeForRVH(RenderViewHost* rvh) { |
| 2240 RenderWidgetHostView* rwh_view = view()->CreateViewForWidget(rvh); | 2254 RenderWidgetHostView* rwh_view = view()->CreateViewForWidget(rvh); |
| 2241 rwh_view->SetSize(view()->GetContainerSize()); | 2255 rwh_view->SetSize(view()->GetContainerSize()); |
| 2242 } | 2256 } |
| 2243 | 2257 |
| 2244 void TabContents::OnOnlineStateChanged(bool online) { | 2258 void TabContents::OnOnlineStateChanged(bool online) { |
| 2245 render_view_host()->Send(new ViewMsg_NetworkStateChanged( | 2259 render_view_host()->Send(new ViewMsg_NetworkStateChanged( |
| 2246 render_view_host()->routing_id(), online)); | 2260 render_view_host()->routing_id(), online)); |
| 2247 } | 2261 } |
| OLD | NEW |