Redirect qute:foo to qute://foo
Before, we just returned the same data for both, but then we'll run into same-origin restrictions as qute:history and qute:history/data are not the same host.
This commit is contained in:
parent
3cc9f9f073
commit
4ec5700cbf
@ -9,7 +9,7 @@ directly ask me via IRC (nickname thorsten\`) in #qutebrowser on freenode.
|
|||||||
|
|
||||||
$blink!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!$reset
|
$blink!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!$reset
|
||||||
WARNING: the passwords are stored in qutebrowser's
|
WARNING: the passwords are stored in qutebrowser's
|
||||||
debug log reachable via the url qute:log
|
debug log reachable via the url qute://log
|
||||||
$blink!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!$reset
|
$blink!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!$reset
|
||||||
|
|
||||||
Usage: run as a userscript form qutebrowser, e.g.:
|
Usage: run as a userscript form qutebrowser, e.g.:
|
||||||
|
@ -273,7 +273,7 @@ class DownloadItem(downloads.AbstractDownloadItem):
|
|||||||
if self.fileobj is None or self._reply is None:
|
if self.fileobj is None or self._reply is None:
|
||||||
# No filename has been set yet (so we don't empty the buffer) or we
|
# No filename has been set yet (so we don't empty the buffer) or we
|
||||||
# got a readyRead after the reply was finished (which happens on
|
# got a readyRead after the reply was finished (which happens on
|
||||||
# qute:log for example).
|
# qute://log for example).
|
||||||
return
|
return
|
||||||
if not self._reply.isOpen():
|
if not self._reply.isOpen():
|
||||||
raise OSError("Reply is closed!")
|
raise OSError("Reply is closed!")
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
|
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
"""Backend-independent qute:* code.
|
"""Backend-independent qute://* code.
|
||||||
|
|
||||||
Module attributes:
|
Module attributes:
|
||||||
pyeval_output: The output of the last :pyeval command.
|
pyeval_output: The output of the last :pyeval command.
|
||||||
@ -31,7 +31,7 @@ import time
|
|||||||
import urllib.parse
|
import urllib.parse
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
from PyQt5.QtCore import QUrlQuery
|
from PyQt5.QtCore import QUrlQuery, QUrl
|
||||||
|
|
||||||
import qutebrowser
|
import qutebrowser
|
||||||
from qutebrowser.config import config
|
from qutebrowser.config import config
|
||||||
@ -78,12 +78,25 @@ class QuteSchemeError(Exception):
|
|||||||
super().__init__(errorstring)
|
super().__init__(errorstring)
|
||||||
|
|
||||||
|
|
||||||
class add_handler: # pylint: disable=invalid-name
|
class Redirect(Exception):
|
||||||
|
|
||||||
"""Decorator to register a qute:* URL handler.
|
"""Exception to signal a redirect should happen.
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
_name: The 'foo' part of qute:foo
|
url: The URL to redirect to, as a QUrl.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, url):
|
||||||
|
super().__init__(url.toDisplayString())
|
||||||
|
self.url = url
|
||||||
|
|
||||||
|
|
||||||
|
class add_handler: # pylint: disable=invalid-name
|
||||||
|
|
||||||
|
"""Decorator to register a qute://* URL handler.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
_name: The 'foo' part of qute://foo
|
||||||
backend: Limit which backends the handler can run with.
|
backend: Limit which backends the handler can run with.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -106,7 +119,7 @@ class add_handler: # pylint: disable=invalid-name
|
|||||||
def wrong_backend_handler(self, url):
|
def wrong_backend_handler(self, url):
|
||||||
"""Show an error page about using the invalid backend."""
|
"""Show an error page about using the invalid backend."""
|
||||||
html = jinja.render('error.html',
|
html = jinja.render('error.html',
|
||||||
title="Error while opening qute:url",
|
title="Error while opening qute://url",
|
||||||
url=url.toDisplayString(),
|
url=url.toDisplayString(),
|
||||||
error='{} is not available with this '
|
error='{} is not available with this '
|
||||||
'backend'.format(url.toDisplayString()),
|
'backend'.format(url.toDisplayString()),
|
||||||
@ -128,13 +141,17 @@ def data_for_url(url):
|
|||||||
# A url like "qute:foo" is split as "scheme:path", not "scheme:host".
|
# A url like "qute:foo" is split as "scheme:path", not "scheme:host".
|
||||||
log.misc.debug("url: {}, path: {}, host {}".format(
|
log.misc.debug("url: {}, path: {}, host {}".format(
|
||||||
url.toDisplayString(), path, host))
|
url.toDisplayString(), path, host))
|
||||||
|
if path and not host:
|
||||||
|
new_url = QUrl()
|
||||||
|
new_url.setScheme('qute')
|
||||||
|
new_url.setHost(path)
|
||||||
|
raise Redirect(new_url)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
handler = _HANDLERS[path]
|
handler = _HANDLERS[host]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
try:
|
raise NoHandlerFound(url)
|
||||||
handler = _HANDLERS[host]
|
|
||||||
except KeyError:
|
|
||||||
raise NoHandlerFound(url)
|
|
||||||
try:
|
try:
|
||||||
mimetype, data = handler(url)
|
mimetype, data = handler(url)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
@ -153,7 +170,7 @@ def data_for_url(url):
|
|||||||
|
|
||||||
@add_handler('bookmarks')
|
@add_handler('bookmarks')
|
||||||
def qute_bookmarks(_url):
|
def qute_bookmarks(_url):
|
||||||
"""Handler for qute:bookmarks. Display all quickmarks / bookmarks."""
|
"""Handler for qute://bookmarks. Display all quickmarks / bookmarks."""
|
||||||
bookmarks = sorted(objreg.get('bookmark-manager').marks.items(),
|
bookmarks = sorted(objreg.get('bookmark-manager').marks.items(),
|
||||||
key=lambda x: x[1]) # Sort by title
|
key=lambda x: x[1]) # Sort by title
|
||||||
quickmarks = sorted(objreg.get('quickmark-manager').marks.items(),
|
quickmarks = sorted(objreg.get('quickmark-manager').marks.items(),
|
||||||
@ -246,7 +263,7 @@ def history_data(start_time): # noqa
|
|||||||
|
|
||||||
@add_handler('history')
|
@add_handler('history')
|
||||||
def qute_history(url):
|
def qute_history(url):
|
||||||
"""Handler for qute:history. Display and serve history."""
|
"""Handler for qute://history. Display and serve history."""
|
||||||
if url.path() == '/data':
|
if url.path() == '/data':
|
||||||
# Use start_time in query or current time.
|
# Use start_time in query or current time.
|
||||||
try:
|
try:
|
||||||
@ -309,7 +326,7 @@ def qute_history(url):
|
|||||||
|
|
||||||
@add_handler('javascript')
|
@add_handler('javascript')
|
||||||
def qute_javascript(url):
|
def qute_javascript(url):
|
||||||
"""Handler for qute:javascript.
|
"""Handler for qute://javascript.
|
||||||
|
|
||||||
Return content of file given as query parameter.
|
Return content of file given as query parameter.
|
||||||
"""
|
"""
|
||||||
@ -323,7 +340,7 @@ def qute_javascript(url):
|
|||||||
|
|
||||||
@add_handler('pyeval')
|
@add_handler('pyeval')
|
||||||
def qute_pyeval(_url):
|
def qute_pyeval(_url):
|
||||||
"""Handler for qute:pyeval."""
|
"""Handler for qute://pyeval."""
|
||||||
html = jinja.render('pre.html', title='pyeval', content=pyeval_output)
|
html = jinja.render('pre.html', title='pyeval', content=pyeval_output)
|
||||||
return 'text/html', html
|
return 'text/html', html
|
||||||
|
|
||||||
@ -331,7 +348,7 @@ def qute_pyeval(_url):
|
|||||||
@add_handler('version')
|
@add_handler('version')
|
||||||
@add_handler('verizon')
|
@add_handler('verizon')
|
||||||
def qute_version(_url):
|
def qute_version(_url):
|
||||||
"""Handler for qute:version."""
|
"""Handler for qute://version."""
|
||||||
html = jinja.render('version.html', title='Version info',
|
html = jinja.render('version.html', title='Version info',
|
||||||
version=version.version(),
|
version=version.version(),
|
||||||
copyright=qutebrowser.__copyright__)
|
copyright=qutebrowser.__copyright__)
|
||||||
@ -340,7 +357,7 @@ def qute_version(_url):
|
|||||||
|
|
||||||
@add_handler('plainlog')
|
@add_handler('plainlog')
|
||||||
def qute_plainlog(url):
|
def qute_plainlog(url):
|
||||||
"""Handler for qute:plainlog.
|
"""Handler for qute://plainlog.
|
||||||
|
|
||||||
An optional query parameter specifies the minimum log level to print.
|
An optional query parameter specifies the minimum log level to print.
|
||||||
For example, qute://log?level=warning prints warnings and errors.
|
For example, qute://log?level=warning prints warnings and errors.
|
||||||
@ -360,7 +377,7 @@ def qute_plainlog(url):
|
|||||||
|
|
||||||
@add_handler('log')
|
@add_handler('log')
|
||||||
def qute_log(url):
|
def qute_log(url):
|
||||||
"""Handler for qute:log.
|
"""Handler for qute://log.
|
||||||
|
|
||||||
An optional query parameter specifies the minimum log level to print.
|
An optional query parameter specifies the minimum log level to print.
|
||||||
For example, qute://log?level=warning prints warnings and errors.
|
For example, qute://log?level=warning prints warnings and errors.
|
||||||
@ -381,13 +398,13 @@ def qute_log(url):
|
|||||||
|
|
||||||
@add_handler('gpl')
|
@add_handler('gpl')
|
||||||
def qute_gpl(_url):
|
def qute_gpl(_url):
|
||||||
"""Handler for qute:gpl. Return HTML content as string."""
|
"""Handler for qute://gpl. Return HTML content as string."""
|
||||||
return 'text/html', utils.read_file('html/COPYING.html')
|
return 'text/html', utils.read_file('html/COPYING.html')
|
||||||
|
|
||||||
|
|
||||||
@add_handler('help')
|
@add_handler('help')
|
||||||
def qute_help(url):
|
def qute_help(url):
|
||||||
"""Handler for qute:help."""
|
"""Handler for qute://help."""
|
||||||
try:
|
try:
|
||||||
utils.read_file('html/doc/index.html')
|
utils.read_file('html/doc/index.html')
|
||||||
except OSError:
|
except OSError:
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
|
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
"""QtWebEngine specific qute:* handlers and glue code."""
|
"""QtWebEngine specific qute://* handlers and glue code."""
|
||||||
|
|
||||||
from PyQt5.QtCore import QBuffer, QIODevice
|
from PyQt5.QtCore import QBuffer, QIODevice
|
||||||
# pylint: disable=no-name-in-module,import-error,useless-suppression
|
# pylint: disable=no-name-in-module,import-error,useless-suppression
|
||||||
@ -26,15 +26,15 @@ from PyQt5.QtWebEngineCore import (QWebEngineUrlSchemeHandler,
|
|||||||
# pylint: enable=no-name-in-module,import-error,useless-suppression
|
# pylint: enable=no-name-in-module,import-error,useless-suppression
|
||||||
|
|
||||||
from qutebrowser.browser import qutescheme
|
from qutebrowser.browser import qutescheme
|
||||||
from qutebrowser.utils import log
|
from qutebrowser.utils import log, qtutils
|
||||||
|
|
||||||
|
|
||||||
class QuteSchemeHandler(QWebEngineUrlSchemeHandler):
|
class QuteSchemeHandler(QWebEngineUrlSchemeHandler):
|
||||||
|
|
||||||
"""Handle qute:* requests on QtWebEngine."""
|
"""Handle qute://* requests on QtWebEngine."""
|
||||||
|
|
||||||
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."""
|
||||||
profile.installUrlSchemeHandler(b'qute', self)
|
profile.installUrlSchemeHandler(b'qute', self)
|
||||||
|
|
||||||
def requestStarted(self, job):
|
def requestStarted(self, job):
|
||||||
@ -58,12 +58,15 @@ class QuteSchemeHandler(QWebEngineUrlSchemeHandler):
|
|||||||
job.fail(QWebEngineUrlRequestJob.UrlNotFound)
|
job.fail(QWebEngineUrlRequestJob.UrlNotFound)
|
||||||
except qutescheme.QuteSchemeOSError:
|
except qutescheme.QuteSchemeOSError:
|
||||||
# FIXME:qtwebengine how do we show a better error here?
|
# FIXME:qtwebengine how do we show a better error here?
|
||||||
log.misc.exception("OSError while handling qute:* URL")
|
log.misc.exception("OSError while handling qute://* URL")
|
||||||
job.fail(QWebEngineUrlRequestJob.UrlNotFound)
|
job.fail(QWebEngineUrlRequestJob.UrlNotFound)
|
||||||
except qutescheme.QuteSchemeError:
|
except qutescheme.QuteSchemeError:
|
||||||
# FIXME:qtwebengine how do we show a better error here?
|
# FIXME:qtwebengine how do we show a better error here?
|
||||||
log.misc.exception("Error while handling qute:* URL")
|
log.misc.exception("Error while handling qute://* URL")
|
||||||
job.fail(QWebEngineUrlRequestJob.RequestFailed)
|
job.fail(QWebEngineUrlRequestJob.RequestFailed)
|
||||||
|
except qutescheme.Redirect as e:
|
||||||
|
qtutils.ensure_valid(e.url)
|
||||||
|
job.redirect(e.url)
|
||||||
else:
|
else:
|
||||||
log.misc.debug("Returning {} data".format(mimetype))
|
log.misc.debug("Returning {} data".format(mimetype))
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ def init():
|
|||||||
app = QApplication.instance()
|
app = QApplication.instance()
|
||||||
profile = QWebEngineProfile.defaultProfile()
|
profile = QWebEngineProfile.defaultProfile()
|
||||||
|
|
||||||
log.init.debug("Initializing qute:* handler...")
|
log.init.debug("Initializing qute://* handler...")
|
||||||
_qute_scheme_handler = webenginequtescheme.QuteSchemeHandler(parent=app)
|
_qute_scheme_handler = webenginequtescheme.QuteSchemeHandler(parent=app)
|
||||||
_qute_scheme_handler.install(profile)
|
_qute_scheme_handler.install(profile)
|
||||||
|
|
||||||
|
@ -19,11 +19,15 @@
|
|||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
|
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# For some reason, a segfault will be triggered if the unnecessary lambdas in
|
||||||
|
# this file aren't there.
|
||||||
|
# pylint: disable=unnecessary-lambda
|
||||||
|
|
||||||
"""Special network replies.."""
|
"""Special network replies.."""
|
||||||
|
|
||||||
from PyQt5.QtNetwork import QNetworkReply, QNetworkRequest
|
from PyQt5.QtNetwork import QNetworkReply, QNetworkRequest, QNetworkAccessManager
|
||||||
from PyQt5.QtCore import pyqtSlot, QIODevice, QByteArray, QTimer
|
from PyQt5.QtCore import pyqtSlot, QIODevice, QByteArray, QTimer, QUrl
|
||||||
|
|
||||||
|
|
||||||
class FixedDataNetworkReply(QNetworkReply):
|
class FixedDataNetworkReply(QNetworkReply):
|
||||||
@ -114,9 +118,6 @@ class ErrorNetworkReply(QNetworkReply):
|
|||||||
# the device to avoid getting a warning.
|
# the device to avoid getting a warning.
|
||||||
self.setOpenMode(QIODevice.ReadOnly)
|
self.setOpenMode(QIODevice.ReadOnly)
|
||||||
self.setError(error, errorstring)
|
self.setError(error, errorstring)
|
||||||
# For some reason, a segfault will be triggered if these lambdas aren't
|
|
||||||
# there.
|
|
||||||
# pylint: disable=unnecessary-lambda
|
|
||||||
QTimer.singleShot(0, lambda: self.error.emit(error))
|
QTimer.singleShot(0, lambda: self.error.emit(error))
|
||||||
QTimer.singleShot(0, lambda: self.finished.emit())
|
QTimer.singleShot(0, lambda: self.finished.emit())
|
||||||
|
|
||||||
@ -137,3 +138,16 @@ class ErrorNetworkReply(QNetworkReply):
|
|||||||
|
|
||||||
def isRunning(self):
|
def isRunning(self):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
class RedirectNetworkReply(QNetworkReply):
|
||||||
|
|
||||||
|
"""A reply which redirects to the given URL."""
|
||||||
|
|
||||||
|
def __init__(self, new_url, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.setAttribute(QNetworkRequest.RedirectionTargetAttribute, new_url)
|
||||||
|
QTimer.singleShot(0, lambda: self.finished.emit())
|
||||||
|
|
||||||
|
def readData(self, _maxlen):
|
||||||
|
return bytes()
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
|
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
"""QtWebKit specific qute:* handlers and glue code."""
|
"""QtWebKit specific qute://* handlers and glue code."""
|
||||||
|
|
||||||
import mimetypes
|
import mimetypes
|
||||||
import functools
|
import functools
|
||||||
@ -28,13 +28,13 @@ from PyQt5.QtNetwork import QNetworkReply
|
|||||||
|
|
||||||
from qutebrowser.browser import pdfjs, qutescheme
|
from qutebrowser.browser import pdfjs, qutescheme
|
||||||
from qutebrowser.browser.webkit.network import schemehandler, networkreply
|
from qutebrowser.browser.webkit.network import schemehandler, networkreply
|
||||||
from qutebrowser.utils import jinja, log, message, objreg, usertypes
|
from qutebrowser.utils import jinja, log, message, objreg, usertypes, qtutils
|
||||||
from qutebrowser.config import configexc, configdata
|
from qutebrowser.config import configexc, configdata
|
||||||
|
|
||||||
|
|
||||||
class QuteSchemeHandler(schemehandler.SchemeHandler):
|
class QuteSchemeHandler(schemehandler.SchemeHandler):
|
||||||
|
|
||||||
"""Scheme handler for qute: URLs."""
|
"""Scheme handler for qute:// URLs."""
|
||||||
|
|
||||||
def createRequest(self, _op, request, _outgoing_data):
|
def createRequest(self, _op, request, _outgoing_data):
|
||||||
"""Create a new request.
|
"""Create a new request.
|
||||||
@ -62,6 +62,9 @@ class QuteSchemeHandler(schemehandler.SchemeHandler):
|
|||||||
except qutescheme.QuteSchemeError as e:
|
except qutescheme.QuteSchemeError as e:
|
||||||
return networkreply.ErrorNetworkReply(request, e.errorstring,
|
return networkreply.ErrorNetworkReply(request, e.errorstring,
|
||||||
e.error, self.parent())
|
e.error, self.parent())
|
||||||
|
except qutescheme.Redirect as e:
|
||||||
|
qtutils.ensure_valid(e.url)
|
||||||
|
return networkreply.RedirectNetworkReply(e.url, self.parent())
|
||||||
|
|
||||||
return networkreply.FixedDataNetworkReply(request, data, mimetype,
|
return networkreply.FixedDataNetworkReply(request, data, mimetype,
|
||||||
self.parent())
|
self.parent())
|
||||||
@ -69,15 +72,15 @@ class QuteSchemeHandler(schemehandler.SchemeHandler):
|
|||||||
|
|
||||||
class JSBridge(QObject):
|
class JSBridge(QObject):
|
||||||
|
|
||||||
"""Javascript-bridge for special qute:... pages."""
|
"""Javascript-bridge for special qute://... pages."""
|
||||||
|
|
||||||
@pyqtSlot(str, str, str)
|
@pyqtSlot(str, str, str)
|
||||||
def set(self, sectname, optname, value):
|
def set(self, sectname, optname, value):
|
||||||
"""Slot to set a setting from qute:settings."""
|
"""Slot to set a setting from qute://settings."""
|
||||||
# https://github.com/qutebrowser/qutebrowser/issues/727
|
# https://github.com/qutebrowser/qutebrowser/issues/727
|
||||||
if ((sectname, optname) == ('content', 'allow-javascript') and
|
if ((sectname, optname) == ('content', 'allow-javascript') and
|
||||||
value == 'false'):
|
value == 'false'):
|
||||||
message.error("Refusing to disable javascript via qute:settings "
|
message.error("Refusing to disable javascript via qute://settings "
|
||||||
"as it needs javascript support.")
|
"as it needs javascript support.")
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
@ -88,7 +91,7 @@ class JSBridge(QObject):
|
|||||||
|
|
||||||
@qutescheme.add_handler('settings', backend=usertypes.Backend.QtWebKit)
|
@qutescheme.add_handler('settings', backend=usertypes.Backend.QtWebKit)
|
||||||
def qute_settings(_url):
|
def qute_settings(_url):
|
||||||
"""Handler for qute:settings. View/change qute configuration."""
|
"""Handler for qute://settings. View/change qute configuration."""
|
||||||
config_getter = functools.partial(objreg.get('config').get, raw=True)
|
config_getter = functools.partial(objreg.get('config').get, raw=True)
|
||||||
html = jinja.render('settings.html', title='settings', config=configdata,
|
html = jinja.render('settings.html', title='settings', config=configdata,
|
||||||
confget=config_getter)
|
confget=config_getter)
|
||||||
|
@ -140,7 +140,7 @@ class WebView(QWebView):
|
|||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def add_js_bridge(self):
|
def add_js_bridge(self):
|
||||||
"""Add the javascript bridge for qute:... pages."""
|
"""Add the javascript bridge for qute://... pages."""
|
||||||
frame = self.sender()
|
frame = self.sender()
|
||||||
if not isinstance(frame, QWebFrame):
|
if not isinstance(frame, QWebFrame):
|
||||||
log.webview.error("Got non-QWebFrame {!r} in "
|
log.webview.error("Got non-QWebFrame {!r} in "
|
||||||
|
@ -805,7 +805,7 @@ class ConfigManager(QObject):
|
|||||||
if section_ is None and option is None:
|
if section_ is None and option is None:
|
||||||
tabbed_browser = objreg.get('tabbed-browser', scope='window',
|
tabbed_browser = objreg.get('tabbed-browser', scope='window',
|
||||||
window=win_id)
|
window=win_id)
|
||||||
tabbed_browser.openurl(QUrl('qute:settings'), newtab=False)
|
tabbed_browser.openurl(QUrl('qute://settings'), newtab=False)
|
||||||
return
|
return
|
||||||
|
|
||||||
if option.endswith('?') and option != '?':
|
if option.endswith('?') and option != '?':
|
||||||
|
@ -1689,7 +1689,7 @@ KEY_DATA = collections.OrderedDict([
|
|||||||
('home', ['<Ctrl-h>']),
|
('home', ['<Ctrl-h>']),
|
||||||
('stop', ['<Ctrl-s>']),
|
('stop', ['<Ctrl-s>']),
|
||||||
('print', ['<Ctrl-Alt-p>']),
|
('print', ['<Ctrl-Alt-p>']),
|
||||||
('open qute:settings', ['Ss']),
|
('open qute://settings', ['Ss']),
|
||||||
('follow-selected', RETURN_KEYS),
|
('follow-selected', RETURN_KEYS),
|
||||||
('follow-selected -t', ['<Ctrl-Return>', '<Ctrl-Enter>']),
|
('follow-selected -t', ['<Ctrl-Return>', '<Ctrl-Enter>']),
|
||||||
('repeat-command', ['.']),
|
('repeat-command', ['.']),
|
||||||
|
@ -228,7 +228,7 @@ def debug_pyeval(s, quiet=False):
|
|||||||
else:
|
else:
|
||||||
tabbed_browser = objreg.get('tabbed-browser', scope='window',
|
tabbed_browser = objreg.get('tabbed-browser', scope='window',
|
||||||
window='last-focused')
|
window='last-focused')
|
||||||
tabbed_browser.openurl(QUrl('qute:pyeval'), newtab=True)
|
tabbed_browser.openurl(QUrl('qute://pyeval'), newtab=True)
|
||||||
|
|
||||||
|
|
||||||
@cmdutils.register(debug=True)
|
@cmdutils.register(debug=True)
|
||||||
|
@ -74,7 +74,7 @@ def whitelist_generator():
|
|||||||
yield 'PyQt5.QtWebKit.QWebPage.ErrorPageExtensionReturn().fileNames'
|
yield 'PyQt5.QtWebKit.QWebPage.ErrorPageExtensionReturn().fileNames'
|
||||||
yield 'PyQt5.QtWidgets.QStyleOptionViewItem.backgroundColor'
|
yield 'PyQt5.QtWidgets.QStyleOptionViewItem.backgroundColor'
|
||||||
|
|
||||||
## qute:... handlers
|
## qute://... handlers
|
||||||
for name in qutescheme._HANDLERS: # pylint: disable=protected-access
|
for name in qutescheme._HANDLERS: # pylint: disable=protected-access
|
||||||
yield 'qutebrowser.browser.qutescheme.qute_' + name
|
yield 'qutebrowser.browser.qutescheme.qute_' + name
|
||||||
|
|
||||||
|
@ -83,6 +83,14 @@ Feature: Page history
|
|||||||
Then the page should contain the plaintext "3.txt"
|
Then the page should contain the plaintext "3.txt"
|
||||||
Then the page should contain the plaintext "4.txt"
|
Then the page should contain the plaintext "4.txt"
|
||||||
|
|
||||||
|
Scenario: Listing history with qute:history redirect
|
||||||
|
When I open data/numbers/3.txt
|
||||||
|
And I open data/numbers/4.txt
|
||||||
|
And I open qute:history without waiting
|
||||||
|
And I wait until qute://history is loaded
|
||||||
|
Then the page should contain the plaintext "3.txt"
|
||||||
|
Then the page should contain the plaintext "4.txt"
|
||||||
|
|
||||||
## Bugs
|
## Bugs
|
||||||
|
|
||||||
@qtwebengine_skip @qtwebkit_ng_skip
|
@qtwebengine_skip @qtwebkit_ng_skip
|
||||||
|
@ -405,12 +405,12 @@ Feature: Various utility commands.
|
|||||||
# :pyeval
|
# :pyeval
|
||||||
Scenario: Running :pyeval
|
Scenario: Running :pyeval
|
||||||
When I run :debug-pyeval 1+1
|
When I run :debug-pyeval 1+1
|
||||||
And I wait until qute:pyeval is loaded
|
And I wait until qute://pyeval is loaded
|
||||||
Then the page should contain the plaintext "2"
|
Then the page should contain the plaintext "2"
|
||||||
|
|
||||||
Scenario: Causing exception in :pyeval
|
Scenario: Causing exception in :pyeval
|
||||||
When I run :debug-pyeval 1/0
|
When I run :debug-pyeval 1/0
|
||||||
And I wait until qute:pyeval is loaded
|
And I wait until qute://pyeval is loaded
|
||||||
Then the page should contain the plaintext "ZeroDivisionError"
|
Then the page should contain the plaintext "ZeroDivisionError"
|
||||||
|
|
||||||
Scenario: Running :pyeval with --quiet
|
Scenario: Running :pyeval with --quiet
|
||||||
@ -512,12 +512,12 @@ Feature: Various utility commands.
|
|||||||
When I run :messages cataclysmic
|
When I run :messages cataclysmic
|
||||||
Then the error "Invalid log level cataclysmic!" should be shown
|
Then the error "Invalid log level cataclysmic!" should be shown
|
||||||
|
|
||||||
Scenario: Using qute:log directly
|
Scenario: Using qute://log directly
|
||||||
When I open qute:log
|
When I open qute://log
|
||||||
Then no crash should happen
|
Then no crash should happen
|
||||||
|
|
||||||
Scenario: Using qute:plainlog directly
|
Scenario: Using qute://plainlog directly
|
||||||
When I open qute:plainlog
|
When I open qute://plainlog
|
||||||
Then no crash should happen
|
Then no crash should happen
|
||||||
|
|
||||||
Scenario: Using :messages without messages
|
Scenario: Using :messages without messages
|
||||||
|
@ -78,15 +78,15 @@ Feature: Setting settings.
|
|||||||
When I run :set -t colors statusbar.bg green
|
When I run :set -t colors statusbar.bg green
|
||||||
Then colors -> statusbar.bg should be green
|
Then colors -> statusbar.bg should be green
|
||||||
|
|
||||||
# qute:settings isn't actually implemented on QtWebEngine, but this works
|
# qute://settings isn't actually implemented on QtWebEngine, but this works
|
||||||
# (and displays a page saying it's not available)
|
# (and displays a page saying it's not available)
|
||||||
Scenario: Opening qute:settings
|
Scenario: Opening qute://settings
|
||||||
When I run :set
|
When I run :set
|
||||||
And I wait until qute:settings is loaded
|
And I wait until qute://settings is loaded
|
||||||
Then the following tabs should be open:
|
Then the following tabs should be open:
|
||||||
- qute:settings (active)
|
- qute://settings (active)
|
||||||
|
|
||||||
@qtwebengine_todo: qute:settings is not implemented yet
|
@qtwebengine_todo: qute://settings is not implemented yet
|
||||||
Scenario: Focusing input fields in qute://settings and entering valid value
|
Scenario: Focusing input fields in qute://settings and entering valid value
|
||||||
When I set general -> ignore-case to false
|
When I set general -> ignore-case to false
|
||||||
And I open qute://settings
|
And I open qute://settings
|
||||||
@ -101,7 +101,7 @@ Feature: Setting settings.
|
|||||||
And I press the key "<Tab>"
|
And I press the key "<Tab>"
|
||||||
Then general -> ignore-case should be true
|
Then general -> ignore-case should be true
|
||||||
|
|
||||||
@qtwebengine_todo: qute:settings is not implemented yet
|
@qtwebengine_todo: qute://settings is not implemented yet
|
||||||
Scenario: Focusing input fields in qute://settings and entering invalid value
|
Scenario: Focusing input fields in qute://settings and entering invalid value
|
||||||
When I open qute://settings
|
When I open qute://settings
|
||||||
# scroll to the right - the table does not fit in the default screen
|
# scroll to the right - the table does not fit in the default screen
|
||||||
|
@ -225,12 +225,12 @@ Feature: quickmarks and bookmarks
|
|||||||
Scenario: Listing quickmarks
|
Scenario: Listing quickmarks
|
||||||
When I run :quickmark-add http://localhost:(port)/data/numbers/20.txt twenty
|
When I run :quickmark-add http://localhost:(port)/data/numbers/20.txt twenty
|
||||||
And I run :quickmark-add http://localhost:(port)/data/numbers/21.txt twentyone
|
And I run :quickmark-add http://localhost:(port)/data/numbers/21.txt twentyone
|
||||||
And I open qute:bookmarks
|
And I open qute://bookmarks
|
||||||
Then the page should contain the plaintext "twenty"
|
Then the page should contain the plaintext "twenty"
|
||||||
And the page should contain the plaintext "twentyone"
|
And the page should contain the plaintext "twentyone"
|
||||||
|
|
||||||
Scenario: Listing bookmarks
|
Scenario: Listing bookmarks
|
||||||
When I open data/title.html in a new tab
|
When I open data/title.html in a new tab
|
||||||
And I run :bookmark-add
|
And I run :bookmark-add
|
||||||
And I open qute:bookmarks
|
And I open qute://bookmarks
|
||||||
Then the page should contain the plaintext "Test title"
|
Then the page should contain the plaintext "Test title"
|
||||||
|
@ -145,7 +145,7 @@ Feature: Miscellaneous utility commands exposed to the user.
|
|||||||
And I run :message-info oldstuff
|
And I run :message-info oldstuff
|
||||||
And I run :repeat 20 message-info otherstuff
|
And I run :repeat 20 message-info otherstuff
|
||||||
And I run :message-info newstuff
|
And I run :message-info newstuff
|
||||||
And I open qute:log
|
And I open qute://log
|
||||||
Then the page should contain the plaintext "newstuff"
|
Then the page should contain the plaintext "newstuff"
|
||||||
And the page should not contain the plaintext "oldstuff"
|
And the page should not contain the plaintext "oldstuff"
|
||||||
|
|
||||||
|
@ -138,10 +138,10 @@ def test_misconfigured_user_dirs(request, httpbin, temp_basedir_env,
|
|||||||
|
|
||||||
|
|
||||||
def test_no_loglines(request, quteproc_new):
|
def test_no_loglines(request, quteproc_new):
|
||||||
"""Test qute:log with --loglines=0."""
|
"""Test qute://log with --loglines=0."""
|
||||||
quteproc_new.start(args=['--temp-basedir', '--loglines=0'] +
|
quteproc_new.start(args=['--temp-basedir', '--loglines=0'] +
|
||||||
_base_args(request.config))
|
_base_args(request.config))
|
||||||
quteproc_new.open_path('qute:log')
|
quteproc_new.open_path('qute://log')
|
||||||
assert quteproc_new.get_content() == 'Log output was disabled.'
|
assert quteproc_new.get_content() == 'Log output was disabled.'
|
||||||
|
|
||||||
|
|
||||||
|
@ -91,3 +91,10 @@ def test_error_network_reply(qtbot, req):
|
|||||||
assert reply.readData(1) == b''
|
assert reply.readData(1) == b''
|
||||||
assert reply.error() == QNetworkReply.UnknownNetworkError
|
assert reply.error() == QNetworkReply.UnknownNetworkError
|
||||||
assert reply.errorString() == "This is an error"
|
assert reply.errorString() == "This is an error"
|
||||||
|
|
||||||
|
|
||||||
|
def test_redirect_network_reply():
|
||||||
|
url = QUrl('https://www.example.com/')
|
||||||
|
reply = networkreply.RedirectNetworkReply(url)
|
||||||
|
assert reply.readData(1) == b''
|
||||||
|
assert reply.attribute(QNetworkRequest.RedirectionTargetAttribute) == url
|
||||||
|
@ -265,6 +265,7 @@ class TestFuzzyUrl:
|
|||||||
('file:///tmp/foo', True),
|
('file:///tmp/foo', True),
|
||||||
('about:blank', True),
|
('about:blank', True),
|
||||||
('qute:version', True),
|
('qute:version', True),
|
||||||
|
('qute://version', True),
|
||||||
('http://www.qutebrowser.org/', False),
|
('http://www.qutebrowser.org/', False),
|
||||||
('www.qutebrowser.org', False),
|
('www.qutebrowser.org', False),
|
||||||
])
|
])
|
||||||
@ -317,9 +318,11 @@ def test_get_search_url_invalid(urlutils_config_stub, url):
|
|||||||
(True, True, False, 'file:///tmp/foo'),
|
(True, True, False, 'file:///tmp/foo'),
|
||||||
(True, True, False, 'about:blank'),
|
(True, True, False, 'about:blank'),
|
||||||
(True, True, False, 'qute:version'),
|
(True, True, False, 'qute:version'),
|
||||||
|
(True, True, False, 'qute://version'),
|
||||||
(True, True, False, 'localhost'),
|
(True, True, False, 'localhost'),
|
||||||
# _has_explicit_scheme False, special_url True
|
# _has_explicit_scheme False, special_url True
|
||||||
(True, True, False, 'qute::foo'),
|
(True, True, False, 'qute::foo'),
|
||||||
|
(True, True, False, 'qute:://foo'),
|
||||||
# Invalid URLs
|
# Invalid URLs
|
||||||
(False, False, False, ''),
|
(False, False, False, ''),
|
||||||
(False, True, False, 'onlyscheme:'),
|
(False, True, False, 'onlyscheme:'),
|
||||||
|
Loading…
Reference in New Issue
Block a user