summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhuangs@chromium.org <huangs@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-01-20 00:37:49 +0000
committerhuangs@chromium.org <huangs@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-01-20 00:37:49 +0000
commitf0d583dfa0a622cf3c6b7c494a91bc9f0e1fc959 (patch)
treefb43ab5dad5c4e0094ef57cd5f18a4804e42a747
parent3dbd64d89febbe85df9b53ad16fbdca06ecdeb9a (diff)
downloadchromium_src-f0d583dfa0a622cf3c6b7c494a91bc9f0e1fc959.zip
chromium_src-f0d583dfa0a622cf3c6b7c494a91bc9f0e1fc959.tar.gz
chromium_src-f0d583dfa0a622cf3c6b7c494a91bc9f0e1fc959.tar.bz2
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
-rw-r--r--chrome/chrome_installer.gypi2
-rw-r--r--chrome/installer/setup/install.cc13
-rw-r--r--chrome/installer/setup/install.h5
-rw-r--r--chrome/installer/setup/setup_constants.cc4
-rw-r--r--chrome/installer/setup/setup_constants.h2
-rw-r--r--chrome/installer/setup/setup_main.cc12
-rw-r--r--chrome/installer/util/google_update_util.cc81
-rw-r--r--chrome/installer/util/google_update_util.h7
8 files changed, 126 insertions, 0 deletions
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 <shellapi.h>
#include <shlobj.h>
+#include <string>
+
#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 <algorithm>
+#include <map>
+#include <utility>
+#include <vector>
+
#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<std::string, std::string>* untrusted_data) {
+ DCHECK(untrusted_data);
+ scoped_ptr<base::Environment> 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<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;
+}
+
} // namespace
bool EnsureUserLevelGoogleUpdatePresent() {
@@ -131,4 +200,16 @@ bool UninstallGoogleUpdate(bool system_install) {
return success;
}
+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();
+}
+
} // 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 <string>
+
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_