WebBrowser/GreaseMonkey/GreaseMonkeyManager.py

Sun, 21 Feb 2016 19:54:14 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Sun, 21 Feb 2016 19:54:14 +0100
branch
QtWebEngine
changeset 4763
8ad353f31184
parent 4631
Helpviewer/GreaseMonkey/GreaseMonkeyManager.py@5c1a96925da4
child 4766
5f8d08aa2217
permissions
-rw-r--r--

Continued porting the web browser.

- started adding the GreaseMonkey stuff

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

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

"""
Module implementing the manager for GreaseMonkey scripts.
"""

from __future__ import unicode_literals

import os

from PyQt5.QtCore import pyqtSignal, QObject, QTimer, QFile, QDir, QSettings, \
    QUrl, QByteArray
from PyQt5.QtNetwork import QNetworkAccessManager

import Utilities
import Preferences


class GreaseMonkeyManager(QObject):
    """
    Class implementing the manager for GreaseMonkey scripts.
    """
    scriptsChanged = pyqtSignal()
    
    def __init__(self, parent=None):
        """
        Constructor
        
        @param parent reference to the parent object (QObject)
        """
        super(GreaseMonkeyManager, self).__init__(parent)
        
        self.__disabledScripts = []
        self.__endScripts = []
        self.__startScripts = []
        self.__downloaders = []
        
        QTimer.singleShot(0, self.__load)
##    , m_interceptor(new GM_UrlInterceptor(this))
##{
##    mApp->networkManager()->installUrlInterceptor(m_interceptor);
##
##    QTimer::singleShot(0, this, SLOT(load()));
##}
##
##GM_Manager::~GM_Manager()
##{
##    mApp->networkManager()->removeUrlInterceptor(m_interceptor);
##}
    
    def showConfigurationDialog(self, parent=None):
        """
        Public method to show the configuration dialog.
        
        @param parent reference to the parent widget (QWidget)
        """
        from .GreaseMonkeyConfiguration.GreaseMonkeyConfigurationDialog \
            import GreaseMonkeyConfigurationDialog
        self.__configDiaolg = GreaseMonkeyConfigurationDialog(self, parent)
        self.__configDiaolg.show()
    
    def downloadScript(self, request):
        """
        Public method to download a GreaseMonkey script.
        
        @param request reference to the request (QNetworkRequest)
        """
        from .GreaseMonkeyDownloader import GreaseMonkeyDownloader
        downloader = GreaseMonkeyDownloader(request, self)
        downloader.finished.connect(self.__downloaderFinished)
        self.__downloaders.append(downloader)
    
    def __downloaderFinished(self):
        """
        Private slot to handle the completion of a script download.
        """
        downloader = self.sender()
        if downloader is None or downloader not in self.__downloaders:
            return
        
        self.__downloaders.remove(downloader)
    
    def scriptsDirectory(self):
        """
        Public method to get the path of the scripts directory.
        
        @return path of the scripts directory (string)
        """
        return os.path.join(
            Utilities.getConfigDir(), "web_browser", "greasemonkey")
    
    def requireScriptsDirectory(self):
        """
        Public method to get the path of the scripts directory.
        
        @return path of the scripts directory (string)
        """
        return os.path.join(self.scriptsDirectory(), "requires")
    
    def requireScripts(self, urlList):
        """
        Public method to get the sources of all required scripts.
        
        @param urlList list of URLs (list of string)
        @return sources of all required scripts (string)
        """
        requiresDir = QDir(self.requireScriptsDirectory())
        if not requiresDir.exists() or len(urlList) == 0:
            return ""
        
        script = ""
        
        settings = QSettings(
            os.path.join(self.requireScriptsDirectory(), "requires.ini"),
            QSettings.IniFormat)
        settings.beginGroup("Files")
        for url in urlList:
            if settings.contains(url):
                fileName = settings.value(url)
                try:
                    f = open(fileName, "r", encoding="utf-8")
                    source = f.read()
                    f.close()
                except (IOError, OSError):
                    source = ""
                script += source.strip() + "\n"
        
        return script
    
    def saveConfiguration(self):
        """
        Public method to save the configuration.
        """
        Preferences.setWebBrowser("GreaseMonkeyDisabledScripts",
                                  self.__disabledScripts)
    
    def allScripts(self):
        """
        Public method to get a list of all scripts.
        
        @return list of all scripts (list of GreaseMonkeyScript)
        """
        return self.__startScripts[:] + self.__endScripts[:]
    
    def containsScript(self, fullName):
        """
        Public method to check, if the given script exists.
        
        @param fullName full name of the script (string)
        @return flag indicating the existence (boolean)
        """
        for script in self.__startScripts:
            if script.fullName() == fullName:
                return True
        for script in self.__endScripts:
            if script.fullName() == fullName:
                return True
        return False
    
    def enableScript(self, script):
        """
        Public method to enable the given script.
        
        @param script script to be enabled (GreaseMonkeyScript)
        """
        script.setEnabled(True)
        fullName = script.fullName()
        if fullName in self.__disabledScripts:
            self.__disabledScripts.remove(fullName)
##void GM_Manager::enableScript(GM_Script* script)
##{
##    script->setEnabled(true);
##    m_disabledScripts.removeOne(script->fullName());
##
##    QWebEngineScriptCollection *collection = mApp->webProfile()->scripts();
##    collection->insert(script->webScript());
##}
    
    def disableScript(self, script):
        """
        Public method to disable the given script.
        
        @param script script to be disabled (GreaseMonkeyScript)
        """
        script.setEnabled(False)
        fullName = script.fullName()
        if fullName not in self.__disabledScripts:
            self.__disabledScripts.append(fullName)
##void GM_Manager::disableScript(GM_Script* script)
##{
##    script->setEnabled(false);
##    m_disabledScripts.append(script->fullName());
##
##    QWebEngineScriptCollection *collection = mApp->webProfile()->scripts();
##    collection->remove(collection->findScript(script->fullName()));
    
    def addScript(self, script):
        """
        Public method to add a script.
        
        @param script script to be added (GreaseMonkeyScript)
        @return flag indicating success (boolean)
        """
        if not script:
            return False
        
        from .GreaseMonkeyScript import GreaseMonkeyScript
        if script.startAt() == GreaseMonkeyScript.DocumentStart:
            self.__startScripts.append(script)
        else:
            self.__endScripts.append(script)
        
        self.scriptsChanged.emit()
        return True
##bool GM_Manager::addScript(GM_Script* script)
##{
##    if (!script || !script->isValid()) {
##        return false;
##    }
##
##    m_scripts.append(script);
##    connect(script, &GM_Script::scriptChanged, this, &GM_Manager::scriptChanged);
##
##    QWebEngineScriptCollection *collection = mApp->webProfile()->scripts();
##    collection->insert(script->webScript());
##
##    emit scriptsChanged();
##    return true;
##}
    
    def removeScript(self, script):
        """
        Public method to remove a script.
        
        @param script script to be removed (GreaseMonkeyScript)
        @return flag indicating success (boolean)
        """
        if not script:
            return False
        
        from .GreaseMonkeyScript import GreaseMonkeyScript
        if script.startAt() == GreaseMonkeyScript.DocumentStart:
            try:
                self.__startScripts.remove(script)
            except ValueError:
                pass
        else:
            try:
                self.__endScripts.remove(script)
            except ValueError:
                pass
        
        fullName = script.fullName()
        if fullName in self.__disabledScripts:
            self.__disabledScripts.remove(fullName)
        QFile.remove(script.fileName())
        
        self.scriptsChanged.emit()
        return True
##bool GM_Manager::removeScript(GM_Script* script, bool removeFile)
##{
##    if (!script) {
##        return false;
##    }
##
##    m_scripts.removeOne(script);
##
##    QWebEngineScriptCollection *collection = mApp->webProfile()->scripts();
##    collection->remove(collection->findScript(script->fullName()));
##
##    m_disabledScripts.removeOne(script->fullName());
##
##    if (removeFile) {
##        QFile::remove(script->fileName());
##        delete script;
##    }
##
##    emit scriptsChanged();
##    return true;
##}
    
    def canRunOnScheme(self, scheme):
        """
        Public method to check, if scripts can be run on a scheme.
        
        @param scheme scheme to check (string)
        @return flag indicating, that scripts can be run (boolean)
        """
        return scheme in ["http", "https", "data", "ftp"]
    
##    def pageLoadStarted(self):
##        """
##        Public slot to handle the start of loading a page.
##        """
##        frame = self.sender()
##        if not frame:
##            return
##        
##        urlScheme = frame.url().scheme()
##        urlString = bytes(frame.url().toEncoded()).decode()
##        
##        if not self.canRunOnScheme(urlScheme):
##            return
##        
##        from .GreaseMonkeyJavaScript import bootstrap_js
##        for script in self.__startScripts:
##            if script.match(urlString):
##                frame.evaluateJavaScript(bootstrap_js + script.script())
##        
##        for script in self.__endScripts:
##            if script.match(urlString):
##                javascript = 'window.addEventListener("DOMContentLoaded",' \
##                    'function(e) {{ {0} }}, false);'.format(
##                        bootstrap_js + script.script())
##                frame.evaluateJavaScript(javascript)
    
    def __load(self):
        """
        Private slot to load the available scripts into the manager.
        """
        scriptsDir = QDir(self.scriptsDirectory())
        if not scriptsDir.exists():
            scriptsDir.mkpath(self.scriptsDirectory())
        
        if not scriptsDir.exists("requires"):
            scriptsDir.mkdir("requires")
        
        self.__disabledScripts = \
            Preferences.getHelp("GreaseMonkeyDisabledScripts")
        
        from .GreaseMonkeyScript import GreaseMonkeyScript
        for fileName in scriptsDir.entryList(["*.js"], QDir.Files):
            absolutePath = scriptsDir.absoluteFilePath(fileName)
            script = GreaseMonkeyScript(self, absolutePath)
            
            if script.fullName() in self.__disabledScripts:
                script.setEnabled(False)
            
            if script.startAt() == GreaseMonkeyScript.DocumentStart:
                self.__startScripts.append(script)
            else:
                self.__endScripts.append(script)
##void GM_Manager::load()
##{
##    QDir gmDir(m_settingsPath + QL1S("/greasemonkey"));
##    if (!gmDir.exists()) {
##        gmDir.mkdir(m_settingsPath + QL1S("/greasemonkey"));
##    }
##
##    if (!gmDir.exists("requires")) {
##        gmDir.mkdir("requires");
##    }
##
##    m_bootstrapScript = QzTools::readAllFileContents(":gm/data/bootstrap.min.js");
##    m_valuesScript = QzTools::readAllFileContents(":gm/data/values.min.js");
##
##    QSettings settings(m_settingsPath + QL1S("/extensions.ini"), QSettings::IniFormat);
##    settings.beginGroup("GreaseMonkey");
##    m_disabledScripts = settings.value("disabledScripts", QStringList()).toStringList();
##
##    foreach (const QString &fileName, gmDir.entryList(QStringList("*.js"), QDir::Files)) {
##        const QString absolutePath = gmDir.absoluteFilePath(fileName);
##        GM_Script* script = new GM_Script(this, absolutePath);
##
##        if (!script->isValid()) {
##            delete script;
##            continue;
##        }
##
##        m_scripts.append(script);
##
##        if (m_disabledScripts.contains(script->fullName())) {
##            script->setEnabled(false);
##        }
##        else {
##            mApp->webProfile()->scripts()->insert(script->webScript());
##        }
##    }
##}
    
    def __scriptChanged(self):
        """
        Private slot handling a changed script.
        """
##void GM_Manager::scriptChanged()
##{
##    GM_Script *script = qobject_cast<GM_Script*>(sender());
##    if (!script)
##        return;
##
##    QWebEngineScriptCollection *collection = mApp->webProfile()->scripts();
##    collection->remove(collection->findScript(script->fullName()));
##    collection->insert(script->webScript());
##}
    
##    def connectPage(self, page):
##        """
##        Public method to allow the GreaseMonkey manager to connect to the page.
##        
##        @param page reference to the web page (HelpWebPage)
##        """
##        page.mainFrame().javaScriptWindowObjectCleared.connect(
##            self.pageLoadStarted)
##    
##    def createRequest(self, op, request, outgoingData=None):
##        """
##        Public method to create a request.
##        
##        @param op the operation to be performed
##            (QNetworkAccessManager.Operation)
##        @param request reference to the request object (QNetworkRequest)
##        @param outgoingData reference to an IODevice containing data to be sent
##            (QIODevice)
##        @return reference to the created reply object (QNetworkReply)
##        """
##        if op == QNetworkAccessManager.GetOperation and \
##           request.rawHeader(b"X-Eric6-UserLoadAction") == QByteArray(b"1"):
##            urlString = request.url().toString(
##                QUrl.RemoveFragment | QUrl.RemoveQuery)
##            if urlString.endswith(".user.js"):
##                self.downloadScript(request)
##                from Helpviewer.Network.EmptyNetworkReply import \
##                    EmptyNetworkReply
##                return EmptyNetworkReply(self)
##        
##        return None

eric ide

mercurial