forked from Pissandshittium/pissandshittium
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a new NavigationThrottle for HTTP-error navigations with empty body
Previously, error page navigations initiated by the renderer will commit synchronously and only notify the browser at DidCommit time, making it have to create a NavigationRequest for the navigation at DidCommit time. One of the cases that do that is main-frame navigations with error HTTP status code and an empty response body. This CL makes it so that we detect that case in the browser side instead of the renderer side by adding a NavigationThrottle that will defer main frame navigations with an error HTTP status code until we can determine if its response body is empty or not, and commit an error page instead of the original (empty) page if so. For more context: doc: https://docs.google.com/document/d/1hf7b7OWlJMCpfFBk3xgxzHnskyNx3X8qjNWg6M1hr_0/edit navigation-dev thread: https://groups.google.com/a/chromium.org/g/navigation-dev/c/WbNkf2alpPU/m/2tQQ-cXWBgAJ Bug: 1133115 Change-Id: I09998edd984b86bad6294edc4c83a32c31e0197f Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2487024 Commit-Queue: Rakina Zata Amni <rakina@chromium.org> Reviewed-by: Charlie Reis <creis@chromium.org> Reviewed-by: Emily Stark <estark@chromium.org> Reviewed-by: Arthur Sonzogni <arthursonzogni@chromium.org> Reviewed-by: Matt Falkenhagen <falken@chromium.org> Cr-Commit-Position: refs/heads/master@{#823093}
- Loading branch information
Showing
47 changed files
with
429 additions
and
225 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
106 changes: 106 additions & 0 deletions
106
content/browser/renderer_host/http_error_navigation_throttle.cc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
// Copyright 2020 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#include "content/browser/renderer_host/http_error_navigation_throttle.h" | ||
|
||
#include "content/browser/renderer_host/navigation_request.h" | ||
#include "content/public/common/content_client.h" | ||
|
||
namespace content { | ||
|
||
// static | ||
std::unique_ptr<NavigationThrottle> | ||
HttpErrorNavigationThrottle::MaybeCreateThrottleFor( | ||
NavigationHandle& navigation_handle) { | ||
// We only care about main frame navigations. | ||
if (!navigation_handle.IsInMainFrame()) | ||
return nullptr; | ||
return base::WrapUnique(new HttpErrorNavigationThrottle(navigation_handle)); | ||
} | ||
|
||
HttpErrorNavigationThrottle::HttpErrorNavigationThrottle( | ||
NavigationHandle& navigation_handle) | ||
: NavigationThrottle(&navigation_handle), | ||
task_runner_(base::ThreadTaskRunnerHandle::Get()), | ||
body_consumer_watcher_(FROM_HERE, | ||
mojo::SimpleWatcher::ArmingPolicy::MANUAL, | ||
task_runner_) {} | ||
|
||
const char* HttpErrorNavigationThrottle::GetNameForLogging() { | ||
return "HttpErrorNavigationThrottle"; | ||
} | ||
|
||
HttpErrorNavigationThrottle::~HttpErrorNavigationThrottle() = default; | ||
|
||
NavigationThrottle::ThrottleCheckResult | ||
HttpErrorNavigationThrottle::WillProcessResponse() { | ||
// We've received the response head, but the response body might not be | ||
// readable yet. We should wait for the body, but only if the response might | ||
// result in an error page (response_code indicates an error, and the embedder | ||
// has a custom error page for it). | ||
const network::mojom::URLResponseHead* response = | ||
NavigationRequest::From(navigation_handle())->response(); | ||
DCHECK(response); | ||
if (!response->headers) | ||
return PROCEED; | ||
int response_code = response->headers->response_code(); | ||
if (response_code < 400 || | ||
!GetContentClient()->browser()->HasErrorPage(response_code)) { | ||
return PROCEED; | ||
} | ||
|
||
// Defer the navigation until we can determine if the response body is empty | ||
// or not, by waiting until it becomes readable or the connection is closed. | ||
body_consumer_watcher_.Watch( | ||
NavigationRequest::From(navigation_handle())->response_body(), | ||
MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, | ||
base::BindRepeating(&HttpErrorNavigationThrottle::OnBodyReadable, | ||
base::Unretained(this))); | ||
body_consumer_watcher_.ArmOrNotify(); | ||
return DEFER; | ||
} | ||
|
||
void HttpErrorNavigationThrottle::OnBodyReadable(MojoResult) { | ||
const mojo::DataPipeConsumerHandle& body = | ||
NavigationRequest::From(navigation_handle())->response_body(); | ||
// See how many bytes are in the body, without consuming anything from the | ||
// response body data pipe. | ||
uint32_t num_bytes = 0; | ||
MojoResult result = | ||
body.ReadData(nullptr, &num_bytes, MOJO_READ_DATA_FLAG_QUERY); | ||
|
||
switch (result) { | ||
case MOJO_RESULT_OK: | ||
break; | ||
case MOJO_RESULT_FAILED_PRECONDITION: | ||
// Failed reading the result, can be due to the connection being closed. | ||
// We should treat this as a signal that the body is empty. | ||
DCHECK_EQ(num_bytes, 0u); | ||
break; | ||
case MOJO_RESULT_SHOULD_WAIT: | ||
// Wait for the next signal to try and read the body again. | ||
body_consumer_watcher_.ArmOrNotify(); | ||
return; | ||
default: | ||
NOTREACHED(); | ||
return; | ||
} | ||
|
||
// Stop watching for signals. | ||
body_consumer_watcher_.Cancel(); | ||
|
||
if (num_bytes == 0) { | ||
// The response body is empty, so cancel the navigation and commit an error | ||
// page instead. The error page's content will be generated in the renderer | ||
// at commit time, so we only need to pass the error code in the call below. | ||
CancelDeferredNavigation({content::NavigationThrottle::CANCEL, | ||
net::ERR_HTTP_RESPONSE_CODE_FAILURE}); | ||
} else { | ||
// There's at least one byte in the body, which means it's not empty. The | ||
// navigation should continue normally. | ||
Resume(); | ||
} | ||
} | ||
|
||
} // namespace content |
44 changes: 44 additions & 0 deletions
44
content/browser/renderer_host/http_error_navigation_throttle.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
// Copyright 2020 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#ifndef CONTENT_BROWSER_RENDERER_HOST_HTTP_ERROR_NAVIGATION_THROTTLE_H_ | ||
#define CONTENT_BROWSER_RENDERER_HOST_HTTP_ERROR_NAVIGATION_THROTTLE_H_ | ||
|
||
#include "content/public/browser/navigation_handle.h" | ||
#include "content/public/browser/navigation_throttle.h" | ||
#include "mojo/public/cpp/system/simple_watcher.h" | ||
|
||
namespace content { | ||
|
||
// If a navigation received a response with a bad HTTP status code, we will | ||
// still display the contents from the response body sent by the site (e.g. some | ||
// sites have custom 404 pages). In cases where the response's body is empty, | ||
// however, we should display an error page if possible (instead of showing a | ||
// blank page, which might confuse users). This throttle will defer main frame | ||
// potentially-empty HTTP error navigations until we can determine if its | ||
// response body is empty or not. | ||
class HttpErrorNavigationThrottle : public NavigationThrottle { | ||
public: | ||
static std::unique_ptr<NavigationThrottle> MaybeCreateThrottleFor( | ||
NavigationHandle& navigation_handle); | ||
|
||
~HttpErrorNavigationThrottle() override; | ||
|
||
private: | ||
explicit HttpErrorNavigationThrottle(NavigationHandle& navigation_handle); | ||
|
||
// NavigationThrottle overrides. | ||
const char* GetNameForLogging() override; | ||
ThrottleCheckResult WillProcessResponse() override; | ||
|
||
void OnBodyReadable(MojoResult); | ||
|
||
private: | ||
scoped_refptr<base::SequencedTaskRunner> task_runner_; | ||
mojo::SimpleWatcher body_consumer_watcher_; | ||
}; | ||
|
||
} // namespace content | ||
|
||
#endif // CONTENT_BROWSER_RENDERER_HOST_HTTP_ERROR_NAVIGATION_THROTTLE_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.