Merge branch 'greasemonkey-quirks'
This commit is contained in:
commit
94542c5f78
@ -31,7 +31,8 @@ import attr
|
|||||||
from PyQt5.QtCore import pyqtSignal, QObject, QUrl
|
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, urlmatch, version, usertypes)
|
javascript, urlmatch, version, usertypes,
|
||||||
|
qtutils)
|
||||||
from qutebrowser.api import cmdutils
|
from qutebrowser.api import cmdutils
|
||||||
from qutebrowser.browser import downloads
|
from qutebrowser.browser import downloads
|
||||||
from qutebrowser.misc import objects
|
from qutebrowser.misc import objects
|
||||||
@ -116,6 +117,40 @@ class GreasemonkeyScript:
|
|||||||
script.includes = ['*']
|
script.includes = ['*']
|
||||||
return script
|
return script
|
||||||
|
|
||||||
|
def force_document_end(self):
|
||||||
|
"""Check whether to force @run-at document-end.
|
||||||
|
|
||||||
|
This needs to be done on QtWebEngine with Qt 5.12 for known-broken
|
||||||
|
scripts.
|
||||||
|
|
||||||
|
On Qt 5.12, accessing the DOM isn't possible with "@run-at
|
||||||
|
document-start". It was documented to be impossible before, but seems
|
||||||
|
to work fine.
|
||||||
|
|
||||||
|
However, some scripts do DOM access with "@run-at document-start". Fix
|
||||||
|
those by forcing them to use document-end instead.
|
||||||
|
"""
|
||||||
|
if objects.backend != usertypes.Backend.QtWebEngine:
|
||||||
|
return False
|
||||||
|
elif not qtutils.version_check('5.12', compiled=False):
|
||||||
|
return False
|
||||||
|
|
||||||
|
broken_scripts = [
|
||||||
|
('http://userstyles.org', None),
|
||||||
|
('https://github.com/ParticleCore', 'Iridium'),
|
||||||
|
]
|
||||||
|
return any(self._matches_id(namespace=namespace, name=name)
|
||||||
|
for namespace, name in broken_scripts)
|
||||||
|
|
||||||
|
def _matches_id(self, *, namespace, name):
|
||||||
|
"""Check if this script matches the given namespace/name.
|
||||||
|
|
||||||
|
Both namespace and name can be None in order to match any script.
|
||||||
|
"""
|
||||||
|
matches_namespace = namespace is None or self.namespace == namespace
|
||||||
|
matches_name = name is None or self.name == name
|
||||||
|
return matches_namespace and matches_name
|
||||||
|
|
||||||
def code(self):
|
def code(self):
|
||||||
"""Return the processed JavaScript code of this script.
|
"""Return the processed JavaScript code of this script.
|
||||||
|
|
||||||
|
@ -1038,9 +1038,15 @@ class _WebEngineScripts(QObject):
|
|||||||
new_script.setSourceCode(script.code())
|
new_script.setSourceCode(script.code())
|
||||||
new_script.setName("GM-{}".format(script.name))
|
new_script.setName("GM-{}".format(script.name))
|
||||||
new_script.setRunsOnSubFrames(script.runs_on_sub_frames)
|
new_script.setRunsOnSubFrames(script.runs_on_sub_frames)
|
||||||
|
|
||||||
# Override the @run-at value parsed by QWebEngineScript if desired.
|
# Override the @run-at value parsed by QWebEngineScript if desired.
|
||||||
if injection_point:
|
if injection_point:
|
||||||
new_script.setInjectionPoint(injection_point)
|
new_script.setInjectionPoint(injection_point)
|
||||||
|
elif script.force_document_end():
|
||||||
|
log.greasemonkey.debug("Forcing @run-at document-end for {}"
|
||||||
|
.format(script.name))
|
||||||
|
new_script.setInjectionPoint(QWebEngineScript.DocumentReady)
|
||||||
|
|
||||||
log.greasemonkey.debug('adding script: {}'
|
log.greasemonkey.debug('adding script: {}'
|
||||||
.format(new_script.name()))
|
.format(new_script.name()))
|
||||||
page_scripts.insert(new_script)
|
page_scripts.insert(new_script)
|
||||||
|
@ -25,8 +25,10 @@ import pytest
|
|||||||
QtWebEngineWidgets = pytest.importorskip("PyQt5.QtWebEngineWidgets")
|
QtWebEngineWidgets = pytest.importorskip("PyQt5.QtWebEngineWidgets")
|
||||||
QWebEnginePage = QtWebEngineWidgets.QWebEnginePage
|
QWebEnginePage = QtWebEngineWidgets.QWebEnginePage
|
||||||
QWebEngineScriptCollection = QtWebEngineWidgets.QWebEngineScriptCollection
|
QWebEngineScriptCollection = QtWebEngineWidgets.QWebEngineScriptCollection
|
||||||
|
QWebEngineScript = QtWebEngineWidgets.QWebEngineScript
|
||||||
|
|
||||||
from qutebrowser.browser import greasemonkey
|
from qutebrowser.browser import greasemonkey
|
||||||
|
from qutebrowser.utils import usertypes
|
||||||
|
|
||||||
pytestmark = pytest.mark.usefixtures('greasemonkey_manager')
|
pytestmark = pytest.mark.usefixtures('greasemonkey_manager')
|
||||||
|
|
||||||
@ -91,3 +93,26 @@ class TestWebengineScripts:
|
|||||||
|
|
||||||
collection = webengine_scripts._widget.page().scripts()
|
collection = webengine_scripts._widget.page().scripts()
|
||||||
assert collection.toList()[-1].worldId() == worldid
|
assert collection.toList()[-1].worldId() == worldid
|
||||||
|
|
||||||
|
def test_greasemonkey_force_document_end(self, monkeypatch,
|
||||||
|
webengine_scripts):
|
||||||
|
"""Make sure document-end is forced when needed."""
|
||||||
|
monkeypatch.setattr(greasemonkey.objects, 'backend',
|
||||||
|
usertypes.Backend.QtWebEngine)
|
||||||
|
monkeypatch.setattr(greasemonkey.qtutils, 'version_check',
|
||||||
|
lambda version, exact=False, compiled=True:
|
||||||
|
True)
|
||||||
|
|
||||||
|
scripts = [
|
||||||
|
greasemonkey.GreasemonkeyScript([
|
||||||
|
('name', 'Iridium'),
|
||||||
|
('namespace', 'https://github.com/ParticleCore'),
|
||||||
|
('run-at', 'document-start'),
|
||||||
|
], None)
|
||||||
|
]
|
||||||
|
|
||||||
|
webengine_scripts._inject_greasemonkey_scripts(scripts)
|
||||||
|
|
||||||
|
collection = webengine_scripts._widget.page().scripts()
|
||||||
|
script = collection.toList()[-1]
|
||||||
|
assert script.injectionPoint() == QWebEngineScript.DocumentReady
|
||||||
|
@ -25,6 +25,7 @@ import pytest
|
|||||||
import py.path # pylint: disable=no-name-in-module
|
import py.path # pylint: disable=no-name-in-module
|
||||||
from PyQt5.QtCore import QUrl
|
from PyQt5.QtCore import QUrl
|
||||||
|
|
||||||
|
from qutebrowser.utils import usertypes
|
||||||
from qutebrowser.browser import greasemonkey
|
from qutebrowser.browser import greasemonkey
|
||||||
|
|
||||||
test_gm_script = r"""
|
test_gm_script = r"""
|
||||||
@ -165,6 +166,56 @@ def test_utf8_bom():
|
|||||||
assert '// ==UserScript==' in script.code().splitlines()
|
assert '// ==UserScript==' in script.code().splitlines()
|
||||||
|
|
||||||
|
|
||||||
|
class TestForceDocumentEnd:
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def patch(self, monkeypatch):
|
||||||
|
def _patch(*, backend, qt_512):
|
||||||
|
monkeypatch.setattr(greasemonkey.objects, 'backend', backend)
|
||||||
|
monkeypatch.setattr(greasemonkey.qtutils, 'version_check',
|
||||||
|
lambda version, exact=False, compiled=True:
|
||||||
|
qt_512)
|
||||||
|
return _patch
|
||||||
|
|
||||||
|
def _get_script(self, *, namespace, name):
|
||||||
|
source = textwrap.dedent("""
|
||||||
|
// ==UserScript==
|
||||||
|
// @namespace {}
|
||||||
|
// @name {}
|
||||||
|
// ==/UserScript==
|
||||||
|
""".format(namespace, name))
|
||||||
|
_save_script(source, 'force.user.js')
|
||||||
|
|
||||||
|
gm_manager = greasemonkey.GreasemonkeyManager()
|
||||||
|
|
||||||
|
scripts = gm_manager.all_scripts()
|
||||||
|
assert len(scripts) == 1
|
||||||
|
return scripts[0]
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('backend, qt_512', [
|
||||||
|
(usertypes.Backend.QtWebKit, True),
|
||||||
|
(usertypes.Backend.QtWebEngine, False),
|
||||||
|
])
|
||||||
|
def test_not_applicable(self, patch, backend, qt_512):
|
||||||
|
"""Test backend/Qt version combinations which don't need a fix."""
|
||||||
|
patch(backend=backend, qt_512=qt_512)
|
||||||
|
script = self._get_script(namespace='https://github.com/ParticleCore',
|
||||||
|
name='Iridium')
|
||||||
|
assert not script.force_document_end()
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('namespace, name, force', [
|
||||||
|
('http://userstyles.org', 'foobar', True),
|
||||||
|
('https://github.com/ParticleCore', 'Iridium', True),
|
||||||
|
('https://github.com/ParticleCore', 'Foo', False),
|
||||||
|
('https://example.org', 'Iridium', False),
|
||||||
|
])
|
||||||
|
def test_matching(self, patch, namespace, name, force):
|
||||||
|
"""Test matching based on namespace/name."""
|
||||||
|
patch(backend=usertypes.Backend.QtWebEngine, qt_512=True)
|
||||||
|
script = self._get_script(namespace=namespace, name=name)
|
||||||
|
assert script.force_document_end() == force
|
||||||
|
|
||||||
|
|
||||||
def test_required_scripts_are_included(download_stub, tmpdir):
|
def test_required_scripts_are_included(download_stub, tmpdir):
|
||||||
test_require_script = textwrap.dedent("""
|
test_require_script = textwrap.dedent("""
|
||||||
// ==UserScript==
|
// ==UserScript==
|
||||||
|
Loading…
Reference in New Issue
Block a user