Merge remote-tracking branch 'origin/pr/4017'

This commit is contained in:
Florian Bruhin 2018-06-26 10:37:17 +02:00
commit 61da5d0c7c
3 changed files with 78 additions and 72 deletions

View File

@ -58,6 +58,7 @@ class GreasemonkeyScript:
self.run_at = None self.run_at = None
self.script_meta = None self.script_meta = None
self.runs_on_sub_frames = True self.runs_on_sub_frames = True
self.jsworld = "main"
for name, value in properties: for name, value in properties:
if name == 'name': if name == 'name':
self.name = value self.name = value
@ -77,6 +78,8 @@ class GreasemonkeyScript:
self.runs_on_sub_frames = False self.runs_on_sub_frames = False
elif name == 'require': elif name == 'require':
self.requires.append(value) self.requires.append(value)
elif name == 'qute-js-world':
self.jsworld = value
HEADER_REGEX = r'// ==UserScript==|\n+// ==/UserScript==\n' HEADER_REGEX = r'// ==UserScript==|\n+// ==/UserScript==\n'
PROPS_REGEX = r'// @(?P<prop>[^\s]+)\s*(?P<val>.*)' PROPS_REGEX = r'// @(?P<prop>[^\s]+)\s*(?P<val>.*)'

View File

@ -853,9 +853,17 @@ class _WebEngineScripts(QObject):
self._inject_early_js('js', js_code, subframes=True) self._inject_early_js('js', js_code, subframes=True)
self._init_stylesheet() self._init_stylesheet()
greasemonkey = objreg.get('greasemonkey') # The Greasemonkey metadata block support in QtWebEngine only starts at
greasemonkey.scripts_reloaded.connect(self._inject_userscripts) # Qt 5.8. With 5.7.1, we need to inject the scripts ourselves in
self._inject_userscripts() # response to urlChanged.
if not qtutils.version_check('5.8'):
self._widget.page().urlChanged.connect(
self._inject_greasemonkey_scripts_for_url)
else:
greasemonkey = objreg.get('greasemonkey')
greasemonkey.scripts_reloaded.connect(
self._inject_all_greasemonkey_scripts)
self._inject_all_greasemonkey_scripts()
def _init_stylesheet(self): def _init_stylesheet(self):
"""Initialize custom stylesheets. """Initialize custom stylesheets.
@ -872,40 +880,77 @@ class _WebEngineScripts(QObject):
) )
self._inject_early_js('stylesheet', js_code, subframes=True) self._inject_early_js('stylesheet', js_code, subframes=True)
def _inject_userscripts(self): def _inject_greasemonkey_scripts_for_url(self, url):
"""Register user JavaScript files with the global profiles.""" greasemonkey = objreg.get('greasemonkey')
# The Greasemonkey metadata block support in QtWebEngine only starts at matching_scripts = greasemonkey.scripts_for(url)
# Qt 5.8. With 5.7.1, we need to inject the scripts ourselves in self._inject_greasemonkey_scripts(
# response to urlChanged. matching_scripts.start, QWebEngineScript.DocumentCreation, True)
if not qtutils.version_check('5.8'): self._inject_greasemonkey_scripts(
matching_scripts.end, QWebEngineScript.DocumentReady, False)
self._inject_greasemonkey_scripts(
matching_scripts.idle, QWebEngineScript.Deferred, False)
def _inject_all_greasemonkey_scripts(self):
greasemonkey = objreg.get('greasemonkey')
scripts = greasemonkey.all_scripts()
self._inject_greasemonkey_scripts(scripts)
def _inject_greasemonkey_scripts(self, scripts=None, injection_point=None,
remove_first=True):
"""Register user JavaScript files with the current tab.
Args:
scripts: A list of GreasemonkeyScripts, or None to add all
known by the Greasemonkey subsystem.
injection_point: The QWebEngineScript::InjectionPoint stage
to inject the script into, None to use
auto-detection.
remove_first: Whether to remove all previously injected
scripts before adding these ones.
"""
if sip.isdeleted(self._widget):
return return
# Since we are inserting scripts into profile.scripts they won't # Since we are inserting scripts into a per-tab collection,
# just get replaced by new gm scripts like if we were injecting them # rather than just injecting scripts on page load, we need to
# ourselves so we need to remove all gm scripts, while not removing # make sure we replace existing scripts, not just add new ones.
# any other stuff that might have been added. Like the one for # While, taking care not to remove any other scripts that might
# stylesheets. # have been added elsewhere, like the one for stylesheets.
greasemonkey = objreg.get('greasemonkey') page_scripts = self._widget.page().scripts()
scripts = self._widget.page().scripts() if remove_first:
for script in scripts.toList(): for script in page_scripts.toList():
if script.name().startswith("GM-"): if script.name().startswith("GM-"):
log.greasemonkey.debug('Removing script: {}' log.greasemonkey.debug('Removing script: {}'
.format(script.name())) .format(script.name()))
removed = scripts.remove(script) removed = page_scripts.remove(script)
assert removed, script.name() assert removed, script.name()
# Then add the new scripts. if not scripts:
for script in greasemonkey.all_scripts(): return
# @run-at (and @include/@exclude/@match) is parsed by
# QWebEngineScript. for script in scripts:
new_script = QWebEngineScript() new_script = QWebEngineScript()
new_script.setWorldId(QWebEngineScript.MainWorld) try:
world = int(script.jsworld)
except ValueError:
try:
world = _JS_WORLD_MAP[usertypes.JsWorld[
script.jsworld.lower()]]
except KeyError:
log.greasemonkey.error(
"script {} has invalid value for '@qute-js-world'"
": {}".format(script.name, script.jsworld))
continue
new_script.setWorldId(world)
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.
if injection_point:
new_script.setInjectionPoint(injection_point)
log.greasemonkey.debug('adding script: {}' log.greasemonkey.debug('adding script: {}'
.format(new_script.name())) .format(new_script.name()))
scripts.insert(new_script) page_scripts.insert(new_script)
class WebEngineTab(browsertab.AbstractTab): class WebEngineTab(browsertab.AbstractTab):

View File

@ -20,11 +20,10 @@
"""The main browser widget for QtWebEngine.""" """The main browser widget for QtWebEngine."""
import sip import sip
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QUrl, PYQT_VERSION from PyQt5.QtCore import pyqtSignal, QUrl, PYQT_VERSION
from PyQt5.QtGui import QPalette from PyQt5.QtGui import QPalette
from PyQt5.QtWidgets import QWidget from PyQt5.QtWidgets import QWidget
from PyQt5.QtWebEngineWidgets import (QWebEngineView, QWebEnginePage, from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEnginePage
QWebEngineScript)
from qutebrowser.browser import shared from qutebrowser.browser import shared
from qutebrowser.browser.webengine import webenginesettings, certificateerror from qutebrowser.browser.webengine import webenginesettings, certificateerror
@ -168,7 +167,6 @@ class WebEnginePage(QWebEnginePage):
self._theme_color = theme_color self._theme_color = theme_color
self._set_bg_color() self._set_bg_color()
config.instance.changed.connect(self._set_bg_color) config.instance.changed.connect(self._set_bg_color)
self.urlChanged.connect(self._inject_userjs)
@config.change_filter('colors.webpage.bg') @config.change_filter('colors.webpage.bg')
def _set_bg_color(self): def _set_bg_color(self):
@ -263,43 +261,3 @@ class WebEnginePage(QWebEnginePage):
is_main_frame=is_main_frame) is_main_frame=is_main_frame)
self.navigation_request.emit(navigation) self.navigation_request.emit(navigation)
return navigation.accepted return navigation.accepted
@pyqtSlot('QUrl')
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
# support.
return
# Using QWebEnginePage.scripts() to hold the user scripts means
# we don't have to worry ourselves about where to inject the
# page but also means scripts hang around for the tab lifecycle.
# So clear them here.
scripts = self.scripts()
for script in scripts.toList():
if script.name().startswith("GM-"):
log.greasemonkey.debug("Removing script: {}"
.format(script.name()))
removed = scripts.remove(script)
assert removed, script.name()
def _add_script(script, injection_point):
new_script = QWebEngineScript()
new_script.setInjectionPoint(injection_point)
new_script.setWorldId(QWebEngineScript.MainWorld)
new_script.setSourceCode(script.code())
new_script.setName("GM-{}".format(script.name))
new_script.setRunsOnSubFrames(script.runs_on_sub_frames)
log.greasemonkey.debug("Adding script: {}"
.format(new_script.name()))
scripts.insert(new_script)
greasemonkey = objreg.get('greasemonkey')
matching_scripts = greasemonkey.scripts_for(url)
for script in matching_scripts.start:
_add_script(script, QWebEngineScript.DocumentCreation)
for script in matching_scripts.end:
_add_script(script, QWebEngineScript.DocumentReady)
for script in matching_scripts.idle:
_add_script(script, QWebEngineScript.Deferred)