Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |