summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkuchhal@chromium.org <kuchhal@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2008-10-20 19:01:13 +0000
committerkuchhal@chromium.org <kuchhal@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2008-10-20 19:01:13 +0000
commit452fc5418259b01cdd2d92c00e03780ef04b4be4 (patch)
tree597bc2da45d6cedcb366a2aea55ab3ce68eb8e3d
parent2ceafa3ddbaaa90ff73abf9941eae217c7808710 (diff)
downloadchromium_src-452fc5418259b01cdd2d92c00e03780ef04b4be4.zip
chromium_src-452fc5418259b01cdd2d92c00e03780ef04b4be4.tar.gz
chromium_src-452fc5418259b01cdd2d92c00e03780ef04b4be4.tar.bz2
Now omaha supports displaying custom error string through registry keys.
Add error strings in Chrome installer. git-svn-id: svn://svn.chromium.org/chrome/trunk/src@3616 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/app/chromium_strings.grd30
-rw-r--r--chrome/app/google_chrome_strings.grd30
-rw-r--r--chrome/installer/setup/install.cc13
-rw-r--r--chrome/installer/setup/main.cc730
-rw-r--r--chrome/installer/setup/setup.cc9
-rw-r--r--chrome/installer/util/google_chrome_distribution.cc2
-rw-r--r--chrome/installer/util/install_util.cc20
-rwxr-xr-xchrome/installer/util/install_util.h6
-rw-r--r--chrome/installer/util/prebuild/create_string_rc.py10
-rw-r--r--chrome/installer/util/util_constants.h2
10 files changed, 481 insertions, 371 deletions
diff --git a/chrome/app/chromium_strings.grd b/chrome/app/chromium_strings.grd
index a900675..a7ae7b9 100644
--- a/chrome/app/chromium_strings.grd
+++ b/chrome/app/chromium_strings.grd
@@ -211,6 +211,36 @@ be available for now. -->
<message name="IDS_MACHINE_LEVEL_INSTALL_CONFLICT" desc="Error message to display when user tries to run user level Chromium even though machine level Chromium is already installed.">
System level Chromium is already installed on this computer. We will replace your user level Chromium with the system level installation.
</message>
+ <message name="IDS_INSTALL_HIGHER_VERSION" desc="Error displayed when higher version already exists.">
+ A newer version of Chromium is already installed on this computer; if it no-longer works, please uninstall it before trying again.
+ </message>
+ <message name="IDS_INSTALL_USER_LEVEL_EXISTS" desc="Error displayed during system level install if user level Chromium is already installed.">
+ Chromium is already installed as a non-administrator. Please uninstall it and try again.
+ </message>
+ <message name="IDS_INSTALL_SYSTEM_LEVEL_EXISTS" desc="Error displayed during user level install if system level Chromium is already installed.">
+ Chromium is already installed as an administrator. Please uninstall it, if you want to install Chromium as a non-administrator.
+ </message>
+ <message name="IDS_INSTALL_FAILED" desc="Error displayed if installation fails due to some unknown error.">
+ Installation failed due to unspecified error. If Chromium is currently running, please close it and try again.
+ </message>
+ <message name="IDS_INSTALL_OS_NOT_SUPPORTED" desc="Error displayed if OS is not supported">
+ Your operating system is not supported - Chromium works on Windows Vista and XP SP1+.
+ </message>
+ <message name="IDS_INSTALL_OS_ERROR" desc="Error displayed when any Windows API call fails and we do not have more specific information.">
+ Your operating system encountered an unspecified error during installation.
+ </message>
+ <message name="IDS_INSTALL_TEMP_DIR_FAILED" desc="Error displayed when we fail to create temporary directory during installation.">
+ Could not create temporary directory for installer; please check for permissions and free space on hard disk.
+ </message>
+ <message name="IDS_INSTALL_UNCOMPRESSION_FAILED" desc="Error when when we can not uncompress installation archive.">
+ Failed to uncompress installer archive. Please try downloading Chromium again.
+ </message>
+ <message name="IDS_INSTALL_INVALID_ARCHIVE" desc="Error displayed when we can not open the installation archive.">
+ Installer archive is corrupted or invalid. Please try downloading Chromium again.
+ </message>
+ <message name="IDS_UNINSTALL_FAILED" desc="Error during uninstall if we can not find the installation directory from registry.">
+ Chromium is not installed or failed to find installation directory from registry.
+ </message>
</messages>
</release>
</grit>
diff --git a/chrome/app/google_chrome_strings.grd b/chrome/app/google_chrome_strings.grd
index f1e21bf..4bec75e 100644
--- a/chrome/app/google_chrome_strings.grd
+++ b/chrome/app/google_chrome_strings.grd
@@ -250,6 +250,36 @@ Chrome supports. -->
<message name="IDS_MACHINE_LEVEL_INSTALL_CONFLICT" desc="Error message to display when user tries to run user level Chromium even though machine level Chromium is already installed.">
System level Google Chrome is already installed on this computer. We will replace your user level Google Chrome with the system level installation.
</message>
+ <message name="IDS_INSTALL_HIGHER_VERSION" desc="Error displayed when higher version already exists.">
+ A newer version of Google Chrome is already installed on this computer; if it no-longer works, please uninstall it before trying again.
+ </message>
+ <message name="IDS_INSTALL_USER_LEVEL_EXISTS" desc="Error displayed during system level install if user level Chromium is already installed.">
+ Google Chrome is already installed as a non-administrator. Please uninstall it and try again.
+ </message>
+ <message name="IDS_INSTALL_SYSTEM_LEVEL_EXISTS" desc="Error displayed during user level install if system level Chromium is already installed.">
+ Google Chrome is already installed as an administrator. Please uninstall it, if you want to install Google Chrome as a non-administrator.
+ </message>
+ <message name="IDS_INSTALL_FAILED" desc="Error displayed if installation fails due to some unknown error.">
+ Installation failed due to unspecified error. If Google Chrome is currently running, please close it and try again.
+ </message>
+ <message name="IDS_INSTALL_OS_NOT_SUPPORTED" desc="Error displayed if OS is not supported">
+ Your operating system is not supported - Google Chrome works on Windows Vista and XP SP1+.
+ </message>
+ <message name="IDS_INSTALL_OS_ERROR" desc="Error displayed when any Windows API call fails and we do not have more specific information.">
+ Your operating system encountered an unspecified error during installation.
+ </message>
+ <message name="IDS_INSTALL_TEMP_DIR_FAILED" desc="Error displayed when we fail to create temporary directory during installation.">
+ Could not create temporary directory for installer; please check for permissions and free space on hard disk.
+ </message>
+ <message name="IDS_INSTALL_UNCOMPRESSION_FAILED" desc="Error when when we can not uncompress installation archive.">
+ Failed to uncompress installer archive. Please try downloading Google Chrome again.
+ </message>
+ <message name="IDS_INSTALL_INVALID_ARCHIVE" desc="Error displayed when we can not open the installation archive.">
+ Installer archive is corrupted or invalid. Please try downloading Google Chrome again.
+ </message>
+ <message name="IDS_UNINSTALL_FAILED" desc="Error during uninstall if we can not find the installation directory from registry.">
+ Google Chrome is not installed or failed to find installation directory from registry.
+ </message>
</messages>
</release>
</grit>
diff --git a/chrome/installer/setup/install.cc b/chrome/installer/setup/install.cc
index 7a0a2dd..34429b3 100644
--- a/chrome/installer/setup/install.cc
+++ b/chrome/installer/setup/install.cc
@@ -10,21 +10,8 @@
#include "chrome/installer/setup/setup.h"
#include "chrome/installer/setup/setup_constants.h"
#include "chrome/installer/util/browser_distribution.h"
-#include "chrome/installer/util/copy_tree_work_item.h"
-#include "chrome/installer/util/create_dir_work_item.h"
-#include "chrome/installer/util/create_reg_key_work_item.h"
-#include "chrome/installer/util/delete_tree_work_item.h"
-#include "chrome/installer/util/install_util.h"
-#include "chrome/installer/util/l10n_string_util.h"
-#include "chrome/installer/util/logging_installer.h"
#include "chrome/installer/util/google_update_constants.h"
-#include "chrome/installer/util/set_reg_value_work_item.h"
#include "chrome/installer/util/shell_util.h"
-#include "chrome/installer/util/util_constants.h"
-#include "chrome/installer/util/version.h"
-#include "chrome/installer/util/work_item_list.h"
-
-#include "installer_util_strings.h"
namespace {
std::wstring AppendPath(const std::wstring parent_path,
diff --git a/chrome/installer/setup/main.cc b/chrome/installer/setup/main.cc
index 6a019ff..10cef00 100644
--- a/chrome/installer/setup/main.cc
+++ b/chrome/installer/setup/main.cc
@@ -1,353 +1,377 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <string>
-#include <windows.h>
-#include <msi.h>
-#include <shlobj.h>
-
-#include "base/at_exit.h"
-#include "base/basictypes.h"
-#include "base/command_line.h"
-#include "base/file_util.h"
-#include "base/path_service.h"
-#include "base/registry.h"
-#include "base/string_util.h"
-#include "base/win_util.h"
-#include "chrome/installer/setup/setup.h"
-#include "chrome/installer/setup/setup_constants.h"
-#include "chrome/installer/setup/uninstall.h"
-#include "chrome/installer/util/browser_distribution.h"
-#include "chrome/installer/util/delete_tree_work_item.h"
-#include "chrome/installer/util/helper.h"
-#include "chrome/installer/util/install_util.h"
-#include "chrome/installer/util/logging_installer.h"
-#include "chrome/installer/util/lzma_util.h"
-#include "chrome/installer/util/google_update_constants.h"
-#include "chrome/installer/util/shell_util.h"
-#include "chrome/installer/util/util_constants.h"
-#include "chrome/installer/util/work_item.h"
-#include "third_party/bspatch/mbspatch.h"
-
-namespace {
-
-// Applies a binary patch to existing Chrome installer archive on the system.
-// Uses bspatch library.
-int PatchArchiveFile(bool system_install, const std::wstring& archive_path,
- const std::wstring& uncompressed_archive,
- const installer::Version* installed_version) {
- std::wstring existing_archive =
- installer::GetChromeInstallPath(system_install);
- file_util::AppendToPath(&existing_archive,
- installed_version->GetString());
- file_util::AppendToPath(&existing_archive, installer::kInstallerDir);
- file_util::AppendToPath(&existing_archive, installer::kChromeArchive);
-
- std::wstring patch_archive(archive_path);
- file_util::AppendToPath(&patch_archive, installer::kChromePatchArchive);
-
- LOG(INFO) << "Applying patch " << patch_archive
- << " to file " << existing_archive
- << " and generating file " << uncompressed_archive;
- return ApplyBinaryPatch(existing_archive.c_str(),
- patch_archive.c_str(),
- uncompressed_archive.c_str());
-}
-
-
-// This method unpacks and uncompresses the given archive file. For Chrome
-// install we are creating a uncompressed archive that contains all the files
-// needed for the installer. This uncompressed archive is later compressed.
-//
-// This method first uncompresses archive specified by parameter "archive"
-// and assumes that it will result in an uncompressed full archive file
-// (chrome.7z) or uncompressed patch archive file (patch.7z). If it is patch
-// archive file, the patch is applied to the old archive file that should be
-// present on the system already. As the final step the new archive file
-// is unpacked in the path specified by parameter "path".
-DWORD UnPackArchive(const std::wstring& archive, bool system_install,
- const installer::Version* installed_version,
- const std::wstring& temp_path, const std::wstring& path,
- bool& incremental_install) {
- DWORD ret = NO_ERROR;
- installer::LzmaUtil util;
- // First uncompress the payload. This could be a differential
- // update (patch.7z) or full archive (chrome.7z). If this uncompress fails
- // return with error.
- LOG(INFO) << "Opening archive " << archive;
- if ((ret = util.OpenArchive(archive)) != NO_ERROR) {
- LOG(ERROR) << "Unable to open install archive: " << archive;
- } else {
- LOG(INFO) << "Uncompressing archive to path " << temp_path;
- if ((ret = util.UnPack(temp_path)) != NO_ERROR) {
- LOG(ERROR) << "Error during uncompression: " << ret;
- }
- util.CloseArchive();
- }
- if (ret != NO_ERROR)
- return ret;
-
- std::wstring archive_name = file_util::GetFilenameFromPath(archive);
- std::wstring uncompressed_archive(temp_path);
- file_util::AppendToPath(&uncompressed_archive, installer::kChromeArchive);
- // Check if this is differential update and if it is, patch it to the
- // installer archive that should already be on the machine.
- std::wstring prefix = installer::kChromeCompressedPatchArchivePrefix;
- if ((archive_name.size() >= prefix.size()) &&
- (std::equal(prefix.begin(), prefix.end(), archive_name.begin(),
- CaseInsensitiveCompare<wchar_t>()))) {
- LOG(INFO) << "Differential patch found. Applying to existing archive.";
- incremental_install = true;
- if (!installed_version) {
- LOG(ERROR) << "Can not use differential update when Chrome is not "
- << "installed on the system.";
- return 1;
- }
- if (int i = PatchArchiveFile(system_install, temp_path,
- uncompressed_archive, installed_version)) {
- LOG(ERROR) << "Binary patching failed with error " << i;
- return 1;
- }
- }
-
- // If we got the uncompressed archive, lets unpack it
- LOG(INFO) << "Opening archive " << uncompressed_archive;
- if ((ret = util.OpenArchive(uncompressed_archive)) != NO_ERROR) {
- LOG(ERROR) << "Unable to open install archive: " <<
- uncompressed_archive;
- } else {
- LOG(INFO) << "Unpacking archive to path " << path;
- if ((ret = util.UnPack(path)) != NO_ERROR) {
- LOG(ERROR) << "Error during uncompression: " << ret;
- }
- util.CloseArchive();
- }
-
- return ret;
-}
-
-
-// Find the version of Chrome from an install source directory.
-// Chrome_path should contain a complete and unpacked install package (i.e.
-// a Chrome directory under which there is a version folder).
-// Returns the version or NULL if no version is found.
-installer::Version* GetVersionFromDir(const std::wstring& chrome_path) {
- LOG(INFO) << "Looking for Chrome version folder under " << chrome_path;
- std::wstring root_path(chrome_path);
- file_util::AppendToPath(&root_path, L"*");
-
- WIN32_FIND_DATA find_file_data;
- HANDLE file_handle = FindFirstFile(root_path.c_str(), &find_file_data);
- BOOL ret = TRUE;
- installer::Version *version = NULL;
- // Here we are assuming that the installer we have is really valid so there
- // can not be two version directories. We exit as soon as we find a valid
- // version directory.
- while (ret) {
- if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
- LOG(INFO) << "directory found: " << find_file_data.cFileName;
- version =
- installer::Version::GetVersionFromString(find_file_data.cFileName);
- if (version) break;
- }
- ret = FindNextFile(file_handle, &find_file_data);
- }
- FindClose(file_handle);
-
- return version;
-}
-
-installer_util::InstallStatus InstallChrome(const CommandLine& cmd_line,
- const installer::Version* installed_version, bool system_install) {
- // For install the default location for chrome.packed.7z is in current
- // folder, so get that value first.
- std::wstring archive = file_util::GetDirectoryFromPath(cmd_line.program());
- file_util::AppendToPath(&archive,
- std::wstring(installer::kChromeCompressedArchive));
- // If --install-archive is given, get the user specified value
- if (cmd_line.HasSwitch(installer_util::switches::kInstallArchive)) {
- archive = cmd_line.GetSwitchValue(
- installer_util::switches::kInstallArchive);
- }
- LOG(INFO) << "Archive found to install Chrome " << archive;
-
- // Create a temp folder where we will unpack Chrome archive. If it fails,
- // then we are doomed, so return immediately and no cleanup is required.
- std::wstring temp_path;
- if (!file_util::CreateNewTempDirectory(std::wstring(L"chrome_"),
- &temp_path)) {
- LOG(ERROR) << "Could not create temporary path.";
- return installer_util::TEMP_DIR_FAILED;
- }
- LOG(INFO) << "created path " << temp_path;
-
- std::wstring unpack_path(temp_path);
- file_util::AppendToPath(&unpack_path,
- std::wstring(installer::kInstallSourceDir));
- bool incremental_install = false;
- installer_util::InstallStatus install_status = installer_util::UNKNOWN_STATUS;
- if (UnPackArchive(archive, system_install, installed_version,
- temp_path, unpack_path, incremental_install)) {
- install_status = installer_util::UNCOMPRESSION_FAILED;
- } else {
- LOG(INFO) << "unpacked to " << unpack_path;
- std::wstring src_path(unpack_path);
- file_util::AppendToPath(&src_path,
- std::wstring(installer::kInstallSourceChromeDir));
- scoped_ptr<installer::Version>
- installer_version(GetVersionFromDir(src_path));
- if (!installer_version.get()) {
- LOG(ERROR) << "Did not find any valid version in installer.";
- install_status = installer_util::INVALID_ARCHIVE;
- } else {
- LOG(INFO) << "version to install: " << installer_version->GetString();
- if (installed_version &&
- installed_version->IsHigherThan(installer_version.get())) {
- LOG(ERROR) << "Higher version is already installed.";
- install_status = installer_util::HIGHER_VERSION_EXISTS;
- } else {
- // We want to keep uncompressed archive (chrome.7z) that we get after
- // uncompressing and binary patching. Get the location for this file.
- std::wstring archive_to_copy(temp_path);
- file_util::AppendToPath(&archive_to_copy,
- std::wstring(installer::kChromeArchive));
- install_status = installer::InstallOrUpdateChrome(
- cmd_line.program(), archive_to_copy, temp_path, system_install,
- *installer_version, installed_version);
- if (install_status == installer_util::FIRST_INSTALL_SUCCESS) {
- LOG(INFO) << "First install successful. Launching Chrome.";
- installer::LaunchChrome(system_install);
- } else if (install_status == installer_util::NEW_VERSION_UPDATED) {
-#if defined(GOOGLE_CHROME_BUILD)
- // TODO(kuchhal): This is just temporary until all users move to the
- // new Chromium version which ships with gears.dll.
- LOG(INFO) << "Google Chrome updated. Uninstalling gears msi.";
- wchar_t product[39]; // GUID + '\0'
- MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL); // Don't show any UI
- for (int i = 0;
- MsiEnumRelatedProducts(google_update::kGearsUpgradeCode, 0,
- i, product) != ERROR_NO_MORE_ITEMS; ++i) {
- LOG(INFO) << "Uninstalling Gears - " << product;
- unsigned int ret = MsiConfigureProduct(product,
- INSTALLLEVEL_MAXIMUM, INSTALLSTATE_ABSENT);
- if (ret != ERROR_SUCCESS)
- LOG(ERROR) << "Failed to uninstall Gears " << product;
- }
-#endif
- }
- }
- }
- }
-
- // Delete install temporary directory.
- LOG(INFO) << "Deleting temporary directory " << temp_path;
- scoped_ptr<DeleteTreeWorkItem> delete_tree(
- WorkItem::CreateDeleteTreeWorkItem(temp_path, std::wstring()));
- delete_tree->Do();
-
- BrowserDistribution* dist = BrowserDistribution::GetDistribution();
- dist->UpdateDiffInstallStatus(system_install, incremental_install,
- install_status);
- return install_status;
-}
-
-installer_util::InstallStatus UninstallChrome(const CommandLine& cmd_line,
- const installer::Version* version,
- bool system_install) {
- LOG(INFO) << "Uninstalling Chome";
- if (!version) {
- LOG(ERROR) << "No Chrome installation found for uninstall.";
- return installer_util::CHROME_NOT_INSTALLED;
- }
-
- bool remove_all = !cmd_line.HasSwitch(
- installer_util::switches::kDoNotRemoveSharedItems);
- bool force = cmd_line.HasSwitch(installer_util::switches::kForceUninstall);
- return installer_setup::UninstallChrome(cmd_line.program(), system_install,
- *version, remove_all, force);
-}
-} // namespace
-
-
-int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance,
- wchar_t* command_line, int show_command) {
- // The exit manager is in charge of calling the dtors of singletons.
- base::AtExitManager exit_manager;
-
- // Check to make sure current system is WinXP or later. If not, log
- // error message and get out.
- if (!InstallUtil::IsOSSupported()) {
- LOG(ERROR) << "Chrome only supports Windows XP or later.";
- return installer_util::OS_NOT_SUPPORTED;
- }
-
- // Initialize COM for use later.
- if (CoInitializeEx(NULL, COINIT_APARTMENTTHREADED) != S_OK) {
- LOG(ERROR) << "COM initialization failed.";
- return installer_util::OS_ERROR;
- }
-
- CommandLine parsed_command_line;
- installer::InitInstallerLogging(parsed_command_line);
- bool system_install =
- parsed_command_line.HasSwitch(installer_util::switches::kSystemLevel);
- LOG(INFO) << "system install is " << system_install;
-
- // Check to avoid simultaneous per-user and per-machine installs.
- scoped_ptr<installer::Version>
- chrome_version(InstallUtil::GetChromeVersion(!system_install));
- if (chrome_version.get()) {
- LOG(ERROR) << "Already installed version " << chrome_version->GetString()
- << " conflicts with the current install mode.";
- return system_install ? installer_util::USER_LEVEL_INSTALL_EXISTS :
- installer_util::MACHINE_LEVEL_INSTALL_EXISTS;
- }
-
- // If --register-chrome-browser option is specified, register all
- // Chrome protocol/file associations as well as register it as a valid
- // browser for StarMenu->Internet shortcut. This option should only
- // be used when setup.exe is launched with admin rights. We do not
- // make any user specific changes in this option.
- if (parsed_command_line.HasSwitch(
- installer_util::switches::kRegisterChromeBrowser)) {
- std::wstring chrome_exe(parsed_command_line.GetSwitchValue(
- installer_util::switches::kRegisterChromeBrowser));
- return ShellUtil::AddChromeToSetAccessDefaults(chrome_exe, true);
- }
-
- if (system_install &&
- win_util::GetWinVersion() == win_util::WINVERSION_VISTA &&
- !IsUserAnAdmin()) {
- std::wstring exe = parsed_command_line.program();
- std::wstring params(command_line);
- DWORD exit_code = installer_util::UNKNOWN_STATUS;
- InstallUtil::ExecuteExeAsAdmin(exe, params, &exit_code);
- return exit_code;
- }
-
- // Check the existing version installed.
- scoped_ptr<installer::Version>
- installed_version(InstallUtil::GetChromeVersion(system_install));
- if (installed_version.get()) {
- LOG(INFO) << "version on the system: " << installed_version->GetString();
- }
-
- installer_util::InstallStatus install_status = installer_util::UNKNOWN_STATUS;
- // If --uninstall option is given, uninstall chrome
- if (parsed_command_line.HasSwitch(installer_util::switches::kUninstall)) {
- install_status = UninstallChrome(parsed_command_line,
- installed_version.get(),
- system_install);
- // If --uninstall option is not specified, we assume it is install case.
- } else {
- install_status = InstallChrome(parsed_command_line,
- installed_version.get(),
- system_install);
- }
-
- CoUninitialize();
- BrowserDistribution* dist = BrowserDistribution::GetDistribution();
- return dist->GetInstallReturnCode(install_status);
-}
-
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+#include <windows.h>
+#include <msi.h>
+#include <shlobj.h>
+
+#include "base/at_exit.h"
+#include "base/basictypes.h"
+#include "base/command_line.h"
+#include "base/file_util.h"
+#include "base/path_service.h"
+#include "base/registry.h"
+#include "base/string_util.h"
+#include "base/win_util.h"
+#include "chrome/installer/setup/setup.h"
+#include "chrome/installer/setup/setup_constants.h"
+#include "chrome/installer/setup/uninstall.h"
+#include "chrome/installer/util/browser_distribution.h"
+#include "chrome/installer/util/delete_tree_work_item.h"
+#include "chrome/installer/util/helper.h"
+#include "chrome/installer/util/install_util.h"
+#include "chrome/installer/util/logging_installer.h"
+#include "chrome/installer/util/lzma_util.h"
+#include "chrome/installer/util/google_update_constants.h"
+#include "chrome/installer/util/shell_util.h"
+#include "chrome/installer/util/util_constants.h"
+#include "chrome/installer/util/work_item.h"
+#include "third_party/bspatch/mbspatch.h"
+
+#include "installer_util_strings.h"
+
+namespace {
+
+// Applies a binary patch to existing Chrome installer archive on the system.
+// Uses bspatch library.
+int PatchArchiveFile(bool system_install, const std::wstring& archive_path,
+ const std::wstring& uncompressed_archive,
+ const installer::Version* installed_version) {
+ std::wstring existing_archive =
+ installer::GetChromeInstallPath(system_install);
+ file_util::AppendToPath(&existing_archive,
+ installed_version->GetString());
+ file_util::AppendToPath(&existing_archive, installer::kInstallerDir);
+ file_util::AppendToPath(&existing_archive, installer::kChromeArchive);
+
+ std::wstring patch_archive(archive_path);
+ file_util::AppendToPath(&patch_archive, installer::kChromePatchArchive);
+
+ LOG(INFO) << "Applying patch " << patch_archive
+ << " to file " << existing_archive
+ << " and generating file " << uncompressed_archive;
+ return ApplyBinaryPatch(existing_archive.c_str(),
+ patch_archive.c_str(),
+ uncompressed_archive.c_str());
+}
+
+
+// This method unpacks and uncompresses the given archive file. For Chrome
+// install we are creating a uncompressed archive that contains all the files
+// needed for the installer. This uncompressed archive is later compressed.
+//
+// This method first uncompresses archive specified by parameter "archive"
+// and assumes that it will result in an uncompressed full archive file
+// (chrome.7z) or uncompressed patch archive file (patch.7z). If it is patch
+// archive file, the patch is applied to the old archive file that should be
+// present on the system already. As the final step the new archive file
+// is unpacked in the path specified by parameter "path".
+DWORD UnPackArchive(const std::wstring& archive, bool system_install,
+ const installer::Version* installed_version,
+ const std::wstring& temp_path, const std::wstring& path,
+ bool& incremental_install) {
+ DWORD ret = NO_ERROR;
+ installer::LzmaUtil util;
+ // First uncompress the payload. This could be a differential
+ // update (patch.7z) or full archive (chrome.7z). If this uncompress fails
+ // return with error.
+ LOG(INFO) << "Opening archive " << archive;
+ if ((ret = util.OpenArchive(archive)) != NO_ERROR) {
+ LOG(ERROR) << "Unable to open install archive: " << archive;
+ } else {
+ LOG(INFO) << "Uncompressing archive to path " << temp_path;
+ if ((ret = util.UnPack(temp_path)) != NO_ERROR) {
+ LOG(ERROR) << "Error during uncompression: " << ret;
+ }
+ util.CloseArchive();
+ }
+ if (ret != NO_ERROR)
+ return ret;
+
+ std::wstring archive_name = file_util::GetFilenameFromPath(archive);
+ std::wstring uncompressed_archive(temp_path);
+ file_util::AppendToPath(&uncompressed_archive, installer::kChromeArchive);
+ // Check if this is differential update and if it is, patch it to the
+ // installer archive that should already be on the machine.
+ std::wstring prefix = installer::kChromeCompressedPatchArchivePrefix;
+ if ((archive_name.size() >= prefix.size()) &&
+ (std::equal(prefix.begin(), prefix.end(), archive_name.begin(),
+ CaseInsensitiveCompare<wchar_t>()))) {
+ LOG(INFO) << "Differential patch found. Applying to existing archive.";
+ incremental_install = true;
+ if (!installed_version) {
+ LOG(ERROR) << "Can not use differential update when Chrome is not "
+ << "installed on the system.";
+ return 1;
+ }
+ if (int i = PatchArchiveFile(system_install, temp_path,
+ uncompressed_archive, installed_version)) {
+ LOG(ERROR) << "Binary patching failed with error " << i;
+ return 1;
+ }
+ }
+
+ // If we got the uncompressed archive, lets unpack it
+ LOG(INFO) << "Opening archive " << uncompressed_archive;
+ if ((ret = util.OpenArchive(uncompressed_archive)) != NO_ERROR) {
+ LOG(ERROR) << "Unable to open install archive: " <<
+ uncompressed_archive;
+ } else {
+ LOG(INFO) << "Unpacking archive to path " << path;
+ if ((ret = util.UnPack(path)) != NO_ERROR) {
+ LOG(ERROR) << "Error during uncompression: " << ret;
+ }
+ util.CloseArchive();
+ }
+
+ return ret;
+}
+
+
+// Find the version of Chrome from an install source directory.
+// Chrome_path should contain a complete and unpacked install package (i.e.
+// a Chrome directory under which there is a version folder).
+// Returns the version or NULL if no version is found.
+installer::Version* GetVersionFromDir(const std::wstring& chrome_path) {
+ LOG(INFO) << "Looking for Chrome version folder under " << chrome_path;
+ std::wstring root_path(chrome_path);
+ file_util::AppendToPath(&root_path, L"*");
+
+ WIN32_FIND_DATA find_file_data;
+ HANDLE file_handle = FindFirstFile(root_path.c_str(), &find_file_data);
+ BOOL ret = TRUE;
+ installer::Version *version = NULL;
+ // Here we are assuming that the installer we have is really valid so there
+ // can not be two version directories. We exit as soon as we find a valid
+ // version directory.
+ while (ret) {
+ if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+ LOG(INFO) << "directory found: " << find_file_data.cFileName;
+ version =
+ installer::Version::GetVersionFromString(find_file_data.cFileName);
+ if (version) break;
+ }
+ ret = FindNextFile(file_handle, &find_file_data);
+ }
+ FindClose(file_handle);
+
+ return version;
+}
+
+installer_util::InstallStatus InstallChrome(const CommandLine& cmd_line,
+ const installer::Version* installed_version, bool system_install) {
+ // For install the default location for chrome.packed.7z is in current
+ // folder, so get that value first.
+ std::wstring archive = file_util::GetDirectoryFromPath(cmd_line.program());
+ file_util::AppendToPath(&archive,
+ std::wstring(installer::kChromeCompressedArchive));
+ // If --install-archive is given, get the user specified value
+ if (cmd_line.HasSwitch(installer_util::switches::kInstallArchive)) {
+ archive = cmd_line.GetSwitchValue(
+ installer_util::switches::kInstallArchive);
+ }
+ LOG(INFO) << "Archive found to install Chrome " << archive;
+
+ // Create a temp folder where we will unpack Chrome archive. If it fails,
+ // then we are doomed, so return immediately and no cleanup is required.
+ std::wstring temp_path;
+ if (!file_util::CreateNewTempDirectory(std::wstring(L"chrome_"),
+ &temp_path)) {
+ LOG(ERROR) << "Could not create temporary path.";
+ InstallUtil::SetInstallerError(system_install,
+ installer_util::TEMP_DIR_FAILED,
+ IDS_INSTALL_TEMP_DIR_FAILED_BASE);
+ return installer_util::TEMP_DIR_FAILED;
+ }
+ LOG(INFO) << "created path " << temp_path;
+
+ std::wstring unpack_path(temp_path);
+ file_util::AppendToPath(&unpack_path,
+ std::wstring(installer::kInstallSourceDir));
+ bool incremental_install = false;
+ installer_util::InstallStatus install_status = installer_util::UNKNOWN_STATUS;
+ if (UnPackArchive(archive, system_install, installed_version,
+ temp_path, unpack_path, incremental_install)) {
+ install_status = installer_util::UNCOMPRESSION_FAILED;
+ InstallUtil::SetInstallerError(system_install, install_status,
+ IDS_INSTALL_UNCOMPRESSION_FAILED_BASE);
+ } else {
+ LOG(INFO) << "unpacked to " << unpack_path;
+ std::wstring src_path(unpack_path);
+ file_util::AppendToPath(&src_path,
+ std::wstring(installer::kInstallSourceChromeDir));
+ scoped_ptr<installer::Version>
+ installer_version(GetVersionFromDir(src_path));
+ if (!installer_version.get()) {
+ LOG(ERROR) << "Did not find any valid version in installer.";
+ install_status = installer_util::INVALID_ARCHIVE;
+ InstallUtil::SetInstallerError(system_install, install_status,
+ IDS_INSTALL_INVALID_ARCHIVE_BASE);
+ } else {
+ LOG(INFO) << "version to install: " << installer_version->GetString();
+ if (installed_version &&
+ installed_version->IsHigherThan(installer_version.get())) {
+ LOG(ERROR) << "Higher version is already installed.";
+ install_status = installer_util::HIGHER_VERSION_EXISTS;
+ InstallUtil::SetInstallerError(system_install, install_status,
+ IDS_INSTALL_HIGHER_VERSION_BASE);
+ } else {
+ // We want to keep uncompressed archive (chrome.7z) that we get after
+ // uncompressing and binary patching. Get the location for this file.
+ std::wstring archive_to_copy(temp_path);
+ file_util::AppendToPath(&archive_to_copy,
+ std::wstring(installer::kChromeArchive));
+ install_status = installer::InstallOrUpdateChrome(
+ cmd_line.program(), archive_to_copy, temp_path, system_install,
+ *installer_version, installed_version);
+ if (install_status == installer_util::FIRST_INSTALL_SUCCESS) {
+ LOG(INFO) << "First install successful. Launching Chrome.";
+ installer::LaunchChrome(system_install);
+ } else if (install_status == installer_util::NEW_VERSION_UPDATED) {
+#if defined(GOOGLE_CHROME_BUILD)
+ // TODO(kuchhal): This is just temporary until all users move to the
+ // new Chromium version which ships with gears.dll.
+ LOG(INFO) << "Google Chrome updated. Uninstalling gears msi.";
+ wchar_t product[39]; // GUID + '\0'
+ MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL); // Don't show any UI
+ for (int i = 0;
+ MsiEnumRelatedProducts(google_update::kGearsUpgradeCode, 0,
+ i, product) != ERROR_NO_MORE_ITEMS; ++i) {
+ LOG(INFO) << "Uninstalling Gears - " << product;
+ unsigned int ret = MsiConfigureProduct(product,
+ INSTALLLEVEL_MAXIMUM, INSTALLSTATE_ABSENT);
+ if (ret != ERROR_SUCCESS)
+ LOG(ERROR) << "Failed to uninstall Gears " << product;
+ }
+#endif
+ }
+ }
+ }
+ }
+
+ // Delete install temporary directory.
+ LOG(INFO) << "Deleting temporary directory " << temp_path;
+ scoped_ptr<DeleteTreeWorkItem> delete_tree(
+ WorkItem::CreateDeleteTreeWorkItem(temp_path, std::wstring()));
+ delete_tree->Do();
+
+ BrowserDistribution* dist = BrowserDistribution::GetDistribution();
+ dist->UpdateDiffInstallStatus(system_install, incremental_install,
+ install_status);
+ return install_status;
+}
+
+installer_util::InstallStatus UninstallChrome(const CommandLine& cmd_line,
+ const installer::Version* version,
+ bool system_install) {
+ LOG(INFO) << "Uninstalling Chome";
+ if (!version) {
+ LOG(ERROR) << "No Chrome installation found for uninstall.";
+ InstallUtil::SetInstallerError(system_install,
+ installer_util::CHROME_NOT_INSTALLED,
+ IDS_UNINSTALL_FAILED_BASE);
+ return installer_util::CHROME_NOT_INSTALLED;
+ }
+
+ bool remove_all = !cmd_line.HasSwitch(
+ installer_util::switches::kDoNotRemoveSharedItems);
+ bool force = cmd_line.HasSwitch(installer_util::switches::kForceUninstall);
+ return installer_setup::UninstallChrome(cmd_line.program(), system_install,
+ *version, remove_all, force);
+}
+} // namespace
+
+
+int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance,
+ wchar_t* command_line, int show_command) {
+ // The exit manager is in charge of calling the dtors of singletons.
+ base::AtExitManager exit_manager;
+ CommandLine parsed_command_line;
+ installer::InitInstallerLogging(parsed_command_line);
+ bool system_install =
+ parsed_command_line.HasSwitch(installer_util::switches::kSystemLevel);
+ LOG(INFO) << "system install is " << system_install;
+
+ // Check to make sure current system is WinXP or later. If not, log
+ // error message and get out.
+ if (!InstallUtil::IsOSSupported()) {
+ LOG(ERROR) << "Chrome only supports Windows XP or later.";
+ InstallUtil::SetInstallerError(system_install,
+ installer_util::OS_NOT_SUPPORTED,
+ IDS_INSTALL_OS_NOT_SUPPORTED_BASE);
+ return installer_util::OS_NOT_SUPPORTED;
+ }
+
+ // Initialize COM for use later.
+ if (CoInitializeEx(NULL, COINIT_APARTMENTTHREADED) != S_OK) {
+ LOG(ERROR) << "COM initialization failed.";
+ InstallUtil::SetInstallerError(system_install,
+ installer_util::OS_ERROR,
+ IDS_INSTALL_OS_ERROR_BASE);
+ return installer_util::OS_ERROR;
+ }
+
+ // Check to avoid simultaneous per-user and per-machine installs.
+ scoped_ptr<installer::Version>
+ chrome_version(InstallUtil::GetChromeVersion(!system_install));
+ if (chrome_version.get()) {
+ LOG(ERROR) << "Already installed version " << chrome_version->GetString()
+ << " conflicts with the current install mode.";
+ installer_util::InstallStatus status = system_install ?
+ installer_util::USER_LEVEL_INSTALL_EXISTS :
+ installer_util::SYSTEM_LEVEL_INSTALL_EXISTS;
+ int str_id = system_install ? IDS_INSTALL_USER_LEVEL_EXISTS_BASE :
+ IDS_INSTALL_SYSTEM_LEVEL_EXISTS_BASE;
+ InstallUtil::SetInstallerError(system_install, status, str_id);
+ return status;
+ }
+
+ // If --register-chrome-browser option is specified, register all
+ // Chrome protocol/file associations as well as register it as a valid
+ // browser for StarMenu->Internet shortcut. This option should only
+ // be used when setup.exe is launched with admin rights. We do not
+ // make any user specific changes in this option.
+ if (parsed_command_line.HasSwitch(
+ installer_util::switches::kRegisterChromeBrowser)) {
+ std::wstring chrome_exe(parsed_command_line.GetSwitchValue(
+ installer_util::switches::kRegisterChromeBrowser));
+ return ShellUtil::AddChromeToSetAccessDefaults(chrome_exe, true);
+ }
+
+ if (system_install &&
+ win_util::GetWinVersion() == win_util::WINVERSION_VISTA &&
+ !IsUserAnAdmin()) {
+ std::wstring exe = parsed_command_line.program();
+ std::wstring params(command_line);
+ DWORD exit_code = installer_util::UNKNOWN_STATUS;
+ InstallUtil::ExecuteExeAsAdmin(exe, params, &exit_code);
+ return exit_code;
+ }
+
+ // Check the existing version installed.
+ scoped_ptr<installer::Version>
+ installed_version(InstallUtil::GetChromeVersion(system_install));
+ if (installed_version.get()) {
+ LOG(INFO) << "version on the system: " << installed_version->GetString();
+ }
+
+ installer_util::InstallStatus install_status = installer_util::UNKNOWN_STATUS;
+ // If --uninstall option is given, uninstall chrome
+ if (parsed_command_line.HasSwitch(installer_util::switches::kUninstall)) {
+ install_status = UninstallChrome(parsed_command_line,
+ installed_version.get(),
+ system_install);
+ // If --uninstall option is not specified, we assume it is install case.
+ } else {
+ install_status = InstallChrome(parsed_command_line,
+ installed_version.get(),
+ system_install);
+ }
+
+ CoUninitialize();
+ BrowserDistribution* dist = BrowserDistribution::GetDistribution();
+ return dist->GetInstallReturnCode(install_status);
+}
+
diff --git a/chrome/installer/setup/setup.cc b/chrome/installer/setup/setup.cc
index 0f5b629..8a301da 100644
--- a/chrome/installer/setup/setup.cc
+++ b/chrome/installer/setup/setup.cc
@@ -14,9 +14,8 @@
#include "chrome/installer/setup/setup_constants.h"
#include "chrome/installer/util/browser_distribution.h"
#include "chrome/installer/util/create_reg_key_work_item.h"
-#include "chrome/installer/util/l10n_string_util.h"
-#include "chrome/installer/util/logging_installer.h"
#include "chrome/installer/util/helper.h"
+#include "chrome/installer/util/install_util.h"
#include "chrome/installer/util/shell_util.h"
#include "chrome/installer/util/util_constants.h"
#include "chrome/installer/util/version.h"
@@ -171,6 +170,9 @@ installer_util::InstallStatus installer::InstallOrUpdateChrome(
std::wstring install_path(GetChromeInstallPath(system_install));
if (install_path.empty()) {
LOG(ERROR) << "Could not get installation destination path.";
+ InstallUtil::SetInstallerError(system_install,
+ installer_util::INSTALL_FAILED,
+ IDS_INSTALL_FAILED_BASE);
return installer_util::INSTALL_FAILED;
} else {
LOG(INFO) << "install destination path: " << install_path;
@@ -187,6 +189,9 @@ installer_util::InstallStatus installer::InstallOrUpdateChrome(
installer_util::InstallStatus result;
if (!install_success) {
LOG(ERROR) << "Install failed.";
+ InstallUtil::SetInstallerError(system_install,
+ installer_util::INSTALL_FAILED,
+ IDS_INSTALL_FAILED_BASE);
result = installer_util::INSTALL_FAILED;
} else {
if (!installed_version) {
diff --git a/chrome/installer/util/google_chrome_distribution.cc b/chrome/installer/util/google_chrome_distribution.cc
index f5ea433..ceeac44 100644
--- a/chrome/installer/util/google_chrome_distribution.cc
+++ b/chrome/installer/util/google_chrome_distribution.cc
@@ -16,11 +16,9 @@
#include "base/registry.h"
#include "base/string_util.h"
#include "base/wmi_util.h"
-#include "chrome/installer/util/install_util.h"
#include "chrome/installer/util/l10n_string_util.h"
#include "chrome/installer/util/google_update_constants.h"
#include "chrome/installer/util/google_update_settings.h"
-#include "chrome/installer/util/logging_installer.h"
#include "installer_util_strings.h"
diff --git a/chrome/installer/util/install_util.cc b/chrome/installer/util/install_util.cc
index 29bc51d..0374236 100644
--- a/chrome/installer/util/install_util.cc
+++ b/chrome/installer/util/install_util.cc
@@ -15,6 +15,8 @@
#include "base/win_util.h"
#include "chrome/installer/util/browser_distribution.h"
#include "chrome/installer/util/google_update_constants.h"
+#include "chrome/installer/util/l10n_string_util.h"
+#include "chrome/installer/util/work_item_list.h"
bool InstallUtil::ExecuteExeAsAdmin(const std::wstring& exe,
const std::wstring& params,
@@ -80,3 +82,21 @@ bool InstallUtil::IsOSSupported() {
}
return false;
}
+
+void InstallUtil::SetInstallerError(bool system_install,
+ installer_util::InstallStatus status,
+ int string_resource_id) {
+ HKEY root = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
+ std::wstring key(google_update::kRegPathClients);
+ key.append(L"\\");
+ key.append(google_update::kChromeGuid);
+ scoped_ptr<WorkItemList> install_list(WorkItem::CreateWorkItemList());
+ install_list->AddSetRegValueWorkItem(root, key, L"InstallerResult", 1, true);
+ install_list->AddSetRegValueWorkItem(root, key, L"InstallerError",
+ status, true);
+ std::wstring msg = installer_util::GetLocalizedString(string_resource_id);
+ install_list->AddSetRegValueWorkItem(root, key, L"InstallerResultUIString",
+ msg, true);
+ if (!install_list->Do())
+ LOG(ERROR) << "Failed to record installer error information in registry.";
+}
diff --git a/chrome/installer/util/install_util.h b/chrome/installer/util/install_util.h
index ed63175..8bf8d2f 100755
--- a/chrome/installer/util/install_util.h
+++ b/chrome/installer/util/install_util.h
@@ -39,6 +39,12 @@ class InstallUtil {
// This function checks if the current OS is supported for Chromium.
static bool IsOSSupported();
+
+ // This function sets installer error information in registry so that Google
+ // Update can read it and display to the user.
+ static void SetInstallerError(bool system_install,
+ installer_util::InstallStatus status,
+ int string_resource_id);
private:
DISALLOW_EVIL_CONSTRUCTORS(InstallUtil);
};
diff --git a/chrome/installer/util/prebuild/create_string_rc.py b/chrome/installer/util/prebuild/create_string_rc.py
index 5c29d4e..c0a91ba 100644
--- a/chrome/installer/util/prebuild/create_string_rc.py
+++ b/chrome/installer/util/prebuild/create_string_rc.py
@@ -39,6 +39,16 @@ kStringIds = [
'IDS_PRODUCT_NAME',
'IDS_UNINSTALL_CHROME',
'IDS_ABOUT_VERSION_COMPANY_NAME',
+ 'IDS_INSTALL_HIGHER_VERSION',
+ 'IDS_INSTALL_USER_LEVEL_EXISTS',
+ 'IDS_INSTALL_SYSTEM_LEVEL_EXISTS',
+ 'IDS_INSTALL_FAILED',
+ 'IDS_INSTALL_OS_NOT_SUPPORTED',
+ 'IDS_INSTALL_OS_ERROR',
+ 'IDS_INSTALL_TEMP_DIR_FAILED',
+ 'IDS_INSTALL_UNCOMPRESSION_FAILED',
+ 'IDS_INSTALL_INVALID_ARCHIVE',
+ 'IDS_UNINSTALL_FAILED',
]
# The ID of the first resource string.
diff --git a/chrome/installer/util/util_constants.h b/chrome/installer/util/util_constants.h
index 5994ef0..41f5a3ed 100644
--- a/chrome/installer/util/util_constants.h
+++ b/chrome/installer/util/util_constants.h
@@ -17,7 +17,7 @@ enum InstallStatus {
NEW_VERSION_UPDATED, // Chrome successfully updated to new version
HIGHER_VERSION_EXISTS, // Higher version of Chrome already exists
USER_LEVEL_INSTALL_EXISTS, // User level install already exists
- MACHINE_LEVEL_INSTALL_EXISTS, // Machine level install already exists
+ SYSTEM_LEVEL_INSTALL_EXISTS, // Machine level install already exists
INSTALL_FAILED, // Install/update failed
OS_NOT_SUPPORTED, // Current OS not supported
OS_ERROR, // OS API call failed