diff options
author | mpearson@chromium.org <mpearson@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-25 22:11:23 +0000 |
---|---|---|
committer | mpearson@chromium.org <mpearson@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-25 22:11:23 +0000 |
commit | efde268d313a402ff730906cc30719d71a7e07b0 (patch) | |
tree | 5998ac359a448c7d0541ff6d1d09a73272f938e3 | |
parent | 3aa54ea723c1f673d9ba184465f42f3555719970 (diff) | |
download | chromium_src-efde268d313a402ff730906cc30719d71a7e07b0.zip chromium_src-efde268d313a402ff730906cc30719d71a7e07b0.tar.gz chromium_src-efde268d313a402ff730906cc30719d71a7e07b0.tar.bz2 |
Revert 285661 "Remove some dead app host code."
Causes compile failures on official builders:
e.g.,
http://build.chromium.org/p/chromium.chrome/builders/Google%20Chrome%20Win/
FAILED: ninja -t msvc -e environment.x64 -- c:\b\build\goma/gomacc "c:\b\depot_tools\win_toolchain\vs2013_files\VC\bin\amd64\cl.exe" /nologo /showIncludes /FC @obj\chrome\installer\util\installer_util_nacl_win64.chrome_app_host_distribution.obj.rsp /c ..\..\chrome\installer\util\chrome_app_host_distribution.cc /Foobj\chrome\installer\util\installer_util_nacl_win64.chrome_app_host_distribution.obj /Fdobj\chrome\installer_util_nacl_win64.cc.pdb
c:\b\build\slave\google-chrome-rel-win\build\src\chrome\installer\util\chrome_app_host_distribution.cc(126) :error C2065: 'kChromeAppHostGuid' : undeclared identifier
ninja: build stopped: subcommand failed.
> Remove some dead app host code.
>
> app_host.exe was removed in r220555. This change removes some dead code
> that was left behind. Specifically:
> - chrome_launcher_support no longer exposes any methods related to the
> AppHost.
> - Chrome's uninstall prompt no longer has a special case to handle
> suppressing the "delete your profile" checkbox.
> - Chrome and its installer no longer have a dependency on
> launcher_support.
> - The installer no longer supports installing items from the webstore.
> - GetUntrustedDataValue no longer has consumers and is gone.
>
> BUG=297647
> R=benwells@chromium.org,huangs@chromium.org,gab@chromium.org
>
> Review URL: https://codereview.chromium.org/422453004
TBR=grt@chromium.org
Review URL: https://codereview.chromium.org/422593002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@285706 0039d316-1c4b-4281-b951-d872f2087c98
25 files changed, 394 insertions, 48 deletions
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index ae62e2d..2395bec 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn @@ -505,6 +505,7 @@ static_library("browser") { "//third_party/wtl", #"chrome_process_finder", TODO(GYP) #"installer_util_strings", TODO(GYP) + #"launcher_support", TODO(GYP) #"../chrome/chrome.gyp:chrome_version_header", TODO(GYP) #"../chrome_elf/chrome_elf.gyp:chrome_elf", TODO(GYP) #"../chrome_elf/chrome_elf.gyp:chrome_elf_constants", TODO(GYP) diff --git a/chrome/browser/chrome_browser_main_win.cc b/chrome/browser/chrome_browser_main_win.cc index 0912b3f..c03597d 100644 --- a/chrome/browser/chrome_browser_main_win.cc +++ b/chrome/browser/chrome_browser_main_win.cc @@ -38,6 +38,7 @@ #include "chrome/common/chrome_switches.h" #include "chrome/common/chrome_version_info.h" #include "chrome/common/env_vars.h" +#include "chrome/installer/launcher_support/chrome_launcher_support.h" #include "chrome/installer/util/browser_distribution.h" #include "chrome/installer/util/helper.h" #include "chrome/installer/util/install_util.h" @@ -118,7 +119,9 @@ int DoUninstallTasks(bool chrome_still_running) { ShowCloseBrowserFirstMessageBox(); return chrome::RESULT_CODE_UNINSTALL_CHROME_ALIVE; } - int result = chrome::ShowUninstallBrowserPrompt(); + int result = chrome::ShowUninstallBrowserPrompt( + !chrome_launcher_support::IsAppLauncherPresent()); + // Don't offer to delete the profile if the App Launcher is also installed. if (browser_util::IsBrowserAlreadyRunning()) { ShowCloseBrowserFirstMessageBox(); return chrome::RESULT_CODE_UNINSTALL_CHROME_ALIVE; diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn index a8a0cab..ec27dc8 100644 --- a/chrome/browser/extensions/BUILD.gn +++ b/chrome/browser/extensions/BUILD.gn @@ -196,6 +196,7 @@ static_library("extensions") { deps += [ "//third_party/iaccessible2", "//third_party/isimpledom", + #'launcher_support', TODO(GYP) ] } else if (!is_chromeos) { sources += [ "api/system_display/display_info_provider_aura.cc" ] diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 0960e3b..5789a58 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn @@ -340,6 +340,7 @@ static_library("ui") { "//ui/views", "//ui/views/controls/webview", #'installer_util_strings', TODO(GYP) + #'launcher_support', TODO(GYP) #'metro_utils', TODO(GYP) #'../google_update/google_update.gyp:google_update', TODO(GYP) ] diff --git a/chrome/browser/ui/uninstall_browser_prompt.h b/chrome/browser/ui/uninstall_browser_prompt.h index 15ce952..eb3c5bc 100644 --- a/chrome/browser/ui/uninstall_browser_prompt.h +++ b/chrome/browser/ui/uninstall_browser_prompt.h @@ -11,7 +11,7 @@ namespace chrome { // content::RESULT_CODE_NORMAL_EXIT, // chrome::RESULT_CODE_UNINSTALL_DELETE_PROFILE or // chrome::RESULT_CODE_UNINSTALL_USER_CANCEL. -int ShowUninstallBrowserPrompt(); +int ShowUninstallBrowserPrompt(bool show_delete_profile); } // namespace chrome diff --git a/chrome/browser/ui/views/app_list/win/app_list_service_win.cc b/chrome/browser/ui/views/app_list/win/app_list_service_win.cc index fffb424..90cc609 100644 --- a/chrome/browser/ui/views/app_list/win/app_list_service_win.cc +++ b/chrome/browser/ui/views/app_list/win/app_list_service_win.cc @@ -41,10 +41,10 @@ #include "ui/base/win/shell.h" #if defined(GOOGLE_CHROME_BUILD) +#include "chrome/installer/launcher_support/chrome_launcher_support.h" #include "chrome/installer/util/google_update_settings.h" #include "chrome/installer/util/install_util.h" #include "chrome/installer/util/updating_app_registration_data.h" -#include "chrome/installer/util/util_constants.h" #endif // GOOGLE_CHROME_BUILD // static @@ -147,7 +147,7 @@ void SetDidRunForNDayActiveStats() { if (chrome_binaries_dist && InstallUtil::IsMultiInstall(chrome_binaries_dist, system_install)) { UpdatingAppRegistrationData app_launcher_reg_data( - installer::kAppLauncherGuid); + chrome_launcher_support::kAppLauncherGuid); GoogleUpdateSettings::UpdateDidRunStateForApp( app_launcher_reg_data, true /* did_run */); } diff --git a/chrome/browser/ui/views/uninstall_view.cc b/chrome/browser/ui/views/uninstall_view.cc index 4c04281..bbd856d 100644 --- a/chrome/browser/ui/views/uninstall_view.cc +++ b/chrome/browser/ui/views/uninstall_view.cc @@ -23,8 +23,10 @@ #include "ui/views/widget/widget.h" UninstallView::UninstallView(int* user_selection, - const base::Closure& quit_closure) + const base::Closure& quit_closure, + bool show_delete_profile) : confirm_label_(NULL), + show_delete_profile_(show_delete_profile), delete_profile_(NULL), change_default_browser_(NULL), browsers_combo_(NULL), @@ -62,15 +64,17 @@ void UninstallView::SetupControls() { layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing); // The "delete profile" check box. - ++column_set_id; - column_set = layout->AddColumnSet(column_set_id); - column_set->AddPaddingColumn(0, views::kPanelHorizIndentation); - column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0, - GridLayout::USE_PREF, 0, 0); - layout->StartRow(0, column_set_id); - delete_profile_ = new views::Checkbox( - l10n_util::GetStringUTF16(IDS_UNINSTALL_DELETE_PROFILE)); - layout->AddView(delete_profile_); + if (show_delete_profile_) { + ++column_set_id; + column_set = layout->AddColumnSet(column_set_id); + column_set->AddPaddingColumn(0, views::kPanelHorizIndentation); + column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0, + GridLayout::USE_PREF, 0, 0); + layout->StartRow(0, column_set_id); + delete_profile_ = new views::Checkbox( + l10n_util::GetStringUTF16(IDS_UNINSTALL_DELETE_PROFILE)); + layout->AddView(delete_profile_); + } // Set default browser combo box. If the default should not or cannot be // changed, widgets are not shown. We assume here that if Chrome cannot @@ -111,7 +115,7 @@ void UninstallView::SetupControls() { bool UninstallView::Accept() { user_selection_ = content::RESULT_CODE_NORMAL_EXIT; - if (delete_profile_->checked()) + if (show_delete_profile_ && delete_profile_->checked()) user_selection_ = chrome::RESULT_CODE_UNINSTALL_DELETE_PROFILE; if (change_default_browser_ && change_default_browser_->checked()) { BrowsersMap::const_iterator i = browsers_->begin(); @@ -163,7 +167,7 @@ base::string16 UninstallView::GetItemAt(int index) { namespace chrome { -int ShowUninstallBrowserPrompt() { +int ShowUninstallBrowserPrompt(bool show_delete_profile) { DCHECK(base::MessageLoopForUI::IsCurrent()); int result = content::RESULT_CODE_NORMAL_EXIT; @@ -178,7 +182,8 @@ int ShowUninstallBrowserPrompt() { base::RunLoop run_loop; UninstallView* view = new UninstallView(&result, - run_loop.QuitClosure()); + run_loop.QuitClosure(), + show_delete_profile); views::DialogDelegate::CreateDialogWidget(view, NULL, NULL)->Show(); run_loop.Run(); return result; diff --git a/chrome/browser/ui/views/uninstall_view.h b/chrome/browser/ui/views/uninstall_view.h index c50a3cd..8fc784d 100644 --- a/chrome/browser/ui/views/uninstall_view.h +++ b/chrome/browser/ui/views/uninstall_view.h @@ -29,7 +29,8 @@ class UninstallView : public views::ButtonListener, public ui::ComboboxModel { public: explicit UninstallView(int* user_selection, - const base::Closure& quit_closure); + const base::Closure& quit_closure, + bool show_delete_profile); virtual ~UninstallView(); // Overridden form views::ButtonListener. @@ -56,6 +57,7 @@ class UninstallView : public views::ButtonListener, void SetupControls(); views::Label* confirm_label_; + bool show_delete_profile_; views::Checkbox* delete_profile_; views::Checkbox* change_default_browser_; views::Combobox* browsers_combo_; diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index b5f3886..5093cf4 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -3332,6 +3332,7 @@ 'dependencies': [ 'chrome_process_finder', 'installer_util_strings', + 'launcher_support', '../chrome/chrome.gyp:chrome_version_header', '../chrome_elf/chrome_elf.gyp:chrome_elf', '../chrome_elf/chrome_elf.gyp:chrome_elf_constants', diff --git a/chrome/chrome_browser_extensions.gypi b/chrome/chrome_browser_extensions.gypi index ee0c223..d84973a 100644 --- a/chrome/chrome_browser_extensions.gypi +++ b/chrome/chrome_browser_extensions.gypi @@ -1134,6 +1134,7 @@ }], ['OS=="win"', { 'dependencies': [ + 'launcher_support', '../third_party/iaccessible2/iaccessible2.gyp:iaccessible2', '../third_party/isimpledom/isimpledom.gyp:isimpledom', ], diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi index b467883..ad12cf1 100644 --- a/chrome/chrome_browser_ui.gypi +++ b/chrome/chrome_browser_ui.gypi @@ -2846,6 +2846,7 @@ ], 'dependencies': [ 'installer_util_strings', + 'launcher_support', 'metro_utils', '../google_update/google_update.gyp:google_update', '../third_party/iaccessible2/iaccessible2.gyp:iaccessible2', diff --git a/chrome/chrome_installer.gypi b/chrome/chrome_installer.gypi index 8281e21..ee3754b 100644 --- a/chrome/chrome_installer.gypi +++ b/chrome/chrome_installer.gypi @@ -216,6 +216,7 @@ 'dependencies': [ 'installer_util', 'installer_util_strings', + 'launcher_support', '../base/base.gyp:base', '../breakpad/breakpad.gyp:breakpad_handler', '../chrome/common_constants.gyp:common_constants', @@ -330,6 +331,7 @@ 'dependencies': [ 'installer_util', 'installer_util_strings', + 'launcher_support', '../base/base.gyp:base', '../base/base.gyp:base_i18n', '../base/base.gyp:test_support_base', diff --git a/chrome/installer/launcher_support/chrome_launcher_support.cc b/chrome/installer/launcher_support/chrome_launcher_support.cc index 9e9ba92..8e5b6a5 100644 --- a/chrome/installer/launcher_support/chrome_launcher_support.cc +++ b/chrome/installer/launcher_support/chrome_launcher_support.cc @@ -5,12 +5,20 @@ #include "chrome/installer/launcher_support/chrome_launcher_support.h" #include <windows.h> +#include <tchar.h> +#include "base/command_line.h" #include "base/file_util.h" #include "base/files/file_path.h" +#include "base/logging.h" +#include "base/process/launch.h" #include "base/strings/string16.h" #include "base/win/registry.h" +#ifndef OFFICIAL_BUILD +#include "base/path_service.h" +#endif + namespace chrome_launcher_support { namespace { @@ -18,6 +26,8 @@ namespace { // TODO(huangs) Refactor the constants: http://crbug.com/148538 const wchar_t kGoogleRegClientStateKey[] = L"Software\\Google\\Update\\ClientState"; +const wchar_t kGoogleRegClientsKey[] = L"Software\\Google\\Update\\Clients"; +const wchar_t kRegVersionField[] = L"pv"; // Copied from chrome_appid.cc. const wchar_t kBinariesAppGuid[] = L"{4DC8B4CA-1BDA-483e-B5FA-D3C12E15B62D}"; @@ -25,8 +35,14 @@ const wchar_t kBinariesAppGuid[] = L"{4DC8B4CA-1BDA-483e-B5FA-D3C12E15B62D}"; // Copied from google_chrome_distribution.cc. const wchar_t kBrowserAppGuid[] = L"{8A69D345-D564-463c-AFF1-A69D9E530F96}"; +// Copied frome google_chrome_sxs_distribution.cc. +const wchar_t kSxSBrowserAppGuid[] = L"{4ea16ac7-fd5a-47c3-875b-dbf4a2008c20}"; + // Copied from util_constants.cc. +const wchar_t kChromeAppHostExe[] = L"app_host.exe"; +const char kChromeAppLauncher[] = "app-launcher"; const wchar_t kChromeExe[] = L"chrome.exe"; +const wchar_t kUninstallArgumentsField[] = L"UninstallArguments"; const wchar_t kUninstallStringField[] = L"UninstallString"; // Reads a string value from the specified product's "ClientState" registry key. @@ -50,6 +66,33 @@ bool GetClientStateValue(InstallationLevel level, return false; } +// Determines whether the specified product has a key in "Clients". This +// indicates whether the product is installed at the given level. +bool IsProductInstalled(InstallationLevel level, const wchar_t* app_guid) { + HKEY root_key = (level == USER_LEVEL_INSTALLATION) ? + HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE; + base::string16 subkey(kGoogleRegClientsKey); + subkey.append(1, L'\\').append(app_guid); + base::win::RegKey reg_key; + // Google Update always uses 32bit hive. + return reg_key.Open(root_key, subkey.c_str(), + KEY_QUERY_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS && + reg_key.HasValue(kRegVersionField); +} + +bool IsAppLauncherEnabledAtLevel(InstallationLevel level) { + base::string16 uninstall_arguments; + if (GetClientStateValue(level, + kAppLauncherGuid, + kUninstallArgumentsField, + &uninstall_arguments)) { + return CommandLine::FromString(L"dummy.exe " + uninstall_arguments) + .HasSwitch(kChromeAppLauncher) && + !GetAppHostPathForInstallationLevel(level).empty(); + } + return false; +} + // Reads the path to setup.exe from the value "UninstallString" within the // specified product's "ClientState" registry key. Returns an empty FilePath if // an error occurs or the product is not installed at the specified level. @@ -64,22 +107,9 @@ base::FilePath GetSetupExeFromRegistry(InstallationLevel level, return base::FilePath(); } -// Returns the path to an existing setup.exe at the specified level, if it can -// be found via Omaha client state. -base::FilePath GetSetupExeForInstallationLevel(InstallationLevel level) { - // Look in the registry for Chrome Binaries first. - base::FilePath setup_exe_path( - GetSetupExeFromRegistry(level, kBinariesAppGuid)); - // If the above fails, look in the registry for Chrome next. - if (setup_exe_path.empty()) - setup_exe_path = GetSetupExeFromRegistry(level, kBrowserAppGuid); - // If we fail again, then setup_exe_path would be empty. - return setup_exe_path; -} - -// Returns the path to an installed |exe_file| (e.g. chrome.exe) at the -// specified level, given |setup_exe_path| from Omaha client state. Returns -// empty base::FilePath if none found, or if |setup_exe_path| is empty. +// Returns the path to an installed |exe_file| (e.g. chrome.exe, app_host.exe) +// at the specified level, given |setup_exe_path| from Omaha client state. +// Returns empty base::FilePath if none found, or if |setup_exe_path| is empty. base::FilePath FindExeRelativeToSetupExe(const base::FilePath setup_exe_path, const wchar_t* exe_file) { if (!setup_exe_path.empty()) { @@ -101,11 +131,52 @@ base::FilePath FindExeRelativeToSetupExe(const base::FilePath setup_exe_path, } // namespace +const wchar_t kAppLauncherGuid[] = L"{FDA71E6F-AC4C-4a00-8B70-9958A68906BF}"; + +void UninstallLegacyAppLauncher(InstallationLevel level) { + base::FilePath setup_exe(GetSetupExeFromRegistry(level, kAppLauncherGuid)); + if (setup_exe.empty()) + return; + base::string16 uninstall_arguments; + if (GetClientStateValue(level, + kAppLauncherGuid, + kUninstallArgumentsField, + &uninstall_arguments)) { + CommandLine uninstall_cmd = CommandLine::FromString( + L"\"" + setup_exe.value() + L"\" " + uninstall_arguments); + + VLOG(1) << "Uninstalling legacy app launcher with command line: " + << uninstall_cmd.GetCommandLineString(); + base::LaunchProcess(uninstall_cmd, base::LaunchOptions(), NULL); + } +} + +base::FilePath GetSetupExeForInstallationLevel(InstallationLevel level) { + // Look in the registry for Chrome Binaries first. + base::FilePath setup_exe_path( + GetSetupExeFromRegistry(level, kBinariesAppGuid)); + // If the above fails, look in the registry for Chrome next. + if (setup_exe_path.empty()) + setup_exe_path = GetSetupExeFromRegistry(level, kBrowserAppGuid); + // If we fail again, then setup_exe_path would be empty. + return setup_exe_path; +} + base::FilePath GetChromePathForInstallationLevel(InstallationLevel level) { return FindExeRelativeToSetupExe( GetSetupExeForInstallationLevel(level), kChromeExe); } +base::FilePath GetAppHostPathForInstallationLevel(InstallationLevel level) { + return FindExeRelativeToSetupExe( + GetSetupExeFromRegistry(level, kAppLauncherGuid), kChromeAppHostExe); +} + +base::FilePath GetChromeSxSPathForInstallationLevel(InstallationLevel level) { + return FindExeRelativeToSetupExe( + GetSetupExeFromRegistry(level, kSxSBrowserAppGuid), kChromeExe); +} + base::FilePath GetAnyChromePath() { base::FilePath chrome_path; if (chrome_path.empty()) @@ -115,4 +186,47 @@ base::FilePath GetAnyChromePath() { return chrome_path; } +base::FilePath GetAnyAppHostPath() { + base::FilePath app_host_path; + if (app_host_path.empty()) { + app_host_path = GetAppHostPathForInstallationLevel( + SYSTEM_LEVEL_INSTALLATION); + } + if (app_host_path.empty()) + app_host_path = GetAppHostPathForInstallationLevel(USER_LEVEL_INSTALLATION); + return app_host_path; +} + +base::FilePath GetAnyChromeSxSPath() { + base::FilePath path = + GetChromeSxSPathForInstallationLevel(USER_LEVEL_INSTALLATION); + if (path.empty()) + path = GetChromeSxSPathForInstallationLevel(SYSTEM_LEVEL_INSTALLATION); + return path; +} + +bool IsAppHostPresent() { + base::FilePath app_host_exe = GetAnyAppHostPath(); + return !app_host_exe.empty(); +} + +InstallationState GetAppLauncherInstallationState() { + if (IsAppLauncherEnabledAtLevel(SYSTEM_LEVEL_INSTALLATION)) + return INSTALLED_AT_SYSTEM_LEVEL; + + if (IsAppLauncherEnabledAtLevel(USER_LEVEL_INSTALLATION)) + return INSTALLED_AT_USER_LEVEL; + + return NOT_INSTALLED; +} + +bool IsAppLauncherPresent() { + return GetAppLauncherInstallationState() != NOT_INSTALLED; +} + +bool IsChromeBrowserPresent() { + return IsProductInstalled(USER_LEVEL_INSTALLATION, kBrowserAppGuid) || + IsProductInstalled(SYSTEM_LEVEL_INSTALLATION, kBrowserAppGuid); +} + } // namespace chrome_launcher_support diff --git a/chrome/installer/launcher_support/chrome_launcher_support.h b/chrome/installer/launcher_support/chrome_launcher_support.h index 9cf1479..f50ff28 100644 --- a/chrome/installer/launcher_support/chrome_launcher_support.h +++ b/chrome/installer/launcher_support/chrome_launcher_support.h @@ -16,18 +16,72 @@ enum InstallationLevel { SYSTEM_LEVEL_INSTALLATION, }; +enum InstallationState { + NOT_INSTALLED, + INSTALLED_AT_USER_LEVEL, + INSTALLED_AT_SYSTEM_LEVEL, +}; + +// The app GUID for Chrome App Launcher. +extern const wchar_t kAppLauncherGuid[]; + +// Returns the path to an existing setup.exe at the specified level, if it can +// be found via Omaha client state. +base::FilePath GetSetupExeForInstallationLevel(InstallationLevel level); + // Returns the path to an installed chrome.exe at the specified level, if it can // be found via Omaha client state. Prefers the installer from a multi-install, // but may also return that of a single-install of Chrome if no multi-install // exists. base::FilePath GetChromePathForInstallationLevel(InstallationLevel level); +// Returns the path to an installed app_host.exe at the specified level, if +// it can be found via Omaha client state. +base::FilePath GetAppHostPathForInstallationLevel(InstallationLevel level); + +// Returns the path to an installed SxS chrome.exe at the specified level, if +// it can be found via Omaha client state. +base::FilePath GetChromeSxSPathForInstallationLevel(InstallationLevel level); + // Returns the path to an installed chrome.exe, or an empty path. Prefers a // system-level installation to a user-level installation. Uses Omaha client // state to identify a Chrome installation location. // The file path returned (if any) is guaranteed to exist. base::FilePath GetAnyChromePath(); +// Returns the path to an installed app_host.exe, or an empty path. Prefers a +// system-level installation to a user-level installation. Uses Omaha client +// state to identify a App Host installation location. +// The file path returned (if any) is guaranteed to exist. +base::FilePath GetAnyAppHostPath(); + +// Returns the path to an installed SxS chrome.exe, or an empty path. Prefers a +// user-level installation to a system-level installation. Uses Omaha client +// state to identify a Chrome Canary installation location. +// The file path returned (if any) is guaranteed to exist. +base::FilePath GetAnyChromeSxSPath(); + +// Uninstalls the legacy app launcher by launching setup.exe with the uninstall +// arguments from the App Launcher ClientState registry key. The uninstall will +// run asynchronously. +void UninstallLegacyAppLauncher(InstallationLevel level); + +// Returns true if App Host is installed (system-level or user-level), +// or in the same directory as the current executable. +bool IsAppHostPresent(); + +// Returns the app launcher installation state. If the launcher is installed +// at both system level and user level, system level is returned. +InstallationState GetAppLauncherInstallationState(); + +// Returns true if App Launcher is installed (system-level or user-level). +bool IsAppLauncherPresent(); + +// Returns true if the Chrome browser is installed (system-level or user-level). +// If this is running in an official build, it will check if a non-canary build +// if installed. If it is not an official build, it will always return true. +bool IsChromeBrowserPresent(); + } // namespace chrome_launcher_support #endif // CHROME_INSTALLER_LAUNCHER_SUPPORT_CHROME_LAUNCHER_SUPPORT_H_ diff --git a/chrome/installer/setup/install.cc b/chrome/installer/setup/install.cc index 5ba2608..05e5b9b 100644 --- a/chrome/installer/setup/install.cc +++ b/chrome/installer/setup/install.cc @@ -10,12 +10,14 @@ #include <string> +#include "base/command_line.h" #include "base/file_util.h" #include "base/files/file_path.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/numerics/safe_conversions.h" #include "base/path_service.h" +#include "base/process/launch.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" @@ -23,6 +25,7 @@ #include "base/win/windows_version.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_switches.h" +#include "chrome/installer/launcher_support/chrome_launcher_support.h" #include "chrome/installer/setup/install_worker.h" #include "chrome/installer/setup/setup_constants.h" #include "chrome/installer/util/auto_launch_util.h" @@ -688,4 +691,15 @@ void HandleActiveSetupForBrowser(const base::FilePath& installation_root, chrome_exe, chrome, prefs, CURRENT_USER, install_operation); } +bool InstallFromWebstore(const std::string& app_code) { + base::FilePath app_host_path(chrome_launcher_support::GetAnyAppHostPath()); + if (app_host_path.empty()) + return false; + + CommandLine cmd(app_host_path); + cmd.AppendSwitchASCII(::switches::kInstallFromWebstore, app_code); + VLOG(1) << "App install command: " << cmd.GetCommandLineString(); + return base::LaunchProcess(cmd, base::LaunchOptions(), NULL); +} + } // namespace installer diff --git a/chrome/installer/setup/install.h b/chrome/installer/setup/install.h index 22f3c3d..a700b3c 100644 --- a/chrome/installer/setup/install.h +++ b/chrome/installer/setup/install.h @@ -132,6 +132,11 @@ void HandleActiveSetupForBrowser(const base::FilePath& installation_root, const Product& chrome, bool force); +// Launches app_host.exe to install content from web store (non-blocking). +// Returns true on successful execution (although successful installation +// is not guaranteed). +bool InstallFromWebstore(const std::string& app_code); + } // namespace installer #endif // CHROME_INSTALLER_SETUP_INSTALL_H_ diff --git a/chrome/installer/setup/setup_constants.cc b/chrome/installer/setup/setup_constants.cc index 77c03a6..10b8479 100644 --- a/chrome/installer/setup/setup_constants.cc +++ b/chrome/installer/setup/setup_constants.cc @@ -20,4 +20,8 @@ const wchar_t kInstallSourceChromeDir[] = L"Chrome-bin"; const wchar_t kMediaPlayerRegPath[] = L"Software\\Microsoft\\MediaPlayer\\ShimInclusionList"; +// Key names for values passed via the GoogleUpdateUntrustedData environment +// variable. +const char kInstallFromWebstore[] = "install-from-webstore"; + } // namespace installer diff --git a/chrome/installer/setup/setup_constants.h b/chrome/installer/setup/setup_constants.h index 9e146b8..376350a 100644 --- a/chrome/installer/setup/setup_constants.h +++ b/chrome/installer/setup/setup_constants.h @@ -20,6 +20,8 @@ extern const wchar_t kInstallSourceChromeDir[]; extern const wchar_t kMediaPlayerRegPath[]; +extern const char kInstallFromWebstore[]; + } // namespace installer #endif // CHROME_INSTALLER_SETUP_SETUP_CONSTANTS_H__ diff --git a/chrome/installer/setup/setup_main.cc b/chrome/installer/setup/setup_main.cc index eda79e5..c5b8c0ff 100644 --- a/chrome/installer/setup/setup_main.cc +++ b/chrome/installer/setup/setup_main.cc @@ -1639,6 +1639,16 @@ InstallStatus InstallProductsHelper( RemoveChromeLegacyRegistryKeys(chrome->distribution(), chrome_exe); } } + + if (prefs.install_chrome_app_launcher() && + InstallUtil::GetInstallReturnCode(install_status) == 0) { + std::string webstore_item(google_update::GetUntrustedDataValue( + kInstallFromWebstore)); + if (!webstore_item.empty()) { + bool success = InstallFromWebstore(webstore_item); + VLOG_IF(1, !success) << "Failed to launch app installation."; + } + } } } diff --git a/chrome/installer/setup/uninstall.cc b/chrome/installer/setup/uninstall.cc index ce02a20..146359f 100644 --- a/chrome/installer/setup/uninstall.cc +++ b/chrome/installer/setup/uninstall.cc @@ -26,6 +26,7 @@ #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_result_codes.h" +#include "chrome/installer/launcher_support/chrome_launcher_support.h" #include "chrome/installer/setup/install.h" #include "chrome/installer/setup/install_worker.h" #include "chrome/installer/setup/setup_constants.h" @@ -1280,18 +1281,24 @@ InstallStatus UninstallProduct(const InstallationState& original_state, // TODO(huangs): Implement actual migration code and remove the hack below. // Remove the "shadow" App Launcher registry keys. - // TODO(hunags): Management of this key should not be conditional on - // multi-install since the app list feature is available regardless of how - // chrome is installed. if (installer_state.is_multi_install()) { - // Delete the "shadow" keys. - BrowserDistribution* shadow_app_launcher_dist = - BrowserDistribution::GetSpecificDistribution( - BrowserDistribution::CHROME_APP_HOST); - InstallUtil::DeleteRegistryKey( - reg_root, - shadow_app_launcher_dist->GetVersionKey(), - KEY_WOW64_32KEY); + // If we're not uninstalling the legacy App Launcher, and if it was + // not installed in the first place, then delete the "shadow" keys. + chrome_launcher_support::InstallationState level_to_check = + installer_state.system_install() ? + chrome_launcher_support::INSTALLED_AT_SYSTEM_LEVEL : + chrome_launcher_support::INSTALLED_AT_USER_LEVEL; + bool has_legacy_app_launcher = level_to_check == + chrome_launcher_support::GetAppLauncherInstallationState(); + if (!has_legacy_app_launcher) { + BrowserDistribution* shadow_app_launcher_dist = + BrowserDistribution::GetSpecificDistribution( + BrowserDistribution::CHROME_APP_HOST); + InstallUtil::DeleteRegistryKey( + reg_root, + shadow_app_launcher_dist->GetVersionKey(), + KEY_WOW64_32KEY); + } } } diff --git a/chrome/installer/util/chrome_app_host_distribution.cc b/chrome/installer/util/chrome_app_host_distribution.cc index 6e831e5..85e50d5 100644 --- a/chrome/installer/util/chrome_app_host_distribution.cc +++ b/chrome/installer/util/chrome_app_host_distribution.cc @@ -21,11 +21,17 @@ #include "installer_util_strings.h" // NOLINT +namespace { + +const wchar_t kChromeAppHostGuid[] = L"{FDA71E6F-AC4C-4a00-8B70-9958A68906BF}"; + +} // namespace + ChromeAppHostDistribution::ChromeAppHostDistribution() : BrowserDistribution( CHROME_APP_HOST, scoped_ptr<AppRegistrationData>( - new UpdatingAppRegistrationData(installer::kAppLauncherGuid))) { + new UpdatingAppRegistrationData(kChromeAppHostGuid))) { } base::string16 ChromeAppHostDistribution::GetBaseAppName() { diff --git a/chrome/installer/util/google_update_util.cc b/chrome/installer/util/google_update_util.cc index d3013ba..c7de7a5 100644 --- a/chrome/installer/util/google_update_util.cc +++ b/chrome/installer/util/google_update_util.cc @@ -4,19 +4,28 @@ #include "chrome/installer/util/google_update_util.h" +#include <algorithm> +#include <map> +#include <utility> +#include <vector> + #include "base/command_line.h" +#include "base/environment.h" #include "base/file_util.h" #include "base/files/file_path.h" #include "base/logging.h" +#include "base/memory/scoped_ptr.h" #include "base/path_service.h" #include "base/process/kill.h" #include "base/process/launch.h" #include "base/strings/string16.h" +#include "base/strings/string_split.h" #include "base/time/time.h" #include "base/win/registry.h" #include "base/win/scoped_handle.h" #include "base/win/win_util.h" #include "base/win/windows_version.h" +#include "chrome/installer/launcher_support/chrome_launcher_support.h" #include "chrome/installer/util/browser_distribution.h" #include "chrome/installer/util/google_update_constants.h" #include "chrome/installer/util/google_update_settings.h" @@ -32,6 +41,9 @@ namespace { const int kGoogleUpdateTimeoutMs = 20 * 1000; +const char kEnvVariableUntrustedData[] = "GoogleUpdateUntrustedData"; +const int kUntrustedDataMaxLength = 4096; + // Returns true if Google Update is present at the given level. bool IsGoogleUpdatePresent(bool system_install) { // Using the existence of version key in the registry to decide. @@ -108,6 +120,73 @@ bool LaunchProcessAndWaitWithTimeout(const base::string16& cmd_string, return success; } +bool IsNotPrintable(unsigned char c) { + return c < 32 || c >= 127; +} + +// Returns whether or not |s| consists of printable characters. +bool IsStringPrintable(const std::string& s) { + return std::find_if(s.begin(), s.end(), IsNotPrintable) == s.end(); +} + +bool IsIllegalUntrustedDataKeyChar(unsigned char c) { + return !(c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z' || + c >= '0' && c <= '9' || c == '-' || c == '_' || c == '$'); +} + +// Returns true if |key| from untrusted data is valid. +bool IsUntrustedDataKeyValid(const std::string& key) { + return std::find_if(key.begin(), key.end(), IsIllegalUntrustedDataKeyChar) + == key.end(); +} + +// Parses |data_string| as key-value pairs and overwrites |untrusted_data| with +// the result. Returns true if the data could be parsed. +bool ParseUntrustedData( + const std::string& data_string, + std::map<std::string, std::string>* untrusted_data) { + DCHECK(untrusted_data); + if (data_string.length() > kUntrustedDataMaxLength || + !IsStringPrintable(data_string)) { + LOG(ERROR) << "Invalid value in untrusted data string."; + return false; + } + + VLOG(1) << "Untrusted data string: " << data_string; + + std::vector<std::pair<std::string, std::string> > kv_pairs; + if (!base::SplitStringIntoKeyValuePairs(data_string, '=', '&', &kv_pairs)) { + LOG(ERROR) << "Failed to parse untrusted data: " << data_string; + return false; + } + + untrusted_data->clear(); + std::vector<std::pair<std::string, std::string> >::const_iterator it; + for (it = kv_pairs.begin(); it != kv_pairs.end(); ++it) { + const std::string& key(it->first); + // TODO(huangs): URL unescape |value|. + const std::string& value(it->second); + if (IsUntrustedDataKeyValid(key) && IsStringPrintable(value)) + (*untrusted_data)[key] = value; + else + LOG(ERROR) << "Illegal character found in untrusted data."; + } + return true; +} + +// Reads and parses untrusted data passed from Google Update as key-value +// pairs, then overwrites |untrusted_data_map| with the result. +// Returns true if data are successfully read. +bool GetGoogleUpdateUntrustedData( + std::map<std::string, std::string>* untrusted_data) { + scoped_ptr<base::Environment> env(base::Environment::Create()); + std::string data_string; + if (!env || !env->GetVar(kEnvVariableUntrustedData, &data_string)) + return false; + + return ParseUntrustedData(data_string, untrusted_data); +} + } // namespace bool EnsureUserLevelGoogleUpdatePresent() { @@ -187,4 +266,25 @@ void ElevateIfNeededToReenableUpdates() { } } +std::string GetUntrustedDataValue(const std::string& key) { + std::map<std::string, std::string> untrusted_data; + if (GetGoogleUpdateUntrustedData(&untrusted_data)) { + std::map<std::string, std::string>::const_iterator data_it( + untrusted_data.find(key)); + if (data_it != untrusted_data.end()) + return data_it->second; + } + + return std::string(); +} + +std::string GetUntrustedDataValueFromTag(const std::string& tag, + const std::string& key) { + std::map<std::string, std::string> untrusted_data; + if (ParseUntrustedData(tag, &untrusted_data)) + return untrusted_data[key]; + + return std::string(); +} + } // namespace google_update diff --git a/chrome/installer/util/google_update_util.h b/chrome/installer/util/google_update_util.h index 97edfad..4f240af 100644 --- a/chrome/installer/util/google_update_util.h +++ b/chrome/installer/util/google_update_util.h @@ -5,6 +5,8 @@ #ifndef CHROME_INSTALLER_UTIL_GOOGLE_UPDATE_UTIL_H_ #define CHROME_INSTALLER_UTIL_GOOGLE_UPDATE_UTIL_H_ +#include <string> + namespace google_update { // If user-level Google Update is absent, calls the system-level @@ -25,6 +27,18 @@ bool UninstallGoogleUpdate(bool system_install); // GoogleUpdateSettings::ReenableAutoupdatesForApp() to do the work. void ElevateIfNeededToReenableUpdates(); +// Returns the value corresponding to |key| in untrusted data passed from +// Google Update. Returns an empty string if |key| is absent or if its value +// contains non-printable characters. +std::string GetUntrustedDataValue(const std::string& key); + +// Returns the value corresponding to |key| in untrusted data passed from +// |tag|. |tag| should be a printable list of key-value pairs, e.g. +// "key1=value1&key2=value2". Returns an empty string if |key| is absent or if +// its value contains non-printable characters. +std::string GetUntrustedDataValueFromTag(const std::string& tag, + const std::string& key); + } // namespace google_update #endif // CHROME_INSTALLER_UTIL_GOOGLE_UPDATE_UTIL_H_ diff --git a/chrome/installer/util/util_constants.cc b/chrome/installer/util/util_constants.cc index 67df18e..8800c5c 100644 --- a/chrome/installer/util/util_constants.cc +++ b/chrome/installer/util/util_constants.cc @@ -212,7 +212,6 @@ const char kOutputFile[] = "output-file"; // TODO(gab): Rename setup.exe itself altogether and use the same binary for // Active Setup. const wchar_t kActiveSetupExe[] = L"chrmstp.exe"; -const wchar_t kAppLauncherGuid[] = L"{FDA71E6F-AC4C-4a00-8B70-9958A68906BF}"; const wchar_t kChromeAppHostExe[] = L"app_host.exe"; const wchar_t kChromeDll[] = L"chrome.dll"; const wchar_t kChromeChildDll[] = L"chrome_child.dll"; diff --git a/chrome/installer/util/util_constants.h b/chrome/installer/util/util_constants.h index da54a38..d2f648a 100644 --- a/chrome/installer/util/util_constants.h +++ b/chrome/installer/util/util_constants.h @@ -201,7 +201,6 @@ extern const char kOutputFile[]; } // namespace switches extern const wchar_t kActiveSetupExe[]; -extern const wchar_t kAppLauncherGuid[]; extern const wchar_t kChromeAppHostExe[]; extern const wchar_t kChromeDll[]; extern const wchar_t kChromeChildDll[]; |