Skip to content

Instantly share code, notes, and snippets.

@ELLIOTTCABLE
Forked from georgebrock/Info.plist
Last active January 25, 2023 00:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ELLIOTTCABLE/b25c6fea41f74ab6e38c5ee8dc744411 to your computer and use it in GitHub Desktop.
Save ELLIOTTCABLE/b25c6fea41f74ab6e38c5ee8dc744411 to your computer and use it in GitHub Desktop.
AppleScript Applet to bypass 'When switching to an application, switch to a Space …' for your web-browser

What's this?

Follow these instructions to create a 'BrowserHereHelper' (or name it whatever you want for easy Spotlight'ing) application that can:

  1. Activate a browser window, if it's open in the current Space already;
  2. create a new window, if there's none in the current Space (instead of switching to another Space!);
  3. open links from other applications in the current Space (again, instead of switching to another Space to open the link you clicked. 🙄)

For obvious reasons, this is only useful if your default setting in System Preferences is "When switching to an application, switch to a Space with open windows for the application." This script is intended to exempt certain apps, like browsers, from that otherwise-wonderful behaviour.

Installation

Follow these instructions to create an AppleScript App that can be used to open URLs:

  1. Open Script Editor (in /Applications/Utilities).

  2. Copy-paste the below script into a new document.

  3. Save the document as an 'Application'

    Warning Do not attempt to run it yet; complete the rest of the steps first. (If you have, you may need to delete the package entirely, and start over with a new Script Editor document.)

  4. Use the Terminal to edit the Contents/Info.plist file inside your newly-created application-bundle (e.g. If the app is at ~/Applications/BrowserHereHelper.app then the Info.plist will be at ~/Applications/BrowserHereHelper.app/Contents/Info.plist) with an editor of your choice;

    $ nano "/Applications/BrowserHereHelper.app/Contents/Info.plist"

    Warning Do not use the Finder to 'Show Package Contents', as that can cause the following code-signing steps to fail.

  5. Add a CFBundleURLTypes section to that Info.plist, indicating it can handle HTTP URLs (see Info.plist below for an example).

  6. Re-sign the generated application to pick up the additional Info.plist entry by running a command like this one in the Terminal:

    $ codesign -fs - --preserve-metadata=entitlements /Applications/BrowserHereHelper.app
    /Applications/BrowserHereHelper.app: replacing existing signature
  7. Open System Preferences > Security & Privacy > Accessibility, and drag your newly-signed app into the 'allow the apps below to control your computer' area, making sure it ends up checked: Screen Shot 2023-01-24 at 2 27 59 PM

  8. Test your application from the command line using open -a ~/Applications/MyApp.app http://www.example.com

  9. Use the application however you like — my favourites are setting it as the defaultbrowser (although in that case, make sure to modify the script below to set preferredBrowser to the value of your choice!), using it via Spotlight (naming it FirefoxHereHelper means I didn't even have to change my muscle-memory 😅), or tying into it with Choosy.app.

Debugging / Known Issues

AppleScripts, assistive-access permissions, and so on seem super fragile in my experience.

Expand the below toggle for some of my tips for fixing issues, some cargo-culted, some discovered through trial-and-error:

  1. If attempting to open a url with `open` has absolutely no effect whatsoever, or if you run into this error:
    executable_is_endpoint_security_client failed for path file:///Applications/BrowserHereHelper.app/Contents/MacOS/appletInfo.plist (plist or signature have been modified)

    … you may have forgotten to use 'export' mode in Script Editor and/or forgotten to switch to 'Don't Code Sign.' Delete the app entirely and start from scratch.

  2. If you run into any of these errors,
    • System Events got an error: BrowserHereHelper is not allowed assistive access. (-25211)
    • Not authorized to send Apple events to System Events. (-1743)

    … you may have munged up the Info.plist permissions, or macOS may just have cached some values incorrectly. First, check your Info.plist; and if that fails, you may be able to 'kick' the system back into giving you access by some combination of the following steps:

    • Delete, and then manually re-add, BrowserHereHelper.app to the Privacy > Accessibility pane, exactly as in step 7 above

    • Run some:tm: combination of the following commands in the Terminal:

         tccutil reset Accessibility
         tccutil reset AppleEvents
         tccutil reset SystemPolicyAllFiles
         tccutil reset SystemPolicySysAdminFiles
      
    • Delete the BrowserHereHelper.app entirely, start from scratch; or even

    • Delete the app entirely, start from scratch, and use a new name and package identifier. Oof.

use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
-- BrowserHereHelper.applescript:
-- v2, by <https://github.com/@ELLIOTTCABLE>
-- Instructions and current version:
-- <https://gist.github.com/ELLIOTTCABLE/b25c6fea41f74ab6e38c5ee8dc744411>
-- ---- ---- ---- --
-- Replace the `getDefaultBrowser()` below with this version that simply returns
-- a static string, if you wish to set this script as the macOS "default browser"
-- (otherwise, it will invoke itself recursively 😅)
(*
to getDefaultBrowser()
return "Firefox"
end getDefaultBrowser
*)
-- ---- ---- ---- --
-- Modify these two functions to add support for a new browser
-- This function should map the package-identifier stored in the LaunchServices
-- database to an 'application name' that works in AppleScript
to getDefaultBrowser()
local output, browserApplication
set output to do shell script "defaults read \\
~/Library/Preferences/com.apple.LaunchServices/com.apple.launchservices.secure \\
| awk -F'\"' '/http;/{print window[(NR)-1]}{window[NR]=$2}'"
if output is "" or output contains "safari" then
set browserApplication to "Safari"
else if output contains "chrome" then
set browserApplication to "Google Chrome"
else if output contains "firefox" then
set browserApplication to "Firefox"
else if output contains "ScriptEditor" then
error "BrowserHereHelper cannot recursively invoke itself! if you want to use BrowserHereHelper as your 'default browser', read the instructions inside the script and re-create the app."
else
error "unknown default browser; modify the script to match against the output you get for the inline shell-script"
end if
return browserApplication
end getDefaultBrowser
-- This function should handle whatever is necessary to instruct your browser-
-- application to create a new, empty window
to makeNewWindow(browserApplication)
if browserApplication = "Safari" then
tell application browserApplication to make new document
else if browserApplication = "Google Chrome" then
tell application browserApplication to make new window
else if browserApplication = "Firefox" then
tell application "System Events"
tell process browserApplication to click menu item "New Window" of menu "File" of menu bar 1
end tell
end if
tell application "System Events"
repeat until (my countVisibleWindows(browserApplication) > 0)
delay 0.05
end repeat
end tell
end makeNewWindow
-- Modify the above two functions to add support for a new browser
-- ---- ---- ---- --
to countVisibleWindows(an_app)
tell application "System Events"
return count (windows of process an_app where value of attribute "AXMinimized" is false)
end tell
end countVisibleWindows
to ensureVisibleWindowInThisSpace(browserApplication)
tell application "System Events"
if my countVisibleWindows(browserApplication) = 0 then
my makeNewWindow(browserApplication)
end if
end tell
end ensureVisibleWindowInThisSpace
on open location the_url
local defaultBrowser
set defaultBrowser to my getDefaultBrowser()
if application defaultBrowser is running then
my ensureVisibleWindowInThisSpace(defaultBrowser)
end if
tell application defaultBrowser
open location the_url
activate
end tell
end open location
on run
local defaultBrowser
set defaultBrowser to my getDefaultBrowser()
if application defaultBrowser is running then
my ensureVisibleWindowInThisSpace(defaultBrowser)
end if
tell application defaultBrowser to activate
end run
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!-- ... -->
<!-- Add this section: -->
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>HTTP URL</string>
<key>CFBundleURLSchemes</key>
<array>
<string>http</string>
<string>https</string>
</array>
</dict>
</array>
<!-- End of what needs adding -->
</dict>
</plist>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment