Index: chrome/installer/mini_installer/configuration.cc |
diff --git a/chrome/installer/mini_installer/configuration.cc b/chrome/installer/mini_installer/configuration.cc |
index 87e08be387e3c3eaaea5ebeac5b5d72a7bc5047b..2a94df613699593db11217305b110989df981d87 100644 |
--- a/chrome/installer/mini_installer/configuration.cc |
+++ b/chrome/installer/mini_installer/configuration.cc |
@@ -7,7 +7,9 @@ |
#include <shellapi.h> // NOLINT |
#include "chrome/installer/mini_installer/appid.h" |
+#include "chrome/installer/mini_installer/mini_installer_constants.h" |
#include "chrome/installer/mini_installer/mini_installer_resource.h" |
+#include "chrome/installer/mini_installer/regkey.h" |
namespace mini_installer { |
@@ -19,6 +21,58 @@ Configuration::~Configuration() { |
Clear(); |
} |
+// When multi_install is true, we are potentially: |
+// 1. Performing a multi-install of some product(s) on a clean machine. |
+// Neither the product(s) nor the multi-installer will have a |
+// ClientState key in the registry, so there is no key to be modified. |
+// 2. Upgrading an existing multi-install. The multi-installer will have |
+// a ClientState key in the registry. Only it need be modified. |
+// 3. Migrating a single-install into a multi-install. The product will |
+// have a ClientState key in the registry. Only it need be modified. |
+// To handle all cases, we inspect the product's ClientState to see if it |
+// exists and its "ap" value does not contain "-multi". This is case 3, |
+// so we modify the product's ClientState. Otherwise, we check the |
+// multi-installer's ClientState and modify it if it exists. |
+// TODO(bcwhite): Write a unit test for this that uses registry virtualization. |
+void Configuration::SetChromeAppGuid() { |
+ const HKEY root_key = |
+ is_system_level_ ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; |
+ const wchar_t* app_guid = |
+ has_chrome_frame_ ? |
+ google_update::kChromeFrameAppGuid : |
+ is_side_by_side_ ? google_update::kSxSAppGuid |
+ : google_update::kAppGuid; |
+ |
+ // This is the value for single-install and case 3. |
+ chrome_app_guid_ = app_guid; |
+ |
+ if (is_multi_install_) { |
+ ValueString value; |
+ LONG ret = ERROR_SUCCESS; |
+ if (ReadClientStateRegistryValue(root_key, app_guid, &ret, value)) { |
+ // The product has a client state key. See if it's a single-install. |
+ if (ret == ERROR_FILE_NOT_FOUND || |
+ (ret == ERROR_SUCCESS && |
+ !FindTagInStr(value.get(), kMultiInstallTag, NULL))) { |
+ // yes -- case 3: use the existing key. |
+ return; |
+ } |
+ } |
+ // error, case 1, or case 2: modify the multi-installer's key. |
+ chrome_app_guid_ = google_update::kMultiInstallAppGuid; |
+ } |
+} |
+ |
+bool Configuration::ReadClientStateRegistryValue( |
+ const HKEY root_key, const wchar_t* app_guid, |
+ LONG* retval, ValueString& value) { |
+ RegKey key; |
+ if (!OpenClientStateKey(root_key, app_guid, KEY_QUERY_VALUE, &key)) |
+ return false; |
+ *retval = key.ReadSZValue(kApRegistryValue, value.get(), value.capacity()); |
+ return true; |
+} |
+ |
const wchar_t* Configuration::program() const { |
return args_ == NULL || argument_count_ < 1 ? NULL : args_[0]; |
} |
@@ -36,6 +90,7 @@ void Configuration::Clear() { |
has_chrome_frame_ = false; |
is_multi_install_ = false; |
is_system_level_ = false; |
+ is_side_by_side_ = false; |
previous_version_ = NULL; |
} |
@@ -54,7 +109,7 @@ bool Configuration::ParseCommandLine(const wchar_t* command_line) { |
if (args_ != NULL) { |
for (int i = 1; i < argument_count_; ++i) { |
if (0 == ::lstrcmpi(args_[i], L"--chrome-sxs")) |
- chrome_app_guid_ = google_update::kSxSAppGuid; |
+ is_side_by_side_ = true; |
else if (0 == ::lstrcmpi(args_[i], L"--chrome")) |
has_chrome_ = true; |
else if (0 == ::lstrcmpi(args_[i], L"--chrome-frame")) |
@@ -67,9 +122,10 @@ bool Configuration::ParseCommandLine(const wchar_t* command_line) { |
operation_ = CLEANUP; |
} |
- // Single-install defaults to Chrome. |
- if (!is_multi_install_) |
+ SetChromeAppGuid(); |
+ if (!is_multi_install_) { |
has_chrome_ = !has_chrome_frame_; |
+ } |
} |
return args_ != NULL; |