WebBrowser/Network/NetworkUrlInterceptor.py

Sun, 06 May 2018 15:23:02 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Sun, 06 May 2018 15:23:02 +0200
changeset 6277
e22952cec018
parent 6131
1ecd0c53e117
child 6281
9f7bbfd6545d
permissions
-rw-r--r--

Added a TODO marker to improve the Referer header handling in the new web browser.

# -*- coding: utf-8 -*-

# Copyright (c) 2016 - 2018 Detlev Offenbach <detlev@die-offenbachs.de>
#

"""
Module implementing a class to handle URL requests before they get processed
by QtWebEngine.
"""

from __future__ import unicode_literals

from PyQt5.QtCore import QMutex, QMutexLocker
from PyQt5.QtWebEngineCore import QWebEngineUrlRequestInterceptor

from ..WebBrowserPage import WebBrowserPage

import Preferences


class NetworkUrlInterceptor(QWebEngineUrlRequestInterceptor):
    """
    Class implementing an URL request handler.
    """
    def __init__(self, parent=None):
        """
        Constructor
        
        @param parent reference to the parent object
        @type QObject
        """
        super(NetworkUrlInterceptor, self).__init__(parent)
        
        self.__interceptors = []
        self.__mutex = QMutex()
        
        self.__loadSettings()
    
    def interceptRequest(self, info):
        """
        Public method handling an URL request.
        
        @param info URL request information
        @type QWebEngineUrlRequestInfo
        """
        locker = QMutexLocker(self.__mutex)     # __IGNORE_WARNING__
        
        # Do Not Track feature
        if self.__doNotTrack:
            info.setHttpHeader(b"DNT", b"1")
            info.setHttpHeader(b"X-Do-Not-Track", b"1")
        
        # Send referrer header?
        if info.requestUrl().host() not in \
                Preferences.getWebBrowser("SendRefererWhitelist"):
            self.__setRefererHeader(info)
        
        # User Agents header
        userAgent = WebBrowserPage.userAgentForUrl(info.requestUrl())
        info.setHttpHeader(b"User-Agent", userAgent.encode())
        
        for interceptor in self.__interceptors:
            interceptor.interceptRequest(info)
    
    def __setRefererHeader(self, info):
        """
        Private method to set the 'Referer' header depending on the configured
        rule set.
        
        @param info URL request information
        @type QWebEngineUrlRequestInfo
        """
        # TODO: extend referrer handling like that:
        # 1. SendReferer:
        #       0 = never
        #       1 = only on click (NavigationTypeLink)
        #       2 = always (default)
        # 2. RefererTrimmingPolicy: 
        #       0 = send full URL (no trimming) (default)
        #       1 = send the URL without its query string
        #       2 = only send the origin (ensure trailing /)
        # 3. RefererDefaultPolicy:
        #   set the default referrer policy (which can be overriden by
        #   the site)
        #       0 = no-referrer
        #       1 = same-origin
        #       2 = strict-origin-when-cross-origin
        #       3 = no-referrer-when-downgrade (default)
        # see: https://wiki.mozilla.org/Security/Referrer
        # see: https://www.w3.org/TR/referrer-policy/
        if not self.__sendReferer:
            info.setHttpHeader(b"Referer", b"")
    
    def installUrlInterceptor(self, interceptor):
        """
        Public method to install an URL interceptor.
        
        @param interceptor URL interceptor to be installed
        @type UrlInterceptor
        """
        locker = QMutexLocker(self.__mutex)     # __IGNORE_WARNING__
        
        if interceptor not in self.__interceptors:
            self.__interceptors.append(interceptor)
    
    def removeUrlInterceptor(self, interceptor):
        """
        Public method to remove an URL interceptor.
        
        @param interceptor URL interceptor to be removed
        @type UrlInterceptor
        """
        locker = QMutexLocker(self.__mutex)     # __IGNORE_WARNING__
        
        if interceptor in self.__interceptors:
            self.__interceptors.remove(interceptor)
    
    def __loadSettings(self):
        """
        Private method to load the Network Manager settings.
        """
        locker = QMutexLocker(self.__mutex)     # __IGNORE_WARNING__
        
        self.__doNotTrack = Preferences.getWebBrowser("DoNotTrack")
        self.__sendReferer = Preferences.getWebBrowser("SendReferer")
    
    def preferencesChanged(self):
        """
        Public slot to handle a change of preferences.
        """
        self.__loadSettings()

eric ide

mercurial