This commit is contained in:
Florian Bruhin 2017-12-06 11:50:59 +01:00
parent dd63508be7
commit 2633dcc0d5
8 changed files with 51 additions and 52 deletions

View File

@ -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 = []

View File

@ -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():

View File

@ -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

View File

@ -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.

View File

@ -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 ====== //
})();

View File

@ -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

View File

@ -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')

View File

@ -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()