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

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

Issue 160578: Move alternate 404 error page loading out of WebFrame and into RenderView.... (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') | webkit/glue/webframe.h » ('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 1265 matching lines...) Expand 10 before | Expand all | Expand 10 after
1276 } else { 1276 } else {
1277 alt_html = html; 1277 alt_html = html;
1278 } 1278 }
1279 1279
1280 frame->LoadHTMLString(alt_html, 1280 frame->LoadHTMLString(alt_html,
1281 GURL(kUnreachableWebDataURL), 1281 GURL(kUnreachableWebDataURL),
1282 failed_url, 1282 failed_url,
1283 replace); 1283 replace);
1284 } 1284 }
1285 1285
1286 void RenderView::DidReceiveDocumentData(WebFrame* frame, const char* data,
1287 size_t data_len) {
1288 NavigationState* navigation_state =
1289 NavigationState::FromDataSource(frame->GetDataSource());
1290 if (!navigation_state->postpone_loading_data()) {
1291 frame->CommitDocumentData(data, data_len);
1292 return;
1293 }
1294
1295 // Continue buffering the response data for the original 404 page. If it
1296 // grows too large, then we'll just let it through.
1297 navigation_state->append_postponed_data(data, data_len);
1298 if (navigation_state->postponed_data().size() >= 512) {
1299 navigation_state->set_postpone_loading_data(false);
1300 frame->CommitDocumentData(navigation_state->postponed_data().data(),
1301 navigation_state->postponed_data().size());
1302 navigation_state->clear_postponed_data();
1303 }
1304 }
1305
1286 void RenderView::DidCommitLoadForFrame(WebView *webview, WebFrame* frame, 1306 void RenderView::DidCommitLoadForFrame(WebView *webview, WebFrame* frame,
1287 bool is_new_navigation) { 1307 bool is_new_navigation) {
1288 NavigationState* navigation_state = 1308 NavigationState* navigation_state =
1289 NavigationState::FromDataSource(frame->GetDataSource()); 1309 NavigationState::FromDataSource(frame->GetDataSource());
1290 1310
1291 navigation_state->set_commit_load_time(Time::Now()); 1311 navigation_state->set_commit_load_time(Time::Now());
1292 if (is_new_navigation) { 1312 if (is_new_navigation) {
1293 // When we perform a new navigation, we need to update the previous session 1313 // When we perform a new navigation, we need to update the previous session
1294 // history entry with state for the page we are leaving. 1314 // history entry with state for the page we are leaving.
1295 UpdateSessionHistory(frame); 1315 UpdateSessionHistory(frame);
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
1435 navigation_state->set_password_form_data( 1455 navigation_state->set_password_form_data(
1436 PasswordFormDomManager::CreatePasswordForm(form)); 1456 PasswordFormDomManager::CreatePasswordForm(form));
1437 1457
1438 if (form.isAutoCompleteEnabled()) { 1458 if (form.isAutoCompleteEnabled()) {
1439 scoped_ptr<AutofillForm> autofill_form(AutofillForm::Create(form)); 1459 scoped_ptr<AutofillForm> autofill_form(AutofillForm::Create(form));
1440 if (autofill_form.get()) 1460 if (autofill_form.get())
1441 Send(new ViewHostMsg_AutofillFormSubmitted(routing_id_, *autofill_form)); 1461 Send(new ViewHostMsg_AutofillFormSubmitted(routing_id_, *autofill_form));
1442 } 1462 }
1443 } 1463 }
1444 1464
1445 void RenderView::WillSendRequest(WebView* webview, 1465 void RenderView::WillSendRequest(WebFrame* frame, uint32 identifier,
1446 uint32 identifier,
1447 WebURLRequest* request) { 1466 WebURLRequest* request) {
1448 request->setRequestorID(routing_id_); 1467 request->setRequestorID(routing_id_);
1449 } 1468 }
1450 1469
1451 void RenderView::BindDOMAutomationController(WebFrame* webframe) { 1470 void RenderView::DidReceiveResponse(WebFrame* frame, uint32 identifier,
1471 const WebURLResponse& response) {
1472 // Consider loading an alternate error page for 404 responses.
1473 if (response.httpStatusCode() != 404)
1474 return;
1475
1476 // Only do this for responses that correspond to a provisional data source
1477 // of the top-most frame. If we have a provisional data source, then we
1478 // can't have any sub-resources yet, so we know that this response must
1479 // correspond to a frame load.
1480 if (!frame->GetProvisionalDataSource() || frame->GetParent())
1481 return;
1482
1483 // If we are in view source mode, then just let the user see the source of
1484 // the server's 404 error page.
1485 if (frame->GetInViewSourceMode())
1486 return;
1487
1488 // Can we even load an alternate error page for this URL?
1489 if (!GetAlternateErrorPageURL(response.url(), HTTP_404).is_valid())
1490 return;
1491
1492 NavigationState* navigation_state =
1493 NavigationState::FromDataSource(frame->GetProvisionalDataSource());
1494 navigation_state->set_postpone_loading_data(true);
1495 navigation_state->clear_postponed_data();
1496 }
1497
1498 void RenderView::DidFinishLoading(WebFrame* frame, uint32 identifier) {
1499 NavigationState* navigation_state =
1500 NavigationState::FromDataSource(frame->GetDataSource());
1501 if (!navigation_state->postpone_loading_data())
1502 return;
1503
1504 // The server returned a 404 and the content was < 512 bytes (which we
1505 // suppressed). Go ahead and fetch the alternate page content.
1506
1507 const GURL& frame_url = frame->GetURL();
1508
1509 const GURL& error_page_url = GetAlternateErrorPageURL(frame_url, HTTP_404);
1510 DCHECK(error_page_url.is_valid());
1511
1512 WebURLError original_error;
1513 original_error.unreachableURL = frame_url;
1514
1515 navigation_state->set_alt_error_page_fetcher(
1516 new AltErrorPageResourceFetcher(
1517 error_page_url, frame, original_error,
1518 NewCallback(this, &RenderView::AltErrorPageFinished)));
1519 }
1520
1521 void RenderView::BindDOMAutomationController(WebFrame* frame) {
1452 dom_automation_controller_.set_message_sender(this); 1522 dom_automation_controller_.set_message_sender(this);
1453 dom_automation_controller_.set_routing_id(routing_id_); 1523 dom_automation_controller_.set_routing_id(routing_id_);
1454 dom_automation_controller_.BindToJavascript(webframe, 1524 dom_automation_controller_.BindToJavascript(frame,
1455 L"domAutomationController"); 1525 L"domAutomationController");
1456 } 1526 }
1457 1527
1458 void RenderView::WindowObjectCleared(WebFrame* webframe) { 1528 void RenderView::WindowObjectCleared(WebFrame* frame) {
1459 if (BindingsPolicy::is_dom_automation_enabled(enabled_bindings_)) 1529 if (BindingsPolicy::is_dom_automation_enabled(enabled_bindings_))
1460 BindDOMAutomationController(webframe); 1530 BindDOMAutomationController(frame);
1461 if (BindingsPolicy::is_dom_ui_enabled(enabled_bindings_)) { 1531 if (BindingsPolicy::is_dom_ui_enabled(enabled_bindings_)) {
1462 dom_ui_bindings_.set_message_sender(this); 1532 dom_ui_bindings_.set_message_sender(this);
1463 dom_ui_bindings_.set_routing_id(routing_id_); 1533 dom_ui_bindings_.set_routing_id(routing_id_);
1464 dom_ui_bindings_.BindToJavascript(webframe, L"chrome"); 1534 dom_ui_bindings_.BindToJavascript(frame, L"chrome");
1465 } 1535 }
1466 if (BindingsPolicy::is_external_host_enabled(enabled_bindings_)) { 1536 if (BindingsPolicy::is_external_host_enabled(enabled_bindings_)) {
1467 external_host_bindings_.set_message_sender(this); 1537 external_host_bindings_.set_message_sender(this);
1468 external_host_bindings_.set_routing_id(routing_id_); 1538 external_host_bindings_.set_routing_id(routing_id_);
1469 external_host_bindings_.BindToJavascript(webframe, L"externalHost"); 1539 external_host_bindings_.BindToJavascript(frame, L"externalHost");
1470 } 1540 }
1471 } 1541 }
1472 1542
1473 void RenderView::DocumentElementAvailable(WebFrame* frame) { 1543 void RenderView::DocumentElementAvailable(WebFrame* frame) {
1474 // TODO(mpcomplete): remove this before Chrome extensions ship. 1544 // TODO(mpcomplete): remove this before Chrome extensions ship.
1475 // HACK. This is a temporary workaround to allow cross-origin XHR for Chrome 1545 // HACK. This is a temporary workaround to allow cross-origin XHR for Chrome
1476 // extensions. It grants full access to every origin, when we really want 1546 // extensions. It grants full access to every origin, when we really want
1477 // to be able to restrict them more specifically. 1547 // to be able to restrict them more specifically.
1478 if (frame->GetURL().SchemeIs(chrome::kExtensionScheme)) 1548 if (frame->GetURL().SchemeIs(chrome::kExtensionScheme))
1479 frame->GrantUniversalAccess(); 1549 frame->GrantUniversalAccess();
(...skipping 619 matching lines...) Expand 10 before | Expand all | Expand 10 after
2099 for (size_t i = 0; i < app_info.icons.size(); ++i) { 2169 for (size_t i = 0; i < app_info.icons.size(); ++i) {
2100 if (app_info.icons[i].url.SchemeIs(chrome::kDataScheme)) { 2170 if (app_info.icons[i].url.SchemeIs(chrome::kDataScheme)) {
2101 app_info.icons.erase(app_info.icons.begin() + i); 2171 app_info.icons.erase(app_info.icons.begin() + i);
2102 --i; 2172 --i;
2103 } 2173 }
2104 } 2174 }
2105 2175
2106 Send(new ViewHostMsg_DidGetApplicationInfo(routing_id_, page_id, app_info)); 2176 Send(new ViewHostMsg_DidGetApplicationInfo(routing_id_, page_id, app_info));
2107 } 2177 }
2108 2178
2109 GURL RenderView::GetAlternateErrorPageURL(const GURL& failedURL, 2179 GURL RenderView::GetAlternateErrorPageURL(const GURL& failed_url,
2110 ErrorPageType error_type) { 2180 ErrorPageType error_type) {
2111 if (failedURL.SchemeIsSecure()) { 2181 if (failed_url.SchemeIsSecure()) {
2112 // If the URL that failed was secure, then the embedding web page was not 2182 // If the URL that failed was secure, then the embedding web page was not
2113 // expecting a network attacker to be able to manipulate its contents. As 2183 // expecting a network attacker to be able to manipulate its contents. As
2114 // we fetch alternate error pages over HTTP, we would be allowing a network 2184 // we fetch alternate error pages over HTTP, we would be allowing a network
2115 // attacker to manipulate the contents of the response if we tried to use 2185 // attacker to manipulate the contents of the response if we tried to use
2116 // the link doctor here. 2186 // the link doctor here.
2117 return GURL::EmptyGURL(); 2187 return GURL::EmptyGURL();
2118 } 2188 }
2119 2189
2120 // Grab the base URL from the browser process. 2190 // Grab the base URL from the browser process.
2121 if (!alternate_error_page_url_.is_valid()) 2191 if (!alternate_error_page_url_.is_valid())
2122 return GURL::EmptyGURL(); 2192 return GURL::EmptyGURL();
2123 2193
2124 // Strip query params from the failed URL. 2194 // Strip query params from the failed URL.
2125 GURL::Replacements remove_params; 2195 GURL::Replacements remove_params;
2126 remove_params.ClearUsername(); 2196 remove_params.ClearUsername();
2127 remove_params.ClearPassword(); 2197 remove_params.ClearPassword();
2128 remove_params.ClearQuery(); 2198 remove_params.ClearQuery();
2129 remove_params.ClearRef(); 2199 remove_params.ClearRef();
2130 const GURL url_to_send = failedURL.ReplaceComponents(remove_params); 2200 const GURL url_to_send = failed_url.ReplaceComponents(remove_params);
2131 2201
2132 // Construct the query params to send to link doctor. 2202 // Construct the query params to send to link doctor.
2133 std::string params(alternate_error_page_url_.query()); 2203 std::string params(alternate_error_page_url_.query());
2134 params.append("&url="); 2204 params.append("&url=");
2135 params.append(EscapeQueryParamValue(url_to_send.spec())); 2205 params.append(EscapeQueryParamValue(url_to_send.spec()));
2136 params.append("&sourceid=chrome"); 2206 params.append("&sourceid=chrome");
2137 params.append("&error="); 2207 params.append("&error=");
2138 switch (error_type) { 2208 switch (error_type) {
2139 case DNS_ERROR: 2209 case DNS_ERROR:
2140 params.append("dnserror"); 2210 params.append("dnserror");
(...skipping 707 matching lines...) Expand 10 before | Expand all | Expand 10 after
2848 // longer use winhttp. 2918 // longer use winhttp.
2849 int ec = error.reason; 2919 int ec = error.reason;
2850 if (ec != net::ERR_NAME_NOT_RESOLVED && 2920 if (ec != net::ERR_NAME_NOT_RESOLVED &&
2851 ec != net::ERR_CONNECTION_FAILED && 2921 ec != net::ERR_CONNECTION_FAILED &&
2852 ec != net::ERR_CONNECTION_REFUSED && 2922 ec != net::ERR_CONNECTION_REFUSED &&
2853 ec != net::ERR_ADDRESS_UNREACHABLE && 2923 ec != net::ERR_ADDRESS_UNREACHABLE &&
2854 ec != net::ERR_TIMED_OUT) 2924 ec != net::ERR_TIMED_OUT)
2855 return false; 2925 return false;
2856 2926
2857 const GURL& error_page_url = GetAlternateErrorPageURL(error.unreachableURL, 2927 const GURL& error_page_url = GetAlternateErrorPageURL(error.unreachableURL,
2858 ec == net::ERR_NAME_NOT_RESOLVED ? WebViewDelegate::DNS_ERROR 2928 ec == net::ERR_NAME_NOT_RESOLVED ? DNS_ERROR : CONNECTION_ERROR);
2859 : WebViewDelegate::CONNECTION_ERROR);
2860 if (!error_page_url.is_valid()) 2929 if (!error_page_url.is_valid())
2861 return false; 2930 return false;
2862 2931
2863 // Load an empty page first so there is an immediate response to the error, 2932 // Load an empty page first so there is an immediate response to the error,
2864 // and then kick off a request for the alternate error page. 2933 // and then kick off a request for the alternate error page.
2865 frame->LoadHTMLString(std::string(), 2934 frame->LoadHTMLString(std::string(),
2866 GURL(kUnreachableWebDataURL), 2935 GURL(kUnreachableWebDataURL),
2867 error.unreachableURL, 2936 error.unreachableURL,
2868 replace); 2937 replace);
2869 2938
(...skipping 22 matching lines...) Expand all
2892 2961
2893 // "t" is the id of the templates root node. 2962 // "t" is the id of the templates root node.
2894 return jstemplate_builder::GetTemplatesHtml( 2963 return jstemplate_builder::GetTemplatesHtml(
2895 template_html, &error_strings, "t"); 2964 template_html, &error_strings, "t");
2896 } 2965 }
2897 2966
2898 void RenderView::AltErrorPageFinished(WebFrame* frame, 2967 void RenderView::AltErrorPageFinished(WebFrame* frame,
2899 const WebURLError& original_error, 2968 const WebURLError& original_error,
2900 const std::string& html) { 2969 const std::string& html) {
2901 // Here, we replace the blank page we loaded previously. 2970 // Here, we replace the blank page we loaded previously.
2902 LoadNavigationErrorPage(frame, WebURLRequest(), original_error, html, true); 2971
2972 // If we failed to download the alternate error page, fall back to the
2973 // original error page if present. Otherwise, LoadNavigationErrorPage
2974 // will simply display a default error page.
2975 const std::string* html_to_load = &html;
2976 if (html.empty()) {
2977 NavigationState* navigation_state =
2978 NavigationState::FromDataSource(frame->GetDataSource());
2979 html_to_load = &navigation_state->postponed_data();
tony 2009/08/04 17:07:45 Ah, good catch about showing the original error pa
darin (slow to review) 2009/08/04 17:34:49 The existing code for alt404 already handled this.
2980 }
2981 LoadNavigationErrorPage(
2982 frame, WebURLRequest(), original_error, *html_to_load, true);
2903 } 2983 }
2904 2984
2905 void RenderView::OnMoveOrResizeStarted() { 2985 void RenderView::OnMoveOrResizeStarted() {
2906 if (webview()) 2986 if (webview())
2907 webview()->HideAutofillPopup(); 2987 webview()->HideAutofillPopup();
2908 } 2988 }
2909 2989
2910 void RenderView::OnResize(const gfx::Size& new_size, 2990 void RenderView::OnResize(const gfx::Size& new_size,
2911 const gfx::Rect& resizer_rect) { 2991 const gfx::Rect& resizer_rect) {
2912 if (webview()) 2992 if (webview())
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after
3179 Send(new ViewHostMsg_PasswordFormsSeen(routing_id_, password_forms)); 3259 Send(new ViewHostMsg_PasswordFormsSeen(routing_id_, password_forms));
3180 } 3260 }
3181 3261
3182 void RenderView::Print(WebFrame* frame, bool script_initiated) { 3262 void RenderView::Print(WebFrame* frame, bool script_initiated) {
3183 DCHECK(frame); 3263 DCHECK(frame);
3184 if (print_helper_.get() == NULL) { 3264 if (print_helper_.get() == NULL) {
3185 print_helper_.reset(new PrintWebViewHelper(this)); 3265 print_helper_.reset(new PrintWebViewHelper(this));
3186 } 3266 }
3187 print_helper_->Print(frame, script_initiated); 3267 print_helper_->Print(frame, script_initiated);
3188 } 3268 }
OLDNEW
« no previous file with comments | « chrome/renderer/render_view.h ('k') | webkit/glue/webframe.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698