Greasemonkey: use UrlPatterns for match directives

The greasemonkey `@match` directive is used to match urls against
chromium url patterns (as opposed to `@include` which treats its
argument as a glob expression). I was using fnmatch for both here
because I am lazy and knew someone else was going to implement chromium
url patterns for me eventually. Now it is done and I should switch to
using them instead. The most common failing case that this will fix is
something matching on `*://*.domain.com/*` because it wouldn't match
the url with no subdomain.

This codepath is only used on webengine 5.7.1 and webkit backends.
This commit is contained in:
Jimmy 2018-04-03 20:29:31 +12:00
parent 0829511221
commit c5334fb683
2 changed files with 14 additions and 6 deletions

View File

@ -32,6 +32,7 @@ from PyQt5.QtCore import pyqtSignal, QObject, QUrl
from qutebrowser.utils import (log, standarddir, jinja, objreg, utils, from qutebrowser.utils import (log, standarddir, jinja, objreg, utils,
javascript) javascript)
from qutebrowser.utils.urlmatch import UrlPattern
from qutebrowser.commands import cmdutils from qutebrowser.commands import cmdutils
from qutebrowser.browser import downloads from qutebrowser.browser import downloads
@ -48,6 +49,7 @@ class GreasemonkeyScript:
def __init__(self, properties, code): def __init__(self, properties, code):
self._code = code self._code = code
self.includes = [] self.includes = []
self.matches = []
self.excludes = [] self.excludes = []
self.requires = [] self.requires = []
self.description = None self.description = None
@ -63,8 +65,10 @@ class GreasemonkeyScript:
self.namespace = value self.namespace = value
elif name == 'description': elif name == 'description':
self.description = value self.description = value
elif name in ['include', 'match']: elif name == 'include':
self.includes.append(value) self.includes.append(value)
elif name == 'match':
self.matches.append(value)
elif name in ['exclude', 'exclude_match']: elif name in ['exclude', 'exclude_match']:
self.excludes.append(value) self.excludes.append(value)
elif name == 'run-at': elif name == 'run-at':
@ -92,7 +96,7 @@ class GreasemonkeyScript:
props = "" props = ""
script = cls(re.findall(cls.PROPS_REGEX, props), source) script = cls(re.findall(cls.PROPS_REGEX, props), source)
script.script_meta = props script.script_meta = props
if not script.includes: if not script.includes and not script.matches:
script.includes = ['*'] script.includes = ['*']
return script return script
@ -117,7 +121,7 @@ class GreasemonkeyScript:
return json.dumps({ return json.dumps({
'name': self.name, 'name': self.name,
'description': self.description, 'description': self.description,
'matches': self.includes, 'matches': self.matches,
'includes': self.includes, 'includes': self.includes,
'excludes': self.excludes, 'excludes': self.excludes,
'run-at': self.run_at, 'run-at': self.run_at,
@ -324,8 +328,12 @@ class GreasemonkeyManager(QObject):
# Otherwise they are glob expressions. # Otherwise they are glob expressions.
return fnmatch.fnmatch(string_url, pattern) return fnmatch.fnmatch(string_url, pattern)
def _chromium_match(pattern):
return UrlPattern(pattern).matches(url)
tester = (lambda script: tester = (lambda script:
any(_match(pat) for pat in script.includes) and (any(_match(pat) for pat in script.includes) or
any(_chromium_match(pat) for pat in script.matches)) and
not any(_match(pat) for pat in script.excludes)) not any(_match(pat) for pat in script.excludes))
return MatchingScripts( return MatchingScripts(

View File

@ -32,7 +32,7 @@ test_gm_script = r"""
// @name qutebrowser test userscript // @name qutebrowser test userscript
// @namespace invalid.org // @namespace invalid.org
// @include http://localhost:*/data/title.html // @include http://localhost:*/data/title.html
// @match http://trolol* // @match http://*.trolol.com/*
// @exclude https://badhost.xxx/* // @exclude https://badhost.xxx/*
// @run-at document-start // @run-at document-start
// ==/UserScript== // ==/UserScript==
@ -60,7 +60,7 @@ def test_all():
@pytest.mark.parametrize("url, expected_matches", [ @pytest.mark.parametrize("url, expected_matches", [
# included # included
('http://trololololololo.com/', 1), ('http://trolol.com/', 1),
# neither included nor excluded # neither included nor excluded
('http://aaaaaaaaaa.com/', 0), ('http://aaaaaaaaaa.com/', 0),
# excluded # excluded