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 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
104 // pending cross-site request, and then installs a CrossSiteEventHandler. | 104 // pending cross-site request, and then installs a CrossSiteEventHandler. |
105 // - When RDH receives a response, the BufferedEventHandler determines whether | 105 // - When RDH receives a response, the BufferedEventHandler determines whether |
106 // it is a download. If so, it sends a message to the new renderer causing | 106 // it is a download. If so, it sends a message to the new renderer causing |
107 // it to cancel the request, and the download proceeds in the download | 107 // it to cancel the request, and the download proceeds in the download |
108 // thread. For now, we stay in a PENDING state (with a pending RVH) until | 108 // thread. For now, we stay in a PENDING state (with a pending RVH) until |
109 // the next DidNavigate event for this TabContents. This isn't ideal, but it | 109 // the next DidNavigate event for this TabContents. This isn't ideal, but it |
110 // doesn't affect any functionality. | 110 // doesn't affect any functionality. |
111 // - After RDH receives a response and determines that it is safe and not a | 111 // - After RDH receives a response and determines that it is safe and not a |
112 // download, it pauses the response to first run the old page's onunload | 112 // download, it pauses the response to first run the old page's onunload |
113 // handler. It does this by asynchronously calling the OnCrossSiteResponse | 113 // handler. It does this by asynchronously calling the OnCrossSiteResponse |
114 // method of TabContents on the UI thread, which sends a ClosePage message | 114 // method of TabContents on the UI thread, which sends a SwapOut message |
115 // to the current RVH. | 115 // to the current RVH. |
116 // - Once the onunload handler is finished, a ClosePage_ACK message is sent to | 116 // - Once the onunload handler is finished, a SwapOut_ACK message is sent to |
117 // the ResourceDispatcherHost, who unpauses the response. Data is then sent | 117 // the ResourceDispatcherHost, who unpauses the response. Data is then sent |
118 // to the pending RVH. | 118 // to the pending RVH. |
119 // - The pending renderer sends a FrameNavigate message that invokes the | 119 // - The pending renderer sends a FrameNavigate message that invokes the |
120 // DidNavigate method. This replaces the current RVH with the | 120 // DidNavigate method. This replaces the current RVH with the |
121 // pending RVH and goes back to the NORMAL RendererState. | 121 // pending RVH and goes back to the NORMAL RendererState. |
| 122 // - The previous renderer is kept swapped out in RenderViewHostManager in case |
| 123 // the user goes back. The process only stays live if another tab is using |
| 124 // it, but if so, the existing frame relationships will be maintained. |
122 | 125 |
123 namespace { | 126 namespace { |
124 | 127 |
125 // Amount of time we wait between when a key event is received and the renderer | 128 // Amount of time we wait between when a key event is received and the renderer |
126 // is queried for its state and pushed to the NavigationEntry. | 129 // is queried for its state and pushed to the NavigationEntry. |
127 const int kQueryStateDelay = 5000; | 130 const int kQueryStateDelay = 5000; |
128 | 131 |
129 const int kSyncWaitDelay = 40; | 132 const int kSyncWaitDelay = 40; |
130 | 133 |
131 // The list of prefs we want to observe. | 134 // The list of prefs we want to observe. |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
252 base_tab_contents->view()->GetContainerSize() : gfx::Size()); | 255 base_tab_contents->view()->GetContainerSize() : gfx::Size()); |
253 | 256 |
254 // Register for notifications about all interested prefs change. | 257 // Register for notifications about all interested prefs change. |
255 PrefService* prefs = profile->GetPrefs(); | 258 PrefService* prefs = profile->GetPrefs(); |
256 pref_change_registrar_.Init(prefs); | 259 pref_change_registrar_.Init(prefs); |
257 if (prefs) { | 260 if (prefs) { |
258 for (int i = 0; i < kPrefsToObserveLength; ++i) | 261 for (int i = 0; i < kPrefsToObserveLength; ++i) |
259 pref_change_registrar_.Add(kPrefsToObserve[i], this); | 262 pref_change_registrar_.Add(kPrefsToObserve[i], this); |
260 } | 263 } |
261 | 264 |
| 265 registrar_.Add(this, NotificationType::RENDERER_PROCESS_CLOSING, |
| 266 NotificationService::AllSources()); |
262 registrar_.Add(this, NotificationType::RENDER_WIDGET_HOST_DESTROYED, | 267 registrar_.Add(this, NotificationType::RENDER_WIDGET_HOST_DESTROYED, |
263 NotificationService::AllSources()); | 268 NotificationService::AllSources()); |
264 #if defined(OS_LINUX) | 269 #if defined(OS_LINUX) |
265 registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED, | 270 registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED, |
266 NotificationService::AllSources()); | 271 NotificationService::AllSources()); |
267 #endif | 272 #endif |
268 | 273 |
269 registrar_.Add(this, NotificationType::USER_STYLE_SHEET_UPDATED, | 274 registrar_.Add(this, NotificationType::USER_STYLE_SHEET_UPDATED, |
270 NotificationService::AllSources()); | 275 NotificationService::AllSources()); |
271 | 276 |
(...skipping 1423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1695 | 1700 |
1696 // Run post-commit tasks. | 1701 // Run post-commit tasks. |
1697 if (details.is_main_frame) | 1702 if (details.is_main_frame) |
1698 DidNavigateMainFramePostCommit(details, params); | 1703 DidNavigateMainFramePostCommit(details, params); |
1699 DidNavigateAnyFramePostCommit(rvh, details, params); | 1704 DidNavigateAnyFramePostCommit(rvh, details, params); |
1700 } | 1705 } |
1701 | 1706 |
1702 void TabContents::UpdateState(RenderViewHost* rvh, | 1707 void TabContents::UpdateState(RenderViewHost* rvh, |
1703 int32 page_id, | 1708 int32 page_id, |
1704 const std::string& state) { | 1709 const std::string& state) { |
1705 DCHECK(rvh == render_view_host()); | 1710 // Ensure that this state update comes from either the active RVH or one of |
| 1711 // the swapped out RVHs. We don't expect to hear from any other RVHs. |
| 1712 DCHECK(rvh == render_view_host() || render_manager_.IsSwappedOut(rvh)); |
1706 | 1713 |
1707 // We must be prepared to handle state updates for any page, these occur | 1714 // We must be prepared to handle state updates for any page, these occur |
1708 // when the user is scrolling and entering form data, as well as when we're | 1715 // when the user is scrolling and entering form data, as well as when we're |
1709 // leaving a page, in which case our state may have already been moved to | 1716 // leaving a page, in which case our state may have already been moved to |
1710 // the next page. The navigation controller will look up the appropriate | 1717 // the next page. The navigation controller will look up the appropriate |
1711 // NavigationEntry and update it when it is notified via the delegate. | 1718 // NavigationEntry and update it when it is notified via the delegate. |
1712 | 1719 |
1713 int entry_index = controller_.GetEntryIndexWithPageID( | 1720 int entry_index = controller_.GetEntryIndexWithPageID( |
1714 GetSiteInstance(), page_id); | 1721 rvh->site_instance(), page_id); |
1715 if (entry_index < 0) | 1722 if (entry_index < 0) |
1716 return; | 1723 return; |
1717 NavigationEntry* entry = controller_.GetEntryAtIndex(entry_index); | 1724 NavigationEntry* entry = controller_.GetEntryAtIndex(entry_index); |
1718 | 1725 |
1719 if (state == entry->content_state()) | 1726 if (state == entry->content_state()) |
1720 return; // Nothing to update. | 1727 return; // Nothing to update. |
1721 entry->set_content_state(state); | 1728 entry->set_content_state(state); |
1722 controller_.NotifyEntryChanged(entry, entry_index); | 1729 controller_.NotifyEntryChanged(entry, entry_index); |
1723 } | 1730 } |
1724 | 1731 |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1866 } | 1873 } |
1867 | 1874 |
1868 void TabContents::ProcessExternalHostMessage(const std::string& message, | 1875 void TabContents::ProcessExternalHostMessage(const std::string& message, |
1869 const std::string& origin, | 1876 const std::string& origin, |
1870 const std::string& target) { | 1877 const std::string& target) { |
1871 if (delegate()) | 1878 if (delegate()) |
1872 delegate()->ForwardMessageToExternalHost(message, origin, target); | 1879 delegate()->ForwardMessageToExternalHost(message, origin, target); |
1873 } | 1880 } |
1874 | 1881 |
1875 void TabContents::RunJavaScriptMessage( | 1882 void TabContents::RunJavaScriptMessage( |
| 1883 const RenderViewHost* rvh, |
1876 const std::wstring& message, | 1884 const std::wstring& message, |
1877 const std::wstring& default_prompt, | 1885 const std::wstring& default_prompt, |
1878 const GURL& frame_url, | 1886 const GURL& frame_url, |
1879 const int flags, | 1887 const int flags, |
1880 IPC::Message* reply_msg, | 1888 IPC::Message* reply_msg, |
1881 bool* did_suppress_message) { | 1889 bool* did_suppress_message) { |
1882 // Suppress javascript messages when requested and when inside a constrained | 1890 // Suppress javascript messages when requested and when inside a constrained |
1883 // popup window (because that activates them and breaks them out of the | 1891 // popup window (because that activates them and breaks them out of the |
1884 // constrained window jail). | 1892 // constrained window jail). |
1885 // Also suppress messages when showing an interstitial. The interstitial is | 1893 // Also suppress messages when showing an interstitial. The interstitial is |
1886 // shown over the previous page, we don't want the hidden page dialogs to | 1894 // shown over the previous page, we don't want the hidden page dialogs to |
1887 // interfere with the interstitial. | 1895 // interfere with the interstitial. |
1888 bool suppress_this_message = | 1896 bool suppress_this_message = |
| 1897 rvh->is_swapped_out() || |
1889 suppress_javascript_messages_ || | 1898 suppress_javascript_messages_ || |
1890 showing_interstitial_page() || | 1899 showing_interstitial_page() || |
1891 (delegate() && delegate()->ShouldSuppressDialogs()); | 1900 (delegate() && delegate()->ShouldSuppressDialogs()); |
1892 if (delegate()) | 1901 if (delegate()) |
1893 suppress_this_message |= | 1902 suppress_this_message |= |
1894 (delegate()->GetConstrainingContents(this) != this); | 1903 (delegate()->GetConstrainingContents(this) != this); |
1895 | 1904 |
1896 *did_suppress_message = suppress_this_message; | 1905 *did_suppress_message = suppress_this_message; |
1897 | 1906 |
1898 if (!suppress_this_message) { | 1907 if (!suppress_this_message) { |
1899 base::TimeDelta time_since_last_message( | 1908 base::TimeDelta time_since_last_message( |
1900 base::TimeTicks::Now() - last_javascript_message_dismissal_); | 1909 base::TimeTicks::Now() - last_javascript_message_dismissal_); |
1901 bool show_suppress_checkbox = false; | 1910 bool show_suppress_checkbox = false; |
1902 // Show a checkbox offering to suppress further messages if this message is | 1911 // Show a checkbox offering to suppress further messages if this message is |
1903 // being displayed within kJavascriptMessageExpectedDelay of the last one. | 1912 // being displayed within kJavascriptMessageExpectedDelay of the last one. |
1904 if (time_since_last_message < | 1913 if (time_since_last_message < |
1905 base::TimeDelta::FromMilliseconds( | 1914 base::TimeDelta::FromMilliseconds( |
1906 chrome::kJavascriptMessageExpectedDelay)) | 1915 chrome::kJavascriptMessageExpectedDelay)) |
1907 show_suppress_checkbox = true; | 1916 show_suppress_checkbox = true; |
1908 | 1917 |
1909 RunJavascriptMessageBox(profile(), this, frame_url, flags, message, | 1918 RunJavascriptMessageBox(profile(), this, frame_url, flags, message, |
1910 default_prompt, show_suppress_checkbox, reply_msg); | 1919 default_prompt, show_suppress_checkbox, reply_msg); |
1911 } else { | 1920 } else { |
1912 // If we are suppressing messages, just reply as is if the user immediately | 1921 // If we are suppressing messages, just reply as is if the user immediately |
1913 // pressed "Cancel". | 1922 // pressed "Cancel". |
1914 OnMessageBoxClosed(reply_msg, false, std::wstring()); | 1923 OnMessageBoxClosed(reply_msg, false, std::wstring()); |
1915 } | 1924 } |
1916 } | 1925 } |
1917 | 1926 |
1918 void TabContents::RunBeforeUnloadConfirm(const std::wstring& message, | 1927 void TabContents::RunBeforeUnloadConfirm(const RenderViewHost* rvh, |
| 1928 const std::wstring& message, |
1919 IPC::Message* reply_msg) { | 1929 IPC::Message* reply_msg) { |
1920 if (delegate()) | 1930 if (delegate()) |
1921 delegate()->WillRunBeforeUnloadConfirm(); | 1931 delegate()->WillRunBeforeUnloadConfirm(); |
1922 if (delegate() && delegate()->ShouldSuppressDialogs()) { | 1932 bool suppress_this_message = rvh->is_swapped_out() || |
| 1933 (delegate() && delegate()->ShouldSuppressDialogs()); |
| 1934 if (suppress_this_message) { |
1923 render_view_host()->JavaScriptMessageBoxClosed(reply_msg, true, | 1935 render_view_host()->JavaScriptMessageBoxClosed(reply_msg, true, |
1924 std::wstring()); | 1936 std::wstring()); |
1925 return; | 1937 return; |
1926 } | 1938 } |
1927 is_showing_before_unload_dialog_ = true; | 1939 is_showing_before_unload_dialog_ = true; |
1928 RunBeforeUnloadDialog(this, message, reply_msg); | 1940 RunBeforeUnloadDialog(this, message, reply_msg); |
1929 } | 1941 } |
1930 | 1942 |
1931 GURL TabContents::GetAlternateErrorPageURL() const { | 1943 GURL TabContents::GetAlternateErrorPageURL() const { |
1932 return content::GetContentClient()->browser()->GetAlternateErrorPageURL(this); | 1944 return content::GetContentClient()->browser()->GetAlternateErrorPageURL(this); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1976 int new_request_id) { | 1988 int new_request_id) { |
1977 // Allows the TabContents to react when a cross-site response is ready to be | 1989 // Allows the TabContents to react when a cross-site response is ready to be |
1978 // delivered to a pending RenderViewHost. We must first run the onunload | 1990 // delivered to a pending RenderViewHost. We must first run the onunload |
1979 // handler of the old RenderViewHost before we can allow it to proceed. | 1991 // handler of the old RenderViewHost before we can allow it to proceed. |
1980 render_manager_.OnCrossSiteResponse(new_render_process_host_id, | 1992 render_manager_.OnCrossSiteResponse(new_render_process_host_id, |
1981 new_request_id); | 1993 new_request_id); |
1982 } | 1994 } |
1983 | 1995 |
1984 void TabContents::RendererUnresponsive(RenderViewHost* rvh, | 1996 void TabContents::RendererUnresponsive(RenderViewHost* rvh, |
1985 bool is_during_unload) { | 1997 bool is_during_unload) { |
| 1998 // Don't show hung renderer dialog for a swapped out RVH. |
| 1999 if (rvh != render_view_host()) |
| 2000 return; |
| 2001 |
1986 if (is_during_unload) { | 2002 if (is_during_unload) { |
1987 // Hang occurred while firing the beforeunload/unload handler. | 2003 // Hang occurred while firing the beforeunload/unload handler. |
1988 // Pretend the handler fired so tab closing continues as if it had. | 2004 // Pretend the handler fired so tab closing continues as if it had. |
1989 rvh->set_sudden_termination_allowed(true); | 2005 rvh->set_sudden_termination_allowed(true); |
1990 | 2006 |
1991 if (!render_manager_.ShouldCloseTabOnUnresponsiveRenderer()) | 2007 if (!render_manager_.ShouldCloseTabOnUnresponsiveRenderer()) |
1992 return; | 2008 return; |
1993 | 2009 |
1994 // If the tab hangs in the beforeunload/unload handler there's really | 2010 // If the tab hangs in the beforeunload/unload handler there's really |
1995 // nothing we can do to recover. Pretend the unload listeners have | 2011 // nothing we can do to recover. Pretend the unload listeners have |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2141 UpdateZoomLevel(); | 2157 UpdateZoomLevel(); |
2142 } else if (*pref_name_in == prefs::kEnableReferrers) { | 2158 } else if (*pref_name_in == prefs::kEnableReferrers) { |
2143 renderer_preferences_util::UpdateFromSystemSettings( | 2159 renderer_preferences_util::UpdateFromSystemSettings( |
2144 &renderer_preferences_, profile()); | 2160 &renderer_preferences_, profile()); |
2145 render_view_host()->SyncRendererPrefs(); | 2161 render_view_host()->SyncRendererPrefs(); |
2146 } else { | 2162 } else { |
2147 NOTREACHED() << "unexpected pref change notification" << *pref_name_in; | 2163 NOTREACHED() << "unexpected pref change notification" << *pref_name_in; |
2148 } | 2164 } |
2149 break; | 2165 break; |
2150 } | 2166 } |
| 2167 case NotificationType::RENDERER_PROCESS_CLOSING: |
| 2168 render_manager_.RendererProcessClosing( |
| 2169 Source<RenderProcessHost>(source).ptr()); |
| 2170 break; |
| 2171 |
2151 case NotificationType::RENDER_WIDGET_HOST_DESTROYED: | 2172 case NotificationType::RENDER_WIDGET_HOST_DESTROYED: |
2152 view_->RenderWidgetHostDestroyed(Source<RenderWidgetHost>(source).ptr()); | 2173 view_->RenderWidgetHostDestroyed(Source<RenderWidgetHost>(source).ptr()); |
2153 break; | 2174 break; |
2154 | 2175 |
2155 case NotificationType::NAV_ENTRY_COMMITTED: { | 2176 case NotificationType::NAV_ENTRY_COMMITTED: { |
2156 DCHECK(&controller_ == Source<NavigationController>(source).ptr()); | 2177 DCHECK(&controller_ == Source<NavigationController>(source).ptr()); |
2157 | 2178 |
2158 NavigationController::LoadCommittedDetails& committed_details = | 2179 NavigationController::LoadCommittedDetails& committed_details = |
2159 *(Details<NavigationController::LoadCommittedDetails>(details).ptr()); | 2180 *(Details<NavigationController::LoadCommittedDetails>(details).ptr()); |
2160 ExpireInfoBars(committed_details); | 2181 ExpireInfoBars(committed_details); |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2240 | 2261 |
2241 void TabContents::CreateViewAndSetSizeForRVH(RenderViewHost* rvh) { | 2262 void TabContents::CreateViewAndSetSizeForRVH(RenderViewHost* rvh) { |
2242 RenderWidgetHostView* rwh_view = view()->CreateViewForWidget(rvh); | 2263 RenderWidgetHostView* rwh_view = view()->CreateViewForWidget(rvh); |
2243 rwh_view->SetSize(view()->GetContainerSize()); | 2264 rwh_view->SetSize(view()->GetContainerSize()); |
2244 } | 2265 } |
2245 | 2266 |
2246 void TabContents::OnOnlineStateChanged(bool online) { | 2267 void TabContents::OnOnlineStateChanged(bool online) { |
2247 render_view_host()->Send(new ViewMsg_NetworkStateChanged( | 2268 render_view_host()->Send(new ViewMsg_NetworkStateChanged( |
2248 render_view_host()->routing_id(), online)); | 2269 render_view_host()->routing_id(), online)); |
2249 } | 2270 } |
OLD | NEW |