From 501379ee09c3510d1737d6292a2dd5732c19dfef Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Tue, 2 Jan 2018 23:53:57 +0100 Subject: [refactor] webengine entrypoint this commit deprecates qtwebkit usage. --- docs/changelog.rst | 1 + docs/hacking/devenv.rst | 2 +- src/leap/bitmask/gui/app.py | 69 ++++++++++++++++-------------------- src/leap/bitmask/gui/app2.py | 7 ++-- src/leap/bitmask/gui/housekeeping.py | 8 ++++- ui/app/index.html | 12 ++++++- 6 files changed, 53 insertions(+), 46 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index e2067a21..aa7ac132 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -15,6 +15,7 @@ Features Bugfixes ~~~~~~~~ - `#9171 `_: fix a bug in bootstrap that avoided more than one user to login. +- `#9165 `_: deprecate pyqt5-webkit, use qtwebengine instead. Misc ~~~~ diff --git a/docs/hacking/devenv.rst b/docs/hacking/devenv.rst index 029d7a3a..5f7341d9 100644 --- a/docs/hacking/devenv.rst +++ b/docs/hacking/devenv.rst @@ -31,7 +31,7 @@ Install the system-wide dependencies. For debian-based systems:: sudo apt install build-essential python-dev python-virtualenv \ libsqlcipher-dev libssl-dev libffi-dev \ - python-pyqt5 python-pyqt5.qtwebkit + python-pyqt5 python-pyqt5.qtwebengine/ If you are going to be running tests that involve creating a lot of OpenPGP keys, and specially in vms, the following is also recommended to speed up diff --git a/src/leap/bitmask/gui/app.py b/src/leap/bitmask/gui/app.py index a616dc3b..2033fc6d 100644 --- a/src/leap/bitmask/gui/app.py +++ b/src/leap/bitmask/gui/app.py @@ -25,7 +25,6 @@ import os import platform import signal import sys -import time import webbrowser from functools import partial @@ -33,12 +32,12 @@ from multiprocessing import Process from leap.bitmask.core.launcher import run_bitmaskd, pid from leap.bitmask.gui import app_rc +from leap.bitmask.gui.systray import WithTrayIcon +from leap.bitmask.gui.housekeeping import cleanup, terminate, reset_authtoken +from leap.bitmask.gui.housekeeping import get_authenticated_url +from leap.bitmask.gui.housekeeping import NoAuthTokenError from leap.common.config import get_path_prefix -from .housekeeping import cleanup, terminate, reset_authtoken -from .housekeeping import get_authenticated_url - -from .systray import WithTrayIcon if platform.system() == 'Windows': from multiprocessing import freeze_support @@ -57,12 +56,9 @@ else: from PyQt5.QtWidgets import QDialog from PyQt5.QtWidgets import QMessageBox - try: - from PyQt5.QtWebKitWidgets import QWebView - from PyQt5.QtWebKit import QWebSettings - except ImportError: - from PyQt5.QtWebEngineWidgets import QWebEngineView as QWebView - from PyQt5.QtWebEngineWidgets import QWebEngineSettings as QWebSettings + from PyQt5.QtWebEngineWidgets import QWebEngineView as QWebView + from PyQt5.QtWebEngineWidgets import QWebEngineSettings as QWebSettings + from PyQt5.QtWebChannel import QWebChannel IS_WIN = platform.system() == "Windows" DEBUG = os.environ.get("DEBUG", False) @@ -90,8 +86,10 @@ class BrowserWindow(QWebView, WithTrayIcon): def __init__(self, *args, **kw): url = kw.pop('url', None) + first = False if not url: url = get_authenticated_url() + first = True self.url = url self.closing = False @@ -100,9 +98,13 @@ class BrowserWindow(QWebView, WithTrayIcon): self.bitmask_browser = NewPageConnector(self) if first else None self.loadPage(self.url) - self.proxy = AppProxy(self) if first else None - self.frame.addToJavaScriptWindowObject( - "bitmaskApp", self.proxy) + self.bridge = AppBridge(self) if first else None + + if self.bridge is not None: + print "[+] registering python<->js bridge" + channel = QWebChannel(self) + channel.registerObject("bitmaskApp", self.bridge) + self.page().setWebChannel(channel) icon = QtGui.QIcon() icon.addPixmap( @@ -111,26 +113,10 @@ class BrowserWindow(QWebView, WithTrayIcon): self.setWindowIcon(icon) def loadPage(self, web_page): - try: - if os.environ.get('DEBUG'): - self.settings().setAttribute( - QWebSettings.DeveloperExtrasEnabled, True) - except Exception: - pass - - if os.environ.get('DEBUG'): - self.inspector = QWebInspector(self) - self.inspector.setPage(self.page()) - self.inspector.show() - if os.path.isabs(web_page): web_page = os.path.relpath(web_page) url = QtCore.QUrl(web_page) - # TODO -- port this to QWebEngine - self.frame = self.page().mainFrame() - self.frame.addToJavaScriptWindowObject( - "bitmaskBrowser", self.bitmask_browser) self.load(url) def shutdown(self, *args): @@ -138,10 +124,12 @@ class BrowserWindow(QWebView, WithTrayIcon): if self.closing: return self.closing = True + bitmaskd.join() terminate(pid) cleanup() print('[bitmask] shutting down gui...') + try: self.stop() try: @@ -157,11 +145,11 @@ class BrowserWindow(QWebView, WithTrayIcon): sys.exit(1) -class AppProxy(QObject): +class AppBridge(QObject): @pyqtSlot() def shutdown(self): - """To be exposed from the js bridge""" + print "[+] shutdown called from js" global browser if browser: browser.user_closed = True @@ -171,8 +159,8 @@ class AppProxy(QObject): def openSystemBrowser(self, url): webbrowser.open(url) - pixbrowser = None +closing = False class NewPageConnector(QObject): @@ -185,12 +173,17 @@ class NewPageConnector(QObject): def _handle_kill(*args, **kw): + global pixbrowser + global closing + if closing: + sys.exit() win = kw.get('win') if win: + win.user_closed = True QtCore.QTimer.singleShot(0, win.close) - global pixbrowser if pixbrowser: QtCore.QTimer.singleShot(0, pixbrowser.close) + closing = True def launch_gui(): @@ -206,7 +199,7 @@ def launch_gui(): qApp = QApplication([]) try: browser = BrowserWindow(None) - except NoAuthToken as e: + except NoAuthTokenError as e: print('ERROR: ' + e.message) sys.exit(1) @@ -237,6 +230,9 @@ def start_app(): # Allow the frozen binary in the bundle double as the cli entrypoint # Why have only a user interface when you can have two? + if DEBUG: + os.environ.setdefault('QTWEBENGINE_REMOTE_DEBUGGING', '8081') + if platform.system() == 'Windows': # In windows, there are some args added to the invocation # by PyInstaller, I guess... @@ -257,9 +253,6 @@ def start_app(): launch_gui() -class NoAuthToken(Exception): - pass - if __name__ == "__main__": start_app() diff --git a/src/leap/bitmask/gui/app2.py b/src/leap/bitmask/gui/app2.py index 649d5deb..3e83b435 100644 --- a/src/leap/bitmask/gui/app2.py +++ b/src/leap/bitmask/gui/app2.py @@ -45,6 +45,7 @@ from leap.common.config import get_path_prefix from leap.bitmask.gui.systray import WithTrayIcon from leap.bitmask.gui.housekeeping import cleanup, terminate, reset_authtoken from leap.bitmask.gui.housekeeping import get_authenticated_url +from leap.bitmask.gui.housekeeping import NoAuthTokenError DEBUG = os.environ.get("DEBUG", False) @@ -151,7 +152,7 @@ def launch_gui(): systray.closeFromSystray() sys.exit(qApp.exec_()) - except NoAuthToken as e: + except NoAuthTokenError as e: print('ERROR: ' + e.message) sys.exit(1) @@ -180,9 +181,5 @@ def start_app(): launch_gui() -class NoAuthToken(Exception): - pass - - if __name__ == "__main__": start_app() diff --git a/src/leap/bitmask/gui/housekeeping.py b/src/leap/bitmask/gui/housekeeping.py index 3202f5e6..7069adba 100644 --- a/src/leap/bitmask/gui/housekeeping.py +++ b/src/leap/bitmask/gui/housekeeping.py @@ -1,7 +1,13 @@ import os +import signal +import time from leap.common.config import get_path_prefix + +class NoAuthTokenError(Exception): + pass + def get_authenticated_url(): url = "http://localhost:7070" path = os.path.join(get_path_prefix(), 'leap', 'authtoken') @@ -12,7 +18,7 @@ def get_authenticated_url(): # because touching the token file is one of the first # things the backend does, and this BrowserWindow # should be called *right after* launching the backend. - raise NoAuthToken( + raise NoAuthTokenError( 'No authentication token found!') time.sleep(0.1) waiting -= 1 diff --git a/ui/app/index.html b/ui/app/index.html index d500e369..2cd0bf17 100644 --- a/ui/app/index.html +++ b/ui/app/index.html @@ -10,5 +10,15 @@
+ + - \ No newline at end of file + -- cgit v1.2.3