Dealing with Firefox I found that its integration script did not handle file URLs properly.
Why file URLs? Most people are probably not aware that you can use most browsers (among them iCab and especially Firefox) as one-stop-document-previewing-app.
I. e. open a blank window and drag and drop pictures, text files, videos, pdfs and many other file types on the big white void or on the browser’s icon in the dock to view them. [See my post on iCab in this forum.]
When I checked the script out I was astonished about its many shortcomings. I found
• completely irrelevant and not functional code
• experimental remnants
• completely outdated code
• hideous verbosity for the simplest things
• damaging code
• missing functionality
The code seems to have never been updated in recent years.
The details:
• irrelevant code
The following code is completely irrelevant, i. e. functionless:
property NSShiftKeyMask : a reference to 131072
property NSAlternateKeyMask : a reference to 524288
property NSControlKeyMask : a reference to 262144
property NSEvent : a reference to current application's NSEvent
set modifier_down to true
repeat while modifier_down
set modifier_flags to NSEvent's modifierFlags()
set option_down to ((modifier_flags div (get NSAlternateKeyMask)) mod 2) = 1
set shift_down to ((modifier_flags div (get NSShiftKeyMask)) mod 2) = 1
set control_down to ((modifier_flags div (get NSControlKeyMask)) mod 2) = 1
set modifier_down to option_down or shift_down or control_down
end repeat
Astonishingly, the same code block is in various other integrations scripts and there also does nothing.
• this code is largely useless
set firefoxVer to version
considering numeric strings
set is87 to firefoxVer ≥ "87"
set is72 to firefoxVer ≥ "72"
end considering
if is72 and myName ends with " - Mozilla Firefox" then
if length of myName > 18 then
set myName to text 1 through -19 of myName
else
set myName to ""
end if
end if
It tried to cope with quirks of nowadays completely outdated versions of Firefox (and not in a particularly elegant way.) Firefox’s current v. 153 supports OS 10.15, the same as the current version of Hookmark, so people can and should update their browser (2026.07.23)
BTW: Hookmarks info.plist designates OS 10.13 as minimal OS, whereas its website states 10.15.
• The following code is incredibly tedious, a maintenance nightmare, but above all outdated (probably for years?) and no longer works:
try
set theUrl to ""
tell application "Firefox"
tell application "System Events"
if toolbar "Navigation" of first group of front window of application process "Firefox" exists then
set theUrl to get value of UI element 1 of combo box 1 of toolbar "Navigation" of first group of front window of application process "Firefox"
else if toolbar "导航" of first group of front window of application process "Firefox" exists then
set theUrl to get value of UI element 1 of combo box 1 of toolbar "导航" of first group of front window of application process "Firefox"
else if toolbar "Área de navegación" of first group of front window of application process "Firefox" exists then
set theUrl to get value of UI element 1 of combo box 1 of toolbar "Área de navegación" of first group of front window of application process "Firefox"
else if toolbar "Navigazione" of first group of front window of application process "Firefox" exists then
set theUrl to get value of UI element 1 of combo box 1 of toolbar "Navigazione" of first group of front window of application process "Firefox"
else if toolbar "ナビゲーション" of first group of front window of application process "Firefox" exists then
set theUrl to get value of UI element 1 of combo box 1 of toolbar "ナビゲーション" of first group of front window of application process "Firefox"
else if toolbar "導覽" of first group of front window of application process "Firefox" exists then
set theUrl to get value of UI element 1 of combo box 1 of toolbar "導覽" of first group of front window of application process "Firefox"
else if toolbar "Navegação" of first group of front window of application process "Firefox" exists then
set theUrl to get value of UI element 1 of combo box 1 of toolbar "Navegação" of first group of front window of application process "Firefox"
end if
if theUrl is not "" then
return ("[" & myName & "](" & theUrl) & ")"
end if
end tell
end tell
end try
This code could have been refactored into this more maintainable form:
set theUrl to ""
tell application "System Events"
tell process "Firefox"
set toolbarNames to {"Navigation", "导航", "Área de navegación", "Navigazione", "ナビゲーション", "導覽", "Navegação"}
repeat with aName in toolbarNames
try
set theUrl to get value of UI element 1 of combo box 1 of toolbar aName of first group of front window
end try
if theUrl is not "" then return ("[" & myName & "](" & theUrl) & ")"
end repeat
end tell
end tell
39 lines of completely useless code since the UI element structure in Firefox has changed long ago, maybe years. Nobody ever realized this, since it fails silently. Even if it worked it would work only for the seven language localisations given, since the code chose to use labeled (and - courtesy of Mozilla - localised) references. To avoid this indexed references should and can be used (see my updated code at the end of this post.)
This code snippet
tell application "Firefox"
tell application "System Events"
is completely meaningless here, clearly an experimental remnant which did not get cleared out. Instead UI references should be pointed specifically to Firefox (instead of some “front application”) whithin the “System Events” tell block for stability reason, like this:
tell application "System Events"
tell process "Firefox"
Now what is left and what keeps the code working at all is fallback code highlighting and copying the URL from Firefoxes URL input field to the clipboard. This approach is forced to use the clipboard but does not even bother to save and restore the previous clipboard contents. Instead it rudely wipes out everything that is there. See my version of the script storing and restoring the previous clipboard content to make the user experience completely transparent.
Apart from that the code does not distinguish between possible entries in the URL entry field:
• Web URLs are handled, but the two code variants return URLs with and without the “https://” prefix.
• File URLs where not properly handled. I added support in my script below.
• Search strings for web searches should be relegated.
My version of the script, free to use (note the various inline comments):
use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
-- classes, constants, and enums used
property NSPasteboard : a reference to current application's NSPasteboard
property NSPasteboardItem : a reference to current application's NSPasteboardItem
property NSString : a reference to current application's NSString
property NSMutableCharacterSet : a reference to current application's NSMutableCharacterSet
property NSMutableArray : a reference to current application's NSMutableArray
-- courtesy Shane Stanley https://www.macscripter.net/t/styled-text-lib/69970/2
on fetchStorableClipboard()
set aMutableArray to NSMutableArray's array() -- used to store contents
-- get the pasteboard and then its pasteboard items
set thePasteboard to NSPasteboard's generalPasteboard()
set theItems to thePasteboard's pasteboardItems()
-- loop through pasteboard items
repeat with i from 1 to count of theItems
-- make a new pasteboard item to store existing item's stuff
set newPBItem to NSPasteboardItem's alloc()'s init()
-- get the types of data stored on the pasteboard item
set theTypes to (item i of theItems)'s |types|()
-- for each type, get the corresponding data and store it all in the new pasteboard item
repeat with j from 1 to count of theTypes
set theData to ((item i of theItems)'s dataForType:(item j of theTypes))'s mutableCopy()
if theData is not missing value then
(newPBItem's setData:theData forType:(item j of theTypes))
end if
end repeat
-- add new pasteboard item to array
(aMutableArray's addObject:newPBItem)
end repeat
return aMutableArray
end fetchStorableClipboard
on putOnClipboard:theArray
-- get pasteboard
set thePasteboard to NSPasteboard's generalPasteboard()
-- clear it, then write new contents
thePasteboard's clearContents()
thePasteboard's writeObjects:theArray
end putOnClipboard:
-- copied from Michael Tsai's Eagle Filer integration script
on urlEncode(input)
tell NSString to set rawUrl to stringWithString_(input)
set charset to NSMutableCharacterSet's URLQueryAllowedCharacterSet's mutableCopyWithZone:(missing value)
charset's removeCharactersInString:"?"
set theEncodedURL to rawUrl's stringByAddingPercentEncodingWithAllowedCharacters:charset
return theEncodedURL as Unicode text
end urlEncode
-- main
tell application "Firefox"
activate
delay 0.05 -- is this needed? shouldn't be, no UI scripting here; and 5/100s?? Shouldn't achieve anything meaningful, just vodoo
set myName to get name of front window
-- bail out if script (accidentally) got executed without a window being displayed
if myName is "" then return -- --nothing; "" will be the name string if no window is open
set firefoxVer to version -- used for notification on UI scripting failure
-- the rest down to "end tell" seems to be practically obsolete (attempting to support antique versions of Firefox)
-- the current FF version 153 supports OS 10.15, the same as the current version of Hookmark, so people can and should update their browser (2026.07.23)
--considering numeric strings
-- --set is87 to firefoxVer ≥ "87" -- not needed
-- set is72 to (firefoxVer ≥ "72" and firefoxVer < "87")
--end considering
--if is72 and myName ends with " - Mozilla Firefox" then
-- if length of myName > 18 then
-- set myName to text 1 through -19 of myName
-- else
-- set myName to ""
-- end if
--end if
end tell
set myURL to ""
-- UI scripting: fast but application version dependent
tell application "System Events"
tell process "Firefox"
try -- valid for v. 153 and very likely several earlier versions
tell group 2 of group 1 of toolbar 2 of group 1 of window 1
-- combo box index changes on the fly according to the type and/or number of open tabs in front window etc.
try
set myURL to get value of combo box 2
on error
try
set myURL to get value of combo box 1
end try
end try
end tell
end try
end tell
end tell
-- any web URL if retrieved at this point does not begin with "https://"! If copy-via-clipboard is used below, it does; file URLs, however, properly begin with "file://" but "Mozilla Firefox" will be the default name for any tab displaying a file URL; ...
if myURL is "" then
-- debugging helper
tell application "Finder" to display notification "Hookmark UI Scripting is broken for Firefox version " & firefoxVer & ". Please inform the developer providing your Firefox version number. Using copy-via-clipboard approach instead."
-- from here, get URL via clipboard: this approach works at least for any Firefox version since 2014 and probably earlier but is slower and possibly shakey
-- backup clipboard contents for later restore
set theClip to my fetchStorableClipboard()
set the clipboard to "" -- empty clipboard avoiding error on ‘clipboard as string'
tell application "System Events"
tell process "Firefox"
keystroke "lc" using {command down} -- highlight URL and copy combined into a single event, so no shakey delay needed in-between
end tell
delay 0.3
keystroke (key code 53) -- esc to close the URL history popup menu and thus allow Firefox to transfer the copied URL to the system clipboard for retrival by this script
end tell
repeat 10 times -- poll clipboard for 5 seconds; should not be necessary with clipboard containing "" and after esc closed the popup menu
-- give the code a chance not to fail at all, even if it takes half a second
delay 0.5 -- why hog the CPU with delays of 0.1 when you are prepared to wait 5s?
try
set myURL to (the clipboard as string) -- this may error after 'set clipboard to {}', i. e. if clipboard is (still) empty, but not after 'set clipboard to ""', clipboard contains empty string
if myURL is not equal to "" then
exit repeat
end if
end try
end repeat
--set myURL to (the clipboard as string)
my putOnClipboard:theClip -- restore backuped clipboard
end if
if myURL is "" then
return -- nothing
else if myURL begins with "file://" then -- in this case myName will be "Mozilla Firefox" for any file
set AppleScript's text item delimiters to "/"
set myName to last item of (get text items of myURL) -- get the full file name instead
set myURL to my urlEncode(myURL) -- the file URL may contain spaces etc. (?!), so it has to be encoded
return ("[" & myName & "](" & myURL) & ")"
else if myURL does not contain " " and myURL contains "." then -- heuristical check that myURL is really a URL and not a search string for a web search
if myURL does not contain "://" then set myURL to "https://" & myURL -- heuristical "repair"
return ("[" & myName & "](" & myURL) & ")"
end if