From 3e4131b89a65e496e7de92086b7dd8ea23926efc Mon Sep 17 00:00:00 2001 From: Allen Houchins <32207388+allenhouchins@users.noreply.github.com> Date: Tue, 18 Nov 2025 22:34:15 -0600 Subject: [PATCH] Add Opera as a macOS FMA (#35966) Introduced Opera as a maintained app for macOS, including input and output JSON definitions, install/uninstall scripts, an SVG icon component, and the app icon image. Updated the apps list to include Opera with relevant metadata. **Related issue:** Resolves # # Checklist for submitter If some of the following don't apply, delete the relevant line. - [ ] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files) for more information. - [ ] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements) - [ ] If paths of existing endpoints are modified without backwards compatibility, checked the frontend/CLI for any necessary changes ## Testing - [ ] Added/updated automated tests - [ ] Where appropriate, [automated tests simulate multiple hosts and test for host isolation](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/reference/patterns-backend.md#unit-testing) (updates to one hosts's records do not affect another) - [ ] QA'd all new/changed functionality manually For unreleased bug fixes in a release candidate, one of: - [ ] Confirmed that the fix is not expected to adversely impact load test results - [ ] Alerted the release DRI if additional load testing is needed ## Database migrations - [ ] Checked schema for all modified table for columns that will auto-update timestamps during migration. - [ ] Confirmed that updating the timestamps is acceptable, and will not cause unwanted side effects. - [ ] Ensured the correct collation is explicitly set for character columns (`COLLATE utf8mb4_unicode_ci`). ## New Fleet configuration settings - [ ] Setting(s) is/are explicitly excluded from GitOps If you didn't check the box above, follow this checklist for GitOps-enabled settings: - [ ] Verified that the setting is exported via `fleetctl generate-gitops` - [ ] Verified the setting is documented in a separate PR to [the GitOps documentation](https://github.com/fleetdm/fleet/blob/main/docs/Configuration/yaml-files.md#L485) - [ ] Verified that the setting is cleared on the server if it is not supplied in a YAML file (or that it is documented as being optional) - [ ] Verified that any relevant UI is disabled when GitOps mode is enabled ## fleetd/orbit/Fleet Desktop - [ ] Verified compatibility with the latest released version of Fleet (see [Must rule](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/workflows/fleetd-development-and-release-strategy.md)) - [ ] If the change applies to only one platform, confirmed that `runtime.GOOS` is used as needed to isolate changes - [ ] Verified that fleetd runs on macOS, Linux and Windows - [ ] Verified auto-update works from the released version of component to the new version (see [tools/tuf/test](../tools/tuf/test/README.md)) --- ee/maintained-apps/inputs/homebrew/opera.json | 8 +++++++ ee/maintained-apps/outputs/apps.json | 7 ++++++ ee/maintained-apps/outputs/opera/darwin.json | 21 ++++++++++++++++++ .../SoftwarePage/components/icons/Opera.tsx | 14 ++++++++++++ .../assets/images/app-icon-opera-60x60@2x.png | Bin 0 -> 4725 bytes 5 files changed, 50 insertions(+) create mode 100644 ee/maintained-apps/inputs/homebrew/opera.json create mode 100644 ee/maintained-apps/outputs/opera/darwin.json create mode 100644 frontend/pages/SoftwarePage/components/icons/Opera.tsx create mode 100644 website/assets/images/app-icon-opera-60x60@2x.png diff --git a/ee/maintained-apps/inputs/homebrew/opera.json b/ee/maintained-apps/inputs/homebrew/opera.json new file mode 100644 index 0000000000..9b195fca8b --- /dev/null +++ b/ee/maintained-apps/inputs/homebrew/opera.json @@ -0,0 +1,8 @@ +{ + "name": "Opera", + "unique_identifier": "com.operasoftware.Opera", + "token": "opera", + "installer_format": "dmg", + "slug": "opera/darwin", + "default_categories": ["Browsers"] +} diff --git a/ee/maintained-apps/outputs/apps.json b/ee/maintained-apps/outputs/apps.json index 44fd2b68af..bbf9600bb2 100644 --- a/ee/maintained-apps/outputs/apps.json +++ b/ee/maintained-apps/outputs/apps.json @@ -372,6 +372,13 @@ "unique_identifier": "com.omnissa.horizon.client.mac", "description": "Omnissa Horizon Client is a tool end users use to access remote virtual desktops." }, + { + "name": "Opera", + "slug": "opera/darwin", + "platform": "darwin", + "unique_identifier": "com.operasoftware.Opera", + "description": "Opera is a web browser." + }, { "name": "P4V", "slug": "p4v/darwin", diff --git a/ee/maintained-apps/outputs/opera/darwin.json b/ee/maintained-apps/outputs/opera/darwin.json new file mode 100644 index 0000000000..d74d65cec6 --- /dev/null +++ b/ee/maintained-apps/outputs/opera/darwin.json @@ -0,0 +1,21 @@ +{ + "versions": [ + { + "version": "124.0.5705.15", + "queries": { + "exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.operasoftware.Opera';" + }, + "installer_url": "https://get.geo.opera.com/pub/opera/desktop/124.0.5705.15/mac/Opera_124.0.5705.15_Setup.dmg", + "install_script_ref": "57501273", + "uninstall_script_ref": "f3ba65ab", + "sha256": "0c4f1dbc7d27348e98d9e0b2675e47bde6441a4ae37d1f8023632bdf1bcf7fea", + "default_categories": [ + "Browsers" + ] + } + ], + "refs": { + "57501273": "#!/bin/sh\n\n# variables\nAPPDIR=\"/Applications/\"\nTMPDIR=$(dirname \"$(realpath $INSTALLER_PATH)\")\n# functions\n\nquit_application() {\n local bundle_id=\"$1\"\n local timeout_duration=10\n\n # check if the application is running\n if ! osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ $EUID -eq 0 && \"$console_user\" == \"root\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n\n# extract contents\nMOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)\nhdiutil attach -plist -nobrowse -readonly -mountpoint \"$MOUNT_POINT\" \"$INSTALLER_PATH\"\nsudo cp -R \"$MOUNT_POINT\"/* \"$TMPDIR\"\nhdiutil detach \"$MOUNT_POINT\"\n# copy to the applications folder\nquit_application 'com.operasoftware.Opera'\nif [ -d \"$APPDIR/Opera.app\" ]; then\n\tsudo mv \"$APPDIR/Opera.app\" \"$TMPDIR/Opera.app.bkp\"\nfi\nsudo cp -R \"$TMPDIR/Opera.app\" \"$APPDIR\"\n", + "f3ba65ab": "#!/bin/sh\n\n# variables\nAPPDIR=\"/Applications/\"\nLOGGED_IN_USER=$(scutil <<< \"show State:/Users/ConsoleUser\" | awk '/Name :/ { print $3 }')\n# functions\n\ntrash() {\n local logged_in_user=\"$1\"\n local target_file=\"$2\"\n local timestamp=\"$(date +%Y-%m-%d-%s)\"\n local rand=\"$(jot -r 1 0 99999)\"\n\n # replace ~ with /Users/$logged_in_user\n if [[ \"$target_file\" == ~* ]]; then\n target_file=\"/Users/$logged_in_user${target_file:1}\"\n fi\n\n local trash=\"/Users/$logged_in_user/.Trash\"\n local file_name=\"$(basename \"${target_file}\")\"\n\n if [[ -e \"$target_file\" ]]; then\n echo \"removing $target_file.\"\n mv -f \"$target_file\" \"$trash/${file_name}_${timestamp}_${rand}\"\n else\n echo \"$target_file doesn't exist.\"\n fi\n}\n\nsudo rm -rf \"$APPDIR/Opera.app\"\ntrash $LOGGED_IN_USER '~/Library/Application Support/com.operasoftware.Opera'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.operasoftware.Installer.Opera'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.operasoftware.Opera'\ntrash $LOGGED_IN_USER '~/Library/Cookies/com.operasoftware.Opera.binarycookies'\ntrash $LOGGED_IN_USER '~/Library/HTTPStorages/com.operasoftware.Installer.Opera'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.operasoftware.Opera.plist'\ntrash $LOGGED_IN_USER '~/Library/Saved Application State/com.operasoftware.Opera.savedState'\n" + } +} diff --git a/frontend/pages/SoftwarePage/components/icons/Opera.tsx b/frontend/pages/SoftwarePage/components/icons/Opera.tsx new file mode 100644 index 0000000000..1fa08bcee8 --- /dev/null +++ b/frontend/pages/SoftwarePage/components/icons/Opera.tsx @@ -0,0 +1,14 @@ +import * as React from "react"; + +import type { SVGProps } from "react"; + +const Opera = (props: SVGProps) => ( + + + +); +export default Opera; diff --git a/website/assets/images/app-icon-opera-60x60@2x.png b/website/assets/images/app-icon-opera-60x60@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b962e04cf79d060b23d49d0c0c3ea27a3dacc772 GIT binary patch literal 4725 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 VDL6Q1;P~(5qouB^R;gkg`ak$*y@>z- literal 0 HcmV?d00001