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