diff options
-rw-r--r-- | chrome/app/app_mode-Info.plist | 6 | ||||
-rw-r--r-- | chrome/app/app_mode_loader_mac.mm | 6 | ||||
-rw-r--r-- | chrome/app/chrome_main_app_mode_mac.mm | 6 | ||||
-rw-r--r-- | chrome/browser/web_applications/web_app_mac.h | 27 | ||||
-rw-r--r-- | chrome/browser/web_applications/web_app_mac.mm | 37 | ||||
-rw-r--r-- | chrome/browser/web_applications/web_app_mac_unittest.mm | 24 | ||||
-rw-r--r-- | chrome/chrome.gyp | 38 | ||||
-rw-r--r-- | chrome/chrome_dll.gypi | 6 | ||||
-rw-r--r-- | chrome/chrome_tests.gypi | 2 | ||||
-rw-r--r-- | chrome/common/mac/app_mode_common.h | 17 | ||||
-rw-r--r-- | chrome/common/mac/app_mode_common.mm | 5 |
11 files changed, 140 insertions, 34 deletions
diff --git a/chrome/app/app_mode-Info.plist b/chrome/app/app_mode-Info.plist index 611f7c5..1603382 100644 --- a/chrome/app/app_mode-Info.plist +++ b/chrome/app/app_mode-Info.plist @@ -6,12 +6,14 @@ <string>en</string> <key>CFBundleDisplayName</key> <string>@APP_MODE_SHORTCUT_SHORT_NAME@</string> + <key>CFBundleSignature</key> + <string>????</string> <key>CFBundleExecutable</key> - <string>@APP_MODE_SHORTCUT_ID@</string> + <string>${EXECUTABLE_NAME}</string> <key>CFBundleIconFile</key> <string>app.icns</string> <key>CFBundleIdentifier</key> - <string>????</string> + <string>${APP_MODE_APP_BUNDLE_ID}</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundleName</key> diff --git a/chrome/app/app_mode_loader_mac.mm b/chrome/app/app_mode_loader_mac.mm index 3d10145..a691b15 100644 --- a/chrome/app/app_mode_loader_mac.mm +++ b/chrome/app/app_mode_loader_mac.mm @@ -39,8 +39,8 @@ void LoadFramework(void** cr_dylib, app_mode::ChromeAppModeInfo* info) { // ** 1: Get path to outer Chrome bundle. // Get the bundle ID of the browser that created this app bundle. - NSString* cr_bundle_id = [app_bundle - objectForInfoDictionaryKey:app_mode::kBrowserBundleIDKey]; + NSString* cr_bundle_id = base::mac::ObjCCast<NSString>( + [app_bundle objectForInfoDictionaryKey:app_mode::kBrowserBundleIDKey]); CHECK(cr_bundle_id) << "couldn't get browser bundle ID"; // First check if Chrome exists at the last known location. @@ -72,6 +72,7 @@ void LoadFramework(void** cr_dylib, app_mode::ChromeAppModeInfo* info) { } // ** 3: Fill in ChromeAppModeInfo. + info->chrome_outer_bundle_path = cr_bundle_path; info->chrome_versioned_path = version_path; info->app_mode_bundle_path = base::mac::NSStringToFilePath([app_bundle bundlePath]); @@ -93,7 +94,6 @@ void LoadFramework(void** cr_dylib, app_mode::ChromeAppModeInfo* info) { info->app_mode_url = SysNSStringToUTF8( [info_plist objectForKey:app_mode::kCrAppModeShortcutURLKey]); - CHECK(info->app_mode_url.size()) << "couldn't get app shortcut URL"; info->user_data_dir = base::mac::NSStringToFilePath( [info_plist objectForKey:app_mode::kCrAppModeUserDataDirKey]); diff --git a/chrome/app/chrome_main_app_mode_mac.mm b/chrome/app/chrome_main_app_mode_mac.mm index b32ae31..043f87f 100644 --- a/chrome/app/chrome_main_app_mode_mac.mm +++ b/chrome/app/chrome_main_app_mode_mac.mm @@ -13,6 +13,8 @@ #include "base/command_line.h" #include "base/file_path.h" #include "base/logging.h" +#include "base/mac/bundle_locations.h" +#include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_paths_internal.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/mac/app_mode_common.h" @@ -43,9 +45,13 @@ int ChromeAppModeStart(const app_mode::ChromeAppModeInfo* info) { FilePath* chrome_versioned_path = new FilePath(info->chrome_versioned_path); RAW_CHECK(!chrome_versioned_path->empty()); chrome::SetOverrideVersionedDirectory(chrome_versioned_path); + base::mac::SetOverrideOuterBundlePath(info->chrome_outer_bundle_path); + base::mac::SetOverrideFrameworkBundlePath( + chrome_versioned_path->Append(chrome::kFrameworkName)); CommandLine command_line(CommandLine::NO_PROGRAM); command_line.AppendSwitch(info->argv[0]); + RAW_CHECK(info->app_mode_id.size()); command_line.AppendSwitchASCII(switches::kAppId, info->app_mode_id); command_line.AppendSwitchPath(switches::kUserDataDir, info->user_data_dir); diff --git a/chrome/browser/web_applications/web_app_mac.h b/chrome/browser/web_applications/web_app_mac.h index 1723ac1..968bb8c 100644 --- a/chrome/browser/web_applications/web_app_mac.h +++ b/chrome/browser/web_applications/web_app_mac.h @@ -8,8 +8,17 @@ #include "base/file_path.h" #include "base/gtest_prod_util.h" +#include "base/string16.h" #include "chrome/browser/shell_integration.h" +#ifdef __OBJC__ +@class NSDictionary; +@class NSString; +#else // __OBJC__ +class NSDictionary; +class NSString; +#endif // __OBJC__ + namespace web_app { // Creates a shortcut for a web application. The shortcut is a stub app @@ -18,12 +27,16 @@ class WebAppShortcutCreator { public: // Creates a new shortcut based on information in |shortcut_info|. // The shortcut stores its user data directory in |user_data_dir|. - explicit WebAppShortcutCreator( + // |chrome_bundle_id| is the CFBundleIdentifier of the Chrome browser bundle. + WebAppShortcutCreator( const FilePath& user_data_dir, - const ShellIntegration::ShortcutInfo& shortcut_info); + const ShellIntegration::ShortcutInfo& shortcut_info, + const string16& chrome_bundle_id); + virtual ~WebAppShortcutCreator(); - // Creates a shortcut. + // Copies the app launcher template into place and fills in all relevant + // information. bool CreateShortcut(); protected: @@ -47,8 +60,16 @@ class WebAppShortcutCreator { // Note, the user data directory is the parent of the profile directory. FilePath user_data_dir_; + // Returns the bundle identifier to use for this app bundle. + // |plist| is a dictionary containg a copy of the template plist file to + // be used for creating the app bundle. + NSString* GetBundleIdentifier(NSDictionary* plist) const; + // Information about the app. ShellIntegration::ShortcutInfo info_; + + // The CFBundleIdentifier of the Chrome browser bundle. + string16 chrome_bundle_id_; }; } // namespace web_app diff --git a/chrome/browser/web_applications/web_app_mac.mm b/chrome/browser/web_applications/web_app_mac.mm index 2bdfe1a..33adce3 100644 --- a/chrome/browser/web_applications/web_app_mac.mm +++ b/chrome/browser/web_applications/web_app_mac.mm @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/web_applications/web_app_mac.h" +#import "chrome/browser/web_applications/web_app_mac.h" #import <Cocoa/Cocoa.h> @@ -13,7 +13,9 @@ #include "base/memory/scoped_nsobject.h" #include "base/scoped_temp_dir.h" #include "base/sys_string_conversions.h" +#include "base/utf_string_conversions.h" #include "chrome/browser/web_applications/web_app.h" +#include "chrome/common/chrome_paths_internal.h" #include "chrome/common/mac/app_mode_common.h" #include "content/public/browser/browser_thread.h" #include "grit/chromium_strings.h" @@ -40,9 +42,11 @@ namespace web_app { WebAppShortcutCreator::WebAppShortcutCreator( const FilePath& user_data_dir, - const ShellIntegration::ShortcutInfo& shortcut_info) + const ShellIntegration::ShortcutInfo& shortcut_info, + const string16& chrome_bundle_id) : user_data_dir_(user_data_dir), - info_(shortcut_info) { + info_(shortcut_info), + chrome_bundle_id_(chrome_bundle_id) { } WebAppShortcutCreator::~WebAppShortcutCreator() { @@ -83,10 +87,8 @@ bool WebAppShortcutCreator::CreateShortcut() { } FilePath WebAppShortcutCreator::GetAppLoaderPath() const { - NSString* app_loader = [l10n_util::GetNSString(IDS_PRODUCT_NAME) - stringByAppendingString:@" App Mode Loader.app"]; return base::mac::PathForFrameworkBundleResource( - base::mac::NSToCFCast(app_loader)); + base::mac::NSToCFCast(@"app_mode_loader.app")); } FilePath WebAppShortcutCreator::GetDestinationPath( @@ -109,6 +111,8 @@ bool WebAppShortcutCreator::UpdatePlist(const FilePath& app_path) const { NSMutableDictionary* dict = [NSMutableDictionary dictionaryWithContentsOfFile:plist_path]; + [dict setObject:GetBundleIdentifier(dict) + forKey:base::mac::CFToNSCast(kCFBundleIdentifierKey)]; [dict setObject:base::SysUTF8ToNSString(info_.extension_id) forKey:app_mode::kCrAppModeShortcutIDKey]; [dict setObject:base::SysUTF16ToNSString(info_.title) @@ -119,6 +123,8 @@ bool WebAppShortcutCreator::UpdatePlist(const FilePath& app_path) const { forKey:app_mode::kCrAppModeUserDataDirKey]; [dict setObject:base::mac::FilePathToNSString(info_.extension_path) forKey:app_mode::kCrAppModeExtensionPathKey]; + [dict setObject:base::SysUTF16ToNSString(chrome_bundle_id_) + forKey:app_mode::kBrowserBundleIDKey]; return [dict writeToFile:plist_path atomically:YES]; } @@ -152,6 +158,21 @@ bool WebAppShortcutCreator::UpdateIcon(const FilePath& app_path) const { return [icon_family writeToFile:base::mac::FilePathToNSString(icon_path)]; } +NSString* WebAppShortcutCreator::GetBundleIdentifier(NSDictionary* plist) const +{ + NSString* bundle_id_template = + base::mac::ObjCCast<NSString>( + [plist objectForKey:base::mac::CFToNSCast(kCFBundleIdentifierKey)]); + NSString* extension_id = base::SysUTF8ToNSString(info_.extension_id); + NSString* placeholder = + [NSString stringWithFormat:@"@%@@", app_mode::kShortcutIdPlaceholder]; + NSString* bundle_id = + [bundle_id_template + stringByReplacingOccurrencesOfString:placeholder + withString:extension_id]; + return bundle_id; +} + } // namespace namespace web_app { @@ -161,7 +182,9 @@ void CreateShortcutTask(const FilePath& web_app_path, const FilePath& profile_path, const ShellIntegration::ShortcutInfo& shortcut_info) { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); - WebAppShortcutCreator shortcut_creator(web_app_path, shortcut_info); + string16 bundle_id = UTF8ToUTF16(base::mac::BaseBundleID()); + WebAppShortcutCreator shortcut_creator(web_app_path, shortcut_info, + bundle_id); shortcut_creator.CreateShortcut(); } diff --git a/chrome/browser/web_applications/web_app_mac_unittest.mm b/chrome/browser/web_applications/web_app_mac_unittest.mm index 6d95261..fa11eaa 100644 --- a/chrome/browser/web_applications/web_app_mac_unittest.mm +++ b/chrome/browser/web_applications/web_app_mac_unittest.mm @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/web_applications/web_app_mac.h" +#import "chrome/browser/web_applications/web_app_mac.h" #import <Cocoa/Cocoa.h> @@ -30,7 +30,8 @@ class WebAppShortcutCreatorMock : public web_app::WebAppShortcutCreator { public: explicit WebAppShortcutCreatorMock( const ShellIntegration::ShortcutInfo& shortcut_info) - : WebAppShortcutCreator(FilePath(), shortcut_info) { + : WebAppShortcutCreator(FilePath(), shortcut_info, + UTF8ToUTF16("fake.cfbundleidentifier")) { } MOCK_CONST_METHOD1(GetDestinationPath, FilePath(const FilePath&)); @@ -48,8 +49,11 @@ ShellIntegration::ShortcutInfo GetShortcutInfo() { namespace web_app { -// This test currently fails because the Mac app loader isn't built yet. -TEST(WebAppShortcutCreatorTest, FAILS_CreateShortcut) { +// This test is disabled for the following reasons: +// * The plist still isn't filled in correctly. +// * WebAppShortcutCreator::CreateShortcut() opens a Finder window which it +// shouldn't be doing when run from a unit test. +TEST(WebAppShortcutCreatorTest, DISABLED_CreateShortcut) { ScopedTempDir scoped_temp_dir; EXPECT_TRUE(scoped_temp_dir.CreateUniqueTempDir()); FilePath dst_path = scoped_temp_dir.path().Append("a.app"); @@ -72,11 +76,17 @@ TEST(WebAppShortcutCreatorTest, FAILS_CreateShortcut) { [plist objectForKey:app_mode::kCrAppModeShortcutURLKey]); // Make sure all values in the plist are actually filled in. - for (NSString* value in [plist allValues]) - EXPECT_FALSE([value hasPrefix:@"@APP_"]); + for (id key in plist) { + id value = [plist valueForKey:key]; + if (!base::mac::ObjCCast<NSString>(value)) + continue; + + EXPECT_EQ([value rangeOfString:@"@APP_"].location, NSNotFound) + << [key UTF8String] << ":" << [value UTF8String]; + } } -TEST(WebAppShortcutCreatorTest, CreateFailure) { +TEST(WebAppShortcutCreatorTest, DISABLED_CreateFailure) { NiceMock<WebAppShortcutCreatorMock> shortcut_creator(GetShortcutInfo()); EXPECT_CALL(shortcut_creator, GetDestinationPath(_)) .WillRepeatedly(Return(FilePath("/non-existant/path/"))); diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index ccac7c4..f07d554 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -781,7 +781,7 @@ # 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, --breakpad=0, -k0, and -s0 are used - # because Breakpad, Keystone, and Subersion keys are never + # because Breakpad, Keystone, and Subversion keys are never # placed into the helper. 'postbuild_name': 'Tweak Info.plist', 'action': ['<(tweak_info_plist_path)', @@ -841,17 +841,21 @@ ], }, # target app_mode_app_support { - # This produces the app mode loader, but not as a bundle. Chromium - # itself is responsible for producing bundles. + # This produces the template for app mode loader bundles. It's a + # template in the sense that parts of it need to be "filled in" by + # Chrome before it can be executed. 'target_name': 'app_mode_app', 'type': 'executable', + 'mac_bundle' : 1, 'variables': { 'enable_wexit_time_destructors': 1, }, - 'product_name': '<(mac_product_name) App Mode Loader', + 'product_name': 'app_mode_loader', 'dependencies': [ 'app_mode_app_support', + 'infoplist_strings_tool', ], 'sources': [ 'app/app_mode_loader_mac.mm', + 'app/app_mode-Info.plist', ], 'include_dirs': [ '..', @@ -862,6 +866,32 @@ '$(SDKROOT)/System/Library/Frameworks/Foundation.framework', ], }, + 'mac_bundle_resources!': [ + 'app/app_mode-Info.plist', + ], + 'mac_bundle_resources/': [ + ['exclude', '.*'], + ], + 'xcode_settings': { + 'INFOPLIST_FILE': 'app/app_mode-Info.plist', + 'APP_MODE_APP_BUNDLE_ID': '<(mac_bundle_id).app.@APP_MODE_SHORTCUT_ID@', + }, + 'postbuilds' : [ + { + # 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, --breakpad=0, -k0, and -s0 are used + # because Breakpad, Keystone, and Subversion keys are never + # placed into the app mode loader. + 'postbuild_name': 'Tweak Info.plist', + 'action': ['<(tweak_info_plist_path)', + '--breakpad=0', + '-k0', + '-s0', + '<(branding)', + '<(mac_bundle_id)'], + }, + ], }, # target app_mode_app { # Convenience target to build a disk image. diff --git a/chrome/chrome_dll.gypi b/chrome/chrome_dll.gypi index afd6034..14d89de 100644 --- a/chrome/chrome_dll.gypi +++ b/chrome/chrome_dll.gypi @@ -310,6 +310,7 @@ 'app/framework-Info.plist', ], 'dependencies': [ + 'app_mode_app', # Bring in pdfsqueeze and run it on all pdfs '../build/temp_gyp/pdfsqueeze.gyp:pdfsqueeze', '../crypto/crypto.gyp:crypto', @@ -444,7 +445,10 @@ }, { 'destination': '<(PRODUCT_DIR)/$(CONTENTS_FOLDER_PATH)/resources', - 'files': [], + 'files': [ + # Loader bundle for platform apps. + '<(PRODUCT_DIR)/app_mode_loader.app', + ], 'conditions': [ ['debug_devtools!=0', { 'files': [ diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index eda65a0..555f224 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -4241,7 +4241,7 @@ # Tests for Mac app launcher. 'target_name': 'app_mode_app_tests', 'type': 'executable', - 'product_name': 'App Mode Loader Tests', + 'product_name': 'app_mode_app_tests', 'dependencies': [ '../base/base.gyp:test_support_base', '../testing/gtest.gyp:gtest', diff --git a/chrome/common/mac/app_mode_common.h b/chrome/common/mac/app_mode_common.h index 930d22d..b8bc539 100644 --- a/chrome/common/mac/app_mode_common.h +++ b/chrome/common/mac/app_mode_common.h @@ -20,10 +20,6 @@ namespace app_mode { // app mode launcher bundle's Info.plist. extern NSString* const kBrowserBundleIDKey; -// The key under which to record the path to the (user-visible) application -// bundle; this key is recorded under the ID given by |kAppPrefsID|. -extern NSString* const kLastRunAppBundlePathPrefsKey; - // Key for the shortcut ID. extern NSString* const kCrAppModeShortcutIDKey; @@ -42,6 +38,14 @@ extern NSString* const kCrAppModeUserDataDirKey; // Key for the app's extension path. extern NSString* const kCrAppModeExtensionPathKey; +// When the Chrome browser is run, it stores it's location in the defaults +// system using this key. +extern NSString* const kLastRunAppBundlePathPrefsKey; + +// Placeholder used in the Info.plist, meant to be replaced by the extension +// shortcut ID. +extern NSString* const kShortcutIdPlaceholder; + // Current major/minor version numbers of |ChromeAppModeInfo| (defined below). const unsigned kCurrentChromeAppModeInfoMajorVersion = 1; const unsigned kCurrentChromeAppModeInfoMinorVersion = 0; @@ -68,9 +72,12 @@ struct ChromeAppModeInfo { // Versioned path to the browser which is being loaded. FilePath chrome_versioned_path; // Required: v1.0 + // Path to Chrome app bundle. + FilePath chrome_outer_bundle_path; // Required: v1.0 + // Information about the App Mode shortcut: - // Path to the App Mode Loader application bundle originally run. + // Path to the App Mode Loader application bundle that launched the process. FilePath app_mode_bundle_path; // Optional: v1.0 // Short ID string, preferably derived from |app_mode_short_name|. Should be diff --git a/chrome/common/mac/app_mode_common.mm b/chrome/common/mac/app_mode_common.mm index 48bf38e..bb8c267 100644 --- a/chrome/common/mac/app_mode_common.mm +++ b/chrome/common/mac/app_mode_common.mm @@ -7,7 +7,6 @@ namespace app_mode { NSString* const kBrowserBundleIDKey = @"CrBundleIdentifier"; -NSString* const kLastRunAppBundlePathPrefsKey = @"LastRunAppBundlePath"; NSString* const kCrAppModeShortcutIDKey = @"CrAppModeShortcutID"; NSString* const kCrAppModeShortcutShortNameKey = @"CrAppModeShortcutShortName"; NSString* const kCrAppModeShortcutNameKey = @"CrAppModeShortcutName"; @@ -15,6 +14,10 @@ NSString* const kCrAppModeShortcutURLKey = @"CrAppModeShortcutURL"; NSString* const kCrAppModeUserDataDirKey = @"CrAppModeUserDataDir"; NSString* const kCrAppModeExtensionPathKey = @"CrAppModeExtensionPath"; +NSString* const kLastRunAppBundlePathPrefsKey = @"LastRunAppBundlePath"; + +NSString* const kShortcutIdPlaceholder = @"APP_MODE_SHORTCUT_ID"; + ChromeAppModeInfo::ChromeAppModeInfo() : major_version(0), minor_version(0), |