Add new certificateProvider extension API.
[chromium-blink-merge.git] / chrome / installer / mini_installer / configuration.cc
blob2a94df613699593db11217305b110989df981d87
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
3 // found in the LICENSE file.
5 #include "chrome/installer/mini_installer/configuration.h"
7 #include <shellapi.h> // NOLINT
9 #include "chrome/installer/mini_installer/appid.h"
10 #include "chrome/installer/mini_installer/mini_installer_constants.h"
11 #include "chrome/installer/mini_installer/mini_installer_resource.h"
12 #include "chrome/installer/mini_installer/regkey.h"
14 namespace mini_installer {
16 Configuration::Configuration() : args_(NULL) {
17 Clear();
20 Configuration::~Configuration() {
21 Clear();
24 // When multi_install is true, we are potentially:
25 // 1. Performing a multi-install of some product(s) on a clean machine.
26 // Neither the product(s) nor the multi-installer will have a
27 // ClientState key in the registry, so there is no key to be modified.
28 // 2. Upgrading an existing multi-install. The multi-installer will have
29 // a ClientState key in the registry. Only it need be modified.
30 // 3. Migrating a single-install into a multi-install. The product will
31 // have a ClientState key in the registry. Only it need be modified.
32 // To handle all cases, we inspect the product's ClientState to see if it
33 // exists and its "ap" value does not contain "-multi". This is case 3,
34 // so we modify the product's ClientState. Otherwise, we check the
35 // multi-installer's ClientState and modify it if it exists.
36 // TODO(bcwhite): Write a unit test for this that uses registry virtualization.
37 void Configuration::SetChromeAppGuid() {
38 const HKEY root_key =
39 is_system_level_ ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
40 const wchar_t* app_guid =
41 has_chrome_frame_ ?
42 google_update::kChromeFrameAppGuid :
43 is_side_by_side_ ? google_update::kSxSAppGuid
44 : google_update::kAppGuid;
46 // This is the value for single-install and case 3.
47 chrome_app_guid_ = app_guid;
49 if (is_multi_install_) {
50 ValueString value;
51 LONG ret = ERROR_SUCCESS;
52 if (ReadClientStateRegistryValue(root_key, app_guid, &ret, value)) {
53 // The product has a client state key. See if it's a single-install.
54 if (ret == ERROR_FILE_NOT_FOUND ||
55 (ret == ERROR_SUCCESS &&
56 !FindTagInStr(value.get(), kMultiInstallTag, NULL))) {
57 // yes -- case 3: use the existing key.
58 return;
61 // error, case 1, or case 2: modify the multi-installer's key.
62 chrome_app_guid_ = google_update::kMultiInstallAppGuid;
66 bool Configuration::ReadClientStateRegistryValue(
67 const HKEY root_key, const wchar_t* app_guid,
68 LONG* retval, ValueString& value) {
69 RegKey key;
70 if (!OpenClientStateKey(root_key, app_guid, KEY_QUERY_VALUE, &key))
71 return false;
72 *retval = key.ReadSZValue(kApRegistryValue, value.get(), value.capacity());
73 return true;
76 const wchar_t* Configuration::program() const {
77 return args_ == NULL || argument_count_ < 1 ? NULL : args_[0];
80 void Configuration::Clear() {
81 if (args_ != NULL) {
82 ::LocalFree(args_);
83 args_ = NULL;
85 chrome_app_guid_ = google_update::kAppGuid;
86 command_line_ = NULL;
87 operation_ = INSTALL_PRODUCT;
88 argument_count_ = 0;
89 has_chrome_ = false;
90 has_chrome_frame_ = false;
91 is_multi_install_ = false;
92 is_system_level_ = false;
93 is_side_by_side_ = false;
94 previous_version_ = NULL;
97 bool Configuration::Initialize(HMODULE module) {
98 Clear();
99 ReadResources(module);
100 return ParseCommandLine(::GetCommandLine());
103 // |command_line| is shared with this instance in the sense that this
104 // instance may refer to it at will throughout its lifetime, yet it will
105 // not release it.
106 bool Configuration::ParseCommandLine(const wchar_t* command_line) {
107 command_line_ = command_line;
108 args_ = ::CommandLineToArgvW(command_line_, &argument_count_);
109 if (args_ != NULL) {
110 for (int i = 1; i < argument_count_; ++i) {
111 if (0 == ::lstrcmpi(args_[i], L"--chrome-sxs"))
112 is_side_by_side_ = true;
113 else if (0 == ::lstrcmpi(args_[i], L"--chrome"))
114 has_chrome_ = true;
115 else if (0 == ::lstrcmpi(args_[i], L"--chrome-frame"))
116 has_chrome_frame_ = true;
117 else if (0 == ::lstrcmpi(args_[i], L"--multi-install"))
118 is_multi_install_ = true;
119 else if (0 == ::lstrcmpi(args_[i], L"--system-level"))
120 is_system_level_ = true;
121 else if (0 == ::lstrcmpi(args_[i], L"--cleanup"))
122 operation_ = CLEANUP;
125 SetChromeAppGuid();
126 if (!is_multi_install_) {
127 has_chrome_ = !has_chrome_frame_;
131 return args_ != NULL;
134 void Configuration::ReadResources(HMODULE module) {
135 HRSRC resource_info_block =
136 FindResource(module, MAKEINTRESOURCE(ID_PREVIOUS_VERSION), RT_RCDATA);
137 if (!resource_info_block)
138 return;
140 HGLOBAL data_handle = LoadResource(module, resource_info_block);
141 if (!data_handle)
142 return;
144 // The data is a Unicode string, so it must be a multiple of two bytes.
145 DWORD version_size = SizeofResource(module, resource_info_block);
146 if (!version_size || (version_size & 0x01) != 0)
147 return;
149 void* version_data = LockResource(data_handle);
150 if (!version_data)
151 return;
153 const wchar_t* version_string = reinterpret_cast<wchar_t*>(version_data);
154 size_t version_len = version_size / sizeof(wchar_t);
156 // The string must be terminated.
157 if (version_string[version_len - 1])
158 return;
160 previous_version_ = version_string;
163 } // namespace mini_installer