Sat, 05 Mar 2016 18:40:16 +0100
Continued porting the web browser.
- modified GreaseMonkey to get rid of the meta data
- modified GreaseMonkey to match the include and exclude patterns in JavaScript.
WebBrowser/GreaseMonkey/GreaseMonkeyScript.py | file | annotate | diff | comparison | revisions | |
WebBrowser/GreaseMonkey/GreaseMonkeyUrlMatcher.py | file | annotate | diff | comparison | revisions | |
eric6.e4p | file | annotate | diff | comparison | revisions |
--- a/WebBrowser/GreaseMonkey/GreaseMonkeyScript.py Sat Mar 05 17:24:44 2016 +0100 +++ b/WebBrowser/GreaseMonkey/GreaseMonkeyScript.py Sat Mar 05 18:40:16 2016 +0100 @@ -13,7 +13,6 @@ QByteArray, QCryptographicHash from PyQt5.QtWebEngineWidgets import QWebEngineScript -from .GreaseMonkeyUrlMatcher import GreaseMonkeyUrlMatcher from .GreaseMonkeyJavaScript import bootstrap_js, values_js from ..Tools.DelayedFileWatcher import DelayedFileWatcher @@ -25,6 +24,7 @@ """ DocumentStart = 0 DocumentEnd = 1 + DocumentIdle = 2 scriptChanged = pyqtSignal() @@ -56,7 +56,6 @@ self.__fileName = path self.__enabled = True self.__valid = False - self.__metaData = "" self.__noFrames = False self.__parseScript() @@ -167,10 +166,7 @@ @return list of included URLs (list of strings) """ - list = [] - for matcher in self.__include: - list.append(matcher.pattern()) - return list + return self.__include[:] def exclude(self): """ @@ -178,10 +174,7 @@ @return list of excluded URLs (list of strings) """ - list = [] - for matcher in self.__exclude: - list.append(matcher.pattern()) - return list + return self.__exclude[:] def script(self): """ @@ -191,15 +184,6 @@ """ return self.__script - def metaData(self): - """ - Public method to get the script meta information. - - @return script meta information - @rtype str - """ - return self.__metaData - def fileName(self): """ Public method to get the path of the Javascript file. @@ -208,26 +192,6 @@ """ return self.__fileName - def match(self, urlString): - """ - Public method to check, if the script matches the given URL. - - @param urlString URL (string) - @return flag indicating a match (boolean) - """ - if not self.isEnabled(): - return False - - for matcher in self.__exclude: - if matcher.match(urlString): - return False - - for matcher in self.__include: - if matcher.match(urlString): - return True - - return False - @pyqtSlot(str) def __watchedFileChanged(self, fileName): """ @@ -266,7 +230,6 @@ self.__script = "" self.__enabled = True self.__valid = False - self.__metaData = "" self.__noFrames = False try: @@ -325,10 +288,10 @@ ## self.__downloadUrl = QUrl(value) ## elif key in ["@include", "@match"]: - self.__include.append(GreaseMonkeyUrlMatcher(value)) + self.__include.append(value) elif key in ["@exclude", "@exclude_match"]: - self.__exclude.append(GreaseMonkeyUrlMatcher(value)) + self.__exclude.append(value) elif key == "@require": requireList.append(value) @@ -338,6 +301,8 @@ self.__startAt = GreaseMonkeyScript.DocumentEnd elif value == "document-start": self.__startAt = GreaseMonkeyScript.DocumentStart + elif value == "document-idle": + self.__startAt = GreaseMonkeyScript.DocumentIdle elif key == "@downloadURL" and self.__downloadUrl.isEmpty(): self.__downloadUrl = QUrl(value) @@ -346,19 +311,37 @@ self.__updateUrl = QUrl(value) if not self.__include: - self.__include.append(GreaseMonkeyUrlMatcher("*")) - - marker = "// ==/UserScript==" - index = fileData.find(marker) + len(marker) - self.__metaData = fileData[:index] - script = fileData[index:].strip() + self.__include.append("*") nspace = bytes(QCryptographicHash.hash( QByteArray(self.fullName().encode("utf-8")), QCryptographicHash.Md4).toHex()).decode("ascii") valuesScript = values_js.format(nspace) - self.__script = "(function(){{{0}\n{1}\n{2}\n}})();".format( - valuesScript, self.__manager.requireScripts(requireList), script + runCheck = """ + for (var value of {0}) {{ + var re = new RegExp(value); + if (re.test(window.location.href)) {{ + return; + }} + }} + __eric_includes = false; + for (var value of {1}) {{ + var re = new RegExp(value); + if (re.test(window.location.href)) {{ + __eric_includes = true; + break; + }} + }} + if (!__eric_includes) {{ + return; + }} + delete __eric_includes;""".format( + self.__toJavaScriptList(self.__exclude[:]), + self.__toJavaScriptList(self.__include[:]) + ) + self.__script = "(function(){{{0}\n{1}\n{2}\n{3}\n}})();".format( + runCheck, valuesScript, + self.__manager.requireScripts(requireList), fileData ) self.__valid = True @@ -369,15 +352,44 @@ @return prepared script object @rtype QWebEngineScript """ + if self.startAt() == GreaseMonkeyScript.DocumentStart: + injectionPoint = QWebEngineScript.DocumentCreation + elif self.startAt() == GreaseMonkeyScript.DocumentEnd: + injectionPoint = QWebEngineScript.DocumentReady + elif self.startAt() == GreaseMonkeyScript.DocumentIdle: + injectionPoint = QWebEngineScript.Deferred + else: + raise ValueError("Wrong script start point.") + script = QWebEngineScript() script.setName(self.fullName()) - if self.startAt() == GreaseMonkeyScript.DocumentStart: - script.setInjectionPoint(QWebEngineScript.DocumentCreation) - else: - script.setInjectionPoint(QWebEngineScript.DocumentReady) + script.setInjectionPoint(injectionPoint) script.setWorldId(QWebEngineScript.MainWorld) script.setRunsOnSubFrames(not self.__noFrames) - script.setSourceCode("{0}\n{1}\n{2}".format( - self.__metaData, bootstrap_js, self.__script + script.setSourceCode("{0}\n{1}".format( + bootstrap_js, self.__script )) return script + + def __toJavaScriptList(self, patterns): + """ + Private method to convert a list of str to a string containing a valid + JavaScript list definition. + + @param patterns list of match patterns + @type list of str + @return JavaScript script containing the list + @rtype str + """ + patternList = [] + for pattern in patterns: + if pattern.startswith("/") and pattern.endswith("/") and \ + len(pattern) > 1: + pattern = pattern[1:-1] + else: + pattern = pattern.replace(".", "\\.").replace("*", ".*") + pattern = "'{0}'".format(pattern) + patternList.append(pattern) + + script = "[{0}]".format(",".join(patternList)) + return script
--- a/WebBrowser/GreaseMonkey/GreaseMonkeyUrlMatcher.py Sat Mar 05 17:24:44 2016 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,114 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright (c) 2012 - 2016 Detlev Offenbach <detlev@die-offenbachs.de> -# - -""" -Module implementing the GreaseMonkey URL matcher. -""" - -from __future__ import unicode_literals - -import re - -from PyQt5.QtCore import Qt, QRegExp - - -def wildcardMatch(string, pattern): - """ - Module function implementing a special wildcard matcher. - - @param string string to match (string) - @param pattern pattern to be used (string) - @return flag indicating a successful match (boolean) - """ - stringSize = len(string) - - startsWithWildcard = pattern.startswith("*") - endsWithWildcard = pattern.endswith("*") - - parts = pattern.split("*") - pos = 0 - - if startsWithWildcard: - pos = string.find(parts[1]) - if pos == -1: - return False - - for part in parts: - pos = string.find(part, pos) - if pos == -1: - return False - - if not endsWithWildcard and stringSize - pos != len(parts[-1]): - return False - - return True - - -class GreaseMonkeyUrlMatcher(object): - """ - Class implementing the GreaseMonkey URL matcher. - """ - def __init__(self, pattern): - """ - Constructor - - @param pattern pattern to be used for the matching (string) - """ - self.__pattern = pattern - self.__matchString = "" - self.__regExp = QRegExp() - self.__useRegExp = False - - self.__parsePattern(self.__pattern) - - def pattern(self): - """ - Public method to get the match pattern. - - @return match pattern (string) - """ - return self.__pattern - - def match(self, urlString): - """ - Public method to match the given URL. - - @param urlString URL to match (string) - @return flag indicating a successful match (boolean) - """ - if self.__useRegExp: - return self.__regExp.indexIn(urlString) != -1 - else: - return wildcardMatch(urlString, self.__matchString) - - def __parsePattern(self, pattern): - """ - Private method to parse the match pattern. - - @param pattern match pattern to be used (string) - """ - if pattern.startswith("/") and pattern.endswith("/"): - pattern = pattern[1:-1] - - self.__regExp = QRegExp(pattern, Qt.CaseInsensitive) - self.__useRegExp = True - elif ".tld" in pattern: - # escape special symbols - pattern = re.sub(r"(\W)", r"\\\1", pattern) - # remove multiple wildcards - pattern = re.sub(r"\*+", "*", pattern) - # process anchor at expression start - pattern = re.sub(r"^\\\|", "^", pattern) - # process anchor at expression end - pattern = re.sub(r"\\\|$", "$", pattern) - # replace wildcards by .* - pattern = re.sub(r"\\\*", ".*", pattern) - # replace domain pattern - pattern = re.sub(r"\.tld", r"\.[a-z.]{2,6}") - - self.__useRegExp = True - self.__regExp = QRegExp(pattern, Qt.CaseInsensitive) - else: - self.__matchString = pattern
--- a/eric6.e4p Sat Mar 05 17:24:44 2016 +0100 +++ b/eric6.e4p Sat Mar 05 18:40:16 2016 +0100 @@ -1323,7 +1323,6 @@ <Source>WebBrowser/GreaseMonkey/GreaseMonkeyManager.py</Source> <Source>WebBrowser/GreaseMonkey/GreaseMonkeyScript.py</Source> <Source>WebBrowser/GreaseMonkey/GreaseMonkeyUrlInterceptor.py</Source> - <Source>WebBrowser/GreaseMonkey/GreaseMonkeyUrlMatcher.py</Source> <Source>WebBrowser/GreaseMonkey/__init__.py</Source> <Source>WebBrowser/History/HistoryCompleter.py</Source> <Source>WebBrowser/History/HistoryDialog.py</Source>