Add new API for extensions (required for cosmetic filtering + scriptlet injection) #7630
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
As per #7629 (comment), I've separated out the API changes required by #7629 into another PR. The proposed API changes are, however, general enough that they can be used for other components/extensions. For example, per-domain user stylesheets (#3854) would be very simple to implement as a separate component/extension using the newly suggested
api.hook.before_loaded
andapi.Tab.add_dynamic_css
. I believe the proposed changes should also be enough to support something like Dark Reader in qutebrowser (#3780).API Changes
api.hook.before_loaded
A hook that is guaranteed to be notified before a page loads. Components which need to do something before a page loads should use this hook. Note the hook may be called multiple times before a page loads. The
api.Tab
object which is about to load and the url which we are about to load are passed in as arguments.api.hook.load_started
A hook that is called after the page loads. Components which need to do something after a page starts loading should use this hook. The
api.Tab
object which is starting to load is passed in as an argument.api.hook.load_finished
A hook that is called after the page finishes loading. Components which need to do something after a page load finishes should use this hook. The
api.Tab
object which just finished loading and the success flag of whether the load was done successfully is passed in as arguments.api.Tab.add_dynamic_css
Adds css which will get applied to every page the
api.Tab
object loads. This has lower precedence than the user-specified stylesheet in the user config. This css is expected to change often, hence the "dynamic".api.Tab.remove_dynamic_css
Removes the aforementioned css which will get applied to every page the
api.Tab
object loads.api.Tab.add_web_script
Adds a snippet of javascript to be executed during the
api.Tab
object's page load. The specific moment in which the web script executes can be controlled withapi.usertypes.InjectionPoint
. These "web scripts" are intentionally separated from the greasemonkey scripts. Greasemonkey scripts are added and managed by the end user, but these scripts are meant to be used by the components/extensions of qutebrowser.api.Tab.remove_web_script
Removes the aforementioned snippet of javascript to be executed during the
api.Tab
object's page load.api.usertypes.InjectionPoint
A type representing the point at which to execute an injected web script.
Non-API changes to core implementation
Emitting
api.Tab.before_loaded
signal multiple timesIn addition to being emitted during
_load_url_prepare
, theapi.Tab.before_load_started
signal is now also emitted during_on_navigation_request
. The reason for this is that_load_url_prepare
is not always called before a new page loads. For example, this can happen when a non-clickable object is clicked to open in the background. In this case,TabbedBrowser.tabopen
will be called withurl=None
, soload_url
and_load_url_prepare
are not called. However,_on_navigation_request
is always called, and the url is always known by this point. For a reliableapi.hook.before_loaded
hook, it is essential we emitbefore_load_started
during_on_navigation_request
as well. We don't want to remove the emit from_load_url_prepare
either, since that gets called before_on_navigation_request
, and we need the hook to fire as soon as possible.Other changes
_update_stylesheet
now also includesstylesheet.js
in its injected script (wrapped in the global wrapper) because sometimes asynchronous code runs before injected scripts, andstylesheet.set_css
will obviously fail ifwindow._qutebrowser.stylesheet
has not been specified.