Last active
August 9, 2024 17:56
-
-
Save wsoyka/8e0497379b9598dfe5116f04282247d1 to your computer and use it in GitHub Desktop.
Applescript - Bring a specific chromium tab to front or open it in a given profile
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
################################################### | |
# | |
# Version: 2024-08 | |
# | |
# This script will search all open Browser Windows for a specified Tab (by Title). | |
# At some point, this worked for Google Chrome and Brave Browser. | |
# Other chromium based browsers should work, but have not been tested. | |
# | |
# If no tab with the given title is found, it will open the specified URL in the | |
# specified Profile. If multiple tabs with the specified title exist, the first one | |
# found will be opened. | |
# | |
# Chromium's applescript APIs does not offer support for changing the browser profile, so we need to emulate clicks on the relevant elements. | |
# Due to this, the application that is going to run the script (a hotkey application (BetterTouchTool, KeyboardMaestro), or e.g | |
# Terminal) will have to be granted Accessibility Access (System Preferences > Security & Privacy > Privacy > Accessibility) | |
# | |
# | |
# Params: | |
# browser: the name of the app ("Google Chrome", "Brave Browser", ...) | |
# profileName: the exact name of the profile to be matched | |
# targetTabTitle: exact or partial tab title, as specified in the <title> tag | |
# targetUrl: the url to open, including http(s):// | |
# | |
# osascript ~/path/to/scriptname.scpt "Brave Browser" "My Profile Name" "Exact or partial <title> of the tab" "https://URLToOpenIfTabtIsNotFound.tld" | |
################################################### | |
property DEBUG : false #whether to log to /tmp/${scriptname}.log and use default args if none provided | |
property NOTIFICATIONS : true #whether to show notifications | |
property TARGET_BROWSER : "Brave Browser" #default, required here for TELL's to work. will be overwritten with provided argument. | |
on run argv | |
if (count of argv) = 4 then | |
set TARGET_BROWSER to item 1 of argv | |
set profileName to item 2 of argv | |
set targetTabTitle to item 3 of argv | |
set targetUrl to item 4 of argv | |
else | |
if DEBUG is true then | |
set TARGET_BROWSER to "Brave Browser" | |
set profileName to "Privat" | |
set targetTabTitle to "Example Domain - https://example.org/" | |
set targetUrl to "https://example.org/" | |
else | |
errExit("Use 4 arguments: <browser>, <profileName>, <targetTabTitle>, <targetUrl>") | |
end if | |
end if | |
mylog("New run. Target Browser: " & TARGET_BROWSER) | |
if browser_try_focus_tab(targetTabTitle) is false then # targetTabTitle is not yet open, lets open targetUrl it in the specified profile | |
#chromium browsers dont support changing profile via applescript api, hence the accessibility requirement of the script to do this | |
tell application "System Events" to tell process TARGET_BROWSER | |
set frontmost to true | |
end tell | |
try | |
set names to {"People", "Profiles"} #2021 - Brave (still) uses People, Chrome renamed it to Profiles, lets try both | |
set click_profile_selection_success to false | |
repeat with targetMenubarItemName in names | |
if click_profile_selection_success = false then | |
try | |
#chromium doesnt support changing profile via applescript api, hence the accessibility requirement | |
tell application "System Events" to tell process TARGET_BROWSER | |
click menu item profileName of menu 1 of menu bar item targetMenubarItemName of menu bar 1 | |
end tell | |
click_profile_selection_success = true | |
exit repeat | |
on error | |
mylog(TARGET_BROWSER & " has no menu named: " & targetMenubarItemName) | |
end try | |
end if | |
end repeat | |
if click_profile_selection_success = false then | |
mylog("cannot open profile selection: " & targetMenubarItemName & "(probably your browser uses a different name)") | |
end if | |
on error errStr | |
errExit("error opening profile: " & profileName & " err:" & errStr) | |
end try | |
wait_for_browser_window() | |
#check again | |
if browser_try_focus_tab(targetTabTitle) is false then | |
showNotif given msg:"Opening new tab" | |
tell application TARGET_BROWSER | |
open location targetUrl | |
end tell | |
else | |
showNotif given msg:"Existing tab found in profile " & profileName | |
end if | |
else | |
showNotif given msg:"Existing tab found in current window" | |
end if | |
end run | |
on browser_try_focus_tab(targetTabTitle) | |
using terms from application "Brave Browser" # Unfortunately, the "base" application name needs to be hardcoded here. | |
tell application TARGET_BROWSER | |
activate | |
repeat with currentWindow in windows # currentWindow is of class "cwin" useful attributes: "title", "index", "document" (probably could do funny stuff with this one to match page content?) | |
my mylog("checking tabs of window" & (index of currentWindow)) | |
set tabIndex to 0 | |
repeat with currentTab in (every tab of currentWindow) | |
set tabIndex to tabIndex + 1 | |
if title of currentTab contains targetTabTitle then | |
my mylog("found relevant tab") | |
set (active tab index of currentWindow) to tabIndex #have to set that tab to be the active tab _first_ | |
#https://stackoverflow.com/questions/10366003/applescript-google-chrome-activate-a-certain-window/34375804#34375804 | |
set index of currentWindow to 1 | |
delay 0.01 | |
do shell script "open -a " & (quoted form of TARGET_BROWSER) #focusing the browser now will show our tab | |
return true | |
end if | |
end repeat | |
end repeat | |
end tell | |
end using terms from | |
return false | |
end browser_try_focus_tab | |
on showNotif given title:nTitle : "", subtitle:nSubtitle : "", msg:nMsg : "", sound:nSound : "Frog" | |
if NOTIFICATIONS is true then | |
set myFilePath to POSIX path of (path to me) | |
set myFileName to do shell script "basename " & quoted form of myFilePath | |
if nTitle is "" then | |
set nTitle to myFileName | |
end if | |
display notification nMsg with title nTitle subtitle nSubtitle sound name nSound | |
end if | |
end showNotif | |
on mylog(myObj) | |
if DEBUG is true then | |
set myFilePath to POSIX path of (path to me) | |
set myFileName to do shell script "basename " & quoted form of myFilePath | |
do shell script "echo " & myFilePath & " `date '+%F %T'`: " & quoted form of (myObj as string) & " >> /tmp/" & myFileName & ".log" | |
end if | |
end mylog | |
on errExit(message) | |
showNotif given title:"Error", msg:message | |
if DEBUG is true then | |
my mylog("Error: " & message) | |
end if | |
error message #exit | |
end errExit | |
#instead of fixed delay, busy wait until profile window is open. | |
#based on https://apple.stackexchange.com/questions/343624/applescript-wait-for-safari-page-to-fully-load/343633 | |
on wait_for_browser_window() | |
using terms from application "Brave Browser" # Unfortunately, the "base" application name needs to be hardcoded here. | |
tell application TARGET_BROWSER | |
delay 1 | |
repeat until (loading of front window's tab 2 is false) | |
delay 0.2 | |
end repeat | |
loading of front window's tab 2 | |
end tell | |
end using terms from | |
end wait_for_browser_window |
If you're not using Brave, you'll probably have to replace all instances of "Brave Browser" in the script with your flavour of chromium (e.g. "Google Chrome",..)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@tomwolber / @oliv-j Indeed. I've been using this script with Brave for a while, which still calls that menu "People".
I just updated the script to a new version that works on (probably) any chromium browser, targeting both the "Profiles" and "People" menu.
@oliv-j Great idea! Added it to the new version. (Might cause conflicts if your targetTabTitle isnt unique though)
I'm currently not actively using this script, so if you find something to not be working, do let me know!