qutebrowser/qutebrowser/browser/shared.py

225 lines
7.7 KiB
Python
Raw Normal View History

2016-09-07 18:17:05 +02:00
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
# qutebrowser is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# qutebrowser is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
"""Various utilities shared between webpage/webview subclasses."""
import html
2016-11-10 06:50:00 +01:00
import jinja2
from qutebrowser.config import config
from qutebrowser.utils import usertypes, message, log, objreg
class CallSuper(Exception):
"""Raised when the caller should call the superclass instead."""
def custom_headers():
"""Get the combined custom headers."""
headers = {}
dnt = b'1' if config.get('network', 'do-not-track') else b'0'
headers[b'DNT'] = dnt
headers[b'X-Do-Not-Track'] = dnt
2016-09-07 18:57:00 +02:00
config_headers = config.get('network', 'custom-headers')
if config_headers is not None:
for header, value in config_headers.items():
headers[header.encode('ascii')] = value.encode('ascii')
accept_language = config.get('network', 'accept-language')
if accept_language is not None:
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."""
realm = authenticator.realm()
if realm:
msg = '<b>{}</b> says:<br/>{}'.format(
html.escape(url.toDisplayString()), html.escape(realm))
else:
msg = '<b>{}</b> needs authentication'.format(
html.escape(url.toDisplayString()))
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)
2016-11-10 06:50:00 +01:00
def ignore_certificate_errors(url, errors, abort_on):
"""Display a certificate error question.
Args:
url: The URL the errors happened in
errors: A list of QSslErrors or QWebEngineCertificateErrors
Return:
True if the error should be ignored, False otherwise.
"""
ssl_strict = config.get('network', 'ssl-strict')
log.webview.debug("Certificate errors {!r}, strict {}".format(
errors, ssl_strict))
for error in errors:
assert error.is_overridable(), repr(error)
if ssl_strict == 'ask':
err_template = jinja2.Template("""
Errors while loading <b>{{url.toDisplayString()}}</b>:<br/>
<ul>
{% for err in errors %}
<li>{{err}}</li>
{% endfor %}
</ul>
""".strip())
msg = err_template.render(url=url, errors=errors)
return message.ask(title="Certificate errors - continue?", text=msg,
mode=usertypes.PromptMode.yesno, default=False,
abort_on=abort_on)
elif ssl_strict is False:
log.webview.debug("ssl-strict is False, only warning about errors")
for err in errors:
# FIXME we might want to use warn here (non-fatal error)
# https://github.com/The-Compiler/qutebrowser/issues/114
message.error('Certificate error: {}'.format(err))
return True
elif ssl_strict is True:
return False
else:
raise ValueError("Invalid ssl_strict value {!r}".format(ssl_strict))
raise AssertionError("Not reached")
def feature_permission(url, option, msg, yes_action, no_action, abort_on):
"""Handle a feature permission request.
Args:
url: The URL the request was done for.
option: A (section, option) tuple for the option to check.
msg: A string like "show notifications"
yes_action: A callable to call if the request was approved
no_action: A callable to call if the request was denied
abort_on: A list of signals which interrupt the question.
Return:
The Question object if a question was asked, None otherwise.
"""
config_val = config.get(*option)
if config_val == 'ask':
if url.isValid():
text = "Allow the website at <b>{}</b> to {}?".format(
html.escape(url.toDisplayString()), msg)
else:
text = "Allow the website to {}?".format(msg)
return message.confirm_async(
yes_action=yes_action, no_action=no_action,
cancel_action=no_action, abort_on=abort_on,
title='Permission request', text=text)
elif config_val:
yes_action()
return None
else:
no_action()
return None
def get_tab(win_id, target):
"""Get a tab widget for the given usertypes.ClickTarget.
Args:
win_id: The window ID to open new tabs in
target: An usertypes.ClickTarget
"""
if target == usertypes.ClickTarget.tab:
win_id = win_id
bg_tab = False
elif target == usertypes.ClickTarget.tab_bg:
win_id = win_id
bg_tab = True
elif target == usertypes.ClickTarget.window:
from qutebrowser.mainwindow import mainwindow
window = mainwindow.MainWindow()
window.show()
win_id = window.win_id
bg_tab = False
else:
raise ValueError("Invalid ClickTarget {}".format(target))
tabbed_browser = objreg.get('tabbed-browser', scope='window',
window=win_id)
return tabbed_browser.tabopen(url=None, background=bg_tab)