Chromium Code Reviews| 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/install.h" | 5 #include "chrome/installer/setup/install.h" |
| 6 | 6 |
| 7 #include <shlobj.h> | 7 #include <shlobj.h> |
| 8 #include <time.h> | 8 #include <time.h> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| 11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
| 12 #include "base/file_path.h" | 12 #include "base/file_path.h" |
| 13 #include "base/file_util.h" | 13 #include "base/file_util.h" |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/path_service.h" | 15 #include "base/path_service.h" |
| 16 #include "base/scoped_ptr.h" | 16 #include "base/scoped_ptr.h" |
| 17 #include "base/string_util.h" | 17 #include "base/string_util.h" |
| 18 #include "base/utf_string_conversions.h" | 18 #include "base/utf_string_conversions.h" |
| 19 #include "base/win/registry.h" | |
| 20 #include "chrome/installer/setup/setup_constants.h" | 19 #include "chrome/installer/setup/setup_constants.h" |
| 21 #include "chrome/installer/setup/install_worker.h" | 20 #include "chrome/installer/setup/install_worker.h" |
| 22 #include "chrome/installer/util/browser_distribution.h" | 21 #include "chrome/installer/util/browser_distribution.h" |
| 23 #include "chrome/installer/util/channel_info.h" | |
| 24 #include "chrome/installer/util/chrome_frame_distribution.h" | |
| 25 #include "chrome/installer/util/conditional_work_item_list.h" | |
| 26 #include "chrome/installer/util/create_reg_key_work_item.h" | 22 #include "chrome/installer/util/create_reg_key_work_item.h" |
| 27 #include "chrome/installer/util/delete_after_reboot_helper.h" | 23 #include "chrome/installer/util/delete_after_reboot_helper.h" |
| 28 #include "chrome/installer/util/google_update_constants.h" | 24 #include "chrome/installer/util/google_update_constants.h" |
| 29 #include "chrome/installer/util/helper.h" | 25 #include "chrome/installer/util/helper.h" |
| 30 #include "chrome/installer/util/install_util.h" | 26 #include "chrome/installer/util/install_util.h" |
| 31 #include "chrome/installer/util/installation_state.h" | 27 #include "chrome/installer/util/installation_state.h" |
| 32 #include "chrome/installer/util/installer_state.h" | 28 #include "chrome/installer/util/installer_state.h" |
| 33 #include "chrome/installer/util/master_preferences.h" | 29 #include "chrome/installer/util/master_preferences.h" |
| 34 #include "chrome/installer/util/master_preferences_constants.h" | 30 #include "chrome/installer/util/master_preferences_constants.h" |
| 35 #include "chrome/installer/util/package.h" | |
| 36 #include "chrome/installer/util/package_properties.h" | |
| 37 #include "chrome/installer/util/product.h" | 31 #include "chrome/installer/util/product.h" |
| 38 #include "chrome/installer/util/set_reg_value_work_item.h" | 32 #include "chrome/installer/util/set_reg_value_work_item.h" |
| 39 #include "chrome/installer/util/shell_util.h" | 33 #include "chrome/installer/util/shell_util.h" |
| 40 #include "chrome/installer/util/util_constants.h" | 34 #include "chrome/installer/util/util_constants.h" |
| 41 #include "chrome/installer/util/work_item_list.h" | 35 #include "chrome/installer/util/work_item_list.h" |
| 42 | 36 |
| 43 // Build-time generated include file. | 37 // Build-time generated include file. |
| 44 #include "installer_util_strings.h" // NOLINT | 38 #include "installer_util_strings.h" // NOLINT |
| 45 #include "registered_dlls.h" // NOLINT | 39 #include "registered_dlls.h" // NOLINT |
| 46 | 40 |
| 47 using base::win::RegKey; | |
| 48 using installer::ChannelInfo; | |
| 49 using installer::InstallerState; | 41 using installer::InstallerState; |
| 50 using installer::InstallationState; | 42 using installer::InstallationState; |
| 51 using installer::MasterPreferences; | |
| 52 using installer::Products; | |
| 53 using installer::Product; | 43 using installer::Product; |
| 54 using installer::Package; | |
| 55 using installer::PackageProperties; | |
| 56 | 44 |
| 57 namespace { | 45 namespace { |
| 58 | 46 |
| 59 void AddChromeToMediaPlayerList() { | 47 void AddChromeToMediaPlayerList() { |
| 60 std::wstring reg_path(installer::kMediaPlayerRegPath); | 48 std::wstring reg_path(installer::kMediaPlayerRegPath); |
| 61 // registry paths can also be appended like file system path | 49 // registry paths can also be appended like file system path |
| 62 file_util::AppendToPath(®_path, installer::kChromeExe); | 50 file_util::AppendToPath(®_path, installer::kChromeExe); |
| 63 VLOG(1) << "Adding Chrome to Media player list at " << reg_path; | 51 VLOG(1) << "Adding Chrome to Media player list at " << reg_path; |
| 64 scoped_ptr<WorkItem> work_item(WorkItem::CreateCreateRegKeyWorkItem( | 52 scoped_ptr<WorkItem> work_item(WorkItem::CreateCreateRegKeyWorkItem( |
| 65 HKEY_LOCAL_MACHINE, reg_path)); | 53 HKEY_LOCAL_MACHINE, reg_path)); |
| 66 | 54 |
| 67 // if the operation fails we log the error but still continue | 55 // if the operation fails we log the error but still continue |
| 68 if (!work_item.get()->Do()) | 56 if (!work_item.get()->Do()) |
| 69 LOG(ERROR) << "Could not add Chrome to media player inclusion list."; | 57 LOG(ERROR) << "Could not add Chrome to media player inclusion list."; |
| 70 } | 58 } |
| 71 | 59 |
| 72 void AddInstallerCopyTasks(const FilePath& setup_path, | 60 void AddInstallerCopyTasks(const InstallerState& installer_state, |
| 61 const FilePath& setup_path, | |
| 73 const FilePath& archive_path, | 62 const FilePath& archive_path, |
| 74 const FilePath& temp_path, | 63 const FilePath& temp_path, |
| 75 const Version& new_version, | 64 const Version& new_version, |
| 76 WorkItemList* install_list, | 65 WorkItemList* install_list) { |
| 77 const Package& package) { | |
| 78 DCHECK(install_list); | 66 DCHECK(install_list); |
| 79 FilePath installer_dir(package.GetInstallerDirectory(new_version)); | 67 FilePath installer_dir(installer_state.GetInstallerDirectory(new_version)); |
| 80 install_list->AddCreateDirWorkItem(installer_dir); | 68 install_list->AddCreateDirWorkItem(installer_dir); |
| 81 | 69 |
| 82 FilePath exe_dst(installer_dir.Append(setup_path.BaseName())); | 70 FilePath exe_dst(installer_dir.Append(setup_path.BaseName())); |
| 83 FilePath archive_dst(installer_dir.Append(archive_path.BaseName())); | 71 FilePath archive_dst(installer_dir.Append(archive_path.BaseName())); |
| 84 | 72 |
| 85 install_list->AddCopyTreeWorkItem(setup_path.value(), exe_dst.value(), | 73 install_list->AddCopyTreeWorkItem(setup_path.value(), exe_dst.value(), |
| 86 temp_path.value(), WorkItem::ALWAYS); | 74 temp_path.value(), WorkItem::ALWAYS); |
| 87 if (package.system_level()) { | 75 if (installer_state.system_install()) { |
| 88 install_list->AddCopyTreeWorkItem(archive_path.value(), archive_dst.value(), | 76 install_list->AddCopyTreeWorkItem(archive_path.value(), archive_dst.value(), |
| 89 temp_path.value(), WorkItem::ALWAYS); | 77 temp_path.value(), WorkItem::ALWAYS); |
| 90 } else { | 78 } else { |
| 91 install_list->AddMoveTreeWorkItem(archive_path.value(), archive_dst.value(), | 79 install_list->AddMoveTreeWorkItem(archive_path.value(), archive_dst.value(), |
| 92 temp_path.value()); | 80 temp_path.value()); |
| 93 } | 81 } |
| 94 } | 82 } |
| 95 | 83 |
| 96 // Adds work items that make registry adjustments for Google Update. When a | |
| 97 // product is installed (including overinstall), Google Update will write the | |
| 98 // channel ("ap") value into either Chrome or Chrome Frame's ClientState key. | |
| 99 // In the multi-install case, this value is used as the basis upon which the | |
| 100 // package's channel value is built (by adding the ordered list of installed | |
| 101 // products and their options). | |
| 102 void AddGoogleUpdateWorkItems(const InstallationState& original_state, | |
| 103 const InstallerState& installer_state, | |
| 104 const Package& package, | |
| 105 WorkItemList* install_list) { | |
| 106 // Is a multi-install product being installed or over-installed? | |
| 107 if (installer_state.operation() != InstallerState::MULTI_INSTALL) | |
| 108 return; | |
| 109 | |
| 110 const HKEY reg_root = package.system_level() ? HKEY_LOCAL_MACHINE : | |
| 111 HKEY_CURRENT_USER; | |
| 112 const std::wstring key_path = installer_state.state_key(); | |
| 113 ChannelInfo channel_info; | |
| 114 | |
| 115 // Update the "ap" value for the product being installed/updated. | |
| 116 // It is completely acceptable for there to be no "ap" value or even no | |
| 117 // ClientState key. Note that we check the registry rather than | |
| 118 // original_state since on a fresh install the "ap" value will be present | |
| 119 // sans "pv" value. | |
| 120 channel_info.Initialize(RegKey(reg_root, key_path.c_str(), KEY_QUERY_VALUE)); | |
| 121 | |
| 122 // This is a multi-install product. | |
| 123 bool modified = channel_info.SetMultiInstall(true); | |
| 124 | |
| 125 // Add the appropriate modifiers for all products and their options. | |
| 126 Products::const_iterator scan = package.products().begin(); | |
| 127 const Products::const_iterator end = package.products().end(); | |
| 128 for (; scan != end; ++scan) { | |
| 129 modified |= scan->get()->distribution()->SetChannelFlags(true, | |
| 130 &channel_info); | |
| 131 } | |
| 132 | |
| 133 // Write the results if needed. | |
| 134 if (modified) { | |
| 135 install_list->AddSetRegValueWorkItem(reg_root, key_path, | |
| 136 google_update::kRegApField, | |
| 137 channel_info.value(), true); | |
| 138 } | |
| 139 | |
| 140 // Synchronize the other products and the package with this one. | |
| 141 std::wstring other_key; | |
| 142 std::vector<std::wstring> keys; | |
| 143 | |
| 144 keys.reserve(package.products().size()); | |
| 145 other_key = package.properties()->GetStateKey(); | |
| 146 if (other_key != key_path) | |
| 147 keys.push_back(other_key); | |
| 148 scan = package.products().begin(); | |
| 149 for (; scan != end; ++scan) { | |
| 150 other_key = scan->get()->distribution()->GetStateKey(); | |
| 151 if (other_key != key_path) | |
| 152 keys.push_back(other_key); | |
| 153 } | |
| 154 | |
| 155 RegKey key; | |
| 156 ChannelInfo other_info; | |
| 157 std::vector<std::wstring>::const_iterator kscan = keys.begin(); | |
| 158 std::vector<std::wstring>::const_iterator kend = keys.end(); | |
| 159 for (; kscan != kend; ++kscan) { | |
| 160 // Handle the case where the ClientState key doesn't exist by creating it. | |
| 161 // This takes care of the multi-installer's package key, which is not | |
| 162 // created by Google Update for us. | |
| 163 if (key.Open(reg_root, kscan->c_str(), KEY_QUERY_VALUE) != ERROR_SUCCESS || | |
| 164 !other_info.Initialize(key)) { | |
| 165 other_info.set_value(std::wstring()); | |
| 166 } | |
| 167 if (!other_info.Equals(channel_info)) { | |
| 168 if (!key.Valid()) | |
| 169 install_list->AddCreateRegKeyWorkItem(reg_root, *kscan); | |
| 170 install_list->AddSetRegValueWorkItem(reg_root, *kscan, | |
| 171 google_update::kRegApField, | |
| 172 channel_info.value(), true); | |
| 173 } | |
| 174 } | |
| 175 // TODO(grt): check for other keys/values we should put in the package's | |
| 176 // ClientState and/or Clients key. | |
| 177 } | |
| 178 | |
| 179 // This is called when an MSI installation is run. It may be that a user is | |
| 180 // attempting to install the MSI on top of a non-MSI managed installation. | |
| 181 // If so, try and remove any existing uninstallation shortcuts, as we want the | |
| 182 // uninstall to be managed entirely by the MSI machinery (accessible via the | |
| 183 // Add/Remove programs dialog). | |
| 184 void AddDeleteUninstallShortcutsForMSIWorkItems(const Product& product, | |
| 185 WorkItemList* work_item_list) { | |
| 186 DCHECK(product.IsMsi()) << "This must only be called for MSI installations!"; | |
| 187 | |
| 188 // First attempt to delete the old installation's ARP dialog entry. | |
| 189 HKEY reg_root = product.system_level() ? HKEY_LOCAL_MACHINE : | |
| 190 HKEY_CURRENT_USER; | |
| 191 base::win::RegKey root_key(reg_root, L"", KEY_ALL_ACCESS); | |
| 192 std::wstring uninstall_reg(product.distribution()->GetUninstallRegPath()); | |
| 193 | |
| 194 WorkItem* delete_reg_key = work_item_list->AddDeleteRegKeyWorkItem( | |
| 195 reg_root, uninstall_reg); | |
| 196 delete_reg_key->set_ignore_failure(true); | |
| 197 | |
| 198 // Then attempt to delete the old installation's start menu shortcut. | |
| 199 FilePath uninstall_link; | |
| 200 if (product.system_level()) { | |
| 201 PathService::Get(base::DIR_COMMON_START_MENU, &uninstall_link); | |
| 202 } else { | |
| 203 PathService::Get(base::DIR_START_MENU, &uninstall_link); | |
| 204 } | |
| 205 | |
| 206 if (uninstall_link.empty()) { | |
| 207 LOG(ERROR) << "Failed to get location for shortcut."; | |
| 208 } else { | |
| 209 uninstall_link = uninstall_link.Append( | |
| 210 product.distribution()->GetAppShortCutName()); | |
| 211 uninstall_link = uninstall_link.Append( | |
| 212 product.distribution()->GetUninstallLinkName() + L".lnk"); | |
| 213 VLOG(1) << "Deleting old uninstall shortcut (if present): " | |
| 214 << uninstall_link.value(); | |
| 215 WorkItem* delete_link = work_item_list->AddDeleteTreeWorkItem( | |
| 216 uninstall_link); | |
| 217 delete_link->set_ignore_failure(true); | |
| 218 delete_link->set_log_message( | |
| 219 "Failed to delete old uninstall shortcut."); | |
| 220 } | |
| 221 } | |
| 222 | |
| 223 // Copy master preferences file provided to installer, in the same folder | 84 // Copy master preferences file provided to installer, in the same folder |
| 224 // as chrome.exe so Chrome first run can find it. This function will be called | 85 // as chrome.exe so Chrome first run can find it. This function will be called |
| 225 // only on the first install of Chrome. | 86 // only on the first install of Chrome. |
| 226 void CopyPreferenceFileForFirstRun(const Package& package, | 87 void CopyPreferenceFileForFirstRun(const InstallerState& installer_state, |
| 227 const FilePath& prefs_source_path) { | 88 const FilePath& prefs_source_path) { |
| 228 FilePath prefs_dest_path(package.path().AppendASCII( | 89 FilePath prefs_dest_path(installer_state.target_path().AppendASCII( |
| 229 installer::kDefaultMasterPrefs)); | 90 installer::kDefaultMasterPrefs)); |
| 230 if (!file_util::CopyFile(prefs_source_path, prefs_dest_path)) { | 91 if (!file_util::CopyFile(prefs_source_path, prefs_dest_path)) { |
| 231 VLOG(1) << "Failed to copy master preferences from:" | 92 VLOG(1) << "Failed to copy master preferences from:" |
| 232 << prefs_source_path.value() << " gle: " << ::GetLastError(); | 93 << prefs_source_path.value() << " gle: " << ::GetLastError(); |
| 233 } | 94 } |
| 234 } | 95 } |
| 235 | 96 |
| 236 // This method creates Chrome shortcuts in Start->Programs for all users or | 97 // This method creates Chrome shortcuts in Start->Programs for all users or |
| 237 // only for current user depending on whether it is system wide install or | 98 // only for current user depending on whether it is system wide install or |
| 238 // user only install. | 99 // user only install. |
| 239 // | 100 // |
| 240 // If first_install is true, it creates shortcuts for launching and | 101 // If first_install is true, it creates shortcuts for launching and |
| 241 // uninstalling chrome. | 102 // uninstalling chrome. |
| 242 // If first_install is false, the function only updates the shortcut for | 103 // If first_install is false, the function only updates the shortcut for |
| 243 // uninstalling chrome. According to | 104 // uninstalling chrome. According to |
| 244 // http://blogs.msdn.com/oldnewthing/archive/2005/11/24/496690.aspx, | 105 // http://blogs.msdn.com/oldnewthing/archive/2005/11/24/496690.aspx, |
| 245 // updating uninstall shortcut should not trigger Windows "new application | 106 // updating uninstall shortcut should not trigger Windows "new application |
| 246 // installed" notification. | 107 // installed" notification. |
| 247 // | 108 // |
| 248 // If the shortcuts do not exist, the function does not recreate them during | 109 // If the shortcuts do not exist, the function does not recreate them during |
| 249 // update. | 110 // update. |
| 250 bool CreateOrUpdateChromeShortcuts(const FilePath& setup_path, | 111 bool CreateOrUpdateChromeShortcuts(const InstallerState& installer_state, |
| 112 const FilePath& setup_path, | |
| 251 const Version& new_version, | 113 const Version& new_version, |
| 252 installer::InstallStatus install_status, | 114 installer::InstallStatus install_status, |
| 253 const Product& product, | 115 const Product& product, |
| 254 bool create_all_shortcut, | 116 bool create_all_shortcut, |
| 255 bool alt_shortcut) { | 117 bool alt_shortcut) { |
| 256 // TODO(tommi): Change this function to use WorkItemList. | 118 // TODO(tommi): Change this function to use WorkItemList. |
| 257 DCHECK(product.is_chrome()); | 119 DCHECK(product.is_chrome()); |
| 258 | 120 |
| 259 FilePath shortcut_path; | 121 FilePath shortcut_path; |
| 260 int dir_enum = product.system_level() ? | 122 int dir_enum = installer_state.system_install() ? |
| 261 base::DIR_COMMON_START_MENU : base::DIR_START_MENU; | 123 base::DIR_COMMON_START_MENU : base::DIR_START_MENU; |
| 262 if (!PathService::Get(dir_enum, &shortcut_path)) { | 124 if (!PathService::Get(dir_enum, &shortcut_path)) { |
| 263 LOG(ERROR) << "Failed to get location for shortcut."; | 125 LOG(ERROR) << "Failed to get location for shortcut."; |
| 264 return false; | 126 return false; |
| 265 } | 127 } |
| 266 | 128 |
| 267 BrowserDistribution* browser_dist = product.distribution(); | 129 BrowserDistribution* browser_dist = product.distribution(); |
| 268 | 130 |
| 269 // The location of Start->Programs->Google Chrome folder | 131 // The location of Start->Programs->Google Chrome folder |
| 270 const std::wstring product_name(browser_dist->GetAppShortCutName()); | 132 const std::wstring product_name(browser_dist->GetAppShortCutName()); |
| 271 const std::wstring product_desc(browser_dist->GetAppDescription()); | 133 const std::wstring product_desc(browser_dist->GetAppDescription()); |
| 272 shortcut_path = shortcut_path.Append(product_name); | 134 shortcut_path = shortcut_path.Append(product_name); |
| 273 | 135 |
| 274 // Create/update Chrome link (points to chrome.exe) & Uninstall Chrome link | 136 // Create/update Chrome link (points to chrome.exe) & Uninstall Chrome link |
| 275 // (which points to setup.exe) under this folder only if: | 137 // (which points to setup.exe) under this folder only if: |
| 276 // - This is a new install or install repair | 138 // - This is a new install or install repair |
| 277 // OR | 139 // OR |
| 278 // - The shortcut already exists in case of updates (user may have deleted | 140 // - The shortcut already exists in case of updates (user may have deleted |
| 279 // shortcuts since our install. So on updates we only update if shortcut | 141 // shortcuts since our install. So on updates we only update if shortcut |
| 280 // already exists) | 142 // already exists) |
| 281 bool ret = true; | 143 bool ret = true; |
| 282 FilePath chrome_link(shortcut_path); // Chrome link (launches Chrome) | 144 FilePath chrome_link(shortcut_path); // Chrome link (launches Chrome) |
| 283 chrome_link = chrome_link.Append(product_name + L".lnk"); | 145 chrome_link = chrome_link.Append(product_name + L".lnk"); |
| 284 // Chrome link target | 146 // Chrome link target |
| 285 FilePath chrome_exe( | 147 FilePath chrome_exe( |
| 286 product.package().path().Append(installer::kChromeExe)); | 148 installer_state.target_path().Append(installer::kChromeExe)); |
| 287 | 149 |
| 288 if ((install_status == installer::FIRST_INSTALL_SUCCESS) || | 150 if ((install_status == installer::FIRST_INSTALL_SUCCESS) || |
| 289 (install_status == installer::INSTALL_REPAIRED)) { | 151 (install_status == installer::INSTALL_REPAIRED)) { |
| 290 if (!file_util::PathExists(shortcut_path)) | 152 if (!file_util::PathExists(shortcut_path)) |
| 291 file_util::CreateDirectoryW(shortcut_path); | 153 file_util::CreateDirectoryW(shortcut_path); |
| 292 | 154 |
| 293 VLOG(1) << "Creating shortcut to " << chrome_exe.value() << " at " | 155 VLOG(1) << "Creating shortcut to " << chrome_exe.value() << " at " |
| 294 << chrome_link.value(); | 156 << chrome_link.value(); |
| 295 ret = ShellUtil::UpdateChromeShortcut(browser_dist, chrome_exe.value(), | 157 ret = ShellUtil::UpdateChromeShortcut(browser_dist, chrome_exe.value(), |
| 296 chrome_link.value(), product_desc, true); | 158 chrome_link.value(), product_desc, true); |
| 297 } else if (file_util::PathExists(chrome_link)) { | 159 } else if (file_util::PathExists(chrome_link)) { |
| 298 VLOG(1) << "Updating shortcut at " << chrome_link.value() | 160 VLOG(1) << "Updating shortcut at " << chrome_link.value() |
| 299 << " to point to " << chrome_exe.value(); | 161 << " to point to " << chrome_exe.value(); |
| 300 ret = ShellUtil::UpdateChromeShortcut(browser_dist, chrome_exe.value(), | 162 ret = ShellUtil::UpdateChromeShortcut(browser_dist, chrome_exe.value(), |
| 301 chrome_link.value(), product_desc, false); | 163 chrome_link.value(), product_desc, false); |
| 302 } else { | 164 } else { |
| 303 VLOG(1) | 165 VLOG(1) |
| 304 << "not first or repaired install, link file doesn't exist. status: " | 166 << "not first or repaired install, link file doesn't exist. status: " |
| 305 << install_status; | 167 << install_status; |
| 306 } | 168 } |
| 307 | 169 |
| 308 // Create/update uninstall link if we are not an MSI install. MSI | 170 // Create/update uninstall link if we are not an MSI install. MSI |
| 309 // installations are, for the time being, managed only through the | 171 // installations are, for the time being, managed only through the |
| 310 // Add/Remove Programs dialog. | 172 // Add/Remove Programs dialog. |
| 311 // TODO(robertshield): We could add a shortcut to msiexec /X {GUID} here. | 173 // TODO(robertshield): We could add a shortcut to msiexec /X {GUID} here. |
| 312 if (ret && !product.IsMsi()) { | 174 if (ret && !installer_state.msi()) { |
| 313 FilePath uninstall_link(shortcut_path); // Uninstall Chrome link | 175 FilePath uninstall_link(shortcut_path); // Uninstall Chrome link |
| 314 uninstall_link = uninstall_link.Append( | 176 uninstall_link = uninstall_link.Append( |
| 315 browser_dist->GetUninstallLinkName() + L".lnk"); | 177 browser_dist->GetUninstallLinkName() + L".lnk"); |
| 316 if ((install_status == installer::FIRST_INSTALL_SUCCESS) || | 178 if ((install_status == installer::FIRST_INSTALL_SUCCESS) || |
| 317 (install_status == installer::INSTALL_REPAIRED) || | 179 (install_status == installer::INSTALL_REPAIRED) || |
| 318 (file_util::PathExists(uninstall_link))) { | 180 (file_util::PathExists(uninstall_link))) { |
| 319 if (!file_util::PathExists(shortcut_path)) | 181 if (!file_util::PathExists(shortcut_path)) |
| 320 file_util::CreateDirectory(shortcut_path); | 182 file_util::CreateDirectory(shortcut_path); |
| 321 | 183 |
| 322 FilePath setup_exe( | 184 FilePath setup_exe(installer_state.GetInstallerDirectory(new_version) |
| 323 product.package().GetInstallerDirectory(new_version) | 185 .Append(setup_path.BaseName())); |
| 324 .Append(setup_path.BaseName())); | |
| 325 | 186 |
| 326 CommandLine arguments(CommandLine::NO_PROGRAM); | 187 CommandLine arguments(CommandLine::NO_PROGRAM); |
| 327 AppendUninstallCommandLineFlags(&arguments, product); | 188 AppendUninstallCommandLineFlags(installer_state, product, &arguments); |
| 328 VLOG(1) << "Creating/updating uninstall link at " | 189 VLOG(1) << "Creating/updating uninstall link at " |
| 329 << uninstall_link.value(); | 190 << uninstall_link.value(); |
| 330 ret = file_util::CreateShortcutLink(setup_exe.value().c_str(), | 191 ret = file_util::CreateShortcutLink(setup_exe.value().c_str(), |
| 331 uninstall_link.value().c_str(), | 192 uninstall_link.value().c_str(), |
| 332 NULL, | 193 NULL, |
| 333 arguments.command_line_string().c_str(), | 194 arguments.command_line_string().c_str(), |
| 334 NULL, | 195 NULL, |
| 335 setup_exe.value().c_str(), | 196 setup_exe.value().c_str(), |
| 336 0, | 197 0, |
| 337 NULL); | 198 NULL); |
| 338 } | 199 } |
| 339 } | 200 } |
| 340 | 201 |
| 341 // Update Desktop and Quick Launch shortcuts. If --create-new-shortcuts | 202 // Update Desktop and Quick Launch shortcuts. If --create-new-shortcuts |
| 342 // is specified we want to create them, otherwise we update them only if | 203 // is specified we want to create them, otherwise we update them only if |
| 343 // they exist. | 204 // they exist. |
| 344 if (ret) { | 205 if (ret) { |
| 345 if (product.system_level()) { | 206 if (installer_state.system_install()) { |
| 346 ret = ShellUtil::CreateChromeDesktopShortcut(product.distribution(), | 207 ret = ShellUtil::CreateChromeDesktopShortcut(product.distribution(), |
| 347 chrome_exe.value(), product_desc, ShellUtil::SYSTEM_LEVEL, | 208 chrome_exe.value(), product_desc, ShellUtil::SYSTEM_LEVEL, |
| 348 alt_shortcut, create_all_shortcut); | 209 alt_shortcut, create_all_shortcut); |
| 349 if (ret) { | 210 if (ret) { |
| 350 ret = ShellUtil::CreateChromeQuickLaunchShortcut( | 211 ret = ShellUtil::CreateChromeQuickLaunchShortcut( |
| 351 product.distribution(), chrome_exe.value(), | 212 product.distribution(), chrome_exe.value(), |
| 352 ShellUtil::CURRENT_USER | ShellUtil::SYSTEM_LEVEL, | 213 ShellUtil::CURRENT_USER | ShellUtil::SYSTEM_LEVEL, |
| 353 create_all_shortcut); | 214 create_all_shortcut); |
| 354 } | 215 } |
| 355 } else { | 216 } else { |
| 356 ret = ShellUtil::CreateChromeDesktopShortcut(product.distribution(), | 217 ret = ShellUtil::CreateChromeDesktopShortcut(product.distribution(), |
| 357 chrome_exe.value(), product_desc, ShellUtil::CURRENT_USER, | 218 chrome_exe.value(), product_desc, ShellUtil::CURRENT_USER, |
| 358 alt_shortcut, create_all_shortcut); | 219 alt_shortcut, create_all_shortcut); |
| 359 if (ret) { | 220 if (ret) { |
| 360 ret = ShellUtil::CreateChromeQuickLaunchShortcut( | 221 ret = ShellUtil::CreateChromeQuickLaunchShortcut( |
| 361 product.distribution(), chrome_exe.value(), ShellUtil::CURRENT_USER, | 222 product.distribution(), chrome_exe.value(), ShellUtil::CURRENT_USER, |
| 362 create_all_shortcut); | 223 create_all_shortcut); |
| 363 } | 224 } |
| 364 } | 225 } |
| 365 } | 226 } |
| 366 | 227 |
| 367 return ret; | 228 return ret; |
| 368 } | 229 } |
| 369 | 230 |
| 370 | 231 void RegisterChromeOnMachine(const InstallerState& installer_state, |
| 371 void RegisterChromeOnMachine(const Product& product, | 232 const Product& product, |
| 372 bool make_chrome_default) { | 233 bool make_chrome_default) { |
| 373 DCHECK(product.is_chrome()); | 234 DCHECK(product.is_chrome()); |
| 374 | 235 |
| 375 // Try to add Chrome to Media Player shim inclusion list. We don't do any | 236 // Try to add Chrome to Media Player shim inclusion list. We don't do any |
| 376 // error checking here because this operation will fail if user doesn't | 237 // error checking here because this operation will fail if user doesn't |
| 377 // have admin rights and we want to ignore the error. | 238 // have admin rights and we want to ignore the error. |
| 378 AddChromeToMediaPlayerList(); | 239 AddChromeToMediaPlayerList(); |
| 379 | 240 |
| 380 // Is --make-chrome-default option is given we make Chrome default browser | 241 // Is --make-chrome-default option is given we make Chrome default browser |
| 381 // otherwise we only register it on the machine as a valid browser. | 242 // otherwise we only register it on the machine as a valid browser. |
| 382 FilePath chrome_exe( | 243 FilePath chrome_exe( |
| 383 product.package().path().Append(installer::kChromeExe)); | 244 installer_state.target_path().Append(installer::kChromeExe)); |
| 384 VLOG(1) << "Registering Chrome as browser: " << chrome_exe.value(); | 245 VLOG(1) << "Registering Chrome as browser: " << chrome_exe.value(); |
| 385 if (make_chrome_default) { | 246 if (make_chrome_default) { |
| 386 int level = ShellUtil::CURRENT_USER; | 247 int level = ShellUtil::CURRENT_USER; |
| 387 if (product.system_level()) | 248 if (installer_state.system_install()) |
| 388 level = level | ShellUtil::SYSTEM_LEVEL; | 249 level = level | ShellUtil::SYSTEM_LEVEL; |
| 389 ShellUtil::MakeChromeDefault(product.distribution(), level, | 250 ShellUtil::MakeChromeDefault(product.distribution(), level, |
| 390 chrome_exe.value(), true); | 251 chrome_exe.value(), true); |
| 391 } else { | 252 } else { |
| 392 ShellUtil::RegisterChromeBrowser(product.distribution(), chrome_exe.value(), | 253 ShellUtil::RegisterChromeBrowser(product.distribution(), chrome_exe.value(), |
| 393 L"", false); | 254 L"", false); |
| 394 } | 255 } |
| 395 } | 256 } |
| 396 | 257 |
| 397 // This function installs a new version of Chrome to the specified location. | 258 // This function installs a new version of Chrome to the specified location. |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 410 // This function makes best effort to do installation in a transactional | 271 // This function makes best effort to do installation in a transactional |
| 411 // manner. If failed it tries to rollback all changes on the file system | 272 // manner. If failed it tries to rollback all changes on the file system |
| 412 // and registry. For example, if package exists before calling the | 273 // and registry. For example, if package exists before calling the |
| 413 // function, it rolls back all new file and directory changes under | 274 // function, it rolls back all new file and directory changes under |
| 414 // package. If package does not exist before calling the function | 275 // package. If package does not exist before calling the function |
| 415 // (typical new install), the function creates package during install | 276 // (typical new install), the function creates package during install |
| 416 // and removes the whole directory during rollback. | 277 // and removes the whole directory during rollback. |
| 417 installer::InstallStatus InstallNewVersion( | 278 installer::InstallStatus InstallNewVersion( |
| 418 const InstallationState& original_state, | 279 const InstallationState& original_state, |
| 419 const InstallerState& installer_state, | 280 const InstallerState& installer_state, |
| 420 bool multi_install, | |
| 421 const FilePath& setup_path, | 281 const FilePath& setup_path, |
| 422 const FilePath& archive_path, | 282 const FilePath& archive_path, |
| 423 const FilePath& src_path, | 283 const FilePath& src_path, |
| 424 const FilePath& temp_dir, | 284 const FilePath& temp_dir, |
| 425 const Version& new_version, | 285 const Version& new_version, |
| 426 scoped_ptr<Version>* current_version, | 286 scoped_ptr<Version>* current_version) { |
| 427 const Package& package) { | |
| 428 DCHECK(current_version); | 287 DCHECK(current_version); |
| 429 | 288 |
| 430 current_version->reset(package.GetCurrentVersion()); | 289 current_version->reset(installer_state.GetCurrentVersion(original_state)); |
| 431 scoped_ptr<WorkItemList> install_list(WorkItem::CreateWorkItemList()); | 290 scoped_ptr<WorkItemList> install_list(WorkItem::CreateWorkItemList()); |
| 432 | 291 |
| 433 AddInstallWorkItems(original_state, | 292 AddInstallWorkItems(original_state, |
| 434 installer_state, | 293 installer_state, |
| 435 multi_install, | |
| 436 setup_path, | 294 setup_path, |
| 437 archive_path, | 295 archive_path, |
| 438 src_path, | 296 src_path, |
| 439 temp_dir, | 297 temp_dir, |
| 440 new_version, | 298 new_version, |
| 441 current_version, | 299 current_version, |
| 442 package, | |
| 443 install_list.get()); | 300 install_list.get()); |
| 444 | 301 |
| 445 FilePath new_chrome_exe( | 302 FilePath new_chrome_exe( |
| 446 package.path().Append(installer::kChromeNewExe)); | 303 installer_state.target_path().Append(installer::kChromeNewExe)); |
| 447 | 304 |
| 448 if (!install_list->Do()) { | 305 if (!install_list->Do()) { |
| 449 installer::InstallStatus result = | 306 installer::InstallStatus result = |
| 450 file_util::PathExists(new_chrome_exe) && current_version->get() && | 307 file_util::PathExists(new_chrome_exe) && current_version->get() && |
| 451 new_version.Equals(*current_version->get()) ? | 308 new_version.Equals(*current_version->get()) ? |
| 452 installer::SAME_VERSION_REPAIR_FAILED : | 309 installer::SAME_VERSION_REPAIR_FAILED : |
| 453 installer::INSTALL_FAILED; | 310 installer::INSTALL_FAILED; |
| 454 LOG(ERROR) << "Install failed, rolling back... result: " << result; | 311 LOG(ERROR) << "Install failed, rolling back... result: " << result; |
| 455 install_list->Rollback(); | 312 install_list->Rollback(); |
| 456 LOG(ERROR) << "Rollback complete. "; | 313 LOG(ERROR) << "Rollback complete. "; |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 481 << ", new version: " << new_version.GetString() | 338 << ", new version: " << new_version.GetString() |
| 482 << ", old version: " << (*current_version)->GetString(); | 339 << ", old version: " << (*current_version)->GetString(); |
| 483 | 340 |
| 484 return installer::INSTALL_FAILED; | 341 return installer::INSTALL_FAILED; |
| 485 } | 342 } |
| 486 | 343 |
| 487 } // end namespace | 344 } // end namespace |
| 488 | 345 |
| 489 namespace installer { | 346 namespace installer { |
| 490 | 347 |
| 491 installer::InstallStatus InstallOrUpdateProduct( | 348 InstallStatus InstallOrUpdateProduct( |
| 492 const InstallationState& original_state, | 349 const InstallationState& original_state, |
| 493 const InstallerState& installer_state, | 350 const InstallerState& installer_state, |
| 494 const FilePath& setup_path, const FilePath& archive_path, | 351 const FilePath& setup_path, const FilePath& archive_path, |
| 495 const FilePath& install_temp_path, const FilePath& prefs_path, | 352 const FilePath& install_temp_path, const FilePath& prefs_path, |
| 496 const installer::MasterPreferences& prefs, const Version& new_version, | 353 const MasterPreferences& prefs, const Version& new_version) { |
|
robertshield
2011/01/20 22:06:06
could we put each of these parameters on a separat
grt (UTC plus 2)
2011/01/21 05:27:51
Done.
| |
| 497 const Package& install) { | |
| 498 FilePath src_path(install_temp_path); | 354 FilePath src_path(install_temp_path); |
| 499 src_path = src_path.Append(kInstallSourceDir).Append(kInstallSourceChromeDir); | 355 src_path = src_path.Append(kInstallSourceDir).Append(kInstallSourceChromeDir); |
| 500 | 356 |
| 501 // TODO(robertshield): Removing the pending on-reboot moves should be done | 357 // TODO(robertshield): Removing the pending on-reboot moves should be done |
| 502 // elsewhere. | 358 // elsewhere. |
| 503 const Products& products = install.products(); | 359 const Products& products = installer_state.products(); |
| 504 DCHECK(products.size()); | 360 DCHECK(products.size()); |
| 505 if (FindProduct(products, BrowserDistribution::CHROME_FRAME)) { | 361 if (installer_state.FindProduct(BrowserDistribution::CHROME_FRAME)) { |
| 506 // Make sure that we don't end up deleting installed files on next reboot. | 362 // Make sure that we don't end up deleting installed files on next reboot. |
| 507 if (!RemoveFromMovesPendingReboot(install.path().value().c_str())) { | 363 if (!RemoveFromMovesPendingReboot( |
| 364 installer_state.target_path().value().c_str())) { | |
| 508 LOG(ERROR) << "Error accessing pending moves value."; | 365 LOG(ERROR) << "Error accessing pending moves value."; |
| 509 } | 366 } |
| 510 } | 367 } |
| 511 | 368 |
| 512 scoped_ptr<Version> existing_version; | 369 scoped_ptr<Version> existing_version; |
| 513 installer::InstallStatus result = InstallNewVersion(original_state, | 370 InstallStatus result = InstallNewVersion(original_state, installer_state, |
| 514 installer_state, prefs.is_multi_install(), setup_path, archive_path, | 371 setup_path, archive_path, src_path, install_temp_path, new_version, |
| 515 src_path, install_temp_path, new_version, &existing_version, install); | 372 &existing_version); |
| 516 | 373 |
| 517 // TODO(robertshield): Everything below this line should instead be captured | 374 // TODO(robertshield): Everything below this line should instead be captured |
| 518 // by WorkItems. | 375 // by WorkItems. |
| 519 if (!InstallUtil::GetInstallReturnCode(result)) { | 376 if (!InstallUtil::GetInstallReturnCode(result)) { |
| 520 if (result == installer::FIRST_INSTALL_SUCCESS && !prefs_path.empty()) | 377 if (result == FIRST_INSTALL_SUCCESS && !prefs_path.empty()) |
| 521 CopyPreferenceFileForFirstRun(install, prefs_path); | 378 CopyPreferenceFileForFirstRun(installer_state, prefs_path); |
| 522 | 379 |
| 523 bool do_not_create_shortcuts = false; | 380 bool do_not_create_shortcuts = false; |
| 524 prefs.GetBool(installer::master_preferences::kDoNotCreateShortcuts, | 381 prefs.GetBool(master_preferences::kDoNotCreateShortcuts, |
| 525 &do_not_create_shortcuts); | 382 &do_not_create_shortcuts); |
| 526 | 383 |
| 527 // Currently this only creates shortcuts for Chrome, but for other products | 384 // Currently this only creates shortcuts for Chrome, but for other products |
| 528 // we might want to create shortcuts. | 385 // we might want to create shortcuts. |
| 529 const Product* chrome_install = | 386 const Product* chrome_install = |
| 530 FindProduct(install.products(), BrowserDistribution::CHROME_BROWSER); | 387 installer_state.FindProduct(BrowserDistribution::CHROME_BROWSER); |
| 531 if (chrome_install && !do_not_create_shortcuts) { | 388 if (chrome_install && !do_not_create_shortcuts) { |
| 532 bool create_all_shortcut = false; | 389 bool create_all_shortcut = false; |
| 533 prefs.GetBool(installer::master_preferences::kCreateAllShortcuts, | 390 prefs.GetBool(master_preferences::kCreateAllShortcuts, |
| 534 &create_all_shortcut); | 391 &create_all_shortcut); |
| 535 bool alt_shortcut = false; | 392 bool alt_shortcut = false; |
| 536 prefs.GetBool(installer::master_preferences::kAltShortcutText, | 393 prefs.GetBool(master_preferences::kAltShortcutText, &alt_shortcut); |
| 537 &alt_shortcut); | 394 if (!CreateOrUpdateChromeShortcuts(installer_state, setup_path, |
| 538 if (!CreateOrUpdateChromeShortcuts(setup_path, new_version, result, | 395 new_version, result, *chrome_install, |
| 539 *chrome_install, create_all_shortcut, | 396 create_all_shortcut, alt_shortcut)) { |
| 540 alt_shortcut)) { | |
| 541 PLOG(WARNING) << "Failed to create/update start menu shortcut."; | 397 PLOG(WARNING) << "Failed to create/update start menu shortcut."; |
| 542 } | 398 } |
| 543 | 399 |
| 544 bool make_chrome_default = false; | 400 bool make_chrome_default = false; |
| 545 prefs.GetBool(installer::master_preferences::kMakeChromeDefault, | 401 prefs.GetBool(master_preferences::kMakeChromeDefault, |
| 546 &make_chrome_default); | 402 &make_chrome_default); |
| 547 | 403 |
| 548 // If this is not the user's first Chrome install, but they have chosen | 404 // If this is not the user's first Chrome install, but they have chosen |
| 549 // Chrome to become their default browser on the download page, we must | 405 // Chrome to become their default browser on the download page, we must |
| 550 // force it here because the master_preferences file will not get copied | 406 // force it here because the master_preferences file will not get copied |
| 551 // into the build. | 407 // into the build. |
| 552 bool force_chrome_default_for_user = false; | 408 bool force_chrome_default_for_user = false; |
| 553 if (result == installer::NEW_VERSION_UPDATED || | 409 if (result == NEW_VERSION_UPDATED || |
| 554 result == installer::INSTALL_REPAIRED) { | 410 result == INSTALL_REPAIRED) { |
| 555 prefs.GetBool( | 411 prefs.GetBool(master_preferences::kMakeChromeDefaultForUser, |
| 556 installer::master_preferences::kMakeChromeDefaultForUser, | 412 &force_chrome_default_for_user); |
| 557 &force_chrome_default_for_user); | |
| 558 } | 413 } |
| 559 | 414 |
| 560 RegisterChromeOnMachine(*chrome_install, | 415 RegisterChromeOnMachine(installer_state, *chrome_install, |
| 561 make_chrome_default || force_chrome_default_for_user); | 416 make_chrome_default || force_chrome_default_for_user); |
| 562 } | 417 } |
| 563 | 418 |
| 564 install.RemoveOldVersionDirectories(existing_version.get() ? | 419 installer_state.RemoveOldVersionDirectories(existing_version.get() ? |
| 565 *existing_version.get() : new_version); | 420 *existing_version.get() : new_version); |
| 566 } | 421 } |
| 567 | 422 |
| 568 return result; | 423 return result; |
| 569 } | 424 } |
| 570 | 425 |
| 571 } // namespace installer | 426 } // namespace installer |
| OLD | NEW |