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