Skip to content
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

Event or method to intercept page redirects/navigation #456

Closed
1 of 2 tasks
atlanticaccent opened this issue Dec 24, 2021 · 6 comments · Fixed by #515
Closed
1 of 2 tasks

Event or method to intercept page redirects/navigation #456

atlanticaccent opened this issue Dec 24, 2021 · 6 comments · Fixed by #515
Labels
help wanted Help is requested to fix this issue platform: All type: feature request

Comments

@atlanticaccent
Copy link
Contributor

atlanticaccent commented Dec 24, 2021

Is your feature request related to a problem? Please describe.
I'd like to be able to detect or monitor when the URL of a webview changes, for instance, when clicking on a link. This can be helpful for implementing things like custom download behaviour.

Describe the solution you'd like
Either a new event describing the URL the current webview or a new webview has navigated to OR a function that can be called on a the WebviewBuilder which allows the registration of a callback which is executed whenever navigation ocurrs.

Describe alternatives you've considered
You could register HTTP/HTTPS as custom protocols, do the fetch yourself in rust then pass the resulting data through, though this seems a bit extreme if you want to just say log page navigations.

You could also potentially insert an onbeforeunload handler using the with_initialization_script builder function, though that might not catch certain navigations events or popups (which may themselves be another problem altogether). There could be a number of other ways to do this through pure javascript too.

Would you assign yourself to implement this feature?

  • Yes
  • No

Additional context
There may be an obvious way to do this that I haven't seen, but I can't find it.

@wusyong wusyong added platform: All help wanted Help is requested to fix this issue type: feature request labels Dec 27, 2021
@atlanticaccent
Copy link
Contributor Author

I'm interested in trying to tackle this - no idea if what I produce will be usable though.
Would anyone be able to provide pointers on where I should look to find the networking code to get started?

@atlanticaccent
Copy link
Contributor Author

Unfortunately, having taken a brief look at the code available, I'm not sure this feature could be implemented without significant rewriting of the existing library, though I also don't have a complete grasp of how everything works yet.

With so much of the navigation logic occurring in FFI/callbacks, there isn't really a way to pre-empt navigation or notify that a navigation has occurred.

The best solution I can think of so far is to utilise a local proxy. This would ensure that all network requests made by the webview are captured (JavaScript and a custom protocol handler as described in the original issue would not cover cases where JavaScript inserts links after page load, for example). The good news is that it should be possible to implement inserting a proxy on Windows and Linux, the bad news is the macOS categorically has no way of doing this as proxying a WKWebView shows no signs of ever being implemented.

Therefore, I'll be making an attempt at implementing passing a proxy value on Windows and Linux, but won't be pursuing a "proper" solution to this issue.

@nothingismagick
Copy link
Member

My advice is to consider a cross platform approach that would work under specific circumstances. It does not need to work for everyone all the time, but it can be seen as one option under specific premises. This is the benefit of feature gating.

@atlanticaccent
Copy link
Contributor Author

Alright, I've given this another shot "properly". What I've discovered however is that this can only be done wit breaking changes in either wry or tao.
For windows at least (I haven't checked other platforms but I assume it's similar) we can write a handler for the NavigationStarting event (the webview2 event for when a navigation is started). We then run into how we actually emit an event into the tao event loop from this handler. We have access to Window, however window doesn't give us a way to submit events. There's the thread executor (which is not a proxy as the comment next to it suggests) but we can't send events through that.

This leaves two options, I believe:

  • Make a breaking change to tao such that it holds an event proxy, however this means making Window generic over T
  • Make a breaking change to wry where we insert an event proxy into the various webview builders (maybe by attacking it to WebContext?

Actually, now that I think about this, we could add a builder method on WebContext, which takes an EventProxy then modify the platform specific inner webview builders to pass that around... I'm going to pursue that approach - let me know if this comment is too much out loud thinking

@atlanticaccent
Copy link
Contributor Author

I've effectively got what I believe would be a working implementation of this, for windows at least. However, the approach I took does not seem to work due to the fact that the library is not actually multithreaded - that is, the thread executing the webview callback functions also appears to be the same thread that executes the event loop. This means that you cannot, as I attempted, pass a oneshot channel to the event loop whilst executing the (webview2) navigation event handler so that you could decide whether to cancel a navigation "at runtime".

I'll continue implementing the event loop approach as I have (we can still deliver an event detailing a navigation that has already happened) but it will only be possible to cancel a navigation by defining preset conditions.

I'll create a PR for this shortly - the Windows functionality will be the best tested/written as I don't have access to a linux or mac machine at the moment.

@atlanticaccent
Copy link
Contributor Author

I have opened PR #519 which would close this issue. It currently includes an implementation for Windows and a basic example.

There's some open points of discussion I mention there that could use some clarification,

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Help is requested to fix this issue platform: All type: feature request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants