1
0
Fork 0
mirror of synced 2024-05-08 14:43:00 +12:00

BrowserLogin: Add dedicated application mode to Rare for the webview login page

Add a sub-application to Rare to launch the webview for logging into EGS.
The sub-application operates similatly to the `laucher` sub-application and
it is autonomous. After a successful login in returns the exchange code
to the standard output to be parsed and used by the login dialog.

The reason this implementation was chosen is because when pywebview uses
pyqtwebengine as the GUI library, we cannot launch it through Rare as
it tries to spawn a QMainWindow inside an existing event loop, which is
prohibited by Qt.

Despite that, EGS login page doesn't work correctly with QtWebEngine,
so on linux default to the GTK backend for pywebview, and this change
helps keeping applications using different toolkits separate.

At this moment, spawning the sub-application blocks the execution of the
main application.

This change should make it easier to authenticate through Rare inside
a gamescope session, such as the steam deck.
This commit is contained in:
loathingKernel 2024-02-02 14:47:29 +02:00
parent 9181641d70
commit 88b6e91530
4 changed files with 57 additions and 21 deletions

View file

@ -2,14 +2,15 @@ import json
from logging import getLogger
from typing import Tuple
from PyQt5.QtCore import pyqtSignal, QUrl
from PyQt5.QtCore import pyqtSignal, QUrl, QProcess, pyqtSlot
from PyQt5.QtGui import QDesktopServices
from PyQt5.QtWidgets import QFrame, qApp, QFormLayout, QLineEdit
from legendary.core import LegendaryCore
from legendary.utils import webview_login
from rare.lgndr.core import LegendaryCore
from rare.ui.components.dialogs.login.browser_login import Ui_BrowserLogin
from rare.utils.misc import icon
from rare.utils.paths import get_rare_executable
from rare.widgets.indicator_edit import IndicatorLineEdit, IndicatorReasonsCommon
logger = getLogger("BrowserLogin")
@ -43,6 +44,7 @@ class BrowserLogin(QFrame):
self.ui.open_button.clicked.connect(self.open_browser)
self.sid_edit.textChanged.connect(self.changed.emit)
@pyqtSlot()
def copy_link(self):
clipboard = qApp.clipboard()
clipboard.setText(self.login_url)
@ -79,12 +81,24 @@ class BrowserLogin(QFrame):
except Exception as e:
logger.warning(e)
@pyqtSlot()
def open_browser(self):
if not webview_login.webview_available:
logger.warning("You don't have webengine installed, you will need to manually copy the authorizationCode.")
QDesktopServices.openUrl(QUrl(self.login_url))
else:
if webview_login.do_webview_login(callback_code=self.core.auth_ex_token):
cmd = get_rare_executable() + ["login", self.core.get_egl_version()]
proc = QProcess(self)
proc.start(cmd[0], cmd[1:])
proc.waitForFinished(-1)
out, err = (
proc.readAllStandardOutput().data().decode("utf-8", "ignore"),
proc.readAllStandardError().data().decode("utf-8", "ignore")
)
proc.deleteLater()
if out:
self.core.auth_ex_token(out)
logger.info("Successfully logged in as %s", {self.core.lgd.userdata['displayName']})
self.success.emit()
else:

View file

@ -57,22 +57,26 @@ def main() -> int:
)
subparsers = parser.add_subparsers(title="Commands", dest="subparser")
launch_minimal_parser = subparsers.add_parser("start", aliases=["launch"])
launch_minimal_parser.add_argument("app_name", help="AppName of the game to launch",
metavar="<App Name>", action="store")
launch_minimal_parser.add_argument("--dry-run", help="Print arguments and exit", action="store_true")
launch_minimal_parser.add_argument("--offline", help="Launch game offline",
action="store_true")
launch_minimal_parser.add_argument('--wine-bin', dest='wine_bin', action='store', metavar='<wine binary>',
default=os.environ.get('LGDRY_WINE_BINARY', None),
help='Set WINE binary to use to launch the app')
launch_minimal_parser.add_argument('--wine-prefix', dest='wine_pfx', action='store', metavar='<wine pfx path>',
default=os.environ.get('LGDRY_WINE_PREFIX', None),
help='Set WINE prefix to use')
launch_minimal_parser.add_argument("--ask-sync-saves", help="Ask to sync cloud saves",
action="store_true")
launch_minimal_parser.add_argument("--skip-update-check", help="Do not check for updates",
action="store_true")
launch_parser = subparsers.add_parser("start", aliases=["launch"])
launch_parser.add_argument("app_name", help="AppName of the game to launch",
metavar="<App Name>", action="store")
launch_parser.add_argument("--dry-run", help="Print arguments and exit", action="store_true")
launch_parser.add_argument("--offline", help="Launch game offline",
action="store_true")
launch_parser.add_argument('--wine-bin', dest='wine_bin', action='store', metavar='<wine binary>',
default=os.environ.get('LGDRY_WINE_BINARY', None),
help='Set WINE binary to use to launch the app')
launch_parser.add_argument('--wine-prefix', dest='wine_pfx', action='store', metavar='<wine pfx path>',
default=os.environ.get('LGDRY_WINE_PREFIX', None),
help='Set WINE prefix to use')
launch_parser.add_argument("--ask-sync-saves", help="Ask to sync cloud saves",
action="store_true")
launch_parser.add_argument("--skip-update-check", help="Do not check for updates",
action="store_true")
login_parser = subparsers.add_parser("login", aliases=["auth"])
login_parser.add_argument("egl_version", help="Epic Games Launcher User Agent version",
metavar="<EGL Version>", action="store")
args = parser.parse_args()
@ -93,6 +97,10 @@ def main() -> int:
print(f"Rare {__version__} Codename: {__codename__}")
return 0
if args.subparser in {"login", "auth"}:
from rare.webview import launch
return launch(args)
if args.subparser in {"start", "launch"}:
from rare.launcher import launch
return launch(args)

13
rare/webview/__init__.py Normal file
View file

@ -0,0 +1,13 @@
import sys
from argparse import Namespace
from legendary.utils import webview_login
def launch(args: Namespace) -> int:
if webview_login.do_webview_login(
callback_code=sys.stdout.write, user_agent=f'EpicGamesLauncher/{args.egl_version}'
):
return 0
else:
return 1

View file

@ -1,5 +1,6 @@
pywebview[qt]; platform_system == "Linux"
pywebview[qt]; platform_system == "FreeBSD"
# pywebview with QtWebEngine backend has issues with EGS login form, so use GTK
pywebview[gtk]; platform_system == "Linux"
pywebview[gtk]; platform_system == "FreeBSD"
pythonnet>=3.0.0rc4; platform_system == "Windows"
cefpython3; platform_system == "Windows"
pywebview[cef]; platform_system == "Windows"