diff -r ea40955a0937 -r 8ad353f31184 WebBrowser/GreaseMonkey/GreaseMonkeyManager.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebBrowser/GreaseMonkey/GreaseMonkeyManager.py Sun Feb 21 19:54:14 2016 +0100 @@ -0,0 +1,429 @@ +# -*- 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