Friday, March 14, 2008

Firefox 3.0bX and AppleScript - What's gone wrong?

First off, I have to acknowledge that I should probably file a bug report, or something with Mozilla on this. But to be honest, I'm not sure it would do any good as there are so many outstanding AppleScript/Firefox bug reports out there. Shame on me for that attitude, but if you look at the bug reports you'll see enough unassigned, unfixed, unattended reports to take the wind out of your sails.

Perhaps this blog post can, at minimum, raise some awareness on the topic. In no way do I wish to insult any developers over this. The Mozilla team is doing everything they can to get 3.0 out the door. I just wish AppleScript support didn't go from "okay, it sorta works" in FF2 to "uhh, now it's broken" in FF3.

Let's look at a couple things:
  1. Getting the URL and Title of the current tab, or front window (which can be the frontmost tab).
  2. Getting general window properties.
I'm going to start with #2 since it shows a regression right of the bat with Firefox 3.

Tell application "Firefox"
properties of window 1
end tell

The result in Firefox 2 is this:

{«class pObT»:window, «class pTit»:"MozillaZine Weblogs", «class curl»:"", index:1, bounds:{639, 44, 1440, 809}, «class pLcn»:{639, 44}, closeable:true, titled:true, modal:false, resizable:false, zoomable:true, zoomed:true, «class pNMo»:true, «class pMMo»:false, floating:false, visible:true}

In the result are the Title: "MozillaZine Weblogs", and the URL: "". Fine so far.

Run the same script in Firefox 3 and you get a similar result; however, the Title «class pTit» is now empty. This appears to be a regression since it worked in FF2. FF3's result is below (on a different page, the title of which is "Minefield Start Page"):

{«class pObT»:window, «class pTit»:"", «class curl»:"", index:1, bounds:{0, 0, 1440, 900}, «class pLcn»:{0, 0}, closeable:false, titled:false, modal:false, resizable:false, zoomable:false, zoomed:false, «class pNMo»:true, «class pMMo»:false, floating:false, visible:false}

The reason I'm using Minefield is to see if this issue has been fixed (as per the bug filing guidelines). And it's the latest Minefield released today, 3/14 - Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10.5; en-US; rv:1.9b5pre) Gecko/2008031404 Minefield/3.0b5pre

If you are running Minefield, you'll want to replace "tell application "Firefox" with "tell application "Minefield"...

Okay - next run this script to get the URL of the current tab/window:

tell application "Firefox"
set Link to get «class curl» of window 1 as text
end tell

and/or to get the Title of the page:

tell application "Firefox"
set theTitle to «class pTit» of window 1
end tell

Your results in Firefox 2 will yield the URL and Title of the tab/window. In Firefox 3 you will only see the URL since the Title is yielding a null result.

Okay so far? Nothing broken other than the Title call in FF3, right?

Now I want you to add a System Events call. Let's copy some text. Highlight some text on the page in FF3 and run this script:

tell application "Firefox"
tell application "System Events" to keystroke "c" using {command down}
delay 0.3 (* or no delay *)
set clipText to (the clipboard) as text
end tell

How'd it go? The script should work fine.

HOWEVER, try the previous script(s) now - to get the URL and/or Title of the page.

Did it break? Breaks 100% of the time for me. So it appears that FF3 window properties get hosed after running a System Events call. Once done, Firefox rejects any further AppleScript calls for Title, URL, window properties, etc.

This is the AppleScript error I now get running the "get URL" script:

"Minefield got an error: Can't get «class curl» of window 1."

This is the error from the "get properties" script:

"Minefield got an error: Can't get every property of window 1."

It is very odd here because I can still run the "COPY highlighted text" script with the call to System Events, and I can also run "tell Firefox/Minefield to activate" only the calls to Firefox/Minefields window elements are broken.

My system info:

OS X 10.5.2 on a 1.33GHz PowerBook G4, 1GB RAM running a NEW profile for Firefox. I've even deleted all .plists, Library references, etc., thinking this was related to something stuck somewhere - so I started from scratch and can replicate this every time. Works fine until a System Events call is made.

I do now know if these errors occur on Intel Macs.

Based on what I've gathered on the web and in the Mozillazine forums, AppleScript is simply not a priority for the Firefox project. And that's too bad.

I've extolled Camino's scriptability, and I know Safari has it in spades, but Camino needs the plug-in architecture of Firefox. I've written scripts to enhance Camino and Safari, but even with the scripts, they just don't compare to the breadth of plug-ins offered by Firefox (for me and my workflow).

Safari, for all its good, bogs down on too many web sites and gives me the ol' spinning beach ball more times than not. I hit several hundred web sites every day for MacSurfer and the one browser that has handled the stress with minimal memory leakage and great efficiency has been Firefox. Camino would be next in line, then Safari.

Yes, I have tested all the latest WebKit and Camino nightly builds - as well as the latest Minefield nightly builds (the script problems still exist).

Finally, I've looked for, but cannot find any information on how to (within AppleScript) run a "do shell script" call to Firefox to backdoor a solution for getting "document.URL" or "document.Title", etc. There's no "do JavaScript" command as there is in Safari, but I wonder if there isn't some way to get that info in the shell, and call it from an AppleScript? (And no, javascript bookmarklets do not help. I need to do this via AppleScript).

Thanks for reading through to the end. If you have any thoughts or know of "do shell script" methods to get the URL and Title of a window, or know why Firefox is broken as I've detailed above, leave a note in the comments.


lemonteh said...

For getting title:

tell application "System Events"
tell process "Minefield"
get name of windows as string
end tell
end tell

For url (copy to clipboard)

tell application "System Events"
tell process "Minefield"
keystroke "l" using command down
keystroke "c" using command down
end tell
end tell

Naat said...

I wаѕ рrеttу рlеаѕеd tо dіѕсоvеr thіѕ wеbѕіtе. I nееd tо tо thаnk уоu fоr оnеѕ tіmе fоr thіѕ wоndеrful rеаd!! I dеfіnіtеlу аррrесіаtеd еvеrу bіt оf іt аnd і аlѕо hаvе уоu ѕаvеd аѕ а fаvоrіtе tо сhесk оut nеw ѕtuff іn уоur blоg.

Arthur Kaufman said...

Great postt