OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 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. | |
4 | |
5 #include "chrome/installer/setup/chrome_frame_ready_mode.h" | |
6 | |
7 #include "base/command_line.h" | |
8 #include "base/files/file_path.h" | |
9 #include "base/logging.h" | |
10 #include "base/memory/ref_counted.h" | |
11 #include "base/strings/string_util.h" | |
12 #include "base/strings/utf_string_conversions.h" | |
13 #include "base/time/time.h" | |
14 #include "base/win/registry.h" | |
15 #include "chrome/installer/setup/install.h" | |
16 #include "chrome/installer/setup/install_worker.h" | |
17 #include "chrome/installer/util/browser_distribution.h" | |
18 #include "chrome/installer/util/google_update_constants.h" | |
19 #include "chrome/installer/util/helper.h" | |
20 #include "chrome/installer/util/install_util.h" | |
21 #include "chrome/installer/util/installation_state.h" | |
22 #include "chrome/installer/util/installer_state.h" | |
23 #include "chrome/installer/util/master_preferences.h" | |
24 #include "chrome/installer/util/master_preferences_constants.h" | |
25 #include "chrome/installer/util/product.h" | |
26 #include "chrome/installer/util/util_constants.h" | |
27 #include "chrome/installer/util/work_item.h" | |
28 #include "chrome/installer/util/work_item_list.h" | |
29 | |
30 namespace installer { | |
31 | |
32 // If Chrome is not multi-installed at the appropriate level, error. | |
33 // If Chrome Frame is already multi-installed at the appropriate level, noop. | |
34 // If Chrome Frame is single-installed at the appropriate level, error. | |
35 // Add uninstall for Chrome Frame. | |
36 // Update uninstall for Chrome. | |
37 // Update ChannelInfo for all multi-installed products. | |
38 // Remove ready-mode. | |
39 InstallStatus ChromeFrameReadyModeOptIn( | |
40 const InstallationState& machine_state, | |
41 const InstallerState& installer_state) { | |
42 VLOG(1) << "Opting into Chrome Frame"; | |
43 InstallStatus status = INSTALL_REPAIRED; | |
44 | |
45 // Make sure Chrome and Chrome Frame are both multi-installed. | |
46 const ProductState* chrome_state = | |
47 machine_state.GetProductState(installer_state.system_install(), | |
48 BrowserDistribution::CHROME_BROWSER); | |
49 const ProductState* cf_state = | |
50 machine_state.GetProductState(installer_state.system_install(), | |
51 BrowserDistribution::CHROME_FRAME); | |
52 if (chrome_state == NULL) { | |
53 LOG(ERROR) << "Chrome Frame opt-in requires multi-install of Chrome."; | |
54 return CHROME_NOT_INSTALLED; | |
55 } | |
56 if (!chrome_state->is_multi_install()) { | |
57 LOG(ERROR) << "Chrome Frame opt-in requires multi-install of Chrome."; | |
58 return NON_MULTI_INSTALLATION_EXISTS; | |
59 } | |
60 if (cf_state == NULL) { | |
61 LOG(ERROR) << "Chrome Frame opt-in requires multi-install of Chrome Frame."; | |
62 return CHROME_NOT_INSTALLED; | |
63 } | |
64 if (!cf_state->is_multi_install()) { | |
65 LOG(ERROR) << "Chrome Frame opt-in requires multi-install of Chrome Frame."; | |
66 return NON_MULTI_INSTALLATION_EXISTS; | |
67 } | |
68 | |
69 // Create a new InstallerState to be used for this operation. | |
70 InstallerState opt_in_state(installer_state.level()); | |
71 | |
72 // Add the two products we're going to operate on. | |
73 const Product* chrome = | |
74 opt_in_state.AddProductFromState(BrowserDistribution::CHROME_BROWSER, | |
75 *chrome_state); | |
76 Product* cf = | |
77 opt_in_state.AddProductFromState(BrowserDistribution::CHROME_FRAME, | |
78 *cf_state); | |
79 // DCHECKs will fire in this case if it ever happens (it won't). | |
80 if (chrome == NULL || cf == NULL) | |
81 return READY_MODE_OPT_IN_FAILED; | |
82 | |
83 // Turn off ready-mode on Chrome Frame, thereby making it fully installed. | |
84 if (!cf->SetOption(kOptionReadyMode, false)) { | |
85 LOG(WARNING) | |
86 << "Chrome Frame is already fully installed; opting-in nonetheless."; | |
87 } | |
88 | |
89 // Update Chrome's uninstallation commands to only uninstall Chrome, and add | |
90 // an entry to the Add/Remove Programs dialog for GCF. | |
91 DCHECK(cf->ShouldCreateUninstallEntry() || opt_in_state.is_msi()); | |
92 | |
93 scoped_ptr<WorkItemList> item_list(WorkItem::CreateWorkItemList()); | |
94 | |
95 // This creates the uninstallation entry for GCF. | |
96 AddUninstallShortcutWorkItems(opt_in_state, cf_state->GetSetupPath(), | |
97 cf_state->version(), *cf, item_list.get()); | |
98 // This updates the Chrome uninstallation entries. | |
99 AddUninstallShortcutWorkItems(opt_in_state, chrome_state->GetSetupPath(), | |
100 chrome_state->version(), *chrome, item_list.get()); | |
101 | |
102 // Add a work item to delete the ChromeFrameReadyMode registry value. | |
103 HKEY root = opt_in_state.root_key(); | |
104 item_list->AddDeleteRegValueWorkItem(root, | |
105 opt_in_state.multi_package_binaries_distribution()->GetStateKey(), | |
106 kChromeFrameReadyModeField); | |
107 | |
108 // Update the Google Update channel ("ap") value. | |
109 AddGoogleUpdateWorkItems(machine_state, opt_in_state, item_list.get()); | |
110 | |
111 // Delete the command elevation registry keys | |
112 std::wstring version_key(cf->distribution()->GetVersionKey()); | |
113 item_list->AddDeleteRegValueWorkItem( | |
114 root, version_key, google_update::kRegCFTempOptOutCmdField); | |
115 item_list->AddDeleteRegValueWorkItem( | |
116 root, version_key, google_update::kRegCFEndTempOptOutCmdField); | |
117 item_list->AddDeleteRegValueWorkItem(root, version_key, | |
118 google_update::kRegCFOptOutCmdField); | |
119 item_list->AddDeleteRegValueWorkItem(root, version_key, | |
120 google_update::kRegCFOptInCmdField); | |
121 | |
122 if (!item_list->Do()) { | |
123 LOG(ERROR) << "Failed to opt into GCF"; | |
124 item_list->Rollback(); | |
125 status = READY_MODE_OPT_IN_FAILED; | |
126 } | |
127 | |
128 return status; | |
129 } | |
130 | |
131 const wchar_t kPostPlatformUAKey[] = | |
132 L"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\" | |
133 L"User Agent\\Post Platform"; | |
134 const wchar_t kChromeFramePrefix[] = L"chromeframe/"; | |
135 | |
136 InstallStatus ChromeFrameReadyModeTempOptOut( | |
137 const InstallationState& machine_state, | |
138 const InstallerState& installer_state) { | |
139 VLOG(1) << "Temporarily opting out of Chrome Frame"; | |
140 InstallStatus status = INSTALL_REPAIRED; | |
141 | |
142 // Make sure Chrome Frame is multi-installed. | |
143 const ProductState* cf_state = | |
144 machine_state.GetProductState(installer_state.system_install(), | |
145 BrowserDistribution::CHROME_FRAME); | |
146 if (cf_state == NULL) { | |
147 LOG(ERROR) | |
148 << "Chrome Frame temp opt-out requires multi-install of Chrome Frame."; | |
149 return CHROME_NOT_INSTALLED; | |
150 } | |
151 if (!cf_state->is_multi_install()) { | |
152 LOG(ERROR) | |
153 << "Chrome Frame temp opt-out requires multi-install of Chrome Frame."; | |
154 return NON_MULTI_INSTALLATION_EXISTS; | |
155 } | |
156 | |
157 scoped_ptr<WorkItemList> item_list(WorkItem::CreateWorkItemList()); | |
158 | |
159 HKEY root = installer_state.root_key(); | |
160 | |
161 // Add a work item to delete the ChromeFrame user agent registry value. | |
162 base::win::RegistryValueIterator values(root, kPostPlatformUAKey); | |
163 while (values.Valid()) { | |
164 const wchar_t* name = values.Name(); | |
165 if (StartsWith(name, kChromeFramePrefix, true)) { | |
166 item_list->AddDeleteRegValueWorkItem(root, kPostPlatformUAKey, name); | |
167 } | |
168 ++values; | |
169 } | |
170 | |
171 // Add a work item to update the Ready Mode state flag | |
172 int64 timestamp = base::Time::Now().ToInternalValue(); | |
173 BrowserDistribution* dist = BrowserDistribution::GetSpecificDistribution( | |
174 BrowserDistribution::CHROME_BINARIES); | |
175 item_list->AddSetRegValueWorkItem(root, dist->GetStateKey(), | |
176 kChromeFrameReadyModeField, timestamp, | |
177 true); | |
178 | |
179 if (!item_list->Do()) { | |
180 LOG(ERROR) << "Failed to temporarily opt out of GCF"; | |
181 item_list->Rollback(); | |
182 status = READY_MODE_TEMP_OPT_OUT_FAILED; | |
183 } | |
184 | |
185 return status; | |
186 } | |
187 | |
188 InstallStatus ChromeFrameReadyModeEndTempOptOut( | |
189 const InstallationState& machine_state, | |
190 const InstallerState& installer_state) { | |
191 VLOG(1) << "Ending temporary opt-out of Chrome Frame"; | |
192 InstallStatus status = INSTALL_REPAIRED; | |
193 | |
194 // Make sure Chrome Frame is multi-installed. | |
195 const ProductState* cf_state = | |
196 machine_state.GetProductState(installer_state.system_install(), | |
197 BrowserDistribution::CHROME_FRAME); | |
198 if (cf_state == NULL) { | |
199 LOG(ERROR) | |
200 << "Chrome Frame temp opt-out requires multi-install of Chrome Frame."; | |
201 return CHROME_NOT_INSTALLED; | |
202 } | |
203 if (!cf_state->is_multi_install()) { | |
204 LOG(ERROR) | |
205 << "Chrome Frame temp opt-out requires multi-install of Chrome Frame."; | |
206 return NON_MULTI_INSTALLATION_EXISTS; | |
207 } | |
208 | |
209 // Replace the ChromeFrame user agent string in the registry, modify the | |
210 // ReadyMode state flag. | |
211 const Version& installed_version = cf_state->version(); | |
212 | |
213 scoped_ptr<WorkItemList> item_list(WorkItem::CreateWorkItemList()); | |
214 | |
215 HKEY root = installer_state.root_key(); | |
216 | |
217 std::wstring chrome_frame_ua_value_name(kChromeFramePrefix); | |
218 chrome_frame_ua_value_name += ASCIIToWide(installed_version.GetString()); | |
219 | |
220 // Store the Chrome Frame user agent string | |
221 item_list->AddSetRegValueWorkItem(root, kPostPlatformUAKey, | |
222 chrome_frame_ua_value_name, L"", true); | |
223 // Add a work item to update the Ready Mode state flag | |
224 BrowserDistribution* dist = BrowserDistribution::GetSpecificDistribution( | |
225 BrowserDistribution::CHROME_BINARIES); | |
226 item_list->AddSetRegValueWorkItem(root, dist->GetStateKey(), | |
227 kChromeFrameReadyModeField, | |
228 static_cast<int64>(1), true); | |
229 | |
230 if (!item_list->Do()) { | |
231 LOG(ERROR) << "Failed to end temporary opt out of GCF"; | |
232 item_list->Rollback(); | |
233 status = READY_MODE_END_TEMP_OPT_OUT_FAILED; | |
234 } | |
235 | |
236 return status; | |
237 } | |
238 | |
239 } // namespace installer | |
OLD | NEW |