diff options
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/app/keystone_glue.mm (renamed from chrome/app/keystone_glue.m) | 21 | ||||
-rwxr-xr-x | chrome/app/make_mac_app_symlinks | 17 | ||||
-rwxr-xr-x | chrome/chrome.gyp | 167 | ||||
-rw-r--r-- | chrome/common/child_process_host.cc | 59 | ||||
-rw-r--r-- | chrome/common/chrome_constants.cc | 1 | ||||
-rw-r--r-- | chrome/common/chrome_paths_internal.h | 11 | ||||
-rw-r--r-- | chrome/common/chrome_paths_mac.mm | 50 | ||||
-rw-r--r-- | chrome/tools/build/mac/app_resource_rules.plist.in | 55 | ||||
-rwxr-xr-x | chrome/tools/build/mac/clean_up_old_versions | 45 | ||||
-rwxr-xr-x | chrome/tools/build/mac/keystone_install.sh | 57 | ||||
-rwxr-xr-x | chrome/tools/build/mac/keystone_install_test.sh | 64 | ||||
-rwxr-xr-x | chrome/tools/build/mac/make_sign_sh | 30 | ||||
-rwxr-xr-x | chrome/tools/build/mac/remove_headers_from_framework | 31 | ||||
-rw-r--r-- | chrome/tools/build/mac/sign.sh.in | 10 |
14 files changed, 453 insertions, 165 deletions
diff --git a/chrome/app/keystone_glue.m b/chrome/app/keystone_glue.mm index 86f48ce..736972c 100644 --- a/chrome/app/keystone_glue.m +++ b/chrome/app/keystone_glue.mm @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "keystone_glue.h" +#include "base/mac_util.h" +#import "chrome/app/keystone_glue.h" @interface KeystoneGlue(Private) @@ -52,8 +53,7 @@ NSString *KSRegistrationRemoveExistingTag = @""; @implementation KeystoneGlue + (id)defaultKeystoneGlue { - // TODO(jrg): rename this file to .mm so I can use C++ and - // make this type a base::SingletonObjC<KeystoneGlue>. + // TODO(jrg): use base::SingletonObjC<KeystoneGlue> static KeystoneGlue* sDefaultKeystoneGlue = nil; // leaked if (sDefaultKeystoneGlue == nil) { @@ -78,7 +78,8 @@ NSString *KSRegistrationRemoveExistingTag = @""; } - (NSDictionary*)infoDictionary { - return [[NSBundle mainBundle] infoDictionary]; + // Use mac_util::MainAppBundle() to get the app framework's dictionary. + return [mac_util::MainAppBundle() infoDictionary]; } - (void)loadParameters { @@ -86,6 +87,8 @@ NSString *KSRegistrationRemoveExistingTag = @""; NSString* url = [infoDictionary objectForKey:@"KSUpdateURL"]; NSString* product = [infoDictionary objectForKey:@"KSProductID"]; if (product == nil) { + // Use [NSBundle mainBundle] to fall back to the app's own bundle + // identifier, not the app framework's. product = [[NSBundle mainBundle] bundleIdentifier]; } NSString* version = [infoDictionary objectForKey:@"KSVersion"]; @@ -110,10 +113,10 @@ NSString *KSRegistrationRemoveExistingTag = @""; if (!productID_ || !url_ || !version_) return NO; - // Load the KeystoneRegistration framework bundle. - NSBundle* mainBundle = [NSBundle mainBundle]; + // Load the KeystoneRegistration framework bundle if present. It lives + // inside the framework, so use mac_util::MainAppBundle(); NSString* ksrPath = - [[mainBundle privateFrameworksPath] + [[mac_util::MainAppBundle() privateFrameworksPath] stringByAppendingPathComponent:@"KeystoneRegistration.framework"]; NSBundle* ksrBundle = [NSBundle bundleWithPath:ksrPath]; [ksrBundle load]; @@ -129,6 +132,10 @@ NSString *KSRegistrationRemoveExistingTag = @""; } - (void)registerWithKeystone { + // The existence checks should use the path to the app bundle, not the + // app framework bundle, so use [NSBundle mainBundle] instead of + // mac_util::MainBundle(). + // // Only use new API if we can. This lets us land the new call // before the new Keystone has been released. // diff --git a/chrome/app/make_mac_app_symlinks b/chrome/app/make_mac_app_symlinks deleted file mode 100755 index 66353a95..0000000 --- a/chrome/app/make_mac_app_symlinks +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/sh - -# Copyright (c) 2009 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. - -# This script is intended to run from a "postbuild" action from within Xcode. -# It sets up symbolic links for an app bundle's Frameworks directory. This is -# intended to be used for app bundles that live within the Resources directory -# of a larger app bundle, when the sub-app's Frameworks directory should point -# to the enclosing app's. - -set -e - -CONTENTS_PATH="${BUILT_PRODUCTS_DIR}/${WRAPPER_NAME}/Contents" - -ln -fhs ../../../Frameworks "${CONTENTS_PATH}/Frameworks" diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 65c01f5..b36b2dc 100755 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -12,8 +12,8 @@ }, 'version_py_path': '<(version_py_path)', 'version_path': '<(version_path)', - 'version_major_minor': - '<!(python <(version_py_path) -f <(version_path) -t "@MAJOR@.@MINOR@")', + 'version_full': + '<!(python <(version_py_path) -f <(version_path) -t "@MAJOR@.@MINOR@.@BUILD@.@PATCH@")', 'version_build_patch': '<!(python <(version_py_path) -f <(version_path) -t "@BUILD@.@PATCH@")', @@ -3469,18 +3469,24 @@ 'variables': { 'make_sign_sh_path': 'tools/build/mac/make_sign_sh', 'sign_sh_in_path': 'tools/build/mac/make_sign_sh', + 'app_resource_rules_in_path': + 'tools/build/mac/app_resource_rules.plist.in', }, 'inputs': [ '<(make_sign_sh_path)', '<(sign_sh_in_path)', + '<(app_resource_rules_in_path)', + '<(version_path)', ], 'outputs': [ '<(mac_packaging_dir)/sign.sh', + '<(mac_packaging_dir)/app_resource_rules.plist', ], 'action': [ '<(make_sign_sh_path)', '<(mac_packaging_sh_dir)', '<(mac_product_name)', + '<(version_full)', ], }, ], @@ -3498,9 +3504,6 @@ 'CHROMIUM_CREATOR': '<(mac_creator)', 'CHROMIUM_SHORT_NAME': '<(branding)', }, - 'mac_bundle_resources': [ - '<(PRODUCT_DIR)/<(mac_product_name) Helper.app', - ], 'dependencies': [ 'helper_app', 'infoplist_strings_tool', @@ -3553,21 +3556,25 @@ ], 'copies': [ { - 'destination': '<(PRODUCT_DIR)/<(mac_product_name).app/Contents/Frameworks', - 'files': ['<(PRODUCT_DIR)/<(mac_product_name) Framework.framework'], + 'destination': '<(PRODUCT_DIR)/<(mac_product_name).app/Contents/Versions/<(version_full)', + 'files': [ + '<(PRODUCT_DIR)/<(mac_product_name) Framework.framework', + '<(PRODUCT_DIR)/<(mac_product_name) Helper.app', + ], }, ], 'postbuilds': [ { # Modify the Info.plist as needed. The script explains why this # is needed. This is also done in the helper_app and chrome_dll - # targets. Use -b0 to not include any Breakpad information; - # that all goes into the framework's Info.plist. + # targets. Use -b0 and -k0 to not include any Breakpad or + # Keystone information; that all goes into the framework's + # Info.plist. Use -s1 to include Subversion information. 'postbuild_name': 'Tweak Info.plist', 'action': ['<(DEPTH)/build/mac/tweak_app_infoplist', '-b0', - '-k<(mac_keystone)', - '-s1', # Include Subversion information + '-k0', + '-s1', '<(branding)'], }, { @@ -3579,6 +3586,13 @@ 'postbuild_name': 'Clean up old resources', 'action': ['app/clean_mac_resources'], }, + { + 'postbuild_name': 'Clean up old versions', + 'action': [ + 'tools/build/mac/clean_up_old_versions', + '<(version_full)' + ], + }, ], # postbuilds }, { # else: OS != "mac" 'conditions': [ @@ -4083,7 +4097,7 @@ ['OS=="mac"', { 'sources': [ 'app/keystone_glue.h', - 'app/keystone_glue.m', + 'app/keystone_glue.mm', 'app/breakpad_mac_stubs.mm', ], 'sources!': [ @@ -4250,8 +4264,8 @@ 'app/breakpad_mac_stubs.mm', # *NO* files in chrome/app have unit tests (except keystone_glue)!!! # It seems a waste to have an app_unittests target, so for now - # I add keystone_glue.m explicitly to this target. - 'app/keystone_glue.m', + # I add keystone_glue.mm explicitly to this target. + 'app/keystone_glue.mm', 'app/keystone_glue_unittest.mm', # All unittests in browser, common, and renderer. 'browser/app_controller_mac_unittest.mm', @@ -5041,7 +5055,8 @@ # version numbers. 'DYLIB_COMPATIBILITY_VERSION': '<(version_build_patch)', 'DYLIB_CURRENT_VERSION': '<(version_build_patch)', - 'DYLIB_INSTALL_NAME_BASE': '@executable_path/../Frameworks', + 'DYLIB_INSTALL_NAME_BASE': + '@executable_path/../Versions/<(version_full)', # FRAMEWORK_VERSION is used as the name of the directory in # the framework's Versions directory that the Current symbolic # link points to. Unfortunately, Xcode does not create this @@ -5052,8 +5067,7 @@ # its default, 'A'. This is more than sufficient for our # purposes, because the framework does not need to maintain # any sort of stable public interface. - # 'FRAMEWORK_VERSION': - # '<(version_major_minor).<(version_build_patch)', + # 'FRAMEWORK_VERSION': '<(version_full)', 'CHROMIUM_BUNDLE_ID': '<(mac_bundle_id)', 'INFOPLIST_FILE': 'app/framework-Info.plist', }, @@ -5062,7 +5076,7 @@ 'app/chrome_dll_resource.h', 'app/chrome_exe_main.mm', 'app/keystone_glue.h', - 'app/keystone_glue.m', + 'app/keystone_glue.mm', ], # TODO(mark): Come up with a fancier way to do this. It should # only be necessary to list framework-Info.plist once, not the @@ -5227,13 +5241,15 @@ { # Modify the Info.plist as needed. The script explains why # this is needed. This is also done in the chrome target. - # The framework does not need the Keystone or Subversion - # keys, but it does need the Breakpad keys. + # The framework needs the Breakpad and Keystone keys if + # those features are enabled. It doesn't currently use the + # Subversion keys for anything, but this seems like a really + # good place to store them. 'postbuild_name': 'Tweak Info.plist', 'action': ['<(DEPTH)/build/mac/tweak_app_infoplist', '-b<(mac_breakpad)', - '-k0', - '-s0', + '-k<(mac_keystone)', + '-s1', '<(branding)'], }, { @@ -5242,10 +5258,12 @@ }, { 'postbuild_name': 'Symlink Libraries', - 'action': ['ln', - '-fhs', - 'Versions/Current/Libraries', - '${BUILT_PRODUCTS_DIR}/${WRAPPER_NAME}/Libraries'], + 'action': [ + 'ln', + '-fhs', + 'Versions/Current/Libraries', + '${BUILT_PRODUCTS_DIR}/${WRAPPER_NAME}/Libraries' + ], }, ], 'copies': [ @@ -5284,6 +5302,35 @@ 'app/breakpad_mac.h', ], }], # mac_breakpad + ['mac_keystone==1', { + 'copies': [ + { + 'destination': + '<(PRODUCT_DIR)/$(CONTENTS_FOLDER_PATH)/Frameworks', + 'files': [ + '../third_party/googlemac/Releases/Keystone/KeystoneRegistration.framework' + ], + }, + ], + 'postbuilds': [ + { + 'postbuild_name': 'Remove Keystone Headers', + 'action': [ + 'tools/build/mac/remove_headers_from_framework', + '${BUILT_PRODUCTS_DIR}/${WRAPPER_NAME}/Frameworks/KeystoneRegistration.framework', + ], + }, + { + 'postbuild_name': 'Symlink Frameworks', + 'action': [ + 'ln', + '-fhs', + 'Versions/Current/Frameworks', + '${BUILT_PRODUCTS_DIR}/${WRAPPER_NAME}/Frameworks' + ], + }, + ], + }], # mac_keystone ['branding=="Chrome"', { 'copies': [ { @@ -5410,17 +5457,26 @@ ], 'postbuilds': [ { - 'postbuild_name': 'Make Symbolic Links', - 'action': ['app/make_mac_app_symlinks'], + # The framework (chrome_dll) defines its load-time path + # (DYLIB_INSTALL_NAME_BASE) relative to the main executable + # (chrome). A different relative path needs to be used in + # helper_app. + 'postbuild_name': 'Fix Framework Link', + 'action': [ + 'install_name_tool', + '-change', + '@executable_path/../Versions/<(version_full)/<(mac_product_name) Framework.framework/Versions/A/<(mac_product_name) Framework', + '@executable_path/../../../<(mac_product_name) Framework.framework/Versions/A/<(mac_product_name) Framework', + '${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}' + ], }, { # Modify the Info.plist as needed. The script explains why this # is needed. This is also done in the chrome and chrome_dll - # targets. In this case, -b0 is used because Breakpad data is - # not placed into the helper, it is only placed in the framework. - # -k0 is used because Keystone never runs within the helper, only - # within the main app. -s0 is used to avoid placing Subversion - # data in the helper's Info.plist. + # targets. In this case, -b0 and -k0 are used because Breakpad + # and Keystone keys are never placed into the helper, only into + # the framework. -s0 is used because Subversion keys are only + # placed into the main app. 'postbuild_name': 'Tweak Info.plist', 'action': ['<(DEPTH)/build/mac/tweak_app_infoplist', '-b0', @@ -5441,7 +5497,7 @@ }, }], ], - }, + }, # target helper_app { # Convenience target to build a disk image. 'target_name': 'build_app_dmg', @@ -5512,8 +5568,26 @@ ], }, 'xcode_settings': { + 'DYLIB_COMPATIBILITY_VERSION': '<(version_build_patch)', + 'DYLIB_CURRENT_VERSION': '<(version_build_patch)', 'DYLIB_INSTALL_NAME_BASE': '@executable_path', }, + 'postbuilds': [ + { + # The framework (chrome_dll) defines its load-time path + # (DYLIB_INSTALL_NAME_BASE) relative to the main executable + # (chrome). A different relative path needs to be used in + # plugin_carbon_interpose, which runs in the helper_app. + 'postbuild_name': 'Fix Framework Link', + 'action': [ + 'install_name_tool', + '-change', + '@executable_path/../Versions/<(version_full)/<(mac_product_name) Framework.framework/Versions/A/<(mac_product_name) Framework', + '@executable_path/../../../<(mac_product_name) Framework.framework/Versions/A/<(mac_product_name) Framework', + '${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}' + ], + }, + ], }, { 'target_name': 'infoplist_strings_tool', @@ -5814,20 +5888,25 @@ 'sources': [ 'app/breakpad_mac_stubs.mm', 'app/keystone_glue.h', - 'app/keystone_glue.m', + 'app/keystone_glue.mm', ], 'sources!': [ '<@(browser_tests_sources_exclude_on_mac)', - ], - # TODO(mark): We really want this for all non-static library targets, - # but when we tried to pull it up to the common.gypi level, it broke - # other things like the ui, startup, and page_cycler tests. *shrug* - 'xcode_settings': {'OTHER_LDFLAGS': ['-Wl,-ObjC']}, + ], + # TODO(mark): We really want this for all non-static library + # targets, but when we tried to pull it up to the common.gypi + # level, it broke other things like the ui, startup, and + # page_cycler tests. *shrug* + 'xcode_settings': { + 'OTHER_LDFLAGS': [ + '-Wl,-ObjC', + ], + }, }], - ], - }, - ], - }], + ], # conditions + }, # target browser_tests + ], # targets + }], # OS!="win" ['OS=="win"', { 'targets': [ { diff --git a/chrome/common/child_process_host.cc b/chrome/common/child_process_host.cc index 6495fba..695ac18 100644 --- a/chrome/common/child_process_host.cc +++ b/chrome/common/child_process_host.cc @@ -15,6 +15,8 @@ #include "base/string_util.h" #include "base/waitable_event.h" #include "chrome/browser/chrome_thread.h" +#include "chrome/common/chrome_constants.h" +#include "chrome/common/chrome_paths_internal.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/notification_service.h" #include "chrome/common/notification_type.h" @@ -83,61 +85,28 @@ ChildProcessHost::~ChildProcessHost() { // static FilePath ChildProcessHost::GetChildPath() { - FilePath child_path = CommandLine::ForCurrentProcess()->GetSwitchValuePath( - switches::kBrowserSubprocessPath); + static FilePath child_path; + if (!child_path.empty()) return child_path; - FilePath path; - PathService::Get(base::FILE_EXE, &path); + child_path = CommandLine::ForCurrentProcess()->GetSwitchValuePath( + switches::kBrowserSubprocessPath); + if (!child_path.empty()) + return child_path; #if !defined(OS_MACOSX) // On most platforms, the child executable is the same as the current // executable. - return path; + PathService::Get(base::FILE_EXE, &child_path); #else // On the Mac, the child executable lives at a predefined location within - // the current app bundle. - - // Figure out the current executable name. In a browser, this will be - // "Chromium" or "Google Chrome". The child name will be the browser - // executable name with " Helper" appended. The child app bundle name will - // be that name with ".app" appended. - FilePath::StringType child_exe_name = path.BaseName().value(); - const FilePath::StringType child_suffix = FILE_PATH_LITERAL(" Helper"); - - if (child_exe_name.size() > child_suffix.size()) { - size_t test_suffix_pos = child_exe_name.size() - child_suffix.size(); - const FilePath::CharType* test_suffix = - child_exe_name.c_str() + test_suffix_pos; - if (strcmp(test_suffix, child_suffix.c_str()) == 0) { - // FILE_EXE already ends with the child suffix and therefore already - // refers to the child process path. Just return it. - return path; - } - } - - child_exe_name.append(child_suffix); - FilePath::StringType child_app_name = child_exe_name; - child_app_name.append(FILE_PATH_LITERAL(".app")); - // The renderer app bundle lives in the browser app bundle's Resources - // directory. Take off the executable name. - path = path.DirName(); - - // Take off the MacOS component, after verifying that's what's there. - FilePath::StringType macos = path.BaseName().value(); - DCHECK_EQ(macos, FILE_PATH_LITERAL("MacOS")); - path = path.DirName(); - - // Append the components to get to the sub-app bundle's executable. - path = path.Append(FILE_PATH_LITERAL("Resources")); - path = path.Append(child_app_name); - path = path.Append(FILE_PATH_LITERAL("Contents")); - path = path.Append(FILE_PATH_LITERAL("MacOS")); - path = path.Append(child_exe_name); - - return path; + // the app bundle's versioned directory. + child_path = chrome::GetVersionedDirectory().Append( + FilePath::FromWStringHack(chrome::kHelperProcessExecutablePath)); #endif // OS_MACOSX + + return child_path; } // static diff --git a/chrome/common/chrome_constants.cc b/chrome/common/chrome_constants.cc index 55ea255..5f8fc9a 100644 --- a/chrome/common/chrome_constants.cc +++ b/chrome/common/chrome_constants.cc @@ -44,7 +44,6 @@ const wchar_t kHelperProcessExecutablePath[] = L"chrome"; const wchar_t kBrowserProcessExecutablePath[] = PRODUCT_STRING_W L".app/Contents/MacOS/" PRODUCT_STRING_W; const wchar_t kHelperProcessExecutablePath[] = - PRODUCT_STRING_W L".app/Contents/Resources/" PRODUCT_STRING_W L" Helper.app/Contents/MacOS/" PRODUCT_STRING_W L" Helper"; #endif // OS_* #if defined(OS_MACOSX) diff --git a/chrome/common/chrome_paths_internal.h b/chrome/common/chrome_paths_internal.h index 38d4dc8..dfaded7 100644 --- a/chrome/common/chrome_paths_internal.h +++ b/chrome/common/chrome_paths_internal.h @@ -38,6 +38,17 @@ bool GetUserDownloadsDirectory(FilePath* result); bool GetUserDesktop(FilePath* result); #if defined(OS_MACOSX) +// The "versioned directory" is a directory in the browser .app bundle. It +// contains the bulk of the application, except for the things that the system +// requires be located at spepcific locations. The versioned directory is +// in the .app at Contents/Versions/w.x.y.z. +FilePath GetVersionedDirectory(); + +// Most of the application is further contained within the framework. The +// framework bundle is located within the versioned directory at a specific +// path. The only components in the versioned directory not included in the +// framework are things that also depend on the framework, such as the helper +// app bundle. FilePath GetFrameworkBundlePath(); #endif // OS_MACOSX diff --git a/chrome/common/chrome_paths_mac.mm b/chrome/common/chrome_paths_mac.mm index 3ddd796..beb22f2 100644 --- a/chrome/common/chrome_paths_mac.mm +++ b/chrome/common/chrome_paths_mac.mm @@ -66,6 +66,40 @@ bool GetUserDesktop(FilePath* result) { return success; } +FilePath GetVersionedDirectory() { + static FilePath path; + + if (path.empty()) { + // Start out with the path to the running .app. + NSBundle* app_bundle = [NSBundle mainBundle]; + path = FilePath([[app_bundle bundlePath] fileSystemRepresentation]); + + if (mac_util::IsBackgroundOnlyProcess()) { + // path identifies the helper .app in the browser .app's versioned + // directory. Go up one level to get to the browser .app's versioned + // directory. + path = path.DirName(); + } else { + // path identifies the browser .app. Go into its versioned directory. + // TODO(mark): Here, |version| comes from the outer .app bundle's + // Info.plist. In the event of an incomplete update, it may be possible + // for this value to be incorrect. Consider the case where the updater + // is able to update one, but not both, of the executable and the + // Info.plist. The executable may load one version of the framework, + // and the Info.plist may refer to another version. Ideally, the + // version would be available in a compile-time constant, or there would + // be a better way to detect the loaded framework version at runtime. + NSString* version = + [app_bundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; + path = path.Append("Contents"). + Append("Versions"). + Append([version fileSystemRepresentation]); + } + } + + return path; +} + FilePath GetFrameworkBundlePath() { // It's tempting to use +[NSBundle bundleWithIdentifier:], but it's really // slow (about 30ms on 10.5 and 10.6), despite Apple's documentation stating @@ -76,21 +110,9 @@ FilePath GetFrameworkBundlePath() { // needed to compute the framework's path are also effectively free, so that // is the approach that is used here. - // Start out with the path to the running .app. - FilePath path([[[NSBundle mainBundle] bundlePath] fileSystemRepresentation]); - - if (mac_util::IsBackgroundOnlyProcess()) { - // path identifies the helper .app in the browser .app's Contents/Resources - // directory. Go up two levels to get to the browser's Contents directory. - path = path.DirName().DirName(); - } else { - // path identifies the browser .app. Go into the Contents directory. - path = path.Append("Contents"); - } - // The framework bundle is at a known path and name from the browser .app's - // Contents directory. - return path.Append("Frameworks").Append(kFrameworkName); + // versioned directory. + return GetVersionedDirectory().Append(kFrameworkName); } } // namespace chrome diff --git a/chrome/tools/build/mac/app_resource_rules.plist.in b/chrome/tools/build/mac/app_resource_rules.plist.in new file mode 100644 index 0000000..d629044 --- /dev/null +++ b/chrome/tools/build/mac/app_resource_rules.plist.in @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>rules</key> + <dict> + <key>^PkgInfo$</key> + <true/> + <key>^MacOS/</key> + <true/> + <key>^Resources/</key> + <true/> + <key>^Versions/</key> + <dict> + <key>omit</key> + <true/> + <key>weight</key> + <real>10</real> + </dict> + <key>^Versions/@VERSION_REGEX@/</key> + <dict> + <key>weight</key> + <real>20</real> + </dict> + <key>^Resources/.+\.lproj/</key> + <dict> + <key>optional</key> + <true/> + <key>weight</key> + <real>30</real> + </dict> + <key>^Versions/@VERSION_REGEX@/.+/Resources/.+\.lproj/</key> + <dict> + <key>optional</key> + <true/> + <key>weight</key> + <real>30</real> + </dict> + <key>^Versions/@VERSION_REGEX@/.+/Resources Disabled/</key> + <dict> + <key>omit</key> + <true/> + <key>weight</key> + <real>40</real> + </dict> + <key>/\.DS_Store$</key> + <dict> + <key>omit</key> + <true/> + <key>weight</key> + <real>50</real> + </dict> + </dict> +</dict> +</plist> diff --git a/chrome/tools/build/mac/clean_up_old_versions b/chrome/tools/build/mac/clean_up_old_versions new file mode 100755 index 0000000..b970a15 --- /dev/null +++ b/chrome/tools/build/mac/clean_up_old_versions @@ -0,0 +1,45 @@ +#!/bin/sh + +# Copyright (c) 2009 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. + +# Remove old versioned directories from an .app bundle. The built-up bundle +# only needs to contain the current versioned directory. + +set -e + +if [ $# -ne 1 ] ; then + echo "usage: ${0} VERSION" >& 2 + exit 1 +fi + +VERSION="${1}" +CONTENTS_DIR="${BUILT_PRODUCTS_DIR}/${CONTENTS_FOLDER_PATH}" +VERSIONED_DIR="${CONTENTS_DIR}/Versions" +CURRENT_VERSIONED_DIR="${VERSIONED_DIR}/${VERSION}" + +for dir in "${VERSIONED_DIR}/"* ; do + if [ "${dir}" != "${CURRENT_VERSIONED_DIR}" ] ; then + rm -rf "${dir}" + fi +done + +# Older builds did not use a versioned directory, and instead placed the +# framework, helper app, and other components directly within the main app +# bundle. To keep incremental developer builds relatively pristine and +# equivalent to clean builds, these old components need to be cleaned up if +# present. +# Frameworks includes the app framework (Chromium Framework.framework or +# Google Chrome Framework.framework) and, if Keystone-enabled, +# KeystoneRegistration.framework. To simplify this script, it removes the +# helper app at its old location under either of the supported branding names. +# TODO(mark): Remove the following section some time after October 27, 2009, +# allowing two weeks for the transition. + +rm -rf "${CONTENTS_DIR}/Frameworks" \ + "${CONTENTS_DIR}/Resources/Chromium Helper.app" \ + "${CONTENTS_DIR}/Resources/Google Chrome Helper.app" \ + "${CONTENTS_DIR}/MacOS/libavcodec.52.dylib" \ + "${CONTENTS_DIR}/MacOS/libavformat.52.dylib" \ + "${CONTENTS_DIR}/MacOS/libavutil.50.dylib" diff --git a/chrome/tools/build/mac/keystone_install.sh b/chrome/tools/build/mac/keystone_install.sh index 173875a..7ef7368 100755 --- a/chrome/tools/build/mac/keystone_install.sh +++ b/chrome/tools/build/mac/keystone_install.sh @@ -27,28 +27,46 @@ if [ $# -lt 1 ] || [ ! -d "${1}" ]; then fi # Who we are. -APP_NAME="Google Chrome.app" +PRODUCT_NAME="Google Chrome" +APP_NAME="${PRODUCT_NAME}.app" +FRAMEWORK_NAME="${PRODUCT_NAME} Framework.framework" SRC="${1}/${APP_NAME}" # Sanity, make sure that there's something to copy from. -if [ ! -d "${SRC}" ]; then +if [ -z "${SRC}" ] || [ ! -d "${SRC}" ]; then exit 10 fi -# Figure out where we're going. -PRODUCT_ID=$(defaults read "${SRC}/Contents/Info" KSProductID || exit 3) +# Figure out where we're going. Determine the application version to be +# installed, use that to locate the framework, and then look inside the +# framework for the Keystone product ID. +APP_VERSION_KEY="CFBundleShortVersionString" +UPD_VERSION_APP=$(defaults read "${SRC}/Contents/Info" "${APP_VERSION_KEY}" || + exit 10) +UPD_KS_PLIST="${SRC}/Contents/Versions/${UPD_VERSION_APP}/${FRAMEWORK_NAME}/Resources/Info" +PRODUCT_ID=$(defaults read "${UPD_KS_PLIST}" KSProductID || exit 10) DEST=$(ksadmin -pP "${PRODUCT_ID}" | grep xc= | sed -E 's/.+path=(.+)>$/\1/g') # More sanity checking. -if [ -z "${SRC}" ] || [ -z "${DEST}" ] || [ ! -d $(dirname "${DEST}") ]; then +if [ -z "${DEST}" ] || [ ! -d "$(dirname "${DEST}")" ]; then exit 2 fi -# Read old version to help confirm install happiness -OLD_VERSION=$(defaults read "${DEST}/Contents/Info" KSVersion || exit 3) +# Read old version to help confirm install happiness. Older versions kept +# the KSVersion key in the application's Info.plist. Newer versions keep it +# in the versioned framework's Info.plist. +KS_VERSION_KEY="KSVersion" +OLD_VERSION_APP=$(defaults read "${DEST}/Contents/Info" "${APP_VERSION_KEY}" || + defaults read "${DEST}/Contents/Info" "${KS_VERSION_KEY}" || + exit 3) +OLD_KS_PLIST="${DEST}/Contents/Versions/${OLD_VERSION_APP}/${FRAMEWORK_NAME}/Resources/Info" +if [ ! -e "${OLD_KS_PLIST}.plist" ] ; then + OLD_KS_PLIST="${DEST}/Contents/Info" +fi +OLD_VERSION_KS=$(defaults read "${OLD_KS_PLIST}" "${KS_VERSION_KEY}" || exit 3) # Make sure we have permission to write the destination -DEST_DIRECTORY=$(dirname "${DEST}") +DEST_DIRECTORY="$(dirname "${DEST}")" if [ ! -w "${DEST_DIRECTORY}" ]; then exit 4 fi @@ -56,18 +74,21 @@ fi # This usage will preserve any changes the user made to the application name. # TODO(jrg): this may choke a running Chrome.app; be smarter. # Note: If the rsync fails we do not update the ticket version. -rsync -a --delete "${SRC}/" "${DEST}/" || exit 5 - -# Read the new values (e.g. version) -VERSION=$(defaults read "${DEST}/Contents/Info" KSVersion || exit 6) -URL=$(defaults read "${DEST}/Contents/Info" KSUpdateURL || exit 6) +rsync -ac --delete "${SRC}/" "${DEST}/" || exit 5 + +# Read the new values (e.g. version). Get the installed application version +# to get the path to the framework, where the Keystone keys are stored. +NEW_VERSION_APP=$(defaults read "${DEST}/Contents/Info" "${APP_VERSION_KEY}" || + exit 6) +NEW_KS_PLIST="${DEST}/Contents/Versions/${NEW_VERSION_APP}/${FRAMEWORK_NAME}/Resources/Info" +NEW_VERSION_KS=$(defaults read "${NEW_KS_PLIST}" "${KS_VERSION_KEY}" || exit 6) +URL=$(defaults read "${NEW_KS_PLIST}" KSUpdateURL || exit 6) # The channel ID is optional. Suppress stderr to prevent Keystone from seeing # possible error output. -CHANNEL_ID=$(defaults read "${DEST}/Contents/Info" KSChannelID 2>/dev/null || \ - true) +CHANNEL_ID=$(defaults read "${NEW_KS_PLIST}" KSChannelID 2>/dev/null || true) # Compare old and new versions. If they are equal we failed somewhere. -if [ "${OLD_VERSION}" = "${VERSION}" ]; then +if [ "${OLD_VERSION_KS}" = "${NEW_VERSION_KS}" ]; then exit 7 fi @@ -83,13 +104,13 @@ fi # patterns for any support checks we need. ksadmin --register \ -P "${PRODUCT_ID}" \ - --version "${VERSION}" \ + --version "${NEW_VERSION_KS}" \ --xcpath "${DEST}" \ --url "${URL}" \ --tag "${CHANNEL_ID}" || \ ksadmin --register \ -P "${PRODUCT_ID}" \ - --version "${VERSION}" \ + --version "${NEW_VERSION_KS}" \ --xcpath "${DEST}" \ --url "${URL}" || exit 8 diff --git a/chrome/tools/build/mac/keystone_install_test.sh b/chrome/tools/build/mac/keystone_install_test.sh index b72a9d4..6ddf9ca9 100755 --- a/chrome/tools/build/mac/keystone_install_test.sh +++ b/chrome/tools/build/mac/keystone_install_test.sh @@ -18,7 +18,9 @@ if [ ! -f "${INSTALLER}" ]; then fi # What I test -APPNAME="Google Chrome.app" +PRODNAME="Google Chrome" +APPNAME="${PRODNAME}.app" +FWKNAME="${PRODNAME} Framework.framework" # Temp directory to be used as the disk image (source) TEMPDIR=$(mktemp -d ${TMPDIR}/$(basename ${0}).XXXXXX) @@ -61,15 +63,11 @@ function pass_installer() { fi } -# Most of the setup for an install source and dest -function make_basic_src_and_dest() { - chmod ugo+w "${TEMPDIR}" - rm -rf "${TEMPDIR}" - mkdir -p "${TEMPDIR}/${APPNAME}/Contents" - defaults write "${TEMPDIR}/${APPNAME}/Contents/Info" \ - KSProductID "com.google.Chrome" - defaults write "${TEMPDIR}/${APPNAME}/Contents/Info" KSVersion 1 +# Make an old-style destination directory, to test updating from old-style +# versions to new-style versions. +function make_old_dest() { DEST="${TEMPDIR}"/Dest.app + rm -rf "${DEST}" mkdir -p "${DEST}"/Contents defaults write "${DEST}/Contents/Info" KSVersion 0 cat >"${TEMPDIR}"/ksadmin <<EOF @@ -80,6 +78,42 @@ EOF chmod u+x "${TEMPDIR}"/ksadmin } +# Make a new-style destination directory, to test updating between new-style +# versions. +function make_new_dest() { + DEST="${TEMPDIR}"/Dest.app + rm -rf "${DEST}" + RSRCDIR="${DEST}/Contents/Versions/0/${FWKNAME}/Resources" + mkdir -p "${RSRCDIR}" + defaults write "${DEST}/Contents/Info" CFBundleShortVersionString 0 + defaults write "${RSRCDIR}/Info" KSVersion 0 + cat >"${TEMPDIR}"/ksadmin <<EOF +#!/bin/sh +echo "echo xc=<blah path=$DEST>" +exit 0 +EOF + chmod u+x "${TEMPDIR}"/ksadmin +} + +# Make a simple source directory - the update that is to be applied +function make_src() { + chmod ugo+w "${TEMPDIR}" + rm -rf "${TEMPDIR}/${APPNAME}" + RSRCDIR="${TEMPDIR}/${APPNAME}/Contents/Versions/1/${FWKNAME}/Resources" + mkdir -p "${RSRCDIR}" + defaults write "${TEMPDIR}/${APPNAME}/Contents/Info" \ + CFBundleShortVersionString "1" + defaults write "${RSRCDIR}/Info" \ + KSProductID "com.google.Chrome" + defaults write "${RSRCDIR}/Info" \ + KSVersion "2" +} + +function make_basic_src_and_dest() { + make_src + make_new_dest +} + fail_installer "No source anything" mkdir "${TEMPDIR}"/"${APPNAME}" @@ -92,9 +126,17 @@ fail_installer "Writable dest directory" make_basic_src_and_dest fail_installer "Was no KSUpdateURL in dest after copy" +make_src +make_old_dest +defaults write \ + "${TEMPDIR}/${APPNAME}/Contents/Versions/1/${FWKNAME}/Resources/Info" \ + KSUpdateURL "http://foo.bar" +pass_installer "Old-style update" + make_basic_src_and_dest -defaults write "${TEMPDIR}/${APPNAME}/Contents/Info" \ - KSUpdateURL "http://foo.bar" +defaults write \ + "${TEMPDIR}/${APPNAME}/Contents/Versions/1/${FWKNAME}/Resources/Info" \ + KSUpdateURL "http://foo.bar" pass_installer "ALL" cleanup_tempdir diff --git a/chrome/tools/build/mac/make_sign_sh b/chrome/tools/build/mac/make_sign_sh index 115882c..db6e1c2 100755 --- a/chrome/tools/build/mac/make_sign_sh +++ b/chrome/tools/build/mac/make_sign_sh @@ -5,24 +5,44 @@ # found in the LICENSE file. # This script creates sign.sh, the script that will be used to sign the -# application bundle and inner bundles. sign.sh is placed in the Packaging +# application bundle and inner bundles. It also creates auxiliary files that +# sign.sh needs to do its job, such as the custom resource rules used to sign +# the outermost application bundle. These files are placed in the Packaging # directory next to the .app bundle. The packaging system is expected to run # sign.sh to sign everything. set -e -if [ $# -ne 2 ] ; then - echo "usage: ${0} PACKAGING_DIR MAC_PRODUCT_NAME" >& 2 +if [ $# -ne 3 ] ; then + echo "usage: ${0} PACKAGING_DIR MAC_PRODUCT_NAME VERSION" >& 2 exit 1 fi PACKAGING_DIR="${1}" MAC_PRODUCT_NAME="${2}" -SIGN_SH_IN_FILE="$(dirname "${0}")/sign.sh.in" +VERSION="${3}" + +INPUT_DIR="$(dirname "${0}")" +SIGN_SH_IN_FILE="${INPUT_DIR}/sign.sh.in" SIGN_SH_FILE="${PACKAGING_DIR}/sign.sh" +BROWSER_APP_RULES_IN_FILE="${INPUT_DIR}/app_resource_rules.plist.in" +BROWSER_APP_RULES_FILE="${PACKAGING_DIR}/app_resource_rules.plist" + +# Double-backslash each dot: one backslash belongs in the regular expression, +# and the other backslash tells sed not to treat the first backslash +# specially. +VERSION_REGEX="$(echo "${VERSION}" | sed -e 's/\./\\\\./g')" mkdir -p "${PACKAGING_DIR}" sed -e "s/@MAC_PRODUCT_NAME@/${MAC_PRODUCT_NAME}/g" \ + -e "s/@VERSION@/${VERSION}/g" \ + -e "s/@VERSION_REGEX@/${VERSION_REGEX}/g" \ < "${SIGN_SH_IN_FILE}" \ > "${SIGN_SH_FILE}" -chmod a+rx "${SIGN_SH_FILE}" +chmod +x "${SIGN_SH_FILE}" + +sed -e "s/@MAC_PRODUCT_NAME@/${MAC_PRODUCT_NAME}/g" \ + -e "s/@VERSION@/${VERSION}/g" \ + -e "s/@VERSION_REGEX@/${VERSION_REGEX}/g" \ + < "${BROWSER_APP_RULES_IN_FILE}" \ + > "${BROWSER_APP_RULES_FILE}" diff --git a/chrome/tools/build/mac/remove_headers_from_framework b/chrome/tools/build/mac/remove_headers_from_framework new file mode 100755 index 0000000..c48fd1f --- /dev/null +++ b/chrome/tools/build/mac/remove_headers_from_framework @@ -0,0 +1,31 @@ +#!/bin/sh + +# Copyright (c) 2009 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. + +# Frameworks included in an application for distribution aren't used for +# development, and don't need to bundle any headers. + +set -e + +if [ $# -ne 1 ] ; then + echo "usage: ${0} FRAMEWORK" >& 2 + exit 1 +fi + +FRAMEWORK="${1}" + +rm -rf -- "${FRAMEWORK}/Versions/Current/Headers" \ + "${FRAMEWORK}/Versions/Current/PrivateHeaders" \ + "${FRAMEWORK}/Headers" \ + "${FRAMEWORK}/PrivateHeaders" + +# Remove other-versioned headers after current-version headers, in case Current +# is a symbolic link to another version, as is the usual case. If everything +# was done in a single invocation, the shell would do the wildcard expansion +# first, and rm would try (and fail) to remove the same directory twice, such +# as Versions/Current/Headers and Versions/A/Headers when Versions/Current is +# a symbolic link for A. +rm -rf -- "${FRAMEWORK}"/Versions/*/Headers \ + "${FRAMEWORK}"/Versions/*/PrivateHeaders diff --git a/chrome/tools/build/mac/sign.sh.in b/chrome/tools/build/mac/sign.sh.in index 41c8b58..07a7593 100644 --- a/chrome/tools/build/mac/sign.sh.in +++ b/chrome/tools/build/mac/sign.sh.in @@ -18,13 +18,16 @@ APP_PATH="${1}" CODESIGN_KEYCHAIN="${2}" CODESIGN_ID="${3}" +# Use custom resource rules for the browser application. +BROWSER_APP_RULES="$(dirname "${0}")/app_resource_rules.plist" + # An .app bundle to be signed can be signed directly. Signging a framework # bundle requires that each version within be signed individually. # http://developer.apple.com/mac/library/technotes/tn2007/tn2206.html#TNTAG13 BROWSER_APP="${APP_PATH}" -FRAMEWORK="${BROWSER_APP}/Contents/Frameworks/@MAC_PRODUCT_NAME@ Framework.framework/Versions/A" -HELPER_APP="${BROWSER_APP}/Contents/Resources/@MAC_PRODUCT_NAME@ Helper.app" +FRAMEWORK="${BROWSER_APP}/Contents/Versions/@VERSION@/@MAC_PRODUCT_NAME@ Framework.framework/Versions/A" +HELPER_APP="${BROWSER_APP}/Contents/Versions/@VERSION@/@MAC_PRODUCT_NAME@ Helper.app" echo "${0}: signing..." @@ -33,7 +36,8 @@ echo "${0}: signing..." codesign -s "${CODESIGN_ID}" --keychain "${CODESIGN_KEYCHAIN}" "${FRAMEWORK}" codesign -s "${CODESIGN_ID}" --keychain "${CODESIGN_KEYCHAIN}" "${HELPER_APP}" -codesign -s "${CODESIGN_ID}" --keychain "${CODESIGN_KEYCHAIN}" "${BROWSER_APP}" +codesign -s "${CODESIGN_ID}" --keychain "${CODESIGN_KEYCHAIN}" \ + "${BROWSER_APP}" --resource-rules "${BROWSER_APP_RULES}" # Verify everything to ensure that signing the outer bundle didn't break an # inner bundle. |