1
+ //
2
+ // NSLoginItems.m
3
+ //
4
+ // Created by BrotherBard on 4/18/09.
5
+ // Copyright 2009 BrotherBard <nkinsinger at earthlink dot net>. All rights reserved.
6
+ //
7
+ // Redistribution and use in source and binary forms, with or without modification,
8
+ // are permitted provided that the following conditions are met:
9
+ // * Redistributions of source code must retain the above copyright notice, this
10
+ // list of conditions and the following disclaimer.
11
+ // * Redistributions in binary form must reproduce the above copyright notice,
12
+ // this list of conditions and the following disclaimer in the documentation
13
+ // and/or other materials provided with the distribution.
14
+ //
15
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16
+ // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17
+ // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
19
+ // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20
+ // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21
+ // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
22
+ // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
+ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24
+ // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+ //
26
+
27
+ #import " BBAppSessionLoginState.h"
28
+
29
+ // Private
30
+ @interface BBAppSessionLoginState ()
31
+
32
+ - (LSSharedFileListItemRef)itemRefForApp ;
33
+ - (void )updateLoginItemState ;
34
+
35
+ @end
36
+
37
+
38
+
39
+ @implementation BBAppSessionLoginState
40
+
41
+ @synthesize isAppInSessionLoginList;
42
+
43
+
44
+ - (void )setIsAppInSessionLoginList : (BOOL )isInList {
45
+ if (isAppInSessionLoginList != isInList) {
46
+ isAppInSessionLoginList = isInList;
47
+ if (isInList) {
48
+ [self addAppToSessionLoginList ];
49
+ } else {
50
+ [self removeAppFromSessionLoginList ];
51
+ }
52
+ }
53
+ }
54
+
55
+ // When something changes I get six calls to this method. The first two have the same seed and
56
+ // the last four do too. I'm not sure if it is something wierd on my computer, but I compare the
57
+ // seed to the previous one to stop updating the login state too often.
58
+ static void SharedFileListChanged (LSSharedFileListRef list, void *context)
59
+ {
60
+ static UInt32 previousSeed = 0 ;
61
+
62
+ // there are other types of lists, so make sure we are just looking at the Session Login list
63
+ LSSharedFileListRef sessionLoginList = (LSSharedFileListRef)context;
64
+
65
+ if (list == sessionLoginList) {
66
+ UInt32 seed = LSSharedFileListGetSeedValue (list);
67
+ if (seed > previousSeed) {
68
+ [[BBAppSessionLoginState sharedController ] updateLoginItemState ];
69
+ previousSeed = seed;
70
+ }
71
+ }
72
+ }
73
+
74
+
75
+ + (id )sharedController
76
+ {
77
+ static BBAppSessionLoginState *sharedController = nil ;
78
+ if (!sharedController)
79
+ sharedController = [[self alloc ] init ];
80
+
81
+ return sharedController;
82
+ }
83
+
84
+
85
+ - (id )init
86
+ {
87
+ self = [super init ];
88
+ if (!self) return nil ;
89
+
90
+ _sessionLoginItemsList = LSSharedFileListCreate (kCFAllocatorDefault , // inAllocator
91
+ kLSSharedFileListSessionLoginItems , // inListType
92
+ NULL ); // listOptions
93
+ if (!_sessionLoginItemsList) {
94
+ [self release ];
95
+ return nil ;
96
+ }
97
+
98
+ LSSharedFileListAddObserver (_sessionLoginItemsList, // inList
99
+ [[NSRunLoop mainRunLoop ] getCFRunLoop ], // inRunloop
100
+ kCFRunLoopDefaultMode , // inRunloopMode
101
+ SharedFileListChanged, // callback
102
+ _sessionLoginItemsList); // context
103
+
104
+ _appPath = [[NSBundle mainBundle ] bundlePath ];
105
+ [self updateLoginItemState ];
106
+
107
+ return self;
108
+ }
109
+
110
+
111
+ - (void )dealloc
112
+ {
113
+ if (_sessionLoginItemsList) {
114
+ LSSharedFileListRemoveObserver (_sessionLoginItemsList, // inList
115
+ [[NSRunLoop mainRunLoop ] getCFRunLoop ], // inRunloop
116
+ kCFRunLoopDefaultMode , // inRunloopMode
117
+ SharedFileListChanged, // callback
118
+ _sessionLoginItemsList); // context
119
+
120
+ CFRelease (_sessionLoginItemsList);
121
+ }
122
+
123
+ [super dealloc ];
124
+ }
125
+
126
+
127
+ - (LSSharedFileListItemRef)itemRefForApp
128
+ {
129
+ UInt32 seed;
130
+ NSArray *items = (NSArray *)LSSharedFileListCopySnapshot (_sessionLoginItemsList, &seed);
131
+
132
+ for (id item in items) {
133
+ LSSharedFileListItemRef itemRef = (LSSharedFileListItemRef)item;
134
+
135
+ NSURL *theURL;
136
+ LSSharedFileListItemResolve (itemRef, // inItem
137
+ kLSSharedFileListNoUserInteraction , // inFlags
138
+ (CFURLRef*)&theURL, // outURL
139
+ NULL ); // outFSRef
140
+ [theURL autorelease ];
141
+
142
+ if ([_appPath isEqualToString: [theURL path ]])
143
+ return itemRef;
144
+ }
145
+
146
+ return NULL ;
147
+ }
148
+
149
+
150
+ - (void )updateLoginItemState
151
+ {
152
+ BOOL currentState = [self itemRefForApp ] ? YES : NO ;
153
+ if (self.isAppInSessionLoginList != currentState)
154
+ isAppInSessionLoginList = currentState;
155
+ }
156
+
157
+
158
+ - (void )toggleAppSessionLoginListState
159
+ {
160
+ if (isAppInSessionLoginList)
161
+ [self removeAppFromSessionLoginList ];
162
+ else
163
+ [self addAppToSessionLoginList ];
164
+ }
165
+
166
+
167
+ - (void )setAppSessionLoginListState : (BOOL )state
168
+ {
169
+ if (state)
170
+ [self addAppToSessionLoginList ];
171
+ else
172
+ [self removeAppFromSessionLoginList ];
173
+ }
174
+
175
+
176
+ - (void )removeAppFromSessionLoginList
177
+ {
178
+ LSSharedFileListItemRef itemRef = [self itemRefForApp ];
179
+
180
+ if (itemRef) {
181
+ OSStatus error = LSSharedFileListItemRemove (_sessionLoginItemsList, itemRef);
182
+ if (error != noErr)
183
+ NSLog (@" Failed to remove App from Session Login Items" );
184
+ }
185
+
186
+ [self updateLoginItemState ];
187
+ }
188
+
189
+
190
+ - (void )addAppToSessionLoginList
191
+ {
192
+ LSSharedFileListItemRef itemRef = [self itemRefForApp ];
193
+
194
+ if (!itemRef) {
195
+ // I believe the default is to not Hide the app, but I'm not really sure because the
196
+ // kLSSharedFileListItemHidden property is not read corretly by LSSharedFileListItemCopyProperty.
197
+ // I'm just setting it here to have a default value.
198
+ NSDictionary * propertiesToSet = [NSDictionary dictionaryWithObject: [NSNumber numberWithBool: NO ]
199
+ forKey: (id )kLSSharedFileListItemHidden ];
200
+ NSURL *url = [NSURL fileURLWithPath: _appPath];
201
+ NSLog (@" %@ " , url);
202
+
203
+ itemRef = LSSharedFileListInsertItemURL (_sessionLoginItemsList, // inList
204
+ kLSSharedFileListItemLast , // insertAfterThisItem
205
+ NULL , // inDisplayName - NULL = will use app name
206
+ NULL , // inIconRef - NULL = will use app icon
207
+ (CFURLRef)url, // inURL
208
+ (CFDictionaryRef)propertiesToSet, // inPropertiesToSet
209
+ NULL ); // inPropertiesToClear
210
+
211
+ if (itemRef)
212
+ CFRelease (itemRef);
213
+ else
214
+ NSLog (@" Failed to add App to Session Login Items" );
215
+ }
216
+
217
+ [self updateLoginItemState ];
218
+ }
219
+
220
+ @end
0 commit comments