From 8f239b4a95bf7ba671af0881b9908d6b8bfc90ed Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 5 May 2014 22:07:41 +0200 Subject: [PATCH] Add proxy settings --- qutebrowser/app.py | 2 ++ qutebrowser/config/_conftypes.py | 43 +++++++++++++++++++++++++++++ qutebrowser/config/configdata.py | 4 +++ qutebrowser/network/proxy.py | 47 ++++++++++++++++++++++++++++++++ 4 files changed, 96 insertions(+) create mode 100644 qutebrowser/network/proxy.py diff --git a/qutebrowser/app.py b/qutebrowser/app.py index 5bc2b43db..8f955a8dc 100644 --- a/qutebrowser/app.py +++ b/qutebrowser/app.py @@ -50,6 +50,7 @@ import qutebrowser.config.style as style import qutebrowser.config.config as config import qutebrowser.network.qutescheme as qutescheme import qutebrowser.config.websettings as websettings +import qutebrowser.network.proxy as proxy from qutebrowser.network.networkmanager import NetworkManager from qutebrowser.config.config import ConfigManager from qutebrowser.keyinput.modeman import ModeManager @@ -123,6 +124,7 @@ class QuteBrowser(QApplication): self._init_config() self._init_modes() websettings.init(self._dirs.user_cache_dir) + proxy.init() self.cookiejar = CookieJar(self._dirs.user_data_dir) self.networkmanager = NetworkManager(self.cookiejar) self.commandmanager = CommandManager() diff --git a/qutebrowser/config/_conftypes.py b/qutebrowser/config/_conftypes.py index 7b6be09a1..bf2c82412 100644 --- a/qutebrowser/config/_conftypes.py +++ b/qutebrowser/config/_conftypes.py @@ -24,6 +24,7 @@ from sre_constants import error as RegexError from PyQt5.QtCore import QUrl from PyQt5.QtGui import QColor +from PyQt5.QtNetwork import QNetworkProxy import qutebrowser.commands.utils as cmdutils @@ -538,6 +539,48 @@ class WebKitBytesList(List): "set!".format(self.length)) +class Proxy(BaseType): + + """A proxy URL or special value.""" + + valid_values = ValidValues(('system', "Use the system wide proxy."), + ('none', "Don't use any proxy")) + + PROXY_TYPES = { + 'http': QNetworkProxy.HttpProxy, + 'socks': QNetworkProxy.Socks5Proxy, + 'socks5': QNetworkProxy.Socks5Proxy, + } + + def validate(self, value): + if value in self.valid_values: + return + url = QUrl(value) + if (url.isValid() and not url.isEmpty() and + url.scheme() in self.PROXY_TYPES): + return + raise ValidationError(value, "must be a proxy URL (http://... or " + "socks://...) or system/none!") + + def complete(self): + out = [] + for val in self.valid_values: + out.append((val, self.valid_values.descriptions[val])) + out.append(('http://', 'HTTP proxy URL')) + out.append(('socks://', 'SOCKS proxy URL')) + return out + + def transform(self, value): + if value == 'system': + return None + elif value == 'none': + return QNetworkProxy(QNetworkProxy.NoProxy) + url = QUrl(value) + typ = self.PROXY_TYPES[url.scheme()] + return QNetworkProxy(typ, url.host(), url.port(), url.userName(), + url.password()) + + class Command(BaseType): """Base class for a command value with arguments.""" diff --git a/qutebrowser/config/configdata.py b/qutebrowser/config/configdata.py index 328d0ba8c..f78308a85 100644 --- a/qutebrowser/config/configdata.py +++ b/qutebrowser/config/configdata.py @@ -217,6 +217,10 @@ DATA = OrderedDict([ ('store-cookies', SettingValue(types.Bool(), 'false'), "Whether to store cookies."), + + ('proxy', + SettingValue(types.Proxy(), 'system'), + "The proxy to use."), )), ('completion', sect.KeyValue( diff --git a/qutebrowser/network/proxy.py b/qutebrowser/network/proxy.py new file mode 100644 index 000000000..a3d909016 --- /dev/null +++ b/qutebrowser/network/proxy.py @@ -0,0 +1,47 @@ +# Copyright 2014 Florian Bruhin (The Compiler) +# +# 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 . + +"""Handling of proxies.""" + +import qutebrowser.config.config as config + +from PyQt5.QtNetwork import QNetworkProxyFactory + + +def init(): + """Set the application wide proxy factory.""" + QNetworkProxyFactory.setApplicationProxyFactory(ProxyFactory()) + + +class ProxyFactory(QNetworkProxyFactory): + + """Factory for proxies to be used by qutebrowser.""" + + def queryProxy(self, query): + """Get the QNetworkProxies for a query. + + Args: + query: The QNetworkProxyQuery to get a proxy for. + + Return: + A list of QNetworkProxy objects in order of preference. + """ + proxy = config.get('network', 'proxy') + if proxy is None: + return QNetworkProxyFactory.systemProxyForQuery(query) + else: + return [proxy]