From 425a7fd7c4e1b52edf49ab51f5898d9d5c704db1 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Tue, 29 Jul 2014 02:05:15 +0200 Subject: [PATCH] Simplify userscript running. --- qutebrowser/app.py | 3 ++ qutebrowser/browser/commands.py | 17 +++--------- qutebrowser/browser/hints.py | 9 +++--- qutebrowser/commands/userscripts.py | 43 +++++++++++++++++++++++++++-- qutebrowser/widgets/webview.py | 6 ---- 5 files changed, 52 insertions(+), 26 deletions(-) diff --git a/qutebrowser/app.py b/qutebrowser/app.py index 2001dc30a..d3e676ba6 100644 --- a/qutebrowser/app.py +++ b/qutebrowser/app.py @@ -45,6 +45,7 @@ import qutebrowser.utils.log as log import qutebrowser.utils.version as version import qutebrowser.utils.url as urlutils import qutebrowser.utils.message as message +import qutebrowser.commands.userscripts as userscripts from qutebrowser.config.config import ConfigManager from qutebrowser.keyinput.modeman import ModeManager from qutebrowser.widgets.mainwindow import MainWindow @@ -136,6 +137,8 @@ class Application(QApplication): quickmarks.init() log.init.debug("Initializing proxy...") proxy.init() + log.init.debug("Initializing userscripts...") + userscripts.init() log.init.debug("Initializing cookies...") self.cookiejar = CookieJar(self) log.init.debug("Initializing commands...") diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py index fb664c324..28de2a626 100644 --- a/qutebrowser/browser/commands.py +++ b/qutebrowser/browser/commands.py @@ -37,10 +37,10 @@ import qutebrowser.utils.webelem as webelem import qutebrowser.browser.quickmarks as quickmarks import qutebrowser.utils.log as log import qutebrowser.utils.url as urlutils +import qutebrowser.commands.userscripts as userscripts from qutebrowser.utils.qt import check_overflow, check_print_compat from qutebrowser.utils.editor import ExternalEditor from qutebrowser.commands.exceptions import CommandError -from qutebrowser.commands.userscripts import UserscriptRunner from qutebrowser.utils.usertypes import KeyMode @@ -57,7 +57,6 @@ class CommandDispatcher: Attributes: _tabs: The TabbedBrowser object. _editor: The ExternalEditor object. - _userscript_runners: A list of userscript runners. """ def __init__(self, parent): @@ -66,7 +65,6 @@ class CommandDispatcher: Args: parent: The TabbedBrowser for this dispatcher. """ - self._userscript_runners = [] self._tabs = parent self._editor = None @@ -603,7 +601,7 @@ class CommandDispatcher: self.openurl(config.get('general', 'startpage')[0]) @cmdutils.register(instance='mainwindow.tabs.cmd') - def run_userscript(self, cmd, *args, url=None): + def run_userscript(self, cmd, *args): """Run an userscript given as argument. Args: @@ -611,15 +609,8 @@ class CommandDispatcher: args: Arguments to pass to the userscript. url: A custom QUrl to use instead of the current url. """ - if url is None: - url = self._tabs.current_url() - # We don't remove the password in the URL here, as it's probably safe - # to pass via env variable. - urlstr = url.toString(QUrl.FullyEncoded) - runner = UserscriptRunner(self._tabs) - runner.got_cmd.connect(self._tabs.got_cmd) - runner.run(cmd, *args, env={'QUTE_URL': urlstr}) - self._userscript_runners.append(runner) + url = self._tabs.current_url() + userscripts.run(cmd, *args, url=url) @cmdutils.register(instance='mainwindow.tabs.cmd') def quickmark_save(self): diff --git a/qutebrowser/browser/hints.py b/qutebrowser/browser/hints.py index e07626233..094dd2d1d 100644 --- a/qutebrowser/browser/hints.py +++ b/qutebrowser/browser/hints.py @@ -31,6 +31,7 @@ import qutebrowser.config.config as config import qutebrowser.keyinput.modeman as modeman import qutebrowser.utils.message as message import qutebrowser.utils.webelem as webelem +import qutebrowser.commands.userscripts as userscripts from qutebrowser.commands.exceptions import CommandError from qutebrowser.utils.usertypes import enum, KeyMode from qutebrowser.utils.log import hints as logger @@ -111,9 +112,6 @@ class HintManager(QObject): download_get: Download an URL. arg 0: The URL to download, as QUrl. arg 1: The QWebPage to download the URL in. - run_userscript: Emitted when a custom userscript should be run. - arg 0: The URL which was selected. - arg 1: The userscript/args to run. """ HINT_CSS = """ @@ -150,7 +148,6 @@ class HintManager(QObject): openurl = pyqtSignal('QUrl', bool) set_open_target = pyqtSignal(str) download_get = pyqtSignal('QUrl', 'QWebPage') - run_userscript = pyqtSignal('QUrl', list) def __init__(self, parent=None): """Constructor. @@ -369,7 +366,9 @@ class HintManager(QObject): def _call_userscript(self, url): """Call an userscript from a hint.""" qt_ensure_valid(url) - self.run_userscript.emit(url, list(self._context.args)) + cmd = self._context.args[0] + args = self._context.args[1:] + userscripts.run(cmd, *args, url=url) def _spawn(self, url): """Spawn a simple command from a hint.""" diff --git a/qutebrowser/commands/userscripts.py b/qutebrowser/commands/userscripts.py index 48d3f37c6..ff91341cb 100644 --- a/qutebrowser/commands/userscripts.py +++ b/qutebrowser/commands/userscripts.py @@ -17,20 +17,30 @@ # You should have received a copy of the GNU General Public License # along with qutebrowser. If not, see . -"""Functions to execute an userscript.""" +"""Functions to execute an userscript. + +Module attributes: + _runners: Active userscript runners from run_userscript. +""" import os import os.path import tempfile from select import select +from functools import partial from PyQt5.QtCore import (pyqtSignal, QObject, QThread, QStandardPaths, - QProcessEnvironment, QProcess) + QProcessEnvironment, QProcess, QUrl) import qutebrowser.utils.message as message from qutebrowser.utils.misc import get_standard_dir from qutebrowser.utils.log import procs as logger from qutebrowser.commands.exceptions import CommandError +from qutebrowser.commands.managers import CommandManager + + +_runners = [] +_commandmanager = None class _BlockingFIFOReader(QObject): @@ -97,9 +107,11 @@ class _BaseUserscriptRunner(QObject): Signals: got_cmd: Emitted when a new command arrived and should be executed. + finished: Emitted when the userscript finished running. """ got_cmd = pyqtSignal(str) + finished = pyqtSignal() PROCESS_MESSAGES = { QProcess.FailedToStart: "The process failed to start.", @@ -229,6 +241,7 @@ class _POSIXUserscriptRunner(_BaseUserscriptRunner): self.reader.fifo.close() self.reader.deleteLater() super()._cleanup() + self.finished.emit() def on_thread_finished(self): """Clean up the QThread object when the thread finished.""" @@ -270,11 +283,13 @@ class _WindowsUserscriptRunner(_BaseUserscriptRunner): for line in f: self.got_cmd.emit(line.rstrip()) self._cleanup() + self.finished.emit() def on_proc_error(self, error): """Clean up when the process had an error.""" super().on_proc_error(error) self._cleanup() + self.finished.emit() def run(self, cmd, *args, env=None): self.oshandle, self.filepath = tempfile.mkstemp(text=True) @@ -287,10 +302,16 @@ class _DummyUserscriptRunner: Used on unknown systems since we don't know what (or if any) approach will work there. + + Signals: + finished: Always emitted. """ + finished = pyqtSignal() + def run(self, _cmd, *_args, _env=None): """Print an error as userscripts are not supported.""" + self.finished.emit() raise CommandError("Userscripts are not supported on this platform!") @@ -302,3 +323,21 @@ elif os.name == 'nt': UserscriptRunner = _WindowsUserscriptRunner else: UserscriptRunner = _DummyUserscriptRunner + + +def init(): + """Initialize the global _commandmanager.""" + global _commandmanager + _commandmanager = CommandManager() + + +def run(cmd, *args, url): + """Convenience method to run an userscript.""" + # We don't remove the password in the URL here, as it's probably safe to + # pass via env variable.. + urlstr = url.toString(QUrl.FullyEncoded) + runner = UserscriptRunner() + runner.got_cmd.connect(_commandmanager.run_safely) + runner.run(cmd, *args, env={'QUTE_URL': urlstr}) + _runners.append(runner) + runner.finished.connect(partial(_runners.remove, runner)) diff --git a/qutebrowser/widgets/webview.py b/qutebrowser/widgets/webview.py index a6ddf4ff5..975f932c6 100644 --- a/qutebrowser/widgets/webview.py +++ b/qutebrowser/widgets/webview.py @@ -112,7 +112,6 @@ class WebView(QWebView): self.setPage(self._page) self.hintmanager = HintManager(self) self.hintmanager.mouse_event.connect(self.on_mouse_event) - self.hintmanager.run_userscript.connect(self.run_hint_userscript) self.hintmanager.set_open_target.connect(self.set_force_open_target) self._page.linkHovered.connect(self.linkHovered) self._page.mainFrame().loadStarted.connect(self.on_load_started) @@ -344,11 +343,6 @@ class WebView(QWebView): """ self._tabs.currentWidget().findText(text, flags) - @pyqtSlot('QUrl', list) - def run_hint_userscript(self, url, args): - """Glue slot to run an userscript via HintManager.""" - self.tabbedbrowser.cmd.run_userscript(args[0], *args[1:], url=url) - def go_back(self): """Go back a page in the history.""" if self.page().history().canGoBack():