OLD | NEW |
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 <sys/stat.h> | 8 #include <sys/stat.h> |
9 #include <sys/types.h> | 9 #include <sys/types.h> |
10 #include <sys/utsname.h> | 10 #include <sys/utsname.h> |
(...skipping 16 matching lines...) Expand all Loading... |
27 | 27 |
28 NSString* const kSystemMasterPrefsPath = | 28 NSString* const kSystemMasterPrefsPath = |
29 @"/Library/Google/Google Chrome Master Preferences"; | 29 @"/Library/Google/Google Chrome Master Preferences"; |
30 NSString* const kUserMasterPrefsPath = | 30 NSString* const kUserMasterPrefsPath = |
31 @"~/Library/Application Support/Google/Google Chrome Master Preferences"; | 31 @"~/Library/Application Support/Google/Google Chrome Master Preferences"; |
32 | 32 |
33 NSString* const kChannelKey = @"KSChannelID"; | 33 NSString* const kChannelKey = @"KSChannelID"; |
34 NSString* const kVersionKey = @"KSVersion"; | 34 NSString* const kVersionKey = @"KSVersion"; |
35 | 35 |
36 // Condensed from chromium's base/mac/mac_util.mm. | 36 // Condensed from chromium's base/mac/mac_util.mm. |
37 bool IsOSXLeopardOrLater() { | 37 bool IsOSXVersionSupported() { |
38 // On 10.6, Gestalt() was observed to be able to spawn threads (see | 38 // On 10.6, Gestalt() was observed to be able to spawn threads (see |
39 // http://crbug.com/53200). Don't call Gestalt(). | 39 // http://crbug.com/53200). Don't call Gestalt(). |
40 struct utsname uname_info; | 40 struct utsname uname_info; |
41 if (uname(&uname_info) != 0) | 41 if (uname(&uname_info) != 0) |
42 return false; | 42 return false; |
43 if (strcmp(uname_info.sysname, "Darwin") != 0) | 43 if (strcmp(uname_info.sysname, "Darwin") != 0) |
44 return false; | 44 return false; |
45 | 45 |
46 char* dot = strchr(uname_info.release, '.'); | 46 char* dot = strchr(uname_info.release, '.'); |
47 if (!dot) | 47 if (!dot) |
48 return false; | 48 return false; |
49 | 49 |
50 int darwin_major_version = atoi(uname_info.release); | 50 int darwin_major_version = atoi(uname_info.release); |
51 if (darwin_major_version < 6) | 51 if (darwin_major_version < 6) |
52 return false; | 52 return false; |
53 | 53 |
54 // The Darwin major version is always 4 greater than the Mac OS X minor | 54 // 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 | 55 // version for Darwin versions beginning with 6, corresponding to Mac OS X |
56 // 10.2. | 56 // 10.2. |
57 int mac_os_x_minor_version = darwin_major_version - 4; | 57 int mac_os_x_minor_version = darwin_major_version - 4; |
58 | 58 |
59 return mac_os_x_minor_version >= 5; | 59 // Chrome is known to work on 10.6 - 10.8. |
| 60 return mac_os_x_minor_version >= 6 && mac_os_x_minor_version <= 8; |
60 } | 61 } |
61 | 62 |
62 enum TicketKind { | 63 enum TicketKind { |
63 kSystemTicket, kUserTicket | 64 kSystemTicket, kUserTicket |
64 }; | 65 }; |
65 | 66 |
66 BOOL HasChromeTicket(TicketKind kind) { | 67 BOOL HasChromeTicket(TicketKind kind) { |
67 // Don't use Objective-C 2 loop syntax, in case an installer runs on 10.4. | 68 // Don't use Objective-C 2 loop syntax, in case an installer runs on 10.4. |
68 NSMutableArray* keystonePaths = | 69 NSMutableArray* keystonePaths = |
69 [NSMutableArray arrayWithObject:kSystemKsadminPath]; | 70 [NSMutableArray arrayWithObject:kSystemKsadminPath]; |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
197 stringByAppendingPathComponent:@"Contents/Versions"] | 198 stringByAppendingPathComponent:@"Contents/Versions"] |
198 stringByAppendingPathComponent:version] | 199 stringByAppendingPathComponent:version] |
199 stringByAppendingPathComponent:@"Google Chrome Framework.framework"]; | 200 stringByAppendingPathComponent:@"Google Chrome Framework.framework"]; |
200 } | 201 } |
201 | 202 |
202 NSString* PathToInstallScript(NSString* app_path, NSDictionary* info_plist) { | 203 NSString* PathToInstallScript(NSString* app_path, NSDictionary* info_plist) { |
203 return [PathToFramework(app_path, info_plist) stringByAppendingPathComponent: | 204 return [PathToFramework(app_path, info_plist) stringByAppendingPathComponent: |
204 @"Resources/install.sh"]; | 205 @"Resources/install.sh"]; |
205 } | 206 } |
206 | 207 |
207 NSString* PathToKeystoneResources( | |
208 NSString* app_path, NSDictionary* info_plist) { | |
209 return [PathToFramework(app_path, info_plist) stringByAppendingPathComponent: | |
210 @"Frameworks/KeystoneRegistration.framework/Resources"]; | |
211 } | |
212 | |
213 NSString* FindOrInstallKeystone(NSString* app_path, NSDictionary* info_plist) { | |
214 NSString* ks_path = kSystemKsadminPath; | |
215 | |
216 // Use user Keystone only if system Keystone doesn't exist / | |
217 // isn't accessible. | |
218 if (geteuid() != 0 && | |
219 ![[NSFileManager defaultManager] isExecutableFileAtPath:ks_path]) { | |
220 ks_path = [kUserKsadminPath stringByExpandingTildeInPath]; | |
221 } | |
222 | |
223 // Always run install.py. It won't overwrite an existing keystone, but | |
224 // it might update it or repair a broken existing installation. | |
225 NSString* ks_resources = PathToKeystoneResources(app_path, info_plist); | |
226 NSString* ks_install = | |
227 [ks_resources stringByAppendingPathComponent:@"install.py"]; | |
228 NSString* ks_tbz = | |
229 [ks_resources stringByAppendingPathComponent:@"Keystone.tbz"]; | |
230 @try { | |
231 NSTask* task = [[[NSTask alloc] init] autorelease]; | |
232 [task setLaunchPath:ks_install]; | |
233 [task setArguments:@[@"--install", ks_tbz]]; | |
234 [task launch]; | |
235 [task waitUntilExit]; | |
236 if ([task terminationStatus] == 0) | |
237 return ks_path; | |
238 } | |
239 @catch (id exception) { | |
240 // Ignore. | |
241 } | |
242 return nil; | |
243 } | |
244 | |
245 bool isbrandchar(int c) { | 208 bool isbrandchar(int c) { |
246 // Always four upper-case alpha chars. | 209 // Always four upper-case alpha chars. |
247 return c >= 'A' && c <= 'Z'; | 210 return c >= 'A' && c <= 'Z'; |
248 } | 211 } |
249 | 212 |
250 } // namespace | 213 } // namespace |
251 | 214 |
252 int GoogleChromeCompatibilityCheck(unsigned* reasons) { | 215 int GoogleChromeCompatibilityCheck(unsigned* reasons) { |
253 unsigned local_reasons = 0; | 216 unsigned local_reasons = 0; |
254 | 217 |
255 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; | 218 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; |
256 | 219 |
257 if (!IsOSXLeopardOrLater()) | 220 if (!IsOSXVersionSupported()) |
258 local_reasons |= GCCC_ERROR_OSNOTSUPPORTED; | 221 local_reasons |= GCCC_ERROR_OSNOTSUPPORTED; |
259 | 222 |
260 if (HasChromeTicket(kSystemTicket)) | 223 if (HasChromeTicket(kSystemTicket)) |
261 local_reasons |= GCCC_ERROR_SYSTEMLEVELALREADYPRESENT; | 224 local_reasons |= GCCC_ERROR_SYSTEMLEVELALREADYPRESENT; |
262 | 225 |
263 if (geteuid() != 0 && HasChromeTicket(kUserTicket)) | 226 if (geteuid() != 0 && HasChromeTicket(kUserTicket)) |
264 local_reasons |= GCCC_ERROR_USERLEVELALREADYPRESENT; | 227 local_reasons |= GCCC_ERROR_USERLEVELALREADYPRESENT; |
265 | 228 |
266 if (![[NSFileManager defaultManager] isWritableFileAtPath:@"/Applications"]) | 229 if (![[NSFileManager defaultManager] isWritableFileAtPath:@"/Applications"]) |
267 local_reasons |= GCCC_ERROR_ACCESSDENIED; | 230 local_reasons |= GCCC_ERROR_ACCESSDENIED; |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
321 isbrandchar(brand_code[2]) && isbrandchar(brand_code[3]); | 284 isbrandchar(brand_code[2]) && isbrandchar(brand_code[3]); |
322 | 285 |
323 NSString* brand_path = nil; | 286 NSString* brand_path = nil; |
324 if (valid_brand_code) | 287 if (valid_brand_code) |
325 brand_path = WriteBrandCode(brand_code); | 288 brand_path = WriteBrandCode(brand_code); |
326 | 289 |
327 // Write master prefs. | 290 // Write master prefs. |
328 if (master_prefs_contents) | 291 if (master_prefs_contents) |
329 WriteMasterPrefs(master_prefs_contents, master_prefs_contents_size); | 292 WriteMasterPrefs(master_prefs_contents, master_prefs_contents_size); |
330 | 293 |
331 // Install Keystone if necessary. | |
332 if (NSString* keystone = FindOrInstallKeystone(app_path, info_plist)) { | |
333 // Register Chrome with Keystone. | |
334 @try { | |
335 NSTask* task = [[[NSTask alloc] init] autorelease]; | |
336 [task setLaunchPath:keystone]; | |
337 NSString* tag = [info_plist objectForKey:kChannelKey]; | |
338 [task setArguments:@[ | |
339 @"--register", | |
340 @"--productid", [info_plist objectForKey:@"KSProductID"], | |
341 @"--version", [info_plist objectForKey:kVersionKey], | |
342 @"--xcpath", kChromeInstallPath, | |
343 @"--url", [info_plist objectForKey:@"KSUpdateURL"], | |
344 | |
345 @"--tag", tag ? tag : @"", // Stable channel | |
346 @"--tag-path", info_plist_path, | |
347 @"--tag-key", kChannelKey, | |
348 | |
349 @"--brand-path", brand_path ? brand_path : @"", | |
350 @"--brand-key", brand_path ? kBrandKey: @"", | |
351 | |
352 @"--version-path", info_plist_path, | |
353 @"--version-key", kVersionKey, | |
354 ]]; | |
355 [task launch]; | |
356 [task waitUntilExit]; | |
357 } | |
358 @catch (id exception) { | |
359 // Chrome will try to register keystone on launch. | |
360 } | |
361 } | |
362 | |
363 // TODO Set default browser if requested. Will be tricky when running as | 294 // TODO Set default browser if requested. Will be tricky when running as |
364 // root. | 295 // root. |
365 } | 296 } |
366 return 1; | 297 return 1; |
367 } | 298 } |
368 | 299 |
369 int LaunchGoogleChrome() { | 300 int LaunchGoogleChrome() { |
370 @autoreleasepool { | 301 @autoreleasepool { |
371 return [[NSWorkspace sharedWorkspace] launchApplication:kChromeInstallPath]; | 302 return [[NSWorkspace sharedWorkspace] launchApplication:kChromeInstallPath]; |
372 } | 303 } |
373 } | 304 } |
OLD | NEW |