Sun, 21 Feb 2016 19:54:14 +0100
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