From 1bd450b11456aa10d01ab84865f63304edb9c5fc Mon Sep 17 00:00:00 2001 From: Katerina Koukiou Date: Tue, 3 Sep 2024 09:48:54 +0200 Subject: [PATCH] Open external links in firefox without the custom profile * Extended firefox-theme to include an extlink profile for opening external links. * Disabled the popup asking for verification by using dom.disable_beforeunload, preventing the confirmation dialog when closing the window. * Removed the custom window.onbeforeunload = () => "";, as it interfered with the external window opening behavior. Note: A new approach will be needed to prevent the window from closing, as the previous method is no longer in use. --- Makefile | 5 +- extlinks.desktop | 66 ++++++++++++++++++++++++ firefox-ext | 37 +++++++++++++ firefox-theme/default/user.js | 6 +++ firefox-theme/extlink/user.js | 5 ++ firefox-theme/live/user.js | 11 ++-- packaging/anaconda-webui.spec.in | 7 +++ src/components/Error.jsx | 17 ++++-- src/components/HeaderKebab.jsx | 7 +-- src/components/app.jsx | 6 +-- src/components/installation/Feedback.jsx | 11 +++- 11 files changed, 158 insertions(+), 20 deletions(-) create mode 100644 extlinks.desktop create mode 100755 firefox-ext create mode 100644 firefox-theme/extlink/user.js diff --git a/Makefile b/Makefile index 449ee10cb9..4d4fcef588 100644 --- a/Makefile +++ b/Makefile @@ -77,7 +77,7 @@ po/LINGUAS: # all: $(DIST_TEST) -dist_libexec_SCRIPTS = webui-desktop +dist_libexec_SCRIPTS = webui-desktop firefox-ext # makes sure it gets built as part of `make` and `make dist` dist_noinst_DATA = \ $(DIST_TEST) \ @@ -108,10 +108,13 @@ install: $(DIST_TEST) po/LINGUAS rm $(DESTDIR)/usr/share/cockpit/$(PACKAGE_NAME)/index.css.LEGAL.txt mkdir -p $(DESTDIR)/usr/share/anaconda cp -r firefox-theme $(DESTDIR)/usr/share/anaconda/ + mkdir -p $(DESTDIR)/usr/share/applications + cp extlinks.desktop $(DESTDIR)/usr/share/applications/ mkdir -p $(DESTDIR)/usr/share/metainfo/ cp org.cockpit-project.$(PACKAGE_NAME).metainfo.xml $(DESTDIR)/usr/share/metainfo/ mkdir -p $(DESTDIR)/usr/libexec/anaconda cp webui-desktop $(DESTDIR)/usr/libexec/anaconda + cp firefox-ext $(DESTDIR)/usr/libexec/anaconda ln -sTfr $(DESTDIR)/usr/share/pixmaps/fedora-logo-sprite.svg $(DESTDIR)/usr/share/cockpit/$(PACKAGE_NAME)/logo.svg # required for running integration tests; diff --git a/extlinks.desktop b/extlinks.desktop new file mode 100644 index 0000000000..24a36ea387 --- /dev/null +++ b/extlinks.desktop @@ -0,0 +1,66 @@ +[Desktop Entry] +Version=1.0 +Name=Firefox External +GenericName=Web Browser +GenericName[ca]=Navegador web +GenericName[cs]=Webový prohlížeč +GenericName[es]=Navegador web +GenericName[fa]=مرورگر اینترنتی +GenericName[fi]=WWW-selain +GenericName[fr]=Navigateur Web +GenericName[hu]=Webböngésző +GenericName[it]=Browser Web +GenericName[ja]=ウェブ・ブラウザ +GenericName[ko]=웹 브라우저 +GenericName[nb]=Nettleser +GenericName[nl]=Webbrowser +GenericName[nn]=Nettlesar +GenericName[no]=Nettleser +GenericName[pl]=Przeglądarka WWW +GenericName[pt]=Navegador Web +GenericName[pt_BR]=Navegador Web +GenericName[sk]=Internetový prehliadač +GenericName[sv]=Webbläsare +Comment=Browse the Web +Comment[ca]=Navegueu per el web +Comment[cs]=Prohlížení stránek World Wide Webu +Comment[de]=Im Internet surfen +Comment[es]=Navegue por la web +Comment[fa]=صفحات شبکه جهانی اینترنت را مرور نمایید +Comment[fi]=Selaa Internetin WWW-sivuja +Comment[fr]=Navigue sur Internet +Comment[hu]=A világháló böngészése +Comment[it]=Esplora il web +Comment[ja]=ウェブを閲覧します +Comment[ko]=웹을 돌아 다닙니다 +Comment[nb]=Surf på nettet +Comment[nl]=Verken het internet +Comment[nn]=Surf på nettet +Comment[no]=Surf på nettet +Comment[pl]=Przeglądanie stron WWW +Comment[pt]=Navegue na Internet +Comment[pt_BR]=Navegue na Internet +Comment[sk]=Prehliadanie internetu +Comment[sv]=Surfa på webben +Exec=/usr/libexec/anaconda/firefox-ext %u +Icon=firefox +Terminal=false +Type=Application +MimeType=x-scheme-handler/extlink; +StartupNotify=true +Categories=Network;WebBrowser; +Actions=new-window;new-private-window;profile-manager-window; +X-Desktop-File-Install-Version=0.26 + + +[Desktop Action new-window] +Name=Open a New Window +Exec=firefox -new-window + +[Desktop Action new-private-window] +Name=Open a New Private Window +Exec=firefox -private-window + +[Desktop Action profile-manager-window] +Name=Open Profile Manager +Exec=firefox -ProfileManager diff --git a/firefox-ext b/firefox-ext new file mode 100755 index 0000000000..4356292894 --- /dev/null +++ b/firefox-ext @@ -0,0 +1,37 @@ +#!/usr/bin/bash +# +# The contents of this file are subject to the Netscape Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/NPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# + +## +## Usage: +## +## $ firefox-ext +## +## This script is meant to run a mozilla program from the mozilla +## rpm installation. +## +## The script will setup all the environment voodoo needed to make +## mozilla work. + +mkdir -p /tmp/anaconda-extlink-firefox-profile +cp /usr/share/anaconda/firefox-theme/extlink/user.js /tmp/anaconda-extlink-firefox-profile/ + +/usr/bin/firefox --profile /tmp/anaconda-extlink-firefox-profile -no-remote "${1/extlink/"https"}" diff --git a/firefox-theme/default/user.js b/firefox-theme/default/user.js index 95f49403da..74da3642a2 100644 --- a/firefox-theme/default/user.js +++ b/firefox-theme/default/user.js @@ -45,3 +45,9 @@ user_pref("datareporting.healthreport.uploadEnabled", false); user_pref("datareporting.policy.dataSubmissionEnabled", false); user_pref("toolkit.telemetry.unified", false); user_pref("trailhead.firstrun.didSeeAboutWelcome", true); + +// Don't show `Allow this site to open the PROTOCOL link with APPLICATION` dialog +user_pref("security.external_protocol_requires_permission", false); + +// Don't show the `This site is trying to open a popup` dialog +user_pref("dom.disable_beforeunload", true); diff --git a/firefox-theme/extlink/user.js b/firefox-theme/extlink/user.js new file mode 100644 index 0000000000..892af2f8b7 --- /dev/null +++ b/firefox-theme/extlink/user.js @@ -0,0 +1,5 @@ +/* global user_pref */ +// Don't have any startup page +user_pref("browser.startup.page", 0); +user_pref("browser.startup.homepage", "about:blank"); +user_pref("browser.startup.homepage_override.once", {}); diff --git a/firefox-theme/live/user.js b/firefox-theme/live/user.js index 15caec361d..a179789188 100644 --- a/firefox-theme/live/user.js +++ b/firefox-theme/live/user.js @@ -5,11 +5,6 @@ user_pref("toolkit.legacyUserProfileCustomizations.stylesheets", true); // We want to use :has() user_pref("layout.css.has-selector.enabled", true); -// New windows, not tabs -user_pref("browser.link.open_newwindow", 2); -user_pref("browser.link.open_newwindow.restriction", 1); -user_pref("browser.link.open_newwindow.override.external", 2); - // Dev stuff (for easier UI adusting with ctrl+shift+alt+i) user_pref("browser.aboutConfig.showWarning", false); user_pref("devtools.chrome.enabled", true); @@ -42,3 +37,9 @@ user_pref("datareporting.healthreport.uploadEnabled", false); user_pref("datareporting.policy.dataSubmissionEnabled", false); user_pref("toolkit.telemetry.unified", false); user_pref("trailhead.firstrun.didSeeAboutWelcome", true); + +// Don't show `Allow this site to open the PROTOCOL link with APPLICATION` dialog +user_pref("security.external_protocol_requires_permission", false); + +// Don't show the `This site is trying to open a popup` dialog +user_pref("dom.disable_beforeunload", true); diff --git a/packaging/anaconda-webui.spec.in b/packaging/anaconda-webui.spec.in index 9516e06890..f15af3a72a 100644 --- a/packaging/anaconda-webui.spec.in +++ b/packaging/anaconda-webui.spec.in @@ -37,6 +37,7 @@ Requires: firefox %if 0%{?fedora} Requires: fedora-logos %endif +BuildRequires: desktop-file-utils %{NPM_PROVIDES} @@ -53,6 +54,8 @@ Anaconda installer Web interface %make_install PREFIX=/usr appstream-util validate-relax --nonet %{buildroot}/%{_datadir}/metainfo/* +desktop-file-install --dir=%{buildroot}%{_datadir}/applications %{buildroot}%{_datadir}/applications/extlinks.desktop + %check exit 0 # We have some integration tests, but those require running a VM, so that would @@ -82,7 +85,11 @@ exit 0 %dir %{_datadir}/anaconda/firefox-theme/live/chrome %{_datadir}/anaconda/firefox-theme/live/user.js %{_datadir}/anaconda/firefox-theme/live/chrome/userChrome.css +%dir %{_datadir}/anaconda/firefox-theme/extlink +%{_datadir}/anaconda/firefox-theme/extlink/user.js %{_libexecdir}/anaconda/webui-desktop +%{_libexecdir}/anaconda/firefox-ext +%{_datadir}/applications/extlinks.desktop # The changelog is automatically generated and merged diff --git a/src/components/Error.jsx b/src/components/Error.jsx index 15ec0bdbf9..696a20591e 100644 --- a/src/components/Error.jsx +++ b/src/components/Error.jsx @@ -45,7 +45,7 @@ import "./Error.scss"; const _ = cockpit.gettext; -export const bugzillaPrefiledReportURL = (productQueryData) => { +export const bugzillaPrefiledReportURL = (productQueryData, isBootIso) => { const baseURL = "https://bugzilla.redhat.com"; const queryData = { ...productQueryData, @@ -55,7 +55,11 @@ export const bugzillaPrefiledReportURL = (productQueryData) => { const reportURL = new URL(baseURL); reportURL.pathname = "enter_bug.cgi"; Object.keys(queryData).map(query => reportURL.searchParams.append(query, queryData[query])); - return reportURL.href; + if (isBootIso) { + return reportURL.href; + } else { + return reportURL.href.replace("https", "extlink"); + } }; const ensureMaximumReportURLLength = (reportURL) => { @@ -99,11 +103,13 @@ export const BZReportModal = ({ }) => { const [logContent, setLogContent] = useState(); const [preparingReport, setPreparingReport] = useState(false); + const isBootIso = useContext(SystemTypeContext) === "BOOT_ISO"; useEffect(() => { cockpit.spawn(["journalctl", "-a"]) .then(content => setLogContent(content)); }, []); + const windowOpenArgs = isBootIso ? ["_blank", "noopener,noreferer"] : []; const openBZIssue = (reportURL, logFile, logContent) => { reportURL = ensureMaximumReportURLLength(reportURL); @@ -113,10 +119,9 @@ export const BZReportModal = ({ .file(logFile) .replace(logContent) .always(() => setPreparingReport(false)) - .then(() => window.open(reportURL, "_blank", "noopener,noreferer")); + .then(() => window.location.replace(reportURL, ...windowOpenArgs)); }; - const isBootIso = useContext(SystemTypeContext) === "BOOT_ISO"; const networkHelperMessageLive = _("Network not available. Configure the network in the top bar menu to report the issue."); const networkHelperMessageBootIso = _("Network not available. Configure the network to report the issue."); @@ -146,7 +151,9 @@ export const BZReportModal = ({ isLoading={preparingReport} isDisabled={logContent === undefined || preparingReport || !isConnected} icon={} - onClick={() => openBZIssue(reportLinkURL, logFile, logContent)} + onClick={() => { openBZIssue(reportLinkURL, logFile, logContent); return false }} + href={reportLinkURL} + target={isBootIso ? "_blank" : ""} component="a"> {preparingReport ? _("Preparing report") : _("Report issue")} diff --git a/src/components/HeaderKebab.jsx b/src/components/HeaderKebab.jsx index f43e939b7c..4c633a122e 100644 --- a/src/components/HeaderKebab.jsx +++ b/src/components/HeaderKebab.jsx @@ -39,7 +39,7 @@ import { import { getAnacondaVersion } from "../helpers/product.js"; -import { OsReleaseContext } from "./Common.jsx"; +import { OsReleaseContext, SystemTypeContext } from "./Common.jsx"; import { UserIssue } from "./Error.jsx"; import { CockpitStorageIntegration, ModifyStorage } from "./storage/CockpitStorageIntegration.jsx"; @@ -76,6 +76,7 @@ const ProductName = () => { }; const AnacondaAboutModal = ({ isModalOpen, setIsAboutModalOpen }) => { + const isBootIso = useContext(SystemTypeContext) === "BOOT_ISO"; const toggleModal = () => { setIsAboutModalOpen(!isModalOpen); }; @@ -95,8 +96,8 @@ const AnacondaAboutModal = ({ isModalOpen, setIsAboutModalOpen }) => { id="anaconda-page-button" variant="link" icon={} - href="https://github.com/rhinstaller/anaconda" - target="_blank" + href={(isBootIso ? "https://" : "extlink://") + "github.com/rhinstaller/anaconda"} + target={isBootIso ? "_blank" : ""} component="a"> {_("Anaconda project page")} diff --git a/src/components/app.jsx b/src/components/app.jsx index 82c79d5aba..c82c9dba5f 100644 --- a/src/components/app.jsx +++ b/src/components/app.jsx @@ -58,9 +58,6 @@ export const Application = ({ conf, dispatch, isFetching, onCritFail, osRelease, return; } - // Before unload ask the user for verification - window.onbeforeunload = () => ""; - Promise.all(clients.map(Client => new Client(address, dispatch).init())) .then(() => { setStoreInitialized(true); @@ -153,6 +150,7 @@ export const ApplicationWithErrorBoundary = () => { ); const conf = useConf({ onCritFail }); const osRelease = useOsRelease({ onCritFail }); + const isBootIso = conf?.["Installation System"].type === "BOOT_ISO"; if (!conf || !osRelease) { return ; @@ -161,7 +159,7 @@ export const ApplicationWithErrorBoundary = () => { const bzReportURL = bugzillaPrefiledReportURL({ product: osRelease.REDHAT_BUGZILLA_PRODUCT, version: osRelease.REDHAT_BUGZILLA_PRODUCT_VERSION, - }); + }, isBootIso); return ( diff --git a/src/components/installation/Feedback.jsx b/src/components/installation/Feedback.jsx index a94a16f263..a8c74d6514 100644 --- a/src/components/installation/Feedback.jsx +++ b/src/components/installation/Feedback.jsx @@ -16,7 +16,7 @@ */ import cockpit from "cockpit"; -import React from "react"; +import React, { useContext } from "react"; import { Flex, Text, @@ -24,19 +24,26 @@ import { } from "@patternfly/react-core"; import feedbackQRcode from "../../../images/qr-code-feedback.svg"; +import { SystemTypeContext } from "../Common.jsx"; import "./Feedback.scss"; const _ = cockpit.gettext; export const Feedback = () => { + const isBootIso = useContext(SystemTypeContext) === "BOOT_ISO"; + return ( {_("Send us feedback on your installation")} {_("Scan the QR code with your phone or visit:")} - + https://discussion.fedoraproject.org/tag/anaconda