@@ -617,74 +617,27 @@ def open(self, url, new=0, autoraise=True):
617617
618618if sys .platform == 'darwin' :
619619 def _macos_default_browser_bundle_id ():
620- """Return the bundle ID of the default web browser via NSWorkspace .
620+ """Return the bundle ID of the default web browser.
621621
622- Uses the Objective-C runtime directly to call
623- NSWorkspace.sharedWorkspace().URLForApplicationToOpenURL() with a
624- probe https:// URL, then reads the bundle identifier from the
625- resulting NSBundle. Returns None if ctypes is unavailable or the
626- lookup fails for any reason.
622+ Reads the LaunchServices preferences file that macOS maintains
623+ when the user sets a default browser. Returns None if the file
624+ is absent or no https handler is recorded.
627625 """
626+ import plistlib , os
627+ plist = os .path .expanduser (
628+ '~/Library/Preferences/com.apple.LaunchServices/'
629+ 'com.apple.launchservices.secure.plist'
630+ )
628631 try :
629- from ctypes import cdll , c_void_p , c_char_p
630- from ctypes .util import find_library
631-
632- # NSWorkspace is an AppKit class; load AppKit to register it.
633- cdll .LoadLibrary (
634- '/System/Library/Frameworks/AppKit.framework/AppKit'
635- )
636- objc = cdll .LoadLibrary (find_library ('objc' ))
637- objc .objc_getClass .restype = c_void_p
638- objc .sel_registerName .restype = c_void_p
639- objc .objc_msgSend .restype = c_void_p
640-
641- def cls (name ):
642- return objc .objc_getClass (name )
643-
644- def sel (name ):
645- return objc .sel_registerName (name )
646-
647- # Build probe NSURL for "https://python.org"
648- NSString = cls (b'NSString' )
649- objc .objc_msgSend .argtypes = [c_void_p , c_void_p , c_char_p ]
650- ns_str = objc .objc_msgSend (
651- NSString , sel (b'stringWithUTF8String:' ), b'https://python.org'
652- )
653-
654- NSURL = cls (b'NSURL' )
655- objc .objc_msgSend .argtypes = [c_void_p , c_void_p , c_void_p ]
656- probe_url = objc .objc_msgSend (NSURL , sel (b'URLWithString:' ), ns_str )
657-
658- # Ask NSWorkspace which app handles https://
659- NSWorkspace = cls (b'NSWorkspace' )
660- objc .objc_msgSend .argtypes = [c_void_p , c_void_p ]
661- workspace = objc .objc_msgSend (NSWorkspace , sel (b'sharedWorkspace' ))
662- if not workspace :
663- return None
664-
665- objc .objc_msgSend .argtypes = [c_void_p , c_void_p , c_void_p ]
666- app_url = objc .objc_msgSend (
667- workspace , sel (b'URLForApplicationToOpenURL:' ), probe_url
668- )
669- if not app_url :
670- return None
671-
672- # Get bundle identifier from that app's NSBundle
673- NSBundle = cls (b'NSBundle' )
674- bundle = objc .objc_msgSend (NSBundle , sel (b'bundleWithURL:' ), app_url )
675- if not bundle :
676- return None
677-
678- objc .objc_msgSend .argtypes = [c_void_p , c_void_p ]
679- bundle_id_ns = objc .objc_msgSend (bundle , sel (b'bundleIdentifier' ))
680- if not bundle_id_ns :
681- return None
682-
683- objc .objc_msgSend .restype = c_char_p
684- bundle_id_bytes = objc .objc_msgSend (bundle_id_ns , sel (b'UTF8String' ))
685- return bundle_id_bytes .decode () if bundle_id_bytes else None
632+ with open (plist , 'rb' ) as f :
633+ data = plistlib .load (f )
634+ for handler in data .get ('LSHandlers' , []):
635+ if handler .get ('LSHandlerURLScheme' ) == 'https' :
636+ return (handler .get ('LSHandlerRoleAll' )
637+ or handler .get ('LSHandlerRoleViewer' ))
686638 except Exception :
687- return None
639+ pass
640+ return None
688641
689642 class MacOSX (BaseBrowser ):
690643 """Launcher class for macOS browsers, using /usr/bin/open.
0 commit comments