From 614893bdd6f338f1727b04a8f0a604d197a19046 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Wed, 3 Aug 2016 15:23:32 +0200 Subject: [PATCH] Initial broken inspector support for QtWebEngine --- qutebrowser/browser/commands.py | 23 +++-- .../browser/webengine/webengineinspector.py | 91 +++++++++++++++++++ .../browser/webengine/webenginesettings.py | 11 ++- .../{inspector.py => webkitinspector.py} | 0 qutebrowser/config/configdata.py | 3 +- 5 files changed, 118 insertions(+), 10 deletions(-) create mode 100644 qutebrowser/browser/webengine/webengineinspector.py rename qutebrowser/browser/webkit/{inspector.py => webkitinspector.py} (100%) diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py index d2f3b801a..77811e0e4 100644 --- a/qutebrowser/browser/commands.py +++ b/qutebrowser/browser/commands.py @@ -41,7 +41,8 @@ import pygments.formatters from qutebrowser.commands import userscripts, cmdexc, cmdutils, runners from qutebrowser.config import config, configexc from qutebrowser.browser import urlmarks, browsertab -from qutebrowser.browser.webkit import webelem, inspector, downloads, mhtml +from qutebrowser.browser.webkit import (webelem, webkitinspector, downloads, + mhtml) from qutebrowser.keyinput import modeman from qutebrowser.utils import (message, usertypes, log, qtutils, urlutils, objreg, utils, typing) @@ -1219,7 +1220,7 @@ class CommandDispatcher: raise cmdexc.CommandError(str(e)) @cmdutils.register(instance='command-dispatcher', name='inspector', - scope='window', backend=usertypes.Backend.QtWebKit) + scope='window') def toggle_inspector(self): """Toggle the web inspector. @@ -1232,11 +1233,21 @@ class CommandDispatcher: raise cmdexc.CommandError( "Please enable developer-extras before using the " "webinspector!") - tab.data.inspector = inspector.WebInspector() + # FIXME:qtwebengine have a proper API for this - page = tab._widget.page() # pylint: disable=protected-access - tab.data.inspector.setPage(page) - tab.data.inspector.show() + if tab.backend == usertypes.Backend.QtWebKit: + tab.data.inspector = webkitinspector.WebInspector() + page = tab._widget.page() # pylint: disable=protected-access + tab.data.inspector.setPage(page) + tab.data.inspector.show() + elif tab.backend == usertypes.Backend.QtWebEngine: + from qutebrowser.browser.webengine import webengineinspector + tab.data.inspector = webengineinspector.WebInspector() + try: + tab.data.inspector.load() + except webengineinspector.WebInspectorError as e: + raise cmdexc.CommandError(e) + tab.data.inspector.show() elif tab.data.inspector.isVisible(): tab.data.inspector.hide() else: diff --git a/qutebrowser/browser/webengine/webengineinspector.py b/qutebrowser/browser/webengine/webengineinspector.py new file mode 100644 index 000000000..64f3c7d5b --- /dev/null +++ b/qutebrowser/browser/webengine/webengineinspector.py @@ -0,0 +1,91 @@ +# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et: + +# Copyright 2015-2016 Florian Bruhin (The Compiler) +# +# This file is part of qutebrowser. +# +# qutebrowser is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# qutebrowser is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with qutebrowser. If not, see . + +"""Customized QWebInspector.""" + +import os +import base64 +import binascii + +from PyQt5.QtCore import QUrl +from PyQt5.QtWidgets import QWidget +from PyQt5.QtWebEngineWidgets import QWebEngineView + +from qutebrowser.utils import log, objreg +from qutebrowser.misc import miscwidgets + + +# FIXME:qtwebengine should we move the geometry stuff to some mixin? + + +class WebInspectorError(Exception): + + """Raised when the inspector could not be initialized.""" + + pass + + +class WebInspector(QWidget): + + """A web inspector for QtWebEngine which stores its geometry.""" + + def __init__(self, parent=None): + super().__init__(parent) + self.port = None + self._view = QWebEngineView() + self._layout = miscwidgets.WrapperLayout(self._view, self) + self.setFocusProxy(self._view) + self._view.setParent(self) + + def load(self): + envvar = 'QTWEBENGINE_REMOTE_DEBUGGING' + if envvar not in os.environ: + raise WebInspectorError( + "Debugging is not set up correctly. Did you restart after " + "setting developer-extras?") + port = int(os.environ[envvar]) + url = QUrl('http://localhost:{}/'.format(port)) + self._view.load(url) + + # self._load_state_geometry() + + # def closeEvent(self, e): + # """Save the geometry when closed.""" + # state_config = objreg.get('state-config') + # data = bytes(self.saveGeometry()) + # geom = base64.b64encode(data).decode('ASCII') + # state_config['geometry']['inspector'] = geom + # super().closeEvent(e) + + # def _load_state_geometry(self): + # """Load the geometry from the state file.""" + # state_config = objreg.get('state-config') + # try: + # data = state_config['geometry']['inspector'] + # geom = base64.b64decode(data, validate=True) + # except KeyError: + # # First start + # pass + # except binascii.Error: + # log.misc.exception("Error while reading geometry") + # else: + # log.init.debug("Loading geometry from {}".format(geom)) + # ok = self.restoreGeometry(geom) + # if not ok: + # log.init.warning("Error while loading geometry.") diff --git a/qutebrowser/browser/webengine/webenginesettings.py b/qutebrowser/browser/webengine/webenginesettings.py index a2b5da57f..d0841c11b 100644 --- a/qutebrowser/browser/webengine/webenginesettings.py +++ b/qutebrowser/browser/webengine/webenginesettings.py @@ -24,12 +24,14 @@ Module attributes: constants. """ +import os + # pylint: disable=no-name-in-module,import-error,useless-suppression from PyQt5.QtWebEngineWidgets import QWebEngineSettings # pylint: enable=no-name-in-module,import-error,useless-suppression -from qutebrowser.config import websettings -from qutebrowser.utils import objreg +from qutebrowser.config import websettings, config +from qutebrowser.utils import objreg, utils class Attribute(websettings.Attribute): @@ -61,6 +63,11 @@ def update_settings(section, option): def init(): """Initialize the global QWebSettings.""" # FIXME:qtwebengine set paths in profile + + if config.get('general', 'developer-extras'): + # FIXME:qtwebengine Make sure we call globalSettings *after* this... + os.environ['QTWEBENGINE_REMOTE_DEBUGGING'] = str(utils.random_port()) + websettings.init_mappings(MAPPINGS) objreg.get('config').changed.connect(update_settings) diff --git a/qutebrowser/browser/webkit/inspector.py b/qutebrowser/browser/webkit/webkitinspector.py similarity index 100% rename from qutebrowser/browser/webkit/inspector.py rename to qutebrowser/browser/webkit/webkitinspector.py diff --git a/qutebrowser/config/configdata.py b/qutebrowser/config/configdata.py index 292106108..4584b242a 100644 --- a/qutebrowser/config/configdata.py +++ b/qutebrowser/config/configdata.py @@ -176,8 +176,7 @@ def data(readonly=False): "icons."), ('developer-extras', - SettingValue(typ.Bool(), 'false', - backends=[usertypes.Backend.QtWebKit]), + SettingValue(typ.Bool(), 'false'), "Enable extra tools for Web developers.\n\n" "This needs to be enabled for `:inspector` to work and also adds " "an _Inspect_ entry to the context menu."),