Tue, 29 Mar 2016 10:32:22 +0200
Continued porting the web browser.
- added the user agents manager
--- a/Preferences/__init__.py Mon Mar 28 17:04:18 2016 +0200 +++ b/Preferences/__init__.py Tue Mar 29 10:32:22 2016 +0200 @@ -1038,6 +1038,7 @@ "KeepCookiesUntil": 0, # CookieJar.KeepUntilExpire "FilterTrackingCookies": True, "SaveUrlColor": QColor(184, 248, 169), + "UserAgent": "", # Grease Monkey "GreaseMonkeyDisabledScripts": [], # Downloads
--- a/WebBrowser/Network/NetworkUrlInterceptor.py Mon Mar 28 17:04:18 2016 +0200 +++ b/WebBrowser/Network/NetworkUrlInterceptor.py Tue Mar 29 10:32:22 2016 +0200 @@ -12,6 +12,8 @@ from PyQt5.QtWebEngineCore import QWebEngineUrlRequestInterceptor +from ..WebBrowserPage import WebBrowserPage + import Preferences @@ -49,6 +51,10 @@ Preferences.getWebBrowser("SendRefererWhitelist"): info.setHttpHeader(b"Referer", b"") + # User Agents header + userAgent = WebBrowserPage.userAgentForUrl(info.requestUrl()) + info.setHttpHeader(b"User-Agent", userAgent.encode()) + for interceptor in self.__interceptors: interceptor.interceptRequest(info)
--- a/WebBrowser/Sync/DirectorySyncHandler.py Mon Mar 28 17:04:18 2016 +0200 +++ b/WebBrowser/Sync/DirectorySyncHandler.py Tue Mar 29 10:32:22 2016 +0200 @@ -200,13 +200,12 @@ "passwords", WebBrowserWindow.passwordManager().getFileName()) - # TODO: UserAgents -## QCoreApplication.processEvents() -## # User Agent Settings -## if Preferences.getWebBrowser("SyncUserAgents"): -## self.__initialSyncFile( -## "useragents", -## WebBrowserWindow.userAgentsManager().getFileName()) + QCoreApplication.processEvents() + # User Agent Settings + if Preferences.getWebBrowser("SyncUserAgents"): + self.__initialSyncFile( + "useragents", + WebBrowserWindow.userAgentsManager().getFileName()) QCoreApplication.processEvents() # Speed Dial Settings @@ -254,14 +253,13 @@ "passwords", WebBrowserWindow.passwordManager().getFileName()) - # TODO: UserAgents def syncUserAgents(self): """ Public method to synchronize the user agents. """ -## self.__syncFile( -## "useragents", -## WebBrowserWindow.userAgentsManager().getFileName()) + self.__syncFile( + "useragents", + WebBrowserWindow.userAgentsManager().getFileName()) def syncSpeedDial(self): """
--- a/WebBrowser/Sync/FtpSyncHandler.py Mon Mar 28 17:04:18 2016 +0200 +++ b/WebBrowser/Sync/FtpSyncHandler.py Tue Mar 29 10:32:22 2016 +0200 @@ -297,12 +297,11 @@ "passwords", WebBrowserWindow.passwordManager().getFileName()) - # TODO: UserAgents # User Agent Settings -## if Preferences.getWebBrowser("SyncUserAgents"): -## self.__initialSyncFile( -## "useragents", -## WebBrowserWindow.userAgentsManager().getFileName()) + if Preferences.getWebBrowser("SyncUserAgents"): + self.__initialSyncFile( + "useragents", + WebBrowserWindow.userAgentsManager().getFileName()) # Speed Dial Settings if Preferences.getWebBrowser("SyncSpeedDial"): @@ -366,14 +365,13 @@ "passwords", WebBrowserWindow.passwordManager().getFileName()) - # TODO: UserAgents def syncUserAgents(self): """ Public method to synchronize the user agents. """ -## self.__syncFile( -## "useragents", -## WebBrowserWindow.userAgentsManager().getFileName()) + self.__syncFile( + "useragents", + WebBrowserWindow.userAgentsManager().getFileName()) def syncSpeedDial(self): """
--- a/WebBrowser/Sync/SyncManager.py Mon Mar 28 17:04:18 2016 +0200 +++ b/WebBrowser/Sync/SyncManager.py Tue Mar 29 10:32:22 2016 +0200 @@ -125,18 +125,17 @@ except TypeError: pass - # TODO: UserAgents # connect sync manager to user agent manager -## if Preferences.getWebBrowser("SyncUserAgents"): -## WebBrowserWindow.userAgentsManager()\ -## .userAgentSettingsSaved.connect(self.__syncUserAgents) -## else: -## try: -## WebBrowserWindow.userAgentsManager()\ -## .userAgentSettingsSaved.disconnect( -## self.__syncUserAgents) -## except TypeError: -## pass + if Preferences.getWebBrowser("SyncUserAgents"): + WebBrowserWindow.userAgentsManager()\ + .userAgentSettingsSaved.connect(self.__syncUserAgents) + else: + try: + WebBrowserWindow.userAgentsManager()\ + .userAgentSettingsSaved.disconnect( + self.__syncUserAgents) + except TypeError: + pass # connect sync manager to speed dial if Preferences.getWebBrowser("SyncSpeedDial"): @@ -166,12 +165,11 @@ .passwordsSaved.disconnect(self.__syncPasswords) except TypeError: pass - # TODO: UserAgents -## try: -## WebBrowserWindow.userAgentsManager()\ -## .userAgentSettingsSaved.disconnect(self.__syncUserAgents) -## except TypeError: -## pass + try: + WebBrowserWindow.userAgentsManager()\ + .userAgentSettingsSaved.disconnect(self.__syncUserAgents) + except TypeError: + pass try: WebBrowserWindow.speedDial()\ .speedDialSaved.disconnect(self.__syncSpeedDial) @@ -248,9 +246,8 @@ WebBrowserWindow.historyManager().reload() elif type_ == "passwords": WebBrowserWindow.passwordManager().reload() - # TODO: UserAgents -## elif type_ == "useragents": -## WebBrowserWindow.userAgentsManager().reload() + elif type_ == "useragents": + WebBrowserWindow.userAgentsManager().reload() elif type_ == "speeddial": WebBrowserWindow.speedDial().reload() self.syncFinished.emit(type_, status, download)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebBrowser/UserAgent/UserAgentDefaults.qrc Tue Mar 29 10:32:22 2016 +0200 @@ -0,0 +1,6 @@ +<!DOCTYPE RCC> +<RCC version="1.0"> +<qresource> + <file>UserAgentDefaults.xml</file> +</qresource> +</RCC>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebBrowser/UserAgent/UserAgentDefaults.xml Tue Mar 29 10:32:22 2016 +0200 @@ -0,0 +1,53 @@ +<useragentswitcher> + <useragentmenu title="Firefox"> + <useragent description="Firefox 9.0.1 (Windows)" useragent="Mozilla/5.0 (Windows; U; Windows NT 6.2; rv:9.0.1) Gecko/20100101 Firefox/9.0.1"/> + <useragent description="Firefox 4.0.1 (Windows)" useragent="Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:2.0.1) Gecko/20100101 Firefox/4.0.1"/> + <useragent description="Firefox 3.5.3 (Windows)" useragent="Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3"/> + </useragentmenu> + + <useragentmenu title="Chrome"> + <useragent description="Chrome 18.0 (Windows)" useragent="Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.12 (KHTML, like Gecko) Chrome/18.6.872.0 Safari/535.12"/> + <useragent description="Chrome 17.0 (Windows)" useragent="Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.12 Safari/535.11"/> + <useragent description="Chrome 12.0 (Windows)" useragent="Mozilla/5.0 (Windows NT 6.1) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.0 Safari/534.30"/> + <useragent description="Chrome 11.0 (Windows)" useragent="Mozilla/5.0 (Windows NT 6.1) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.50 Safari/534.24"/> + </useragentmenu> + + <useragentmenu title="Internet Explorer"> + <useragent description="Internet Explorer 10.0" useragent="Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1)"/> + <useragent description="Internet Explorer 9.0" useragent="Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 6.1)"/> + <useragent description="Internet Explorer 8.0" useragent="Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1)"/> + <useragent description="Internet Explorer 7.0" useragent="Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)"/> + <useragent description="Internet Explorer 6.0" useragent="Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)"/> + </useragentmenu> + + <useragentmenu title="Opera"> + <useragent description="Opera 12.0 (Linux)" useragent="Opera/9.80 (X11; Linux x86_64; U) Presto/2.9.181 Version/12.00"/> + <useragent description="Opera 12.0 (Mac)" useragent="Opera/9.80 (Macintosh; Intel Mac OS X 10.6.7; U) Presto/2.9.181 Version/12.00"/> + <useragent description="Opera 12.0 (Windows)" useragent="Opera/9.80 (Windows NT 6.1; U) Presto/2.9.181 Version/12.00"/> + <useragent description="Opera 11.1 (Linux)" useragent="Opera/9.80 (X11; Linux x86_64; U; en) Presto/2.8.131 Version/11.10"/> + <useragent description="Opera 11.1 (Mac)" useragent="Opera/9.80 (Macintosh; Intel Mac OS X 10.6.7; U; en) Presto/2.8.131 Version/11.10"/> + <useragent description="Opera 11.1 (Windows)" useragent="Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.10"/> + <useragent description="Opera 10.0 (Linux)" useragent="Opera/9.80 (X11; Linux x86_64; U; de) Presto/2.2.15 Version/10.00"/> + <useragent description="Opera 10.0 (Mac)" useragent="Opera/9.80 (Macintosh; Intel Mac OS X; U; en) Presto/2.2.15 Version/10.00"/> + <useragent description="Opera 10.0 (Windows)" useragent="Opera/9.80 (Windows NT 6.0; U; en) Presto/2.2.15 Version/10.00"/> + </useragentmenu> + + <useragentmenu title="Safari"> + <useragent description="Safari 5.0.5 (Mac)" useragent="Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_7_2; en-us) AppleWebKit/535.12 (KHTML, like Gecko) Version/5.0.5 Safari/535.12"/> + <useragent description="Safari 5.0.4 (Mac)" useragent="Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7; en-us) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27"/> + <useragent description="Safari 4.0.4 (Mac)" useragent="Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_1; en-us) AppleWebKit/531.21.8 (KHTML, like Gecko) Version/4.0.4 Safari/531.21.10"/> + <separator/> + <useragent description="Mobile Safari 4.3.2 (iPad)" useragent="Mozilla/5.0 (iPad; U; CPU OS 4_3_2 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8H7 Safari/6533.18.5"/> + <useragent description="Mobile Safari 4.3.2 (iPhone)" useragent="Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_2 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8H7 Safari/6533.18.5"/> + <useragent description="Mobile Safari 4.3.2 (iPod touch)" useragent="Mozilla/5.0 (iPod; U; CPU iPhone OS 4_3_2 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8H7 Safari/6533.18.5"/> + <useragent description="Mobile Safari 3.1.2 (iPhone)" useragent="Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_1_2 like Mac OS X; en-us) AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0 Mobile/7D11 Safari/528.16"/> + <useragent description="Mobile Safari 3.1.2 (iPod touch)" useragent="Mozilla/5.0 (iPod; U; CPU iPhone OS 3_1_2 like Mac OS X; en-us) AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0 Mobile/7D11 Safari/528.16"/> + </useragentmenu> + + <useragentmenu title="v_a_r_i_o_u_s"> + <useragent description="Googlebot 2.1" useragent="Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"/> + <useragent description="Msnbot 1.1" useragent="msnbot/1.1 (+http://search.msn.com/msnbot.htm)" appcodename="" appname="" appversion="" platform="" vendor="" vendorsub=""/> + <useragent description="Yahoo Slurp" useragent="Mozilla/5.0 (compatible; Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp)" appcodename="" appname="" appversion="" platform="" vendor="" vendorsub=""/> + </useragentmenu> + +</useragentswitcher>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebBrowser/UserAgent/UserAgentDefaults_rc.py Tue Mar 29 10:32:22 2016 +0200 @@ -0,0 +1,98 @@ +# -*- coding: utf-8 -*- + +# Resource object code +# +# Created: So. Juni 29 18:58:08 2014 +# by: The Resource Compiler for PyQt (Qt v5.3.1) +# +# WARNING! All changes made in this file will be lost! + +from PyQt5 import QtCore + +qt_resource_data = b"\ +\x00\x00\x03\xd6\ +\x00\ +\x00\x15\xe1\x78\x9c\xd5\x58\xdb\x6e\xdb\x38\x10\x7d\xef\x57\xcc\ +\xfa\x29\xc6\xee\x52\xa2\xee\xae\xd3\x02\x45\xef\x68\xbd\x0d\xe0\ +\x66\xdb\x3e\x09\xb2\xcd\x44\x42\x65\x51\xa0\xe4\x38\xdd\xaf\xdf\ +\x21\xe5\x8b\x6c\xc7\x0a\x65\xab\x05\x1a\xe4\x41\x24\x67\x74\xce\ +\x99\x19\x72\x28\x5f\x2e\x0a\x26\xa2\x5b\x96\x95\xc5\x32\x29\xa7\ +\x31\x13\xcf\x9f\x00\xfe\x5d\x6e\xe6\xe7\x2c\x5b\x40\x99\x94\x29\ +\x7b\xd6\x7b\x93\x08\x76\xc3\xef\x7b\x95\xcd\xae\x1d\xcc\x58\x31\ +\x15\x49\x5e\x26\x3c\xdb\x58\xc2\x80\x98\x84\xc2\xc5\x97\x24\x9b\ +\xf1\x65\xd1\xef\xc1\xc6\xfe\x59\x6f\xc4\xff\x4b\xd2\x34\x32\x5c\ +\x62\x6e\x2c\x86\x70\x3d\x84\xd5\x33\xfc\xf3\x19\x3c\x62\x0d\x41\ +\xdc\x3d\x55\xef\xe9\xc3\x5b\x36\xfd\xce\x0d\xcb\xa4\x26\xfe\x53\ +\x58\xa1\x18\x6a\xb5\x67\xe8\xd3\x72\xce\xa6\x45\x87\xc0\xb2\xbf\ +\xaf\xc7\x8a\x9d\xd5\xc8\xce\x69\xcb\xce\x26\x2e\xb1\xbb\x63\x47\ +\xc9\x80\x50\x62\x6f\xf9\x99\x03\x33\xb0\x9c\x0d\x3f\x05\xb7\xe6\ +\x77\x69\xec\x64\xfe\xf9\x93\x86\x72\x78\x19\x0b\x3e\x67\x1a\xd5\ +\x50\x19\x02\x0d\x6a\xa4\x1f\x97\xb5\x92\xd2\x87\x17\x79\x9e\xb2\ +\x2f\x6c\xf2\x21\x29\x0d\xd7\x76\x09\xb5\xe0\xe2\xc3\xbb\xcf\xa3\ +\x8f\x7f\x41\x9a\x7c\x67\x95\xae\x3e\x54\x28\x06\xa2\x78\x24\xf0\ +\x31\x27\x30\x8e\x6e\x22\x91\xac\x7c\x74\x32\xb0\x26\xea\x77\x44\ +\x94\x36\x12\x45\x14\x32\xf0\x6c\xa9\xa7\xce\x54\xab\x56\xd6\x4c\ +\xad\x2e\x98\x3a\xc4\x36\x1b\x99\xca\x02\xf7\x9d\x9d\x90\x4a\x9f\ +\x36\x44\x69\x37\x44\xb1\x6e\x9b\x88\x22\x0a\xf1\x06\x1e\x71\x77\ +\x98\x5a\xce\x29\xe5\xfd\x3e\x2b\x99\xc8\x58\x09\xaf\xef\xf3\x94\ +\x0b\x26\x34\x2a\xfd\xc0\x07\xa8\x49\xcc\xe3\x72\xa7\x7c\x9e\x47\ +\x65\x32\x49\xd9\x10\x46\xe3\xf7\xaf\x95\xf9\xfe\x66\xee\xeb\xc4\ +\xf9\x10\x79\x70\x04\xd8\x79\x10\x78\xd0\x19\x6e\xd0\x0a\x37\xe8\ +\x0c\xd7\x6f\x85\xeb\x1f\xe0\x9a\x27\xe2\x7a\xad\x70\xbd\x3d\x5c\ +\xb7\xa6\xb7\x4d\x75\x7e\xca\x71\x52\xa3\x22\x95\xdd\xea\x9c\xf8\ +\x98\x64\x8b\xfb\xdd\xcd\xa7\x96\xb1\x81\x06\xb8\xfc\x95\x62\xdf\ +\x50\x36\x70\x1f\x78\xa1\xe7\x60\x63\xe9\xc3\x95\x60\x45\x89\x6d\ +\x43\x76\x91\x80\xc2\xbf\x4c\x14\xf8\x62\x75\x26\x68\x1d\x00\x75\ +\x02\xa3\x68\x7a\x1c\x1e\x17\x93\xac\xe4\x45\x3c\x04\x19\xe4\x14\ +\x70\x02\x3e\x8d\xe1\xab\xdc\x14\x1e\xf1\x3b\x67\xf3\xe0\x69\x54\ +\x67\xb4\xdf\x53\xbb\xc3\xa7\xf2\xfa\x71\x42\x3a\x64\x5f\xaf\x91\ +\x08\x08\xb5\x6b\x24\xf0\xad\xad\x49\x9c\x9b\x92\xee\x19\xb5\x4f\ +\x4b\xa7\x1c\xcc\x13\x77\xca\x10\xdf\x56\x23\x61\x11\xea\x6e\x39\ +\x98\xed\xca\xc3\x3c\x7d\xb3\x1c\x86\xe3\x7c\x26\xed\x32\x62\xb6\ +\xa1\xd0\xe6\xc8\xab\x3a\xba\xc6\x99\x57\x19\xe2\xd1\x6a\x12\xf7\ +\x81\x38\xee\x74\xe0\x5a\x20\xaf\x1f\xa8\xf2\xd0\x0f\x2d\x75\x99\ +\x5e\x14\xda\x17\xd1\xb5\xd0\x0a\xbf\xf5\x25\xb4\xc6\xde\x39\x97\ +\xbd\x17\xfa\x47\xd8\xdb\xc4\x32\x89\xe5\x3e\x2a\xc0\xd9\x0a\xa8\ +\x5c\xfc\x16\x1a\x9c\x6e\x34\xd0\x23\x1a\x28\xb1\x28\x09\x1a\x25\ +\x38\xbb\x12\x94\xc7\xde\x71\x50\xb0\x3c\x12\x51\xc9\x85\x86\xae\ +\x11\x9f\x24\x29\x83\x8d\x3c\x0c\x09\x5c\x24\x57\xd1\xac\x41\x9f\ +\x5c\x56\xd2\x5e\x5e\x5d\x4b\x51\x4e\x68\x87\x56\x45\x76\xbb\x69\ +\x8f\xe4\x08\xbf\x11\x06\x8f\xa6\xc8\x82\x8a\x96\x11\xbc\xf3\xd7\ +\x52\x3d\xe5\x1d\x10\x57\x27\x5b\x47\x54\xc5\x3c\x63\x8d\xba\xa4\ +\xc1\x46\x59\x35\xfc\xad\x04\xf2\x19\x94\x7c\x31\x8d\x1b\x45\xf2\ +\xd9\x6f\x28\x11\xfd\xce\xcb\xa1\x1d\x52\x3d\x81\x16\x76\xdb\x47\ +\xb7\xe0\x5a\x9c\xff\x0a\x3f\x89\xd7\x9b\x51\x7a\x7a\x67\x48\x3b\ +\x3d\x7b\xbf\x5a\x5c\x9b\x26\x77\x17\x46\xa1\x08\x93\x90\x87\x8b\ +\xb0\xd0\xe8\x75\x6f\x39\xbf\x4d\xd9\x84\x97\x80\x4d\x56\xef\x43\ +\x73\xe3\x82\x9d\x19\x8f\xd6\x3f\xe3\xb2\xcc\x9f\x1a\xc6\x72\xb9\ +\x24\xb7\x6a\x89\xa0\xb5\x81\xeb\x24\x2e\xe7\xa9\xd6\x57\xd1\xa8\ +\xc8\x24\x05\xba\x47\x61\xae\xa6\x0d\x75\xad\x5b\xc3\x14\x2c\x12\ +\xd3\x98\xe0\x92\x82\xa9\x4c\x24\x12\xe6\x31\xca\xf3\x29\x9f\xb1\ +\x2c\x9a\x63\x24\xd4\xb0\xf6\x78\x57\x85\x5c\x8e\xf2\x34\x2a\x6f\ +\xb8\x98\xcb\xe7\x3b\x86\x77\x0f\xb1\x7d\x2a\x16\x13\x1c\x68\x70\ +\xfe\x16\xc5\x9c\xc3\x38\x5d\x88\x5c\x2f\x6e\xca\xe1\x8f\xca\x63\ +\x08\x2b\x39\x31\x4b\x73\xf2\x43\xae\x28\x39\x72\x88\xd9\x36\x7e\ +\x54\x32\x8d\x42\x1a\xff\x0c\x65\x87\x35\x55\x9b\xd9\xfe\x98\xfb\ +\x3f\x25\x8f\xae\x3e\ +" + +qt_resource_name = b"\ +\x00\x15\ +\x03\x80\x5a\x3c\ +\x00\x55\ +\x00\x73\x00\x65\x00\x72\x00\x41\x00\x67\x00\x65\x00\x6e\x00\x74\x00\x44\x00\x65\x00\x66\x00\x61\x00\x75\x00\x6c\x00\x74\x00\x73\ +\x00\x2e\x00\x78\x00\x6d\x00\x6c\ +" + +qt_resource_struct = b"\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ +\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\ +" + +def qInitResources(): + QtCore.qRegisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data) + +def qCleanupResources(): + QtCore.qUnregisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data) + +qInitResources()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebBrowser/UserAgent/UserAgentManager.py Tue Mar 29 10:32:22 2016 +0200 @@ -0,0 +1,195 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2012 - 2016 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing a user agent manager. +""" + +from __future__ import unicode_literals + +import os + +from PyQt5.QtCore import pyqtSignal, QObject, QXmlStreamReader + +from E5Gui import E5MessageBox + +from Utilities.AutoSaver import AutoSaver +import Utilities + + +class UserAgentManager(QObject): + """ + Class implementing a user agent manager. + + @signal changed() emitted to indicate a change + @signal userAgentSettingsSaved() emitted after the user agent settings + were saved + """ + changed = pyqtSignal() + userAgentSettingsSaved = pyqtSignal() + + def __init__(self, parent=None): + """ + Constructor + + @param parent reference to the parent object (QObject) + """ + super(UserAgentManager, self).__init__(parent) + + self.__agents = {} + # dictionary with agent strings indexed by host name + self.__loaded = False + self.__saveTimer = AutoSaver(self, self.save) + + self.changed.connect(self.__saveTimer.changeOccurred) + + def getFileName(self): + """ + Public method to get the file name of the user agents file. + + @return name of the user agents file (string) + """ + return os.path.join( + Utilities.getConfigDir(), "web_browser", "userAgentSettings.xml") + + def save(self): + """ + Public slot to save the user agent entries to disk. + """ + if not self.__loaded: + return + + from .UserAgentWriter import UserAgentWriter + agentFile = self.getFileName() + writer = UserAgentWriter() + if not writer.write(agentFile, self.__agents): + E5MessageBox.critical( + None, + self.tr("Saving user agent data"), + self.tr( + """<p>User agent data could not be saved to""" + """ <b>{0}</b></p>""").format(agentFile)) + else: + self.userAgentSettingsSaved.emit() + + def __load(self): + """ + Private method to load the saved user agent settings. + """ + agentFile = self.getFileName() + from .UserAgentReader import UserAgentReader + reader = UserAgentReader() + self.__agents = reader.read(agentFile) + if reader.error() != QXmlStreamReader.NoError: + E5MessageBox.warning( + None, + self.tr("Loading user agent data"), + self.tr("""Error when loading user agent data on""" + """ line {0}, column {1}:\n{2}""") + .format(reader.lineNumber(), + reader.columnNumber(), + reader.errorString())) + + self.__loaded = True + + def reload(self): + """ + Public method to reload the user agent settings. + """ + if not self.__loaded: + return + + self.__agents = {} + self.__load() + + def close(self): + """ + Public method to close the user agents manager. + """ + self.__saveTimer.saveIfNeccessary() + + def removeUserAgent(self, host): + """ + Public method to remove a user agent entry. + + @param host host name (string) + """ + if host in self.__agents: + del self.__agents[host] + self.changed.emit() + + def allHostNames(self): + """ + Public method to get a list of all host names we a user agent setting + for. + + @return sorted list of all host names (list of strings) + """ + if not self.__loaded: + self.__load() + + return sorted(self.__agents.keys()) + + def hostsCount(self): + """ + Public method to get the number of available user agent settings. + + @return number of user agent settings (integer) + """ + if not self.__loaded: + self.__load() + + return len(self.__agents) + + def userAgent(self, host): + """ + Public method to get the user agent setting for a host. + + @param host host name (string) + @return user agent string (string) + """ + if not self.__loaded: + self.__load() + + for agentHost in self.__agents: + if host.endswith(agentHost): + return self.__agents[agentHost] + + return "" + + def setUserAgent(self, host, agent): + """ + Public method to set the user agent string for a host. + + @param host host name (string) + @param agent user agent string (string) + """ + if host != "" and agent != "": + self.__agents[host] = agent + self.changed.emit() + + def userAgentForUrl(self, url): + """ + Public method to determine the user agent for the given URL. + + @param url URL to determine user agent for (QUrl) + @return user agent string (string) + """ + if url.isValid(): + host = url.host() + return self.userAgent(host) + + return "" + + def setUserAgentForUrl(self, url, agent): + """ + Public method to set the user agent string for an URL. + + @param url URL to register user agent setting for (QUrl) + @param agent new current user agent string (string) + """ + if url.isValid(): + host = url.host() + self.setUserAgent(host, agent)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebBrowser/UserAgent/UserAgentMenu.py Tue Mar 29 10:32:22 2016 +0200 @@ -0,0 +1,190 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2010 - 2016 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing a menu to select the user agent string. +""" + +from __future__ import unicode_literals + +from PyQt5.QtCore import QXmlStreamReader, QFile, QIODevice +from PyQt5.QtWidgets import QMenu, QAction, QActionGroup, QInputDialog, \ + QLineEdit + +from E5Gui import E5MessageBox + + +class UserAgentMenu(QMenu): + """ + Class implementing a menu to select the user agent string. + """ + def __init__(self, title, url=None, parent=None): + """ + Constructor + + @param title title of the menu (string) + @param url URL to set user agent for (QUrl) + @param parent reference to the parent widget (QWidget) + """ + super(UserAgentMenu, self).__init__(title, parent) + + self.__manager = None + self.__url = url + if self.__url: + if self.__url.isValid(): + from WebBrowser.WebBrowserWindow import WebBrowserWindow + self.__manager = WebBrowserWindow.userAgentsManager() + else: + self.__url = None + + self.aboutToShow.connect(self.__populateMenu) + + def __populateMenu(self): + """ + Private slot to populate the menu. + """ + self.aboutToShow.disconnect(self.__populateMenu) + + self.__actionGroup = QActionGroup(self) + + # add default action + self.__defaultUserAgent = QAction(self) + self.__defaultUserAgent.setText(self.tr("Default")) + self.__defaultUserAgent.setCheckable(True) + self.__defaultUserAgent.triggered.connect( + self.__switchToDefaultUserAgent) + if self.__url: + self.__defaultUserAgent.setChecked( + self.__manager.userAgentForUrl(self.__url) == "") + else: + from WebBrowser.WebBrowserPage import WebBrowserPage + self.__defaultUserAgent.setChecked( + WebBrowserPage.userAgent() == "") + self.addAction(self.__defaultUserAgent) + self.__actionGroup.addAction(self.__defaultUserAgent) + isChecked = self.__defaultUserAgent.isChecked() + + # add default extra user agents + isChecked = self.__addDefaultActions() or isChecked + + # add other action + self.addSeparator() + self.__otherUserAgent = QAction(self) + self.__otherUserAgent.setText(self.tr("Other...")) + self.__otherUserAgent.setCheckable(True) + self.__otherUserAgent.triggered.connect( + self.__switchToOtherUserAgent) + self.addAction(self.__otherUserAgent) + self.__actionGroup.addAction(self.__otherUserAgent) + self.__otherUserAgent.setChecked(not isChecked) + + def __switchToDefaultUserAgent(self): + """ + Private slot to set the default user agent. + """ + if self.__url: + self.__manager.removeUserAgent(self.__url.host()) + else: + from WebBrowser.WebBrowserPage import WebBrowserPage + WebBrowserPage.setUserAgent("") + + def __switchToOtherUserAgent(self): + """ + Private slot to set a custom user agent string. + """ + from WebBrowser.WebBrowserPage import WebBrowserPage + userAgent, ok = QInputDialog.getText( + self, + self.tr("Custom user agent"), + self.tr("User agent:"), + QLineEdit.Normal, + WebBrowserPage.userAgent(resolveEmpty=True)) + if ok: + if self.__url: + self.__manager.setUserAgentForUrl(self.__url, userAgent) + else: + WebBrowserPage.setUserAgent(userAgent) + + def __changeUserAgent(self): + """ + Private slot to change the user agent. + """ + act = self.sender() + if self.__url: + self.__manager.setUserAgentForUrl(self.__url, act.data()) + else: + from WebBrowser.WebBrowserPage import WebBrowserPage + WebBrowserPage.setUserAgent(act.data()) + + def __addDefaultActions(self): + """ + Private slot to add the default user agent entries. + + @return flag indicating that a user agent entry is checked (boolean) + """ + from . import UserAgentDefaults_rc # __IGNORE_WARNING__ + defaultUserAgents = QFile(":/UserAgentDefaults.xml") + defaultUserAgents.open(QIODevice.ReadOnly) + + menuStack = [] + isChecked = False + + if self.__url: + currentUserAgentString = self.__manager.userAgentForUrl(self.__url) + else: + from WebBrowser.WebBrowserPage import WebBrowserPage + currentUserAgentString = WebBrowserPage.userAgent() + xml = QXmlStreamReader(defaultUserAgents) + while not xml.atEnd(): + xml.readNext() + if xml.isStartElement() and xml.name() == "separator": + if menuStack: + menuStack[-1].addSeparator() + else: + self.addSeparator() + continue + + if xml.isStartElement() and xml.name() == "useragent": + attributes = xml.attributes() + title = attributes.value("description") + userAgent = attributes.value("useragent") + + act = QAction(self) + act.setText(title) + act.setData(userAgent) + act.setToolTip(userAgent) + act.setCheckable(True) + act.setChecked(userAgent == currentUserAgentString) + act.triggered.connect(self.__changeUserAgent) + if menuStack: + menuStack[-1].addAction(act) + else: + self.addAction(act) + self.__actionGroup.addAction(act) + isChecked = isChecked or act.isChecked() + + if xml.isStartElement() and xml.name() == "useragentmenu": + attributes = xml.attributes() + title = attributes.value("title") + if title == "v_a_r_i_o_u_s": + title = self.tr("Various") + + menu = QMenu(self) + menu.setTitle(title) + self.addMenu(menu) + menuStack.append(menu) + + if xml.isEndElement() and xml.name() == "useragentmenu": + menuStack.pop() + + if xml.hasError(): + E5MessageBox.critical( + self, + self.tr("Parsing default user agents"), + self.tr( + """<p>Error parsing default user agents.</p><p>{0}</p>""") + .format(xml.errorString())) + + return isChecked
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebBrowser/UserAgent/UserAgentModel.py Tue Mar 29 10:32:22 2016 +0200 @@ -0,0 +1,129 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2012 - 2016 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing a model for user agent management. +""" + +from __future__ import unicode_literals + +from PyQt5.QtCore import Qt, QModelIndex, QAbstractTableModel + + +class UserAgentModel(QAbstractTableModel): + """ + Class implementing a model for user agent management. + """ + def __init__(self, manager, parent=None): + """ + Constructor + + @param manager reference to the user agent manager (UserAgentManager) + @param parent reference to the parent object (QObject) + """ + super(UserAgentModel, self).__init__(parent) + + self.__manager = manager + self.__manager.changed.connect(self.__userAgentsChanged) + + self.__headers = [ + self.tr("Host"), + self.tr("User Agent String"), + ] + + def __userAgentsChanged(self): + """ + Private slot handling a change of the registered user agent strings. + """ + self.beginResetModel() + self.endResetModel() + + def removeRows(self, row, count, parent=QModelIndex()): + """ + Public method to remove entries from the model. + + @param row start row (integer) + @param count number of rows to remove (integer) + @param parent parent index (QModelIndex) + @return flag indicating success (boolean) + """ + if parent.isValid(): + return False + + if count <= 0: + return False + + lastRow = row + count - 1 + + self.beginRemoveRows(parent, row, lastRow) + + hostsList = self.__manager.allHostNames() + for index in range(row, lastRow + 1): + self.__manager.removeUserAgent(hostsList[index]) + + return True + + def rowCount(self, parent=QModelIndex()): + """ + Public method to get the number of rows of the model. + + @param parent parent index (QModelIndex) + @return number of rows (integer) + """ + if parent.isValid(): + return 0 + else: + return self.__manager.hostsCount() + + def columnCount(self, parent=QModelIndex()): + """ + Public method to get the number of columns of the model. + + @param parent parent index (QModelIndex) + @return number of columns (integer) + """ + return len(self.__headers) + + def data(self, index, role): + """ + Public method to get data from the model. + + @param index index to get data for (QModelIndex) + @param role role of the data to retrieve (integer) + @return requested data + """ + if index.row() >= self.__manager.hostsCount() or index.row() < 0: + return None + + host = self.__manager.allHostNames()[index.row()] + userAgent = self.__manager.userAgent(host) + + if userAgent is None: + return None + + if role == Qt.DisplayRole: + if index.column() == 0: + return host + elif index.column() == 1: + return userAgent + + return None + + def headerData(self, section, orientation, role=Qt.DisplayRole): + """ + Public method to get the header data. + + @param section section number (integer) + @param orientation header orientation (Qt.Orientation) + @param role data role (integer) + @return header data + """ + if orientation == Qt.Horizontal and role == Qt.DisplayRole: + try: + return self.__headers[section] + except IndexError: + pass + + return None
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebBrowser/UserAgent/UserAgentReader.py Tue Mar 29 10:32:22 2016 +0200 @@ -0,0 +1,97 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2012 - 2016 Detlev Offenbach <detlev@die-offenbachs.de> +# + + +""" +Module implementing a class to read user agent data files. +""" + +from __future__ import unicode_literals + +from PyQt5.QtCore import QXmlStreamReader, QIODevice, QFile, QCoreApplication + + +class UserAgentReader(QXmlStreamReader): + """ + Class implementing a reader object for user agent data files. + """ + def __init__(self): + """ + Constructor + """ + super(UserAgentReader, self).__init__() + + def read(self, fileNameOrDevice): + """ + Public method to read a user agent file. + + @param fileNameOrDevice name of the file to read (string) + or reference to the device to read (QIODevice) + @return dictionary with user agent data (host as key, agent string as + value) + """ + self.__agents = {} + + if isinstance(fileNameOrDevice, QIODevice): + self.setDevice(fileNameOrDevice) + else: + f = QFile(fileNameOrDevice) + if not f.exists(): + return self.__agents + f.open(QFile.ReadOnly) + self.setDevice(f) + + while not self.atEnd(): + self.readNext() + if self.isStartElement(): + version = self.attributes().value("version") + if self.name() == "UserAgents" and \ + (not version or version == "1.0"): + self.__readUserAgents() + else: + self.raiseError(QCoreApplication.translate( + "UserAgentReader", + "The file is not a UserAgents version 1.0 file.")) + + return self.__agents + + def __readUserAgents(self): + """ + Private method to read the user agents data. + """ + if not self.isStartElement() and self.name() != "UserAgents": + return + + while not self.atEnd(): + self.readNext() + if self.isEndElement(): + if self.name() == "UserAgent": + continue + else: + break + + if self.isStartElement(): + if self.name() == "UserAgent": + attributes = self.attributes() + host = attributes.value("host") + agent = attributes.value("agent") + self.__agents[host] = agent + else: + self.__skipUnknownElement() + + def __skipUnknownElement(self): + """ + Private method to skip over all unknown elements. + """ + if not self.isStartElement(): + return + + while not self.atEnd(): + self.readNext() + if self.isEndElement(): + break + + if self.isStartElement(): + self.__skipUnknownElement()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebBrowser/UserAgent/UserAgentWriter.py Tue Mar 29 10:32:22 2016 +0200 @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2012 - 2016 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing a class to write user agent data files. +""" + +from __future__ import unicode_literals + +from PyQt5.QtCore import QXmlStreamWriter, QIODevice, QFile + + +class UserAgentWriter(QXmlStreamWriter): + """ + Class implementing a writer object to generate user agent data files. + """ + def __init__(self): + """ + Constructor + """ + super(UserAgentWriter, self).__init__() + + self.setAutoFormatting(True) + + def write(self, fileNameOrDevice, agents): + """ + Public method to write a user agent data file. + + @param fileNameOrDevice name of the file to write (string) + or device to write to (QIODevice) + @param agents dictionary with user agent data (host as key, agent + string as value) + @return flag indicating success (boolean) + """ + if isinstance(fileNameOrDevice, QIODevice): + f = fileNameOrDevice + else: + f = QFile(fileNameOrDevice) + if not f.open(QFile.WriteOnly): + return False + + self.setDevice(f) + return self.__write(agents) + + def __write(self, agents): + """ + Private method to write a user agent file. + + @param agents dictionary with user agent data (host as key, agent + string as value) + @return flag indicating success (boolean) + """ + self.writeStartDocument() + self.writeDTD("<!DOCTYPE useragents>") + self.writeStartElement("UserAgents") + self.writeAttribute("version", "1.0") + + for host, agent in agents.items(): + self.writeEmptyElement("UserAgent") + self.writeAttribute("host", host) + self.writeAttribute("agent", agent) + + self.writeEndDocument() + return True
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebBrowser/UserAgent/UserAgentsDialog.py Tue Mar 29 10:32:22 2016 +0200 @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2012 - 2016 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing a dialog to show all saved user agent settings. +""" + +from __future__ import unicode_literals + +from PyQt5.QtCore import QSortFilterProxyModel +from PyQt5.QtGui import QFont, QFontMetrics +from PyQt5.QtWidgets import QDialog + +from WebBrowser.WebBrowserWindow import WebBrowserWindow + +from .UserAgentModel import UserAgentModel + +from .Ui_UserAgentsDialog import Ui_UserAgentsDialog + + +class UserAgentsDialog(QDialog, Ui_UserAgentsDialog): + """ + Class implementing a dialog to show all saved user agent settings. + """ + def __init__(self, parent=None): + """ + Constructor + + @param parent reference to the parent widget (QWidget) + """ + super(UserAgentsDialog, self).__init__(parent) + self.setupUi(self) + + self.removeButton.clicked.connect( + self.userAgentsTable.removeSelected) + self.removeAllButton.clicked.connect( + self.userAgentsTable.removeAll) + + self.userAgentsTable.verticalHeader().hide() + self.__userAgentModel = UserAgentModel( + WebBrowserWindow.userAgentsManager(), self) + self.__proxyModel = QSortFilterProxyModel(self) + self.__proxyModel.setSourceModel(self.__userAgentModel) + self.searchEdit.textChanged.connect( + self.__proxyModel.setFilterFixedString) + self.userAgentsTable.setModel(self.__proxyModel) + + fm = QFontMetrics(QFont()) + height = fm.height() + fm.height() // 3 + self.userAgentsTable.verticalHeader().setDefaultSectionSize(height) + self.userAgentsTable.verticalHeader().setMinimumSectionSize(-1) + + self.userAgentsTable.resizeColumnsToContents() + self.userAgentsTable.horizontalHeader().setStretchLastSection(True)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebBrowser/UserAgent/UserAgentsDialog.ui Tue Mar 29 10:32:22 2016 +0200 @@ -0,0 +1,179 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>UserAgentsDialog</class> + <widget class="QDialog" name="UserAgentsDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>700</width> + <height>400</height> + </rect> + </property> + <property name="windowTitle"> + <string>User Agent Settings</string> + </property> + <property name="sizeGripEnabled"> + <bool>true</bool> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="spacing"> + <number>0</number> + </property> + <item> + <widget class="E5ClearableLineEdit" name="searchEdit"> + <property name="toolTip"> + <string>Enter search term</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + <item> + <widget class="E5TableView" name="userAgentsTable"> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <property name="selectionBehavior"> + <enum>QAbstractItemView::SelectRows</enum> + </property> + <property name="textElideMode"> + <enum>Qt::ElideMiddle</enum> + </property> + <property name="showGrid"> + <bool>false</bool> + </property> + <property name="sortingEnabled"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <widget class="QPushButton" name="removeButton"> + <property name="toolTip"> + <string>Press to remove the selected entries</string> + </property> + <property name="text"> + <string>&Remove</string> + </property> + <property name="autoDefault"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="removeAllButton"> + <property name="toolTip"> + <string>Press to remove all entries</string> + </property> + <property name="text"> + <string>Remove &All</string> + </property> + <property name="autoDefault"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>208</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Close</set> + </property> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>E5ClearableLineEdit</class> + <extends>QLineEdit</extends> + <header>E5Gui/E5LineEdit.h</header> + </customwidget> + <customwidget> + <class>E5TableView</class> + <extends>QTableView</extends> + <header>E5Gui/E5TableView.h</header> + </customwidget> + </customwidgets> + <tabstops> + <tabstop>searchEdit</tabstop> + <tabstop>userAgentsTable</tabstop> + <tabstop>removeButton</tabstop> + <tabstop>removeAllButton</tabstop> + <tabstop>buttonBox</tabstop> + </tabstops> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>UserAgentsDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>237</x> + <y>390</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>UserAgentsDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>325</x> + <y>390</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebBrowser/UserAgent/__init__.py Tue Mar 29 10:32:22 2016 +0200 @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2010 - 2016 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Package implementing the user agents manager. +"""
--- a/WebBrowser/WebBrowserPage.py Mon Mar 28 17:04:18 2016 +0200 +++ b/WebBrowser/WebBrowserPage.py Tue Mar 29 10:32:22 2016 +0200 @@ -351,70 +351,45 @@ ## """ ## return self.__adBlockedEntries - # TODO: User Agent Manager -## def userAgent(self, resolveEmpty=False): -## """ -## Public method to get the global user agent setting. -## -## @param resolveEmpty flag indicating to resolve an empty -## user agent (boolean) -## @return user agent string (string) -## """ -## agent = Preferences.getWebBrowser("UserAgent") -## if agent == "" and resolveEmpty: -## agent = self.userAgentForUrl(QUrl()) -## return agent -## -## def setUserAgent(self, agent): -## """ -## Public method to set the global user agent string. -## -## @param agent new current user agent string (string) -## """ -## Preferences.setWebBrowser("UserAgent", agent) -## -## def userAgentForUrl(self, url): -## """ -## Public method to determine the user agent for the given URL. -## -## @param url URL to determine user agent for (QUrl) -## @return user agent string (string) -## """ -## agent = WebBrowserWindow.userAgentsManager().userAgentForUrl(url) -## if agent == "": -## # no agent string specified for the given host -> use global one -## agent = Preferences.getWebBrowser("UserAgent") -## if agent == "": -## # no global agent string specified -> use default one -## agent = QWebPage.userAgentForUrl(self, url) -## return agent -## -## def hasValidSslInfo(self): -## """ -## Public method to check, if the page has a valid SSL certificate. -## -## @return flag indicating a valid SSL certificate (boolean) -## """ -## if self.__sslConfiguration is None: -## return False -## -## certList = self.__sslConfiguration.peerCertificateChain() -## if not certList: -## return False -## -## certificateDict = Globals.toDict( -## Preferences.Prefs.settings.value("Ssl/CaCertificatesDict")) -## for server in certificateDict: -## localCAList = QSslCertificate.fromData(certificateDict[server]) -## for cert in certList: -## if cert in localCAList: -## return True -## -## for cert in certList: -## if cert.isBlacklisted(): -## return False -## -## return True + @classmethod + def userAgent(cls, resolveEmpty=False): + """ + Class method to get the global user agent setting. + + @param resolveEmpty flag indicating to resolve an empty + user agent (boolean) + @return user agent string (string) + """ + agent = Preferences.getWebBrowser("UserAgent") + if agent == "" and resolveEmpty: + agent = cls.userAgentForUrl(QUrl()) + return agent + + @classmethod + def setUserAgent(cls, agent): + """ + Class method to set the global user agent string. + + @param agent new current user agent string (string) + """ + Preferences.setWebBrowser("UserAgent", agent) + + @classmethod + def userAgentForUrl(cls, url): + """ + Class method to determine the user agent for the given URL. + + @param url URL to determine user agent for (QUrl) + @return user agent string (string) + """ + agent = WebBrowserWindow.userAgentsManager().userAgentForUrl(url) + if agent == "": + # no agent string specified for the given host -> use global one + agent = Preferences.getWebBrowser("UserAgent") + if agent == "": + # no global agent string specified -> use default one + agent = WebBrowserWindow.webProfile().httpUserAgent() + return agent ## @classmethod ## def webPluginFactory(cls):
--- a/WebBrowser/WebBrowserView.py Mon Mar 28 17:04:18 2016 +0200 +++ b/WebBrowser/WebBrowserView.py Tue Mar 29 10:32:22 2016 +0200 @@ -827,12 +827,11 @@ self.tr("Send Page Link"), self.__sendLink).setData(self.url()) menu.addSeparator() - # TODO: User Agent -## from .UserAgent.UserAgentMenu import UserAgentMenu -## self.__userAgentMenu = UserAgentMenu(self.tr("User Agent"), -## url=self.url()) -## menu.addMenu(self.__userAgentMenu) -## menu.addSeparator() + from .UserAgent.UserAgentMenu import UserAgentMenu + self.__userAgentMenu = UserAgentMenu(self.tr("User Agent"), + url=self.url()) + menu.addMenu(self.__userAgentMenu) + menu.addSeparator() menu.addAction(self.__mw.backAct) menu.addAction(self.__mw.forwardAct) menu.addAction(self.__mw.homeAct)
--- a/WebBrowser/WebBrowserWindow.py Mon Mar 28 17:04:18 2016 +0200 +++ b/WebBrowser/WebBrowserWindow.py Tue Mar 29 10:32:22 2016 +0200 @@ -93,7 +93,7 @@ _adblockManager = None _downloadManager = None _feedsManager = None -## _userAgentsManager = None + _userAgentsManager = None _syncManager = None _speedDial = None _personalInformationManager = None @@ -1592,21 +1592,20 @@ self.siteInfoAct.triggered.connect(self.__showSiteinfoDialog) self.__actions.append(self.siteInfoAct) - # TODO: User Agents -## self.userAgentManagerAct = E5Action( -## self.tr('Manage User Agent Settings'), -## self.tr('Manage &User Agent Settings'), -## 0, 0, self, 'webbrowser_user_agent_settings') -## self.userAgentManagerAct.setStatusTip(self.tr( -## 'Shows a dialog to manage the User Agent settings')) -## self.userAgentManagerAct.setWhatsThis(self.tr( -## """<b>Manage User Agent Settings</b>""" -## """<p>Shows a dialog to manage the User Agent settings.</p>""" -## )) -## if not self.__initShortcutsOnly: -## self.userAgentManagerAct.triggered.connect( -## self.__showUserAgentsDialog) -## self.__actions.append(self.userAgentManagerAct) + self.userAgentManagerAct = E5Action( + self.tr('Manage User Agent Settings'), + self.tr('Manage &User Agent Settings'), + 0, 0, self, 'webbrowser_user_agent_settings') + self.userAgentManagerAct.setStatusTip(self.tr( + 'Shows a dialog to manage the User Agent settings')) + self.userAgentManagerAct.setWhatsThis(self.tr( + """<b>Manage User Agent Settings</b>""" + """<p>Shows a dialog to manage the User Agent settings.</p>""" + )) + if not self.__initShortcutsOnly: + self.userAgentManagerAct.triggered.connect( + self.__showUserAgentsDialog) + self.__actions.append(self.userAgentManagerAct) self.synchronizationAct = E5Action( self.tr('Synchronize data'), @@ -1792,12 +1791,11 @@ self.__settingsMenu.aboutToShow.connect( self.__aboutToShowSettingsMenu) - # TODO: UserAgents -## from .UserAgent.UserAgentMenu import UserAgentMenu -## self.__userAgentMenu = UserAgentMenu(self.tr("Global User Agent")) -## menu.addMenu(self.__userAgentMenu) -## menu.addAction(self.userAgentManagerAct) -## menu.addSeparator() + from .UserAgent.UserAgentMenu import UserAgentMenu + self.__userAgentMenu = UserAgentMenu(self.tr("Global User Agent")) + menu.addMenu(self.__userAgentMenu) + menu.addAction(self.userAgentManagerAct) + menu.addSeparator() if WebBrowserWindow.useQtHelp: menu.addAction(self.manageQtHelpDocsAct) @@ -2414,9 +2412,8 @@ self.adBlockManager().close() - # TODO: UserAgents -## self.userAgentsManager().close() -## + self.userAgentsManager().close() + self.speedDial().close() self.syncManager().close() @@ -3682,29 +3679,28 @@ self.__siteinfoDialog = SiteInfoDialog(self.currentBrowser(), self) self.__siteinfoDialog.show() - # TODO: User Agents -## @classmethod -## def userAgentsManager(cls): -## """ -## Class method to get a reference to the user agents manager. -## -## @return reference to the user agents manager (UserAgentManager) -## """ -## if cls._userAgentsManager is None: -## from .UserAgent.UserAgentManager import UserAgentManager -## cls._userAgentsManager = UserAgentManager() -## -## return cls._userAgentsManager -## -## def __showUserAgentsDialog(self): -## """ -## Private slot to show the user agents management dialog. -## """ -## from .UserAgent.UserAgentsDialog import UserAgentsDialog -## -## dlg = UserAgentsDialog(self) -## dlg.exec_() -## + @classmethod + def userAgentsManager(cls): + """ + Class method to get a reference to the user agents manager. + + @return reference to the user agents manager (UserAgentManager) + """ + if cls._userAgentsManager is None: + from .UserAgent.UserAgentManager import UserAgentManager + cls._userAgentsManager = UserAgentManager() + + return cls._userAgentsManager + + def __showUserAgentsDialog(self): + """ + Private slot to show the user agents management dialog. + """ + from .UserAgent.UserAgentsDialog import UserAgentsDialog + + dlg = UserAgentsDialog(self) + dlg.exec_() + @classmethod def syncManager(cls): """
--- a/eric6.e4p Mon Mar 28 17:04:18 2016 +0200 +++ b/eric6.e4p Tue Mar 29 10:32:22 2016 +0200 @@ -1429,6 +1429,14 @@ <Source>WebBrowser/UrlBar/StackedUrlBar.py</Source> <Source>WebBrowser/UrlBar/UrlBar.py</Source> <Source>WebBrowser/UrlBar/__init__.py</Source> + <Source>WebBrowser/UserAgent/UserAgentDefaults_rc.py</Source> + <Source>WebBrowser/UserAgent/UserAgentManager.py</Source> + <Source>WebBrowser/UserAgent/UserAgentMenu.py</Source> + <Source>WebBrowser/UserAgent/UserAgentModel.py</Source> + <Source>WebBrowser/UserAgent/UserAgentReader.py</Source> + <Source>WebBrowser/UserAgent/UserAgentWriter.py</Source> + <Source>WebBrowser/UserAgent/UserAgentsDialog.py</Source> + <Source>WebBrowser/UserAgent/__init__.py</Source> <Source>WebBrowser/VirusTotal/VirusTotalApi.py</Source> <Source>WebBrowser/VirusTotal/VirusTotalDomainReportDialog.py</Source> <Source>WebBrowser/VirusTotal/VirusTotalIpReportDialog.py</Source> @@ -1896,6 +1904,7 @@ <Form>WebBrowser/Tools/WebIconDialog.ui</Form> <Form>WebBrowser/UrlBar/BookmarkActionSelectionDialog.ui</Form> <Form>WebBrowser/UrlBar/BookmarkInfoDialog.ui</Form> + <Form>WebBrowser/UserAgent/UserAgentsDialog.ui</Form> <Form>WebBrowser/VirusTotal/VirusTotalDomainReportDialog.ui</Form> <Form>WebBrowser/VirusTotal/VirusTotalIpReportDialog.ui</Form> <Form>WebBrowser/VirusTotal/VirusTotalWhoisDialog.ui</Form> @@ -1935,6 +1944,7 @@ <Resource>IconEditor/cursors/cursors.qrc</Resource> <Resource>WebBrowser/Bookmarks/DefaultBookmarks.qrc</Resource> <Resource>WebBrowser/OpenSearch/DefaultSearchEngines/DefaultSearchEngines.qrc</Resource> + <Resource>WebBrowser/UserAgent/UserAgentDefaults.qrc</Resource> <Resource>WebBrowser/data/html.qrc</Resource> <Resource>WebBrowser/data/icons.qrc</Resource> <Resource>WebBrowser/data/javascript.qrc</Resource> @@ -2060,6 +2070,7 @@ <Other>WebBrowser/OpenSearch/DefaultSearchEngines/Wiktionary.xml</Other> <Other>WebBrowser/OpenSearch/DefaultSearchEngines/Yahoo.xml</Other> <Other>WebBrowser/OpenSearch/DefaultSearchEngines/YouTube.xml</Other> + <Other>WebBrowser/UserAgent/UserAgentDefaults.xml</Other> <Other>WebBrowser/data/html/adblockPage.html</Other> <Other>WebBrowser/data/html/speeddialPage.html</Other> <Other>WebBrowser/data/html/startPage.html</Other>