summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
Diffstat (limited to 'chrome')
-rw-r--r--chrome/app/keystone_glue.mm (renamed from chrome/app/keystone_glue.m)21
-rwxr-xr-xchrome/app/make_mac_app_symlinks17
-rwxr-xr-xchrome/chrome.gyp167
-rw-r--r--chrome/common/child_process_host.cc59
-rw-r--r--chrome/common/chrome_constants.cc1
-rw-r--r--chrome/common/chrome_paths_internal.h11
-rw-r--r--chrome/common/chrome_paths_mac.mm50
-rw-r--r--chrome/tools/build/mac/app_resource_rules.plist.in55
-rwxr-xr-xchrome/tools/build/mac/clean_up_old_versions45
-rwxr-xr-xchrome/tools/build/mac/keystone_install.sh57
-rwxr-xr-xchrome/tools/build/mac/keystone_install_test.sh64
-rwxr-xr-xchrome/tools/build/mac/make_sign_sh30
-rwxr-xr-xchrome/tools/build/mac/remove_headers_from_framework31
-rw-r--r--chrome/tools/build/mac/sign.sh.in10
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.