diff --git a/gnome-shell.spec b/gnome-shell.spec index 66bb215..ca915ca 100644 --- a/gnome-shell.spec +++ b/gnome-shell.spec @@ -1,6 +1,12 @@ %global tarball_version %%(echo %{version} | tr '~' '.') %global major_version %%(cut -d "." -f 1 <<<%{tarball_version}) +%if 0%{?rhel} +%global portal_helper 0 +%else +%global portal_helper 1 +%endif + Name: gnome-shell Version: 46.3.1 Release: %autorelease @@ -16,9 +22,6 @@ Patch: gnome-shell-favourite-apps-firefox.patch Patch: gnome-shell-favourite-apps-terminal.patch Patch: gnome-shell-enabled-extensions-background-logos.patch -# No portal helper if WebKitGTK is not installed -Patch: optional-portal-helper.patch - # Some users might have a broken PAM config, so we really need this # downstream patch to stop trying on configuration errors. Patch: 0001-gdm-Work-around-failing-fingerprint-auth.patch @@ -40,6 +43,7 @@ Patch: 0001-st-texture-cache-purge-on-resume.patch Patch: fix-some-js-warnings.patch Patch: 0001-data-Update-generated-stylesheets.patch Patch: 0001-data-App-icon-for-captive-portal.patch +Patch: portal-notify.patch %define eds_version 3.45.1 %define gnome_desktop_version 44.0-7 @@ -151,9 +155,9 @@ Requires: xdg-desktop-portal-gnome # needed by the welcome dialog Recommends: gnome-tour -%if !0%{?rhel} +%if %{portal_helper} # needed for captive portal helper -Recommends: webkitgtk6.0%{?_isa} +Requires: webkitgtk6.0%{?_isa} %endif # https://github.com/containers/composefs/pull/229#issuecomment-1838735764 @@ -192,7 +196,14 @@ easy to use experience. %autosetup -S git -n %{name}-%{tarball_version} %build -%meson -Dextensions_app=false +%meson \ + -Dextensions_app=false \ +%if %{portal_helper} + -Dportal_helper=true \ +%else + -Dportal_helper=false \ +%endif + %{nil} %meson_build %install @@ -207,7 +218,10 @@ mkdir -p %{buildroot}%{_datadir}/gnome-shell/search-providers %check desktop-file-validate %{buildroot}%{_datadir}/applications/org.gnome.Shell.desktop desktop-file-validate %{buildroot}%{_datadir}/applications/org.gnome.Shell.Extensions.desktop + +%if %{portal_helper} desktop-file-validate %{buildroot}%{_datadir}/applications/org.gnome.Shell.PortalHelper.desktop +%endif %files -f %{name}.lang %license COPYING @@ -221,7 +235,6 @@ desktop-file-validate %{buildroot}%{_datadir}/applications/org.gnome.Shell.Porta %{_datadir}/glib-2.0/schemas/00_org.gnome.shell.gschema.override %{_datadir}/applications/org.gnome.Shell.Extensions.desktop %{_datadir}/applications/org.gnome.Shell.desktop -%{_datadir}/applications/org.gnome.Shell.PortalHelper.desktop %{_datadir}/bash-completion/completions/gnome-extensions %{_datadir}/gnome-control-center/keybindings/50-gnome-shell-launchers.xml %{_datadir}/gnome-control-center/keybindings/50-gnome-shell-screenshots.xml @@ -232,7 +245,6 @@ desktop-file-validate %{buildroot}%{_datadir}/applications/org.gnome.Shell.Porta %{_datadir}/dbus-1/services/org.gnome.Shell.Extensions.service %{_datadir}/dbus-1/services/org.gnome.Shell.HotplugSniffer.service %{_datadir}/dbus-1/services/org.gnome.Shell.Notifications.service -%{_datadir}/dbus-1/services/org.gnome.Shell.PortalHelper.service %{_datadir}/dbus-1/services/org.gnome.Shell.Screencast.service %{_datadir}/dbus-1/interfaces/org.gnome.Shell.Extensions.xml %{_datadir}/dbus-1/interfaces/org.gnome.Shell.Introspect.xml @@ -241,9 +253,7 @@ desktop-file-validate %{buildroot}%{_datadir}/applications/org.gnome.Shell.Porta %{_datadir}/dbus-1/interfaces/org.gnome.Shell.Screenshot.xml %{_datadir}/dbus-1/interfaces/org.gnome.ShellSearchProvider.xml %{_datadir}/dbus-1/interfaces/org.gnome.ShellSearchProvider2.xml -%{_datadir}/icons/hicolor/scalable/apps/org.gnome.Shell.CaptivePortal.svg %{_datadir}/icons/hicolor/scalable/apps/org.gnome.Shell.Extensions.svg -%{_datadir}/icons/hicolor/symbolic/apps/org.gnome.Shell.CaptivePortal-symbolic.svg %{_datadir}/icons/hicolor/symbolic/apps/org.gnome.Shell.Extensions-symbolic.svg %{_userunitdir}/org.gnome.Shell-disable-extensions.service %{_userunitdir}/org.gnome.Shell.target @@ -253,9 +263,16 @@ desktop-file-validate %{buildroot}%{_datadir}/applications/org.gnome.Shell.Porta %{_libexecdir}/gnome-shell-calendar-server %{_libexecdir}/gnome-shell-perf-helper %{_libexecdir}/gnome-shell-hotplug-sniffer -%{_libexecdir}/gnome-shell-portal-helper %{_mandir}/man1/gnome-extensions.1* %{_mandir}/man1/gnome-shell.1* +%if %{portal_helper} +%{_datadir}/applications/org.gnome.Shell.PortalHelper.desktop +%{_datadir}/dbus-1/services/org.gnome.Shell.PortalHelper.service +%{_datadir}/icons/hicolor/scalable/apps/org.gnome.Shell.CaptivePortal.svg +%{_datadir}/icons/hicolor/symbolic/apps/org.gnome.Shell.CaptivePortal-symbolic.svg +%{_libexecdir}/gnome-shell-portal-helper +%endif + %changelog %autochangelog diff --git a/optional-portal-helper.patch b/optional-portal-helper.patch deleted file mode 100644 index 901b0d0..0000000 --- a/optional-portal-helper.patch +++ /dev/null @@ -1,47 +0,0 @@ -diff --git a/js/portalHelper/main.js b/js/portalHelper/main.js -index 7000089fa..d9a768a3f 100644 ---- a/js/portalHelper/main.js -+++ b/js/portalHelper/main.js -@@ -3,7 +3,13 @@ import Gio from 'gi://Gio'; - import GLib from 'gi://GLib'; - import GObject from 'gi://GObject'; - import Gtk from 'gi://Gtk?version=4.0'; --import WebKit from 'gi://WebKit?version=6.0'; -+ -+let WebKit; -+try { -+ WebKit = (await import('gi://WebKit?version=6.0')).default; -+} catch { -+ WebKit = null; -+} - - import * as Gettext from 'gettext'; - import {programInvocationName, programArgs} from 'system'; -@@ -365,5 +371,9 @@ class WebPortalHelper extends Adw.Application { - Gettext.bindtextdomain(Config.GETTEXT_PACKAGE, Config.LOCALEDIR); - Gettext.textdomain(Config.GETTEXT_PACKAGE); - --const app = new WebPortalHelper(); --await app.runAsync([programInvocationName, ...programArgs]); -+if (WebKit) { -+ const app = new WebPortalHelper(); -+ await app.runAsync([programInvocationName, ...programArgs]); -+} else { -+ log('WebKit typelib is not installed, captive portal helper will be disabled'); -+} -diff --git a/js/ui/status/network.js b/js/ui/status/network.js -index 322d7d91a..afca42e31 100644 ---- a/js/ui/status/network.js -+++ b/js/ui/status/network.js -@@ -2147,7 +2147,9 @@ class Indicator extends SystemIndicator { - await this._portalHelperProxy.init_async( - GLib.PRIORITY_DEFAULT, null); - } catch (e) { -- console.error(`Error launching the portal helper: ${e.message}`); -+ // Timeout is expected if WebKit is unavailable -+ if (!error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.TIMED_OUT)) -+ console.error(`Error launching the portal helper: ${e.message}`); - } - } - - diff --git a/portal-notify.patch b/portal-notify.patch new file mode 100644 index 0000000..52050e1 --- /dev/null +++ b/portal-notify.patch @@ -0,0 +1,511 @@ +From 9e43e0f7172b448d449764ab20dbe0540316f388 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 12 Jun 2024 13:13:41 +0200 +Subject: [PATCH 1/3] network: Split out CaptivePortalHandler class + +The handling of captive portals is going to be extended a bit, +so split out a proper class instead of mixing it in with the +indicator code. +--- + js/ui/status/network.js | 151 +++++++++++++++++++++++----------------- + 1 file changed, 87 insertions(+), 64 deletions(-) + +diff --git a/js/ui/status/network.js b/js/ui/status/network.js +index 404733b74c..d34e947073 100644 +--- a/js/ui/status/network.js ++++ b/js/ui/status/network.js +@@ -14,6 +14,7 @@ import * as Main from '../main.js'; + import * as PopupMenu from '../popupMenu.js'; + import * as MessageTray from '../messageTray.js'; + import * as ModemManager from '../../misc/modemManager.js'; ++import * as Signals from '../../misc/signals.js'; + import * as Util from '../../misc/util.js'; + + import {Spinner} from '../animation.js'; +@@ -1944,12 +1945,84 @@ class NMModemToggle extends NMDeviceToggle { + } + }); + ++class CaptivePortalHandler extends Signals.EventEmitter { ++ constructor(checkUri) { ++ super(); ++ ++ this._checkUri = checkUri; ++ this._connectivityQueue = new Set(); ++ this._portalHelperProxy = null; ++ } ++ ++ addConnection(path) { ++ if (this._connectivityQueue.has(path)) ++ return; ++ ++ this._launchPortalHelper(path).catch(logError); ++ } ++ ++ removeConnection(path) { ++ if (this._connectivityQueue.delete(path)) ++ this._portalHelperProxy?.CloseAsync(path); ++ } ++ ++ _portalHelperDone(parameters) { ++ const [path, result] = parameters; ++ ++ if (result === PortalHelperResult.CANCELLED) { ++ // Keep the connection in the queue, so the user is not ++ // spammed with more logins until we next flush the queue, ++ // which will happen once they choose a better connection ++ // or we get to full connectivity through other means ++ } else if (result === PortalHelperResult.COMPLETED) { ++ this.removeConnection(path); ++ } else if (result === PortalHelperResult.RECHECK) { ++ this.emit('recheck', path); ++ } else { ++ log(`Invalid result from portal helper: ${result}`); ++ } ++ } ++ ++ async _launchPortalHelper(path) { ++ const timestamp = global.get_current_time(); ++ if (!this._portalHelperProxy) { ++ this._portalHelperProxy = new Gio.DBusProxy({ ++ g_connection: Gio.DBus.session, ++ g_name: 'org.gnome.Shell.PortalHelper', ++ g_object_path: '/org/gnome/Shell/PortalHelper', ++ g_interface_name: PortalHelperInfo.name, ++ g_interface_info: PortalHelperInfo, ++ }); ++ this._portalHelperProxy.connectSignal('Done', ++ (proxy, emitter, params) => { ++ this._portalHelperDone(params); ++ }); ++ ++ try { ++ await this._portalHelperProxy.init_async( ++ GLib.PRIORITY_DEFAULT, null); ++ } catch (e) { ++ console.error(`Error launching the portal helper: ${e.message}`); ++ } ++ } ++ ++ this._portalHelperProxy?.AuthenticateAsync(path, this._checkUri, timestamp).catch(logError); ++ this._connectivityQueue.add(path); ++ } ++ ++ clear() { ++ for (const item of this._connectivityQueue) ++ this._portalHelperProxy?.CloseAsync(item); ++ this._connectivityQueue.clear(); ++ } ++} ++ + export const Indicator = GObject.registerClass( + class Indicator extends SystemIndicator { + _init() { + super._init(); + +- this._connectivityQueue = new Set(); ++ this._portalHandler = null; + + this._mainConnection = null; + +@@ -2004,6 +2077,16 @@ class Indicator extends SystemIndicator { + this, 'visible', + GObject.BindingFlags.SYNC_CREATE); + ++ const {connectivityCheckUri} = this._client; ++ this._portalHandler = new CaptivePortalHandler(connectivityCheckUri); ++ this._portalHandler.connect('recheck', async (o, path) => { ++ try { ++ const state = await this._client.check_connectivity_async(null); ++ if (state >= NM.ConnectivityState.FULL) ++ this._portalHandler.removeConnection(path); ++ } catch (e) { } ++ }); ++ + this._client.connectObject( + 'notify::primary-connection', () => this._syncMainConnection(), + 'notify::activating-connection', () => this._syncMainConnection(), +@@ -2066,42 +2149,10 @@ class Indicator extends SystemIndicator { + this._notification?.destroy(); + } + +- _flushConnectivityQueue() { +- for (let item of this._connectivityQueue) +- this._portalHelperProxy?.CloseAsync(item); +- this._connectivityQueue.clear(); +- } +- +- _closeConnectivityCheck(path) { +- if (this._connectivityQueue.delete(path)) +- this._portalHelperProxy?.CloseAsync(path); +- } +- +- async _portalHelperDone(parameters) { +- let [path, result] = parameters; +- +- if (result === PortalHelperResult.CANCELLED) { +- // Keep the connection in the queue, so the user is not +- // spammed with more logins until we next flush the queue, +- // which will happen once they choose a better connection +- // or we get to full connectivity through other means +- } else if (result === PortalHelperResult.COMPLETED) { +- this._closeConnectivityCheck(path); +- } else if (result === PortalHelperResult.RECHECK) { +- try { +- const state = await this._client.check_connectivity_async(null); +- if (state >= NM.ConnectivityState.FULL) +- this._closeConnectivityCheck(path); +- } catch (e) { } +- } else { +- log(`Invalid result from portal helper: ${result}`); +- } +- } +- +- async _syncConnectivity() { ++ _syncConnectivity() { + if (this._mainConnection == null || + this._mainConnection.state !== NM.ActiveConnectionState.ACTIVATED) { +- this._flushConnectivityQueue(); ++ this._portalHandler.clear(); + return; + } + +@@ -2116,35 +2167,7 @@ class Indicator extends SystemIndicator { + if (!isPortal || Main.sessionMode.isGreeter) + return; + +- let path = this._mainConnection.get_path(); +- if (this._connectivityQueue.has(path)) +- return; +- +- let timestamp = global.get_current_time(); +- if (!this._portalHelperProxy) { +- this._portalHelperProxy = new Gio.DBusProxy({ +- g_connection: Gio.DBus.session, +- g_name: 'org.gnome.Shell.PortalHelper', +- g_object_path: '/org/gnome/Shell/PortalHelper', +- g_interface_name: PortalHelperInfo.name, +- g_interface_info: PortalHelperInfo, +- }); +- this._portalHelperProxy.connectSignal('Done', +- (proxy, emitter, params) => { +- this._portalHelperDone(params).catch(logError); +- }); +- +- try { +- await this._portalHelperProxy.init_async( +- GLib.PRIORITY_DEFAULT, null); +- } catch (e) { +- console.error(`Error launching the portal helper: ${e.message}`); +- } +- } +- +- this._portalHelperProxy?.AuthenticateAsync(path, this._client.connectivity_check_uri, timestamp).catch(logError); +- +- this._connectivityQueue.add(path); ++ this._portalHandler.addConnection(this._mainConnection.get_path()); + } + + _updateIcon() { +-- +2.45.2 + + +From 44242a1a79a4d9b0311b735d484c996584bee0e2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 12 Jun 2024 13:13:41 +0200 +Subject: [PATCH 2/3] status/network: Show notification when detecting captive + portal + +When NetworkManager detects limited connectivity, we currently +pop up the portal helper window immediately. This can both be +disruptive when it happens unexpectedly, and unnoticeable +when it happens during screen lock. + +In any case, it seems better to not pop up a window without +explicit user action, so instead show a notification that +launches the portal window when activated. + +Closes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/7688 +--- + js/ui/status/network.js | 38 ++++++++++++++++++++++++++++++++++---- + 1 file changed, 34 insertions(+), 4 deletions(-) + +diff --git a/js/ui/status/network.js b/js/ui/status/network.js +index d34e947073..39140d0ce4 100644 +--- a/js/ui/status/network.js ++++ b/js/ui/status/network.js +@@ -1951,19 +1951,43 @@ class CaptivePortalHandler extends Signals.EventEmitter { + + this._checkUri = checkUri; + this._connectivityQueue = new Set(); ++ this._notifications = new Map(); + this._portalHelperProxy = null; + } + +- addConnection(path) { +- if (this._connectivityQueue.has(path)) ++ addConnection(name, path) { ++ if (this._connectivityQueue.has(path) || this._notifications.has(path)) + return; + +- this._launchPortalHelper(path).catch(logError); ++ const source = new MessageTray.getSystemSource(); ++ ++ const notification = new MessageTray.Notification({ ++ title: _('Sign Into Wi–Fi Network'), ++ body: name, ++ source, ++ }); ++ notification.connect('activated', ++ () => this._onNotificationActivated(path).catch(logError)); ++ notification.connect('destroy', ++ () => this._notifications.delete(path)); ++ this._notifications.set(path, notification); ++ source.addNotification(notification); + } + ++ + removeConnection(path) { + if (this._connectivityQueue.delete(path)) + this._portalHelperProxy?.CloseAsync(path); ++ this._notifications.get(path)?.destroy( ++ MessageTray.NotificationDestroyedReason.SOURCE_CLOSED); ++ this._notifications.delete(path); ++ } ++ ++ _onNotificationActivated(path) { ++ this._launchPortalHelper(path).catch(logError); ++ ++ Main.overview.hide(); ++ Main.panel.closeCalendar(); + } + + _portalHelperDone(parameters) { +@@ -2014,6 +2038,10 @@ class CaptivePortalHandler extends Signals.EventEmitter { + for (const item of this._connectivityQueue) + this._portalHelperProxy?.CloseAsync(item); + this._connectivityQueue.clear(); ++ ++ for (const n of this._notifications.values()) ++ n.destroy(MessageTray.NotificationDestroyedReason.SOURCE_CLOSED); ++ this._notifications.clear(); + } + } + +@@ -2167,7 +2195,9 @@ class Indicator extends SystemIndicator { + if (!isPortal || Main.sessionMode.isGreeter) + return; + +- this._portalHandler.addConnection(this._mainConnection.get_path()); ++ this._portalHandler.addConnection( ++ this._mainConnection.get_id(), ++ this._mainConnection.get_path()); + } + + _updateIcon() { +-- +2.45.2 + + +From b25485ef256068b53a852070bcb5fcf4c4a62875 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 12 Jun 2024 13:13:41 +0200 +Subject: [PATCH 3/3] build: Add option to disable portal-helper + +The portal login window uses WebKit, which is a security-sensitive +component that not all vendors want to support. + +Support that case with a build option, and update the captive +portal handler to use the user's default browser if the portal-helper +is disabled. +--- + data/icons/meson.build | 10 +++++++++- + data/meson.build | 2 +- + js/meson.build | 14 ++++++++------ + js/misc/config.js.in | 2 ++ + js/misc/meson.build | 1 + + js/ui/status/network.js | 15 +++++++++++---- + meson.build | 5 +++++ + meson_options.txt | 6 ++++++ + src/meson.build | 2 +- + 9 files changed, 44 insertions(+), 13 deletions(-) + +diff --git a/data/icons/meson.build b/data/icons/meson.build +index eff6e4b530..277df017b2 100644 +--- a/data/icons/meson.build ++++ b/data/icons/meson.build +@@ -1 +1,9 @@ +-install_subdir('hicolor', install_dir: icondir) ++excluded_icons=[] ++if not have_portal_helper ++ excluded_icons += [ ++ 'scalable/apps/org.gnome.Shell.CaptivePortal.svg', ++ 'symbolic/apps/org.gnome.Shell.CaptivePortal-symbolic.svg', ++ ] ++endif ++install_subdir('hicolor', ++ install_dir: icondir, exclude_files: excluded_icons) +diff --git a/data/meson.build b/data/meson.build +index 0307613e70..8b376a6d6b 100644 +--- a/data/meson.build ++++ b/data/meson.build +@@ -6,7 +6,7 @@ desktop_files = [ + ] + service_files = [] + +-if have_networkmanager ++if have_portal_helper + desktop_files += 'org.gnome.Shell.PortalHelper.desktop' + service_files += 'org.gnome.Shell.PortalHelper.service' + endif +diff --git a/js/meson.build b/js/meson.build +index 4809f82b83..e594e23627 100644 +--- a/js/meson.build ++++ b/js/meson.build +@@ -8,9 +8,11 @@ js_resources = gnome.compile_resources( + dependencies: [config_js] + ) + +-portal_resources = gnome.compile_resources( +- 'portal-resources', 'portal-resources.gresource.xml', +- source_dir: ['.', meson.current_build_dir()], +- c_name: 'portal_js_resources', +- dependencies: [config_js] +-) ++if have_portal_helper ++ portal_resources = gnome.compile_resources( ++ 'portal-resources', 'portal-resources.gresource.xml', ++ source_dir: ['.', meson.current_build_dir()], ++ c_name: 'portal_js_resources', ++ dependencies: [config_js] ++ ) ++endif +diff --git a/js/misc/config.js.in b/js/misc/config.js.in +index ad8d46d841..ce319e0f84 100644 +--- a/js/misc/config.js.in ++++ b/js/misc/config.js.in +@@ -7,6 +7,8 @@ export const PACKAGE_NAME = '@PACKAGE_NAME@'; + export const PACKAGE_VERSION = '@PACKAGE_VERSION@'; + /* 1 if networkmanager is available, 0 otherwise */ + export const HAVE_NETWORKMANAGER = @HAVE_NETWORKMANAGER@; ++/* 1 if portal helper is enabled, 0 otherwise */ ++export const HAVE_PORTAL_HELPER = @HAVE_PORTAL_HELPER@; + /* gettext package */ + export const GETTEXT_PACKAGE = '@GETTEXT_PACKAGE@'; + /* locale dir */ +diff --git a/js/misc/meson.build b/js/misc/meson.build +index 5aceefac42..5fc8ca433f 100644 +--- a/js/misc/meson.build ++++ b/js/misc/meson.build +@@ -4,6 +4,7 @@ jsconf.set('PACKAGE_VERSION', meson.project_version()) + jsconf.set('GETTEXT_PACKAGE', meson.project_name()) + jsconf.set('LIBMUTTER_API_VERSION', mutter_api_version) + jsconf.set10('HAVE_NETWORKMANAGER', have_networkmanager) ++jsconf.set10('HAVE_PORTAL_HELPER', have_portal_helper) + jsconf.set('datadir', datadir) + jsconf.set('libexecdir', libexecdir) + +diff --git a/js/ui/status/network.js b/js/ui/status/network.js +index 39140d0ce4..5832d96dc6 100644 +--- a/js/ui/status/network.js ++++ b/js/ui/status/network.js +@@ -10,6 +10,7 @@ import Polkit from 'gi://Polkit'; + import Shell from 'gi://Shell'; + import St from 'gi://St'; + ++import * as Config from '../../misc/config.js'; + import * as Main from '../main.js'; + import * as PopupMenu from '../popupMenu.js'; + import * as MessageTray from '../messageTray.js'; +@@ -1967,7 +1968,7 @@ class CaptivePortalHandler extends Signals.EventEmitter { + source, + }); + notification.connect('activated', +- () => this._onNotificationActivated(path).catch(logError)); ++ () => this._onNotificationActivated(path)); + notification.connect('destroy', + () => this._notifications.delete(path)); + this._notifications.set(path, notification); +@@ -1984,7 +1985,13 @@ class CaptivePortalHandler extends Signals.EventEmitter { + } + + _onNotificationActivated(path) { +- this._launchPortalHelper(path).catch(logError); ++ const context = global.create_app_launch_context( ++ global.get_current_time(), -1); ++ ++ if (Config.HAVE_PORTAL_HELPER) ++ this._launchPortalHelper(path, context).catch(logError); ++ else ++ Gio.AppInfo.launch_default_for_uri(this._checkUri, context); + + Main.overview.hide(); + Main.panel.closeCalendar(); +@@ -2007,8 +2014,7 @@ class CaptivePortalHandler extends Signals.EventEmitter { + } + } + +- async _launchPortalHelper(path) { +- const timestamp = global.get_current_time(); ++ async _launchPortalHelper(path, context) { + if (!this._portalHelperProxy) { + this._portalHelperProxy = new Gio.DBusProxy({ + g_connection: Gio.DBus.session, +@@ -2030,6 +2036,7 @@ class CaptivePortalHandler extends Signals.EventEmitter { + } + } + ++ const {timestamp} = context; + this._portalHelperProxy?.AuthenticateAsync(path, this._checkUri, timestamp).catch(logError); + this._connectivityQueue.add(path); + } +diff --git a/meson.build b/meson.build +index 923a5228ec..d554045c5b 100644 +--- a/meson.build ++++ b/meson.build +@@ -101,6 +101,11 @@ else + have_networkmanager = false + endif + ++have_portal_helper = get_option('portal_helper') ++if have_portal_helper and not have_networkmanager ++ error('Portal helper requires networkmanager support') ++endif ++ + if get_option('camera_monitor') + libpipewire_dep = dependency('libpipewire-0.3', version: pipewire_req) + have_pipewire = true +diff --git a/meson_options.txt b/meson_options.txt +index 6e83d92f2e..01e0d5803b 100644 +--- a/meson_options.txt ++++ b/meson_options.txt +@@ -40,6 +40,12 @@ option('networkmanager', + description: 'Enable NetworkManager support' + ) + ++option('portal_helper', ++ type: 'boolean', ++ value: true, ++ description: 'Enable build-in network portal login' ++) ++ + option('systemd', + type: 'boolean', + value: true, +diff --git a/src/meson.build b/src/meson.build +index c81bd1a42a..d4445743bd 100644 +--- a/src/meson.build ++++ b/src/meson.build +@@ -258,7 +258,7 @@ executable('gnome-shell', 'main.c', + install: true + ) + +-if have_networkmanager ++if have_portal_helper + executable('gnome-shell-portal-helper', + 'gnome-shell-portal-helper.c', portal_resources, + c_args: tools_cflags, +-- +2.45.2 +