This commit is contained in:
Ellis 2018-09-18 13:33:30 -04:00
commit 398519762b
24 changed files with 515 additions and 137 deletions

1
.gitignore vendored
View File

@ -16,7 +16,6 @@ __pycache__
/doc/*.html
/README.html
/qutebrowser/html/doc/
/qutebrowser/html/*.html
/.venv*
/.coverage
/htmlcov

View File

@ -32,10 +32,19 @@ Added
QtWebEngine.
* Opening a PDF file now doesn't start a second request anymore.
* Opening PDFs on https:// sites now works properly.
- New `qt.process_model` setting which can be used to change Chromium's process
model.
- New `qt.low_end_device_mode` setting which turns on Chromium's low-end device
mode. This mode uses less RAM, but the expense of performance.
- New `content.webrtc_ip_handling_policy` setting, which allows more
fine-grained/restrictive control about which IPs are exposed via WebRTC.
- Running qutebrowser with QtWebKit or Qt < 5.9 now shows a warning (only
once), as support for those is going to be removed in a future release.
Changed
~~~~~~~
- The `content.headers.referer` setting now works on QtWebEngine.
- The `:repeat` command now takes a count which is multiplied with the given
"times" argument.
- The default keybinding to leave passthrough mode was changed from `<Ctrl-V>`
@ -67,6 +76,8 @@ Removed
~~~~~~~
- Support for importing pre-v1.0.0 history files has been removed.
- The `content.webrtc_public_interfaces_only` setting has been removed and
replaced by `content.webrtc_ip_handling_policy`.
v1.4.2
------

View File

@ -158,7 +158,7 @@
|<<content.ssl_strict,content.ssl_strict>>|Validate SSL handshakes.
|<<content.user_stylesheets,content.user_stylesheets>>|List of user stylesheet filenames to use.
|<<content.webgl,content.webgl>>|Enable WebGL.
|<<content.webrtc_public_interfaces_only,content.webrtc_public_interfaces_only>>|Only expose public interfaces via WebRTC.
|<<content.webrtc_ip_handling_policy,content.webrtc_ip_handling_policy>>|Which interfaces to expose via WebRTC.
|<<content.windowed_fullscreen,content.windowed_fullscreen>>|Limit fullscreen to the browser window (does not expand to fill the screen).
|<<content.xss_auditing,content.xss_auditing>>|Monitor load requests for cross-site scripting attempts.
|<<downloads.location.directory,downloads.location.directory>>|Directory to save downloads to.
@ -229,6 +229,8 @@
|<<qt.force_platform,qt.force_platform>>|Force a Qt platform to use.
|<<qt.force_software_rendering,qt.force_software_rendering>>|Force software rendering for QtWebEngine.
|<<qt.highdpi,qt.highdpi>>|Turn on Qt HighDPI scaling.
|<<qt.low_end_device_mode,qt.low_end_device_mode>>|When to use Chromium's low-end device mode.
|<<qt.process_model,qt.process_model>>|Which Chromium process model to use.
|<<scrolling.bar,scrolling.bar>>|Show a scrollbar.
|<<scrolling.smooth,scrolling.smooth>>|Enable smooth scrolling for web pages.
|<<search.ignore_case,search.ignore_case>>|When to find text on a page case-insensitively.
@ -1675,6 +1677,8 @@ Default: +pass:[true]+
=== content.headers.referer
When to send the Referer header.
The Referer header tells websites from which website you were coming from when visiting them.
No restart is needed with QtWebKit.
This setting requires a restart.
Type: <<types,String>>
@ -1682,12 +1686,10 @@ Valid values:
* +always+: Always send the Referer.
* +never+: Never send the Referer. This is not recommended, as some sites may break.
* +same-domain+: Only send the Referer for the same domain. This will still protect your privacy, but shouldn't break any sites.
* +same-domain+: Only send the Referer for the same domain. This will still protect your privacy, but shouldn't break any sites. With QtWebEngine, the referer will still be sent for other domains, but with stripped path information.
Default: +pass:[same-domain]+
This setting is only available with the QtWebKit backend.
[[content.headers.user_agent]]
=== content.headers.user_agent
User agent to send. Unset to send the default.
@ -2071,14 +2073,22 @@ Type: <<types,Bool>>
Default: +pass:[true]+
[[content.webrtc_public_interfaces_only]]
=== content.webrtc_public_interfaces_only
Only expose public interfaces via WebRTC.
On Qt 5.9, this option requires a restart. On Qt 5.10, this option doesn't work at all because of a Qt bug. On Qt >= 5.11, no restart is required.
[[content.webrtc_ip_handling_policy]]
=== content.webrtc_ip_handling_policy
Which interfaces to expose via WebRTC.
On Qt 5.10, this option doesn't work because of a Qt bug.
This setting requires a restart.
Type: <<types,Bool>>
Type: <<types,String>>
Default: +pass:[false]+
Valid values:
* +all-interfaces+: WebRTC has the right to enumerate all interfaces and bind them to discover public interfaces.
* +default-public-and-private-interfaces+: WebRTC should only use the default route used by http. This also exposes the associated default private address. Default route is the route chosen by the OS on a multi-homed endpoint.
* +default-public-interface-only+: WebRTC should only use the default route used by http. This doesn't expose any local addresses.
* +disable-non-proxied-udp+: WebRTC should only use TCP to contact peers or servers unless the proxy server supports UDP. This doesn't expose any local addresses either.
Default: +pass:[all-interfaces]+
On QtWebEngine, this setting requires Qt 5.9.2 or newer.
@ -2757,6 +2767,46 @@ Type: <<types,Bool>>
Default: +pass:[false]+
[[qt.low_end_device_mode]]
=== qt.low_end_device_mode
When to use Chromium's low-end device mode.
This improves the RAM usage of renderer processes, at the expense of performance.
This setting requires a restart.
Type: <<types,String>>
Valid values:
* +always+: Always use low-end device mode.
* +auto+: Decide automatically (uses low-end mode with < 1 GB available RAM).
* +never+: Never use low-end device mode.
Default: +pass:[auto]+
This setting is only available with the QtWebEngine backend.
[[qt.process_model]]
=== qt.process_model
Which Chromium process model to use.
Alternative process models use less resources, but decrease security and robustness.
See the following pages for more details:
- https://www.chromium.org/developers/design-documents/process-models
- https://doc.qt.io/qt-5/qtwebengine-features.html#process-models
This setting requires a restart.
Type: <<types,String>>
Valid values:
* +process-per-site-instance+: Pages from separate sites are put into separate processes and separate visits to the same site are also isolated.
* +process-per-site+: Pages from separate sites are put into separate processes. Unlike Process per Site Instance, all visits to the same site will share an OS process. The benefit of this model is reduced memory consumption, because more web pages will share processes. The drawbacks include reduced security, robustness, and responsiveness.
* +single-process+: Run all tabs in a single process. This should be used for debugging purposes only, and it disables `:open --private`.
Default: +pass:[process-per-site-instance]+
This setting is only available with the QtWebEngine backend.
[[scrolling.bar]]
=== scrolling.bar
Show a scrollbar.

View File

@ -3,6 +3,6 @@
appdirs==1.4.3
packaging==17.1
pyparsing==2.2.0
setuptools==40.2.0
setuptools==40.3.0
six==1.11.0
wheel==0.31.1

View File

@ -4,4 +4,4 @@ altgraph==0.16.1
future==0.16.0
macholib==1.11
pefile==2018.8.8
PyInstaller==3.3.1
PyInstaller==3.4

View File

@ -1,23 +0,0 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
asn1crypto==0.24.0
-e git+https://github.com/PyCQA/astroid.git#egg=astroid
certifi==2018.8.24
cffi==1.11.5
chardet==3.0.4
cryptography==2.3.1
github3.py==1.2.0
idna==2.7
isort==4.3.4
jwcrypto==0.5.0
lazy-object-proxy==1.3.1
mccabe==0.6.1
pycparser==2.18
-e git+https://github.com/PyCQA/pylint.git#egg=pylint
python-dateutil==2.7.3
./scripts/dev/pylint_checkers
requests==2.19.1
six==1.11.0
uritemplate==3.0.0
urllib3==1.23
wrapt==1.10.11

View File

@ -1,11 +0,0 @@
-e git+https://github.com/PyCQA/astroid.git#egg=astroid
-e git+https://github.com/PyCQA/pylint.git#egg=pylint
./scripts/dev/pylint_checkers
requests
github3.py
# remove @commit-id for scm installs
#@ replace: @.*# #
# fix qute-pylint location
#@ replace: qute-pylint==.* ./scripts/dev/pylint_checkers

View File

@ -13,7 +13,7 @@ fields==5.0.0
Flask==1.0.2
glob2==0.6
hunter==2.0.2
hypothesis==3.70.3
hypothesis==3.71.8
itsdangerous==0.24
# Jinja2==2.10
Mako==1.0.7
@ -24,10 +24,10 @@ parse-type==0.4.2
pluggy==0.7.1
py==1.6.0
py-cpuinfo==4.0.0
pytest==3.6.4 # rq.filter: != 3.7, != 3.7.1, != 3.7.2, != 3.7.3, != 3.7.4
pytest==3.6.4 # rq.filter: <3.7
pytest-bdd==2.21.0
pytest-benchmark==3.1.1
pytest-cov==2.5.1
pytest-cov==2.6.0
pytest-faulthandler==1.5.0
pytest-instafail==0.4.0
pytest-mock==1.10.0

View File

@ -19,4 +19,4 @@ pytest-xvfb
vulture
#@ ignore: Jinja2, MarkupSafe, colorama
#@ filter: pytest != 3.7, != 3.7.1, != 3.7.2, != 3.7.3, != 3.7.4
#@ filter: pytest <3.7

View File

@ -3,5 +3,6 @@
pluggy==0.7.1
py==1.6.0
six==1.11.0
tox==3.2.1
toml==0.9.6
tox==3.3.0
virtualenv==16.0.0

View File

@ -72,9 +72,9 @@ from qutebrowser.keyinput import macros
from qutebrowser.mainwindow import mainwindow, prompt
from qutebrowser.misc import (readline, ipc, savemanager, sessions,
crashsignal, earlyinit, sql, cmdhistory,
backendproblem)
backendproblem, objects)
from qutebrowser.utils import (log, version, message, utils, urlutils, objreg,
usertypes, standarddir, error)
usertypes, standarddir, error, qtutils)
# pylint: disable=unused-import
# We import those to run the cmdutils.register decorators.
from qutebrowser.mainwindow.statusbar import command
@ -351,10 +351,6 @@ def _open_startpage(win_id=None):
def _open_special_pages(args):
"""Open special notification pages which are only shown once.
Currently this is:
- Quickstart page if it's the first start.
- Legacy QtWebKit warning if needed.
Args:
args: The argparse namespace.
"""
@ -366,25 +362,30 @@ def _open_special_pages(args):
tabbed_browser = objreg.get('tabbed-browser', scope='window',
window='last-focused')
# Quickstart page
pages = [
# state, condition, URL
('quickstart-done',
True,
'https://www.qutebrowser.org/quickstart.html'),
quickstart_done = general_sect.get('quickstart-done') == '1'
('config-migration-shown',
os.path.exists(os.path.join(standarddir.config(),
'qutebrowser.conf')),
'qute://help/configuring.html'),
if not quickstart_done:
tabbed_browser.tabopen(
QUrl('https://www.qutebrowser.org/quickstart.html'))
general_sect['quickstart-done'] = '1'
('webkit-warning-shown',
objects.backend == usertypes.Backend.QtWebKit,
'qute://warning/webkit'),
# Setting migration page
('old-qt-warning-shown',
not qtutils.version_check('5.9'),
'qute://warning/old-qt'),
]
needs_migration = os.path.exists(
os.path.join(standarddir.config(), 'qutebrowser.conf'))
migration_shown = general_sect.get('config-migration-shown') == '1'
if needs_migration and not migration_shown:
tabbed_browser.tabopen(QUrl('qute://help/configuring.html'),
background=False)
general_sect['config-migration-shown'] = '1'
for state, condition, url in pages:
if general_sect.get(state) != '1' and condition:
tabbed_browser.tabopen(QUrl(url), background=False)
general_sect[state] = '1'
def on_focus_changed(_old, new):

View File

@ -66,6 +66,11 @@ class CommandDispatcher:
def _new_tabbed_browser(self, private):
"""Get a tabbed-browser from a new window."""
args = QApplication.instance().arguments()
if private and '--single-process' in args:
raise cmdexc.CommandError("Private windows are unavailable with "
"the single-process process model.")
new_window = mainwindow.MainWindow(private=private)
new_window.show()
return new_window.tabbed_browser

View File

@ -39,8 +39,7 @@ except ImportError:
# New in Python 3.6
secrets = None
import pkg_resources
from PyQt5.QtCore import QUrlQuery, QUrl
from PyQt5.QtCore import QUrlQuery, QUrl, qVersion
import qutebrowser
from qutebrowser.browser import pdfjs, downloads
@ -349,9 +348,9 @@ def qute_gpl(_url):
return 'text/html', utils.read_file('html/license.html')
def _asciidoc_fallback_path(path):
def _asciidoc_fallback_path(html_path):
"""Fall back to plaintext asciidoc if the HTML is unavailable."""
asciidoc_path = path.replace('.html', '.asciidoc')
asciidoc_path = html_path.replace('.html', '.asciidoc')
asciidoc_paths = [asciidoc_path]
if asciidoc_path.startswith('html/doc/'):
asciidoc_paths += [asciidoc_path.replace('html/doc/', '../doc/help/'),
@ -416,17 +415,6 @@ def qute_help(url):
return 'text/html', data
@add_handler('backend-warning')
def qute_backend_warning(_url):
"""Handler for qute://backend-warning."""
src = jinja.render('backend-warning.html',
distribution=version.distribution(),
Distribution=version.Distribution,
version=pkg_resources.parse_version,
title="Legacy backend warning")
return 'text/html', src
def _qute_settings_set(url):
"""Handler for qute://settings/set."""
query = QUrlQuery(url)
@ -564,3 +552,19 @@ def qute_pdfjs(url):
else:
mimetype = utils.guess_mimetype(url.fileName(), fallback=True)
return mimetype, data
@add_handler('warning')
def qute_warning(url):
"""Handler for qute://warning."""
path = url.path()
if path == '/old-qt':
src = jinja.render('warning-old-qt.html',
title='Old Qt warning',
qt_version=qVersion())
elif path == '/webkit':
src = jinja.render('warning-webkit.html',
title='QtWebKit backend warning')
else:
raise NotFoundError("Invalid warning page {}".format(path))
return 'text/html', src

View File

@ -166,8 +166,6 @@ class WebEngineSettings(websettings.AbstractSettings):
# Qt 5.11
'content.autoplay':
('PlaybackRequiresUserGesture', lambda val: not val),
'content.webrtc_public_interfaces_only':
('WebRTCPublicInterfacesOnly', None),
}
for name, (attribute, converter) in new_attributes.items():
try:

View File

@ -181,6 +181,51 @@ qt.force_platform:
This sets the `QT_QPA_PLATFORM` environment variable and is useful to force
using the XCB plugin when running QtWebEngine on Wayland.
qt.process_model:
type:
name: String
valid_values:
- process-per-site-instance: Pages from separate sites are put into
separate processes and separate visits to the same site are also
isolated.
- process-per-site: Pages from separate sites are put into separate
processes. Unlike Process per Site Instance, all visits to the same
site will share an OS process. The benefit of this model is reduced
memory consumption, because more web pages will share processes.
The drawbacks include reduced security, robustness, and
responsiveness.
- single-process: Run all tabs in a single process. This should be used
for debugging purposes only, and it disables `:open --private`.
default: process-per-site-instance
backend: QtWebEngine
restart: true
desc: >-
Which Chromium process model to use.
Alternative process models use less resources, but decrease security and
robustness.
See the following pages for more details:
- https://www.chromium.org/developers/design-documents/process-models
- https://doc.qt.io/qt-5/qtwebengine-features.html#process-models
qt.low_end_device_mode:
type:
name: String
valid_values:
- always: Always use low-end device mode.
- auto: Decide automatically (uses low-end mode with < 1 GB available
RAM).
- never: Never use low-end device mode.
default: auto
backend: QtWebEngine
restart: true
desc: >-
When to use Chromium's low-end device mode.
This improves the RAM usage of renderer processes, at the expense of
performance.
qt.highdpi:
type: Bool
@ -411,14 +456,18 @@ content.headers.referer:
- never: "Never send the Referer. This is not recommended, as some sites
may break."
- same-domain: "Only send the Referer for the same domain. This will
still protect your privacy, but shouldn't break any sites."
backend: QtWebKit
still protect your privacy, but shouldn't break any sites. With
QtWebEngine, the referer will still be sent for other domains, but
with stripped path information."
restart: true
desc: >-
When to send the Referer header.
The Referer header tells websites from which website you were coming from
when visiting them.
No restart is needed with QtWebKit.
content.headers.user_agent:
default: null
type:
@ -721,18 +770,31 @@ content.webgl:
supports_pattern: true
desc: Enable WebGL.
content.webrtc_public_interfaces_only:
default: false
type: Bool
content.webrtc_ip_handling_policy:
default: all-interfaces
type:
name: String
valid_values:
- all-interfaces: WebRTC has the right to enumerate all interfaces and
bind them to discover public interfaces.
- default-public-and-private-interfaces: WebRTC should only use the
default route used by http. This also exposes the associated
default private address. Default route is the route chosen by the
OS on a multi-homed endpoint.
- default-public-interface-only: WebRTC should only use the default route
used by http. This doesn't expose any local addresses.
- disable-non-proxied-udp: WebRTC should only use TCP to contact peers or
servers unless the proxy server supports UDP. This doesn't expose
any local addresses either.
default: all-interfaces
backend:
QtWebKit: false
QtWebEngine: Qt 5.9.2
restart: true
desc: >-
Only expose public interfaces via WebRTC.
Which interfaces to expose via WebRTC.
On Qt 5.9, this option requires a restart.
On Qt 5.10, this option doesn't work at all because of a Qt bug.
On Qt >= 5.11, no restart is required.
On Qt 5.10, this option doesn't work because of a Qt bug.
content.xss_auditing:
type: Bool

View File

@ -276,6 +276,21 @@ class YamlConfig(QObject):
del settings['bindings.default']
self._mark_changed()
# content.webrtc_public_interfaces_only got merged into
# content.webrtc_ip_handling_policy.
old = 'content.webrtc_public_interfaces_only'
new = 'content.webrtc_ip_handling_policy'
if old in settings:
settings[new] = {}
for scope, val in settings[old].items():
if val:
settings[new][scope] = 'default-public-interface-only'
else:
settings[new][scope] = 'all-interfaces'
del settings[old]
self._mark_changed()
self._migrate_bool(settings, 'tabs.favicons.show', 'always', 'never')
self._migrate_bool(settings, 'qt.force_software_rendering',
'software-opengl', 'none')

View File

@ -171,24 +171,67 @@ def qt_args(namespace):
argv += ['--' + arg for arg in config.val.qt.args]
if objects.backend == usertypes.Backend.QtWebEngine:
if not qtutils.version_check('5.11', compiled=False):
# WORKAROUND equivalent to
# https://codereview.qt-project.org/#/c/217932/
# Needed for Qt < 5.9.5 and < 5.10.1
argv.append('--disable-shared-workers')
if config.val.qt.force_software_rendering == 'chromium':
argv.append('--disable-gpu')
if not config.val.content.canvas_reading:
argv.append('--disable-reading-from-canvas')
if not qtutils.version_check('5.11'):
# On Qt 5.11, we can control this via QWebEngineSettings
if not config.val.content.autoplay:
argv.append('--autoplay-policy=user-gesture-required')
if config.val.content.webrtc_public_interfaces_only:
argv.append('--force-webrtc-ip-handling-policy='
'default_public_interface_only')
argv += list(_qtwebengine_args())
return argv
def _qtwebengine_args():
"""Get the QtWebEngine arguments to use based on the config."""
if not qtutils.version_check('5.11', compiled=False):
# WORKAROUND equivalent to
# https://codereview.qt-project.org/#/c/217932/
# Needed for Qt < 5.9.5 and < 5.10.1
yield '--disable-shared-workers'
settings = {
'qt.force_software_rendering': {
'software-opengl': None,
'qt-quick': None,
'chromium': '--disable-gpu',
'none': None,
},
'content.canvas_reading': {
True: None,
False: '--disable-reading-from-canvas',
},
'content.webrtc_ip_handling_policy': {
'all-interfaces': None,
'default-public-and-private-interfaces':
'--force-webrtc-ip-handling-policy='
'default_public_and_private_interfaces',
'default-public-interface-only':
'--force-webrtc-ip-handling-policy='
'default_public_interface_only',
'disable-non-proxied-udp':
'--force-webrtc-ip-handling-policy='
'disable_non_proxied_udp',
},
'qt.process_model': {
'process-per-site-instance': None,
'process-per-site': '--process-per-site',
'single-process': '--single-process',
},
'qt.low_end_device_mode': {
'auto': None,
'always': '--enable-low-end-device-mode',
'never': '--disable-low-end-device-mode',
},
'content.headers.referer': {
'always': None,
'never': '--no-referrers',
'same-domain': '--reduced-referrer-granularity',
}
}
if not qtutils.version_check('5.11'):
# On Qt 5.11, we can control this via QWebEngineSettings
settings['content.autoplay'] = {
True: None,
False: '--autoplay-policy=user-gesture-required',
}
for setting, args in sorted(settings.items()):
arg = args[config.instance.get(setting)]
if arg is not None:
yield arg

View File

@ -24,6 +24,10 @@ h1 {
font-weight: normal;
}
h2 {
font-weight: normal;
}
table {
border-collapse: collapse;
width: 100%;
@ -45,4 +49,13 @@ td {
margin-left: 10px;
text-decoration: none;
}
.note {
font-size: smaller;
color: grey;
}
.mono {
font-family: monospace;
}
{% endblock %}

View File

@ -0,0 +1,24 @@
{% extends "styled.html" %}
{% block content %}
<h1>{{ title }}</h1>
<span class="note">Note this warning will only appear once. Use <span class="mono">:open
qute://warning/old-qt</span> to show it again at a later time.</span>
<p>You're using qutebrowser with Qt {{qt_version}}.</p>
<p>Qt 5.7 was released in June 2016, with the 5.7.1 patch release in December
2016. It is based on Chromium 49 (March 2016) with (some) security fixes up to
Chromium 54 (October 2016). It is also
<a href="https://www.debian.org/releases/stable/amd64/release-notes/ch-information.en.html#browser-security">not covered</a>
by Debian security updates.</p>
<p>Qt 5.8 has had various bugs, and has been unsupported (but working to some
degree) in qutebrowser for a while.</p>
<p>Because of those security issues and the maintaince burden coming with
supporting old versions, support for Qt < 5.9 will be dropped in a future
qutebrowser release. You might want to check
<a href="https://qutebrowser.org/doc/install.html">alternate installation methods</a>
which allow you to get a newer Qt.</p>
{% endblock %}

View File

@ -0,0 +1,82 @@
{% extends "styled.html" %}
{% block content %}
<h1>{{ title }}</h1>
<span class="note">Note this warning will only appear once. Use <span class="mono">:open
qute://warning/webkit</span> to show it again at a later time.</span>
<p>You're using qutebrowser with the QtWebKit backend.</p>
<p>Unfortunately, QtWebKit hasn't seen a release (including security updates)
since June 2017, and it also lacks various security features (process
isolation/sandboxing) present in QtWebEngine.</p>
<p>Because of those security issues and the maintaince burden coming with
supporting QtWebKit, support for it will be dropped in a future qutebrowser
release. It's recommended that you use QtWebEngine instead.</p>
<h2>(Outdated) reasons to use QtWebKit</h2>
<p>Most reasons why people preferred the QtWebKit backend aren't relevant anymore:</p>
<p><b>PDF.js support</b>: This qutebrowser release comes with PDF.js support
for QtWebEngine.</p>
<p><b>Missing control over Referer header</b>: This qutebrowser release
supports <span class="mono">content.headers.referer</span> for QtWebEngine.</p>
<p><b>Missing control over cookies</b>: With Qt 5.11 or newer, the <span
class="mono">content.cookies.accept</span> setting works on QtWebEngine.</p>
<p><b>Graphical glitches</b>: The new values for the <span
class="mono">qt.force_software_rendering</span> setting added in v1.4.0 should
hopefully help.</p>
<p><b>Missing support for notifications</b>: Those <a
href="https://bugreports.qt.io/browse/QTBUG-29611">aren't supported yet</a> in
Qt, but support is planned to be added in Qt 5.13, released around May 2019.</p>
<p><b>Resource usage</b>: This release adds the <span
class="mono">qt.process_model</span> and <span
class="mono">qt.low_end_device_mode</span> settings which can be used to
decrease the resource usage of QtWebEngine (but come with other drawbacks).</p>
<p><b>Not trusting Google</b>: Various people have checked the connections made
by QtWebEngine/qutebrowser, and it doesn't make any connections to Google (or
any other unsolicited connections at all). Arguably, having to trust Google
also is a smaller issue than having to trust every website you visit because of
heaps of security issues...</p>
<p><b>Nouveau graphic driver</b>: You can use QtWebEngine with software
rendering. With Qt 5.13 (~May 2019) it might be possible to run with Nouveau
without software rendering.</p>
<p><b>Wayland</b>: It's possible to use QtWebEngine with XWayland. Some users
also seem to be able to run it natively with Qt 5.11, but currently, <span
class="mono">QUTE_SKIP_WAYLAND_CHECK=1</span> needs to be set in the
environment to do so.</p>
<p><b>Instability on FreeBSD</b>: Those seem to be FreeBSD-specific crashes,
and unfortunately nobody has looked into them yet so far...</p>
<p><b>QtWebEngine being unavailable in ArchlinuxARM's PyQt package</b>:
QtWebEngine itself is available on the armv7h/aarch64 architectures, but their
PyQt package is broken and doesn't come with QtWebEngine support. This
<a href="https://archlinuxarm.org/forum/viewtopic.php?f=15&t=11269&p=54587">has
been reported</a> in their forums, but without any change so far. It should
however be possible to rebuild the PyQt package from source with QtWebEngine
installed.</p>
<p><b>QtWebEngine being unavailable on Parabola</b>: Claims of Parabola
developers about QtWebEngine being "non-free" have repeatedly been disputed,
and so far nobody came up with solid evidence about that being the case. Also,
note that their qutebrowser package is orphaned and was often outdated in the
past (even qutebrowser security fixes took months to arrive there). You
might be better off chosing an <a
href="https://qutebrowser.org/doc/install.html">alternative install
method</a>.</p>
<p><b>White flashing between loads with a custom stylesheet</b>: This doesn't
seem to happen with <span class="mono">qt.process_model = single-process</span>
set. However, note that that setting comes with decreased security and
stability, but QtWebKit doesn't have any process isolation at all.</p>
{% endblock %}

View File

@ -68,6 +68,11 @@ def _other_backend(backend):
def _error_text(because, text, backend):
"""Get an error text for the given information."""
other_backend, other_setting = _other_backend(backend)
if other_backend == usertypes.Backend.QtWebKit:
warning = ("<i>Note that QtWebKit hasn't been updated since "
"July 2017 (including security updates).</i>")
else:
warning = ""
return ("<b>Failed to start with the {backend} backend!</b>"
"<p>qutebrowser tried to start with the {backend} backend but "
"failed because {because}.</p>{text}"
@ -75,9 +80,10 @@ def _error_text(because, text, backend):
"<p>This forces usage of the {other_backend.name} backend by "
"setting the <i>backend = '{other_setting}'</i> option "
"(if you have a <i>config.py</i> file, you'll need to set "
"this manually).</p>".format(
"this manually). {warning}</p>".format(
backend=backend.name, because=because, text=text,
other_backend=other_backend, other_setting=other_setting))
other_backend=other_backend, other_setting=other_setting,
warning=warning))
class _Dialog(QDialog):
@ -102,8 +108,10 @@ class _Dialog(QDialog):
quit_button.clicked.connect(lambda: self.done(_Result.quit))
hbox.addWidget(quit_button)
backend_button = QPushButton("Force {} backend".format(
other_backend.name))
backend_text = "Force {} backend".format(other_backend.name)
if other_backend == usertypes.Backend.QtWebKit:
backend_text += ' (not recommended)'
backend_button = QPushButton(backend_text)
backend_button.clicked.connect(functools.partial(
self._change_setting, 'backend', other_setting))
hbox.addWidget(backend_button)

View File

@ -65,9 +65,16 @@ def temp_basedir_env(tmpdir, short_tmpdir):
runtime_dir.ensure(dir=True)
runtime_dir.chmod(0o700)
(data_dir / 'qutebrowser' / 'state').write_text(
'[general]\nquickstart-done = 1\nbackend-warning-shown=1',
encoding='utf-8', ensure=True)
lines = [
'[general]',
'quickstart-done = 1',
'backend-warning-shown = 1',
'old-qt-warning-shown = 1',
'webkit-warning-shown = 1',
]
state_file = data_dir / 'qutebrowser' / 'state'
state_file.write_text('\n'.join(lines), encoding='utf-8', ensure=True)
env = {
'XDG_DATA_HOME': str(data_dir),

View File

@ -235,6 +235,21 @@ class TestYaml:
data = autoconfig.read()
assert 'bindings.default' not in data
@pytest.mark.parametrize('public_only, expected', [
(True, 'default-public-interface-only'),
(False, 'all-interfaces'),
])
def test_webrtc(self, yaml, autoconfig, public_only, expected):
"""Tests for migration of content.webrtc_public_interfaces_only."""
autoconfig.write({'content.webrtc_public_interfaces_only':
{'global': public_only}})
yaml.load()
yaml._save()
data = autoconfig.read()
assert data['content.webrtc_ip_handling_policy']['global'] == expected
@pytest.mark.parametrize('show, expected', [
(True, 'always'),
(False, 'never'),

View File

@ -359,10 +359,11 @@ class TestQtArgs:
return parser
@pytest.fixture(autouse=True)
def patch_version_check(self, monkeypatch):
"""Make sure no --disable-shared-workers argument gets added."""
def reduce_args(self, monkeypatch, config_stub):
"""Make sure no --disable-shared-workers/referer argument get added."""
monkeypatch.setattr(configinit.qtutils, 'version_check',
lambda version, compiled=False: True)
config_stub.val.content.headers.referer = 'always'
@pytest.mark.parametrize('args, expected', [
# No Qt arguments
@ -438,23 +439,35 @@ class TestQtArgs:
assert ('--autoplay-policy=user-gesture-required' in args) == added
@utils.qt59
@pytest.mark.parametrize('new_version, public_only, added', [
(True, True, False), # new enough to not need it
(False, False, False), # option disabled
(False, True, True),
@pytest.mark.parametrize('policy, arg', [
('all-interfaces', None),
('default-public-and-private-interfaces',
'--force-webrtc-ip-handling-policy='
'default_public_and_private_interfaces'),
('default-public-interface-only',
'--force-webrtc-ip-handling-policy='
'default_public_interface_only'),
('disable-non-proxied-udp',
'--force-webrtc-ip-handling-policy='
'disable_non_proxied_udp'),
])
def test_webrtc(self, config_stub, monkeypatch, parser,
new_version, public_only, added):
policy, arg):
monkeypatch.setattr(configinit.objects, 'backend',
usertypes.Backend.QtWebEngine)
config_stub.val.content.webrtc_public_interfaces_only = public_only
monkeypatch.setattr(configinit.qtutils, 'version_check',
lambda version, compiled=False: new_version)
config_stub.val.content.webrtc_ip_handling_policy = policy
parsed = parser.parse_args([])
args = configinit.qt_args(parsed)
arg = '--force-webrtc-ip-handling-policy=default_public_interface_only'
assert (arg in args) == added
if arg is None:
assert not any(a.startswith('--force-webrtc-ip-handling-policy=')
for a in args)
else:
assert arg in args
@pytest.mark.parametrize('canvas_reading, added', [
(True, False), # canvas reading enabled
@ -470,6 +483,67 @@ class TestQtArgs:
args = configinit.qt_args(parsed)
assert ('--disable-reading-from-canvas' in args) == added
@pytest.mark.parametrize('process_model, added', [
('process-per-site-instance', False),
('process-per-site', True),
('single-process', True),
])
def test_process_model(self, config_stub, monkeypatch, parser,
process_model, added):
monkeypatch.setattr(configinit.objects, 'backend',
usertypes.Backend.QtWebEngine)
config_stub.val.qt.process_model = process_model
parsed = parser.parse_args([])
args = configinit.qt_args(parsed)
if added:
assert '--' + process_model in args
else:
assert '--process-per-site' not in args
assert '--single-process' not in args
assert '--process-per-site-instance' not in args
assert '--process-per-tab' not in args
@pytest.mark.parametrize('low_end_device_mode, arg', [
('auto', None),
('always', '--enable-low-end-device-mode'),
('never', '--disable-low-end-device-mode'),
])
def test_low_end_device_mode(self, config_stub, monkeypatch, parser,
low_end_device_mode, arg):
monkeypatch.setattr(configinit.objects, 'backend',
usertypes.Backend.QtWebEngine)
config_stub.val.qt.low_end_device_mode = low_end_device_mode
parsed = parser.parse_args([])
args = configinit.qt_args(parsed)
if arg is None:
assert '--enable-low-end-device-mode' not in args
assert '--disable-low-end-device-mode' not in args
else:
assert arg in args
@pytest.mark.parametrize('referer, arg', [
('always', None),
('never', '--no-referrers'),
('same-domain', '--reduced-referrer-granularity'),
])
def test_referer(self, config_stub, monkeypatch, parser, referer, arg):
monkeypatch.setattr(configinit.objects, 'backend',
usertypes.Backend.QtWebEngine)
config_stub.val.content.headers.referer = referer
parsed = parser.parse_args([])
args = configinit.qt_args(parsed)
if arg is None:
assert '--no-referrers' not in args
assert '--reduced-referrer-granularity' not in args
else:
assert arg in args
@pytest.mark.parametrize('arg, confval, used', [
# overridden by commandline arg