summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Bruhin <git@the-compiler.org>2018-06-26 10:37:17 +0200
committerFlorian Bruhin <git@the-compiler.org>2018-06-26 10:37:17 +0200
commit61da5d0c7c30338f52c80a056113844794cba94f (patch)
tree7deb1680ae52819a7698f59063f3592887d0b962
parent3312c221c4691357a8564448f4d2c0f686a4944e (diff)
parentc43d173197b02bd765a47335643d3643b35f687f (diff)
downloadqutebrowser-61da5d0c7c30338f52c80a056113844794cba94f.tar.gz
qutebrowser-61da5d0c7c30338f52c80a056113844794cba94f.zip
Merge remote-tracking branch 'origin/pr/4017'
-rw-r--r--qutebrowser/browser/greasemonkey.py3
-rw-r--r--qutebrowser/browser/webengine/webenginetab.py103
-rw-r--r--qutebrowser/browser/webengine/webview.py46
3 files changed, 79 insertions, 73 deletions
diff --git a/qutebrowser/browser/greasemonkey.py b/qutebrowser/browser/greasemonkey.py
index db8246bab..cff45f3ac 100644
--- a/qutebrowser/browser/greasemonkey.py
+++ b/qutebrowser/browser/greasemonkey.py
@@ -58,6 +58,7 @@ class GreasemonkeyScript:
self.run_at = None
self.script_meta = None
self.runs_on_sub_frames = True
+ self.jsworld = "main"
for name, value in properties:
if name == 'name':
self.name = value
@@ -77,6 +78,8 @@ class GreasemonkeyScript:
self.runs_on_sub_frames = False
elif name == 'require':
self.requires.append(value)
+ elif name == 'qute-js-world':
+ self.jsworld = value
HEADER_REGEX = r'// ==UserScript==|\n+// ==/UserScript==\n'
PROPS_REGEX = r'// @(?P<prop>[^\s]+)\s*(?P<val>.*)'
diff --git a/qutebrowser/browser/webengine/webenginetab.py b/qutebrowser/browser/webengine/webenginetab.py
index 8e88a6efb..aa1c014ef 100644
--- a/qutebrowser/browser/webengine/webenginetab.py
+++ b/qutebrowser/browser/webengine/webenginetab.py
@@ -853,9 +853,17 @@ class _WebEngineScripts(QObject):
self._inject_early_js('js', js_code, subframes=True)
self._init_stylesheet()
- greasemonkey = objreg.get('greasemonkey')
- greasemonkey.scripts_reloaded.connect(self._inject_userscripts)
- self._inject_userscripts()
+ # 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'):
+ 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):
"""Initialize custom stylesheets.
@@ -872,40 +880,77 @@ class _WebEngineScripts(QObject):
)
self._inject_early_js('stylesheet', js_code, subframes=True)
- def _inject_userscripts(self):
- """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'):
+ def _inject_greasemonkey_scripts_for_url(self, url):
+ greasemonkey = objreg.get('greasemonkey')
+ matching_scripts = greasemonkey.scripts_for(url)
+ self._inject_greasemonkey_scripts(
+ matching_scripts.start, QWebEngineScript.DocumentCreation, True)
+ 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
- # Since we are inserting scripts into profile.scripts they won't
- # 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
- # stylesheets.
- greasemonkey = objreg.get('greasemonkey')
- scripts = self._widget.page().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()
-
- # Then add the new scripts.
- for script in greasemonkey.all_scripts():
- # @run-at (and @include/@exclude/@match) is parsed by
- # QWebEngineScript.
+ # Since we are inserting scripts into a per-tab collection,
+ # rather than just injecting scripts on page load, we need to
+ # make sure we replace existing scripts, not just add new ones.
+ # While, taking care not to remove any other scripts that might
+ # have been added elsewhere, like the one for stylesheets.
+ page_scripts = self._widget.page().scripts()
+ if remove_first:
+ for script in page_scripts.toList():
+ if script.name().startswith("GM-"):
+ log.greasemonkey.debug('Removing script: {}'
+ .format(script.name()))
+ removed = page_scripts.remove(script)
+ assert removed, script.name()
+
+ if not scripts:
+ return
+
+ for script in scripts:
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.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)
log.greasemonkey.debug('adding script: {}'
.format(new_script.name()))
- scripts.insert(new_script)
+ page_scripts.insert(new_script)
class WebEngineTab(browsertab.AbstractTab):
diff --git a/qutebrowser/browser/webengine/webview.py b/qutebrowser/browser/webengine/webview.py
index 6a854d513..ca4126833 100644
--- a/qutebrowser/browser/webengine/webview.py
+++ b/qutebrowser/browser/webengine/webview.py
@@ -20,11 +20,10 @@
"""The main browser widget for QtWebEngine."""
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.QtWidgets import QWidget
-from PyQt5.QtWebEngineWidgets import (QWebEngineView, QWebEnginePage,
- QWebEngineScript)
+from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEnginePage
from qutebrowser.browser import shared
from qutebrowser.browser.webengine import webenginesettings, certificateerror
@@ -168,7 +167,6 @@ class WebEnginePage(QWebEnginePage):
self._theme_color = theme_color
self._set_bg_color()
config.instance.changed.connect(self._set_bg_color)
- self.urlChanged.connect(self._inject_userjs)
@config.change_filter('colors.webpage.bg')
def _set_bg_color(self):
@@ -263,43 +261,3 @@ class WebEnginePage(QWebEnginePage):
is_main_frame=is_main_frame)
self.navigation_request.emit(navigation)
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)