diff options
| -rw-r--r-- | docs/changelog.rst | 1 | ||||
| -rw-r--r-- | docs/hacking/devenv.rst | 2 | ||||
| -rw-r--r-- | src/leap/bitmask/gui/app.py | 69 | ||||
| -rw-r--r-- | src/leap/bitmask/gui/app2.py | 7 | ||||
| -rw-r--r-- | src/leap/bitmask/gui/housekeeping.py | 8 | ||||
| -rw-r--r-- | 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 <https://0xacab.org/leap/bitmask-dev/issues/9171>`_: fix a bug in bootstrap that avoided more than one user to login. +- `#9165 <https://0xacab.org/leap/bitmask-dev/issues/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 @@    <body>      <div id="app"></div>      <script src="app.bundle.js"></script> +    <script src="qrc:///qtwebchannel/qwebchannel.js"></script> +    <script> +        function _onload() { +            window.webChannel = new QWebChannel(qt.webChannelTransport, function (channel) {  +                window.bitmaskApp = channel.objects.bitmaskApp; +            }); +            console.log(window.bitmaskApp); +        } +        window.onload = _onload; +    </script>    </body> -</html>
\ No newline at end of file +</html> | 
