webengine: Initial support for authentication and javascript prompts
This commit is contained in:
parent
6d72bce4b6
commit
65625a9dea
@ -19,7 +19,15 @@
|
||||
|
||||
"""Various utilities shared between webpage/webview subclasses."""
|
||||
|
||||
import html
|
||||
|
||||
from qutebrowser.config import config
|
||||
from qutebrowser.utils import usertypes, message, log
|
||||
|
||||
|
||||
class CallSuper(Exception):
|
||||
|
||||
"""Raised when the caller should call the superclass instead."""
|
||||
|
||||
|
||||
def custom_headers():
|
||||
@ -39,3 +47,66 @@ def custom_headers():
|
||||
headers[b'Accept-Language'] = accept_language.encode('ascii')
|
||||
|
||||
return sorted(headers.items())
|
||||
|
||||
|
||||
def authentication_required(url, authenticator, abort_on):
|
||||
"""Ask a prompt for an authentication question."""
|
||||
msg = '<b>{}</b> says:<br/>{}'.format(
|
||||
html.escape(url.toDisplayString()),
|
||||
html.escape(authenticator.realm()))
|
||||
answer = message.ask(title="Authentication required", text=msg,
|
||||
mode=usertypes.PromptMode.user_pwd,
|
||||
abort_on=abort_on)
|
||||
if answer is not None:
|
||||
authenticator.setUser(answer.user)
|
||||
authenticator.setPassword(answer.password)
|
||||
|
||||
|
||||
def javascript_confirm(url, js_msg, abort_on):
|
||||
"""Display a javascript confirm prompt."""
|
||||
log.js.debug("confirm: {}".format(js_msg))
|
||||
if config.get('ui', 'modal-js-dialog'):
|
||||
raise CallSuper
|
||||
|
||||
msg = 'From <b>{}</b>:<br/>{}'.format(html.escape(url.toDisplayString()),
|
||||
html.escape(js_msg))
|
||||
ans = message.ask('Javascript confirm', msg,
|
||||
mode=usertypes.PromptMode.yesno,
|
||||
abort_on=abort_on)
|
||||
return bool(ans)
|
||||
|
||||
|
||||
def javascript_prompt(url, js_msg, default, abort_on):
|
||||
"""Display a javascript prompt."""
|
||||
log.js.debug("prompt: {}".format(js_msg))
|
||||
if config.get('ui', 'modal-js-dialog'):
|
||||
raise CallSuper
|
||||
if config.get('content', 'ignore-javascript-prompt'):
|
||||
return (False, "")
|
||||
|
||||
msg = '<b>{}</b> asks:<br/>{}'.format(html.escape(url.toDisplayString()),
|
||||
html.escape(js_msg))
|
||||
answer = message.ask('Javascript prompt', msg,
|
||||
mode=usertypes.PromptMode.text,
|
||||
default=default,
|
||||
abort_on=abort_on)
|
||||
|
||||
if answer is None:
|
||||
return (False, "")
|
||||
else:
|
||||
return (True, answer)
|
||||
|
||||
|
||||
def javascript_alert(url, js_msg, abort_on):
|
||||
"""Display a javascript alert."""
|
||||
log.js.debug("alert: {}".format(js_msg))
|
||||
if config.get('ui', 'modal-js-dialog'):
|
||||
raise CallSuper
|
||||
|
||||
if config.get('content', 'ignore-javascript-alert'):
|
||||
return
|
||||
|
||||
msg = 'From <b>{}</b>:<br/>{}'.format(html.escape(url.toDisplayString()),
|
||||
html.escape(js_msg))
|
||||
message.ask('Javascript alert', msg, mode=usertypes.PromptMode.alert,
|
||||
abort_on=abort_on)
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
"""Wrapper over a QWebEngineView."""
|
||||
|
||||
import html
|
||||
import functools
|
||||
|
||||
from PyQt5.QtCore import pyqtSlot, Qt, QEvent, QPoint, QUrl, QTimer
|
||||
@ -32,12 +33,12 @@ from PyQt5.QtWebEngineWidgets import (QWebEnginePage, QWebEngineScript,
|
||||
QWebEngineProfile)
|
||||
# pylint: enable=no-name-in-module,import-error,useless-suppression
|
||||
|
||||
from qutebrowser.browser import browsertab, mouse
|
||||
from qutebrowser.browser import browsertab, mouse, shared
|
||||
from qutebrowser.browser.webengine import (webview, webengineelem, tabhistory,
|
||||
interceptor, webenginequtescheme,
|
||||
webenginedownloads)
|
||||
from qutebrowser.utils import (usertypes, qtutils, log, javascript, utils,
|
||||
objreg)
|
||||
objreg, message)
|
||||
|
||||
|
||||
_qute_scheme_handler = None
|
||||
@ -538,7 +539,7 @@ class WebEngineTab(browsertab.AbstractTab):
|
||||
self._widget.page().runJavaScript(code, callback)
|
||||
|
||||
def shutdown(self):
|
||||
log.stub()
|
||||
self._widget.shutdown()
|
||||
|
||||
def reload(self, *, force=False):
|
||||
if force:
|
||||
@ -590,6 +591,13 @@ class WebEngineTab(browsertab.AbstractTab):
|
||||
|
||||
self.add_history_item.emit(url, requested_url, title)
|
||||
|
||||
@pyqtSlot(QUrl, 'QAuthenticator*')
|
||||
def _on_authentication_required(self, url, authenticator):
|
||||
# FIXME:qtwebengine support .netrc
|
||||
shared.authentication_required(url, authenticator,
|
||||
abort_on=[self.shutting_down,
|
||||
self.load_started])
|
||||
|
||||
def _connect_signals(self):
|
||||
view = self._widget
|
||||
page = view.page()
|
||||
@ -603,6 +611,7 @@ class WebEngineTab(browsertab.AbstractTab):
|
||||
page.loadFinished.connect(self._on_load_finished)
|
||||
page.certificate_error.connect(self._on_ssl_errors)
|
||||
page.link_clicked.connect(self._on_link_clicked)
|
||||
page.authenticationRequired.connect(self._on_authentication_required)
|
||||
try:
|
||||
view.iconChanged.connect(self.icon_changed)
|
||||
except AttributeError:
|
||||
|
@ -26,6 +26,7 @@ from PyQt5.QtCore import pyqtSignal, QUrl
|
||||
from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEnginePage
|
||||
# pylint: enable=no-name-in-module,import-error,useless-suppression
|
||||
|
||||
from qutebrowser.browser import shared
|
||||
from qutebrowser.config import config
|
||||
from qutebrowser.utils import log, debug, usertypes, objreg, qtutils
|
||||
|
||||
@ -39,6 +40,9 @@ class WebEngineView(QWebEngineView):
|
||||
self._win_id = win_id
|
||||
self.setPage(WebEnginePage(tabdata, parent=self))
|
||||
|
||||
def shutdown(self):
|
||||
self.page().shutdown()
|
||||
|
||||
def createWindow(self, wintype):
|
||||
"""Called by Qt when a page wants to create a new window.
|
||||
|
||||
@ -99,22 +103,65 @@ class WebEnginePage(QWebEnginePage):
|
||||
|
||||
"""Custom QWebEnginePage subclass with qutebrowser-specific features.
|
||||
|
||||
Attributes:
|
||||
_is_shutting_down: Whether the page is currently shutting down.
|
||||
|
||||
Signals:
|
||||
certificate_error: FIXME:qtwebengine
|
||||
link_clicked: Emitted when a link was clicked on a page.
|
||||
shutting_down: Emitted when the page is shutting down.
|
||||
"""
|
||||
|
||||
certificate_error = pyqtSignal()
|
||||
link_clicked = pyqtSignal(QUrl)
|
||||
shutting_down = pyqtSignal()
|
||||
|
||||
def __init__(self, tabdata, parent=None):
|
||||
super().__init__(parent)
|
||||
self._tabdata = tabdata
|
||||
self._is_shutting_down = False
|
||||
|
||||
def shutdown(self):
|
||||
self._is_shutting_down = True
|
||||
self.shutting_down.emit()
|
||||
|
||||
def certificateError(self, error):
|
||||
self.certificate_error.emit()
|
||||
return super().certificateError(error)
|
||||
|
||||
def javaScriptConfirm(self, url, js_msg):
|
||||
if self._is_shutting_down:
|
||||
return False
|
||||
try:
|
||||
return shared.javascript_confirm(url, js_msg,
|
||||
abort_on=[self.loadStarted,
|
||||
self.shutting_down])
|
||||
except shared.CallSuper:
|
||||
return super().javaScriptConfirm(url, js_msg)
|
||||
|
||||
# Can't override javaScriptPrompt currently
|
||||
# https://www.riverbankcomputing.com/pipermail/pyqt/2016-November/038293.html
|
||||
# def javaScriptPrompt(self, url, js_msg, default, result):
|
||||
# if self._is_shutting_down:
|
||||
# return (False, "")
|
||||
# try:
|
||||
# return shared.javascript_prompt(url, js_msg, default,
|
||||
# abort_on=[self.loadStarted,
|
||||
# self.shutting_down])
|
||||
# except shared.CallSuper:
|
||||
# return super().javaScriptPrompt(url, js_msg, default)
|
||||
|
||||
def javaScriptAlert(self, url, js_msg):
|
||||
"""Override javaScriptAlert to use the statusbar."""
|
||||
if self._is_shutting_down:
|
||||
return
|
||||
try:
|
||||
shared.javascript_alert(url, js_msg,
|
||||
abort_on=[self.loadStarted,
|
||||
self.shutting_down])
|
||||
except shared.CallSuper:
|
||||
super().javaScriptAlert(url, js_msg)
|
||||
|
||||
def javaScriptConsoleMessage(self, level, msg, line, source):
|
||||
"""Log javascript messages to qutebrowser's log."""
|
||||
# FIXME:qtwebengine maybe unify this in the tab api somehow?
|
||||
|
@ -343,19 +343,18 @@ class NetworkManager(QNetworkAccessManager):
|
||||
except netrc.NetrcParseError:
|
||||
log.misc.exception("Error when parsing the netrc file")
|
||||
|
||||
if user is None:
|
||||
# netrc check failed
|
||||
msg = '<b>{}</b> says:<br/>{}'.format(
|
||||
html.escape(reply.url().toDisplayString()),
|
||||
html.escape(authenticator.realm()))
|
||||
answer = self._ask("Authentication required",
|
||||
text=msg, mode=usertypes.PromptMode.user_pwd,
|
||||
owner=reply)
|
||||
if answer is not None:
|
||||
user, password = answer.user, answer.password
|
||||
if user is not None:
|
||||
authenticator.setUser(user)
|
||||
authenticator.setPassword(password)
|
||||
else:
|
||||
abort_on = [self.shutting_down, reply.destroyed]
|
||||
if self._tab_id is not None:
|
||||
tab = objreg.get('tab', scope='tab', window=self._win_id,
|
||||
tab=self._tab_id)
|
||||
abort_on.append(tab.load_started)
|
||||
|
||||
shared.authentication_required(reply.url(), authenticator,
|
||||
abort_on=abort_on)
|
||||
|
||||
@pyqtSlot('QNetworkProxy', 'QAuthenticator*')
|
||||
def on_proxy_authentication_required(self, proxy, authenticator):
|
||||
|
@ -30,7 +30,7 @@ from PyQt5.QtPrintSupport import QPrintDialog
|
||||
from PyQt5.QtWebKitWidgets import QWebPage, QWebFrame
|
||||
|
||||
from qutebrowser.config import config
|
||||
from qutebrowser.browser import pdfjs
|
||||
from qutebrowser.browser import pdfjs, shared
|
||||
from qutebrowser.browser.webkit import http
|
||||
from qutebrowser.browser.webkit.network import networkmanager
|
||||
from qutebrowser.utils import (message, usertypes, log, jinja, qtutils, utils,
|
||||
@ -94,23 +94,16 @@ class BrowserPage(QWebPage):
|
||||
# of a bug in PyQt.
|
||||
# See http://www.riverbankcomputing.com/pipermail/pyqt/2014-June/034385.html
|
||||
|
||||
def javaScriptPrompt(self, _frame, js_msg, default):
|
||||
def javaScriptPrompt(self, frame, js_msg, default):
|
||||
"""Override javaScriptPrompt to use the statusbar."""
|
||||
if (self._is_shutting_down or
|
||||
config.get('content', 'ignore-javascript-prompt')):
|
||||
if self._is_shutting_down:
|
||||
return (False, "")
|
||||
msg = '<b>{}</b> asks:<br/>{}'.format(
|
||||
html.escape(self.mainFrame().url().toDisplayString()),
|
||||
html.escape(js_msg))
|
||||
answer = message.ask('Javascript prompt', msg,
|
||||
mode=usertypes.PromptMode.text,
|
||||
default=default,
|
||||
abort_on=[self.loadStarted,
|
||||
self.shutting_down])
|
||||
if answer is None:
|
||||
return (False, "")
|
||||
else:
|
||||
return (True, answer)
|
||||
try:
|
||||
return shared.javascript_prompt(frame.url(), js_msg, default,
|
||||
abort_on=[self.loadStarted,
|
||||
self.shutting_down])
|
||||
except shared.CallSuper:
|
||||
return super().javaScriptPrompt(frame, js_msg, default)
|
||||
|
||||
def _handle_errorpage(self, info, errpage):
|
||||
"""Display an error page if needed.
|
||||
@ -442,36 +435,25 @@ class BrowserPage(QWebPage):
|
||||
|
||||
def javaScriptAlert(self, frame, js_msg):
|
||||
"""Override javaScriptAlert to use the statusbar."""
|
||||
log.js.debug("alert: {}".format(js_msg))
|
||||
if config.get('ui', 'modal-js-dialog'):
|
||||
return super().javaScriptAlert(frame, js_msg)
|
||||
|
||||
if (self._is_shutting_down or
|
||||
config.get('content', 'ignore-javascript-alert')):
|
||||
if self._is_shutting_down:
|
||||
return
|
||||
|
||||
msg = 'From <b>{}</b>:<br/>{}'.format(
|
||||
html.escape(self.mainFrame().url().toDisplayString()),
|
||||
html.escape(js_msg))
|
||||
message.ask('Javascript alert', msg, mode=usertypes.PromptMode.alert,
|
||||
abort_on=[self.loadStarted, self.shutting_down])
|
||||
try:
|
||||
shared.javascript_alert(frame.url(), js_msg,
|
||||
abort_on=[self.loadStarted,
|
||||
self.shutting_down])
|
||||
except shared.CallSuper:
|
||||
super().javaScriptAlert(frame, js_msg)
|
||||
|
||||
def javaScriptConfirm(self, frame, js_msg):
|
||||
"""Override javaScriptConfirm to use the statusbar."""
|
||||
log.js.debug("confirm: {}".format(js_msg))
|
||||
if config.get('ui', 'modal-js-dialog'):
|
||||
return super().javaScriptConfirm(frame, js_msg)
|
||||
|
||||
if self._is_shutting_down:
|
||||
return False
|
||||
|
||||
msg = 'From <b>{}</b>:<br/>{}'.format(
|
||||
html.escape(self.mainFrame().url().toDisplayString()),
|
||||
html.escape(js_msg))
|
||||
ans = message.ask('Javascript confirm', msg,
|
||||
mode=usertypes.PromptMode.yesno,
|
||||
abort_on=[self.loadStarted, self.shutting_down])
|
||||
return bool(ans)
|
||||
try:
|
||||
return shared.javascript_confirm(frame.url(), js_msg,
|
||||
abort_on=[self.loadStarted,
|
||||
self.shutting_down])
|
||||
except shared.CallSuper:
|
||||
return super().javaScriptConfirm(frame, js_msg)
|
||||
|
||||
def javaScriptConsoleMessage(self, msg, line, source):
|
||||
"""Override javaScriptConsoleMessage to use debug log."""
|
||||
|
@ -40,7 +40,7 @@ Feature: Prompts
|
||||
And I run :leave-mode
|
||||
Then the javascript message "confirm reply: false" should be logged
|
||||
|
||||
@pyqt>=5.3.1
|
||||
@pyqt>=5.3.1 @qtwebengine_skip
|
||||
Scenario: Javascript prompt
|
||||
When I open data/prompt/jsprompt.html
|
||||
And I run :click-element id button
|
||||
@ -49,7 +49,7 @@ Feature: Prompts
|
||||
And I run :prompt-accept
|
||||
Then the javascript message "Prompt reply: prompt test" should be logged
|
||||
|
||||
@pyqt>=5.3.1
|
||||
@pyqt>=5.3.1 @qtwebengine_skip
|
||||
Scenario: Javascript prompt with default
|
||||
When I open data/prompt/jsprompt.html
|
||||
And I run :click-element id button-default
|
||||
@ -57,7 +57,7 @@ Feature: Prompts
|
||||
And I run :prompt-accept
|
||||
Then the javascript message "Prompt reply: default" should be logged
|
||||
|
||||
@pyqt>=5.3.1
|
||||
@pyqt>=5.3.1 @qtwebengine_skip
|
||||
Scenario: Rejected javascript prompt
|
||||
When I open data/prompt/jsprompt.html
|
||||
And I run :click-element id button
|
||||
@ -68,6 +68,7 @@ Feature: Prompts
|
||||
|
||||
# Multiple prompts
|
||||
|
||||
@qtwebengine_skip: QtWebEngine refuses to load anything with a JS question
|
||||
Scenario: Blocking question interrupted by blocking one
|
||||
When I set content -> ignore-javascript-alert to false
|
||||
And I open data/prompt/jsalert.html
|
||||
@ -83,6 +84,7 @@ Feature: Prompts
|
||||
Then the javascript message "confirm reply: true" should be logged
|
||||
And the javascript message "Alert done" should be logged
|
||||
|
||||
@qtwebengine_skip: QtWebEngine refuses to load anything with a JS question
|
||||
Scenario: Blocking question interrupted by async one
|
||||
When I set content -> ignore-javascript-alert to false
|
||||
And I set content -> notifications to ask
|
||||
@ -99,6 +101,7 @@ Feature: Prompts
|
||||
Then the javascript message "Alert done" should be logged
|
||||
And the javascript message "notification permission granted" should be logged
|
||||
|
||||
@qtwebengine_todo: Permissions are not implemented yet
|
||||
Scenario: Async question interrupted by async one
|
||||
When I set content -> notifications to ask
|
||||
And I open data/prompt/notifications.html in a new tab
|
||||
@ -113,6 +116,7 @@ Feature: Prompts
|
||||
Then the javascript message "notification permission granted" should be logged
|
||||
And "Added quickmark test for *" should be logged
|
||||
|
||||
@qtwebengine_todo: Permissions are not implemented yet
|
||||
Scenario: Async question interrupted by blocking one
|
||||
When I set content -> notifications to ask
|
||||
And I set content -> ignore-javascript-alert to false
|
||||
@ -131,7 +135,7 @@ Feature: Prompts
|
||||
|
||||
# Shift-Insert with prompt (issue 1299)
|
||||
|
||||
@pyqt>=5.3.1
|
||||
@pyqt>=5.3.1 @qtwebengine_skip
|
||||
Scenario: Pasting via shift-insert in prompt mode
|
||||
When selection is supported
|
||||
And I put "insert test" into the primary selection
|
||||
@ -142,7 +146,7 @@ Feature: Prompts
|
||||
And I run :prompt-accept
|
||||
Then the javascript message "Prompt reply: insert test" should be logged
|
||||
|
||||
@pyqt>=5.3.1
|
||||
@pyqt>=5.3.1 @qtwebengine_skip
|
||||
Scenario: Pasting via shift-insert without it being supported
|
||||
When selection is not supported
|
||||
And I put "insert test" into the primary selection
|
||||
@ -153,7 +157,7 @@ Feature: Prompts
|
||||
And I run :prompt-accept
|
||||
Then the javascript message "Prompt reply: " should be logged
|
||||
|
||||
@pyqt>=5.3.1
|
||||
@pyqt>=5.3.1 @qtwebengine_skip
|
||||
Scenario: Using content -> ignore-javascript-prompt
|
||||
When I set content -> ignore-javascript-prompt to true
|
||||
And I open data/prompt/jsprompt.html
|
||||
@ -162,6 +166,7 @@ Feature: Prompts
|
||||
|
||||
# SSL
|
||||
|
||||
@qtwebengine_todo: SSL errors are not implemented yet
|
||||
Scenario: SSL error with ssl-strict = false
|
||||
When I run :debug-clear-ssl-errors
|
||||
And I set network -> ssl-strict to false
|
||||
@ -170,6 +175,7 @@ Feature: Prompts
|
||||
Then the error "SSL error: *" should be shown
|
||||
And the page should contain the plaintext "Hello World via SSL!"
|
||||
|
||||
@qtwebengine_todo: SSL errors are not implemented yet
|
||||
Scenario: SSL error with ssl-strict = true
|
||||
When I run :debug-clear-ssl-errors
|
||||
And I set network -> ssl-strict to true
|
||||
@ -177,6 +183,7 @@ Feature: Prompts
|
||||
Then "Error while loading *: SSL handshake failed" should be logged
|
||||
And the page should contain the plaintext "Unable to load page"
|
||||
|
||||
@qtwebengine_todo: SSL errors are not implemented yet
|
||||
Scenario: SSL error with ssl-strict = ask -> yes
|
||||
When I run :debug-clear-ssl-errors
|
||||
And I set network -> ssl-strict to ask
|
||||
@ -186,6 +193,7 @@ Feature: Prompts
|
||||
And I wait until the SSL page finished loading
|
||||
Then the page should contain the plaintext "Hello World via SSL!"
|
||||
|
||||
@qtwebengine_todo: SSL errors are not implemented yet
|
||||
Scenario: SSL error with ssl-strict = ask -> no
|
||||
When I run :debug-clear-ssl-errors
|
||||
And I set network -> ssl-strict to ask
|
||||
@ -197,20 +205,21 @@ Feature: Prompts
|
||||
|
||||
# Geolocation
|
||||
|
||||
@qtwebengine_todo: Permissions are not implemented yet
|
||||
Scenario: Always rejecting geolocation
|
||||
When I set content -> geolocation to false
|
||||
And I open data/prompt/geolocation.html in a new tab
|
||||
And I run :click-element id button
|
||||
Then the javascript message "geolocation permission denied" should be logged
|
||||
|
||||
@ci @not_osx
|
||||
@ci @not_osx @qtwebengine_todo: Permissions are not implemented yet
|
||||
Scenario: Always accepting geolocation
|
||||
When I set content -> geolocation to true
|
||||
And I open data/prompt/geolocation.html in a new tab
|
||||
And I run :click-element id button
|
||||
Then the javascript message "geolocation permission denied" should not be logged
|
||||
|
||||
@ci @not_osx
|
||||
@ci @not_osx @qtwebengine_todo: Permissions are not implemented yet
|
||||
Scenario: geolocation with ask -> true
|
||||
When I set content -> geolocation to ask
|
||||
And I open data/prompt/geolocation.html in a new tab
|
||||
@ -219,6 +228,7 @@ Feature: Prompts
|
||||
And I run :prompt-accept yes
|
||||
Then the javascript message "geolocation permission denied" should not be logged
|
||||
|
||||
@qtwebengine_todo: Permissions are not implemented yet
|
||||
Scenario: geolocation with ask -> false
|
||||
When I set content -> geolocation to ask
|
||||
And I open data/prompt/geolocation.html in a new tab
|
||||
@ -227,6 +237,7 @@ Feature: Prompts
|
||||
And I run :prompt-accept no
|
||||
Then the javascript message "geolocation permission denied" should be logged
|
||||
|
||||
@qtwebengine_todo: Permissions are not implemented yet
|
||||
Scenario: geolocation with ask -> abort
|
||||
When I set content -> geolocation to ask
|
||||
And I open data/prompt/geolocation.html in a new tab
|
||||
@ -237,18 +248,21 @@ Feature: Prompts
|
||||
|
||||
# Notifications
|
||||
|
||||
@qtwebengine_todo: Permissions are not implemented yet
|
||||
Scenario: Always rejecting notifications
|
||||
When I set content -> notifications to false
|
||||
And I open data/prompt/notifications.html in a new tab
|
||||
And I run :click-element id button
|
||||
Then the javascript message "notification permission denied" should be logged
|
||||
|
||||
@qtwebengine_todo: Permissions are not implemented yet
|
||||
Scenario: Always accepting notifications
|
||||
When I set content -> notifications to true
|
||||
And I open data/prompt/notifications.html in a new tab
|
||||
And I run :click-element id button
|
||||
Then the javascript message "notification permission granted" should be logged
|
||||
|
||||
@qtwebengine_todo: Permissions are not implemented yet
|
||||
Scenario: notifications with ask -> false
|
||||
When I set content -> notifications to ask
|
||||
And I open data/prompt/notifications.html in a new tab
|
||||
@ -257,6 +271,7 @@ Feature: Prompts
|
||||
And I run :prompt-accept no
|
||||
Then the javascript message "notification permission denied" should be logged
|
||||
|
||||
@qtwebengine_todo: Permissions are not implemented yet
|
||||
Scenario: notifications with ask -> true
|
||||
When I set content -> notifications to ask
|
||||
And I open data/prompt/notifications.html in a new tab
|
||||
@ -275,6 +290,7 @@ Feature: Prompts
|
||||
And I run :leave-mode
|
||||
Then the javascript message "notification permission aborted" should be logged
|
||||
|
||||
@qtwebengine_todo: Permissions are not implemented yet
|
||||
Scenario: answering notification after closing tab
|
||||
When I set content -> notifications to ask
|
||||
And I open data/prompt/notifications.html in a new tab
|
||||
@ -287,55 +303,55 @@ Feature: Prompts
|
||||
# Page authentication
|
||||
|
||||
Scenario: Successful webpage authentification
|
||||
When I open basic-auth/user/password without waiting
|
||||
When I open basic-auth/user1/password1 without waiting
|
||||
And I wait for a prompt
|
||||
And I press the keys "user"
|
||||
And I press the keys "user1"
|
||||
And I run :prompt-accept
|
||||
And I press the keys "password"
|
||||
And I press the keys "password1"
|
||||
And I run :prompt-accept
|
||||
And I wait until basic-auth/user/password is loaded
|
||||
And I wait until basic-auth/user1/password1 is loaded
|
||||
Then the json on the page should be:
|
||||
{
|
||||
"authenticated": true,
|
||||
"user": "user"
|
||||
"user": "user1"
|
||||
}
|
||||
|
||||
Scenario: Authentication with :prompt-accept value
|
||||
When I open about:blank in a new tab
|
||||
And I open basic-auth/user/password without waiting
|
||||
And I open basic-auth/user2/password2 without waiting
|
||||
And I wait for a prompt
|
||||
And I run :prompt-accept user:password
|
||||
And I wait until basic-auth/user/password is loaded
|
||||
And I run :prompt-accept user2:password2
|
||||
And I wait until basic-auth/user2/password2 is loaded
|
||||
Then the json on the page should be:
|
||||
{
|
||||
"authenticated": true,
|
||||
"user": "user"
|
||||
"user": "user2"
|
||||
}
|
||||
|
||||
Scenario: Authentication with invalid :prompt-accept value
|
||||
When I open about:blank in a new tab
|
||||
And I open basic-auth/user/password without waiting
|
||||
And I open basic-auth/user3/password3 without waiting
|
||||
And I wait for a prompt
|
||||
And I run :prompt-accept foo
|
||||
And I run :prompt-accept user:password
|
||||
And I run :prompt-accept user3:password3
|
||||
Then the error "Value needs to be in the format username:password, but foo was given" should be shown
|
||||
|
||||
Scenario: Tabbing between username and password
|
||||
When I open about:blank in a new tab
|
||||
And I open basic-auth/user/password without waiting
|
||||
And I open basic-auth/user4/password4 without waiting
|
||||
And I wait for a prompt
|
||||
And I press the keys "us"
|
||||
And I run :prompt-item-focus next
|
||||
And I press the keys "password"
|
||||
And I press the keys "password4"
|
||||
And I run :prompt-item-focus prev
|
||||
And I press the keys "er"
|
||||
And I press the keys "er4"
|
||||
And I run :prompt-accept
|
||||
And I run :prompt-accept
|
||||
And I wait until basic-auth/user/password is loaded
|
||||
And I wait until basic-auth/user4/password4 is loaded
|
||||
Then the json on the page should be:
|
||||
{
|
||||
"authenticated": true,
|
||||
"user": "user"
|
||||
"user": "user4"
|
||||
}
|
||||
|
||||
# :prompt-accept with value argument
|
||||
@ -350,7 +366,7 @@ Feature: Prompts
|
||||
Then the javascript message "Alert done" should be logged
|
||||
And the error "No value is permitted with alert prompts!" should be shown
|
||||
|
||||
@pyqt>=5.3.1
|
||||
@pyqt>=5.3.1 @qtwebengine_skip
|
||||
Scenario: Javascript prompt with value
|
||||
When I set content -> ignore-javascript-prompt to false
|
||||
And I open data/prompt/jsprompt.html
|
||||
@ -396,6 +412,7 @@ Feature: Prompts
|
||||
|
||||
# Other
|
||||
|
||||
@qtwebengine_skip
|
||||
Scenario: Shutting down with a question
|
||||
When I open data/prompt/jsconfirm.html
|
||||
And I run :click-element id button
|
||||
@ -429,32 +446,34 @@ Feature: Prompts
|
||||
Then "Added quickmark prompt-in-command-mode for *" should be logged
|
||||
|
||||
# https://github.com/The-Compiler/qutebrowser/issues/1093
|
||||
@qtwebengine_skip: QtWebEngine doesn't open the second page/prompt
|
||||
Scenario: Keyboard focus with multiple auth prompts
|
||||
When I open basic-auth/user1/password1 without waiting
|
||||
And I open basic-auth/user2/password2 in a new tab without waiting
|
||||
When I open basic-auth/user5/password5 without waiting
|
||||
And I open basic-auth/user6/password6 in a new tab without waiting
|
||||
And I wait for a prompt
|
||||
And I wait for a prompt
|
||||
# Second prompt (showed first)
|
||||
And I press the keys "user2"
|
||||
And I press the keys "user6"
|
||||
And I press the key "<Enter>"
|
||||
And I press the keys "password2"
|
||||
And I press the keys "password6"
|
||||
And I press the key "<Enter>"
|
||||
And I wait until basic-auth/user2/password2 is loaded
|
||||
And I wait until basic-auth/user6/password6 is loaded
|
||||
# First prompt
|
||||
And I press the keys "user1"
|
||||
And I press the keys "user5"
|
||||
And I press the key "<Enter>"
|
||||
And I press the keys "password1"
|
||||
And I press the keys "password5"
|
||||
And I press the key "<Enter>"
|
||||
And I wait until basic-auth/user1/password1 is loaded
|
||||
And I wait until basic-auth/user5/password5 is loaded
|
||||
# We're on the second page
|
||||
Then the json on the page should be:
|
||||
{
|
||||
"authenticated": true,
|
||||
"user": "user2"
|
||||
"user": "user6"
|
||||
}
|
||||
|
||||
# https://github.com/The-Compiler/qutebrowser/issues/1249#issuecomment-175205531
|
||||
# https://github.com/The-Compiler/qutebrowser/pull/2054#issuecomment-258285544
|
||||
@qtwebengine_todo: SSL errors are not implemented yet
|
||||
Scenario: Interrupting SSL prompt during a notification prompt
|
||||
When I set content -> notifications to ask
|
||||
And I set network -> ssl-strict to ask
|
||||
|
@ -22,9 +22,6 @@ import pytest_bdd as bdd
|
||||
bdd.scenarios('prompts.feature')
|
||||
|
||||
|
||||
pytestmark = pytest.mark.qtwebengine_todo("Prompts are not implemented")
|
||||
|
||||
|
||||
@bdd.when("I load an SSL page")
|
||||
def load_ssl_page(quteproc, ssl_server):
|
||||
# We don't wait here as we can get an SSL question.
|
||||
|
@ -81,7 +81,7 @@ class Request(testprocess.Line):
|
||||
http.client.FOUND]
|
||||
path_to_statuses['/absolute-redirect/{}'.format(i)] = [
|
||||
http.client.FOUND]
|
||||
for suffix in ['', '1', '2']:
|
||||
for suffix in ['', '1', '2', '3', '4', '5', '6']:
|
||||
key = '/basic-auth/user{}/password{}'.format(suffix, suffix)
|
||||
path_to_statuses[key] = [http.client.UNAUTHORIZED, http.client.OK]
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user