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

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: . 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
« no previous file with comments | « chrome/installer/gcapi_mac/gcapi.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 session_info_dict = CGSessionCopyCurrentDictionary();
70 //[reinterpret_cast<NSDictionary*>(session_info_dict) autorelease];
Mark Mentovai 2012/08/13 18:43:24 How is this supposed to work when it’s commented o
Nico 2012/08/13 18:54:37 I had a vague memory that I wanted to do something
71 if (!session_info_dict)
72 return NULL; // Possibly no screen plugged in.
73
74 CFNumberRef ns_uid = (CFNumberRef)CFDictionaryGetValue(session_info_dict,
75 kCGSessionUserIDKey);
76 if (CFGetTypeID(ns_uid) != CFNumberGetTypeID())
77 return NULL;
78
79 uid_t uid;
80 BOOL success = CFNumberGetValue(ns_uid, kCFNumberSInt32Type, &uid);
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];
74 id ksPath; 106 }
75 while ((ksPath = [e nextObject])) { 107 NSEnumerator* e = [keystone_paths objectEnumerator];
108 id ks_path;
109 while ((ks_path = [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 {
81 task = [[NSTask alloc] init]; 115 task = [[NSTask alloc] init];
82 [task setLaunchPath:ksPath]; 116 [task setLaunchPath:ks_path];
83 117
84 NSArray* arguments = @[ 118 NSArray* arguments = @[
85 kind == kUserTicket ? @"--user-store" : @"--system-store", 119 kind == kUserTicket ? @"--user-store" : @"--system-store",
86 @"--print-tickets", 120 @"--print-tickets",
87 @"--productid", 121 @"--productid",
88 @"com.google.Chrome", 122 @"com.google.Chrome",
89 ]; 123 ];
124 if (geteuid() == 0 && kind == kUserTicket) {
125 NSString* run_as = [NSString stringWithUTF8String:user->pw_name];
126 [task setLaunchPath:@"/usr/bin/sudo"];
127 arguments = [@[@"-u", run_as, ks_path]
Mark Mentovai 2012/08/13 18:43:24 The indentation is still weird here. In case it w
Nico 2012/08/13 18:54:37 Oh, you meant the "arguments" line, not the contin
128 arrayByAddingObjectsFromArray:arguments];
129 }
90 [task setArguments:arguments]; 130 [task setArguments:arguments];
91 131
92 NSPipe* pipe = [NSPipe pipe]; 132 NSPipe* pipe = [NSPipe pipe];
93 [task setStandardOutput:pipe]; 133 [task setStandardOutput:pipe];
94 134
95 NSFileHandle* file = [pipe fileHandleForReading]; 135 NSFileHandle* file = [pipe fileHandleForReading];
96 136
97 [task launch]; 137 [task launch];
98 138
99 NSData* data = [file readDataToEndOfFile]; 139 NSData* data = [file readDataToEndOfFile];
100 [task waitUntilExit]; 140 [task waitUntilExit];
101 141
102 ksadminRanSuccessfully = [task terminationStatus] == 0; 142 ksadmin_ran_successfully = [task terminationStatus] == 0;
103 string = [[[NSString alloc] initWithData:data 143 string = [[[NSString alloc] initWithData:data
104 encoding:NSUTF8StringEncoding] autorelease]; 144 encoding:NSUTF8StringEncoding] autorelease];
105 } 145 }
106 @catch (id exception) { 146 @catch (id exception) {
107 // Most likely, ksPath didn't exist. 147 // Most likely, ks_path didn't exist.
108 } 148 }
109 [task release]; 149 [task release];
110 150
111 if (ksadminRanSuccessfully && [string length] > 0) 151 if (ksadmin_ran_successfully && [string length] > 0)
112 return YES; 152 return YES;
113 } 153 }
114 154
115 return NO; 155 return NO;
116 } 156 }
117 157
118 // Returns the file permission mask for files created by gcapi. 158 // File permission mask for files created by gcapi.
119 mode_t Permissions() { 159 const mode_t kUserPermissions = 0755;
120 return 0755; 160 const mode_t kAdminPermissions = 0775;
121 }
122 161
123 BOOL CreatePathToFile(NSString* path) { 162 BOOL CreatePathToFile(NSString* path, const passwd* user) {
124 path = [path stringByDeletingLastPathComponent]; 163 path = [path stringByDeletingLastPathComponent];
125 164
126 // Default owner, group, permissions: 165 // Default owner, group, permissions:
127 // * Permissions are set according to the umask of the current process. For 166 // * Permissions are set according to the umask of the current process. For
128 // more information, see umask. 167 // more information, see umask.
129 // * The owner ID is set to the effective user ID of the process. 168 // * 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. 169 // * 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 170 // 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 171 // 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. 172 // Do set permissions explicitly; for admin paths all admins can write, for
134 NSMutableDictionary* attributes = [NSMutableDictionary 173 // user paths just the owner may.
135 dictionaryWithObject:[NSNumber numberWithShort:Permissions()] 174 NSMutableDictionary* attributes = [NSMutableDictionary dictionary];
136 forKey:NSFilePosixPermissions]; 175 if (user) {
137 if (geteuid() == 0) 176 [attributes setObject:[NSNumber numberWithShort:kUserPermissions]
138 [attributes setObject:@"wheel" forKey:NSFileGroupOwnerAccountName]; 177 forKey:NSFilePosixPermissions];
178 [attributes setObject:[NSNumber numberWithInt:user->pw_uid]
179 forKey:NSFileOwnerAccountID];
180 } else {
181 [attributes setObject:[NSNumber numberWithShort:kAdminPermissions]
182 forKey:NSFilePosixPermissions];
183 [attributes setObject:@"admin" forKey:NSFileGroupOwnerAccountName];
184 }
139 185
140 NSFileManager* manager = [NSFileManager defaultManager]; 186 NSFileManager* manager = [NSFileManager defaultManager];
141 return [manager createDirectoryAtPath:path 187 return [manager createDirectoryAtPath:path
142 withIntermediateDirectories:YES 188 withIntermediateDirectories:YES
143 attributes:attributes 189 attributes:attributes
144 error:nil]; 190 error:nil];
145 } 191 }
146 192
147 // Tries to write |data| at |system_path| or if that fails and geteuid() is not 193 // Tries to write |data| at |user_path|.
148 // 0 at |user_path|. Returns the path where it wrote, or nil on failure. 194 // Returns the path where it wrote, or nil on failure.
149 NSString* WriteData(NSData* data, NSString* system_path, NSString* user_path) { 195 NSString* WriteUserData(NSData* data,
196 NSString* user_path,
197 const passwd* user) {
198 user_path = AdjustHomedir(user_path, user->pw_dir);
199 if (CreatePathToFile(user_path, user) &&
200 [data writeToFile:user_path atomically:YES]) {
201 chmod([user_path fileSystemRepresentation], kUserPermissions & ~0111);
202 chown([user_path fileSystemRepresentation], user->pw_uid, user->pw_gid);
203 return user_path;
204 }
205 return nil;
206 }
207
208 // Tries to write |data| at |system_path| or if that fails at |user_path|.
209 // Returns the path where it wrote, or nil on failure.
210 NSString* WriteData(NSData* data,
211 NSString* system_path,
212 NSString* user_path,
213 const passwd* user) {
150 // Try system first. 214 // Try system first.
151 if (CreatePathToFile(system_path) && 215 if (CreatePathToFile(system_path, NULL) &&
152 [data writeToFile:system_path atomically:YES]) { 216 [data writeToFile:system_path atomically:YES]) {
153 // files are created with group of parent dir (good), owner of euid (good). 217 // files are created with group of parent dir (good), owner of euid (good).
154 chmod([system_path fileSystemRepresentation], Permissions() & ~0111); 218 chmod([system_path fileSystemRepresentation], kAdminPermissions & ~0111);
155 return system_path; 219 return system_path;
156 } 220 }
157 221
158 // Failed, try user. 222 // Failed, try user.
159 // -stringByExpandingTildeInPath returns root's home directory if this is run 223 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 } 224 }
172 225
173 NSString* WriteBrandCode(const char* brand_code) { 226 NSString* WriteBrandCode(const char* brand_code, const passwd* user) {
174 NSDictionary* brand_dict = @{ 227 NSDictionary* brand_dict = @{
175 kBrandKey: [NSString stringWithUTF8String:brand_code], 228 kBrandKey: [NSString stringWithUTF8String:brand_code],
176 }; 229 };
177 NSData* contents = [NSPropertyListSerialization 230 NSData* contents = [NSPropertyListSerialization
178 dataFromPropertyList:brand_dict 231 dataFromPropertyList:brand_dict
179 format:NSPropertyListBinaryFormat_v1_0 232 format:NSPropertyListBinaryFormat_v1_0
180 errorDescription:nil]; 233 errorDescription:nil];
181 234
182 return WriteData(contents, kSystemBrandPath, kUserBrandPath); 235 return WriteUserData(contents, kUserBrandPath, user);
183 } 236 }
184 237
185 BOOL WriteMasterPrefs(const char* master_prefs_contents, 238 BOOL WriteMasterPrefs(const char* master_prefs_contents,
186 size_t master_prefs_contents_size) { 239 size_t master_prefs_contents_size,
240 const passwd* user) {
187 NSData* contents = [NSData dataWithBytes:master_prefs_contents 241 NSData* contents = [NSData dataWithBytes:master_prefs_contents
188 length:master_prefs_contents_size]; 242 length:master_prefs_contents_size];
189 return 243 return WriteData(
190 WriteData(contents, kSystemMasterPrefsPath, kUserMasterPrefsPath) != nil; 244 contents, kSystemMasterPrefsPath, kUserMasterPrefsPath, user) != nil;
191 } 245 }
192 246
193 NSString* PathToFramework(NSString* app_path, NSDictionary* info_plist) { 247 NSString* PathToFramework(NSString* app_path, NSDictionary* info_plist) {
194 NSString* version = [info_plist objectForKey:@"CFBundleShortVersionString"]; 248 NSString* version = [info_plist objectForKey:@"CFBundleShortVersionString"];
195 if (!version) 249 if (!version)
196 return nil; 250 return nil;
197 return [[[app_path 251 return [[[app_path
198 stringByAppendingPathComponent:@"Contents/Versions"] 252 stringByAppendingPathComponent:@"Contents/Versions"]
199 stringByAppendingPathComponent:version] 253 stringByAppendingPathComponent:version]
200 stringByAppendingPathComponent:@"Google Chrome Framework.framework"]; 254 stringByAppendingPathComponent:@"Google Chrome Framework.framework"];
201 } 255 }
202 256
203 NSString* PathToInstallScript(NSString* app_path, NSDictionary* info_plist) { 257 NSString* PathToInstallScript(NSString* app_path, NSDictionary* info_plist) {
204 return [PathToFramework(app_path, info_plist) stringByAppendingPathComponent: 258 return [PathToFramework(app_path, info_plist) stringByAppendingPathComponent:
205 @"Resources/install.sh"]; 259 @"Resources/install.sh"];
206 } 260 }
207 261
208 bool isbrandchar(int c) { 262 bool isbrandchar(int c) {
209 // Always four upper-case alpha chars. 263 // Always four upper-case alpha chars.
210 return c >= 'A' && c <= 'Z'; 264 return c >= 'A' && c <= 'Z';
211 } 265 }
212 266
213 } // namespace 267 } // namespace
214 268
215 int GoogleChromeCompatibilityCheck(unsigned* reasons) { 269 int GoogleChromeCompatibilityCheck(unsigned* reasons) {
270 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
Mark Mentovai 2012/08/13 18:43:24 You used @autoreleasepool elsewhere in this file.
Nico 2012/08/13 18:54:37 Done.
271
216 unsigned local_reasons = 0; 272 unsigned local_reasons = 0;
217 273 passwd* user = GetRealUserId();
218 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
219 274
220 if (!IsOSXVersionSupported()) 275 if (!IsOSXVersionSupported())
221 local_reasons |= GCCC_ERROR_OSNOTSUPPORTED; 276 local_reasons |= GCCC_ERROR_OSNOTSUPPORTED;
222 277
223 if (HasChromeTicket(kSystemTicket)) 278 if (HasChromeTicket(kSystemTicket, NULL))
224 local_reasons |= GCCC_ERROR_SYSTEMLEVELALREADYPRESENT; 279 local_reasons |= GCCC_ERROR_ALREADYPRESENT;
225 280
226 if (geteuid() != 0 && HasChromeTicket(kUserTicket)) 281 if (HasChromeTicket(kUserTicket, user))
227 local_reasons |= GCCC_ERROR_USERLEVELALREADYPRESENT; 282 local_reasons |= GCCC_ERROR_ALREADYPRESENT;
228 283
229 if (![[NSFileManager defaultManager] isWritableFileAtPath:@"/Applications"]) 284 if (![[NSFileManager defaultManager] isWritableFileAtPath:@"/Applications"])
230 local_reasons |= GCCC_ERROR_ACCESSDENIED; 285 local_reasons |= GCCC_ERROR_ACCESSDENIED;
231 286
287 if ([[NSFileManager defaultManager] fileExistsAtPath:kChromeInstallPath])
288 local_reasons |= GCCC_ERROR_ALREADYPRESENT;
289
232 [pool drain]; 290 [pool drain];
233 291
234 // Done. Copy/return results. 292 // Done. Copy/return results.
235 if (reasons != NULL) 293 if (reasons != NULL)
236 *reasons = local_reasons; 294 *reasons = local_reasons;
237 295
238 return local_reasons == 0; 296 return local_reasons == 0;
239 } 297 }
240 298
241 int InstallGoogleChrome(const char* source_path, 299 int InstallGoogleChrome(const char* source_path,
242 const char* brand_code, 300 const char* brand_code,
243 const char* master_prefs_contents, 301 const char* master_prefs_contents,
244 unsigned master_prefs_contents_size) { 302 unsigned master_prefs_contents_size) {
245 if (!GoogleChromeCompatibilityCheck(NULL)) 303 if (!GoogleChromeCompatibilityCheck(NULL))
246 return 0; 304 return 0;
247 305
248 @autoreleasepool { 306 @autoreleasepool {
307 passwd* user = GetRealUserId();
308
249 NSString* app_path = [NSString stringWithUTF8String:source_path]; 309 NSString* app_path = [NSString stringWithUTF8String:source_path];
250 NSString* info_plist_path = 310 NSString* info_plist_path =
251 [app_path stringByAppendingPathComponent:@"Contents/Info.plist"]; 311 [app_path stringByAppendingPathComponent:@"Contents/Info.plist"];
252 NSDictionary* info_plist = 312 NSDictionary* info_plist =
253 [NSDictionary dictionaryWithContentsOfFile:info_plist_path]; 313 [NSDictionary dictionaryWithContentsOfFile:info_plist_path];
254 314
255 // Use install.sh from the Chrome app bundle to copy Chrome to its 315 // Use install.sh from the Chrome app bundle to copy Chrome to its
256 // destination. 316 // destination.
257 NSString* install_script = PathToInstallScript(app_path, info_plist); 317 NSString* install_script = PathToInstallScript(app_path, info_plist);
258 if (!install_script) { 318 if (!install_script) {
259 return 0; 319 return 0;
260 } 320 }
261 321
262 @try { 322 @try {
323 // install.sh tries to make the installed app admin-writable, but
324 // only when it's not run as root.
325 NSString* run_as = [NSString stringWithUTF8String:user->pw_name];
263 NSTask* task = [[[NSTask alloc] init] autorelease]; 326 NSTask* task = [[[NSTask alloc] init] autorelease];
264 [task setLaunchPath:install_script]; 327 [task setLaunchPath:@"/usr/bin/sudo"];
265 [task setArguments:@[app_path, kChromeInstallPath]]; 328 [task setArguments:
329 @[@"-u", run_as, install_script, app_path, kChromeInstallPath]];
266 [task launch]; 330 [task launch];
267 [task waitUntilExit]; 331 [task waitUntilExit];
268 if ([task terminationStatus] != 0) { 332 if ([task terminationStatus] != 0) {
269 return 0; 333 return 0;
270 } 334 }
271 } 335 }
272 @catch (id exception) { 336 @catch (id exception) {
273 return 0; 337 return 0;
274 } 338 }
275 339
276 // Set brand code. If Chrome's Info.plist contains a brand code, use that. 340 // Set brand code. If Chrome's Info.plist contains a brand code, use that.
277 NSString* info_plist_brand = [info_plist objectForKey:kBrandKey]; 341 NSString* info_plist_brand = [info_plist objectForKey:kBrandKey];
278 if (info_plist_brand && 342 if (info_plist_brand &&
279 [info_plist_brand respondsToSelector:@selector(UTF8String)]) 343 [info_plist_brand respondsToSelector:@selector(UTF8String)])
280 brand_code = [info_plist_brand UTF8String]; 344 brand_code = [info_plist_brand UTF8String];
281 345
282 BOOL valid_brand_code = brand_code && strlen(brand_code) == 4 && 346 BOOL valid_brand_code = brand_code && strlen(brand_code) == 4 &&
283 isbrandchar(brand_code[0]) && isbrandchar(brand_code[1]) && 347 isbrandchar(brand_code[0]) && isbrandchar(brand_code[1]) &&
284 isbrandchar(brand_code[2]) && isbrandchar(brand_code[3]); 348 isbrandchar(brand_code[2]) && isbrandchar(brand_code[3]);
285 349
286 NSString* brand_path = nil; 350 NSString* brand_path = nil;
287 if (valid_brand_code) 351 if (valid_brand_code)
288 brand_path = WriteBrandCode(brand_code); 352 brand_path = WriteBrandCode(brand_code, user);
289 353
290 // Write master prefs. 354 // Write master prefs.
291 if (master_prefs_contents) 355 if (master_prefs_contents)
292 WriteMasterPrefs(master_prefs_contents, master_prefs_contents_size); 356 WriteMasterPrefs(master_prefs_contents, master_prefs_contents_size, user);
293 357
294 // TODO Set default browser if requested. Will be tricky when running as 358 // TODO Set default browser if requested.
295 // root.
296 } 359 }
297 return 1; 360 return 1;
298 } 361 }
299 362
300 int LaunchGoogleChrome() { 363 int LaunchGoogleChrome() {
301 @autoreleasepool { 364 @autoreleasepool {
365 // NSWorkspace launches processes as the current console owner,
366 // even when running with euid of 0.
302 return [[NSWorkspace sharedWorkspace] launchApplication:kChromeInstallPath]; 367 return [[NSWorkspace sharedWorkspace] launchApplication:kChromeInstallPath];
303 } 368 }
304 } 369 }
OLDNEW
« no previous file with comments | « chrome/installer/gcapi_mac/gcapi.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698