Merge branch 'master' of https://github.com/qutebrowser/qutebrowser into stylesheet-fix

This commit is contained in:
Jay Kamat 2019-02-14 17:51:19 -08:00
commit bc29ff60b3
No known key found for this signature in database
GPG Key ID: 5D2E399600F4F7B5
37 changed files with 184 additions and 84 deletions

View File

@ -68,16 +68,3 @@ after_success:
after_failure: after_failure:
- bash scripts/dev/ci/travis_backtrace.sh - bash scripts/dev/ci/travis_backtrace.sh
notifications:
webhooks:
- https://buildtimetrend.herokuapp.com/travis
irc:
channels:
- "chat.freenode.net#qutebrowser-dev"
on_success: always
on_failure: always
skip_join: true
template:
- "%{repository}#%{build_number} (%{branch} - %{commit} : %{author}): %{message}"
- "%{compare_url} - %{build_url}"

View File

@ -13,7 +13,7 @@ include qutebrowser/utils/testfile
include qutebrowser/git-commit-id include qutebrowser/git-commit-id
include LICENSE doc/* README.asciidoc include LICENSE doc/* README.asciidoc
include misc/qutebrowser.desktop include misc/qutebrowser.desktop
include misc/qutebrowser.appdata.xml include misc/org.qutebrowser.qutebrowser.appdata.xml
include misc/Makefile include misc/Makefile
include requirements.txt include requirements.txt
include tox.ini include tox.ini

View File

@ -25,6 +25,7 @@ Added
opened from a page should stack on each other or not. opened from a page should stack on each other or not.
- New `completion.open_categories` setting which allows to configure which - New `completion.open_categories` setting which allows to configure which
categories are shown in the `:open` completion, and how they are ordered. categories are shown in the `:open` completion, and how they are ordered.
- New `tabs.pinned.frozen` setting to allow/deny navigating in pinned tabs.
- New config manipulation commands: - New config manipulation commands:
* `:config-dict-add` and `:config-list-add` to a new element to a dict/list * `:config-dict-add` and `:config-list-add` to a new element to a dict/list
setting. setting.
@ -53,6 +54,11 @@ Changed
- Various small performance improvements for hints and the completion. - Various small performance improvements for hints and the completion.
- The Wayland check for QtWebEngine is now disabled on Qt >= 5.11.2, as those - The Wayland check for QtWebEngine is now disabled on Qt >= 5.11.2, as those
versions should work without any issues. versions should work without any issues.
- The JavaScript `console` object is now available in PAC files.
- The metainfo file `qutebrowser.appdata.xml` is now renamed to
`org.qutebrowser.qutebrowser.appdata.xml`.
- The `qute-pass` userscript now understands domains in gpg filenames
in addition to directory names.
Fixed Fixed
~~~~~ ~~~~~
@ -67,9 +73,13 @@ Fixed
`content.cookies.accept = no-3rdparty` from working properly on some pages `content.cookies.accept = no-3rdparty` from working properly on some pages
like GMail. However, the default for `content.cookies.accept` is still `all` like GMail. However, the default for `content.cookies.accept` is still `all`
to be in line with what other browsers do. to be in line with what other browsers do.
- `:navigate` not incrementing in anchors or queries or anchors. - `:navigate` not incrementing in anchors or queries.
- Crash when trying to use a proxy requiring authentication with QtWebKit. - Crash when trying to use a proxy requiring authentication with QtWebKit.
- Slashes in search terms are now percent-escaped. - Slashes in search terms are now percent-escaped.
- When `scrolling.bar = True` was set in versions before v1.5.0, this now
correctly gets migrated to `always` instead of `when-searching`.
- Completion highlighting now works again on Qt 5.11.3 and 5.12.1.
- The outdated header `X-Do-Not-Track` is no longer sent.
v1.5.2 v1.5.2
------ ------

View File

@ -211,9 +211,10 @@ Why does J move to the next (right) tab, and K to the previous (left) one?::
What's the difference between insert and passthrough mode?:: What's the difference between insert and passthrough mode?::
They are quite similar, but insert mode has some bindings (like `Ctrl-e` to They are quite similar, but insert mode has some bindings (like `Ctrl-e` to
open an editor) while passthrough mode only has escape bound. It might also open an editor) while passthrough mode only has shift+escape bound. This is
be useful to rebind escape to something else in passthrough mode only, to be because shift+escape is unlikely to be a useful binding to be passed to a
able to send an escape keypress to the website. webpage. However, any other keys may be assigned to leaving passthrough mode
instead of shift+escape should this be desired.
Why does it take longer to open a URL in qutebrowser than in chromium?:: Why does it take longer to open a URL in qutebrowser than in chromium?::
When opening a URL in an existing instance, the normal qutebrowser When opening a URL in an existing instance, the normal qutebrowser

View File

@ -396,6 +396,7 @@ Pre-built colorschemes
- A collection of https://github.com/chriskempson/base16[base16] color-schemes can be found in https://github.com/theova/base16-qutebrowser[base16-qutebrowser] and used with https://github.com/AuditeMarlow/base16-manager[base16-manager]. - A collection of https://github.com/chriskempson/base16[base16] color-schemes can be found in https://github.com/theova/base16-qutebrowser[base16-qutebrowser] and used with https://github.com/AuditeMarlow/base16-manager[base16-manager].
- Two implementations of the https://github.com/arcticicestudio/nord[Nord] colorscheme for qutebrowser exist: https://github.com/Linuus/nord-qutebrowser[Linuus], https://github.com/KnownAsDon/QuteBrowser-Nord-Theme[KnownAsDon] - Two implementations of the https://github.com/arcticicestudio/nord[Nord] colorscheme for qutebrowser exist: https://github.com/Linuus/nord-qutebrowser[Linuus], https://github.com/KnownAsDon/QuteBrowser-Nord-Theme[KnownAsDon]
- https://github.com/evannagle/qutebrowser-dracula-theme[Dracula] - https://github.com/evannagle/qutebrowser-dracula-theme[Dracula]
- https://github.com/jjzmajic/qutewal[Pywal theme]
Avoiding flake8 errors Avoiding flake8 errors
^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^

View File

@ -261,6 +261,7 @@
|<<tabs.new_position.stacking,tabs.new_position.stacking>>|Stack related tabs on top of each other when opened consecutively. |<<tabs.new_position.stacking,tabs.new_position.stacking>>|Stack related tabs on top of each other when opened consecutively.
|<<tabs.new_position.unrelated,tabs.new_position.unrelated>>|Position of new tabs which are not opened from another tab. |<<tabs.new_position.unrelated,tabs.new_position.unrelated>>|Position of new tabs which are not opened from another tab.
|<<tabs.padding,tabs.padding>>|Padding (in pixels) around text for tabs. |<<tabs.padding,tabs.padding>>|Padding (in pixels) around text for tabs.
|<<tabs.pinned.frozen,tabs.pinned.frozen>>|Force pinned tabs to stay at fixed URL.
|<<tabs.pinned.shrink,tabs.pinned.shrink>>|Shrink pinned tabs down to their contents. |<<tabs.pinned.shrink,tabs.pinned.shrink>>|Shrink pinned tabs down to their contents.
|<<tabs.position,tabs.position>>|Position of the tab bar. |<<tabs.position,tabs.position>>|Position of the tab bar.
|<<tabs.select_on_remove,tabs.select_on_remove>>|Which tab to select when the focused tab is removed. |<<tabs.select_on_remove,tabs.select_on_remove>>|Which tab to select when the focused tab is removed.
@ -3307,6 +3308,14 @@ Default:
- +pass:[right]+: +pass:[5]+ - +pass:[right]+: +pass:[5]+
- +pass:[top]+: +pass:[0]+ - +pass:[top]+: +pass:[0]+
[[tabs.pinned.frozen]]
=== tabs.pinned.frozen
Force pinned tabs to stay at fixed URL.
Type: <<types,Bool>>
Default: +pass:[true]+
[[tabs.pinned.shrink]] [[tabs.pinned.shrink]]
=== tabs.pinned.shrink === tabs.pinned.shrink
Shrink pinned tabs down to their contents. Shrink pinned tabs down to their contents.

View File

@ -102,18 +102,12 @@ $ python3 scripts/asciidoc2html.py
On Fedora On Fedora
--------- ---------
NOTE: Fedora's packages used to be outdated for a long time, but are
now (November 2017) maintained and up-to-date again.
qutebrowser is available in the official repositories: qutebrowser is available in the official repositories:
----- -----
# dnf install qutebrowser # dnf install qutebrowser
----- -----
However, note that Fedora 25/26 won't be updated to qutebrowser v1.0, so you
might want to <<tox,install qutebrowser via tox>> instead there.
Additional hints Additional hints
~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~

View File

@ -17,8 +17,8 @@ doc/qutebrowser.1.html:
install: doc/qutebrowser.1.html install: doc/qutebrowser.1.html
$(PYTHON) setup.py install --prefix="$(PREFIX)" --optimize=1 $(SETUPTOOLSOPTS) $(PYTHON) setup.py install --prefix="$(PREFIX)" --optimize=1 $(SETUPTOOLSOPTS)
install -Dm644 misc/qutebrowser.appdata.xml \ install -Dm644 misc/org.qutebrowser.qutebrowser.appdata.xml \
"$(DESTDIR)$(DATADIR)/metainfo/qutebrowser.appdata.xml" "$(DESTDIR)$(DATADIR)/metainfo/org.qutebrowser.qutebrowser.appdata.xml"
install -Dm644 doc/qutebrowser.1 \ install -Dm644 doc/qutebrowser.1 \
"$(DESTDIR)$(MANDIR)/man1/qutebrowser.1" "$(DESTDIR)$(MANDIR)/man1/qutebrowser.1"
install -Dm644 misc/qutebrowser.desktop \ install -Dm644 misc/qutebrowser.desktop \

View File

@ -11,7 +11,7 @@ flake8-deprecated==1.3
flake8-docstrings==1.3.0 flake8-docstrings==1.3.0
flake8-future-import==0.4.5 flake8-future-import==0.4.5
flake8-mock==0.3 flake8-mock==0.3
flake8-per-file-ignores==0.6 flake8-per-file-ignores==0.7
flake8-polyfill==1.0.2 flake8-polyfill==1.0.2
flake8-string-format==0.2.3 flake8-string-format==0.2.3
flake8-tidy-imports==1.1.0 flake8-tidy-imports==1.1.0

View File

@ -16,6 +16,6 @@ pytz==2018.7
requests==2.21.0 requests==2.21.0
six==1.12.0 six==1.12.0
snowballstemmer==1.2.1 snowballstemmer==1.2.1
Sphinx==1.8.2 Sphinx==1.8.3
sphinxcontrib-websupport==1.1.0 sphinxcontrib-websupport==1.1.0
urllib3==1.24.1 urllib3==1.24.1

View File

@ -3,8 +3,8 @@
atomicwrites==1.2.1 atomicwrites==1.2.1
attrs==18.2.0 attrs==18.2.0
backports.functools-lru-cache==1.5 backports.functools-lru-cache==1.5
beautifulsoup4==4.6.3 beautifulsoup4==4.7.0
cheroot==6.5.2 cheroot==6.5.3
Click==7.0 Click==7.0
# colorama==0.4.1 # colorama==0.4.1
coverage==4.5.2 coverage==4.5.2
@ -12,12 +12,12 @@ EasyProcess==0.2.5
Flask==1.0.2 Flask==1.0.2
glob2==0.6 glob2==0.6
hunter==2.1.0 hunter==2.1.0
hypothesis==3.84.5 hypothesis==3.85.2
itsdangerous==1.1.0 itsdangerous==1.1.0
# Jinja2==2.10 # Jinja2==2.10
Mako==1.0.7 Mako==1.0.7
# MarkupSafe==1.1.0 # MarkupSafe==1.1.0
more-itertools==4.3.0 more-itertools==5.0.0
parse==1.9.0 parse==1.9.0
parse-type==0.4.2 parse-type==0.4.2
pluggy==0.8.0 pluggy==0.8.0

View File

@ -64,6 +64,7 @@ die() {
javascript_escape() { javascript_escape() {
# print the first argument in an escaped way, such that it can safely # print the first argument in an escaped way, such that it can safely
# be used within javascripts double quotes # be used within javascripts double quotes
# shellcheck disable=SC2001
sed "s,[\\\\'\"],\\\\&,g" <<< "$1" sed "s,[\\\\'\"],\\\\&,g" <<< "$1"
} }
@ -111,6 +112,7 @@ simplify_url() {
# are found: # are found:
no_entries_found() { no_entries_found() {
while [ 0 -eq "${#files[@]}" ] && [ -n "$simple_url" ]; do while [ 0 -eq "${#files[@]}" ] && [ -n "$simple_url" ]; do
# shellcheck disable=SC2001
shorter_simple_url=$(sed 's,^[^.]*\.,,' <<< "$simple_url") shorter_simple_url=$(sed 's,^[^.]*\.,,' <<< "$simple_url")
if [ "$shorter_simple_url" = "$simple_url" ] ; then if [ "$shorter_simple_url" = "$simple_url" ] ; then
# if no dot, then even remove the top level domain # if no dot, then even remove the top level domain

View File

@ -97,13 +97,19 @@ def qute_command(command):
def find_pass_candidates(domain, password_store_path): def find_pass_candidates(domain, password_store_path):
candidates = [] candidates = []
for path, directories, file_names in os.walk(password_store_path, followlinks=True): for path, directories, file_names in os.walk(password_store_path, followlinks=True):
if directories or domain not in path.split(os.path.sep): secrets = fnmatch.filter(file_names, '*.gpg')
if not secrets:
continue continue
# Strip password store path prefix to get the relative pass path # Strip password store path prefix to get the relative pass path
pass_path = path[len(password_store_path) + 1:] pass_path = path[len(password_store_path) + 1:]
secrets = fnmatch.filter(file_names, '*.gpg') split_path = pass_path.split(os.path.sep)
candidates.extend(os.path.join(pass_path, os.path.splitext(secret)[0]) for secret in secrets) for secret in secrets:
secret_base = os.path.splitext(secret)[0]
if domain not in (split_path + [secret_base]):
continue
candidates.append(os.path.join(pass_path, secret_base))
return candidates return candidates

View File

@ -37,7 +37,7 @@ get_selection() {
# https://github.com/halfwit/dotfiles/blob/master/.config/dmenu/font # https://github.com/halfwit/dotfiles/blob/master/.config/dmenu/font
[[ -s $confdir/dmenu/font ]] && read -r font < "$confdir"/dmenu/font [[ -s $confdir/dmenu/font ]] && read -r font < "$confdir"/dmenu/font
[[ $font ]] && opts+=(-fn "$font") [[ -n $font ]] && opts+=(-fn "$font")
# shellcheck source=/dev/null # shellcheck source=/dev/null
[[ -s $optsfile ]] && source "$optsfile" [[ -s $optsfile ]] && source "$optsfile"
@ -46,7 +46,7 @@ url=$(get_selection)
url=${url/*http/http} url=${url/*http/http}
# If no selection is made, exit (escape pressed, e.g.) # If no selection is made, exit (escape pressed, e.g.)
[[ ! $url ]] && exit 0 [[ -z $url ]] && exit 0
case $1 in case $1 in
open) printf '%s' "open $url" >> "$QUTE_FIFO" || qutebrowser "$url" ;; open) printf '%s' "open $url" >> "$QUTE_FIFO" || qutebrowser "$url" ;;

View File

@ -64,6 +64,7 @@ qt_log_ignore =
^QSettings::value: Empty key passed ^QSettings::value: Empty key passed
^Icon theme ".*" not found ^Icon theme ".*" not found
^Error receiving trust for a CA certificate ^Error receiving trust for a CA certificate
^QBackingStore::endPaint\(\) called with active painter on backingstore paint device
xfail_strict = true xfail_strict = true
filterwarnings = filterwarnings =
error error

View File

@ -943,6 +943,10 @@ class AbstractTab(QWidget):
evt.posted = True evt.posted = True
QApplication.postEvent(recipient, evt) QApplication.postEvent(recipient, evt)
def navigation_blocked(self) -> bool:
"""Test if navigation is allowed on the current tab."""
return self.data.pinned and config.val.tabs.pinned.frozen
@pyqtSlot(QUrl) @pyqtSlot(QUrl)
def _on_before_load_started(self, url: QUrl) -> None: def _on_before_load_started(self, url: QUrl) -> None:
"""Adjust the title if we are going to visit a URL soon.""" """Adjust the title if we are going to visit a URL soon."""

View File

@ -316,7 +316,7 @@ class CommandDispatcher:
else: else:
# Explicit count with a tab that doesn't exist. # Explicit count with a tab that doesn't exist.
return return
elif curtab.data.pinned: elif curtab.navigation_blocked():
message.info("Tab is pinned!") message.info("Tab is pinned!")
else: else:
curtab.load_url(cur_url) curtab.load_url(cur_url)

View File

@ -180,6 +180,8 @@ class PACResolver:
""" """
self._engine = QJSEngine() self._engine = QJSEngine()
self._engine.installExtensions(QJSEngine.ConsoleExtension)
self._ctx = _PACContext(self._engine) self._ctx = _PACContext(self._engine)
self._engine.globalObject().setProperty( self._engine.globalObject().setProperty(
"PAC", self._engine.newQObject(self._ctx)) "PAC", self._engine.newQObject(self._ctx))

View File

@ -42,7 +42,6 @@ def custom_headers(url):
if dnt_config is not None: if dnt_config is not None:
dnt = b'1' if dnt_config else b'0' dnt = b'1' if dnt_config else b'0'
headers[b'DNT'] = dnt headers[b'DNT'] = dnt
headers[b'X-Do-Not-Track'] = dnt
conf_headers = config.instance.get('content.headers.custom', url=url) conf_headers = config.instance.get('content.headers.custom', url=url)
for header, value in conf_headers.items(): for header, value in conf_headers.items():

View File

@ -22,6 +22,11 @@
from PyQt5.QtCore import QBuffer, QIODevice, QUrl from PyQt5.QtCore import QBuffer, QIODevice, QUrl
from PyQt5.QtWebEngineCore import (QWebEngineUrlSchemeHandler, from PyQt5.QtWebEngineCore import (QWebEngineUrlSchemeHandler,
QWebEngineUrlRequestJob) QWebEngineUrlRequestJob)
try:
from PyQt5.QtWebEngineCore import QWebEngineUrlScheme # type: ignore
except ImportError:
# Added in Qt 5.12
QWebEngineUrlScheme = None
from qutebrowser.browser import qutescheme from qutebrowser.browser import qutescheme
from qutebrowser.utils import log, qtutils from qutebrowser.utils import log, qtutils
@ -33,8 +38,12 @@ class QuteSchemeHandler(QWebEngineUrlSchemeHandler):
def install(self, profile): def install(self, profile):
"""Install the handler for qute:// URLs on the given profile.""" """Install the handler for qute:// URLs on the given profile."""
if QWebEngineUrlScheme is not None:
assert QWebEngineUrlScheme.schemeByName(b'qute') is not None
profile.installUrlSchemeHandler(b'qute', self) profile.installUrlSchemeHandler(b'qute', self)
if qtutils.version_check('5.11', compiled=False): if (qtutils.version_check('5.11', compiled=False) and
not qtutils.version_check('5.12', compiled=False)):
# WORKAROUND for https://bugreports.qt.io/browse/QTBUG-63378 # WORKAROUND for https://bugreports.qt.io/browse/QTBUG-63378
profile.installUrlSchemeHandler(b'chrome-error', self) profile.installUrlSchemeHandler(b'chrome-error', self)
profile.installUrlSchemeHandler(b'chrome-extension', self) profile.installUrlSchemeHandler(b'chrome-extension', self)
@ -130,3 +139,16 @@ class QuteSchemeHandler(QWebEngineUrlSchemeHandler):
buf.seek(0) buf.seek(0)
buf.close() buf.close()
job.reply(mimetype.encode('ascii'), buf) job.reply(mimetype.encode('ascii'), buf)
def init():
"""Register the qute:// scheme.
Note this needs to be called early, before constructing any QtWebEngine
classes.
"""
if QWebEngineUrlScheme is not None:
scheme = QWebEngineUrlScheme(b'qute')
scheme.setFlags(QWebEngineUrlScheme.LocalScheme |
QWebEngineUrlScheme.LocalAccessAllowed)
QWebEngineUrlScheme.registerScheme(scheme)

View File

@ -30,7 +30,7 @@ from PyQt5.QtGui import QFont
from PyQt5.QtWebEngineWidgets import (QWebEngineSettings, QWebEngineProfile, from PyQt5.QtWebEngineWidgets import (QWebEngineSettings, QWebEngineProfile,
QWebEnginePage) QWebEnginePage)
from qutebrowser.browser.webengine import spell from qutebrowser.browser.webengine import spell, webenginequtescheme
from qutebrowser.config import config, websettings from qutebrowser.config import config, websettings
from qutebrowser.config.websettings import AttributeInfo as Attr from qutebrowser.config.websettings import AttributeInfo as Attr
from qutebrowser.utils import utils, standarddir, qtutils, message, log from qutebrowser.utils import utils, standarddir, qtutils, message, log
@ -298,6 +298,7 @@ def init(args):
not hasattr(QWebEnginePage, 'setInspectedPage')): # only Qt < 5.11 not hasattr(QWebEnginePage, 'setInspectedPage')): # only Qt < 5.11
os.environ['QTWEBENGINE_REMOTE_DEBUGGING'] = str(utils.random_port()) os.environ['QTWEBENGINE_REMOTE_DEBUGGING'] = str(utils.random_port())
webenginequtescheme.init()
spell.init() spell.init()
_init_profiles() _init_profiles()

View File

@ -212,11 +212,11 @@ class CompletionItemDelegate(QStyledItemDelegate):
view = self.parent() view = self.parent()
pattern = view.pattern pattern = view.pattern
columns_to_filter = index.model().columns_to_filter(index) columns_to_filter = index.model().columns_to_filter(index)
self._doc.setPlainText(self._opt.text)
if index.column() in columns_to_filter and pattern: if index.column() in columns_to_filter and pattern:
pat = re.escape(pattern).replace(r'\ ', r'|') pat = re.escape(pattern).replace(r'\ ', r'|')
_Highlighter(self._doc, pat, _Highlighter(self._doc, pat,
config.val.colors.completion.match.fg) config.val.colors.completion.match.fg)
self._doc.setPlainText(self._opt.text)
else: else:
self._doc.setHtml( self._doc.setHtml(
'<span style="font: {};">{}</span>'.format( '<span style="font: {};">{}</span>'.format(

View File

@ -118,7 +118,7 @@ def printpage(tab: apitypes.Tab,
@cmdutils.argument('tab', value=cmdutils.Value.cur_tab) @cmdutils.argument('tab', value=cmdutils.Value.cur_tab)
def home(tab: apitypes.Tab) -> None: def home(tab: apitypes.Tab) -> None:
"""Open main startpage in current tab.""" """Open main startpage in current tab."""
if tab.data.pinned: if tab.navigation_blocked():
message.info("Tab is pinned!") message.info("Tab is pinned!")
else: else:
tab.load_url(config.val.url.start_pages[0]) tab.load_url(config.val.url.start_pages[0])

View File

@ -46,7 +46,9 @@ class ConfigCache:
self._cache[attr] = config.instance.get(attr) self._cache[attr] = config.instance.get(attr)
def __getitem__(self, attr: str) -> typing.Any: def __getitem__(self, attr: str) -> typing.Any:
if attr not in self._cache: try:
return self._cache[attr]
except KeyError:
assert not config.instance.get_opt(attr).supports_pattern assert not config.instance.get_opt(attr).supports_pattern
self._cache[attr] = config.instance.get(attr) self._cache[attr] = config.instance.get(attr)
return self._cache[attr] return self._cache[attr]

View File

@ -1768,6 +1768,11 @@ tabs.pinned.shrink:
type: Bool type: Bool
desc: Shrink pinned tabs down to their contents. desc: Shrink pinned tabs down to their contents.
tabs.pinned.frozen:
type: Bool
default: True
desc: Force pinned tabs to stay at fixed URL.
tabs.wrap: tabs.wrap:
default: true default: true
type: Bool type: Bool

View File

@ -308,7 +308,7 @@ class YamlConfig(QObject):
self._migrate_bool(settings, 'tabs.favicons.show', 'always', 'never') self._migrate_bool(settings, 'tabs.favicons.show', 'always', 'never')
self._migrate_bool(settings, 'scrolling.bar', self._migrate_bool(settings, 'scrolling.bar',
'when-searching', 'never') 'always', 'when-searching')
self._migrate_bool(settings, 'qt.force_software_rendering', self._migrate_bool(settings, 'qt.force_software_rendering',
'software-opengl', 'none') 'software-opengl', 'none')

View File

@ -71,7 +71,7 @@ EOF
set -e set -e
if [[ $DOCKER ]]; then if [[ -n $DOCKER ]]; then
exit 0 exit 0
elif [[ $TRAVIS_OS_NAME == osx ]]; then elif [[ $TRAVIS_OS_NAME == osx ]]; then
# Disable App Nap # Disable App Nap

View File

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
if [[ $DOCKER ]]; then if [[ -n $DOCKER ]]; then
docker run \ docker run \
--privileged \ --privileged \
-v "$PWD:/outside" \ -v "$PWD:/outside" \

View File

@ -93,7 +93,7 @@ Feature: Downloading things from a website.
Then no crash should happen Then no crash should happen
# https://github.com/qutebrowser/qutebrowser/issues/4240 # https://github.com/qutebrowser/qutebrowser/issues/4240
@qt!=5.11.2 @qt<5.11.2
Scenario: Downloading with SSL errors (issue 1413) Scenario: Downloading with SSL errors (issue 1413)
When SSL is supported When SSL is supported
And I clear SSL errors And I clear SSL errors

View File

@ -331,19 +331,16 @@ Feature: Various utility commands.
When I set content.headers.do_not_track to true When I set content.headers.do_not_track to true
And I open headers And I open headers
Then the header Dnt should be set to 1 Then the header Dnt should be set to 1
And the header X-Do-Not-Track should be set to 1
Scenario: DNT header (off) Scenario: DNT header (off)
When I set content.headers.do_not_track to false When I set content.headers.do_not_track to false
And I open headers And I open headers
Then the header Dnt should be set to 0 Then the header Dnt should be set to 0
And the header X-Do-Not-Track should be set to 0
Scenario: DNT header (unset) Scenario: DNT header (unset)
When I set content.headers.do_not_track to <empty> When I set content.headers.do_not_track to <empty>
And I open headers And I open headers
Then the header Dnt should be set to <unset> Then the header Dnt should be set to <unset>
And the header X-Do-Not-Track should be set to <unset>
Scenario: Accept-Language header Scenario: Accept-Language header
When I set content.headers.accept_language to en,de When I set content.headers.accept_language to en,de

View File

@ -1289,6 +1289,14 @@ Feature: Tab management
And the following tabs should be open: And the following tabs should be open:
- data/numbers/1.txt (active) (pinned) - data/numbers/1.txt (active) (pinned)
Scenario: :tab-pin open url with tabs.pinned.frozen = false
When I set tabs.pinned.frozen to false
And I open data/numbers/1.txt
And I run :tab-pin
And I open data/numbers/2.txt
Then the following tabs should be open:
- data/numbers/2.txt (active) (pinned)
Scenario: :home on a pinned tab Scenario: :home on a pinned tab
When I open data/numbers/1.txt When I open data/numbers/1.txt
And I run :tab-pin And I run :tab-pin
@ -1297,6 +1305,16 @@ Feature: Tab management
And the following tabs should be open: And the following tabs should be open:
- data/numbers/1.txt (active) (pinned) - data/numbers/1.txt (active) (pinned)
Scenario: :home on a pinned tab with tabs.pinned.frozen = false
When I set url.start_pages to ["http://localhost:(port)/data/numbers/2.txt"]
And I set tabs.pinned.frozen to false
And I open data/numbers/1.txt
And I run :tab-pin
And I run :home
Then data/numbers/2.txt should be loaded
And the following tabs should be open:
- data/numbers/2.txt (active) (pinned)
Scenario: Cloning a pinned tab Scenario: Cloning a pinned tab
When I open data/numbers/1.txt When I open data/numbers/1.txt
And I run :tab-pin And I run :tab-pin

View File

@ -26,18 +26,15 @@ from qutebrowser.browser import shared
@pytest.mark.parametrize('dnt, accept_language, custom_headers, expected', [ @pytest.mark.parametrize('dnt, accept_language, custom_headers, expected', [
# DNT # DNT
(True, None, {}, {b'DNT': b'1', b'X-Do-Not-Track': b'1'}), (True, None, {}, {b'DNT': b'1'}),
(False, None, {}, {b'DNT': b'0', b'X-Do-Not-Track': b'0'}), (False, None, {}, {b'DNT': b'0'}),
(None, None, {}, {}), (None, None, {}, {}),
# Accept-Language # Accept-Language
(False, 'de, en', {}, {b'DNT': b'0', b'X-Do-Not-Track': b'0', (False, 'de, en', {}, {b'DNT': b'0', b'Accept-Language': b'de, en'}),
b'Accept-Language': b'de, en'}),
# Custom headers # Custom headers
(False, None, {'X-Qute': 'yes'}, {b'DNT': b'0', b'X-Do-Not-Track': b'0', (False, None, {'X-Qute': 'yes'}, {b'DNT': b'0', b'X-Qute': b'yes'}),
b'X-Qute': b'yes'}),
# Mixed # Mixed
(False, 'de, en', {'X-Qute': 'yes'}, {b'DNT': b'0', (False, 'de, en', {'X-Qute': 'yes'}, {b'DNT': b'0',
b'X-Do-Not-Track': b'0',
b'Accept-Language': b'de, en', b'Accept-Language': b'de, en',
b'X-Qute': b'yes'}), b'X-Qute': b'yes'}),
]) ])

View File

@ -205,6 +205,20 @@ def test_secret_url(url, has_secret, from_file):
res.resolve(QNetworkProxyQuery(QUrl(url)), from_file=from_file) res.resolve(QNetworkProxyQuery(QUrl(url)), from_file=from_file)
def test_logging(qtlog):
"""Make sure console.log() works for PAC files."""
test_str = """
function FindProxyForURL(domain, host) {
console.log("logging test");
return "DIRECT";
}
"""
res = pac.PACResolver(test_str)
res.resolve(QNetworkProxyQuery(QUrl("https://example.com/test")))
assert len(qtlog.records) == 1
assert qtlog.records[0].message == 'logging test'
def fetcher_test(test_str): def fetcher_test(test_str):
class PACHandler(http.server.BaseHTTPRequestHandler): class PACHandler(http.server.BaseHTTPRequestHandler):
def do_GET(self): def do_GET(self):

View File

@ -20,7 +20,8 @@ from unittest import mock
import pytest import pytest
from PyQt5.QtCore import Qt from PyQt5.QtCore import Qt
from PyQt5.QtGui import QTextDocument from PyQt5.QtGui import QTextDocument, QColor
from PyQt5.QtWidgets import QTextEdit
from qutebrowser.completion import completiondelegate from qutebrowser.completion import completiondelegate
@ -50,3 +51,24 @@ def test_highlight(pat, txt, segments):
highlighter.setFormat.assert_has_calls([ highlighter.setFormat.assert_has_calls([
mock.call(s[0], s[1], mock.ANY) for s in segments mock.call(s[0], s[1], mock.ANY) for s in segments
]) ])
def test_highlighted(qtbot):
"""Make sure highlighting works.
Note that with Qt 5.11.3 and > 5.12.1 we need to call setPlainText *after*
creating the highlighter for highlighting to work. Ideally, we'd test
whether CompletionItemDelegate._get_textdoc() works properly, but testing
that is kind of hard, so we just test it in isolation here.
"""
doc = QTextDocument()
completiondelegate._Highlighter(doc, 'Hello', Qt.red)
doc.setPlainText('Hello World')
# Needed so the highlighting actually works.
edit = QTextEdit()
qtbot.addWidget(edit)
edit.setDocument(doc)
colors = [f.foreground().color() for f in doc.allFormats()]
assert QColor('red') in colors

View File

@ -50,3 +50,17 @@ def test_configcache_get_after_set(config_stub):
assert not config.cache['auto_save.session'] assert not config.cache['auto_save.session']
config_stub.val.auto_save.session = True config_stub.val.auto_save.session = True
assert config.cache['auto_save.session'] assert config.cache['auto_save.session']
def test_configcache_naive_benchmark(config_stub, benchmark):
def _run_bench():
for _i in range(10000):
# pylint: disable=pointless-statement
config.cache['tabs.padding']
config.cache['tabs.indicator.width']
config.cache['tabs.indicator.padding']
config.cache['tabs.min_width']
config.cache['tabs.max_width']
config.cache['tabs.pinned.shrink']
# pylint: enable=pointless-statement
benchmark(_run_bench)

View File

@ -250,36 +250,28 @@ class TestYaml:
data = autoconfig.read() data = autoconfig.read()
assert data['content.webrtc_ip_handling_policy']['global'] == expected assert data['content.webrtc_ip_handling_policy']['global'] == expected
@pytest.mark.parametrize('show, expected', [ @pytest.mark.parametrize('setting, old, new', [
(True, 'always'), ('tabs.favicons.show', True, 'always'),
(False, 'never'), ('tabs.favicons.show', False, 'never'),
('always', 'always'), ('tabs.favicons.show', 'always', 'always'),
('never', 'never'),
('pinned', 'pinned'), ('scrolling.bar', True, 'always'),
('scrolling.bar', False, 'when-searching'),
('scrolling.bar', 'always', 'always'),
('qt.force_software_rendering', True, 'software-opengl'),
('qt.force_software_rendering', False, 'none'),
('qt.force_software_rendering', 'chromium', 'chromium'),
]) ])
def test_tabs_favicons_show(self, yaml, autoconfig, show, expected): def test_bool_migrations(self, yaml, autoconfig, setting, old, new):
"""Tests for migration of tabs.favicons.show.""" """Tests for migration of former boolean settings."""
autoconfig.write({'tabs.favicons.show': {'global': show}}) autoconfig.write({setting: {'global': old}})
yaml.load() yaml.load()
yaml._save() yaml._save()
data = autoconfig.read() data = autoconfig.read()
assert data['tabs.favicons.show']['global'] == expected assert data[setting]['global'] == new
@pytest.mark.parametrize('force, expected', [
(True, 'software-opengl'),
(False, 'none'),
('chromium', 'chromium'),
])
def test_force_software_rendering(self, yaml, autoconfig, force, expected):
autoconfig.write({'qt.force_software_rendering': {'global': force}})
yaml.load()
yaml._save()
data = autoconfig.read()
assert data['qt.force_software_rendering']['global'] == expected
def test_renamed_key_unknown_target(self, monkeypatch, yaml, def test_renamed_key_unknown_target(self, monkeypatch, yaml,
autoconfig): autoconfig):