diff --git a/ee/maintained-apps/inputs/homebrew/google-drive.json b/ee/maintained-apps/inputs/homebrew/google-drive.json new file mode 100644 index 0000000000..eac6182765 --- /dev/null +++ b/ee/maintained-apps/inputs/homebrew/google-drive.json @@ -0,0 +1,8 @@ +{ + "name": "Google Drive", + "slug": "google-drive/darwin", + "unique_identifier": "com.google.drivefs", + "token": "google-drive", + "installer_format": "dmg", + "default_categories": ["Productivity"] +} diff --git a/ee/maintained-apps/inputs/winget/google-drive.json b/ee/maintained-apps/inputs/winget/google-drive.json new file mode 100644 index 0000000000..7f68f0b4e3 --- /dev/null +++ b/ee/maintained-apps/inputs/winget/google-drive.json @@ -0,0 +1,12 @@ +{ + "name": "Google Drive", + "slug": "google-drive/windows", + "package_identifier": "Google.GoogleDrive", + "unique_identifier": "Google Drive", + "install_script_path": "ee/maintained-apps/inputs/winget/scripts/google_drive_install.ps1", + "uninstall_script_path": "ee/maintained-apps/inputs/winget/scripts/google_drive_uninstall.ps1", + "installer_arch": "x64", + "installer_type": "exe", + "installer_scope": "machine", + "default_categories": ["Productivity"] +} diff --git a/ee/maintained-apps/inputs/winget/scripts/google_drive_install.ps1 b/ee/maintained-apps/inputs/winget/scripts/google_drive_install.ps1 new file mode 100644 index 0000000000..c7b959a1a3 --- /dev/null +++ b/ee/maintained-apps/inputs/winget/scripts/google_drive_install.ps1 @@ -0,0 +1,23 @@ +$exeFilePath = "${env:INSTALLER_PATH}" + +try { + +$processOptions = @{ + FilePath = "$exeFilePath" + ArgumentList = "--silent --skip_launch_new --gsuite_shortcuts=false" + PassThru = $true + Wait = $true +} + +# Start process and track exit code +$process = Start-Process @processOptions +$exitCode = $process.ExitCode + +# Prints the exit code +Write-Host "Install exit code: $exitCode" +Exit $exitCode + +} catch { + Write-Host "Error: $_" + Exit 1 +} diff --git a/ee/maintained-apps/inputs/winget/scripts/google_drive_uninstall.ps1 b/ee/maintained-apps/inputs/winget/scripts/google_drive_uninstall.ps1 new file mode 100644 index 0000000000..19107e150f --- /dev/null +++ b/ee/maintained-apps/inputs/winget/scripts/google_drive_uninstall.ps1 @@ -0,0 +1,79 @@ +$softwareName = "Google Drive" + +$uninstallArgs = "--silent --force_stop" + +$expectedExitCodes = @() + +$machineKey = ` + 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*' +$machineKey32on64 = ` + 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*' + +$exitCode = 0 + +try { + + [array]$uninstallKeys = Get-ChildItem ` + -Path @($machineKey, $machineKey32on64) ` + -ErrorAction SilentlyContinue | + ForEach-Object { Get-ItemProperty $_.PSPath } + + $foundUninstaller = $false + foreach ($key in $uninstallKeys) { + if ($key.DisplayName -eq $softwareName) { + $foundUninstaller = $true + # Get the uninstall command. + $uninstallCommand = if ($key.QuietUninstallString) { + $key.QuietUninstallString + } else { + $key.UninstallString + } + + # Split the command and args + $splitArgs = $uninstallCommand.Split('"') + if ($splitArgs.Length -gt 1) { + if ($splitArgs.Length -eq 3) { + $uninstallArgs = "$( $splitArgs[2] ) $uninstallArgs".Trim() + } elseif ($splitArgs.Length -gt 3) { + Throw ` + "Uninstall command contains multiple quoted strings. " + + "Please update the uninstall script.`n" + + "Uninstall command: $uninstallCommand" + } + $uninstallCommand = $splitArgs[1] + } + Write-Host "Uninstall command: $uninstallCommand" + Write-Host "Uninstall args: $uninstallArgs" + + $processOptions = @{ + FilePath = $uninstallCommand + PassThru = $true + Wait = $true + ArgumentList = "$uninstallArgs".Split(' ') + NoNewWindow = $true + } + + # Start process and track exit code + $process = Start-Process @processOptions + $exitCode = $process.ExitCode + + Write-Host "Uninstall exit code: $exitCode" + break + } + } + + if (-not $foundUninstaller) { + Write-Host "Uninstaller for '$softwareName' not found." + Exit 1 + } + +} catch { + Write-Host "Error: $_" + Exit 1 +} + +if ($expectedExitCodes -contains $exitCode) { + $exitCode = 0 +} + +Exit $exitCode diff --git a/ee/maintained-apps/outputs/apps.json b/ee/maintained-apps/outputs/apps.json index 6cf2028366..3db64904bb 100644 --- a/ee/maintained-apps/outputs/apps.json +++ b/ee/maintained-apps/outputs/apps.json @@ -232,6 +232,20 @@ "unique_identifier": "Google Chrome", "description": "Google Chrome Enterprise is a fast, reliable web browser built for performance and compatibility across platforms." }, + { + "name": "Google Drive", + "slug": "google-drive/darwin", + "platform": "darwin", + "unique_identifier": "com.google.drivefs", + "description": "Google Drive is a cloud storage service that allows you to store, sync, and share files across devices with seamless access to your Google Workspace content." + }, + { + "name": "Google Drive", + "slug": "google-drive/windows", + "platform": "windows", + "unique_identifier": "Google Drive", + "description": "Google Drive is a cloud storage service that allows you to store, sync, and share files across devices with seamless access to your Google Workspace content." + }, { "name": "iMazing Profile Editor", "slug": "imazing-profile-editor/darwin", diff --git a/ee/maintained-apps/outputs/google-drive/darwin.json b/ee/maintained-apps/outputs/google-drive/darwin.json new file mode 100644 index 0000000000..7998df5373 --- /dev/null +++ b/ee/maintained-apps/outputs/google-drive/darwin.json @@ -0,0 +1,21 @@ +{ + "versions": [ + { + "version": "117.0.0", + "queries": { + "exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.google.drivefs';" + }, + "installer_url": "https://dl.google.com/drive-file-stream/5-percent/GoogleDrive.dmg", + "install_script_ref": "b1cef788", + "uninstall_script_ref": "9f918e97", + "sha256": "no_check", + "default_categories": [ + "Productivity" + ] + } + ], + "refs": { + "9f918e97": "#!/bin/sh\n\n# variables\nLOGGED_IN_USER=$(scutil <<< \"show State:/Users/ConsoleUser\" | awk '/Name :/ { print $3 }')\n# functions\n\nexpand_pkgid_and_map() {\n local PKGID=\"$1\"\n local FUNC=\"$2\"\n if [[ \"$PKGID\" == *\"*\" ]]; then\n local prefix=\"${PKGID%\\*}\"\n echo \"Expanding wildcard for PKGID: $PKGID\"\n for receipt in $(pkgutil --pkgs | grep \"^${prefix}\"); do\n echo \"Processing $receipt\"\n \"$FUNC\" \"$receipt\"\n done\n else\n \"$FUNC\" \"$PKGID\"\n fi\n}\n\nforget_pkg() {\n local PKGID=\"$1\"\n expand_pkgid_and_map \"$PKGID\" forget_receipt\n}\n\nforget_receipt() {\n local PKGID=\"$1\"\n sudo pkgutil --forget \"$PKGID\"\n}\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\nremove_launchctl_service() {\n local service=\"$1\"\n local booleans=(\"true\" \"false\")\n local plist_status\n local paths\n local should_sudo\n\n echo \"Removing launchctl service ${service}\"\n\n for should_sudo in \"${booleans[@]}\"; do\n plist_status=$(launchctl list \"${service}\" 2>/dev/null)\n\n if [[ $plist_status == \\{* ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo launchctl remove \"${service}\"\n else\n launchctl remove \"${service}\"\n fi\n sleep 1\n fi\n\n paths=(\n \"/Library/LaunchAgents/${service}.plist\"\n \"/Library/LaunchDaemons/${service}.plist\"\n )\n\n # if not using sudo, prepend the home directory to the paths\n if [[ $should_sudo == \"false\" ]]; then\n for i in \"${!paths[@]}\"; do\n paths[i]=\"${HOME}${paths[i]}\"\n done\n fi\n\n for path in \"${paths[@]}\"; do\n if [[ -e \"$path\" ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo rm -f -- \"$path\"\n else\n rm -f -- \"$path\"\n fi\n fi\n done\n done\n}\n\nremove_pkg_files() {\n local PKGID=\"$1\"\n expand_pkgid_and_map \"$PKGID\" remove_receipt_files\n}\n\nremove_receipt_files() {\n local PKGID=\"$1\"\n local PKGINFO VOLUME INSTALL_LOCATION FULL_INSTALL_LOCATION\n\n echo \"pkgutil --pkg-info-plist \\\"$PKGID\\\"\"\n PKGINFO=$(pkgutil --pkg-info-plist \"$PKGID\")\n VOLUME=$(echo \"$PKGINFO\" | awk '/volume<\\/key>/ {getline; gsub(/.*|<\\/string>.*/, \"\"); print}')\n INSTALL_LOCATION=$(echo \"$PKGINFO\" | awk '/install-location<\\/key>/ {getline; gsub(/.*|<\\/string>.*/, \"\"); print}')\n\n if [ -z \"$INSTALL_LOCATION\" ] || [ \"$INSTALL_LOCATION\" = \"/\" ]; then\n FULL_INSTALL_LOCATION=\"$VOLUME\"\n else\n FULL_INSTALL_LOCATION=\"$VOLUME/$INSTALL_LOCATION\"\n FULL_INSTALL_LOCATION=$(echo \"$FULL_INSTALL_LOCATION\" | sed 's|//|/|g')\n fi\n\n echo \"sudo pkgutil --only-files --files \\\"$PKGID\\\" | sed \\\"s|^|${FULL_INSTALL_LOCATION}/|\\\" | tr '\\\\\\\\n' '\\\\\\\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\"\n sudo pkgutil --only-files --files \"$PKGID\" | sed \"s|^|/${INSTALL_LOCATION}/|\" | tr '\\n' '\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\n\n echo \"sudo pkgutil --only-dirs --files \\\"$PKGID\\\" | sed \\\"s|^|${FULL_INSTALL_LOCATION}/|\\\" | grep '\\\\.app$' | tr '\\\\\\\\n' '\\\\\\\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\"\n sudo pkgutil --only-dirs --files \"$PKGID\" | sed \"s|^|${FULL_INSTALL_LOCATION}/|\" | grep '\\.app$' | tr '\\n' '\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\n\n root_app_dir=$(\n sudo pkgutil --only-dirs --files \"$PKGID\" \\\n | sed \"s|^|${FULL_INSTALL_LOCATION}/|\" \\\n | grep 'Applications' \\\n | awk '{ print length, $0 }' \\\n | sort -n \\\n | head -n1 \\\n | cut -d' ' -f2-\n )\n if [ -n \"$root_app_dir\" ]; then\n echo \"sudo rmdir -p \\\"$root_app_dir\\\" 2>/dev/null || :\"\n sudo rmdir -p \"$root_app_dir\" 2>/dev/null || :\n fi\n}\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\nquit_application 'com.google.drivefs'\nquit_application 'com.google.drivefs.finderhelper.findersync'\nremove_pkg_files 'com.google.drivefs.arm64'\nforget_pkg 'com.google.drivefs.arm64'\nremove_pkg_files 'com.google.drivefs.filesystems.dfsfuse.arm64'\nforget_pkg 'com.google.drivefs.filesystems.dfsfuse.arm64'\nremove_pkg_files 'com.google.drivefs.filesystems.dfsfuse.x86_64'\nforget_pkg 'com.google.drivefs.filesystems.dfsfuse.x86_64'\nremove_pkg_files 'com.google.drivefs.shortcuts'\nforget_pkg 'com.google.drivefs.shortcuts'\nremove_pkg_files 'com.google.drivefs.x86_64'\nforget_pkg 'com.google.drivefs.x86_64'\nremove_launchctl_service 'com.google.GoogleUpdater.wake.system'\nremove_launchctl_service 'com.google.keystone.agent'\nremove_launchctl_service 'com.google.keystone.daemon'\nremove_launchctl_service 'com.google.keystone.system.agent'\nremove_launchctl_service 'com.google.keystone.system.xpcservice'\nremove_launchctl_service 'com.google.keystone.xpcservice'\nremove_pkg_files 'com.google.pkg.Keystone'\nforget_pkg 'com.google.pkg.Keystone'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/com.google.drivefs*'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/EQHXZ8M8AV.group.com.google.drivefs'\ntrash $LOGGED_IN_USER '~/Library/Application Support/FileProvider/com.google.drivefs.fpext'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Google/DriveFS'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.google.drivefs'\ntrash $LOGGED_IN_USER '~/Library/Containers/com.google.drivefs*'\ntrash $LOGGED_IN_USER '~/Library/Group Containers/*group.com.google.drivefs'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.google.drivefs*.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/Google Drive File Stream Helper.plist'\n", + "b1cef788": "#!/bin/sh\n\n# variables\nAPPDIR=\"/Applications/\"\nTMPDIR=$(dirname \"$(realpath $INSTALLER_PATH)\")\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# install pkg files\nsudo installer -pkg \"$TMPDIR/GoogleDrive.pkg\" -target /\n" + } +} diff --git a/ee/maintained-apps/outputs/google-drive/windows.json b/ee/maintained-apps/outputs/google-drive/windows.json new file mode 100644 index 0000000000..5349df1c80 --- /dev/null +++ b/ee/maintained-apps/outputs/google-drive/windows.json @@ -0,0 +1,21 @@ +{ + "versions": [ + { + "version": "116.0.6.0", + "queries": { + "exists": "SELECT 1 FROM programs WHERE name = 'Google Drive' AND publisher = 'Google LLC';" + }, + "installer_url": "https://dl.google.com/release2/drive-file-stream/dsiupwjcww5gzroykb7fpxic4q_116.0.6.0/setup.exe", + "install_script_ref": "fa36b892", + "uninstall_script_ref": "785a96b9", + "sha256": "5741e2d046554906b923257b8922d7109e5ac879c9fb6c376c988a5126ae90ae", + "default_categories": [ + "Productivity" + ] + } + ], + "refs": { + "785a96b9": "$softwareName = \"Google Drive\"\n\n$uninstallArgs = \"--silent --force_stop\"\n\n$expectedExitCodes = @()\n\n$machineKey = `\n 'HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\*'\n$machineKey32on64 = `\n 'HKLM:\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\*'\n\n$exitCode = 0\n\ntry {\n\n [array]$uninstallKeys = Get-ChildItem `\n -Path @($machineKey, $machineKey32on64) `\n -ErrorAction SilentlyContinue |\n ForEach-Object { Get-ItemProperty $_.PSPath }\n\n $foundUninstaller = $false\n foreach ($key in $uninstallKeys) {\n if ($key.DisplayName -eq $softwareName) {\n $foundUninstaller = $true\n # Get the uninstall command.\n $uninstallCommand = if ($key.QuietUninstallString) {\n $key.QuietUninstallString\n } else {\n $key.UninstallString\n }\n\n # Split the command and args\n $splitArgs = $uninstallCommand.Split('\"')\n if ($splitArgs.Length -gt 1) {\n if ($splitArgs.Length -eq 3) {\n $uninstallArgs = \"$( $splitArgs[2] ) $uninstallArgs\".Trim()\n } elseif ($splitArgs.Length -gt 3) {\n Throw `\n \"Uninstall command contains multiple quoted strings. \" +\n \"Please update the uninstall script.`n\" +\n \"Uninstall command: $uninstallCommand\"\n }\n $uninstallCommand = $splitArgs[1]\n }\n Write-Host \"Uninstall command: $uninstallCommand\"\n Write-Host \"Uninstall args: $uninstallArgs\"\n\n $processOptions = @{\n FilePath = $uninstallCommand\n PassThru = $true\n Wait = $true\n ArgumentList = \"$uninstallArgs\".Split(' ')\n NoNewWindow = $true\n }\n\n # Start process and track exit code\n $process = Start-Process @processOptions\n $exitCode = $process.ExitCode\n\n Write-Host \"Uninstall exit code: $exitCode\"\n break\n }\n }\n\n if (-not $foundUninstaller) {\n Write-Host \"Uninstaller for '$softwareName' not found.\"\n Exit 1\n }\n\n} catch {\n Write-Host \"Error: $_\"\n Exit 1\n}\n\nif ($expectedExitCodes -contains $exitCode) {\n $exitCode = 0\n}\n\nExit $exitCode\n", + "fa36b892": "$exeFilePath = \"${env:INSTALLER_PATH}\"\n\ntry {\n\n$processOptions = @{\n FilePath = \"$exeFilePath\"\n ArgumentList = \"--silent --skip_launch_new --gsuite_shortcuts=false\"\n PassThru = $true\n Wait = $true\n}\n\n# Start process and track exit code\n$process = Start-Process @processOptions\n$exitCode = $process.ExitCode\n\n# Prints the exit code\nWrite-Host \"Install exit code: $exitCode\"\nExit $exitCode\n\n} catch {\n Write-Host \"Error: $_\"\n Exit 1\n}\n" + } +} diff --git a/frontend/pages/SoftwarePage/components/icons/GoogleDrive.tsx b/frontend/pages/SoftwarePage/components/icons/GoogleDrive.tsx new file mode 100644 index 0000000000..b4abd431fb --- /dev/null +++ b/frontend/pages/SoftwarePage/components/icons/GoogleDrive.tsx @@ -0,0 +1,14 @@ +import * as React from "react"; + +import type { SVGProps } from "react"; + +const GoogleDrive = (props: SVGProps) => ( + + + +); +export default GoogleDrive; diff --git a/website/assets/images/app-icon-google-drive-60x60@2x.png b/website/assets/images/app-icon-google-drive-60x60@2x.png new file mode 100644 index 0000000000..fde88db09b Binary files /dev/null and b/website/assets/images/app-icon-google-drive-60x60@2x.png differ