diff --git a/qutebrowser/browser/greasemonkey.py b/qutebrowser/browser/greasemonkey.py index 669b9d0bc..9a82d6a93 100644 --- a/qutebrowser/browser/greasemonkey.py +++ b/qutebrowser/browser/greasemonkey.py @@ -17,7 +17,7 @@ # You should have received a copy of the GNU General Public License # along with qutebrowser. If not, see <http://www.gnu.org/licenses/>. -"""Load, parse and make avalaible greasemonkey scripts.""" +"""Load, parse and make available Greasemonkey scripts.""" import re import os @@ -39,6 +39,7 @@ def _scripts_dir(): class GreasemonkeyScript: + """Container class for userscripts, parses metadata blocks.""" def __init__(self, properties, code): @@ -72,15 +73,15 @@ class GreasemonkeyScript: @classmethod def parse(cls, source): - """GreaseMonkeyScript factory. + """GreasemonkeyScript factory. - Takes a userscript source and returns a GreaseMonkeyScript. - Parses the greasemonkey metadata block, if present, to fill out + Takes a userscript source and returns a GreasemonkeyScript. + Parses the Greasemonkey metadata block, if present, to fill out attributes. """ matches = re.split(cls.HEADER_REGEX, source, maxsplit=2) try: - _, props, _code = matches + _head, props, _code = matches except ValueError: props = "" script = cls(re.findall(cls.PROPS_REGEX, props), source) @@ -90,9 +91,9 @@ class GreasemonkeyScript: return script def code(self): - """Return the processed javascript code of this script. + """Return the processed JavaScript code of this script. - Adorns the source code with GM_* methods for greasemonkey + Adorns the source code with GM_* methods for Greasemonkey compatibility and wraps it in an IFFE to hide it within a lexical scope. Note that this means line numbers in your browser's debugger/inspector will not match up to the line @@ -118,6 +119,7 @@ class GreasemonkeyScript: @attr.s class MatchingScripts(object): + """All userscripts registered to run on a particular url.""" url = attr.ib() @@ -128,11 +130,11 @@ class MatchingScripts(object): class GreasemonkeyManager(QObject): - """Manager of userscripts and a greasemonkey compatible environment. + """Manager of userscripts and a Greasemonkey compatible environment. Signals: scripts_reloaded: Emitted when scripts are reloaded from disk. - Any any cached or already-injected scripts should be + Any cached or already-injected scripts should be considered obselete. """ @@ -151,8 +153,8 @@ class GreasemonkeyManager(QObject): def load_scripts(self): """Re-read Greasemonkey scripts from disk. - The scripts are read from a 'greasemonkey' subdirectory in qutebrowser's - data directory (see `:version`). + The scripts are read from a 'greasemonkey' subdirectory in + qutebrowser's data directory (see `:version`). """ self._run_start = [] self._run_end = [] diff --git a/qutebrowser/browser/webengine/webenginesettings.py b/qutebrowser/browser/webengine/webenginesettings.py index dade671c8..c2c388993 100644 --- a/qutebrowser/browser/webengine/webenginesettings.py +++ b/qutebrowser/browser/webengine/webenginesettings.py @@ -245,10 +245,10 @@ def _init_profiles(): def inject_userscripts(): - """Register user javascript files with the global profiles.""" - # The greasemonkey metadata block support in qtwebengine only starts at 5.8 - # Otherwise have to handle injecting the scripts into the page at very - # early load, probs same place in view as the enableJS check. + """Register user JavaScript files with the global profiles.""" + # The Greasemonkey metadata block support in QtWebEngine only starts at + # Qt 5.8. With 5.7.1, we need to inject the scripts ourselves in response + # to urlChanged. if not qtutils.version_check('5.8'): return @@ -256,10 +256,7 @@ def inject_userscripts(): # just get replaced by new gm scripts like if we were injecting them # ourselves so we need to remove all gm scripts, while not removing # any other stuff that might have been added. Like the one for - # stylsheets. - # Could either use a different world for gm scripts, check for gm metadata - # values (would mean no non-gm userscripts), or check the code for - # _qute_script_id + # stylesheets. for profile in [default_profile, private_profile]: scripts = profile.scripts() for script in scripts.toList(): diff --git a/qutebrowser/browser/webengine/webview.py b/qutebrowser/browser/webengine/webview.py index af4476d4a..0668e3aa5 100644 --- a/qutebrowser/browser/webengine/webview.py +++ b/qutebrowser/browser/webengine/webview.py @@ -308,7 +308,7 @@ class WebEnginePage(QWebEnginePage): def _inject_userjs(self, url): """Inject userscripts registered for `url` into the current page.""" if qtutils.version_check('5.8'): - # Handled in webenginetab with the builtin greasemonkey + # Handled in webenginetab with the builtin Greasemonkey # support. return diff --git a/qutebrowser/browser/webkit/webpage.py b/qutebrowser/browser/webkit/webpage.py index 02aa270d7..89407fcdf 100644 --- a/qutebrowser/browser/webkit/webpage.py +++ b/qutebrowser/browser/webkit/webpage.py @@ -95,7 +95,7 @@ class BrowserPage(QWebPage): """Connect userjs related signals to `frame`. Connect the signals used as triggers for injecting user - javascripts into the passed QWebFrame. + JavaScripts into the passed QWebFrame. """ log.greasemonkey.debug("Connecting to frame {} ({})" .format(frame, frame.url().toDisplayString())) @@ -299,7 +299,7 @@ class BrowserPage(QWebPage): self.error_occurred = False def _inject_userjs(self, frame): - """Inject user javascripts into the page. + """Inject user JavaScripts into the page. Args: frame: The QWebFrame to inject the user scripts into. diff --git a/qutebrowser/javascript/greasemonkey_wrapper.js b/qutebrowser/javascript/greasemonkey_wrapper.js index e86991040..2d36220dc 100644 --- a/qutebrowser/javascript/greasemonkey_wrapper.js +++ b/qutebrowser/javascript/greasemonkey_wrapper.js @@ -1,5 +1,5 @@ -(function () { - const _qute_script_id = "__gm_"+{{ scriptName | tojson }}; +(function() { + const _qute_script_id = "__gm_" + {{ scriptName | tojson }}; function GM_log(text) { console.log(text); @@ -10,7 +10,8 @@ 'scriptMetaStr': {{ scriptMeta | tojson }}, 'scriptWillUpdate': false, 'version': "0.0.1", - 'scriptHandler': 'Tampermonkey' // so scripts don't expect exportFunction + // so scripts don't expect exportFunction + 'scriptHandler': 'Tampermonkey', }; function checkKey(key, funcName) { @@ -40,7 +41,7 @@ } function GM_listValues() { - let keys = []; + const keys = []; for (let i = 0; i < localStorage.length; i++) { if (localStorage.key(i).startsWith(_qute_script_id)) { keys.push(localStorage.key(i).slice(_qute_script_id.length)); @@ -59,28 +60,28 @@ details.method = details.method ? details.method.toUpperCase() : "GET"; if (!details.url) { - throw ("GM_xmlhttpRequest requires an URL."); + throw new Error("GM_xmlhttpRequest requires an URL."); } // build XMLHttpRequest object - let oXhr = new XMLHttpRequest(); + const oXhr = new XMLHttpRequest(); // run it if ("onreadystatechange" in details) { - oXhr.onreadystatechange = function () { + oXhr.onreadystatechange = function() { details.onreadystatechange(oXhr); }; } if ("onload" in details) { - oXhr.onload = function () { details.onload(oXhr) }; + oXhr.onload = function() { details.onload(oXhr); }; } if ("onerror" in details) { - oXhr.onerror = function () { details.onerror(oXhr) }; + oXhr.onerror = function () { details.onerror(oXhr); }; } oXhr.open(details.method, details.url, true); if ("headers" in details) { - for (let header in details.headers) { + for (const header in details.headers) { oXhr.setRequestHeader(header, details.headers[header]); } } @@ -93,26 +94,25 @@ } function GM_addStyle(/* String */ styles) { - let oStyle = document.createElement("style"); + const oStyle = document.createElement("style"); oStyle.setAttribute("type", "text/css"); oStyle.appendChild(document.createTextNode(styles)); - let head = document.getElementsByTagName("head")[0]; + const head = document.getElementsByTagName("head")[0]; if (head === undefined) { - document.onreadystatechange = function () { - if (document.readyState == "interactive") { + document.onreadystatechange = function() { + if (document.readyState === "interactive") { document.getElementsByTagName("head")[0].appendChild(oStyle); } - } - } - else { + }; + } else { head.appendChild(oStyle); } } const unsafeWindow = window; - //====== The actual user script source ======// + // ====== The actual user script source ====== // {{ scriptSource }} - //====== End User Script ======// + // ====== End User Script ====== // })(); diff --git a/tests/end2end/features/javascript.feature b/tests/end2end/features/javascript.feature index 944d2606d..3ccd50efb 100644 --- a/tests/end2end/features/javascript.feature +++ b/tests/end2end/features/javascript.feature @@ -124,8 +124,8 @@ Feature: Javascript stuff And I run :tab-next Then the window sizes should be the same - Scenario: Have a greasemonkey script run at page start - When I have a greasemonkey file saved for document-start with noframes unset + Scenario: Have a GreaseMonkey script run at page start + When I have a GreaseMonkey file saved for document-start with noframes unset And I run :greasemonkey-reload And I open data/hints/iframe.html # This second reload is required in webengine < 5.8 for scripts @@ -133,15 +133,15 @@ Feature: Javascript stuff And I run :reload Then the javascript message "Script is running on /data/hints/iframe.html" should be logged - Scenario: Have a greasemonkey script running on frames - When I have a greasemonkey file saved for document-end with noframes unset + Scenario: Have a GreaseMonkey script running on frames + When I have a GreaseMonkey file saved for document-end with noframes unset And I run :greasemonkey-reload And I open data/hints/iframe.html Then the javascript message "Script is running on /data/hints/html/wrapped.html" should be logged @flaky - Scenario: Have a greasemonkey script running on noframes - When I have a greasemonkey file saved for document-end with noframes set + Scenario: Have a GreaseMonkey script running on noframes + When I have a GreaseMonkey file saved for document-end with noframes set And I run :greasemonkey-reload And I open data/hints/iframe.html Then the javascript message "Script is running on /data/hints/html/wrapped.html" should not be logged diff --git a/tests/end2end/features/test_javascript_bdd.py b/tests/end2end/features/test_javascript_bdd.py index 16896d4b5..8f69ef6d4 100644 --- a/tests/end2end/features/test_javascript_bdd.py +++ b/tests/end2end/features/test_javascript_bdd.py @@ -35,7 +35,7 @@ def check_window_sizes(quteproc): test_gm_script = r""" // ==UserScript== -// @name Qutebrowser test userscript +// @name qutebrowser test userscript // @namespace invalid.org // @include http://localhost:*/data/hints/iframe.html // @include http://localhost:*/data/hints/html/wrapped.html @@ -47,7 +47,7 @@ console.log("Script is running on " + window.location.pathname); """ -@bdd.when(bdd.parsers.parse("I have a greasemonkey file saved for {stage} " +@bdd.when(bdd.parsers.parse("I have a GreaseMonkey file saved for {stage} " "with noframes {frameset}")) def create_greasemonkey_file(quteproc, stage, frameset): script_path = os.path.join(quteproc.basedir, 'data', 'greasemonkey') diff --git a/tests/unit/javascript/test_greasemonkey.py b/tests/unit/javascript/test_greasemonkey.py index b0ba64bdf..670be416d 100644 --- a/tests/unit/javascript/test_greasemonkey.py +++ b/tests/unit/javascript/test_greasemonkey.py @@ -28,7 +28,7 @@ from qutebrowser.browser import greasemonkey test_gm_script = """ // ==UserScript== -// @name Qutebrowser test userscript +// @name qutebrowser test userscript // @namespace invalid.org // @include http://localhost:*/data/title.html // @match http://trolol* @@ -58,7 +58,7 @@ def test_all(): gm_manager = greasemonkey.GreasemonkeyManager() assert (gm_manager.all_scripts()[0].name == - "Qutebrowser test userscript") + "qutebrowser test userscript") @pytest.mark.parametrize("url, expected_matches", [ @@ -70,7 +70,7 @@ def test_all(): ('https://badhost.xxx/', 0), ]) def test_get_scripts_by_url(url, expected_matches): - """Check greasemonkey include/exclude rules work.""" + """Check Greasemonkey include/exclude rules work.""" save_script(test_gm_script, 'test.user.js') gm_manager = greasemonkey.GreasemonkeyManager()