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 qutebrowser.utils import (log, standarddir, jinja, objreg, utils,
|
||||
javascript, urlmatch, version, usertypes)
|
||||
javascript, urlmatch, version, usertypes,
|
||||
qtutils)
|
||||
from qutebrowser.api import cmdutils
|
||||
from qutebrowser.browser import downloads
|
||||
from qutebrowser.misc import objects
|
||||
@ -116,6 +117,40 @@ class GreasemonkeyScript:
|
||||
script.includes = ['*']
|
||||
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):
|
||||
"""Return the processed JavaScript code of this script.
|
||||
|
||||
|
@ -1038,9 +1038,15 @@ class _WebEngineScripts(QObject):
|
||||
new_script.setSourceCode(script.code())
|
||||
new_script.setName("GM-{}".format(script.name))
|
||||
new_script.setRunsOnSubFrames(script.runs_on_sub_frames)
|
||||
|
||||
# Override the @run-at value parsed by QWebEngineScript if desired.
|
||||
if 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: {}'
|
||||
.format(new_script.name()))
|
||||
page_scripts.insert(new_script)
|
||||
|
@ -25,8 +25,10 @@ import pytest
|
||||
QtWebEngineWidgets = pytest.importorskip("PyQt5.QtWebEngineWidgets")
|
||||
QWebEnginePage = QtWebEngineWidgets.QWebEnginePage
|
||||
QWebEngineScriptCollection = QtWebEngineWidgets.QWebEngineScriptCollection
|
||||
QWebEngineScript = QtWebEngineWidgets.QWebEngineScript
|
||||
|
||||
from qutebrowser.browser import greasemonkey
|
||||
from qutebrowser.utils import usertypes
|
||||
|
||||
pytestmark = pytest.mark.usefixtures('greasemonkey_manager')
|
||||
|
||||
@ -91,3 +93,26 @@ class TestWebengineScripts:
|
||||
|
||||
collection = webengine_scripts._widget.page().scripts()
|
||||
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
|
||||
from PyQt5.QtCore import QUrl
|
||||
|
||||
from qutebrowser.utils import usertypes
|
||||
from qutebrowser.browser import greasemonkey
|
||||
|
||||
test_gm_script = r"""
|
||||
@ -165,6 +166,56 @@ def test_utf8_bom():
|
||||
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):
|
||||
test_require_script = textwrap.dedent("""
|
||||
// ==UserScript==
|
||||
|
Loading…
Reference in New Issue
Block a user