Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(515)

Side by Side Diff: chrome/renderer/render_view.cc

Issue 159575: Move alternate error page loading out of WebFrame.... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 11 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/renderer/render_view.h ('k') | chrome/test/data/iframe_dns_error.html » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 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 "chrome/renderer/render_view.h" 5 #include "chrome/renderer/render_view.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <string> 8 #include <string>
9 #include <vector> 9 #include <vector>
10 10
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
91 #include "webkit/glue/webview.h" 91 #include "webkit/glue/webview.h"
92 92
93 #if defined(OS_WIN) 93 #if defined(OS_WIN)
94 // TODO(port): these files are currently Windows only because they concern: 94 // TODO(port): these files are currently Windows only because they concern:
95 // * theming 95 // * theming
96 #include "base/gfx/native_theme.h" 96 #include "base/gfx/native_theme.h"
97 #endif 97 #endif
98 98
99 using base::Time; 99 using base::Time;
100 using base::TimeDelta; 100 using base::TimeDelta;
101 using webkit_glue::AltErrorPageResourceFetcher;
101 using webkit_glue::AutofillForm; 102 using webkit_glue::AutofillForm;
102 using webkit_glue::PasswordForm; 103 using webkit_glue::PasswordForm;
103 using webkit_glue::PasswordFormDomManager; 104 using webkit_glue::PasswordFormDomManager;
104 using webkit_glue::SearchableFormData; 105 using webkit_glue::SearchableFormData;
105 using WebKit::WebConsoleMessage; 106 using WebKit::WebConsoleMessage;
106 using WebKit::WebData; 107 using WebKit::WebData;
107 using WebKit::WebDataSource; 108 using WebKit::WebDataSource;
108 using WebKit::WebDragData; 109 using WebKit::WebDragData;
109 using WebKit::WebForm; 110 using WebKit::WebForm;
110 using WebKit::WebHistoryItem; 111 using WebKit::WebHistoryItem;
(...skipping 847 matching lines...) Expand 10 before | Expand all | Expand 10 after
958 } else { 959 } else {
959 // Subframe navigation: the type depends on whether this navigation 960 // Subframe navigation: the type depends on whether this navigation
960 // generated a new session history entry. When they do generate a session 961 // generated a new session history entry. When they do generate a session
961 // history entry, it means the user initiated the navigation and we should 962 // history entry, it means the user initiated the navigation and we should
962 // mark it as such. This test checks if this is the first time UpdateURL 963 // mark it as such. This test checks if this is the first time UpdateURL
963 // has been called since WillNavigateToURL was called to initiate the load. 964 // has been called since WillNavigateToURL was called to initiate the load.
964 if (page_id_ > last_page_id_sent_to_browser_) 965 if (page_id_ > last_page_id_sent_to_browser_)
965 params.transition = PageTransition::MANUAL_SUBFRAME; 966 params.transition = PageTransition::MANUAL_SUBFRAME;
966 else 967 else
967 params.transition = PageTransition::AUTO_SUBFRAME; 968 params.transition = PageTransition::AUTO_SUBFRAME;
969 //XXX navigation_state->set_transition_type(params.transition);
968 970
969 Send(new ViewHostMsg_FrameNavigate(routing_id_, params)); 971 Send(new ViewHostMsg_FrameNavigate(routing_id_, params));
970 } 972 }
971 973
972 last_page_id_sent_to_browser_ = 974 last_page_id_sent_to_browser_ =
973 std::max(last_page_id_sent_to_browser_, page_id_); 975 std::max(last_page_id_sent_to_browser_, page_id_);
974 976
975 // If we end up reusing this WebRequest (for example, due to a #ref click), 977 // If we end up reusing this WebRequest (for example, due to a #ref click),
976 // we don't want the transition type to persist. Just clear it. 978 // we don't want the transition type to persist. Just clear it.
977 navigation_state->set_transition_type(PageTransition::LINK); 979 navigation_state->set_transition_type(PageTransition::LINK);
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
1133 if (event_time != 0.0) 1135 if (event_time != 0.0)
1134 navigation_state->set_request_time(Time::FromDoubleT(event_time)); 1136 navigation_state->set_request_time(Time::FromDoubleT(event_time));
1135 } 1137 }
1136 1138
1137 bool is_top_most = !frame->GetParent(); 1139 bool is_top_most = !frame->GetParent();
1138 if (is_top_most) { 1140 if (is_top_most) {
1139 navigation_gesture_ = gesture; 1141 navigation_gesture_ = gesture;
1140 1142
1141 // Make sure redirect tracking state is clear for the new load. 1143 // Make sure redirect tracking state is clear for the new load.
1142 completed_client_redirect_src_ = GURL(); 1144 completed_client_redirect_src_ = GURL();
1145 } else if (frame->GetParent()->IsLoading()) {
1146 // Take note of AUTO_SUBFRAME loads here, so that we can know how to
1147 // load an error page. See DidFailProvisionalLoadWithError.
1148 navigation_state->set_transition_type(PageTransition::AUTO_SUBFRAME);
1143 } 1149 }
1144 1150
1145 Send(new ViewHostMsg_DidStartProvisionalLoadForFrame( 1151 Send(new ViewHostMsg_DidStartProvisionalLoadForFrame(
1146 routing_id_, is_top_most, ds->request().url())); 1152 routing_id_, is_top_most, ds->request().url()));
1147 } 1153 }
1148 1154
1149 bool RenderView::DidLoadResourceFromMemoryCache(WebView* webview, 1155 bool RenderView::DidLoadResourceFromMemoryCache(WebView* webview,
1150 const WebURLRequest& request, 1156 const WebURLRequest& request,
1151 const WebURLResponse& response, 1157 const WebURLResponse& response,
1152 WebFrame* frame) { 1158 WebFrame* frame) {
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1204 show_repost_interstitial)); 1210 show_repost_interstitial));
1205 1211
1206 // Don't display an error page if this is simply a cancelled load. Aside 1212 // Don't display an error page if this is simply a cancelled load. Aside
1207 // from being dumb, WebCore doesn't expect it and it will cause a crash. 1213 // from being dumb, WebCore doesn't expect it and it will cause a crash.
1208 if (error.reason == net::ERR_ABORTED) 1214 if (error.reason == net::ERR_ABORTED)
1209 return; 1215 return;
1210 1216
1211 // Make sure we never show errors in view source mode. 1217 // Make sure we never show errors in view source mode.
1212 frame->SetInViewSourceMode(false); 1218 frame->SetInViewSourceMode(false);
1213 1219
1220 NavigationState* navigation_state = NavigationState::FromDataSource(ds);
1221
1214 // If this is a failed back/forward/reload navigation, then we need to do a 1222 // If this is a failed back/forward/reload navigation, then we need to do a
1215 // 'replace' load. This is necessary to avoid messing up session history. 1223 // 'replace' load. This is necessary to avoid messing up session history.
1216 // Otherwise, we do a normal load, which simulates a 'go' navigation as far 1224 // Otherwise, we do a normal load, which simulates a 'go' navigation as far
1217 // as session history is concerned. 1225 // as session history is concerned.
1218 bool replace = !NavigationState::FromDataSource(ds)->is_new_navigation(); 1226 //
1227 // AUTO_SUBFRAME loads should always be treated as loads that do not advance
1228 // the page id.
1229 //
1230 bool replace =
1231 navigation_state->pending_page_id() != -1 ||
1232 navigation_state->transition_type() == PageTransition::AUTO_SUBFRAME;
1219 1233
1220 // Use the alternate error page service if this is a DNS failure or 1234 // If we failed on a browser initiated request, then make sure that our error
1221 // connection failure. ERR_CONNECTION_FAILED can be dropped once we no longer 1235 // page load is regarded as the same browser initiated request.
1222 // use winhttp. 1236 if (!navigation_state->is_content_initiated()) {
1223 int ec = error.reason; 1237 pending_navigation_state_.reset(NavigationState::CreateBrowserInitiated(
1224 if (ec == net::ERR_NAME_NOT_RESOLVED || 1238 navigation_state->pending_page_id(),
1225 ec == net::ERR_CONNECTION_FAILED || 1239 navigation_state->transition_type(),
1226 ec == net::ERR_CONNECTION_REFUSED || 1240 navigation_state->request_time()));
1227 ec == net::ERR_ADDRESS_UNREACHABLE ||
1228 ec == net::ERR_TIMED_OUT) {
1229 const GURL& failed_url = error.unreachableURL;
1230 const GURL& error_page_url = GetAlternateErrorPageURL(failed_url,
1231 ec == net::ERR_NAME_NOT_RESOLVED ? WebViewDelegate::DNS_ERROR
1232 : WebViewDelegate::CONNECTION_ERROR);
1233 if (error_page_url.is_valid()) {
1234 // Ask the WebFrame to fetch the alternate error page for us.
1235 frame->LoadAlternateHTMLErrorPage(failed_request, error, error_page_url,
1236 replace, GURL(kUnreachableWebDataURL));
1237 return;
1238 }
1239 } 1241 }
1240 1242
1243 // Provide the user with a more helpful error page?
1244 if (MaybeLoadAlternateErrorPage(frame, error, replace))
1245 return;
1246
1241 // Fallback to a local error page. 1247 // Fallback to a local error page.
1242 LoadNavigationErrorPage(frame, failed_request, error, std::string(), 1248 LoadNavigationErrorPage(frame, failed_request, error, std::string(),
1243 replace); 1249 replace);
1244 } 1250 }
1245 1251
1246 void RenderView::LoadNavigationErrorPage(WebFrame* frame, 1252 void RenderView::LoadNavigationErrorPage(WebFrame* frame,
1247 const WebURLRequest& failed_request, 1253 const WebURLRequest& failed_request,
1248 const WebURLError& error, 1254 const WebURLError& error,
1249 const std::string& html, 1255 const std::string& html,
1250 bool replace) { 1256 bool replace) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1290 UpdateSessionHistory(frame); 1296 UpdateSessionHistory(frame);
1291 1297
1292 // We bump our Page ID to correspond with the new session history entry. 1298 // We bump our Page ID to correspond with the new session history entry.
1293 page_id_ = next_page_id_++; 1299 page_id_ = next_page_id_++;
1294 1300
1295 MessageLoop::current()->PostDelayedTask(FROM_HERE, 1301 MessageLoop::current()->PostDelayedTask(FROM_HERE,
1296 method_factory_.NewRunnableMethod(&RenderView::CapturePageInfo, 1302 method_factory_.NewRunnableMethod(&RenderView::CapturePageInfo,
1297 page_id_, true), 1303 page_id_, true),
1298 kDelayForForcedCaptureMs); 1304 kDelayForForcedCaptureMs);
1299 } else { 1305 } else {
1300 // Inspect the navigation_state on the main frame (set in our Navigate 1306 // Inspect the navigation_state on this frame to see if the navigation
1301 // method) to see if the navigation corresponds to a session history 1307 // corresponds to a session history navigation... Note: |frame| may or
1302 // navigation... Note: |frame| may or may not be the toplevel frame, but 1308 // may not be the toplevel frame, but for the case of capturing session
1303 // for the case of capturing session history, the first committed frame 1309 // history, the first committed frame suffices. We keep track of whether
1304 // suffices. We keep track of whether we've seen this commit before so 1310 // we've seen this commit before so that only capture session history once
1305 // that only capture session history once per navigation. 1311 // per navigation.
1306 // 1312 //
1307 // Note that we need to check if the page ID changed. In the case of a 1313 // Note that we need to check if the page ID changed. In the case of a
1308 // reload, the page ID doesn't change, and UpdateSessionHistory gets the 1314 // reload, the page ID doesn't change, and UpdateSessionHistory gets the
1309 // previous URL and the current page ID, which would be wrong. 1315 // previous URL and the current page ID, which would be wrong.
1310 if (!navigation_state->is_new_navigation() && 1316 if (navigation_state->pending_page_id() != -1 &&
1311 !navigation_state->request_committed() && 1317 navigation_state->pending_page_id() != page_id_ &&
1312 page_id_ != navigation_state->pending_page_id()) { 1318 !navigation_state->request_committed()) {
1313 // This is a successful session history navigation! 1319 // This is a successful session history navigation!
1314 UpdateSessionHistory(frame); 1320 UpdateSessionHistory(frame);
1315 page_id_ = navigation_state->pending_page_id(); 1321 page_id_ = navigation_state->pending_page_id();
1316 } 1322 }
1317 } 1323 }
1318 1324
1319 // Remember that we've already processed this request, so we don't update 1325 // Remember that we've already processed this request, so we don't update
1320 // the session history again. We do this regardless of whether this is 1326 // the session history again. We do this regardless of whether this is
1321 // a session history navigation, because if we attempted a session history 1327 // a session history navigation, because if we attempted a session history
1322 // navigation without valid HistoryItem state, WebCore will think it is a 1328 // navigation without valid HistoryItem state, WebCore will think it is a
(...skipping 1497 matching lines...) Expand 10 before | Expand all | Expand 10 after
2820 target); 2826 target);
2821 } 2827 }
2822 2828
2823 void RenderView::OnDisassociateFromPopupCount() { 2829 void RenderView::OnDisassociateFromPopupCount() {
2824 if (decrement_shared_popup_at_destruction_) 2830 if (decrement_shared_popup_at_destruction_)
2825 shared_popup_counter_->data--; 2831 shared_popup_counter_->data--;
2826 shared_popup_counter_ = new SharedRenderViewCounter(0); 2832 shared_popup_counter_ = new SharedRenderViewCounter(0);
2827 decrement_shared_popup_at_destruction_ = false; 2833 decrement_shared_popup_at_destruction_ = false;
2828 } 2834 }
2829 2835
2836 bool RenderView::MaybeLoadAlternateErrorPage(WebFrame* frame,
2837 const WebURLError& error,
2838 bool replace) {
2839 // We only show alternate error pages in the main frame. They are
2840 // intended to assist the user when navigating, so there is not much
2841 // value in showing them for failed subframes. Ideally, we would be
2842 // able to use the TYPED transition type for this, but that flag is
2843 // not preserved across page reloads.
2844 if (frame->GetParent())
2845 return false;
2846
2847 // Use the alternate error page service if this is a DNS failure or
2848 // connection failure. ERR_CONNECTION_FAILED can be dropped once we no
2849 // longer use winhttp.
2850 int ec = error.reason;
2851 if (ec != net::ERR_NAME_NOT_RESOLVED &&
2852 ec != net::ERR_CONNECTION_FAILED &&
2853 ec != net::ERR_CONNECTION_REFUSED &&
2854 ec != net::ERR_ADDRESS_UNREACHABLE &&
2855 ec != net::ERR_TIMED_OUT)
2856 return false;
2857
2858 const GURL& error_page_url = GetAlternateErrorPageURL(error.unreachableURL,
2859 ec == net::ERR_NAME_NOT_RESOLVED ? WebViewDelegate::DNS_ERROR
2860 : WebViewDelegate::CONNECTION_ERROR);
2861 if (!error_page_url.is_valid())
2862 return false;
2863
2864 // Load an empty page first so there is an immediate response to the error,
2865 // and then kick off a request for the alternate error page.
2866 frame->LoadHTMLString(std::string(),
2867 GURL(kUnreachableWebDataURL),
2868 error.unreachableURL,
2869 replace);
2870
2871 // Now, create a fetcher for the error page and associate it with the data
2872 // source we just created via the LoadHTMLString call. That way if another
2873 // navigation occurs, the fetcher will get destroyed.
2874 NavigationState* navigation_state =
2875 NavigationState::FromDataSource(frame->GetProvisionalDataSource());
2876 navigation_state->set_alt_error_page_fetcher(
2877 new AltErrorPageResourceFetcher(
2878 error_page_url, frame, error.unreachableURL,
2879 NewCallback(this, &RenderView::AltErrorPageFinished)));
2880 return true;
2881 }
2882
2830 std::string RenderView::GetAltHTMLForTemplate( 2883 std::string RenderView::GetAltHTMLForTemplate(
2831 const DictionaryValue& error_strings, int template_resource_id) const { 2884 const DictionaryValue& error_strings, int template_resource_id) const {
2832 const StringPiece template_html( 2885 const StringPiece template_html(
2833 ResourceBundle::GetSharedInstance().GetRawDataResource( 2886 ResourceBundle::GetSharedInstance().GetRawDataResource(
2834 template_resource_id)); 2887 template_resource_id));
2835 2888
2836 if (template_html.empty()) { 2889 if (template_html.empty()) {
2837 NOTREACHED() << "unable to load template. ID: " << template_resource_id; 2890 NOTREACHED() << "unable to load template. ID: " << template_resource_id;
2838 return ""; 2891 return "";
2839 } 2892 }
2840 2893
2841 // "t" is the id of the templates root node. 2894 // "t" is the id of the templates root node.
2842 return jstemplate_builder::GetTemplatesHtml( 2895 return jstemplate_builder::GetTemplatesHtml(
2843 template_html, &error_strings, "t"); 2896 template_html, &error_strings, "t");
2844 } 2897 }
2845 2898
2899 void RenderView::AltErrorPageFinished(WebFrame* frame,
2900 const GURL& unreachable_url,
2901 const std::string& html) {
2902 // Here, we replace the blank page we loaded previously.
2903 WebURLError error;
2904 error.unreachableURL = unreachable_url;
2905 LoadNavigationErrorPage(frame, WebURLRequest(), error, html, true);
2906 }
2907
2846 void RenderView::OnMoveOrResizeStarted() { 2908 void RenderView::OnMoveOrResizeStarted() {
2847 if (webview()) 2909 if (webview())
2848 webview()->HideAutofillPopup(); 2910 webview()->HideAutofillPopup();
2849 } 2911 }
2850 2912
2851 void RenderView::OnResize(const gfx::Size& new_size, 2913 void RenderView::OnResize(const gfx::Size& new_size,
2852 const gfx::Rect& resizer_rect) { 2914 const gfx::Rect& resizer_rect) {
2853 if (webview()) 2915 if (webview())
2854 webview()->HideAutofillPopup(); 2916 webview()->HideAutofillPopup();
2855 RenderWidget::OnResize(new_size, resizer_rect); 2917 RenderWidget::OnResize(new_size, resizer_rect);
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
3098 Send(new ViewHostMsg_PasswordFormsSeen(routing_id_, password_forms)); 3160 Send(new ViewHostMsg_PasswordFormsSeen(routing_id_, password_forms));
3099 } 3161 }
3100 3162
3101 void RenderView::Print(WebFrame* frame, bool script_initiated) { 3163 void RenderView::Print(WebFrame* frame, bool script_initiated) {
3102 DCHECK(frame); 3164 DCHECK(frame);
3103 if (print_helper_.get() == NULL) { 3165 if (print_helper_.get() == NULL) {
3104 print_helper_.reset(new PrintWebViewHelper(this)); 3166 print_helper_.reset(new PrintWebViewHelper(this));
3105 } 3167 }
3106 print_helper_->Print(frame, script_initiated); 3168 print_helper_->Print(frame, script_initiated);
3107 } 3169 }
OLDNEW
« no previous file with comments | « chrome/renderer/render_view.h ('k') | chrome/test/data/iframe_dns_error.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698