1# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et: 2 3# Copyright 2016-2021 Florian Bruhin (The Compiler) <mail@qutebrowser.org> 4# 5# This file is part of qutebrowser. 6# 7# qutebrowser is free software: you can redistribute it and/or modify 8# it under the terms of the GNU General Public License as published by 9# the Free Software Foundation, either version 3 of the License, or 10# (at your option) any later version. 11# 12# qutebrowser is distributed in the hope that it will be useful, 13# but WITHOUT ANY WARRANTY; without even the implied warranty of 14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15# GNU General Public License for more details. 16# 17# You should have received a copy of the GNU General Public License 18# along with qutebrowser. If not, see <https://www.gnu.org/licenses/>. 19 20"""Bridge from QWebSettings to our own settings. 21 22Module attributes: 23 ATTRIBUTES: A mapping from internal setting names to QWebSetting enum 24 constants. 25""" 26 27from typing import cast 28import os.path 29 30from PyQt5.QtCore import QUrl 31from PyQt5.QtGui import QFont 32from PyQt5.QtWebKit import QWebSettings 33from PyQt5.QtWebKitWidgets import QWebPage 34 35from qutebrowser.config import config, websettings 36from qutebrowser.config.websettings import AttributeInfo as Attr 37from qutebrowser.utils import standarddir, urlutils 38from qutebrowser.browser import shared 39 40 41# The global WebKitSettings object 42global_settings = cast('WebKitSettings', None) 43 44parsed_user_agent = None 45 46 47class WebKitSettings(websettings.AbstractSettings): 48 49 """A wrapper for the config for QWebSettings.""" 50 51 _ATTRIBUTES = { 52 'content.images': 53 Attr(QWebSettings.AutoLoadImages), 54 'content.javascript.enabled': 55 Attr(QWebSettings.JavascriptEnabled), 56 'content.javascript.can_open_tabs_automatically': 57 Attr(QWebSettings.JavascriptCanOpenWindows), 58 'content.javascript.can_close_tabs': 59 Attr(QWebSettings.JavascriptCanCloseWindows), 60 'content.javascript.can_access_clipboard': 61 Attr(QWebSettings.JavascriptCanAccessClipboard), 62 'content.plugins': 63 Attr(QWebSettings.PluginsEnabled), 64 'content.webgl': 65 Attr(QWebSettings.WebGLEnabled), 66 'content.hyperlink_auditing': 67 Attr(QWebSettings.HyperlinkAuditingEnabled), 68 'content.local_content_can_access_remote_urls': 69 Attr(QWebSettings.LocalContentCanAccessRemoteUrls), 70 'content.local_content_can_access_file_urls': 71 Attr(QWebSettings.LocalContentCanAccessFileUrls), 72 'content.dns_prefetch': 73 Attr(QWebSettings.DnsPrefetchEnabled), 74 'content.frame_flattening': 75 Attr(QWebSettings.FrameFlatteningEnabled), 76 'content.cache.appcache': 77 Attr(QWebSettings.OfflineWebApplicationCacheEnabled), 78 'content.local_storage': 79 Attr(QWebSettings.LocalStorageEnabled, 80 QWebSettings.OfflineStorageDatabaseEnabled), 81 'content.print_element_backgrounds': 82 Attr(QWebSettings.PrintElementBackgrounds), 83 'content.xss_auditing': 84 Attr(QWebSettings.XSSAuditingEnabled), 85 'content.site_specific_quirks.enabled': 86 Attr(QWebSettings.SiteSpecificQuirksEnabled), 87 88 'input.spatial_navigation': 89 Attr(QWebSettings.SpatialNavigationEnabled), 90 'input.links_included_in_focus_chain': 91 Attr(QWebSettings.LinksIncludedInFocusChain), 92 93 'zoom.text_only': 94 Attr(QWebSettings.ZoomTextOnly), 95 'scrolling.smooth': 96 Attr(QWebSettings.ScrollAnimatorEnabled), 97 } 98 99 _FONT_SIZES = { 100 'fonts.web.size.minimum': 101 QWebSettings.MinimumFontSize, 102 'fonts.web.size.minimum_logical': 103 QWebSettings.MinimumLogicalFontSize, 104 'fonts.web.size.default': 105 QWebSettings.DefaultFontSize, 106 'fonts.web.size.default_fixed': 107 QWebSettings.DefaultFixedFontSize, 108 } 109 110 _FONT_FAMILIES = { 111 'fonts.web.family.standard': QWebSettings.StandardFont, 112 'fonts.web.family.fixed': QWebSettings.FixedFont, 113 'fonts.web.family.serif': QWebSettings.SerifFont, 114 'fonts.web.family.sans_serif': QWebSettings.SansSerifFont, 115 'fonts.web.family.cursive': QWebSettings.CursiveFont, 116 'fonts.web.family.fantasy': QWebSettings.FantasyFont, 117 } 118 119 # Mapping from QWebSettings::QWebSettings() in 120 # qtwebkit/Source/WebKit/qt/Api/qwebsettings.cpp 121 _FONT_TO_QFONT = { 122 QWebSettings.StandardFont: QFont.Serif, 123 QWebSettings.FixedFont: QFont.Monospace, 124 QWebSettings.SerifFont: QFont.Serif, 125 QWebSettings.SansSerifFont: QFont.SansSerif, 126 QWebSettings.CursiveFont: QFont.Cursive, 127 QWebSettings.FantasyFont: QFont.Fantasy, 128 } 129 130 131def _set_user_stylesheet(settings): 132 """Set the generated user-stylesheet.""" 133 stylesheet = shared.get_user_stylesheet().encode('utf-8') 134 url = urlutils.data_url('text/css;charset=utf-8', stylesheet) 135 settings.setUserStyleSheetUrl(url) 136 137 138def _set_cookie_accept_policy(settings): 139 """Update the content.cookies.accept setting.""" 140 mapping = { 141 'all': QWebSettings.AlwaysAllowThirdPartyCookies, 142 'no-3rdparty': QWebSettings.AlwaysBlockThirdPartyCookies, 143 'never': QWebSettings.AlwaysBlockThirdPartyCookies, 144 'no-unknown-3rdparty': QWebSettings.AllowThirdPartyWithExistingCookies, 145 } 146 value = config.val.content.cookies.accept 147 settings.setThirdPartyCookiePolicy(mapping[value]) 148 149 150def _set_cache_maximum_pages(settings): 151 """Update the content.cache.maximum_pages setting.""" 152 value = config.val.content.cache.maximum_pages 153 settings.setMaximumPagesInCache(value) 154 155 156def _update_settings(option): 157 """Update global settings when qwebsettings changed.""" 158 global_settings.update_setting(option) 159 160 settings = QWebSettings.globalSettings() 161 if option in ['scrollbar.hide', 'content.user_stylesheets']: 162 _set_user_stylesheet(settings) 163 elif option == 'content.cookies.accept': 164 _set_cookie_accept_policy(settings) 165 elif option == 'content.cache.maximum_pages': 166 _set_cache_maximum_pages(settings) 167 168 169def _init_user_agent(): 170 global parsed_user_agent 171 ua = QWebPage().userAgentForUrl(QUrl()) 172 parsed_user_agent = websettings.UserAgent.parse(ua) 173 174 175def init(): 176 """Initialize the global QWebSettings.""" 177 cache_path = standarddir.cache() 178 data_path = standarddir.data() 179 180 QWebSettings.setIconDatabasePath(standarddir.cache()) 181 QWebSettings.setOfflineWebApplicationCachePath( 182 os.path.join(cache_path, 'application-cache')) 183 QWebSettings.globalSettings().setLocalStoragePath( 184 os.path.join(data_path, 'local-storage')) 185 QWebSettings.setOfflineStoragePath( 186 os.path.join(data_path, 'offline-storage')) 187 188 settings = QWebSettings.globalSettings() 189 _set_user_stylesheet(settings) 190 _set_cookie_accept_policy(settings) 191 _set_cache_maximum_pages(settings) 192 193 _init_user_agent() 194 195 config.instance.changed.connect(_update_settings) 196 197 global global_settings 198 global_settings = WebKitSettings(QWebSettings.globalSettings()) 199 global_settings.init_settings() 200 201 202def shutdown(): 203 """Disable storage so removing tmpdir will work.""" 204 QWebSettings.setIconDatabasePath('') 205 QWebSettings.setOfflineWebApplicationCachePath('') 206 QWebSettings.globalSettings().setLocalStoragePath('') 207