Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(118)

Side by Side Diff: chrome/installer/gcapi_mac/gcapi.mm

Issue 10834102: mac: Let gcapi install chrome as the CGSession owner (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: comments2 Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/installer/gcapi_mac/gcapi.h" 5 #include "chrome/installer/gcapi_mac/gcapi.h"
6 6
7 #import <Cocoa/Cocoa.h> 7 #import <Cocoa/Cocoa.h>
8 #include <pwd.h>
8 #include <sys/stat.h> 9 #include <sys/stat.h>
9 #include <sys/types.h> 10 #include <sys/types.h>
10 #include <sys/utsname.h> 11 #include <sys/utsname.h>
11 12
12 namespace { 13 namespace {
13 14
15 // The "~~" prefixes are replaced with the home directory of the
16 // console owner (i.e. not the home directory of the euid).
14 NSString* const kChromeInstallPath = @"/Applications/Google Chrome.app"; 17 NSString* const kChromeInstallPath = @"/Applications/Google Chrome.app";
15 18
16 NSString* const kBrandKey = @"KSBrandID"; 19 NSString* const kBrandKey = @"KSBrandID";
17 NSString* const kSystemBrandPath = @"/Library/Google/Google Chrome Brand.plist"; 20 NSString* const kUserBrandPath = @"~~/Library/Google/Google Chrome Brand.plist";
18 NSString* const kUserBrandPath = @"~/Library/Google/Google Chrome Brand.plist";
19 21
20 NSString* const kSystemKsadminPath = 22 NSString* const kSystemKsadminPath =
21 @"/Library/Google/GoogleSoftwareUpdate/GoogleSoftwareUpdate.bundle/" 23 @"/Library/Google/GoogleSoftwareUpdate/GoogleSoftwareUpdate.bundle/"
22 "Contents/MacOS/ksadmin"; 24 "Contents/MacOS/ksadmin";
23 25
24 NSString* const kUserKsadminPath = 26 NSString* const kUserKsadminPath =
25 @"~/Library/Google/GoogleSoftwareUpdate/GoogleSoftwareUpdate.bundle/" 27 @"~~/Library/Google/GoogleSoftwareUpdate/GoogleSoftwareUpdate.bundle/"
26 "Contents/MacOS/ksadmin"; 28 "Contents/MacOS/ksadmin";
27 29
28 NSString* const kSystemMasterPrefsPath = 30 NSString* const kSystemMasterPrefsPath =
29 @"/Library/Google/Google Chrome Master Preferences"; 31 @"/Library/Google/Google Chrome Master Preferences";
30 NSString* const kUserMasterPrefsPath = 32 NSString* const kUserMasterPrefsPath =
31 @"~/Library/Application Support/Google/Google Chrome Master Preferences"; 33 @"~~/Library/Application Support/Google/Google Chrome Master Preferences";
32 34
33 NSString* const kChannelKey = @"KSChannelID"; 35 NSString* const kChannelKey = @"KSChannelID";
34 NSString* const kVersionKey = @"KSVersion"; 36 NSString* const kVersionKey = @"KSVersion";
35 37
36 // Condensed from chromium's base/mac/mac_util.mm. 38 // Condensed from chromium's base/mac/mac_util.mm.
37 bool IsOSXVersionSupported() { 39 bool IsOSXVersionSupported() {
38 // On 10.6, Gestalt() was observed to be able to spawn threads (see 40 // On 10.6, Gestalt() was observed to be able to spawn threads (see
39 // http://crbug.com/53200). Don't call Gestalt(). 41 // http://crbug.com/53200). Don't call Gestalt().
40 struct utsname uname_info; 42 struct utsname uname_info;
41 if (uname(&uname_info) != 0) 43 if (uname(&uname_info) != 0)
(...skipping 11 matching lines...) Expand all
53 55
54 // The Darwin major version is always 4 greater than the Mac OS X minor 56 // The Darwin major version is always 4 greater than the Mac OS X minor
55 // version for Darwin versions beginning with 6, corresponding to Mac OS X 57 // version for Darwin versions beginning with 6, corresponding to Mac OS X
56 // 10.2. 58 // 10.2.
57 int mac_os_x_minor_version = darwin_major_version - 4; 59 int mac_os_x_minor_version = darwin_major_version - 4;
58 60
59 // Chrome is known to work on 10.6 - 10.8. 61 // Chrome is known to work on 10.6 - 10.8.
60 return mac_os_x_minor_version >= 6 && mac_os_x_minor_version <= 8; 62 return mac_os_x_minor_version >= 6 && mac_os_x_minor_version <= 8;
61 } 63 }
62 64
65 // Returns the pid/gid of the logged-in user, even if getuid() claims that the
66 // current user is root.
67 // Returns NULL on error.
68 passwd* GetRealUserId() {
69 CFDictionaryRef sessionInfoDict = CGSessionCopyCurrentDictionary();
70 if (!sessionInfoDict)
71 return NULL; // Possibly no screen plugged in.
72
73 CFNumberRef ns_uid = (CFNumberRef)CFDictionaryGetValue(sessionInfoDict,
74 kCGSessionUserIDKey);
75 if (CFGetTypeID(ns_uid) != CFNumberGetTypeID())
76 return NULL;
Mark Mentovai 2012/08/13 15:59:25 But you haven’t released sessionInfoDict (which sh
Nico 2012/08/13 18:03:58 Done.
77
78 uid_t uid;
79 BOOL success = CFNumberGetValue(ns_uid, kCFNumberSInt32Type, &uid);
80 CFRelease(sessionInfoDict);
81 if (!success)
82 return NULL;
83
84 return getpwuid(uid);
85 }
86
63 enum TicketKind { 87 enum TicketKind {
64 kSystemTicket, kUserTicket 88 kSystemTicket, kUserTicket
65 }; 89 };
66 90
67 BOOL HasChromeTicket(TicketKind kind) { 91 // Replaces "~~" with |home_dir|.
92 NSString* AdjustHomedir(NSString* s, const char* home_dir) {
93 if (![s hasPrefix:@"~~"])
94 return s;
95 NSString* ns_home_dir = [NSString stringWithUTF8String:home_dir];
96 return [ns_home_dir stringByAppendingString:[s substringFromIndex:2]];
97 }
98
99 BOOL HasChromeTicket(TicketKind kind, const passwd* user) {
68 // Don't use Objective-C 2 loop syntax, in case an installer runs on 10.4. 100 // Don't use Objective-C 2 loop syntax, in case an installer runs on 10.4.
69 NSMutableArray* keystonePaths = 101 NSMutableArray* keystone_paths =
70 [NSMutableArray arrayWithObject:kSystemKsadminPath]; 102 [NSMutableArray arrayWithObject:kSystemKsadminPath];
71 if (kind == kUserTicket && geteuid() != 0) 103 if (kind == kUserTicket) {
72 [keystonePaths insertObject:kUserKsadminPath atIndex:0]; 104 [keystone_paths insertObject:AdjustHomedir(kUserKsadminPath, user->pw_dir)
73 NSEnumerator* e = [keystonePaths objectEnumerator]; 105 atIndex:0];
106 }
107 NSEnumerator* e = [keystone_paths objectEnumerator];
74 id ksPath; 108 id ksPath;
Mark Mentovai 2012/08/13 15:59:25 Naming again.
Nico 2012/08/13 18:03:58 Done.
75 while ((ksPath = [e nextObject])) { 109 while ((ksPath = [e nextObject])) {
76 NSTask* task = nil; 110 NSTask* task = nil;
77 NSString* string = nil; 111 NSString* string = nil;
78 bool ksadminRanSuccessfully = false; 112 bool ksadmin_ran_successfully = false;
79 113
80 @try { 114 @try {
115 // XXX does this need to run as other user? or can admin read the user sto re?
Mark Mentovai 2012/08/13 15:59:25 This XXX is now obsolete?
Nico 2012/08/13 18:03:58 Done.
116 // it should be able to, so I think this is fine as is?
81 task = [[NSTask alloc] init]; 117 task = [[NSTask alloc] init];
82 [task setLaunchPath:ksPath]; 118 [task setLaunchPath:ksPath];
83 119
84 NSArray* arguments = @[ 120 NSArray* arguments = @[
85 kind == kUserTicket ? @"--user-store" : @"--system-store", 121 kind == kUserTicket ? @"--user-store" : @"--system-store",
86 @"--print-tickets", 122 @"--print-tickets",
87 @"--productid", 123 @"--productid",
88 @"com.google.Chrome", 124 @"com.google.Chrome",
89 ]; 125 ];
126 if (geteuid() == 0 && kind == kUserTicket) {
127 NSString* run_as = [NSString stringWithUTF8String:user->pw_name];
128 [task setLaunchPath:@"/usr/bin/sudo"];
129 arguments = [
Mark Mentovai 2012/08/13 15:59:25 Weird indentation.
Nico 2012/08/13 18:03:58 Made it weird in a different way.
130 @[@"-u", run_as, ksPath] arrayByAddingObjectsFromArray:arguments];
131 }
90 [task setArguments:arguments]; 132 [task setArguments:arguments];
91 133
92 NSPipe* pipe = [NSPipe pipe]; 134 NSPipe* pipe = [NSPipe pipe];
93 [task setStandardOutput:pipe]; 135 [task setStandardOutput:pipe];
94 136
95 NSFileHandle* file = [pipe fileHandleForReading]; 137 NSFileHandle* file = [pipe fileHandleForReading];
96 138
97 [task launch]; 139 [task launch];
98 140
99 NSData* data = [file readDataToEndOfFile]; 141 NSData* data = [file readDataToEndOfFile];
100 [task waitUntilExit]; 142 [task waitUntilExit];
101 143
102 ksadminRanSuccessfully = [task terminationStatus] == 0; 144 ksadmin_ran_successfully = [task terminationStatus] == 0;
103 string = [[[NSString alloc] initWithData:data 145 string = [[[NSString alloc] initWithData:data
104 encoding:NSUTF8StringEncoding] autorelease]; 146 encoding:NSUTF8StringEncoding] autorelease];
105 } 147 }
106 @catch (id exception) { 148 @catch (id exception) {
107 // Most likely, ksPath didn't exist. 149 // Most likely, ksPath didn't exist.
108 } 150 }
109 [task release]; 151 [task release];
110 152
111 if (ksadminRanSuccessfully && [string length] > 0) 153 if (ksadmin_ran_successfully && [string length] > 0)
112 return YES; 154 return YES;
113 } 155 }
114 156
115 return NO; 157 return NO;
116 } 158 }
117 159
118 // Returns the file permission mask for files created by gcapi. 160 // File permission mask for files created by gcapi.
119 mode_t Permissions() { 161 const mode_t kUserPermissions = 0755;
120 return 0755; 162 const mode_t kAdminPermissions = 0775;
121 }
122 163
123 BOOL CreatePathToFile(NSString* path) { 164 BOOL CreatePathToFile(NSString* path, const passwd* user) {
124 path = [path stringByDeletingLastPathComponent]; 165 path = [path stringByDeletingLastPathComponent];
125 166
126 // Default owner, group, permissions: 167 // Default owner, group, permissions:
127 // * Permissions are set according to the umask of the current process. For 168 // * Permissions are set according to the umask of the current process. For
128 // more information, see umask. 169 // more information, see umask.
129 // * The owner ID is set to the effective user ID of the process. 170 // * The owner ID is set to the effective user ID of the process.
130 // * The group ID is set to that of the parent directory. 171 // * The group ID is set to that of the parent directory.
131 // The default group ID is fine. Owner ID is fine too, since user directory 172 // The default group ID is fine. Owner ID is fine if creating a system path,
132 // paths won't be created if euid is 0. Do set permissions explicitly; for 173 // but when creating a user path explicitly set the owner in case euid is 0.
133 // admin paths all admins can write, for user paths just the owner may. 174 // Do set permissions explicitly; for admin paths all admins can write, for
134 NSMutableDictionary* attributes = [NSMutableDictionary 175 // user paths just the owner may.
135 dictionaryWithObject:[NSNumber numberWithShort:Permissions()] 176 NSMutableDictionary* attributes = [NSMutableDictionary dictionary];
136 forKey:NSFilePosixPermissions]; 177 if (user) {
137 if (geteuid() == 0) 178 [attributes setObject:[NSNumber numberWithShort:kUserPermissions]
138 [attributes setObject:@"wheel" forKey:NSFileGroupOwnerAccountName]; 179 forKey:NSFilePosixPermissions];
180 [attributes setObject:[NSNumber numberWithInt:user->pw_uid]
181 forKey:NSFileOwnerAccountID];
182 // XXX do this? not needed i think?
Mark Mentovai 2012/08/13 15:59:25 Right, shouldn’t be needed.
183 //[attributes setObject:[NSNumber numberWithInt:user->pw_gid]
184 //forKey:NSFileGroupOwnerAccountID];
185 } else {
186 [attributes setObject:[NSNumber numberWithShort:kAdminPermissions]
187 forKey:NSFilePosixPermissions];
188 [attributes setObject:@"admin" forKey:NSFileGroupOwnerAccountName];
189 }
139 190
140 NSFileManager* manager = [NSFileManager defaultManager]; 191 NSFileManager* manager = [NSFileManager defaultManager];
141 return [manager createDirectoryAtPath:path 192 return [manager createDirectoryAtPath:path
142 withIntermediateDirectories:YES 193 withIntermediateDirectories:YES
143 attributes:attributes 194 attributes:attributes
144 error:nil]; 195 error:nil];
145 } 196 }
146 197
147 // Tries to write |data| at |system_path| or if that fails and geteuid() is not 198 // Tries to write |data| at |user_path|.
148 // 0 at |user_path|. Returns the path where it wrote, or nil on failure. 199 // Returns the path where it wrote, or nil on failure.
149 NSString* WriteData(NSData* data, NSString* system_path, NSString* user_path) { 200 NSString* WriteUserData(NSData* data,
201 NSString* user_path,
202 const passwd* user) {
203 user_path = AdjustHomedir(user_path, user->pw_dir);
204 if (CreatePathToFile(user_path, user) &&
205 [data writeToFile:user_path atomically:YES]) {
206 chmod([user_path fileSystemRepresentation], kUserPermissions & ~0111);
207 chown([user_path fileSystemRepresentation], user->pw_uid, user->pw_gid);
208 return user_path;
209 }
210 return nil;
211 }
212
213 // Tries to write |data| at |system_path| or if that fails at |user_path|.
214 // Returns the path where it wrote, or nil on failure.
215 NSString* WriteData(NSData* data,
216 NSString* system_path,
217 NSString* user_path,
218 const passwd* user) {
150 // Try system first. 219 // Try system first.
151 if (CreatePathToFile(system_path) && 220 if (CreatePathToFile(system_path, NULL) &&
152 [data writeToFile:system_path atomically:YES]) { 221 [data writeToFile:system_path atomically:YES]) {
153 // files are created with group of parent dir (good), owner of euid (good). 222 // files are created with group of parent dir (good), owner of euid (good).
Mark Mentovai 2012/08/13 15:59:25 You have no assurance what the group of the parent
Nico 2012/08/13 18:03:58 The directory is /Library/Google -- if that exist
Mark Mentovai 2012/08/13 18:43:24 Nico wrote:
154 chmod([system_path fileSystemRepresentation], Permissions() & ~0111); 223 chmod([system_path fileSystemRepresentation], kAdminPermissions & ~0111);
155 return system_path; 224 return system_path;
156 } 225 }
157 226
158 // Failed, try user. 227 // Failed, try user.
159 // -stringByExpandingTildeInPath returns root's home directory if this is run 228 return WriteUserData(data, user_path, user);
160 // setuid root, and in that case the kSystemBrandPath path above should have
161 // worked anyway. So only try user if geteuid() isn't root.
162 if (geteuid() != 0) {
163 user_path = [user_path stringByExpandingTildeInPath];
164 if (CreatePathToFile(user_path) &&
165 [data writeToFile:user_path atomically:YES]) {
166 chmod([user_path fileSystemRepresentation], Permissions() & ~0111);
167 return user_path;
168 }
169 }
170 return nil;
171 } 229 }
172 230
173 NSString* WriteBrandCode(const char* brand_code) { 231 NSString* WriteBrandCode(const char* brand_code, const passwd* user) {
174 NSDictionary* brand_dict = @{ 232 NSDictionary* brand_dict = @{
175 kBrandKey: [NSString stringWithUTF8String:brand_code], 233 kBrandKey: [NSString stringWithUTF8String:brand_code],
176 }; 234 };
177 NSData* contents = [NSPropertyListSerialization 235 NSData* contents = [NSPropertyListSerialization
178 dataFromPropertyList:brand_dict 236 dataFromPropertyList:brand_dict
179 format:NSPropertyListBinaryFormat_v1_0 237 format:NSPropertyListBinaryFormat_v1_0
180 errorDescription:nil]; 238 errorDescription:nil];
181 239
182 return WriteData(contents, kSystemBrandPath, kUserBrandPath); 240 return WriteUserData(contents, kUserBrandPath, user);
183 } 241 }
184 242
185 BOOL WriteMasterPrefs(const char* master_prefs_contents, 243 BOOL WriteMasterPrefs(const char* master_prefs_contents,
186 size_t master_prefs_contents_size) { 244 size_t master_prefs_contents_size,
245 const passwd* user) {
187 NSData* contents = [NSData dataWithBytes:master_prefs_contents 246 NSData* contents = [NSData dataWithBytes:master_prefs_contents
188 length:master_prefs_contents_size]; 247 length:master_prefs_contents_size];
189 return 248 return WriteData(
190 WriteData(contents, kSystemMasterPrefsPath, kUserMasterPrefsPath) != nil; 249 contents, kSystemMasterPrefsPath, kUserMasterPrefsPath, user) != nil;
191 } 250 }
192 251
193 NSString* PathToFramework(NSString* app_path, NSDictionary* info_plist) { 252 NSString* PathToFramework(NSString* app_path, NSDictionary* info_plist) {
194 NSString* version = [info_plist objectForKey:@"CFBundleShortVersionString"]; 253 NSString* version = [info_plist objectForKey:@"CFBundleShortVersionString"];
195 if (!version) 254 if (!version)
196 return nil; 255 return nil;
197 return [[[app_path 256 return [[[app_path
198 stringByAppendingPathComponent:@"Contents/Versions"] 257 stringByAppendingPathComponent:@"Contents/Versions"]
199 stringByAppendingPathComponent:version] 258 stringByAppendingPathComponent:version]
200 stringByAppendingPathComponent:@"Google Chrome Framework.framework"]; 259 stringByAppendingPathComponent:@"Google Chrome Framework.framework"];
201 } 260 }
202 261
203 NSString* PathToInstallScript(NSString* app_path, NSDictionary* info_plist) { 262 NSString* PathToInstallScript(NSString* app_path, NSDictionary* info_plist) {
204 return [PathToFramework(app_path, info_plist) stringByAppendingPathComponent: 263 return [PathToFramework(app_path, info_plist) stringByAppendingPathComponent:
205 @"Resources/install.sh"]; 264 @"Resources/install.sh"];
206 } 265 }
207 266
208 bool isbrandchar(int c) { 267 bool isbrandchar(int c) {
209 // Always four upper-case alpha chars. 268 // Always four upper-case alpha chars.
210 return c >= 'A' && c <= 'Z'; 269 return c >= 'A' && c <= 'Z';
211 } 270 }
212 271
213 } // namespace 272 } // namespace
214 273
215 int GoogleChromeCompatibilityCheck(unsigned* reasons) { 274 int GoogleChromeCompatibilityCheck(unsigned* reasons) {
275 passwd* user = GetRealUserId();
276
216 unsigned local_reasons = 0; 277 unsigned local_reasons = 0;
217 278
218 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; 279 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
219 280
220 if (!IsOSXVersionSupported()) 281 if (!IsOSXVersionSupported())
221 local_reasons |= GCCC_ERROR_OSNOTSUPPORTED; 282 local_reasons |= GCCC_ERROR_OSNOTSUPPORTED;
222 283
223 if (HasChromeTicket(kSystemTicket)) 284 if (HasChromeTicket(kSystemTicket, NULL))
224 local_reasons |= GCCC_ERROR_SYSTEMLEVELALREADYPRESENT; 285 local_reasons |= GCCC_ERROR_ALREADYPRESENT;
225 286
226 if (geteuid() != 0 && HasChromeTicket(kUserTicket)) 287 if (HasChromeTicket(kUserTicket, user))
227 local_reasons |= GCCC_ERROR_USERLEVELALREADYPRESENT; 288 local_reasons |= GCCC_ERROR_ALREADYPRESENT;
228 289
229 if (![[NSFileManager defaultManager] isWritableFileAtPath:@"/Applications"]) 290 if (![[NSFileManager defaultManager] isWritableFileAtPath:@"/Applications"])
230 local_reasons |= GCCC_ERROR_ACCESSDENIED; 291 local_reasons |= GCCC_ERROR_ACCESSDENIED;
231 292
293 if (!local_reasons && [[NSFileManager defaultManager]
Mark Mentovai 2012/08/13 15:59:25 Why are you checking !local_reasons here, when in
Nico 2012/08/13 18:03:58 Done. I thought that ACCESSDENIED shouldn't be set
294 fileExistsAtPath:@"/Applications/Google Chrome.app"]) {
295 local_reasons |= GCCC_ERROR_ALREADYPRESENT;
296 }
297
232 [pool drain]; 298 [pool drain];
233 299
234 // Done. Copy/return results. 300 // Done. Copy/return results.
235 if (reasons != NULL) 301 if (reasons != NULL)
236 *reasons = local_reasons; 302 *reasons = local_reasons;
237 303
238 return local_reasons == 0; 304 return local_reasons == 0;
239 } 305 }
240 306
241 int InstallGoogleChrome(const char* source_path, 307 int InstallGoogleChrome(const char* source_path,
242 const char* brand_code, 308 const char* brand_code,
243 const char* master_prefs_contents, 309 const char* master_prefs_contents,
244 unsigned master_prefs_contents_size) { 310 unsigned master_prefs_contents_size) {
245 if (!GoogleChromeCompatibilityCheck(NULL)) 311 if (!GoogleChromeCompatibilityCheck(NULL))
246 return 0; 312 return 0;
247 313
314 passwd* user = GetRealUserId();
315
248 @autoreleasepool { 316 @autoreleasepool {
249 NSString* app_path = [NSString stringWithUTF8String:source_path]; 317 NSString* app_path = [NSString stringWithUTF8String:source_path];
250 NSString* info_plist_path = 318 NSString* info_plist_path =
251 [app_path stringByAppendingPathComponent:@"Contents/Info.plist"]; 319 [app_path stringByAppendingPathComponent:@"Contents/Info.plist"];
252 NSDictionary* info_plist = 320 NSDictionary* info_plist =
253 [NSDictionary dictionaryWithContentsOfFile:info_plist_path]; 321 [NSDictionary dictionaryWithContentsOfFile:info_plist_path];
254 322
255 // Use install.sh from the Chrome app bundle to copy Chrome to its 323 // Use install.sh from the Chrome app bundle to copy Chrome to its
256 // destination. 324 // destination.
257 NSString* install_script = PathToInstallScript(app_path, info_plist); 325 NSString* install_script = PathToInstallScript(app_path, info_plist);
258 if (!install_script) { 326 if (!install_script) {
259 return 0; 327 return 0;
260 } 328 }
261 329
262 @try { 330 @try {
331 // install.sh tries to make the installed app admin-writable, but
332 // only when it's not run as root.
333 NSString* run_as = [NSString stringWithUTF8String:user->pw_name];
263 NSTask* task = [[[NSTask alloc] init] autorelease]; 334 NSTask* task = [[[NSTask alloc] init] autorelease];
264 [task setLaunchPath:install_script]; 335 [task setLaunchPath:@"/usr/bin/sudo"];
265 [task setArguments:@[app_path, kChromeInstallPath]]; 336 [task setArguments:
337 @[@"-u", run_as, install_script, app_path, kChromeInstallPath]];
Mark Mentovai 2012/08/13 15:59:25 But if run_as is not an admin user, it won’t be ab
Nico 2012/08/13 18:03:58 Right, the new approach won't be able to install c
266 [task launch]; 338 [task launch];
267 [task waitUntilExit]; 339 [task waitUntilExit];
268 if ([task terminationStatus] != 0) { 340 if ([task terminationStatus] != 0) {
269 return 0; 341 return 0;
270 } 342 }
271 } 343 }
272 @catch (id exception) { 344 @catch (id exception) {
273 return 0; 345 return 0;
274 } 346 }
275 347
276 // Set brand code. If Chrome's Info.plist contains a brand code, use that. 348 // Set brand code. If Chrome's Info.plist contains a brand code, use that.
277 NSString* info_plist_brand = [info_plist objectForKey:kBrandKey]; 349 NSString* info_plist_brand = [info_plist objectForKey:kBrandKey];
278 if (info_plist_brand && 350 if (info_plist_brand &&
279 [info_plist_brand respondsToSelector:@selector(UTF8String)]) 351 [info_plist_brand respondsToSelector:@selector(UTF8String)])
280 brand_code = [info_plist_brand UTF8String]; 352 brand_code = [info_plist_brand UTF8String];
281 353
282 BOOL valid_brand_code = brand_code && strlen(brand_code) == 4 && 354 BOOL valid_brand_code = brand_code && strlen(brand_code) == 4 &&
283 isbrandchar(brand_code[0]) && isbrandchar(brand_code[1]) && 355 isbrandchar(brand_code[0]) && isbrandchar(brand_code[1]) &&
284 isbrandchar(brand_code[2]) && isbrandchar(brand_code[3]); 356 isbrandchar(brand_code[2]) && isbrandchar(brand_code[3]);
285 357
286 NSString* brand_path = nil; 358 NSString* brand_path = nil;
287 if (valid_brand_code) 359 if (valid_brand_code)
288 brand_path = WriteBrandCode(brand_code); 360 brand_path = WriteBrandCode(brand_code, user);
289 361
290 // Write master prefs. 362 // Write master prefs.
291 if (master_prefs_contents) 363 if (master_prefs_contents)
292 WriteMasterPrefs(master_prefs_contents, master_prefs_contents_size); 364 WriteMasterPrefs(master_prefs_contents, master_prefs_contents_size, user);
293 365
294 // TODO Set default browser if requested. Will be tricky when running as 366 // TODO Set default browser if requested.
295 // root.
296 } 367 }
297 return 1; 368 return 1;
298 } 369 }
299 370
300 int LaunchGoogleChrome() { 371 int LaunchGoogleChrome() {
372 //passwd* user = GetRealUserId();
Mark Mentovai 2012/08/13 15:59:25 Not needed?
Nico 2012/08/13 18:03:58 Done.
373
301 @autoreleasepool { 374 @autoreleasepool {
375 // NSWorkspace launches processes as the current console owner,
376 // even when running with euid of 0.
302 return [[NSWorkspace sharedWorkspace] launchApplication:kChromeInstallPath]; 377 return [[NSWorkspace sharedWorkspace] launchApplication:kChromeInstallPath];
303 } 378 }
304 } 379 }
OLDNEW
« chrome/installer/gcapi_mac/gcapi.h ('K') | « chrome/installer/gcapi_mac/gcapi.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698