Simplify userscript running.

This commit is contained in:
Florian Bruhin 2014-07-29 02:05:15 +02:00
parent b83dd59469
commit 425a7fd7c4
5 changed files with 52 additions and 26 deletions

View File

@ -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...")

View File

@ -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):

View File

@ -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."""

View File

@ -17,20 +17,30 @@
# You should have received a copy of the GNU General Public License
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
"""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))

View File

@ -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():