diff options
author | thakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-17 23:48:56 +0000 |
---|---|---|
committer | thakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-17 23:48:56 +0000 |
commit | 0db4cb1262c482ffa303eba8f38532602b755099 (patch) | |
tree | f26182b151c2a280ba27d956533a7e36bf6600b9 /chrome | |
parent | 795a597b1171b9f91d2cdc3bb1455e428592013a (diff) | |
download | chromium_src-0db4cb1262c482ffa303eba8f38532602b755099.zip chromium_src-0db4cb1262c482ffa303eba8f38532602b755099.tar.gz chromium_src-0db4cb1262c482ffa303eba8f38532602b755099.tar.bz2 |
mac: Start implementing gcapi.
For now, this includes checks if chrome is installed and if the OS X version
is recent enough for chrome.
BUG=128462
TEST=none
Review URL: https://chromiumcodereview.appspot.com/10388132
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@137774 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/chrome_installer.gypi | 127 | ||||
-rw-r--r-- | chrome/installer/gcapi/gcapi.h | 33 | ||||
-rw-r--r-- | chrome/installer/gcapi_mac/gcapi.h | 38 | ||||
-rw-r--r-- | chrome/installer/gcapi_mac/gcapi.mm | 124 | ||||
-rw-r--r-- | chrome/installer/gcapi_mac/gcapi_example_client.mm | 13 |
5 files changed, 275 insertions, 60 deletions
diff --git a/chrome/chrome_installer.gypi b/chrome/chrome_installer.gypi index b178e67..54aa94a 100644 --- a/chrome/chrome_installer.gypi +++ b/chrome/chrome_installer.gypi @@ -4,7 +4,7 @@ { 'variables': { - 'lastchange_path': '<(DEPTH)/build/util/LASTCHANGE', + 'lastchange_path': '../build/util/LASTCHANGE', # 'branding_dir' is set in the 'conditions' section at the bottom. }, 'conditions': [ @@ -15,11 +15,11 @@ 'type': 'loadable_module', 'dependencies': [ 'installer_util', - '<(DEPTH)/base/base.gyp:base', - '<(DEPTH)/google_update/google_update.gyp:google_update', + '../base/base.gyp:base', + '../google_update/google_update.gyp:google_update', ], 'include_dirs': [ - '<(DEPTH)', + '..', ], 'sources': [ 'installer/gcapi/gcapi.cc', @@ -36,11 +36,11 @@ 'type': 'static_library', 'dependencies': [ 'installer_util', - '<(DEPTH)/base/base.gyp:base', - '<(DEPTH)/google_update/google_update.gyp:google_update', + '../base/base.gyp:base', + '../google_update/google_update.gyp:google_update', ], 'include_dirs': [ - '<(DEPTH)', + '..', ], 'sources': [ 'installer/gcapi/gcapi.cc', @@ -59,12 +59,12 @@ 'gcapi_dll', 'gcapi_lib', 'installer_util', - '<(DEPTH)/base/base.gyp:base', - '<(DEPTH)/base/base.gyp:test_support_base', - '<(DEPTH)/testing/gtest.gyp:gtest', + '../base/base.gyp:base', + '../base/base.gyp:test_support_base', + '../testing/gtest.gyp:gtest', ], 'include_dirs': [ - '<(DEPTH)', + '..', ], 'sources': [ 'installer/gcapi/gcapi_last_run_test.cc', @@ -80,16 +80,16 @@ 'dependencies': [ 'installer_util', 'installer_util_strings', - '<(DEPTH)/base/base.gyp:base', - '<(DEPTH)/base/base.gyp:base_i18n', - '<(DEPTH)/base/base.gyp:test_support_base', - '<(DEPTH)/build/temp_gyp/googleurl.gyp:googleurl', - '<(DEPTH)/content/content.gyp:content_common', - '<(DEPTH)/testing/gmock.gyp:gmock', - '<(DEPTH)/testing/gtest.gyp:gtest', + '../base/base.gyp:base', + '../base/base.gyp:base_i18n', + '../base/base.gyp:test_support_base', + '../build/temp_gyp/googleurl.gyp:googleurl', + '../content/content.gyp:content_common', + '../testing/gmock.gyp:gmock', + '../testing/gtest.gyp:gtest', ], 'include_dirs': [ - '<(DEPTH)', + '..', ], 'sources': [ 'installer/setup/compat_checks_unittest.cc', @@ -183,14 +183,14 @@ 'dependencies': [ 'installer_util', 'installer_util_strings', - '<(DEPTH)/base/base.gyp:base', - '<(DEPTH)/base/base.gyp:base_i18n', - '<(DEPTH)/base/base.gyp:test_support_base', - '<(DEPTH)/chrome/chrome.gyp:test_support_common', - '<(DEPTH)/testing/gtest.gyp:gtest', + '../base/base.gyp:base', + '../base/base.gyp:base_i18n', + '../base/base.gyp:test_support_base', + '../chrome/chrome.gyp:test_support_common', + '../testing/gtest.gyp:gtest', ], 'include_dirs': [ - '<(DEPTH)', + '..', ], 'sources': [ '<(SHARED_INTERMEDIATE_DIR)/installer_util_strings/installer_util_strings.rc', @@ -219,18 +219,18 @@ 'dependencies': [ 'installer_util', 'installer_util_strings', - '<(DEPTH)/base/base.gyp:base', - '<(DEPTH)/build/temp_gyp/googleurl.gyp:googleurl', - '<(DEPTH)/build/util/build_util.gyp:lastchange#target', - '<(DEPTH)/build/util/support/support.gyp:*', - '<(DEPTH)/chrome_frame/chrome_frame.gyp:chrome_tab_idl', - '<(DEPTH)/chrome_frame/chrome_frame.gyp:npchrome_frame', - '<(DEPTH)/breakpad/breakpad.gyp:breakpad_handler', - '<(DEPTH)/rlz/rlz.gyp:rlz_lib', - '<(DEPTH)/third_party/zlib/zlib.gyp:zlib', + '../base/base.gyp:base', + '../build/temp_gyp/googleurl.gyp:googleurl', + '../build/util/build_util.gyp:lastchange#target', + '../build/util/support/support.gyp:*', + '../chrome_frame/chrome_frame.gyp:chrome_tab_idl', + '../chrome_frame/chrome_frame.gyp:npchrome_frame', + '../breakpad/breakpad.gyp:breakpad_handler', + '../rlz/rlz.gyp:rlz_lib', + '../third_party/zlib/zlib.gyp:zlib', ], 'include_dirs': [ - '<(DEPTH)', + '..', '<(INTERMEDIATE_DIR)', '<(SHARED_INTERMEDIATE_DIR)/setup', ], @@ -274,7 +274,7 @@ 'rule_name': 'setup_version', 'extension': 'version', 'variables': { - 'version_py_path': '<(DEPTH)/chrome/tools/build/version.py', + 'version_py_path': '../chrome/tools/build/version.py', 'template_input_path': 'installer/setup/setup_exe_version.rc.version', }, 'inputs': [ @@ -355,16 +355,16 @@ 'dependencies': [ 'installer_util', 'installer_util_strings', - '<(DEPTH)/base/base.gyp:base', - '<(DEPTH)/base/base.gyp:base_i18n', - '<(DEPTH)/base/base.gyp:test_support_base', - '<(DEPTH)/build/temp_gyp/googleurl.gyp:googleurl', - '<(DEPTH)/chrome_frame/chrome_frame.gyp:chrome_tab_idl', - '<(DEPTH)/testing/gmock.gyp:gmock', - '<(DEPTH)/testing/gtest.gyp:gtest', + '../base/base.gyp:base', + '../base/base.gyp:base_i18n', + '../base/base.gyp:test_support_base', + '../build/temp_gyp/googleurl.gyp:googleurl', + '../chrome_frame/chrome_frame.gyp:chrome_tab_idl', + '../testing/gmock.gyp:gmock', + '../testing/gtest.gyp:gtest', ], 'include_dirs': [ - '<(DEPTH)', + '..', '<(INTERMEDIATE_DIR)', ], # TODO(robertshield): Move the items marked with "Move to lib" @@ -431,8 +431,8 @@ 'variables': { # Always google_chrome since this only applies to branding==Chrome. 'branding_dir': 'app/theme/google_chrome', - 'version' : '<!(python <(version_py_path) -f <(DEPTH)/chrome/VERSION -t "@MAJOR@.@MINOR@.@BUILD@.@PATCH@")', - 'revision' : '<!(python <(DEPTH)/build/util/lastchange.py --revision-only)', + 'version' : '<!(python <(version_py_path) -f ../chrome/VERSION -t "@MAJOR@.@MINOR@.@BUILD@.@PATCH@")', + 'revision' : '<!(python ../build/util/lastchange.py --revision-only)', 'packaging_files_common': [ 'installer/linux/internal/common/apt.include', 'installer/linux/internal/common/default-app.template', @@ -984,6 +984,41 @@ 'installer/mac/keychain_reauthorize_main.cc', ], }, # target: keychain_reauthorize + { + 'target_name': 'gcapi_lib', + 'type': 'static_library', + 'include_dirs': [ + '..', + ], + 'sources': [ + 'installer/gcapi_mac/gcapi.h', + 'installer/gcapi_mac/gcapi.mm', + ], + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/Cocoa.framework', + ], + }, + 'xcode_settings': { + # TODO(thakis): Enable once http://crbug.com/90185 is done. + # 'ARCHS': [ 'i386', 'x86_64' ], + 'MACOSX_DEPLOYMENT_TARGET': '10.4', + 'GCC_ENABLE_OBJC_GC': 'supported', + }, + }, + { + 'target_name': 'gcapi_example', + 'type': 'executable', + 'dependencies': [ + 'gcapi_lib', + ], + 'include_dirs': [ + '..', + ], + 'sources': [ + 'installer/gcapi_mac/gcapi_example_client.mm', + ], + }, ], # targets }], # OS=="mac" [ 'branding == "Chrome"', { diff --git a/chrome/installer/gcapi/gcapi.h b/chrome/installer/gcapi/gcapi.h index 5d950fa..bca1c66 100644 --- a/chrome/installer/gcapi/gcapi.h +++ b/chrome/installer/gcapi/gcapi.h @@ -8,25 +8,28 @@ #include <windows.h> -extern "C" { // Error conditions for GoogleChromeCompatibilityCheck(). -#define GCCC_ERROR_USERLEVELALREADYPRESENT 0x01 -#define GCCC_ERROR_SYSTEMLEVELALREADYPRESENT 0x02 -#define GCCC_ERROR_ACCESSDENIED 0x04 -#define GCCC_ERROR_OSNOTSUPPORTED 0x08 -#define GCCC_ERROR_ALREADYOFFERED 0x10 -#define GCCC_ERROR_INTEGRITYLEVEL 0x20 +#define GCCC_ERROR_USERLEVELALREADYPRESENT (1 << 0) +#define GCCC_ERROR_SYSTEMLEVELALREADYPRESENT (1 << 1) +#define GCCC_ERROR_ACCESSDENIED (1 << 2) +#define GCCC_ERROR_OSNOTSUPPORTED (1 << 3) +#define GCCC_ERROR_ALREADYOFFERED (1 << 4) +#define GCCC_ERROR_INTEGRITYLEVEL (1 << 5) // Error conditions for CanReactivateChrome(). -#define REACTIVATE_ERROR_NOTINSTALLED 0x01 -#define REACTIVATE_ERROR_NOTDORMANT 0x02 -#define REACTIVATE_ERROR_ALREADY_REACTIVATED 0x04 -#define REACTIVATE_ERROR_INVALID_INPUT 0x08 -#define REACTIVATE_ERROR_REACTIVATION_FAILED 0x10 +#define REACTIVATE_ERROR_NOTINSTALLED (1 << 0) +#define REACTIVATE_ERROR_NOTDORMANT (1 << 1) +#define REACTIVATE_ERROR_ALREADY_REACTIVATED (1 << 2) +#define REACTIVATE_ERROR_INVALID_INPUT (1 << 3) +#define REACTIVATE_ERROR_REACTIVATION_FAILED (1 << 4) // Flags to indicate how GCAPI is invoked -#define GCAPI_INVOKED_STANDARD_SHELL 0x01 -#define GCAPI_INVOKED_UAC_ELEVATION 0x02 +#define GCAPI_INVOKED_STANDARD_SHELL (1 << 0) +#define GCAPI_INVOKED_UAC_ELEVATION (1 << 1) + +#ifdef __cplusplus +extern "C" { +#endif // The minimum number of days an installation can be dormant before reactivation // may be offered. @@ -107,6 +110,8 @@ typedef BOOL (__stdcall *GCCC_ReactivateChrome)(const wchar_t*, int, DWORD*); +#ifdef __cplusplus } // extern "C" +#endif #endif // CHROME_INSTALLER_GCAPI_GCAPI_H_ diff --git a/chrome/installer/gcapi_mac/gcapi.h b/chrome/installer/gcapi_mac/gcapi.h new file mode 100644 index 0000000..3a84a1f --- /dev/null +++ b/chrome/installer/gcapi_mac/gcapi.h @@ -0,0 +1,38 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_INSTALLER_GCAPI_MAC_GCAPI_H_ +#define CHROME_INSTALLER_GCAPI_MAC_GCAPI_H_ +#pragma once + +// Error conditions for GoogleChromeCompatibilityCheck(). +#define GCCC_ERROR_USERLEVELALREADYPRESENT (1 << 0) +#define GCCC_ERROR_SYSTEMLEVELALREADYPRESENT (1 << 1) +#define GCCC_ERROR_ACCESSDENIED (1 << 2) +#define GCCC_ERROR_OSNOTSUPPORTED (1 << 3) +#define GCCC_ERROR_ALREADYOFFERED (1 << 4) +#define GCCC_ERROR_INTEGRITYLEVEL (1 << 5) + +#ifdef __cplusplus +extern "C" { +#endif + +// This function returns YES if Google Chrome should be offered. +// If the return is NO, |reasons| explains why. If you don't care for the +// reason, you can pass NULL for |reasons|. +// |set_flag| indicates whether a flag should be set indicating that Chrome was +// offered within the last six months; if passed NO, this method will not +// set the flag even if Chrome can be offered. If passed TRUE, this method +// will set the flag only if Chrome can be offered. +// |shell_mode| should be set to one of GCAPI_INVOKED_STANDARD_SHELL or +// GCAPI_INVOKED_UAC_ELEVATION depending on whether this method is invoked +// from an elevated or non-elevated process. TODO(thakis): This doesn't make +// sense on mac, change comment. +int GoogleChromeCompatibilityCheck(unsigned* reasons); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // CHROME_INSTALLER_GCAPI_MAC_GCAPI_H_ diff --git a/chrome/installer/gcapi_mac/gcapi.mm b/chrome/installer/gcapi_mac/gcapi.mm new file mode 100644 index 0000000..2530e8d --- /dev/null +++ b/chrome/installer/gcapi_mac/gcapi.mm @@ -0,0 +1,124 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/installer/gcapi_mac/gcapi.h" + +#import <Cocoa/Cocoa.h> +#include <sys/utsname.h> + +namespace { + +// Condensed from chromium's base/mac/mac_util.mm. +bool IsOSXLeopardOrLater() { + // On 10.6, Gestalt() was observed to be able to spawn threads (see + // http://crbug.com/53200). Don't call Gestalt(). + struct utsname uname_info; + if (uname(&uname_info) != 0) + return false; + if (strcmp(uname_info.sysname, "Darwin") != 0) + return false; + + char* dot = strchr(uname_info.release, '.'); + if (!dot) + return false; + + int darwin_major_version = atoi(uname_info.release); + if (darwin_major_version < 6) + return false; + + // The Darwin major version is always 4 greater than the Mac OS X minor + // version for Darwin versions beginning with 6, corresponding to Mac OS X + // 10.2. + int mac_os_x_minor_version = darwin_major_version - 4; + + return mac_os_x_minor_version >= 5; +} + +NSString* const kSystemKsadminPath = + @"/Library/Google/GoogleSoftwareUpdate/GoogleSoftwareUpdate.bundle/" + "Contents/MacOS/ksadmin"; + +NSString* const kUserKsadminPath = + @"~/Library/Google/GoogleSoftwareUpdate/GoogleSoftwareUpdate.bundle/" + "Contents/MacOS/ksadmin"; + +enum TicketKind { + kSystemTicket, kUserTicket +}; + +BOOL HasChromeTicket(TicketKind kind) { + // Don't use Objective-C 2 loop syntax, in case an installer runs on 10.4. + NSMutableArray* keystonePaths = + [NSMutableArray arrayWithObject:kUserKsadminPath]; + if (kind == kSystemTicket) + [keystonePaths insertObject:kSystemKsadminPath atIndex:0]; + NSEnumerator* e = [keystonePaths objectEnumerator]; + id ksPath; + while ((ksPath = [e nextObject])) { + NSTask* task = nil; + NSString* string = nil; + bool ksadminRanSuccessfully = false; + + @try { + task = [[NSTask alloc] init]; + [task setLaunchPath:ksPath]; + + NSArray* arguments = @[ + kind == kUserTicket ? @"--user-store" : @"--system-store", + @"--print-tickets", + @"--productid", + @"com.google.Chrome", + ]; + [task setArguments:arguments]; + + NSPipe* pipe = [NSPipe pipe]; + [task setStandardOutput:pipe]; + + NSFileHandle* file = [pipe fileHandleForReading]; + + [task launch]; + + NSData* data = [file readDataToEndOfFile]; + [task waitUntilExit]; + + ksadminRanSuccessfully = [task terminationStatus] == 0; + string = [[[NSString alloc] initWithData:data + encoding:NSUTF8StringEncoding] autorelease]; + } + @catch (id exception) { + // Most likely, ksPath didn't exist. + } + [task release]; + + if (ksadminRanSuccessfully && [string length] > 0) + return YES; + } + + return NO; +} + +} // namespace + +int GoogleChromeCompatibilityCheck(unsigned* reasons) { + unsigned local_reasons = 0; + + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + + if (!IsOSXLeopardOrLater()) + local_reasons |= GCCC_ERROR_OSNOTSUPPORTED; + + if (HasChromeTicket(kSystemTicket)) + local_reasons |= GCCC_ERROR_SYSTEMLEVELALREADYPRESENT; + + if (HasChromeTicket(kUserTicket)) + local_reasons |= GCCC_ERROR_USERLEVELALREADYPRESENT; + + [pool drain]; + + // Done. Copy/return results. + if (reasons != NULL) + *reasons = local_reasons; + + return local_reasons == 0; +} diff --git a/chrome/installer/gcapi_mac/gcapi_example_client.mm b/chrome/installer/gcapi_mac/gcapi_example_client.mm new file mode 100644 index 0000000..902fff3 --- /dev/null +++ b/chrome/installer/gcapi_mac/gcapi_example_client.mm @@ -0,0 +1,13 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/installer/gcapi_mac/gcapi.h" + +#import <Foundation/Foundation.h> + +int main() { + unsigned reasons; + int b = GoogleChromeCompatibilityCheck(&reasons); + NSLog(@"%d: %x", b, reasons); +} |