From f0d583dfa0a622cf3c6b7c494a91bc9f0e1fc959 Mon Sep 17 00:00:00 2001 From: "huangs@chromium.org" Date: Sun, 20 Jan 2013 00:37:49 +0000 Subject: During App Launcher install, install V2 App if instructed to do so via environment variable. The environment variable read is GoogleUpdateUntrustedData. To test this: 1. Set the following environmental variable (to install Smooth Life): set GoogleUpdateUntrustedData=install-from-webstore=cehnejjbgmkcpmabgambbdjiechjaped 2. Install App Launcher: mini_installer.exe --verbose-logging --multi-install --app-launcher We're making 'setup' depend on 'launcher_support' because install.c needs to call chrome_launcher_support::GetAnyAppHostPath(). BUG=151107 Review URL: https://chromiumcodereview.appspot.com/11737011 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@177855 0039d316-1c4b-4281-b951-d872f2087c98 --- chrome/chrome_installer.gypi | 2 + chrome/installer/setup/install.cc | 13 +++++ chrome/installer/setup/install.h | 5 ++ chrome/installer/setup/setup_constants.cc | 4 ++ chrome/installer/setup/setup_constants.h | 2 + chrome/installer/setup/setup_main.cc | 12 +++++ chrome/installer/util/google_update_util.cc | 81 +++++++++++++++++++++++++++++ chrome/installer/util/google_update_util.h | 7 +++ 8 files changed, 126 insertions(+) diff --git a/chrome/chrome_installer.gypi b/chrome/chrome_installer.gypi index abb2791..9d94b27 100644 --- a/chrome/chrome_installer.gypi +++ b/chrome/chrome_installer.gypi @@ -266,6 +266,7 @@ 'dependencies': [ 'installer_util', 'installer_util_strings', + 'launcher_support', '../base/base.gyp:base', '../breakpad/breakpad.gyp:breakpad_handler', '../build/temp_gyp/googleurl.gyp:googleurl', @@ -413,6 +414,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/setup/install.cc b/chrome/installer/setup/install.cc index 0574eee..2be1efd 100644 --- a/chrome/installer/setup/install.cc +++ b/chrome/installer/setup/install.cc @@ -17,6 +17,7 @@ #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/path_service.h" +#include "base/process_util.h" #include "base/string_util.h" #include "base/stringprintf.h" #include "base/utf_string_conversions.h" @@ -24,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" @@ -697,4 +699,15 @@ void HandleActiveSetupForBrowser(const FilePath& installation_root, chrome_exe, chrome, prefs, CURRENT_USER, install_operation); } +bool InstallFromWebstore(const std::string& app_code) { + 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 b8c35f1..abf0ab3 100644 --- a/chrome/installer/setup/install.h +++ b/chrome/installer/setup/install.h @@ -131,6 +131,11 @@ void HandleActiveSetupForBrowser(const 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 e31afaa..4ec738f 100644 --- a/chrome/installer/setup/setup_main.cc +++ b/chrome/installer/setup/setup_main.cc @@ -7,6 +7,8 @@ #include #include +#include + #include "base/at_exit.h" #include "base/basictypes.h" #include "base/command_line.h" @@ -884,6 +886,16 @@ installer::InstallStatus InstallProductsHelper( chrome_exe); } } + + if (prefs.install_chrome_app_launcher() && + InstallUtil::GetInstallReturnCode(install_status) == 0) { + std::string webstore_item(google_update::GetUntrustedDataValue( + installer::kInstallFromWebstore)); + if (!webstore_item.empty()) { + bool success = installer::InstallFromWebstore(webstore_item); + VLOG_IF(1, !success) << "Failed to launch app installation."; + } + } } } diff --git a/chrome/installer/util/google_update_util.cc b/chrome/installer/util/google_update_util.cc index 6ce3d75..d7daf5c 100644 --- a/chrome/installer/util/google_update_util.cc +++ b/chrome/installer/util/google_update_util.cc @@ -4,12 +4,19 @@ #include "chrome/installer/util/google_update_util.h" +#include +#include +#include +#include + #include "base/command_line.h" +#include "base/environment.h" #include "base/file_path.h" #include "base/file_util.h" #include "base/logging.h" #include "base/process_util.h" #include "base/string16.h" +#include "base/string_split.h" #include "base/time.h" #include "base/win/registry.h" #include "base/win/scoped_handle.h" @@ -25,6 +32,9 @@ namespace { const int kGoogleUpdateTimeoutMs = 20 * 1000; +const char kEnvVariableUntrustedData[] = "GoogleUpdateUntrustedData"; +const int kEnvVariableUntrustedDataMaxLength = 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. @@ -98,6 +108,65 @@ bool LaunchProcessAndWaitWithTimeout(const 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(); +} + +// 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* untrusted_data) { + DCHECK(untrusted_data); + scoped_ptr env(base::Environment::Create()); + std::string data_string; + if (env == NULL || !env->GetVar(kEnvVariableUntrustedData, &data_string)) + return false; + + if (data_string.length() > kEnvVariableUntrustedDataMaxLength || + !IsStringPrintable(data_string)) { + LOG(ERROR) << "Invalid value in " << kEnvVariableUntrustedData; + return false; + } + + VLOG(1) << kEnvVariableUntrustedData << ": " << data_string; + + std::vector > 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 >::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; +} + } // namespace bool EnsureUserLevelGoogleUpdatePresent() { @@ -131,4 +200,16 @@ bool UninstallGoogleUpdate(bool system_install) { return success; } +std::string GetUntrustedDataValue(const std::string& key) { + std::map untrusted_data; + if (GetGoogleUpdateUntrustedData(&untrusted_data)) { + std::map::const_iterator data_it( + untrusted_data.find(key)); + if (data_it != untrusted_data.end()) + return data_it->second; + } + + 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 7ac15d5..1e4995e 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 + namespace google_update { // If user-level Google Update is absent, calls the system-level @@ -19,6 +21,11 @@ bool EnsureUserLevelGoogleUpdatePresent(); // Returns false if Google Update could not be executed, or times out. bool UninstallGoogleUpdate(bool system_install); +// 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); + } // namespace google_update #endif // CHROME_INSTALLER_UTIL_GOOGLE_UPDATE_UTIL_H_ -- cgit v1.1