diff options
author | jackhou@chromium.org <jackhou@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-18 18:26:38 +0000 |
---|---|---|
committer | jackhou@chromium.org <jackhou@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-18 18:26:38 +0000 |
commit | 5bbfbae20e9c1871d100d649c4c59e39e4264da4 (patch) | |
tree | 9a4b7e065f65071173eea850c3cfa8eddad195c6 | |
parent | 34f1c4212da0da25773254f32b3c8f76fb56af45 (diff) | |
download | chromium_src-5bbfbae20e9c1871d100d649c4c59e39e4264da4.zip chromium_src-5bbfbae20e9c1871d100d649c4c59e39e4264da4.tar.gz chromium_src-5bbfbae20e9c1871d100d649c4c59e39e4264da4.tar.bz2 |
[Mac] Rebuild app shims when they fail to dyload Chrome Framework.
This also changes app_mode_loader to start Chrome with --app-shim-error
only when it was started by Chrome or if it is the app_list shim. When
started by the user, it launches Chrome with --app-id. This simplifies
how Chrome handles --app-shim-error. It does not need to load the
profile or app extension, and rebuilding the shim does not block
launching the app.
BUG=353047
Review URL: https://codereview.chromium.org/265163006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@278126 0039d316-1c4b-4281-b951-d872f2087c98
18 files changed, 213 insertions, 74 deletions
diff --git a/chrome/app/app_mode_loader_mac.mm b/chrome/app/app_mode_loader_mac.mm index 402aea8..7a489eb 100644 --- a/chrome/app/app_mode_loader_mac.mm +++ b/chrome/app/app_mode_loader_mac.mm @@ -20,7 +20,9 @@ #include "base/mac/foundation_util.h" #include "base/mac/launch_services_util.h" #include "base/mac/scoped_nsautorelease_pool.h" +#include "base/process/launch.h" #include "base/strings/sys_string_conversions.h" +#include "chrome/common/chrome_switches.h" #import "chrome/common/mac/app_mode_chrome_locator.h" #include "chrome/common/mac/app_mode_common.h" @@ -67,11 +69,15 @@ int LoadFrameworkAndStart(app_mode::ChromeAppModeInfo* info) { } // ** 2: Read information from the Chrome bundle. + base::FilePath executable_path; base::string16 raw_version_str; base::FilePath version_path; base::FilePath framework_shlib_path; - if (!app_mode::GetChromeBundleInfo(cr_bundle_path, &raw_version_str, - &version_path, &framework_shlib_path)) { + if (!app_mode::GetChromeBundleInfo(cr_bundle_path, + &executable_path, + &raw_version_str, + &version_path, + &framework_shlib_path)) { LOG(FATAL) << "Couldn't ready Chrome bundle info"; } base::FilePath app_mode_bundle_path = @@ -115,28 +121,53 @@ int LoadFrameworkAndStart(app_mode::ChromeAppModeInfo* info) { LOG(ERROR) << "Couldn't load framework: " << dlerror(); } - if (ChromeAppModeStart) { + if (ChromeAppModeStart) return ChromeAppModeStart(info); - } else { - LOG(ERROR) << "Loading Chrome failed, launching with command line."; - // Launch Chrome instead and have it update this app_mode_loader bundle. - CommandLine command_line(CommandLine::NO_PROGRAM); - command_line.AppendSwitchPath(app_mode::kAppShimError, - app_mode_bundle_path); - if (!base::mac::OpenApplicationWithPath( - cr_bundle_path, command_line, kLSLaunchDefaults, NULL)) { - LOG(ERROR) << "Could not launch Chrome from: " << cr_bundle_path.value(); - return 1; - } - return 0; + LOG(ERROR) << "Loading Chrome failed, launching Chrome with command line"; + CommandLine command_line(executable_path); + // The user_data_dir from the plist is actually the app data dir. + command_line.AppendSwitchPath( + switches::kUserDataDir, + info->user_data_dir.DirName().DirName().DirName()); + if (CommandLine::ForCurrentProcess()->HasSwitch( + app_mode::kLaunchedByChromeProcessId) || + info->app_mode_id == app_mode::kAppListModeId) { + // Pass --app-shim-error to have Chrome rebuild this shim. + // If Chrome has rebuilt this shim once already, then rebuilding doesn't fix + // the problem, so don't try again. + if (!CommandLine::ForCurrentProcess()->HasSwitch( + app_mode::kLaunchedAfterRebuild)) { + command_line.AppendSwitchPath(app_mode::kAppShimError, + app_mode_bundle_path); + } + } else { + // If the shim was launched directly (instead of by Chrome), first ask + // Chrome to launch the app. Chrome will launch the shim again, the same + // error will occur and be handled above. This approach allows the app to be + // started without blocking on fixing the shim and guarantees that the + // profile is loaded when Chrome receives --app-shim-error. + command_line.AppendSwitchPath(switches::kProfileDirectory, + info->profile_dir); + command_line.AppendSwitchASCII(switches::kAppId, info->app_mode_id); + } + // Launch the executable directly since base::mac::OpenApplicationWithPath + // uses LSOpenApplication which doesn't pass command line arguments if the + // application is already running. + if (!base::LaunchProcess(command_line, base::LaunchOptions(), NULL)) { + LOG(ERROR) << "Could not launch Chrome: " + << command_line.GetCommandLineString(); + return 1; } + + return 0; } } // namespace __attribute__((visibility("default"))) int main(int argc, char** argv) { + CommandLine::Init(argc, argv); app_mode::ChromeAppModeInfo info; // Hard coded info parameters. diff --git a/chrome/browser/ui/app_list/app_list_service.h b/chrome/browser/ui/app_list/app_list_service.h index 91fbe7f..ce92300 100644 --- a/chrome/browser/ui/app_list/app_list_service.h +++ b/chrome/browser/ui/app_list/app_list_service.h @@ -103,6 +103,9 @@ class AppListService { // Returns a pointer to the platform specific AppListControllerDelegate. virtual AppListControllerDelegate* GetControllerDelegate() = 0; + // Create a platform-specific shortcut for the app list. + virtual void CreateShortcut() = 0; + protected: AppListService() {} virtual ~AppListService() {} diff --git a/chrome/browser/ui/app_list/app_list_service_disabled.cc b/chrome/browser/ui/app_list/app_list_service_disabled.cc index 4e7b5d1..5261459 100644 --- a/chrome/browser/ui/app_list/app_list_service_disabled.cc +++ b/chrome/browser/ui/app_list/app_list_service_disabled.cc @@ -45,6 +45,8 @@ class AppListServiceDisabled : public AppListService { return NULL; } + virtual void CreateShortcut() OVERRIDE {} + virtual gfx::NativeWindow GetAppListWindow() OVERRIDE { return NULL; } diff --git a/chrome/browser/ui/app_list/app_list_service_impl.h b/chrome/browser/ui/app_list/app_list_service_impl.h index 9cc514c..6fe68ae 100644 --- a/chrome/browser/ui/app_list/app_list_service_impl.h +++ b/chrome/browser/ui/app_list/app_list_service_impl.h @@ -48,6 +48,7 @@ class AppListServiceImpl : public AppListService, virtual void AutoShowForProfile(Profile* requested_profile) OVERRIDE; virtual void EnableAppList(Profile* initial_profile, AppListEnableSource enable_source) OVERRIDE; + virtual void CreateShortcut() OVERRIDE; protected: AppListServiceImpl(); @@ -61,9 +62,6 @@ class AppListServiceImpl : public AppListService, // list, and records UMA stats delayed from a previous Chrome process. void PerformStartupChecks(Profile* initial_profile); - // Create a platform-specific shortcut for the app list. - virtual void CreateShortcut(); - private: static void SendAppListStats(); diff --git a/chrome/browser/ui/app_list/app_list_service_mac.h b/chrome/browser/ui/app_list/app_list_service_mac.h index 9247531..4f0646d 100644 --- a/chrome/browser/ui/app_list/app_list_service_mac.h +++ b/chrome/browser/ui/app_list/app_list_service_mac.h @@ -62,8 +62,6 @@ class AppListServiceMac : public AppListServiceImpl, virtual gfx::NativeWindow GetAppListWindow() OVERRIDE; virtual AppListControllerDelegate* GetControllerDelegate() OVERRIDE; virtual Profile* GetCurrentAppListProfile() OVERRIDE; - - // AppListServiceImpl overrides: virtual void CreateShortcut() OVERRIDE; // AppShimHandler overrides: diff --git a/chrome/browser/ui/startup/startup_browser_creator.cc b/chrome/browser/ui/startup/startup_browser_creator.cc index defd5bd..4393aa0 100644 --- a/chrome/browser/ui/startup/startup_browser_creator.cc +++ b/chrome/browser/ui/startup/startup_browser_creator.cc @@ -85,6 +85,10 @@ #include "ui/events/x/touch_factory_x11.h" #endif +#if defined(OS_MACOSX) +#include "chrome/browser/web_applications/web_app_mac.h" +#endif + #if defined(ENABLE_FULL_PRINTING) #include "chrome/browser/printing/cloud_print/cloud_print_proxy_service.h" #include "chrome/browser/printing/cloud_print/cloud_print_proxy_service_factory.h" @@ -558,6 +562,11 @@ bool StartupBrowserCreator::ProcessCmdLineImpl( ui::TouchFactory::SetTouchDeviceListFromCommandLine(); #endif +#if defined(OS_MACOSX) + if (web_app::MaybeRebuildShortcut(command_line)) + return true; +#endif + if (!process_startup && command_line.HasSwitch(switches::kDumpBrowserHistograms)) { // Only handle --dump-browser-histograms from a rendezvous. In this case, do diff --git a/chrome/browser/ui/views/app_list/linux/app_list_service_linux.h b/chrome/browser/ui/views/app_list/linux/app_list_service_linux.h index 1dc35f2..dc32e83 100644 --- a/chrome/browser/ui/views/app_list/linux/app_list_service_linux.h +++ b/chrome/browser/ui/views/app_list/linux/app_list_service_linux.h @@ -19,7 +19,7 @@ class AppListServiceLinux : public AppListServiceViews, static AppListServiceLinux* GetInstance(); - // AppListServiceImpl overrides: + // AppListService overrides: virtual void CreateShortcut() OVERRIDE; // app_list::AppListViewObserver overrides: diff --git a/chrome/browser/ui/views/app_list/win/app_list_service_win.h b/chrome/browser/ui/views/app_list/win/app_list_service_win.h index 12b09b9..290b2f5 100644 --- a/chrome/browser/ui/views/app_list/win/app_list_service_win.h +++ b/chrome/browser/ui/views/app_list/win/app_list_service_win.h @@ -24,8 +24,6 @@ class AppListServiceWin : public AppListServiceViews { virtual void HandleFirstRun() OVERRIDE; virtual void Init(Profile* initial_profile) OVERRIDE; virtual void ShowForProfile(Profile* requested_profile) OVERRIDE; - - // AppListServiceImpl overrides: virtual void CreateShortcut() OVERRIDE; private: diff --git a/chrome/browser/web_applications/web_app.cc b/chrome/browser/web_applications/web_app.cc index e594589..67d3fbe 100644 --- a/chrome/browser/web_applications/web_app.cc +++ b/chrome/browser/web_applications/web_app.cc @@ -44,9 +44,6 @@ using content::BrowserThread; namespace { -typedef base::Callback<void(const web_app::ShortcutInfo&, - const extensions::FileHandlersInfo&)> InfoCallback; - #if defined(OS_MACOSX) const int kDesiredSizes[] = {16, 32, 128, 256, 512}; const size_t kNumDesiredSizes = arraysize(kDesiredSizes); @@ -107,7 +104,7 @@ void UpdateAllShortcutsForShortcutInfo( void OnImageLoaded(web_app::ShortcutInfo shortcut_info, extensions::FileHandlersInfo file_handlers_info, - InfoCallback callback, + web_app::InfoCallback callback, const gfx::ImageFamily& image_family) { // If the image failed to load (e.g. if the resource being loaded was empty) // use the standard application icon. @@ -130,6 +127,27 @@ void OnImageLoaded(web_app::ShortcutInfo shortcut_info, callback.Run(shortcut_info, file_handlers_info); } +void IgnoreFileHandlersInfo( + const web_app::ShortcutInfoCallback& shortcut_info_callback, + const web_app::ShortcutInfo& shortcut_info, + const extensions::FileHandlersInfo& file_handlers_info) { + shortcut_info_callback.Run(shortcut_info); +} + +} // namespace + +namespace web_app { + +// The following string is used to build the directory name for +// shortcuts to chrome applications (the kind which are installed +// from a CRX). Application shortcuts to URLs use the {host}_{path} +// for the name of this directory. Hosts can't include an underscore. +// By starting this string with an underscore, we ensure that there +// are no naming conflicts. +static const char kCrxAppPrefix[] = "_crx_"; + +namespace internals { + void GetInfoForApp(const extensions::Extension* extension, Profile* profile, const InfoCallback& callback) { @@ -185,27 +203,6 @@ void GetInfoForApp(const extensions::Extension* extension, base::Bind(&OnImageLoaded, shortcut_info, file_handlers_info, callback)); } -void IgnoreFileHandlersInfo( - const web_app::ShortcutInfoCallback& shortcut_info_callback, - const web_app::ShortcutInfo& shortcut_info, - const extensions::FileHandlersInfo& file_handlers_info) { - shortcut_info_callback.Run(shortcut_info); -} - -} // namespace - -namespace web_app { - -// The following string is used to build the directory name for -// shortcuts to chrome applications (the kind which are installed -// from a CRX). Application shortcuts to URLs use the {host}_{path} -// for the name of this directory. Hosts can't include an underscore. -// By starting this string with an underscore, we ensure that there -// are no naming conflicts. -static const char* kCrxAppPrefix = "_crx_"; - -namespace internals { - base::FilePath GetSanitizedFileName(const base::string16& name) { #if defined(OS_WIN) base::string16 file_name = name; @@ -286,9 +283,8 @@ ShortcutInfo ShortcutInfoForExtensionAndProfile( void UpdateShortcutInfoAndIconForApp(const extensions::Extension* extension, Profile* profile, const ShortcutInfoCallback& callback) { - GetInfoForApp(extension, - profile, - base::Bind(&IgnoreFileHandlersInfo, callback)); + web_app::internals::GetInfoForApp( + extension, profile, base::Bind(&IgnoreFileHandlersInfo, callback)); } bool ShouldCreateShortcutFor(Profile* profile, @@ -383,9 +379,8 @@ void CreateShortcuts(ShortcutCreationReason reason, if (!ShouldCreateShortcutFor(profile, app)) return; - GetInfoForApp(app, - profile, - base::Bind(&CreateShortcutsWithInfo, reason, locations)); + internals::GetInfoForApp( + app, profile, base::Bind(&CreateShortcutsWithInfo, reason, locations)); } void DeleteAllShortcuts(Profile* profile, const extensions::Extension* app) { @@ -405,9 +400,10 @@ void UpdateAllShortcuts(const base::string16& old_app_title, const extensions::Extension* app) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - GetInfoForApp(app, - profile, - base::Bind(&UpdateAllShortcutsForShortcutInfo, old_app_title)); + internals::GetInfoForApp( + app, + profile, + base::Bind(&UpdateAllShortcutsForShortcutInfo, old_app_title)); } bool IsValidUrl(const GURL& url) { diff --git a/chrome/browser/web_applications/web_app.h b/chrome/browser/web_applications/web_app.h index 79487681..c4f5eb2 100644 --- a/chrome/browser/web_applications/web_app.h +++ b/chrome/browser/web_applications/web_app.h @@ -96,6 +96,11 @@ enum ShortcutCreationReason { SHORTCUT_CREATION_AUTOMATED, }; +// Called by GetInfoForApp after fetching the ShortcutInfo and FileHandlersInfo. +typedef base::Callback<void(const ShortcutInfo&, + const extensions::FileHandlersInfo&)> InfoCallback; + +// Called by UpdateShortcutInfoAndIconForApp after loading the icon. typedef base::Callback<void(const ShortcutInfo&)> ShortcutInfoCallback; // Extracts shortcut info of the given WebContents. @@ -197,6 +202,11 @@ std::string GetWMClassFromAppName(std::string app_name); namespace internals { +// Loads relevant info structs for the app and calls |callback|. +void GetInfoForApp(const extensions::Extension* extension, + Profile* profile, + const InfoCallback& callback); + #if defined(OS_WIN) // Returns the Windows user-level shortcut paths that are specified in // |creation_locations|. diff --git a/chrome/browser/web_applications/web_app_mac.h b/chrome/browser/web_applications/web_app_mac.h index a0a8b20..7c2ff41 100644 --- a/chrome/browser/web_applications/web_app_mac.h +++ b/chrome/browser/web_applications/web_app_mac.h @@ -14,6 +14,10 @@ #include "chrome/browser/web_applications/web_app.h" #include "extensions/common/manifest_handlers/file_handler_info.h" +namespace base { +class CommandLine; +} + // Whether to enable update and launch of app shims in tests. (Normally shims // are never created or launched in tests). Note that update only creates // internal shim bundles, i.e. it does not create new shims in ~/Applications. @@ -28,6 +32,9 @@ base::FilePath GetAppInstallPath(const ShortcutInfo& shortcut_info); // If necessary, launch the shortcut for an app. void MaybeLaunchShortcut(const ShortcutInfo& shortcut_info); +// Rebuild the shortcut and relaunch it. +bool MaybeRebuildShortcut(const base::CommandLine& command_line); + // Creates a shortcut for a web application. The shortcut is a stub app // that simply loads the browser framework and runs the given app. class WebAppShortcutCreator { diff --git a/chrome/browser/web_applications/web_app_mac.mm b/chrome/browser/web_applications/web_app_mac.mm index b46170c..02f3f0d 100644 --- a/chrome/browser/web_applications/web_app_mac.mm +++ b/chrome/browser/web_applications/web_app_mac.mm @@ -20,14 +20,17 @@ #include "base/process/process_handle.h" #include "base/strings/string16.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "base/strings/sys_string_conversions.h" #include "base/strings/utf_string_conversions.h" +#include "chrome/browser/browser_process.h" #import "chrome/browser/mac/dock.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/shell_integration.h" +#include "chrome/browser/ui/app_list/app_list_service.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" @@ -214,8 +217,8 @@ bool HasSameUserDataDir(const base::FilePath& bundle_path) { true /* case_sensitive */); } -void LaunchShimOnFileThread( - const web_app::ShortcutInfo& shortcut_info) { +void LaunchShimOnFileThread(const web_app::ShortcutInfo& shortcut_info, + bool launched_after_rebuild) { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); base::FilePath shim_path = web_app::GetAppInstallPath(shortcut_info); @@ -236,6 +239,8 @@ void LaunchShimOnFileThread( command_line.AppendSwitchASCII( app_mode::kLaunchedByChromeProcessId, base::IntToString(base::GetCurrentProcId())); + if (launched_after_rebuild) + command_line.AppendSwitch(app_mode::kLaunchedAfterRebuild); // Launch without activating (kLSLaunchDontSwitch). base::mac::OpenApplicationWithPath( shim_path, command_line, kLSLaunchDefaults | kLSLaunchDontSwitch, NULL); @@ -246,6 +251,53 @@ base::FilePath GetAppLoaderPath() { base::mac::NSToCFCast(@"app_mode_loader.app")); } +void UpdateAndLaunchShimOnFileThread( + const web_app::ShortcutInfo& shortcut_info, + const extensions::FileHandlersInfo& file_handlers_info) { + base::FilePath shortcut_data_dir = web_app::GetWebAppDataDirectory( + shortcut_info.profile_path, shortcut_info.extension_id, GURL()); + web_app::internals::UpdatePlatformShortcuts( + shortcut_data_dir, base::string16(), shortcut_info, file_handlers_info); + LaunchShimOnFileThread(shortcut_info, true); +} + +void UpdateAndLaunchShim( + const web_app::ShortcutInfo& shortcut_info, + const extensions::FileHandlersInfo& file_handlers_info) { + content::BrowserThread::PostTask( + content::BrowserThread::FILE, + FROM_HERE, + base::Bind( + &UpdateAndLaunchShimOnFileThread, shortcut_info, file_handlers_info)); +} + +void RebuildAppAndLaunch(const web_app::ShortcutInfo& shortcut_info) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (shortcut_info.extension_id == app_mode::kAppListModeId) { + AppListService* app_list_service = + AppListService::Get(chrome::HOST_DESKTOP_TYPE_NATIVE); + app_list_service->CreateShortcut(); + app_list_service->Show(); + return; + } + + ProfileManager* profile_manager = g_browser_process->profile_manager(); + Profile* profile = + profile_manager->GetProfileByPath(shortcut_info.profile_path); + if (!profile || !profile_manager->IsValidProfile(profile)) + return; + + extensions::ExtensionRegistry* registry = + extensions::ExtensionRegistry::Get(profile); + const extensions::Extension* extension = registry->GetExtensionById( + shortcut_info.extension_id, extensions::ExtensionRegistry::ENABLED); + if (!extension || !extension->is_platform_app()) + return; + + web_app::internals::GetInfoForApp( + extension, profile, base::Bind(&UpdateAndLaunchShim)); +} + base::FilePath GetLocalizableAppShortcutsSubdirName() { static const char kChromiumAppDirName[] = "Chromium Apps.localized"; static const char kChromeAppDirName[] = "Chrome Apps.localized"; @@ -875,8 +927,22 @@ void MaybeLaunchShortcut(const ShortcutInfo& shortcut_info) { } content::BrowserThread::PostTask( - content::BrowserThread::FILE, FROM_HERE, - base::Bind(&LaunchShimOnFileThread, shortcut_info)); + content::BrowserThread::FILE, + FROM_HERE, + base::Bind(&LaunchShimOnFileThread, shortcut_info, false)); +} + +bool MaybeRebuildShortcut(const CommandLine& command_line) { + if (!command_line.HasSwitch(app_mode::kAppShimError)) + return false; + + base::PostTaskAndReplyWithResult( + content::BrowserThread::GetBlockingPool(), + FROM_HERE, + base::Bind(&BuildShortcutInfoFromBundle, + command_line.GetSwitchValuePath(app_mode::kAppShimError)), + base::Bind(&RebuildAppAndLaunch)); + return true; } // Called when the app's ShortcutInfo (with icon) is loaded when creating app diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 19609cc..6cecc30 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -286,7 +286,10 @@ 'target_name': 'app_mode_app', 'type': 'executable', 'mac_bundle' : 1, - 'variables': { 'enable_wexit_time_destructors': 1, }, + 'variables': { + 'enable_wexit_time_destructors': 1, + 'mac_real_dsym': 1, + }, 'product_name': 'app_mode_loader', 'dependencies': [ 'app_mode_app_support', diff --git a/chrome/common/mac/app_mode_chrome_locator.h b/chrome/common/mac/app_mode_chrome_locator.h index 1b260d2..b608e9c 100644 --- a/chrome/common/mac/app_mode_chrome_locator.h +++ b/chrome/common/mac/app_mode_chrome_locator.h @@ -22,12 +22,14 @@ namespace app_mode { bool FindBundleById(NSString* bundle_id, base::FilePath* out_bundle); // Given the path to the Chrome bundle, read the following information: +// |executable_path| - Path to the Chrome executable. // |raw_version_str| - Chrome version. // |version_path| - |chrome_bundle|/Contents/Versions/|raw_version_str|/ // |framework_shlib_path| - Path to the chrome framework's shared library (not // the framework directory). // Returns true if all information read succesfuly, false otherwise. bool GetChromeBundleInfo(const base::FilePath& chrome_bundle, + base::FilePath* executable_path, base::string16* raw_version_str, base::FilePath* version_path, base::FilePath* framework_shlib_path); diff --git a/chrome/common/mac/app_mode_chrome_locator.mm b/chrome/common/mac/app_mode_chrome_locator.mm index ac62380..3cd5302 100644 --- a/chrome/common/mac/app_mode_chrome_locator.mm +++ b/chrome/common/mac/app_mode_chrome_locator.mm @@ -25,6 +25,7 @@ bool FindBundleById(NSString* bundle_id, base::FilePath* out_bundle) { } bool GetChromeBundleInfo(const base::FilePath& chrome_bundle, + base::FilePath* executable_path, base::string16* raw_version_str, base::FilePath* version_path, base::FilePath* framework_shlib_path) { @@ -57,19 +58,25 @@ bool GetChromeBundleInfo(const base::FilePath& chrome_bundle, NSString* cr_bundle_exe = ObjCCast<NSString>( [cr_bundle objectForInfoDictionaryKey:@"CFBundleExecutable"]); + // Essentially we want chrome::kFrameworkName which looks like + // "$PRODUCT_STRING Framework.framework". The library itself is at + // "$PRODUCT_STRING Framework.framework/$PRODUCT_STRING Framework". Note that + // $PRODUCT_STRING is not |cr_bundle_exe| because in Canary the framework is + // still called "Google Chrome Framework". + // However, we want the shims to be agnostic to distribution and operate based + // on the data in their plist, so encode the framework names here. + NSDictionary* framework_for_exe = @{ + @"Chromium": @"Chromium", + @"Google Chrome": @"Google Chrome", + @"Google Chrome Canary": @"Google Chrome", + }; + NSString* framework_name = [framework_for_exe objectForKey:cr_bundle_exe]; NSString* cr_framework_shlib_path = [cr_versioned_path stringByAppendingPathComponent: - base::SysUTF8ToNSString(chrome::kFrameworkName)]; - // chrome::kFrameworkName looks like "$PRODUCT_STRING Framework.framework". - // The library itself is at - // "$PRODUCT_STRING Framework.framework/$PRODUCT_STRING Framework", so we cut - // off the .framework extension here and append it to the path. - // It's important to build the path to the framework this way because - // in Canary the framework is still called "Google Chrome Framework". + [framework_name stringByAppendingString:@" Framework.framework"]]; cr_framework_shlib_path = [cr_framework_shlib_path stringByAppendingPathComponent: - [base::SysUTF8ToNSString(chrome::kFrameworkName) - stringByDeletingPathExtension]]; + [framework_name stringByAppendingString:@" Framework"]]; if (!cr_bundle_exe || !cr_framework_shlib_path) return false; @@ -82,6 +89,7 @@ bool GetChromeBundleInfo(const base::FilePath& chrome_bundle, return false; // Everything OK, copy output parameters. + *executable_path = base::mac::NSStringToFilePath([cr_bundle executablePath]); *raw_version_str = base::SysNSStringToUTF16(cr_version); *version_path = base::mac::NSStringToFilePath(cr_versioned_path); *framework_shlib_path = diff --git a/chrome/common/mac/app_mode_chrome_locator_unittest.mm b/chrome/common/mac/app_mode_chrome_locator_unittest.mm index 50e98bf..ecaed7d 100644 --- a/chrome/common/mac/app_mode_chrome_locator_unittest.mm +++ b/chrome/common/mac/app_mode_chrome_locator_unittest.mm @@ -43,11 +43,12 @@ TEST(ChromeLocatorTest, GetNonExistentBundleInfo) { base::ScopedTempDir temp_dir; ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); + base::FilePath executable_path; base::string16 raw_version; base::FilePath version_path; base::FilePath framework_path; EXPECT_FALSE(app_mode::GetChromeBundleInfo(temp_dir.path(), - &raw_version, &version_path, &framework_path)); + &executable_path, &raw_version, &version_path, &framework_path)); } TEST(ChromeLocatorTest, GetChromeBundleInfo) { @@ -57,11 +58,13 @@ TEST(ChromeLocatorTest, GetChromeBundleInfo) { GetChromeBundlePath(&chrome_bundle_path); ASSERT_TRUE(base::DirectoryExists(chrome_bundle_path)); + base::FilePath executable_path; base::string16 raw_version; base::FilePath version_path; base::FilePath framework_path; EXPECT_TRUE(GetChromeBundleInfo(chrome_bundle_path, - &raw_version, &version_path, &framework_path)); + &executable_path, &raw_version, &version_path, &framework_path)); + EXPECT_TRUE(base::PathExists(executable_path)); EXPECT_GT(raw_version.size(), 0U); EXPECT_TRUE(base::DirectoryExists(version_path)); EXPECT_TRUE(base::PathExists(framework_path)); diff --git a/chrome/common/mac/app_mode_common.h b/chrome/common/mac/app_mode_common.h index 4d686da..670b883 100644 --- a/chrome/common/mac/app_mode_common.h +++ b/chrome/common/mac/app_mode_common.h @@ -41,6 +41,10 @@ extern const char kLaunchedByChromeProcessId[]; // launch Chrome. extern const char kLaunchedForTest[]; +// Indicates to the shim that this Chrome has rebuilt it once already, i.e. if +// it fails to launch again, don't trigger another rebuild. +extern const char kLaunchedAfterRebuild[]; + // Path to an app shim bundle. Indicates to Chrome that this shim attempted to // launch but failed. extern const char kAppShimError[]; @@ -98,7 +102,7 @@ extern NSString* const kShortcutBrowserBundleIDPlaceholder; // Current major/minor version numbers of |ChromeAppModeInfo| (defined below). const unsigned kCurrentChromeAppModeInfoMajorVersion = 1; -const unsigned kCurrentChromeAppModeInfoMinorVersion = 1; +const unsigned kCurrentChromeAppModeInfoMinorVersion = 2; // The structure used to pass information from the app mode loader to the // (browser) framework. This is versioned using major and minor version numbers, diff --git a/chrome/common/mac/app_mode_common.mm b/chrome/common/mac/app_mode_common.mm index 9996090..bb63ed4 100644 --- a/chrome/common/mac/app_mode_common.mm +++ b/chrome/common/mac/app_mode_common.mm @@ -15,6 +15,7 @@ const char kAppListModeId[] = "app_list"; const char kLaunchedByChromeProcessId[] = "launched-by-chrome-process-id"; const char kLaunchedForTest[] = "launched-for-test"; +const char kLaunchedAfterRebuild[] = "launched-after-rebuild"; const char kAppShimError[] = "app-shim-error"; |