Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(63)

Side by Side Diff: chrome/installer/mini_installer/configuration.cc

Issue 2507293005: Force migrate all clients from multi-install back to single-install. (Closed)
Patch Set: gab comments Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/installer/mini_installer/configuration.h" 5 #include "chrome/installer/mini_installer/configuration.h"
6 6
7 #include <windows.h> 7 #include <windows.h>
8 #include <shellapi.h> // NOLINT 8 #include <shellapi.h> // NOLINT
9 #include <stddef.h> 9 #include <stddef.h>
10 10
11 #include "chrome/installer/mini_installer/appid.h" 11 #include "chrome/installer/mini_installer/appid.h"
12 #include "chrome/installer/mini_installer/mini_installer_constants.h" 12 #include "chrome/installer/mini_installer/mini_installer_constants.h"
13 #include "chrome/installer/mini_installer/mini_installer_resource.h" 13 #include "chrome/installer/mini_installer/mini_installer_resource.h"
14 #include "chrome/installer/mini_installer/mini_string.h"
14 #include "chrome/installer/mini_installer/regkey.h" 15 #include "chrome/installer/mini_installer/regkey.h"
15 16
16 namespace mini_installer { 17 namespace mini_installer {
17 18
18 namespace { 19 namespace {
19 20
20 // Returns true if GoogleUpdateIsMachine=1 is present in the environment. 21 // Returns true if GoogleUpdateIsMachine=1 is present in the environment.
21 bool GetGoogleUpdateIsMachineEnvVar() { 22 bool GetGoogleUpdateIsMachineEnvVar() {
22 const DWORD kBufferSize = 2; 23 const DWORD kBufferSize = 2;
23 StackString<kBufferSize> value; 24 StackString<kBufferSize> value;
24 DWORD length = ::GetEnvironmentVariableW(L"GoogleUpdateIsMachine", 25 DWORD length = ::GetEnvironmentVariableW(L"GoogleUpdateIsMachine",
25 value.get(), kBufferSize); 26 value.get(), kBufferSize);
26 return length == 1 && *value.get() == L'1'; 27 return length == 1 && *value.get() == L'1';
27 } 28 }
28 29
29 } // namespace 30 } // namespace
30 31
31 Configuration::Configuration() : args_(NULL) { 32 Configuration::Configuration() : args_(NULL) {
32 Clear(); 33 Clear();
33 } 34 }
34 35
35 Configuration::~Configuration() { 36 Configuration::~Configuration() {
36 Clear(); 37 Clear();
37 } 38 }
38 39
39 // When multi_install is true, we are potentially: 40 bool Configuration::Initialize(HMODULE module) {
40 // 1. Performing a multi-install of some product(s) on a clean machine. 41 Clear();
41 // Neither the product(s) nor the multi-installer will have a 42 ReadResources(module);
42 // ClientState key in the registry, so there is no key to be modified. 43 return ParseCommandLine(::GetCommandLine());
43 // 2. Upgrading an existing multi-install. The multi-installer will have
44 // a ClientState key in the registry. Only it need be modified.
45 // 3. Migrating a single-install into a multi-install. The product will
46 // have a ClientState key in the registry. Only it need be modified.
47 // To handle all cases, we inspect the product's ClientState to see if it
48 // exists and its "ap" value does not contain "-multi". This is case 3,
49 // so we modify the product's ClientState. Otherwise, we check the
50 // multi-installer's ClientState and modify it if it exists.
51 // TODO(bcwhite): Write a unit test for this that uses registry virtualization.
52 void Configuration::SetChromeAppGuid() {
53 const HKEY root_key =
54 is_system_level_ ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
55 const wchar_t* app_guid =
56 is_side_by_side_ ? google_update::kSxSAppGuid
57 : google_update::kAppGuid;
58
59 // This is the value for single-install and case 3.
60 chrome_app_guid_ = app_guid;
61
62 if (is_multi_install_) {
63 ValueString value;
64 LONG ret = ERROR_SUCCESS;
65 if (ReadClientStateRegistryValue(root_key, app_guid, &ret, value)) {
66 // The product has a client state key. See if it's a single-install.
67 if (ret == ERROR_FILE_NOT_FOUND ||
68 (ret == ERROR_SUCCESS &&
69 !FindTagInStr(value.get(), kMultiInstallTag, NULL))) {
70 // yes -- case 3: use the existing key.
71 return;
72 }
73 }
74 // error, case 1, or case 2: modify the multi-installer's key.
75 chrome_app_guid_ = google_update::kMultiInstallAppGuid;
76 }
77 }
78
79 bool Configuration::ReadClientStateRegistryValue(
80 const HKEY root_key, const wchar_t* app_guid,
81 LONG* retval, ValueString& value) {
82 RegKey key;
83 if (!OpenClientStateKey(root_key, app_guid, KEY_QUERY_VALUE, &key))
84 return false;
85 *retval = key.ReadSZValue(kApRegistryValue, value.get(), value.capacity());
86 return true;
87 } 44 }
88 45
89 const wchar_t* Configuration::program() const { 46 const wchar_t* Configuration::program() const {
90 return args_ == NULL || argument_count_ < 1 ? NULL : args_[0]; 47 return args_ == NULL || argument_count_ < 1 ? NULL : args_[0];
91 } 48 }
92 49
93 void Configuration::Clear() { 50 void Configuration::Clear() {
94 if (args_ != NULL) { 51 if (args_ != NULL) {
95 ::LocalFree(args_); 52 ::LocalFree(args_);
96 args_ = NULL; 53 args_ = NULL;
97 } 54 }
98 chrome_app_guid_ = google_update::kAppGuid; 55 chrome_app_guid_ = google_update::kAppGuid;
99 command_line_ = NULL; 56 command_line_ = NULL;
100 operation_ = INSTALL_PRODUCT; 57 operation_ = INSTALL_PRODUCT;
101 argument_count_ = 0; 58 argument_count_ = 0;
102 has_chrome_ = false;
103 is_multi_install_ = false;
104 is_system_level_ = false; 59 is_system_level_ = false;
105 is_side_by_side_ = false; 60 is_side_by_side_ = false;
61 is_updating_multi_chrome_ = false;
106 has_invalid_switch_ = false; 62 has_invalid_switch_ = false;
107 previous_version_ = NULL; 63 previous_version_ = NULL;
108 } 64 }
109 65
110 bool Configuration::Initialize(HMODULE module) {
111 Clear();
112 ReadResources(module);
113 return ParseCommandLine(::GetCommandLine());
114 }
115
116 // |command_line| is shared with this instance in the sense that this 66 // |command_line| is shared with this instance in the sense that this
117 // instance may refer to it at will throughout its lifetime, yet it will 67 // instance may refer to it at will throughout its lifetime, yet it will
118 // not release it. 68 // not release it.
119 bool Configuration::ParseCommandLine(const wchar_t* command_line) { 69 bool Configuration::ParseCommandLine(const wchar_t* command_line) {
120 command_line_ = command_line; 70 command_line_ = command_line;
121 args_ = ::CommandLineToArgvW(command_line_, &argument_count_); 71 args_ = ::CommandLineToArgvW(command_line_, &argument_count_);
122 if (!args_) 72 if (!args_)
123 return false; 73 return false;
124 74
125 for (int i = 1; i < argument_count_; ++i) { 75 for (int i = 1; i < argument_count_; ++i) {
126 if (0 == ::lstrcmpi(args_[i], L"--chrome-sxs")) 76 if (0 == ::lstrcmpi(args_[i], L"--system-level")) {
77 is_system_level_ = true;
78 #if defined(GOOGLE_CHROME_BUILD)
79 } else if (0 == ::lstrcmpi(args_[i], L"--chrome-sxs")) {
127 is_side_by_side_ = true; 80 is_side_by_side_ = true;
128 else if (0 == ::lstrcmpi(args_[i], L"--chrome")) 81 chrome_app_guid_ = google_update::kSxSAppGuid;
129 has_chrome_ = true; 82 #endif
130 else if (0 == ::lstrcmpi(args_[i], L"--multi-install")) 83 } else if (0 == ::lstrcmpi(args_[i], L"--cleanup")) {
131 is_multi_install_ = true;
132 else if (0 == ::lstrcmpi(args_[i], L"--system-level"))
133 is_system_level_ = true;
134 else if (0 == ::lstrcmpi(args_[i], L"--cleanup"))
135 operation_ = CLEANUP; 84 operation_ = CLEANUP;
136 else if (0 == ::lstrcmpi(args_[i], L"--chrome-frame")) 85 } else if (0 == ::lstrcmpi(args_[i], L"--chrome-frame")) {
137 has_invalid_switch_ = true; 86 has_invalid_switch_ = true;
87 }
138 } 88 }
139 89
140 if (!is_system_level_) 90 if (!is_system_level_)
141 is_system_level_ = GetGoogleUpdateIsMachineEnvVar(); 91 is_system_level_ = GetGoogleUpdateIsMachineEnvVar();
142 SetChromeAppGuid(); 92
143 if (!is_multi_install_) 93 is_updating_multi_chrome_ = IsUpdatingMultiChrome();
144 has_chrome_ = true;
145 94
146 return true; 95 return true;
147 } 96 }
148 97
149 void Configuration::ReadResources(HMODULE module) { 98 void Configuration::ReadResources(HMODULE module) {
150 HRSRC resource_info_block = 99 HRSRC resource_info_block =
151 FindResource(module, MAKEINTRESOURCE(ID_PREVIOUS_VERSION), RT_RCDATA); 100 FindResource(module, MAKEINTRESOURCE(ID_PREVIOUS_VERSION), RT_RCDATA);
152 if (!resource_info_block) 101 if (!resource_info_block)
153 return; 102 return;
154 103
(...skipping 13 matching lines...) Expand all
168 const wchar_t* version_string = reinterpret_cast<wchar_t*>(version_data); 117 const wchar_t* version_string = reinterpret_cast<wchar_t*>(version_data);
169 size_t version_len = version_size / sizeof(wchar_t); 118 size_t version_len = version_size / sizeof(wchar_t);
170 119
171 // The string must be terminated. 120 // The string must be terminated.
172 if (version_string[version_len - 1]) 121 if (version_string[version_len - 1])
173 return; 122 return;
174 123
175 previous_version_ = version_string; 124 previous_version_ = version_string;
176 } 125 }
177 126
127 bool Configuration::IsUpdatingMultiChrome() const {
128 #if defined(GOOGLE_CHROME_BUILD)
129 // SxS/canary does not support multi-install.
130 if (is_side_by_side_)
131 return false;
132
133 // Is Chrome already installed as multi-install?
134 const HKEY root = is_system_level_ ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
135 StackString<128> value;
136 RegKey key;
137 return (OpenClientsKey(root, google_update::kAppGuid, KEY_QUERY_VALUE,
138 &key) == ERROR_SUCCESS &&
139 key.ReadSZValue(kPvRegistryValue, value.get(), value.capacity()) ==
140 ERROR_SUCCESS &&
141 value.length() != 0 &&
142 OpenClientStateKey(root, google_update::kAppGuid, KEY_QUERY_VALUE,
143 &key) == ERROR_SUCCESS &&
144 key.ReadSZValue(kUninstallArgumentsRegistryValue, value.get(),
145 value.capacity()) == ERROR_SUCCESS &&
146 value.findi(L"--multi-install") != nullptr);
147 #else
148 return false;
149 #endif
150 }
151
178 } // namespace mini_installer 152 } // namespace mini_installer
OLDNEW
« no previous file with comments | « chrome/installer/mini_installer/configuration.h ('k') | chrome/installer/mini_installer/configuration_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698