Get default web browser

This script determines the default web browser on the system from the user’s plist preference file. With small modification it can get other default helpers. Tested on 10.6, but probably works on 10.5 as well.

(* Handler that will return the name of the system's default handler for the specified protocol. Specify the protocol in the handler_scheme property *)

property handler_scheme : "<key>LSHandlerURLScheme</key>
	<string>http</string>"

on get_default_handler()
	tell application "System Events"
		
		tell property list file ((path to preferences from user domain as text) & "com.apple.LaunchServices.plist")
			
			set active_prop to null
			repeat with i_count from 1 to (count property list items)
				if name of property list item i_count contains "LSHandlers" then set active_prop to i_count
				exit repeat
			end repeat
			tell property list item active_prop
				set active_prop to null
				repeat with i_count from 1 to (count property list items)
					set prop_contents to text of property list item i_count
					if (prop_contents contains handler_scheme) then
						set active_prop to i_count
						exit repeat
					end if
				end repeat
				
				tell property list item active_prop
					set active_prop to null
					repeat with i_count from 1 to (count property list items)
						if (name of property list item i_count contains "LSHandlerRoleAll") then
							set active_prop to i_count
							exit repeat
						end if
					end repeat
					set default_app to value of property list item active_prop
					
				end tell
			end tell
		end tell
	end tell
	
	set saved_delims to AppleScript's text item delimiters
	set AppleScript's text item delimiters to {"."}
	set app_name to last item of (every text item of default_app)
	set AppleScript's text item delimiters to saved_delims
	
	return app_name
end get_default_handler

2-4-10 18:25: edited code to address bug noted by Nigel Garvey

Model: MacBook Pro
Browser: Camino 2.0.2
Operating System: Mac OS X (10.6)

Hi, Jolin.

Welcome to MacScripter and thanks for posting your script!

Unfortunately, it returns “iCal” on my machine. The problems seem to be:

  1. There’s no mention of “Safari”, my default browser, in com.apple.LaunchServices.plist. By analogy with other settings in the system ” ie. without actually testing! ” I imagine that if I change the default to, say, Firefox, then there’ll be an entry for Firefox in the file. If I then change back to Safari, there’ll be an entry for Safari. But otherwise, on a fresh system, Safari is simply assumed.

  2. The loop in your script which looks for “LSHandlerURLScheme” and “http” in the text of property list items turns up this on my machine:

It satisfies the search criteria but obviously has no connection with Web browsers.

Hope this helps.

On my PM G5 machine (10.5.8), it doesn’t the script doesn’t return anything even though it doesn’t error. Don’t feel bad though – I have two scripts for determining the default browser from previous years. One of them fails entirely and the other produces a wrong answer. Apparently this is trickier than it seems.

This one, using Perl (by John Gruber of Daring Fireball) works on both of my machines:

on GetDefaultWebBrowser()
	-- First line of _scpt is a workaround for Snow Leopard issues
	-- with 32-bit Mac:: Carbon modules
	set _scpt to "export VERSIONER_PERL_PREFER_32_BIT=yes; " & ¬
		"perl -MMac::InternetConfig -le " & ¬
		"'print +(GetICHelper \"http\")[1]'"
	return do shell script _scpt
end GetDefaultWebBrowser

GetDefaultWebBrowser()

Nigel, thanks for pointing out a pretty significant error in my script! On my machine, the http handler is the first entry which is why I hadn’t spotted it. I’ve updated the script (in the original post) to correct for this. It is also now easy to change which protocol to get the default handler for.

Regarding http handler not being set in LaunchServices.plist if the default browser has never been changed from Safari, that is quite interesting. I acknowledge (and maybe should have noted in the original post) that there is no error checking in this code, but it would be fairly easy to add. I just didn’t have time.

Adam, try the updated script. It should give an error (about not able to make null into an integer) on one of your machines and hopefully provide the right answer on the other! I am aware of the Perl script from Daring Fireball, but I wanted to do this all in AppleScript. As the Perl script relies on InternetConfig, I don’t feel this will be reliable long-term. Though, plainly, my script isn’t reliable either.

If I had more time, I would add the error handling, which would return ‘Safari’ if no handler could be found.

Thanks for the comments!

Hi,

Nigel is right. Safari is the default browser if there is no http entry.
This version works in 10.5 and higher


(* Handler that will return the bundle identifier of the system's default web browser *)

tell application "Finder" to set defaultBrowser to (application file id (my get_default_browser())) as alias

on get_default_browser()
    tell application "System Events"
        tell property list file ((path to preferences from user domain as text) & "com.apple.LaunchServices.plist")
            tell contents
                tell property list item "LSHandlers"
                    try
                        set active_prop to 1st property list item whose value of property list item 2 is "http"
                        return value of property list item 1 of active_prop
                    on error
                        return "com.apple.Safari"
                    end try
                end tell
            end tell
        end tell
    end tell
end get_default_browser

Alternatively I wrote a simple Foundation tool command line interface which calls LSServices directly.
You can download it here: defaultbrowser

Usage:

do shell script "/path/to/defaultbrowser"

returns the POSIX path to the default browser.

The source code is just a few lines

[code]#import <Foundation/Foundation.h>
#import <ApplicationServices/ApplicationServices.h>

int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
FSRef appRef;
OSErr err;
char *URL = “http:”;
CFStringRef urlStr = CFStringCreateWithCString(NULL, URL, kCFStringEncodingASCII);
CFURLRef inURL = CFURLCreateWithString(NULL, urlStr, NULL);
err = LSGetApplicationForURL(inURL, kLSRolesAll, &appRef, NULL);
CFRelease(inURL);
CFRelease(urlStr);
if (err == kLSApplicationNotFoundErr) {
// if there is no entry, Safari is the default browser
printf(“/Applications/Safari.app\n”);
}
else {
CFURLRef url = CFURLCreateFromFSRef(kCFAllocatorDefault, &appRef);
NSString *path = [(NSURL *)url path];
CFRelease(url);
printf(“%s\n”, [path UTF8String]);
}
[pool drain];
return 0;
}[/code]

Hi StefanK,

Thanks, your script is much more elegant. I was going to add error handling to my code, but no need now! I thought I probably wasn’t going about reading the plist file the best way, but it’s the first time I’ve dealt with plist files in AppleScript. As I was short on time, I just went for the brute force approach. :slight_smile:

Interestingly, both JolinWarren’s version and StefanK’s fail on my G5 machine in 10.5.8 and it turns out that the reason is simple. For a while there I played with the nightly builds of webkit, so when I run the core of Stefan’s handler:

tell application "System Events"
	tell property list file ((path to preferences from user domain as text) & "com.apple.LaunchServices.plist")
		tell contents
			tell property list item "LSHandlers"
				try
					set active_prop to 1st property list item whose value of property list item 2 is "http"
					return value of property list item 1 of active_prop
				on error
					return "com.apple.Safari"
				end try
			end tell
		end tell
	end tell
end tell

it returns: “org.webkit.nightly.webkit” because that is, in fact the second item. The first line of SK’s script then fails, of course, which is why I extracted the core of the handler to test alone.

The executable works perfectly, however, since it doesn’t depend on position.