/core/externals/update-engine/externals/google-toolbox-for-mac/AppKit/GTMLoginItems.m
Objective C | 342 lines | 268 code | 29 blank | 45 comment | 56 complexity | 6794bcb4adac07b3bbfa11041df248f5 MD5 | raw file
Possible License(s): Apache-2.0, BSD-3-Clause, GPL-2.0
- //
- // GTMLoginItems.m
- // Based on AELoginItems from DTS.
- //
- // Copyright 2007-2008 Google Inc.
- //
- // 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
- // License for the specific language governing permissions and limitations under
- // the License.
- //
- #import "GTMLoginItems.h"
- #import "GTMDefines.h"
- #include <Carbon/Carbon.h>
- // Exposed constants
- 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)
- + (NSInteger)indexOfLoginItemWithValue:(id)value
- forKey:(NSString *)key
- loginItems:(NSArray *)items {
- if (!value || !key || !items) return NSNotFound;
- NSDictionary *item = nil;
- NSInteger found = -1;
- GTM_FOREACH_OBJECT(item, items) {
- ++found;
- id itemValue = [item objectForKey:key];
- if (itemValue && [itemValue isEqual:value]) {
- return found;
- }
- }
- 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) {
- // COV_NF_START - no real way to test this
- if (errorInfo)
- *errorInfo = [NSError errorWithDomain:@"GTMLoginItems" code:-90 userInfo:nil];
- return NO;
- // COV_NF_END
- }
- NSAppleScript *query = [[[NSAppleScript alloc] initWithSource:script] autorelease];
- NSDictionary *errDict = nil;
- if ( ![query compileAndReturnError:&errDict]) {
- // COV_NF_START - no real way to test this
- if (errorInfo)
- *errorInfo = [NSError errorWithDomain:@"GTMLoginItems" code:-91 userInfo:errDict];
- return NO;
- // COV_NF_END
- }
- NSAppleEventDescriptor *scriptResult = [query executeAndReturnError:&errDict];
- if (!scriptResult) {
- // COV_NF_START - no real way to test this
- if (errorInfo)
- *errorInfo = [NSError errorWithDomain:@"GTMLoginItems" code:-92 userInfo:errDict];
- return NO;
- // COV_NF_END
- }
- // we don't process the result
- 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 fileItem in fileList) {
- LSSharedFileListItemRef itemRef = (LSSharedFileListItemRef)fileItem;
- // 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
- static NSAppleScript *query = nil;
- if (!query) {
- NSString *querySource = @"tell application \"System Events\" to get properties of login items";
- query = [[NSAppleScript alloc] initWithSource:querySource];
- if ( ![query compileAndReturnError:&errDict]) {
- // COV_NF_START - no real way to test this
- if (errorInfo)
- *errorInfo = [NSError errorWithDomain:@"GTMLoginItems" code:-1 userInfo:errDict];
- [query release];
- query = nil;
- return nil;
- // COV_NF_END
- }
- }
- // run the script
- NSAppleEventDescriptor *scriptResult = [query executeAndReturnError:&errDict];
- if (!scriptResult) {
- // COV_NF_START - no real way to test this
- if (errorInfo)
- *errorInfo = [NSError errorWithDomain:@"GTMLoginItems" code:-2 userInfo:errDict];
- return nil;
- // COV_NF_END
- }
- // build our results
- NSMutableArray *result = [NSMutableArray array];
- NSInteger count = [scriptResult numberOfItems];
- for (NSInteger i = 0; i < count; ++i) {
- NSAppleEventDescriptor *aeItem = [scriptResult descriptorAtIndex:i+1];
- NSAppleEventDescriptor *hidn = [aeItem descriptorForKeyword:kAEHidden];
- NSAppleEventDescriptor *nam = [aeItem descriptorForKeyword:pName];
- NSAppleEventDescriptor *ppth = [aeItem descriptorForKeyword:'ppth'];
- NSMutableDictionary *item = [NSMutableDictionary dictionary];
- if (hidn && [hidn booleanValue]) {
- [item setObject:[NSNumber numberWithBool:YES] forKey:kGTMLoginItemsHiddenKey];
- }
- if (nam) {
- NSString *name = [nam stringValue];
- if (name) {
- [item setObject:name forKey:kGTMLoginItemsNameKey];
- }
- }
- if (ppth) {
- NSString *path = [ppth stringValue];
- if (path) {
- [item setObject:path forKey:kGTMLoginItemsPathKey];
- }
- }
- [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
- forKey:kGTMLoginItemsPathKey
- loginItems:loginItems];
- return (itemIndex != NSNotFound) ? YES : NO;
- }
- + (BOOL)itemWithNameInLoginItems:(NSString *)name {
- NSArray *loginItems = [self loginItems:nil];
- NSInteger itemIndex = [self indexOfLoginItemWithValue:name
- forKey:kGTMLoginItemsNameKey
- loginItems:loginItems];
- return (itemIndex != NSNotFound) ? YES : NO;
- }
- + (void)addPathToLoginItems:(NSString*)path hide:(BOOL)hide {
- if (!path) return;
- // 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:(id)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