blob: 3354b1c773a1d72bd0f5115cab1effa73411b9d6 [file] [log] [blame]
Alexander Afanasyevcc5c6712013-09-30 17:43:54 -07001//
2// LaunchAtLoginController.m
3//
4// Copyright 2011 Tomáš Znamenáček
5// Copyright 2010 Ben Clark-Robinson
6//
7// Permission is hereby granted, free of charge, to any person obtaining
8// a copy of this software and associated documentation files (the ‘Software’),
9// to deal in the Software without restriction, including without limitation
10// the rights to use, copy, modify, merge, publish, distribute, sublicense,
11// and/or sell copies of the Software, and to permit persons to whom the
12// Software is furnished to do so, subject to the following conditions:
13//
14// The above copyright notice and this permission notice shall be
15// included in all copies or substantial portions of the Software.
16//
17// THE SOFTWARE IS PROVIDED ‘AS IS’, WITHOUT WARRANTY OF ANY KIND,
18// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25#import "launch-at-login-controller.h"
26
27static NSString *const StartAtLoginKey = @"launchAtLogin";
28
29@interface LaunchAtLoginController ()
30@property(assign) LSSharedFileListRef loginItems;
31@end
32
33@implementation LaunchAtLoginController
34@synthesize loginItems;
35
36#pragma mark Change Observing
37
38void sharedFileListDidChange(LSSharedFileListRef inList, void *context)
39{
40 LaunchAtLoginController *self = (__bridge id) context;
41 [self willChangeValueForKey:StartAtLoginKey];
42 [self didChangeValueForKey:StartAtLoginKey];
43}
44
45#pragma mark Initialization
46
47- (id) init
48{
49 self = [super init];
50 loginItems = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL);
51 LSSharedFileListAddObserver(loginItems, CFRunLoopGetMain(),
Alexander Afanasyevb6392e32014-05-12 23:43:50 -070052 (__bridge CFStringRef)NSDefaultRunLoopMode, sharedFileListDidChange, (voidPtr)CFBridgingRetain(self));
Alexander Afanasyevcc5c6712013-09-30 17:43:54 -070053 return self;
54}
55
56- (void) dealloc
57{
58 LSSharedFileListRemoveObserver(loginItems, CFRunLoopGetMain(),
Alexander Afanasyevb6392e32014-05-12 23:43:50 -070059 (__bridge CFStringRef)NSDefaultRunLoopMode, sharedFileListDidChange, (__bridge void *)(self));
Alexander Afanasyevcc5c6712013-09-30 17:43:54 -070060 CFRelease(loginItems);
61}
62
63#pragma mark Launch List Control
64
65- (LSSharedFileListItemRef) findItemWithURL: (NSURL*) wantedURL inFileList: (LSSharedFileListRef) fileList
66{
67 if (wantedURL == NULL || fileList == NULL)
68 return NULL;
69
70 NSArray *listSnapshot = (__bridge NSArray *)(LSSharedFileListCopySnapshot(fileList, NULL));
71 for (id itemObject in listSnapshot) {
72 LSSharedFileListItemRef item = (__bridge LSSharedFileListItemRef) itemObject;
73 UInt32 resolutionFlags = kLSSharedFileListNoUserInteraction | kLSSharedFileListDoNotMountVolumes;
74 CFURLRef currentItemURL = NULL;
75 LSSharedFileListItemResolve(item, resolutionFlags, &currentItemURL, NULL);
76 if (currentItemURL && CFEqual(currentItemURL, (__bridge CFTypeRef)(wantedURL)))
77 {
78 CFRelease(currentItemURL);
79 return item;
80 }
81 if (currentItemURL)
82 CFRelease(currentItemURL);
83 }
84
85 return NULL;
86}
87
88- (BOOL) willLaunchAtLogin: (NSURL*) itemURL
89{
90 return !![self findItemWithURL:itemURL inFileList:loginItems];
91}
92
93- (void) setLaunchAtLogin: (BOOL) enabled forURL: (NSURL*) itemURL
94{
95 LSSharedFileListItemRef appItem = [self findItemWithURL:itemURL inFileList:loginItems];
96 if (enabled && !appItem) {
97 LSSharedFileListInsertItemURL(loginItems, kLSSharedFileListItemBeforeFirst,
98 NULL, NULL, (__bridge CFURLRef)itemURL, NULL, NULL);
99 } else if (!enabled && appItem)
100 LSSharedFileListItemRemove(loginItems, appItem);
101}
102
103#pragma mark Basic Interface
104
105- (NSURL*) appURL
106{
107 return [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]];
108}
109
110- (void) setLaunchAtLogin: (BOOL) enabled
111{
112 [self willChangeValueForKey:StartAtLoginKey];
113 [self setLaunchAtLogin:enabled forURL:[self appURL]];
114 [self didChangeValueForKey:StartAtLoginKey];
115}
116
117- (BOOL) launchAtLogin
118{
119 return [self willLaunchAtLogin:[self appURL]];
120}
121
122@end