Commit 30b56844 authored by Dmitry Gozman's avatar Dmitry Gozman Committed by Commit Bot

RenderFrameImpl: unify error page handling

This patch makes CommitFailedNavigation not use
LoadNavigationErrorPage, which is left for loading
renderer-initiated error pages. That allows us
to simplify LoadNavigationErrorPage and unify all three
renderer-initiated calls.

Bug: 855189
Change-Id: Ic56fe7b63376e0c4d92d4fb38b87e9d20aae85a5
Reviewed-on: https://chromium-review.googlesource.com/c/1338919Reviewed-by: default avatarCharlie Reis <creis@chromium.org>
Reviewed-by: default avatarArthur Sonzogni <arthursonzogni@chromium.org>
Commit-Queue: Dmitry Gozman <dgozman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#612270}
parent c185420a
...@@ -2772,46 +2772,25 @@ void RenderFrameImpl::DidFailProvisionalLoad( ...@@ -2772,46 +2772,25 @@ void RenderFrameImpl::DidFailProvisionalLoad(
if (!document_loader) if (!document_loader)
return; return;
const WebURLRequest& failed_request = document_loader->GetRequest();
// Notify the browser that we failed a provisional load with an error. // Notify the browser that we failed a provisional load with an error.
SendFailedProvisionalLoad(failed_request, error, frame_); SendFailedProvisionalLoad(document_loader->GetRequest(), error, frame_);
if (!ShouldDisplayErrorPageForFailedLoad(error.reason(), error.url())) if (!ShouldDisplayErrorPageForFailedLoad(error.reason(), error.url()))
return; return;
NavigationState* navigation_state =
NavigationState::FromDocumentLoader(document_loader);
std::unique_ptr<blink::WebNavigationParams> navigation_params;
std::unique_ptr<DocumentState> document_state;
// If we failed on a browser initiated request, then make sure that our error
// page load is regarded as the same browser initiated request.
if (!navigation_state->IsContentInitiated()) {
document_state = BuildDocumentStateFromParams(
navigation_state->common_params(), navigation_state->request_params(),
base::TimeTicks(), // Not used for failed navigation.
CommitNavigationCallback(), nullptr);
navigation_params = BuildNavigationParams(
navigation_state->common_params(), navigation_state->request_params(),
BuildServiceWorkerNetworkProviderForNavigation(
nullptr /* request_params */,
nullptr /* controller_service_worker_info */));
}
// If this is a failed back/forward/reload navigation, then we need to do a // If this is a failed back/forward/reload navigation, then we need to do a
// 'replace' load. This is necessary to avoid messing up session history. // 'replace' load. This is necessary to avoid messing up session history.
// Otherwise, we do a normal load, which simulates a 'go' navigation as far // Otherwise, we do a normal load, which simulates a 'go' navigation as far
// as session history is concerned. // as session history is concerned.
bool replace = commit_type != blink::kWebStandardCommit; bool replace_current_item = commit_type != blink::kWebStandardCommit;
std::string error_html; // If we failed on a browser initiated request, then make sure that our error
GetContentClient()->renderer()->PrepareErrorPage(this, failed_request, error, // page load is regarded as the same browser initiated request.
&error_html); bool inherit_document_state =
LoadNavigationErrorPage(error_html, error.url(), replace, nullptr, !NavigationState::FromDocumentLoader(document_loader)
std::move(navigation_params), ->IsContentInitiated();
std::move(document_state), &failed_request); LoadNavigationErrorPage(document_loader, error, base::nullopt,
replace_current_item, inherit_document_state);
} }
void RenderFrameImpl::NotifyObserversOfFailedProvisionalLoad( void RenderFrameImpl::NotifyObserversOfFailedProvisionalLoad(
...@@ -2823,41 +2802,53 @@ void RenderFrameImpl::NotifyObserversOfFailedProvisionalLoad( ...@@ -2823,41 +2802,53 @@ void RenderFrameImpl::NotifyObserversOfFailedProvisionalLoad(
} }
void RenderFrameImpl::LoadNavigationErrorPage( void RenderFrameImpl::LoadNavigationErrorPage(
const std::string& error_html, WebDocumentLoader* document_loader,
const GURL& error_url, const WebURLError& error,
bool replace, const base::Optional<std::string>& error_page_content,
HistoryEntry* history_entry, bool replace_current_item,
std::unique_ptr<blink::WebNavigationParams> navigation_params, bool inherit_document_state) {
std::unique_ptr<blink::WebDocumentLoader::ExtraData> navigation_data, WebURLRequest failed_request = document_loader->GetRequest();
const WebURLRequest* failed_request) {
// Make sure we never show errors in view source mode.
frame_->EnableViewSourceMode(false);
blink::WebFrameLoadType frame_load_type = std::string error_html;
history_entry ? blink::WebFrameLoadType::kBackForward if (error_page_content) {
: blink::WebFrameLoadType::kStandard; error_html = error_page_content.value();
const blink::WebHistoryItem& history_item = } else {
history_entry ? history_entry->root() : blink::WebHistoryItem(); GetContentClient()->renderer()->PrepareErrorPage(this, failed_request,
if (replace && frame_load_type == WebFrameLoadType::kStandard) error, &error_html);
frame_load_type = WebFrameLoadType::kReplaceCurrentItem; }
std::unique_ptr<blink::WebNavigationParams> navigation_params;
std::unique_ptr<DocumentState> document_state;
// Failed navigations will always provide a |failed_request|. Error induced if (inherit_document_state) {
// by the client/renderer side after a commit won't have a |failed_request|. NavigationState* navigation_state =
bool is_client_redirect = !failed_request; NavigationState::FromDocumentLoader(document_loader);
document_state = BuildDocumentStateFromParams(
navigation_state->common_params(), navigation_state->request_params(),
base::TimeTicks(), // Not used for failed navigation.
CommitNavigationCallback(), nullptr);
navigation_params = BuildNavigationParams(
navigation_state->common_params(), navigation_state->request_params(),
BuildServiceWorkerNetworkProviderForNavigation(
nullptr /* request_params */,
nullptr /* controller_service_worker_info */));
} else {
document_state = BuildDocumentState();
}
WebURLRequest new_request; // Make sure we never show errors in view source mode.
if (failed_request) frame_->EnableViewSourceMode(false);
new_request = *failed_request;
new_request.SetURL(GURL(kUnreachableWebDataURL));
// Locally generated error pages should not be cached (in particular they // Locally generated error pages should not be cached.
// should not inherit the cache mode from |failed_request|). failed_request.SetCacheMode(blink::mojom::FetchCacheMode::kNoStore);
new_request.SetCacheMode(blink::mojom::FetchCacheMode::kNoStore); failed_request.SetURL(GURL(kUnreachableWebDataURL));
frame_->CommitDataNavigation(new_request, error_html, "text/html", "UTF-8", frame_->CommitDataNavigation(
error_url, frame_load_type, history_item, failed_request, error_html, "text/html", "UTF-8", error.url(),
is_client_redirect, std::move(navigation_params), replace_current_item ? WebFrameLoadType::kReplaceCurrentItem
std::move(navigation_data)); : WebFrameLoadType::kStandard,
WebHistoryItem(), false /* is_client_redirect */,
std::move(navigation_params), std::move(document_state));
} }
void RenderFrameImpl::DidMeaningfulLayout( void RenderFrameImpl::DidMeaningfulLayout(
...@@ -2973,16 +2964,10 @@ blink::WebPlugin* RenderFrameImpl::CreatePlugin( ...@@ -2973,16 +2964,10 @@ blink::WebPlugin* RenderFrameImpl::CreatePlugin(
} }
void RenderFrameImpl::LoadErrorPage(int reason) { void RenderFrameImpl::LoadErrorPage(int reason) {
WebURLError error(reason, frame_->GetDocument().Url()); LoadNavigationErrorPage(frame_->GetDocumentLoader(),
WebURLError(reason, frame_->GetDocument().Url()),
std::string error_html; base::nullopt, true /* replace_current_item */,
GetContentClient()->renderer()->PrepareErrorPage( false /* inherit_document_state */);
this, frame_->GetDocumentLoader()->GetRequest(), error, &error_html);
LoadNavigationErrorPage(
error_html, error.url(), true /* replace */, nullptr /* history_entry */,
nullptr /* navigation_params */, nullptr /* navigation_data */,
nullptr /* failed_request */);
} }
void RenderFrameImpl::ExecuteJavaScript(const base::string16& javascript) { void RenderFrameImpl::ExecuteJavaScript(const base::string16& javascript) {
...@@ -3461,21 +3446,29 @@ void RenderFrameImpl::CommitFailedNavigation( ...@@ -3461,21 +3446,29 @@ void RenderFrameImpl::CommitFailedNavigation(
error, &error_html); error, &error_html);
} }
// Make sure we never show errors in view source mode.
frame_->EnableViewSourceMode(false);
WebFrameLoadType frame_load_type = WebFrameLoadType::kStandard;
if (history_entry)
frame_load_type = WebFrameLoadType::kBackForward;
else if (replace)
frame_load_type = WebFrameLoadType::kReplaceCurrentItem;
failed_request.SetURL(GURL(kUnreachableWebDataURL));
failed_request.SetCacheMode(blink::mojom::FetchCacheMode::kNoStore);
// The load of the error page can result in this frame being removed. // The load of the error page can result in this frame being removed.
// Use a WeakPtr as an easy way to detect whether this has occured. If so, // Use a WeakPtr as an easy way to detect whether this has occured. If so,
// this method should return immediately and not touch any part of the object, // this method should return immediately and not touch any part of the object,
// otherwise it will result in a use-after-free bug. // otherwise it will result in a use-after-free bug.
base::WeakPtr<RenderFrameImpl> weak_this = weak_factory_.GetWeakPtr(); base::WeakPtr<RenderFrameImpl> weak_this = weak_factory_.GetWeakPtr();
frame_->CommitDataNavigation(
// Don't pass history entry for renderer initiated navigations. failed_request, error_html, "text/html", "UTF-8", error.url(),
bool pass_history_entry = request_params.nav_entry_id != 0; frame_load_type,
// TODO(dgozman): if this DCHECK never triggers, we can just pass history_entry ? history_entry->root() : blink::WebHistoryItem(),
// |history_entry| unconditionally. false /* is_client_redirect */, std::move(navigation_params),
DCHECK(pass_history_entry || !history_entry); std::move(document_state));
LoadNavigationErrorPage(error_html, error.url(), replace,
pass_history_entry ? history_entry.get() : nullptr,
std::move(navigation_params),
std::move(document_state), &failed_request);
if (!weak_this) if (!weak_this)
return; return;
...@@ -4546,23 +4539,22 @@ void RenderFrameImpl::RunScriptsAtDocumentReady(bool document_is_empty) { ...@@ -4546,23 +4539,22 @@ void RenderFrameImpl::RunScriptsAtDocumentReady(bool document_is_empty) {
frame_->GetDocumentLoader()); frame_->GetDocumentLoader());
int http_status_code = internal_data->http_status_code(); int http_status_code = internal_data->http_status_code();
if (GetContentClient()->renderer()->HasErrorPage(http_status_code)) { if (GetContentClient()->renderer()->HasErrorPage(http_status_code)) {
// This call may run scripts, e.g. via the beforeunload event. WebDocumentLoader* document_loader = frame_->GetDocumentLoader();
std::unique_ptr<DocumentState> document_state(BuildDocumentState());
std::unique_ptr<blink::WebNavigationParams> navigation_params =
std::make_unique<blink::WebNavigationParams>();
navigation_params->service_worker_network_provider =
BuildServiceWorkerNetworkProviderForNavigation(
nullptr /* request_params */, nullptr /* controller_info */);
WebURLRequest failed_request = frame_->GetDocumentLoader()->GetRequest();
WebURL unreachable_url = frame_->GetDocument().Url(); WebURL unreachable_url = frame_->GetDocument().Url();
std::string error_html; std::string error_html;
GetContentClient()->renderer()->PrepareErrorPageForHttpStatusError( GetContentClient()->renderer()->PrepareErrorPageForHttpStatusError(
this, failed_request, unreachable_url, http_status_code, &error_html); this, document_loader->GetRequest(), unreachable_url, http_status_code,
LoadNavigationErrorPage(error_html, unreachable_url, true /* replace */, &error_html);
nullptr /* entry */, std::move(navigation_params), // This call may run scripts, e.g. via the beforeunload event, and possibly
std::move(document_state), &failed_request); // delete |this|.
} LoadNavigationErrorPage(document_loader,
WebURLError(net::ERR_FAILED, unreachable_url),
error_html, true /* replace_current_item */,
false /* inherit_document_state */);
if (!weak_self)
return;
// Do not use |this| or |frame_| here without checking |weak_self|. // Do not use |this| or |frame_| here without checking |weak_self|.
}
} }
void RenderFrameImpl::RunScriptsAtDocumentIdle() { void RenderFrameImpl::RunScriptsAtDocumentIdle() {
......
...@@ -127,7 +127,6 @@ class WebURL; ...@@ -127,7 +127,6 @@ class WebURL;
struct FramePolicy; struct FramePolicy;
struct WebContextMenuData; struct WebContextMenuData;
struct WebCursorInfo; struct WebCursorInfo;
struct WebNavigationParams;
struct WebMediaPlayerAction; struct WebMediaPlayerAction;
struct WebImeTextSpan; struct WebImeTextSpan;
struct WebScrollIntoViewParams; struct WebScrollIntoViewParams;
...@@ -160,7 +159,6 @@ class BlinkInterfaceRegistryImpl; ...@@ -160,7 +159,6 @@ class BlinkInterfaceRegistryImpl;
class CompositorDependencies; class CompositorDependencies;
class ExternalPopupMenu; class ExternalPopupMenu;
class FrameRequestBlocker; class FrameRequestBlocker;
class HistoryEntry;
class ManifestManager; class ManifestManager;
class MediaPermissionDispatcher; class MediaPermissionDispatcher;
class MediaStreamDeviceObserver; class MediaStreamDeviceObserver;
...@@ -1130,15 +1128,12 @@ class CONTENT_EXPORT RenderFrameImpl ...@@ -1130,15 +1128,12 @@ class CONTENT_EXPORT RenderFrameImpl
base::string16* result); base::string16* result);
// Loads the appropriate error page for the specified failure into the frame. // Loads the appropriate error page for the specified failure into the frame.
// |entry| is only when navigating to a history item.
void LoadNavigationErrorPage( void LoadNavigationErrorPage(
const std::string& error_html, blink::WebDocumentLoader* document_loader,
const GURL& error_url, const blink::WebURLError& error,
bool replace, const base::Optional<std::string>& error_page_content,
HistoryEntry* history_entry, bool replace_current_item,
std::unique_ptr<blink::WebNavigationParams> navigation_params, bool inherit_document_state);
std::unique_ptr<blink::WebDocumentLoader::ExtraData> navigation_data,
const blink::WebURLRequest* failed_request);
void HandleJavascriptExecutionResult(const base::string16& javascript, void HandleJavascriptExecutionResult(const base::string16& javascript,
int id, int id,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment