When we click the download button in PDF.js, it downloads a blob://qute:...
URL. We can detect that and force a download rather than opening it in PDF.js
again.
Note that what actually happens depends on the Qt version and backend:
QtWebKit (any Qt version):
Downloads always work properly (regardless of Qt version).
QtWebEngine, Qt 5.7.1:
Downloads work.
QtWebEngine, Qt 5.9 - 5.11:
Downloads won't work as we need to tell PDF.js to not use blob: URLs:
https://bugreports.qt.io/browse/QTBUG-70420 - in theory, PDF.js could fall back
to downloading the existing qute:// URL, but it has a whitelist of schemes
which does not include qute://... Since it's not in that whitelist, it just
ends up doing nothing at all.
QtWebEngine, Qt 5.12:
Downloads should hopefully work properly again, as we can register the qute://
scheme with Chromium, which allows us to use blob:// URLs.
This reverts commit 9c731bde85627308fdde4730b0181a014096cb47.
We need to set some PDF.js options, so we can't just use the default viewer
with ?file=...
Previously calling `script.code()` would fail if the script didn't have
a `name`. This wasn't being hit in practice because the only place that
constructs GreasemonkeyScripts was checking for that condition and add
the filename there as a fallback.
This change make the `name` attribute more explicitly mandatory by
failing with a `ValueError` if it is not provided and make it still
possible to use the filename fallback in that case by adding a
`filename` keyward argument to `__init__()`.
Additionally where `script_meta` is used in `script.code()` a fallback
to and emptry string was added so it doesn't fail for raw javascript
files without greasemonkey metadata.
Otherwise, stuff goes haywire when trying to use the caret mode very fast (like
in a unit test), because new stuff runs before we've managed to update the selection.
Before Qt 5.11.2, for unique origins, we always got QUrl() and thus passed it
through.
With Qt 5.11.2, only missing origins (browser-initiated requests) get an empty
initiator, while unique origins get QUrl("null"):
https://codereview.qt-project.org/#/c/234849/https://bugreports.qt.io/browse/QTBUG-69372
In theory, those should be locked down (as an unique origin is e.g. a sandboxed
iframe) and never have access to any other content.
However, thanks to a Qt bug, XHR on qute:// pages has QUrl("null") as origin as
long as the URL scheme is not registered. We can only do the registering once
Qt 5.12 is out.
Since unique origins were effectively already allowed on Qt 5.11.0/.1, we pass
them through here as well until Qt 5.12.
See #4198
If the blacklist is only valid for the completion, the setting should also be
under completion.
This also un-renames history.gap_interval and renames
completion.web_history_max_items.
Fixes#3060
IOERR: The SQLITE_IOERR result code says that the operation could not finish
because the operating system reported an I/O error.
CANTOPEN: The SQLITE_CANTOPEN result code indicates that SQLite was unable to
open a file. The file in question might be a primary database file or on of
several temporary disk files.
This adds a new CompletionMetaInfo table which is a simple key/value store.
Thanks to Python/sqlite duck typing, we can use that to store values of any
type, even new ones in the future.
Currently, the only allowed key is force_rebuild, which forces a rebuild of the
CompletionHistory table. This will be needed for a future change.
`ListCategory` sorts its completion by default, we are already building
the categories in the right order so don't need that.
The test tests the case of where you have 11 tabs and if the model was
sorted the tabs with index 10 and 11 would be sorted before the one with
index 2.
The `random.sample` bit for the tab url and title is to also make sure
the model isn't being sorted on those columns, whithout haveng to write
and all ten lines.
We changed this a while ago in a2f62238f1
already, but Ctrl-V was kind of cumbersome as well, as it conflicted with
pasting.
Shift-Escape is closer to the default leave-mode binding (Escape), and also
unlikely to conflict as it's used for the task manager in Chrome.
- Update the docstring for repeat
- Remove the blank line after the docstring
- Update the docstring with scripts/dev/src2asciidoc.py
- Simplify the test
On Qt 5.7.1, window.print() caused a CommandError which wasn't handled as the
command was called from accept_navigation_request.
Instead, we now show the dialog in AbstractPrinting and use that directly.
Fixes#2603
The call to processEvents fixes an apparent race condition with some window
managers, e.g. i3. QT seems to be thinking, that the window is not marked as
urgent and toggles it twice, so synchronizing before issuing the alert makes QT
behave correctly.
This change should not change the behaviour on other systems only correct the
fault reported in #2603.
In ffc29ee043 (part of v1.0.0), a
qute://settings/set URL was added to change settings.
Contrary to what I apparently believed at the time, it *is* possible for
websites to access `qute://*` URLs (i.e., neither QtWebKit nor QtWebEngine
prohibit such requests, other than the usual cross-origin rules).
In other words, this means a website can e.g. have an `<img>` tag which loads a
`qute://settings/set` URL, which then sets `editor.command` to a bash script.
The result of that is arbitrary code execution.
Fixes#4060
See #2332
Add an additional argument to is_blocked for the current url, and enable
the host_blocking.enabled property to be set per domain.
This allows to bypass host blocking for specific domains
Moves the 5.8 check to `_WebEngineScripts.init()`.
Changes `_inject_userscripts` to allow for the two code paths. With
5.7.1 we need to specify the injection point and not clear all scripts
for each call, since we have to call it three times.
Change the 5.8+ hook to call a new method which passes all the scripts
into `_inject_userscripts` so that doesn't have to have a fallback
conditional inside it because thats an inversion of responsibility!
Pulling the remove scripts part into a seperate function and making it
the callers responsibilty to call that first would tidy it up a little
more but meh.
I was worried about just doing `_widget.page().urlChanged.connect()`
once at tab init, where before it was connected at page init, because I
was under the impression that the child page can be replaced at any
time, eg when navigating to a new origin. But under manual testing I
didn't see that at all. Maybe I was mistaken or maybe that only started
in a later Qt version.
QtWebEngine (via chromium) has the ability to run injected scripts in
isolated "worlds". What is isolated is just the javascript environment,
so variables and functions defined by the page and the script won't
clobber each other, or be able to interact (including variables saved to
the global `window` object). The DOM is still accessible from "isolated"
scripts.
This is NOT a security measure. You cannot put untrusted scripts in one
of these isolated worlds and expect it to not be able to do whatever
page js can do, it is just for namespacing convenience. See
https://stackoverflow.com/questions/9515704/insert-code-into-the-page-context-using-a-content-script
for some examples of how to inject scripts into the page scope using DOM
elements.
Now you can specify the world ID in a `@qute-js-world` directive like:
```
// ==UserScript==
// @name Do thing
// @match *://some.site/*
// @qute-js-world 1234
// ==/UserScript==
document.body.innerHTML = "<strong>overwritten</strong>"
```
The QtWebEngine docs say worldid is a `quint32` so you can put whatever
number (positive, whole, real) you want there. I have chosen to allow
the `qutebrowser.utils.usertypes` enum as aliases for IDs that are
predefined in
`qutebrowser.browser.webengine.webenginetab._JS_WORLD_MAP`. So you can
pass `main`, `application`, `user` or `jseval` in there too. `main` (0)
is the default one and is the only one in which JS disabled when
`content.javascript.enabled` is set to `false`. All others are still
enabled.
I'm not sure whether using any of those already-named worlds makes
sense, apart from `main`. We could stop people from using them I
suppose. Another option is to allow people to pass in `*` as a value to
have scripts put into their own little worlds, probably backed by a
counter in the GreaseMonkeyManager class.
Chrome docs: https://developer.chrome.com/extensions/content_scripts#execution-environment
Webengine docs: https://doc.qt.io/qt-5/qwebenginescript.html#details