From 749900bde6560d275418871bff922df9cf1e9643 Mon Sep 17 00:00:00 2001 From: "gtm.daemon" Date: Fri, 2 Apr 2010 19:30:55 +0000 Subject: [Author: csilv] use LaunchServices APIs when running on 10.5 and above. R=dmaclach,thomasvl APPROVED=dmaclach DELTA=150 (150 added, 0 deleted, 0 changed) --- AppKit/GTMLoginItems.m | 156 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 153 insertions(+), 3 deletions(-) (limited to 'AppKit') diff --git a/AppKit/GTMLoginItems.m b/AppKit/GTMLoginItems.m index f124ef5..9da1ff9 100644 --- a/AppKit/GTMLoginItems.m +++ b/AppKit/GTMLoginItems.m @@ -7,9 +7,9 @@ // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy // of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the @@ -19,6 +19,7 @@ #import "GTMLoginItems.h" #import "GTMDefines.h" +#import "GTMGarbageCollection.h" #include @@ -27,12 +28,25 @@ NSString * const kGTMLoginItemsNameKey = @"Name"; NSString * const kGTMLoginItemsPathKey = @"Path"; NSString * const kGTMLoginItemsHiddenKey = @"Hide"; +// kLSSharedFileListLoginItemHidden is supported on +// 10.5, but missing from the 10.5 headers. +// http://openradar.appspot.com/6482251 +#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6 +static NSString * const kLSSharedFileListLoginItemHidden = + @"com.apple.loginitem.HideOnLaunch"; +#endif // MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6 + @interface GTMLoginItems (PrivateMethods) + (NSInteger)indexOfLoginItemWithValue:(id)value forKey:(NSString *)key loginItems:(NSArray *)items; +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ++ (LSSharedFileListRef)loginItemsFileListRef; ++ (NSArray *)loginItemsArrayForFileListRef:(LSSharedFileListRef)fileListRef; +#else // MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 + (BOOL)compileAndRunScript:(NSString *)script withError:(NSError **)errorInfo; +#endif // MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 @end @implementation GTMLoginItems (PrivateMethods) @@ -53,6 +67,23 @@ NSString * const kGTMLoginItemsHiddenKey = @"Hide"; return NSNotFound; } +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 + ++ (LSSharedFileListRef)loginItemsFileListRef { + LSSharedFileListRef loginItemsRef = + LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL); + return (LSSharedFileListRef)GTMCFAutorelease(loginItemsRef); +} + ++ (NSArray *)loginItemsArrayForFileListRef:(LSSharedFileListRef)fileListRef { + UInt32 seedValue; + CFArrayRef filelistArrayRef = LSSharedFileListCopySnapshot(fileListRef, + &seedValue); + return GTMCFAutorelease(filelistArrayRef); +} + +#else // MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 + + (BOOL)compileAndRunScript:(NSString *)script withError:(NSError **)errorInfo { if ([script length] == 0) { @@ -83,10 +114,70 @@ NSString * const kGTMLoginItemsHiddenKey = @"Hide"; return YES; } +#endif // MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 + @end @implementation GTMLoginItems +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 + ++ (NSArray*)loginItems:(NSError **)errorInfo { + // get the login items from LaunchServices + LSSharedFileListRef loginItemsRef = [self loginItemsFileListRef]; + if (!loginItemsRef) { + // COV_NF_START - no real way to test this + if (errorInfo) { + *errorInfo = [NSError errorWithDomain:@"GTMLoginItems" + code:-1 + userInfo:nil]; + } + return nil; + // COV_NF_END + } + NSArray *fileList = [self loginItemsArrayForFileListRef:loginItemsRef]; + + // build our results + NSMutableArray *result = [NSMutableArray array]; + for (id item in fileList) { + LSSharedFileListItemRef itemRef = (LSSharedFileListItemRef)item; + // name + NSMutableDictionary *item = [NSMutableDictionary dictionary]; + CFStringRef nameRef = LSSharedFileListItemCopyDisplayName(itemRef); + if (nameRef) { + [item setObject:[(NSString *)nameRef stringByDeletingPathExtension] + forKey:kGTMLoginItemsNameKey]; + CFRelease(nameRef); + } + // path + CFURLRef urlRef = NULL; + if (LSSharedFileListItemResolve(itemRef, 0, &urlRef, NULL) == noErr) { + if (urlRef) { + NSString *path = [(NSURL *)urlRef path]; + if (path) { + [item setObject:path forKey:kGTMLoginItemsPathKey]; + } + CFRelease(urlRef); + } + } + // hidden + CFBooleanRef hiddenRef = LSSharedFileListItemCopyProperty(itemRef, + (CFStringRef)kLSSharedFileListLoginItemHidden); + if (hiddenRef) { + if (hiddenRef == kCFBooleanTrue) { + [item setObject:[NSNumber numberWithBool:YES] + forKey:kGTMLoginItemsHiddenKey]; + } + CFRelease(hiddenRef); + } + [result addObject:item]; + } + + return result; +} + +#else // MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 + + (NSArray*)loginItems:(NSError **)errorInfo { NSDictionary *errDict = nil; // get the script compiled and saved off @@ -139,10 +230,12 @@ NSString * const kGTMLoginItemsHiddenKey = @"Hide"; } [result addObject:item]; } - + return result; } +#endif // MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 + + (BOOL)pathInLoginItems:(NSString *)path { NSArray *loginItems = [self loginItems:nil]; NSInteger itemIndex = [self indexOfLoginItemWithValue:path @@ -164,30 +257,87 @@ NSString * const kGTMLoginItemsHiddenKey = @"Hide"; // make sure it isn't already there if ([self pathInLoginItems:path]) return; // now append it +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 + NSURL *url = [NSURL fileURLWithPath:path]; + if (url) { + LSSharedFileListRef loginItemsRef = [self loginItemsFileListRef]; + if (loginItemsRef) { + NSDictionary *setProperties = + [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:hide] + forKey:kLSSharedFileListLoginItemHidden]; + LSSharedFileListItemRef itemRef = + LSSharedFileListInsertItemURL(loginItemsRef, + kLSSharedFileListItemLast, NULL, NULL, + (CFURLRef)url, + (CFDictionaryRef)setProperties, NULL); + if (itemRef) CFRelease(itemRef); + } + } +#else // MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 NSString *scriptSource = [NSString stringWithFormat: @"tell application \"System Events\" to make new login item with properties { path:\"%s\", hidden:%s } at end", [path UTF8String], (hide ? "yes" : "no")]; [self compileAndRunScript:scriptSource withError:nil]; +#endif // MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 } + (void)removePathFromLoginItems:(NSString*)path { if ([path length] == 0) return; +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 + NSURL *url = [NSURL fileURLWithPath:path]; + LSSharedFileListRef loginItemsRef = [self loginItemsFileListRef]; + if (loginItemsRef) { + NSArray *fileList = [self loginItemsArrayForFileListRef:loginItemsRef]; + for (id item in fileList) { + LSSharedFileListItemRef itemRef = (LSSharedFileListItemRef)item; + CFURLRef urlRef = NULL; + if (LSSharedFileListItemResolve(itemRef, 0, &urlRef, NULL) == noErr) { + if (urlRef) { + if (CFEqual(urlRef, (CFURLRef)url)) { + LSSharedFileListItemRemove(loginItemsRef, itemRef); + } + CFRelease(urlRef); + } + } + } + } +#else // MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 NSString *scriptSource = [NSString stringWithFormat: @"tell application \"System Events\" to delete (login items whose path is \"%s\")", [path UTF8String]]; [self compileAndRunScript:scriptSource withError:nil]; +#endif // MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 } + (void)removeItemWithNameFromLoginItems:(NSString *)name { if ([name length] == 0) return; +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 + LSSharedFileListRef loginItemsRef = [self loginItemsFileListRef]; + if (loginItemsRef) { + NSArray *fileList = [self loginItemsArrayForFileListRef:loginItemsRef]; + for (id item in fileList) { + LSSharedFileListItemRef itemRef = (LSSharedFileListItemRef)item; + CFStringRef itemNameRef = LSSharedFileListItemCopyDisplayName(itemRef); + if (itemNameRef) { + NSString *itemName = + [(NSString *)itemNameRef stringByDeletingPathExtension]; + if ([itemName isEqual:name]) { + LSSharedFileListItemRemove(loginItemsRef, itemRef); + } + CFRelease(itemNameRef); + } + } + } +#else // MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 NSString *scriptSource = [NSString stringWithFormat: @"tell application \"System Events\" to delete (login items whose name is \"%s\")", [name UTF8String]]; [self compileAndRunScript:scriptSource withError:nil]; +#endif // MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 } @end -- cgit v1.2.3