New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add will-redirect #13866
feat: add will-redirect #13866
Conversation
47055b2
to
f483586
Compare
Please do not merge until after the meeting on Monday 30th |
Well that was easy - I had no idea Chrome already has an event, but of course it does. 👏 for sprinting into action, this seems like a very clean solution. |
if (EmitNavigationEvent("will-redirect", navigation_handle)) { | ||
scoped_refptr<base::SingleThreadTaskRunner> task_runner( | ||
base::ThreadTaskRunnerHandle::Get()); | ||
task_runner->PostTask(FROM_HERE, base::BindOnce(&OnStopSoon, this)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does the asynchronous nature of this leave a window of opportunity for the redirect to start happening? It'd be awesome if there was a way to guarantee that not a single byte of network traffic leaves to the domain of the redirect's target.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It'd be awesome if there was a way to guarantee that not a single byte of network traffic leaves to the domain of the redirect's target.
Its possible by registering navigation throttlers https://cs.chromium.org/chromium/src/content/public/browser/navigation_throttle.h
97d4dc6
to
aba6d24
Compare
@nornagon @deepak1556 I re-implemented this event and the prevention logic using |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, with some minor changes. Thanks!
atom/browser/atom_browser_client.cc
Outdated
AtomBrowserClient::CreateThrottlesForNavigation( | ||
content::NavigationHandle* handle) { | ||
std::vector<std::unique_ptr<content::NavigationThrottle>> throttles; | ||
throttles.push_back(base::WrapUnique(new AtomNavigationThrottle(handle))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prefer std::make_unique
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Call me crazy, but std::make_unique
didn't compile ❓ and the equivalent CreateThrottlesForNavigation
inside chromium uses the base helper 🤔 I can look into changing it tomorrow if it's a big thing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Call me crazy, but std::make_unique didn't compile
Hmm it should work.
and the equivalent CreateThrottlesForNavigation inside chromium uses the base helper
yeah in this case its fine using either, but prefer make_unique
for creation of unique_ptr
, More context from chromium style guide https://www.chromium.org/developers/coding-style/cpp-dos-and-donts#TOC-Prefer-std::make_unique-to-base::WrapUnique
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would still like to see this resolved
auto* handle = navigation_handle(); | ||
auto* contents = handle->GetWebContents(); | ||
if (!contents) | ||
return PROCEED; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we let the navigation proceed if there are no web contents ? This case should definitely not happen, but in the rarest chance it occurs we should terminate the navigation otherwise potential for use-after-free bugs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah this is more like a NOREACHED()
but I thought I'd handle it for safety. Current behavior where we have no throttles would be for the navigation to proceed so I'd like to maintain that behavior. Might be worth adding a DCHECK
or something there so that it would cause failures in debug mode though?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Current behavior where we have no throttles would be for the navigation to proceed so I'd like to maintain that behavior
👍
auto api_contents = | ||
atom::api::WebContents::CreateFrom(v8::Isolate::GetCurrent(), contents); | ||
if (api_contents.IsEmpty()) | ||
return PROCEED; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Navigation should be terminated for the same reason mentioned above.
|
||
#include "content/public/browser/navigation_throttle.h" | ||
|
||
class URLPattern; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Unused declaration.
|
||
AtomNavigationThrottle::ThrottleCheckResult WillRedirectRequest() override; | ||
|
||
const char* GetNameForLogging() { return "AtomNavigationThrottle"; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const char* GetNameForLogging() override { }
@@ -27,6 +27,7 @@ | |||
#include "atom/browser/child_web_contents_tracker.h" | |||
#include "atom/browser/lib/bluetooth_chooser.h" | |||
#include "atom/browser/native_window.h" | |||
#include "atom/browser/net/atom_navigation_throttle.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you move the atom_navigation_throttle
under atom/browser
, the throttler is entirely used on the UI thread and it doesn't directly handle any component from //net
of chromium.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the DCHECKs should be CHECKs. It's scary to me that those supposedly-never-reached conditions result in allowing the navigation to occur. Safer to CHECK, if they're truly never reached.
atom/browser/atom_browser_client.cc
Outdated
AtomBrowserClient::CreateThrottlesForNavigation( | ||
content::NavigationHandle* handle) { | ||
std::vector<std::unique_ptr<content::NavigationThrottle>> throttles; | ||
throttles.push_back(base::WrapUnique(new AtomNavigationThrottle(handle))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would still like to see this resolved
auto* handle = navigation_handle(); | ||
auto* contents = handle->GetWebContents(); | ||
if (!contents) { | ||
DCHECK(false); // This should be unreachable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CHECK(false)
then?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason they are DCHECK
is to maintain existing behavior in release builds (see the comment chain above). Although this should be unreachable, in it's current state Electron would PROCEED
with the navigation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok. BTW NOTREACHED()
exists and should be used here (it just DCHECK(false)
es, but it documents itself and is greppable)
auto api_contents = | ||
atom::api::WebContents::CreateFrom(v8::Isolate::GetCurrent(), contents); | ||
if (api_contents.IsEmpty()) { | ||
DCHECK(false); // This should be unreachable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here too
… PostTask This avoids a potential race condition and immediately cancels the navigation
e8e9cb3
to
4b9e1e4
Compare
@nornagon This has been updated and I even made Assuming CI is green I'm gonna merge this in 👍 |
Release Notes Persisted
|
Example usage:
TODO:
Notes: added a
will-redirect
event on webContents to capture, handle and prevent redirects during navigations