In the linux branch when it was doing:
header, *lines, empty, result = text.split("\n")
assert not empty
It was complaining that "empty" was "}", because the windows sandbox
page has JSON at the bottom now. The whole things looks to have changed
completely. I'm actually surprised it was working before, why would it
have been saying seccomp was enabled on windows?
Anyway, I did the debug-dump-text --plain that quteproc is doing in a VM
and tested this with sandboxing off an on. No idea how stable that will
be!
ref: https://github.com/qutebrowser/qutebrowser/issues/7989
Since the bug was fixed in qtbase it shouldn't matter what version of
PyQt (or webengine for that matter) you are running against. So pass
`compiled=False`.
Also expand the docstring of `check_version()` to explain a little more
what the `compiled` kwarg does. Based on a discussion here:
https://github.com/qutebrowser/qutebrowser/pull/7933#issuecomment-1732400960
What's still not clear to me is when the runtime and compiled Qt
versions can differ. I always have to rebuild PyQt when I switch Qt
versions, but maybe I'm doing something wrong there.
This avoids having to mess about with static methods. And makes the test a bit
clearer as we aren't passing a class in place of an instance anymore.
Hopefully I put it in the right place. It's above the class where it is used.
Should it be at the top of the file? Bottom of the file? IDK
Works around a Qt bug where QFileDialog might not see all the filename
extensions you have registered for a mimetype. There is an issue where
if you have suffixes (filename extensions) registered in your home dir
and in a system dir, it'll only see the ones in your home dir.
So get suffixes from python and proactively add them into the list the
list provided by the website. Duplicating work that Qt would already do,
if it weren't for the bug case we are working around.
Note that this does NOT help with mimetypes like `image/*` which, we
have seen in at least one example (on #7866). If we wanted to handle
that case it it looks like we could get the list from:
[suffix for suffix, mime in mimetypes.types_map.items() if mime.startswith('image/')]
I added two tests. The first is a simple one but it felt a bit
imcomplete without actually testing that we were passing the right thing
to `super().chooseFiles()`. Not sure how "bad" it is to be mocking
`super()` and what should be instance methods unbound from the class.
Regarding the `qtutils.version_check()`, here we are only interested in
the Qt version check, but that class also checks the PyQt version. The
practical effect of this is that we would probably end up doing the
workaround for Qt 6.7.0 if we run against that with PyQt 6.6.x. But
since we are just adding stuff, it isn't slow and isn't called in a hot
path it doesn't really matter.
I previously changed the assertion to be a subset match, to deal with a qt arg
being added based on the Qt version the tests were being run on. I didn't
notice this fixture that can set setting to avoid that dynamic-ness instead.
I would like to be able to disable this workound for new enough chromium
versions (we still need to test that chrome 111 will be fixed, but we
can always bump it up later).
I also wanted to use the declarative mapping `_WEBENGINE_SETTINGS` instead
of adding a new conditional in `_qtwebengine_args`, because that just
seems nicer.
So I changed `_WEBENGINE_SETTINGS` so that the value could also be a
function. The idea is that the function returns on of the other values
based on some feature detection. This also required passing down the
args being used for feature detection in the calling method already.
I feel like that dict is being a bit abused here and if the entries
could be turned into objects with a bit more consistency it might be
nice. But this isn't too bad, right?
Had to change the `test_qt_args` test to be a superset test instead of
exact match because the new `--disable-accelerated-2d-canvas` arg was
showing up in the results based on whatever Qt version you happen to be
running the tests on.
We replace the `(testdata)` placeholder with `testutils.abs_datapath()` in a few end2end
tests. So far we only needed to replace `(testdata)` with an OS path (e.g. in
`tests/end2end/features/spawn.feature`). By introducing `(testdata)` to an end2end test
in `tests/end2end/features/hints.feature`, we required a new use case: replacing
`(testdata)` as part of a valid file:// URI.
```
When I open file://(testdata)/some/file.txt
```
Replacing `(testdata)` in above BDD step with a plain OS path resulted in invalid URIs,
e.g. for the path "C:\\Users" above BDD step results in this invalid URI:
```
When I open file://C:\Users/some/file.txt
```
We deal with this by first isolating the `(testdata)` substitution in a single place.
Having `(testdata)` substitutions in a single place, we simply special-case the substitution
of file:// paths, which will be part of a URI.
Successful substitution for above BDD step looks like the following:
```
When I open file:///C:/Users/some/file.txt
```
As of Qt 6 navigating from local to remote origins requires user interaction. This broke
following links to remote origins via hints from a local file (e.g. `bookmarks.html`),
because hints use JavaScript to open links by default.
Example:
1. Have a local `bookmarks.html`:
```html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>My bookmarks</title>
</head>
<body>
<a href="https://example.com/" id="link">some bookmark</a>
</body>
</html>
```
2. Open that local `bookmarks.html` in qutebrowser (e.g. `:open path/to/bookmarks.html`)
3. Start hinting
4. Follow a link to a bookmark (e.g. https://example.com/)
5. Instead of the link opening, be presented with `Your internet access is blocked`
error
To fix this, we simply force a user interaction for all hints on file:// URLs (like we
did for `qute://` URLs in 8defe1ae44).
We skip the end2end test for webkit, because webkit does not support URLSearchParams[1]
used in `tests/end2end/data/hints/link_inject.html`
[1] https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams
Given the following scenario:
```
When I open file://(testdata)/some/file.html
Then file://(testdata)/some/file.html should be loaded
```
If the end2end data directory is not normalized, the scenario fails because we try to
compare
```
file:///home/palbrecht/dev/qutebrowser/tests/helpers/../end2end/data/hints/link_inject.html?port=50…
```
to
```
file:///home/palbrecht/dev/qutebrowser/tests/end2end/data/hints/link_inject.html?port=50…
```
Normalizing the path resolves the `..` and fixes the issue.
When handling counts during keyparsing we convert the count string to an integer. If the
count is too high (i.e. the count string has too many digits), we run into Python's
integer string conversion length limit[1]:
```
ValueError: Exceeds the limit (4300 digits) for integer string conversion: value has
4301 digits; use sys.set_int_max_str_digits() to increase the limit
```
Instead of blowing up with an exception, we now handle this more gracefully by showing
an error message.
Reproducer:
```
$ qutebrowser --temp-basedir ":later 500 fake-key -g $(printf '1%.0s' {1..4301})j"
```
**NOTE:**
I had to rename `_debug_log()`'s `message` argument to `msg`, because pylint yelled at
me for redefined-outer-name[2].
[1] https://docs.python.org/3/library/stdtypes.html#integer-string-conversion-length-limitation
[2] https://pylint.readthedocs.io/en/stable/user_guide/messages/warning/redefined-outer-name.html
This is required to use BDD steps like the following:
```
When I open file://path/to/file.html
```
If we don't treat `file:` as a special scheme, we implicitly convert it to an invalid
URL:
```
http://localhost:48595/file:///path/to/file.html
```
With Qt 6.3+, user interaction is required to navigate outside of qute:// from a
qute:// page.
Follow-up to 8defe1ae44.
Also see 216a9f9a9bFixes#7815
See #7220 - should be revisited once we have a qute-bookmarks:// instead where
we can adjust permissions when registering the URL handler.
Opening a download in a new tab leaves a "dead" tab (see example of a "dead" tab below)
behind. When saving a session containing such a "dead" tab, we end up with entries in
the session like this one:
```yaml
- active: true
history:
- active: true
last_visited: '1970-01-01T02:00:00'
pinned: false
scroll-pos:
x: 0
y: 0
title: ''
url: ''
zoom: 1.0
```
When loading a session containing such a "dead" tab, qutebrowser does not restore any
history of that session and logs the following error:
```
ERROR: Failed to load session default: PyQt6.QtCore.QUrl('') is not valid
```
As pointed out by @The-Compiler in this comment[1], the behavior of
`QWebEngineHistoryItem::isValid()`[2] changed somehow between Qt 6.4 and 6.5.
`QWebEngineHistoryItem::isValid()` now returns `True` for "dead" tabs, even though the
history item is not valid (i.e. `url().isValid()` returns `False`).
To fix this we simply add an additional check if the URL is valid before adding a tab to
the session to be saved.
[1] https://github.com/qutebrowser/qutebrowser/issues/7696#issuecomment-1672854592
[2] https://github.com/qt/qtwebengine/blob/v6.5.2/src/core/api/qwebenginehistory.cpp#L69-L75
See 5ff0a573f4
With that commit, encoding the header ourselves means that we'll actually be
navigating to the path `/b'data/...'` instead of `/data/...`.
Restored from dd2fc8e10bb9d4a1bd0158110173793a18736d6b
Now that we are putting our data files in the qutebrowser/ directory
again pkgutil/importlib is getting confused by that dir existing and
returning us a FileLoader for `qutebrowser.components`, I think that's
what's happening anyway. Should try reverting that and this commit and
see if extensions get loaded right again.
So bring back this workaround of using the toc on the PyInstaller loader
to get the list of component modules for now.
ref: #7803
Group commands related to commands/commandline by prefixing them with `cmd-`. In this
case we additionally renamed the command slightly to fit better with the `cmd-` prefix.
Group commands related to commands/commandline by prefixing them with `cmd-`. In this
case we additionally renamed the command slightly to fit better with the `cmd-` prefix.