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

Plugin support #30

Open
The-Compiler opened this Issue Oct 1, 2014 · 75 comments

Comments

Projects
@The-Compiler
Collaborator

The-Compiler commented Oct 1, 2014

There should be support for writing plugins which are more complex than the simple (non-js) userscripts.

Python plugins are the way to go. Javascript support would be cool but is currently hard because there's no second JS context.

WebExtensions

Support for WebExtensions is currently out-of-scope for qutebrowser. It's hard to even evaluate to which extend support for them would be possible, but if possible, it's going to be a lot of work. Partial support for often used plugin APIs (i.e. some WebExtensions) might happen some day, but currently it's too early to say if/when. The main focus is on a Python plugin API right now. Related QtWebEngine issues which might make this easier: QTBUG-51185, QTBUG-61676.

Plugin ideas

  • Adblock (probably better in core?) (implemented in core)
  • Ghostery/Disconnect
  • Certificate Patrol
  • Remove google redirects
  • Filling forms (e.g. password management with KeePassX/gnome keyring/passwordstore/... - as in #180, also form filling as in #695)
  • HoverZoom
  • speed dial
  • periodic auto-reload
  • detailed page loading bar (like otter/opera)
  • automatically spawn mpv on video pages
  • copy URLs of all pages or write them to a file
  • DownThemAll
  • Google Cloud Print (devguide)
  • Rewriting URLs to their .onion equivalents based on a list
  • Chromecast integration? (#1319)
  • autoscroll
  • decentraleyes
  • URL rewriting like PureURL for Firefox (removing things like utm_foo)
  • Open certain links (like youtube) in a handler application automatically instead of following it
  • Adding a "real" address bar
  • Adding a bookmarks bar
  • Yanking a short URL (e.g. youtube has a shortlink ref for youtu.be links)
  • Restarting failed downloads after a timeout (with bad internet connection)
  • alternative stylesheet selector
  • A way to show md5/sha/etc. for downloads or even enter the correct one.
  • Plasma Shell browser integration (#3996)
  • also see existing dwb userscripts

Abilities that plugins should have

  • Interact with the WebElements on the page (e.g. make non-clickable links clickable) - or maybe only do this via JS, e.g. Linkify.
  • Add widgets to the statusbar. (e.g. RSS or search engine symbol)
  • Register new commands (with capital letter, like vim)
  • Register new settings (in a special [plugin.foo] section probably)
  • Subscribe to Qt signals (QWebPage/QWebView)
  • Add new completions, e.g. with an external bookmark manager like cym13/bookmark
  • Create widget-tabs when #724 is done, so someone could theoretically write an RSS reader or mail client or whatever
  • Adjust page content, like Detox (and many others)
  • Maybe make it possible to interact with the command input so that adding www. and .com to an URL like in #1749 would be possible.
  • Maybe bind keys with prefixes, e.g. g# with any number
  • Custom URL schemes
  • Custom completions (see #3376)

Libraries

Resources

Javascript plugins

  • Javascript: QJSEngine
  • PyV8 would probably work as well for javascript extensions (and maybe be easier/more pythonic), but it's another dependency and a different javascript engine.

Possible API inspirations

Other interesting links

First ideas

Separate namespace for plugins

There should be a new qutebrowser.pluginapi namespace. Everything outside of that namespace is to be considered to be "private" for plugins, and will likely break at some point.

Only some stuff (like possibly utils.urlutils) will be exposed directly - everything else will be exposed through a wrapper, for various reasons:

  • I can change stuff without breaking plugins, if I update the wrappers accordingly.
  • The wrappers will be easier to expose to a javascript plugin API
  • They will be less complex than the qutebrowser internals, so it should be easier to get started

If something is missing from the wrappers, it should be trivial for a plugin author to open a feature request to have it added - this should be encouraged in the docs.

Qt signal based workflow

I don't think using something like pluggy will be neccessary (especially because pluggy is still expected to undergo changes, and is not packaged).

Instead of that, there's a simple function (say, plugin_init) which gets called when a plugin is loaded. The plugin gets a PluginContext object with some version information and a signals attribute.

The signals object then has many signals (perhaps also in sub-objects), like started, cmd.entered, etc. etc. Such a signals object also exists per-tab and per-window. The plugin will get the window-specific object with a global new_window signal (and something similar for new tabs).

Those events/signals are the main entry point for plugins. There will also be APIs for certain tasks (like adding an icon to the statusbar), but the majority of tasks should be possible using those signals.

For most actions, an API to call commands nicely (i.e. as functions rather than as strings) would probably already suffice.

Exposing plugin signals to userscripts

This is related to #902 - the signals mentioned above should be written to userscript FIFOs so those can react on the events - similar to herbstluftwm's hooks and herbstclient --idle.

This could possibly be implemented as a plugin by itself, which binds to all available signals - some layer to transform the signal arguments to strings will be needed either way.

A line written to the FIFO could look like this:

category sender signalname arg1 arg2 ...
  • category: For extensibility - currently always signal
  • sender: A dotted path of the sender of the signal, i.e. which signal object from above emitted the signal:
    • global: A global signal, like started
    • win0: A signal from the window with win ID 0
    • win0.tab1: A signal from the tab 1 in window 0
  • signalname: A dotted path of the signal, e.g. started or cmd.entered, etc.
  • arg1, arg2: Arguments which were passed to the signal, which need to be converted to a string in some way. Either there's a plugin which handles this argument for argument, or there's type-checking:
    • str: passed through
    • int, float: str() called on them
    • QUrl: url.toString() called on them
    • window objects -> win0
    • tab objects -> win0.tab1

Resources from BPL

resources

libraries & apps

@noctuid

This comment has been minimized.

Show comment
Hide comment
@noctuid

noctuid Apr 14, 2015

automatically spawn mpv on video pages

Just to contribute to this idea for a possible future plugin, it would be awesome to be able to bind a key to manually invoke mpv (or another player with :spawn) on the direct link (not the {url}) of a playing video. With pentadactyl I do this with the firefox media sniffer plugin currently.

noctuid commented Apr 14, 2015

automatically spawn mpv on video pages

Just to contribute to this idea for a possible future plugin, it would be awesome to be able to bind a key to manually invoke mpv (or another player with :spawn) on the direct link (not the {url}) of a playing video. With pentadactyl I do this with the firefox media sniffer plugin currently.

@cwmke

This comment has been minimized.

Show comment
Hide comment
@cwmke

cwmke Aug 22, 2015

Just thought I would throw a couple possibilities/alternatives into the mix for long term feature ideas. Ublock Origin, Umatrix, Random-Agent-Switcher. Also, pass support would be amazing. http://www.passwordstore.org/ Thanks for this incredible project. I'm really excited for its future.

cwmke commented Aug 22, 2015

Just thought I would throw a couple possibilities/alternatives into the mix for long term feature ideas. Ublock Origin, Umatrix, Random-Agent-Switcher. Also, pass support would be amazing. http://www.passwordstore.org/ Thanks for this incredible project. I'm really excited for its future.

@lamarpavel

This comment has been minimized.

Show comment
Hide comment
@lamarpavel

lamarpavel Aug 22, 2015

Contributor

@cwmke The integration of password managers has come up in several suggestions before and it is unlikely that one specific password manager will be integrated into qutebrowser, rather there might be an abstract interface that can be used with many different password managers.

Until then, there are user scripts for this purpose, for example this one.

Contributor

lamarpavel commented Aug 22, 2015

@cwmke The integration of password managers has come up in several suggestions before and it is unlikely that one specific password manager will be integrated into qutebrowser, rather there might be an abstract interface that can be used with many different password managers.

Until then, there are user scripts for this purpose, for example this one.

@The-Compiler

This comment has been minimized.

Show comment
Hide comment
@The-Compiler

The-Compiler Sep 1, 2015

Collaborator

I added some thoughts to "First ideas" above - any feedback would be much appreciated!

Collaborator

The-Compiler commented Sep 1, 2015

I added some thoughts to "First ideas" above - any feedback would be much appreciated!

@The-Compiler The-Compiler removed their assignment Oct 1, 2015

@traverseda

This comment has been minimized.

Show comment
Hide comment
@traverseda

traverseda Nov 19, 2015

Has any progress been made in this direction?

traverseda commented Nov 19, 2015

Has any progress been made in this direction?

@The-Compiler

This comment has been minimized.

Show comment
Hide comment
@The-Compiler

The-Compiler Nov 19, 2015

Collaborator

No, not yet. Tests, the QtWebEngine backend, config revolution and per-domain settings are the current main focus. After that I'll look at this, but it's probably going to take a few months.

Collaborator

The-Compiler commented Nov 19, 2015

No, not yet. Tests, the QtWebEngine backend, config revolution and per-domain settings are the current main focus. After that I'll look at this, but it's probably going to take a few months.

@traverseda

This comment has been minimized.

Show comment
Hide comment
@traverseda

traverseda Nov 19, 2015

Seems like reasonable priorities. Just though I'd drop in and remind you that this issues exists.

A lot of projects, like django, allow you to include apps that are basically just python code. You can get a long way with monkey patching, and just providing some entry points.

Is there a reason you don't provide a quick and hacky solution? Load and run python scripts from a directory or something?

traverseda commented Nov 19, 2015

Seems like reasonable priorities. Just though I'd drop in and remind you that this issues exists.

A lot of projects, like django, allow you to include apps that are basically just python code. You can get a long way with monkey patching, and just providing some entry points.

Is there a reason you don't provide a quick and hacky solution? Load and run python scripts from a directory or something?

@The-Compiler

This comment has been minimized.

Show comment
Hide comment
@The-Compiler

The-Compiler Nov 19, 2015

Collaborator

Yes, because I don't like quick and hacky solutions 😉

I don't want third party plugins which break with every release, there's already Firefox for that 😉 - so I'd like to do things right.

Collaborator

The-Compiler commented Nov 19, 2015

Yes, because I don't like quick and hacky solutions 😉

I don't want third party plugins which break with every release, there's already Firefox for that 😉 - so I'd like to do things right.

@traverseda

This comment has been minimized.

Show comment
Hide comment
@traverseda

traverseda Nov 19, 2015

Fair enough

traverseda commented Nov 19, 2015

Fair enough

@btall

This comment has been minimized.

Show comment
Hide comment
@btall

btall Mar 25, 2016

👍 Ghostery/Disconnect and Remove google redirects

btall commented Mar 25, 2016

👍 Ghostery/Disconnect and Remove google redirects

@RomanSC

This comment has been minimized.

Show comment
Hide comment
@RomanSC

RomanSC Jun 8, 2016

RomanSC commented Jun 8, 2016

@The-Compiler

This comment has been minimized.

Show comment
Hide comment
@The-Compiler

The-Compiler Jun 8, 2016

Collaborator

@RomanSC: I think you mean the ability to use adblock-style lists rather than just hosts, because all of the default block lists are already third party, and you can add your own 😉

See #29 for that, though it's not a priority for me currently, as the simple host-blocker we have now works well enough for 95% of the cases.

Collaborator

The-Compiler commented Jun 8, 2016

@RomanSC: I think you mean the ability to use adblock-style lists rather than just hosts, because all of the default block lists are already third party, and you can add your own 😉

See #29 for that, though it's not a priority for me currently, as the simple host-blocker we have now works well enough for 95% of the cases.

@pkillnine

This comment has been minimized.

Show comment
Hide comment
@pkillnine

pkillnine Dec 16, 2017

@oblitum I think support for lpass could easily be added to userscript password_fill or qute-pass.

pkillnine commented Dec 16, 2017

@oblitum I think support for lpass could easily be added to userscript password_fill or qute-pass.

@The-Compiler The-Compiler referenced this issue Dec 17, 2017

Closed

surfraw #3410

@biinari

This comment has been minimized.

Show comment
Hide comment
@biinari

biinari Dec 18, 2017

@oblitum I've made a backend to password_fill for lpass: https://gist.github.com/biinari/e5611220f90258552cd85032c9c09021 - it could be improved upon but works reasonably well for starters.

biinari commented Dec 18, 2017

@oblitum I've made a backend to password_fill for lpass: https://gist.github.com/biinari/e5611220f90258552cd85032c9c09021 - it could be improved upon but works reasonably well for starters.

@oblitum

This comment has been minimized.

Show comment
Hide comment
@oblitum

oblitum Dec 18, 2017

@biinari cool thanks for that.

oblitum commented Dec 18, 2017

@biinari cool thanks for that.

@The-Compiler

This comment has been minimized.

Show comment
Hide comment
@The-Compiler

The-Compiler Mar 22, 2018

Collaborator

Some more notes on my opinion on plugin security

Sandboxing Python in some safe way is widely regarded as impossible - instead, I think it's fine for qutebrowser to trust plugins.

Manually installed

If people dump stuff in their ~/.local/share/qutebrowser/plugins or whatever it'll be, it's their responsibility to ensure it's safe.

Plugin manager

For plugins installed via some kind of plugin manager (or something like a :plugin-install), there could be a plugin registry somewhere - for example in some JSON/YAML file in the repository, which gets downloaded by qutebrowser with a :plugin-update or so. That file could contain entries like:

exampleplugin:
  repo: https://github.com/example/qutebrowser-exampleplugin
  version: 1.0
  commit: 11a94957dc038fc27c5ff976197ad2b2d0352d20

Then when people write a new plugin or release a new version of an existing one, this happens:

  • They push their plugin to a GitHub repository
  • They open a PR against qutebrowser to update the plugin index
  • A qutebrowser maintainer does a quick review of the plugin code to make sure it doesn't do anything clearly stupid or malicious and merges the PR
  • qutebrowser uses that file to offer plugins to install, and when downloading a plugin, makes sure the commit (or possibly some hash on a GitHub .zip file, depending on implementation) matches.

That means there's at least some review of what plugins want to do (but people can still install plugins manually). It still should be documented that qutebrowser isn't responsible for whatever happens in plugins.

External libraries

It gets trickier when plugins require external (Python/C) libraries. Not even sure if qutebrowser's plugin manager will be able to install them. If not, it gets tricky for people using the macOS/Windows builds to install plugins, though...

Feedback welcome! 😄

Collaborator

The-Compiler commented Mar 22, 2018

Some more notes on my opinion on plugin security

Sandboxing Python in some safe way is widely regarded as impossible - instead, I think it's fine for qutebrowser to trust plugins.

Manually installed

If people dump stuff in their ~/.local/share/qutebrowser/plugins or whatever it'll be, it's their responsibility to ensure it's safe.

Plugin manager

For plugins installed via some kind of plugin manager (or something like a :plugin-install), there could be a plugin registry somewhere - for example in some JSON/YAML file in the repository, which gets downloaded by qutebrowser with a :plugin-update or so. That file could contain entries like:

exampleplugin:
  repo: https://github.com/example/qutebrowser-exampleplugin
  version: 1.0
  commit: 11a94957dc038fc27c5ff976197ad2b2d0352d20

Then when people write a new plugin or release a new version of an existing one, this happens:

  • They push their plugin to a GitHub repository
  • They open a PR against qutebrowser to update the plugin index
  • A qutebrowser maintainer does a quick review of the plugin code to make sure it doesn't do anything clearly stupid or malicious and merges the PR
  • qutebrowser uses that file to offer plugins to install, and when downloading a plugin, makes sure the commit (or possibly some hash on a GitHub .zip file, depending on implementation) matches.

That means there's at least some review of what plugins want to do (but people can still install plugins manually). It still should be documented that qutebrowser isn't responsible for whatever happens in plugins.

External libraries

It gets trickier when plugins require external (Python/C) libraries. Not even sure if qutebrowser's plugin manager will be able to install them. If not, it gets tricky for people using the macOS/Windows builds to install plugins, though...

Feedback welcome! 😄

@gebulmer

This comment has been minimized.

Show comment
Hide comment
@gebulmer

gebulmer Mar 22, 2018

Contributor

I don't know if it's even worth making a built-in plugin manager, just having a standard directory to dump them is enough. A plugin manager would then be simply another plugin, registering its commands in the usual (provided) way, that handles the others.

Contributor

gebulmer commented Mar 22, 2018

I don't know if it's even worth making a built-in plugin manager, just having a standard directory to dump them is enough. A plugin manager would then be simply another plugin, registering its commands in the usual (provided) way, that handles the others.

@pkillnine

This comment has been minimized.

Show comment
Hide comment
@pkillnine

pkillnine Mar 22, 2018

I do like the idea of an official qutebrowser plugin repo that is maintained, since plugins are going to be assumed to be fully trusted. Maybe a simple compromise could be to ship qutebrowser with an official plugin manager, which is simply another plugin (like @gebulmer said), with the official qutebrowser plugin repo? This way if someone wants to use a different plugin manager they can easily remove the default one.

pkillnine commented Mar 22, 2018

I do like the idea of an official qutebrowser plugin repo that is maintained, since plugins are going to be assumed to be fully trusted. Maybe a simple compromise could be to ship qutebrowser with an official plugin manager, which is simply another plugin (like @gebulmer said), with the official qutebrowser plugin repo? This way if someone wants to use a different plugin manager they can easily remove the default one.

@traverseda

This comment has been minimized.

Show comment
Hide comment
@traverseda

traverseda Mar 22, 2018

It seems to me like the obvious plugin manager is... pip. It does everything you'd need. I don't know how easy it would be to have a per-user/per-profile virtualenv, but that would certainly make things easier.

traverseda commented Mar 22, 2018

It seems to me like the obvious plugin manager is... pip. It does everything you'd need. I don't know how easy it would be to have a per-user/per-profile virtualenv, but that would certainly make things easier.

@The-Compiler

This comment has been minimized.

Show comment
Hide comment
@The-Compiler

The-Compiler Mar 22, 2018

Collaborator

Yeah, I've had that in the back of my mind for a while as well. I'm not sure how well it'd work with locally installed plugins and with frozen distributions (macOS/Windows), but it's certainly worth some more thought.

Collaborator

The-Compiler commented Mar 22, 2018

Yeah, I've had that in the back of my mind for a while as well. I'm not sure how well it'd work with locally installed plugins and with frozen distributions (macOS/Windows), but it's certainly worth some more thought.

@lamarpavel

This comment has been minimized.

Show comment
Hide comment
@lamarpavel

lamarpavel Mar 23, 2018

Contributor

That would mean pip becomes a qb dependency for regular users?
Also, I don't see how pip makes any guarantees about which plugins were curated by qutebrowser developers.

Contributor

lamarpavel commented Mar 23, 2018

That would mean pip becomes a qb dependency for regular users?
Also, I don't see how pip makes any guarantees about which plugins were curated by qutebrowser developers.

@The-Compiler

This comment has been minimized.

Show comment
Hide comment
@The-Compiler

The-Compiler Mar 27, 2018

Collaborator

That would mean pip becomes a qb dependency for regular users?

Indeed, that probably wouldn't be a problem, though. I'm pretty sure it's available on any Linux distribution, and it can be shipped with qutebrowser binaries for macOS/Windows.

Also, I don't see how pip makes any guarantees about which plugins were curated by qutebrowser developers.

It doesn't - but qutebrowser can do so. If the user invokes pip by hand, it's the same situation like them throwing a plugin somewhere by hand - it's their fault™ 😉

Collaborator

The-Compiler commented Mar 27, 2018

That would mean pip becomes a qb dependency for regular users?

Indeed, that probably wouldn't be a problem, though. I'm pretty sure it's available on any Linux distribution, and it can be shipped with qutebrowser binaries for macOS/Windows.

Also, I don't see how pip makes any guarantees about which plugins were curated by qutebrowser developers.

It doesn't - but qutebrowser can do so. If the user invokes pip by hand, it's the same situation like them throwing a plugin somewhere by hand - it's their fault™ 😉

@Yodzorah

This comment has been minimized.

Show comment
Hide comment
@Yodzorah

Yodzorah May 22, 2018

About 'uMatrix': I think, better to look at 'ContentBlockHelper' extension for Chrome (doesn't work for Firefox now), since it has the same goal and more useful features (just isn't as likable as 'uMatrix' because of awful design and one annoying bug).

Yodzorah commented May 22, 2018

About 'uMatrix': I think, better to look at 'ContentBlockHelper' extension for Chrome (doesn't work for Firefox now), since it has the same goal and more useful features (just isn't as likable as 'uMatrix' because of awful design and one annoying bug).

@def14nt

This comment has been minimized.

Show comment
Hide comment
@def14nt

def14nt Oct 17, 2018

@The-Compiler This isn't really my field, but wouldn't it be better to use the JavaScript engine that qutebrowser uses, instead of using a different one?

def14nt commented Oct 17, 2018

@The-Compiler This isn't really my field, but wouldn't it be better to use the JavaScript engine that qutebrowser uses, instead of using a different one?

@The-Compiler

This comment has been minimized.

Show comment
Hide comment
@The-Compiler

The-Compiler Oct 17, 2018

Collaborator

@def14nt I'll need more context for that question. The current focus are Python plugins anyways, not JS plugins. As for JS plugins, qutebrowser can't run any JS in QtWebEngine which has more permissions than the page has.

Collaborator

The-Compiler commented Oct 17, 2018

@def14nt I'll need more context for that question. The current focus are Python plugins anyways, not JS plugins. As for JS plugins, qutebrowser can't run any JS in QtWebEngine which has more permissions than the page has.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment