From f3f9106c281f61e7ce7e343e7cea47ae112dff8e Mon Sep 17 00:00:00 2001 From: "kuchhal@chromium.org" Date: Wed, 29 Oct 2008 19:20:44 +0000 Subject: Add command line option to suppress Chrome launch after successful install BUG=1443250 Review URL: http://codereview.chromium.org/8644 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@4154 0039d316-1c4b-4281-b951-d872f2087c98 --- chrome/installer/setup/main.cc | 52 +- chrome/installer/setup/setup.cc | 506 ++++++------- chrome/installer/util/install_util.cc | 29 +- chrome/installer/util/install_util.h | 109 +-- chrome/installer/util/shell_util.cc | 1204 +++++++++++++++---------------- chrome/installer/util/util_constants.cc | 133 ++-- chrome/installer/util/util_constants.h | 123 ++-- 7 files changed, 1090 insertions(+), 1066 deletions(-) mode change 100644 => 100755 chrome/installer/setup/setup.cc mode change 100644 => 100755 chrome/installer/util/install_util.h mode change 100644 => 100755 chrome/installer/util/util_constants.cc mode change 100644 => 100755 chrome/installer/util/util_constants.h diff --git a/chrome/installer/setup/main.cc b/chrome/installer/setup/main.cc index 8f0591e..d0a5298 100644 --- a/chrome/installer/setup/main.cc +++ b/chrome/installer/setup/main.cc @@ -180,9 +180,10 @@ installer_util::InstallStatus InstallChrome(const CommandLine& cmd_line, 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); + InstallUtil::WriteInstallerResult(system_install, + installer_util::TEMP_DIR_FAILED, + IDS_INSTALL_TEMP_DIR_FAILED_BASE, + NULL); return installer_util::TEMP_DIR_FAILED; } LOG(INFO) << "created path " << temp_path; @@ -195,8 +196,9 @@ installer_util::InstallStatus InstallChrome(const CommandLine& cmd_line, 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); + InstallUtil::WriteInstallerResult(system_install, install_status, + IDS_INSTALL_UNCOMPRESSION_FAILED_BASE, + NULL); } else { LOG(INFO) << "unpacked to " << unpack_path; std::wstring src_path(unpack_path); @@ -207,16 +209,16 @@ installer_util::InstallStatus InstallChrome(const CommandLine& cmd_line, 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); + InstallUtil::WriteInstallerResult(system_install, install_status, + IDS_INSTALL_INVALID_ARCHIVE_BASE, NULL); } 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); + InstallUtil::WriteInstallerResult(system_install, install_status, + IDS_INSTALL_HIGHER_VERSION_BASE, NULL); } else { // We want to keep uncompressed archive (chrome.7z) that we get after // uncompressing and binary patching. Get the location for this file. @@ -227,8 +229,16 @@ installer_util::InstallStatus InstallChrome(const CommandLine& cmd_line, 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); + LOG(INFO) << "First install successful."; + if (cmd_line.HasSwitch( + installer_util::switches::kDoNotLaunchChrome)) { + std::wstring chrome_exe = + installer::GetChromeInstallPath(system_install); + InstallUtil::WriteInstallerResult(system_install, install_status, + 0, &chrome_exe); + } else { + 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 @@ -269,9 +279,9 @@ installer_util::InstallStatus UninstallChrome(const CommandLine& cmd_line, 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); + InstallUtil::WriteInstallerResult(system_install, + installer_util::CHROME_NOT_INSTALLED, + IDS_UNINSTALL_FAILED_BASE, NULL); return installer_util::CHROME_NOT_INSTALLED; } @@ -298,18 +308,18 @@ int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance, // 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); + InstallUtil::WriteInstallerResult(system_install, + installer_util::OS_NOT_SUPPORTED, + IDS_INSTALL_OS_NOT_SUPPORTED_BASE, NULL); 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); + InstallUtil::WriteInstallerResult(system_install, + installer_util::OS_ERROR, + IDS_INSTALL_OS_ERROR_BASE, NULL); return installer_util::OS_ERROR; } @@ -324,7 +334,7 @@ int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance, 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); + InstallUtil::WriteInstallerResult(system_install, status, str_id, NULL); return status; } diff --git a/chrome/installer/setup/setup.cc b/chrome/installer/setup/setup.cc old mode 100644 new mode 100755 index 493a519..d9a4298 --- a/chrome/installer/setup/setup.cc +++ b/chrome/installer/setup/setup.cc @@ -1,253 +1,253 @@ -// 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 - -#include "chrome/installer/setup/setup.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 "chrome/common/chrome_constants.h" -#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/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" -#include "chrome/installer/util/work_item_list.h" - -#include "installer_util_strings.h" - -namespace { - -void AddChromeToMediaPlayerList() { - std::wstring reg_path(installer::kMediaPlayerRegPath); - // registry paths can also be appended like file system path - file_util::AppendToPath(®_path, installer_util::kChromeExe); - LOG(INFO) << "Adding Chrome to Media player list at " << reg_path; - scoped_ptr work_item(WorkItem::CreateCreateRegKeyWorkItem( - HKEY_LOCAL_MACHINE, reg_path)); - - // if the operation fails we log the error but still continue - if (!work_item.get()->Do()) - LOG(ERROR) << "Could not add Chrome to media player inclusion list."; - -} - -void DoFirstInstallTasks(std::wstring install_path, bool system_level) { - // Try to add Chrome to Media Player shim inclusion list. We don't do any - // error checking here because this operation will fail if user doesn't - // have admin rights and we want to ignore the error. - AddChromeToMediaPlayerList(); - - // We try to register Chrome as a valid browser on local machine. This - // will work only if current user has admin rights. - std::wstring chrome_exe(install_path); - file_util::AppendToPath(&chrome_exe, installer_util::kChromeExe); - CommandLine cmd_line; - LOG(INFO) << "Registering Chrome as browser"; - ShellUtil::RegisterStatus ret = ShellUtil::FAILURE; - if (cmd_line.HasSwitch(installer_util::switches::kMakeChromeDefault)) { - ret = ShellUtil::AddChromeToSetAccessDefaults(chrome_exe, false); - if (ret == ShellUtil::SUCCESS) { - if (system_level) { - ShellUtil::MakeChromeDefault( - ShellUtil::CURRENT_USER | ShellUtil::SYSTEM_LEVEL, chrome_exe); - } else { - ShellUtil::MakeChromeDefault(ShellUtil::CURRENT_USER, chrome_exe); - } - } - } else { - ret = ShellUtil::AddChromeToSetAccessDefaults(chrome_exe, true); - } - LOG(INFO) << "Return status of Chrome browser registration " << ret; -} - -// This method creates Chrome shortcuts in Start->Programs for all users or -// only for current user depending on whether it is system wide install or -// user only install. -// -// If first_install is true, it creates shortcuts for launching and -// uninstalling chrome. -// If first_install is false, the function only updates the shortcut for -// uninstalling chrome. According to -// http://blogs.msdn.com/oldnewthing/archive/2005/11/24/496690.aspx, -// updating uninstall shortcut should not trigger Windows "new application -// installed" notification. -// -// If the shortcuts do not exist, the function does not recreate them during -// update. -bool CreateOrUpdateChromeShortcuts(const std::wstring& exe_path, - bool system_install, - installer_util::InstallStatus install_status, - const std::wstring& install_path, - const std::wstring& new_version) { - std::wstring shortcut_path; - int dir_enum = (system_install) ? base::DIR_COMMON_START_MENU : - base::DIR_START_MENU; - if (!PathService::Get(dir_enum, &shortcut_path)) { - LOG(ERROR) << "Failed to get location for shortcut."; - return false; - } - - // The location of Start->Programs->Google Chrome folder - BrowserDistribution* dist = BrowserDistribution::GetDistribution(); - const std::wstring& product_name = dist->GetApplicationName(); - file_util::AppendToPath(&shortcut_path, product_name); - - // Create/update Chrome link (points to chrome.exe) & Uninstall Chrome link - // (which points to setup.exe) under this folder only if: - // - This is a new install or install repair - // OR - // - The shortcut already exists in case of updates (user may have deleted - // shortcuts since our install. So on updates we only update if shortcut - // already exists) - bool ret = true; - std::wstring chrome_link(shortcut_path); // Chrome link (launches Chrome) - file_util::AppendToPath(&chrome_link, product_name + L".lnk"); - std::wstring chrome_exe(install_path); // Chrome link target - file_util::AppendToPath(&chrome_exe, installer_util::kChromeExe); - - if ((install_status == installer_util::FIRST_INSTALL_SUCCESS) || - (install_status == installer_util::INSTALL_REPAIRED)) { - if (!file_util::PathExists(shortcut_path)) - file_util::CreateDirectoryW(shortcut_path); - - LOG(INFO) << "Creating shortcut to " << chrome_exe << " at " << chrome_link; - ret = ret && ShellUtil::UpdateChromeShortcut(chrome_exe, chrome_link, true); - } else if (file_util::PathExists(chrome_link)) { - LOG(INFO) << "Updating shortcut at " << chrome_link - << " to point to " << chrome_exe; - ret = ret && ShellUtil::UpdateChromeShortcut(chrome_exe, - chrome_link, - false); // do not create new - } - - // Create/update uninstall link - std::wstring uninstall_link(shortcut_path); // Uninstall Chrome link - file_util::AppendToPath(&uninstall_link, - dist->GetUninstallLinkName() + L".lnk"); - if ((install_status == installer_util::FIRST_INSTALL_SUCCESS) || - (install_status == installer_util::INSTALL_REPAIRED) || - (file_util::PathExists(uninstall_link))) { - if (!file_util::PathExists(shortcut_path)) - file_util::CreateDirectoryW(shortcut_path); - std::wstring setup_exe(installer::GetInstallerPathUnderChrome(install_path, - new_version)); - file_util::AppendToPath(&setup_exe, - file_util::GetFilenameFromPath(exe_path)); - std::wstring arguments(L" --"); - arguments.append(installer_util::switches::kUninstall); - if (system_install) { - arguments.append(L" --"); - arguments.append(installer_util::switches::kSystemLevel); - } - - LOG(INFO) << "Creating/updating uninstall link at " << uninstall_link; - std::wstring target_folder = file_util::GetDirectoryFromPath(install_path); - ret = ret && file_util::CreateShortcutLink(setup_exe.c_str(), - uninstall_link.c_str(), - target_folder.c_str(), - arguments.c_str(), - NULL, setup_exe.c_str(), 0); - } - - // Update Desktop and Quick Launch shortcuts. If --create-new-shortcuts - // is specified we want to create them, otherwise we update them only if - // they exist. - bool create = false; // Only update; do not create, if they do not exist - CommandLine cmd_line; - if (cmd_line.HasSwitch(installer_util::switches::kCreateAllShortcuts)) - create = true; - if (system_install) { - ret = ret && ShellUtil::CreateChromeDesktopShortcut(chrome_exe, - ShellUtil::SYSTEM_LEVEL, create); - ret = ret && ShellUtil::CreateChromeQuickLaunchShortcut(chrome_exe, - ShellUtil::CURRENT_USER | ShellUtil::SYSTEM_LEVEL, create); - } else { - ret = ret && ShellUtil::CreateChromeDesktopShortcut(chrome_exe, - ShellUtil::CURRENT_USER, create); - ret = ret && ShellUtil::CreateChromeQuickLaunchShortcut(chrome_exe, - ShellUtil::CURRENT_USER, create); - } - - return ret; -} -} // namespace - - -std::wstring installer::GetInstallerPathUnderChrome( - const std::wstring& install_path, const std::wstring& new_version) { - std::wstring installer_path(install_path); - file_util::AppendToPath(&installer_path, new_version); - file_util::AppendToPath(&installer_path, installer::kInstallerDir); - return installer_path; -} - - -installer_util::InstallStatus installer::InstallOrUpdateChrome( - const std::wstring& exe_path, const std::wstring& archive_path, - const std::wstring& install_temp_path, bool system_install, - const Version& new_version, const Version* installed_version) { - - 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; - } - - std::wstring src_path(install_temp_path); - file_util::AppendToPath(&src_path, std::wstring(kInstallSourceDir)); - file_util::AppendToPath(&src_path, std::wstring(kInstallSourceChromeDir)); - - HKEY reg_root = (system_install) ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; - bool install_success = InstallNewVersion(exe_path, archive_path, src_path, - install_path, install_temp_path, reg_root, new_version); - - 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) { - LOG(INFO) << "First install of version " << new_version.GetString(); - result = installer_util::FIRST_INSTALL_SUCCESS; - } else if (new_version.GetString() == installed_version->GetString()) { - LOG(INFO) << "Install repaired of version " << new_version.GetString(); - result = installer_util::INSTALL_REPAIRED; - } else if (new_version.IsHigherThan(installed_version)) { - LOG(INFO) << "Version updated to " << new_version.GetString(); - result = installer_util::NEW_VERSION_UPDATED; - } else { - NOTREACHED(); - } - - if (!CreateOrUpdateChromeShortcuts(exe_path, system_install, result, - install_path, new_version.GetString())) - LOG(WARNING) << "Failed to create/update start menu shortcut."; - - if (result == installer_util::FIRST_INSTALL_SUCCESS || - result == installer_util::INSTALL_REPAIRED) { - DoFirstInstallTasks(install_path, system_install); - } else { - RemoveOldVersionDirs(install_path, new_version.GetString()); - } - } - - return result; -} - +// 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 + +#include "chrome/installer/setup/setup.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 "chrome/common/chrome_constants.h" +#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/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" +#include "chrome/installer/util/work_item_list.h" + +#include "installer_util_strings.h" + +namespace { + +void AddChromeToMediaPlayerList() { + std::wstring reg_path(installer::kMediaPlayerRegPath); + // registry paths can also be appended like file system path + file_util::AppendToPath(®_path, installer_util::kChromeExe); + LOG(INFO) << "Adding Chrome to Media player list at " << reg_path; + scoped_ptr work_item(WorkItem::CreateCreateRegKeyWorkItem( + HKEY_LOCAL_MACHINE, reg_path)); + + // if the operation fails we log the error but still continue + if (!work_item.get()->Do()) + LOG(ERROR) << "Could not add Chrome to media player inclusion list."; + +} + +void DoFirstInstallTasks(std::wstring install_path, bool system_level) { + // Try to add Chrome to Media Player shim inclusion list. We don't do any + // error checking here because this operation will fail if user doesn't + // have admin rights and we want to ignore the error. + AddChromeToMediaPlayerList(); + + // We try to register Chrome as a valid browser on local machine. This + // will work only if current user has admin rights. + std::wstring chrome_exe(install_path); + file_util::AppendToPath(&chrome_exe, installer_util::kChromeExe); + CommandLine cmd_line; + LOG(INFO) << "Registering Chrome as browser"; + ShellUtil::RegisterStatus ret = ShellUtil::FAILURE; + if (cmd_line.HasSwitch(installer_util::switches::kMakeChromeDefault)) { + ret = ShellUtil::AddChromeToSetAccessDefaults(chrome_exe, false); + if (ret == ShellUtil::SUCCESS) { + if (system_level) { + ShellUtil::MakeChromeDefault( + ShellUtil::CURRENT_USER | ShellUtil::SYSTEM_LEVEL, chrome_exe); + } else { + ShellUtil::MakeChromeDefault(ShellUtil::CURRENT_USER, chrome_exe); + } + } + } else { + ret = ShellUtil::AddChromeToSetAccessDefaults(chrome_exe, true); + } + LOG(INFO) << "Return status of Chrome browser registration " << ret; +} + +// This method creates Chrome shortcuts in Start->Programs for all users or +// only for current user depending on whether it is system wide install or +// user only install. +// +// If first_install is true, it creates shortcuts for launching and +// uninstalling chrome. +// If first_install is false, the function only updates the shortcut for +// uninstalling chrome. According to +// http://blogs.msdn.com/oldnewthing/archive/2005/11/24/496690.aspx, +// updating uninstall shortcut should not trigger Windows "new application +// installed" notification. +// +// If the shortcuts do not exist, the function does not recreate them during +// update. +bool CreateOrUpdateChromeShortcuts(const std::wstring& exe_path, + bool system_install, + installer_util::InstallStatus install_status, + const std::wstring& install_path, + const std::wstring& new_version) { + std::wstring shortcut_path; + int dir_enum = (system_install) ? base::DIR_COMMON_START_MENU : + base::DIR_START_MENU; + if (!PathService::Get(dir_enum, &shortcut_path)) { + LOG(ERROR) << "Failed to get location for shortcut."; + return false; + } + + // The location of Start->Programs->Google Chrome folder + BrowserDistribution* dist = BrowserDistribution::GetDistribution(); + const std::wstring& product_name = dist->GetApplicationName(); + file_util::AppendToPath(&shortcut_path, product_name); + + // Create/update Chrome link (points to chrome.exe) & Uninstall Chrome link + // (which points to setup.exe) under this folder only if: + // - This is a new install or install repair + // OR + // - The shortcut already exists in case of updates (user may have deleted + // shortcuts since our install. So on updates we only update if shortcut + // already exists) + bool ret = true; + std::wstring chrome_link(shortcut_path); // Chrome link (launches Chrome) + file_util::AppendToPath(&chrome_link, product_name + L".lnk"); + std::wstring chrome_exe(install_path); // Chrome link target + file_util::AppendToPath(&chrome_exe, installer_util::kChromeExe); + + if ((install_status == installer_util::FIRST_INSTALL_SUCCESS) || + (install_status == installer_util::INSTALL_REPAIRED)) { + if (!file_util::PathExists(shortcut_path)) + file_util::CreateDirectoryW(shortcut_path); + + LOG(INFO) << "Creating shortcut to " << chrome_exe << " at " << chrome_link; + ret = ret && ShellUtil::UpdateChromeShortcut(chrome_exe, chrome_link, true); + } else if (file_util::PathExists(chrome_link)) { + LOG(INFO) << "Updating shortcut at " << chrome_link + << " to point to " << chrome_exe; + ret = ret && ShellUtil::UpdateChromeShortcut(chrome_exe, + chrome_link, + false); // do not create new + } + + // Create/update uninstall link + std::wstring uninstall_link(shortcut_path); // Uninstall Chrome link + file_util::AppendToPath(&uninstall_link, + dist->GetUninstallLinkName() + L".lnk"); + if ((install_status == installer_util::FIRST_INSTALL_SUCCESS) || + (install_status == installer_util::INSTALL_REPAIRED) || + (file_util::PathExists(uninstall_link))) { + if (!file_util::PathExists(shortcut_path)) + file_util::CreateDirectoryW(shortcut_path); + std::wstring setup_exe(installer::GetInstallerPathUnderChrome(install_path, + new_version)); + file_util::AppendToPath(&setup_exe, + file_util::GetFilenameFromPath(exe_path)); + std::wstring arguments(L" --"); + arguments.append(installer_util::switches::kUninstall); + if (system_install) { + arguments.append(L" --"); + arguments.append(installer_util::switches::kSystemLevel); + } + + LOG(INFO) << "Creating/updating uninstall link at " << uninstall_link; + std::wstring target_folder = file_util::GetDirectoryFromPath(install_path); + ret = ret && file_util::CreateShortcutLink(setup_exe.c_str(), + uninstall_link.c_str(), + target_folder.c_str(), + arguments.c_str(), + NULL, setup_exe.c_str(), 0); + } + + // Update Desktop and Quick Launch shortcuts. If --create-new-shortcuts + // is specified we want to create them, otherwise we update them only if + // they exist. + bool create = false; // Only update; do not create, if they do not exist + CommandLine cmd_line; + if (cmd_line.HasSwitch(installer_util::switches::kCreateAllShortcuts)) + create = true; + if (system_install) { + ret = ret && ShellUtil::CreateChromeDesktopShortcut(chrome_exe, + ShellUtil::SYSTEM_LEVEL, create); + ret = ret && ShellUtil::CreateChromeQuickLaunchShortcut(chrome_exe, + ShellUtil::CURRENT_USER | ShellUtil::SYSTEM_LEVEL, create); + } else { + ret = ret && ShellUtil::CreateChromeDesktopShortcut(chrome_exe, + ShellUtil::CURRENT_USER, create); + ret = ret && ShellUtil::CreateChromeQuickLaunchShortcut(chrome_exe, + ShellUtil::CURRENT_USER, create); + } + + return ret; +} +} // namespace + + +std::wstring installer::GetInstallerPathUnderChrome( + const std::wstring& install_path, const std::wstring& new_version) { + std::wstring installer_path(install_path); + file_util::AppendToPath(&installer_path, new_version); + file_util::AppendToPath(&installer_path, installer::kInstallerDir); + return installer_path; +} + + +installer_util::InstallStatus installer::InstallOrUpdateChrome( + const std::wstring& exe_path, const std::wstring& archive_path, + const std::wstring& install_temp_path, bool system_install, + const Version& new_version, const Version* installed_version) { + + std::wstring install_path(GetChromeInstallPath(system_install)); + if (install_path.empty()) { + LOG(ERROR) << "Could not get installation destination path."; + InstallUtil::WriteInstallerResult(system_install, + installer_util::INSTALL_FAILED, + IDS_INSTALL_FAILED_BASE, NULL); + return installer_util::INSTALL_FAILED; + } else { + LOG(INFO) << "install destination path: " << install_path; + } + + std::wstring src_path(install_temp_path); + file_util::AppendToPath(&src_path, std::wstring(kInstallSourceDir)); + file_util::AppendToPath(&src_path, std::wstring(kInstallSourceChromeDir)); + + HKEY reg_root = (system_install) ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; + bool install_success = InstallNewVersion(exe_path, archive_path, src_path, + install_path, install_temp_path, reg_root, new_version); + + installer_util::InstallStatus result; + if (!install_success) { + LOG(ERROR) << "Install failed."; + InstallUtil::WriteInstallerResult(system_install, + installer_util::INSTALL_FAILED, + IDS_INSTALL_FAILED_BASE, NULL); + result = installer_util::INSTALL_FAILED; + } else { + if (!installed_version) { + LOG(INFO) << "First install of version " << new_version.GetString(); + result = installer_util::FIRST_INSTALL_SUCCESS; + } else if (new_version.GetString() == installed_version->GetString()) { + LOG(INFO) << "Install repaired of version " << new_version.GetString(); + result = installer_util::INSTALL_REPAIRED; + } else if (new_version.IsHigherThan(installed_version)) { + LOG(INFO) << "Version updated to " << new_version.GetString(); + result = installer_util::NEW_VERSION_UPDATED; + } else { + NOTREACHED(); + } + + if (!CreateOrUpdateChromeShortcuts(exe_path, system_install, result, + install_path, new_version.GetString())) + LOG(WARNING) << "Failed to create/update start menu shortcut."; + + if (result == installer_util::FIRST_INSTALL_SUCCESS || + result == installer_util::INSTALL_REPAIRED) { + DoFirstInstallTasks(install_path, system_install); + } else { + RemoveOldVersionDirs(install_path, new_version.GetString()); + } + } + + return result; +} + diff --git a/chrome/installer/util/install_util.cc b/chrome/installer/util/install_util.cc index 0374236..a372070 100644 --- a/chrome/installer/util/install_util.cc +++ b/chrome/installer/util/install_util.cc @@ -83,20 +83,29 @@ bool InstallUtil::IsOSSupported() { return false; } -void InstallUtil::SetInstallerError(bool system_install, - installer_util::InstallStatus status, - int string_resource_id) { +void InstallUtil::WriteInstallerResult(bool system_install, + installer_util::InstallStatus status, + int string_resource_id, + const std::wstring* const launch_cmd) { HKEY root = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; - std::wstring key(google_update::kRegPathClients); - key.append(L"\\"); - key.append(google_update::kChromeGuid); + BrowserDistribution* dist = BrowserDistribution::GetDistribution(); + std::wstring key = dist->GetVersionKey(); + int installer_result = (dist->GetInstallReturnCode(status) == 0) ? 0 : 1; scoped_ptr install_list(WorkItem::CreateWorkItemList()); - install_list->AddSetRegValueWorkItem(root, key, L"InstallerResult", 1, true); + install_list->AddSetRegValueWorkItem(root, key, L"InstallerResult", + installer_result, 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 (string_resource_id != 0) { + std::wstring msg = installer_util::GetLocalizedString(string_resource_id); + install_list->AddSetRegValueWorkItem(root, key, L"InstallerResultUIString", + msg, true); + } + if (launch_cmd != NULL) { + install_list->AddSetRegValueWorkItem(root, key, + L"InstallerSuccessLaunchCmdLine", + *launch_cmd, 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 old mode 100644 new mode 100755 index 8bf8d2f..95c4bf9 --- a/chrome/installer/util/install_util.h +++ b/chrome/installer/util/install_util.h @@ -1,54 +1,55 @@ -// 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. -// -// This file declares utility functions for the installer. The original reason -// for putting these functions in installer\util library is so that we can -// separate out the critical logic and write unit tests for it. - -#ifndef CHROME_INSTALLER_UTIL_INSTALL_UTIL_H__ -#define CHROME_INSTALLER_UTIL_INSTALL_UTIL_H__ - -#include -#include - -#include "base/basictypes.h" -#include "chrome/installer/util/util_constants.h" -#include "chrome/installer/util/version.h" - -// This is a utility class that provides common installation related -// utility methods that can be used by installer and also unit tested -// independently. -class InstallUtil { - public: - // Launches given exe as admin on Vista. - static bool ExecuteExeAsAdmin(const std::wstring& exe, - const std::wstring& params, - DWORD* exit_code); - - // Reads the uninstall command for Chromium from registry and returns it. - // If system_install is true the command is read from HKLM, otherwise - // from HKCU. - static std::wstring GetChromeUninstallCmd(bool system_install); - // Find the version of Chrome installed on the system by checking the - // Google Update registry key. Returns the version or NULL if no version is - // found. - // system_install: if true, looks for version number under the HKLM root, - // otherwise looks under the HKCU. - static installer::Version* GetChromeVersion(bool system_install); - - // 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); -}; - - -#endif // CHROME_INSTALLER_UTIL_INSTALL_UTIL_H__ - +// 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. +// +// This file declares utility functions for the installer. The original reason +// for putting these functions in installer\util library is so that we can +// separate out the critical logic and write unit tests for it. + +#ifndef CHROME_INSTALLER_UTIL_INSTALL_UTIL_H__ +#define CHROME_INSTALLER_UTIL_INSTALL_UTIL_H__ + +#include +#include + +#include "base/basictypes.h" +#include "chrome/installer/util/util_constants.h" +#include "chrome/installer/util/version.h" + +// This is a utility class that provides common installation related +// utility methods that can be used by installer and also unit tested +// independently. +class InstallUtil { + public: + // Launches given exe as admin on Vista. + static bool ExecuteExeAsAdmin(const std::wstring& exe, + const std::wstring& params, + DWORD* exit_code); + + // Reads the uninstall command for Chromium from registry and returns it. + // If system_install is true the command is read from HKLM, otherwise + // from HKCU. + static std::wstring GetChromeUninstallCmd(bool system_install); + // Find the version of Chrome installed on the system by checking the + // Google Update registry key. Returns the version or NULL if no version is + // found. + // system_install: if true, looks for version number under the HKLM root, + // otherwise looks under the HKCU. + static installer::Version* GetChromeVersion(bool system_install); + + // 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 WriteInstallerResult(bool system_install, + installer_util::InstallStatus status, + int string_resource_id, + const std::wstring* const launch_cmd); + private: + DISALLOW_EVIL_CONSTRUCTORS(InstallUtil); +}; + + +#endif // CHROME_INSTALLER_UTIL_INSTALL_UTIL_H__ + diff --git a/chrome/installer/util/shell_util.cc b/chrome/installer/util/shell_util.cc index d03d44a..4f97cd6 100644 --- a/chrome/installer/util/shell_util.cc +++ b/chrome/installer/util/shell_util.cc @@ -1,605 +1,605 @@ -// 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. -// -// This file defines functions that integrate Chrome in Windows shell. These -// functions can be used by Chrome as well as Chrome installer. All of the -// work is done by the local functions defined in anonymous namespace in -// this class. - -#include -#include -#include - -#include "shell_util.h" - -#include "base/file_util.h" -#include "base/logging.h" -#include "base/path_service.h" -#include "base/registry.h" -#include "base/scoped_ptr.h" -#include "base/string_util.h" -#include "base/win_util.h" -#include "chrome/common/chrome_constants.h" -#include "chrome/common/chrome_switches.h" -#include "chrome/installer/util/browser_distribution.h" -#include "chrome/installer/util/create_reg_key_work_item.h" -#include "chrome/installer/util/install_util.h" -#include "chrome/installer/util/l10n_string_util.h" -#include "chrome/installer/util/set_reg_value_work_item.h" -#include "chrome/installer/util/util_constants.h" -#include "chrome/installer/util/work_item.h" - -#include "installer_util_strings.h" - -namespace { - -// This class represents a single registry entry. The objective is to -// encapsulate all the registry entries required for registering Chrome at one -// place. This class can not be instantiated outside the class and the objects -// of this class type can be obtained only by calling a static method of this -// class. -class RegistryEntry { - public: - // This method returns a list of all the registry entries that are needed - // to register Chrome. - static std::list GetAllEntries(const std::wstring& chrome_exe) { - std::list entries; - std::wstring icon_path(chrome_exe); - ShellUtil::GetChromeIcon(icon_path); - std::wstring quoted_exe_path = L"\"" + chrome_exe + L"\""; - std::wstring open_cmd = ShellUtil::GetChromeShellOpenCmd(chrome_exe); - - entries.push_front(new RegistryEntry(L"Software\\Classes\\ChromeHTML", - L"Chrome HTML")); - entries.push_front(new RegistryEntry( - L"Software\\Classes\\ChromeHTML\\DefaultIcon", icon_path)); - entries.push_front(new RegistryEntry( - L"Software\\Classes\\ChromeHTML\\shell\\open\\command", open_cmd)); - - BrowserDistribution* dist = BrowserDistribution::GetDistribution(); - entries.push_front(new RegistryEntry( - L"Software\\Clients\\StartMenuInternet\\chrome.exe", - dist->GetApplicationName())); - entries.push_front(new RegistryEntry( - L"Software\\Clients\\StartMenuInternet\\chrome.exe\\shell\\open\\command", - quoted_exe_path)); - entries.push_front(new RegistryEntry( - L"Software\\Clients\\StartMenuInternet\\chrome.exe\\DefaultIcon", - icon_path)); - entries.push_front(new RegistryEntry( - L"Software\\Clients\\StartMenuInternet\\chrome.exe\\InstallInfo", - L"ReinstallCommand", - quoted_exe_path + L" --" + switches::kMakeDefaultBrowser)); - entries.push_front(new RegistryEntry( - L"Software\\Clients\\StartMenuInternet\\chrome.exe\\InstallInfo", - L"HideIconsCommand", - quoted_exe_path + L" --" + switches::kHideIcons)); - entries.push_front(new RegistryEntry( - L"Software\\Clients\\StartMenuInternet\\chrome.exe\\InstallInfo", - L"ShowIconsCommand", - quoted_exe_path + L" --" + switches::kShowIcons)); - entries.push_front(new RegistryEntry( - L"Software\\Clients\\StartMenuInternet\\chrome.exe\\InstallInfo", - L"IconsVisible", 1)); - - entries.push_front(new RegistryEntry( - ShellUtil::kRegRegisteredApplications, - dist->GetApplicationName(), - L"Software\\Clients\\StartMenuInternet\\chrome.exe\\Capabilities")); - entries.push_front(new RegistryEntry( - L"Software\\Clients\\StartMenuInternet\\chrome.exe\\Capabilities", - L"ApplicationDescription", dist->GetApplicationName())); - entries.push_front(new RegistryEntry( - L"Software\\Clients\\StartMenuInternet\\chrome.exe\\Capabilities", - L"ApplicationIcon", icon_path)); - entries.push_front(new RegistryEntry( - L"Software\\Clients\\StartMenuInternet\\chrome.exe\\Capabilities", - L"ApplicationName", dist->GetApplicationName())); - - entries.push_front(new RegistryEntry( - L"Software\\Clients\\StartMenuInternet\\chrome.exe\\Capabilities\\StartMenu", - L"StartMenuInternet", L"chrome.exe")); - for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) { - entries.push_front(new RegistryEntry( - L"Software\\Clients\\StartMenuInternet\\chrome.exe\\Capabilities\\FileAssociations", - ShellUtil::kFileAssociations[i], ShellUtil::kChromeHTMLProgId)); - } - for (int i = 0; ShellUtil::kProtocolAssociations[i] != NULL; i++) { - entries.push_front(new RegistryEntry( - L"Software\\Clients\\StartMenuInternet\\chrome.exe\\Capabilities\\URLAssociations", - ShellUtil::kProtocolAssociations[i], ShellUtil::kChromeHTMLProgId)); - } - return entries; - } - - // Generate work_item tasks required to create current regitry entry and - // add them to the given work item list. - void AddToWorkItemList(HKEY root, WorkItemList *items) { - items->AddCreateRegKeyWorkItem(root, _key_path); - if (_is_string) { - items->AddSetRegValueWorkItem(root, _key_path, _name, _value, true); - } else { - items->AddSetRegValueWorkItem(root, _key_path, _name, _int_value, true); - } - } - - // Check if the current registry entry exists in HKLM registry. - bool ExistsInHKLM() { - RegKey key(HKEY_LOCAL_MACHINE, _key_path.c_str()); - bool found = false; - if (_is_string) { - std::wstring read_value; - found = key.ReadValue(_name.c_str(), &read_value) && - read_value == _value; - } else { - DWORD read_value; - found = key.ReadValueDW(_name.c_str(), &read_value) && - read_value == _int_value; - } - key.Close(); - return found; - } - - private: - // Create a object that represent default value of a key - RegistryEntry(const std::wstring& key_path, const std::wstring& value) : - _key_path(key_path), _name(L""), _value(value), - _is_string(true) { - } - - // Create a object that represent a key of type REG_SZ - RegistryEntry(const std::wstring& key_path, const std::wstring& name, - const std::wstring& value) : _key_path(key_path), - _name(name), _value(value), _is_string(true) { - } - - // Create a object that represent a key of integer type - RegistryEntry(const std::wstring& key_path, const std::wstring& name, - DWORD value) : _key_path(key_path), - _name(name), _int_value(value), _is_string(false) { - } - - bool _is_string; // true if current registry entry is of type REG_SZ - std::wstring _key_path; // key path for the registry entry - std::wstring _name; // name of the registry entry - std::wstring _value; // string value (useful if _is_string = true) - DWORD _int_value; // integer value (useful if _is_string = false) -}; // class RegistryEntry - - -// This method checks if Chrome is already registered on the local machine. -// It gets all the required registry entries for Chrome and then checks if -// they exist in HKLM. Returns true if all the entries exist, otherwise false. -bool IsChromeRegistered(const std::wstring& chrome_exe) { - bool registered = true; - std::list entries = RegistryEntry::GetAllEntries(chrome_exe); - for (std::list::iterator itr = entries.begin(); - itr != entries.end(); ++itr) { - if (registered && !(*itr)->ExistsInHKLM()) - registered = false; - delete (*itr); - } - LOG(INFO) << "Check for Chrome registeration returned " << registered; - return registered; -} - -bool CreateChromeRegKeysForXP(HKEY root_key, const std::wstring& chrome_exe) { - // Create a list of registry entries to create so that we can rollback - // in case of problem. - scoped_ptr items(WorkItem::CreateWorkItemList()); - std::wstring classes_path(ShellUtil::kRegClasses); - - std::wstring exe_name = file_util::GetFilenameFromPath(chrome_exe); - std::wstring chrome_open = ShellUtil::GetChromeShellOpenCmd(chrome_exe); - std::wstring chrome_icon(chrome_exe); - ShellUtil::GetChromeIcon(chrome_icon); - - // Create Software\Classes\ChromeHTML - std::wstring html_prog_id = classes_path + L"\\" + - ShellUtil::kChromeHTMLProgId; - items->AddCreateRegKeyWorkItem(root_key, html_prog_id); - std::wstring default_icon = html_prog_id + ShellUtil::kRegDefaultIcon; - items->AddCreateRegKeyWorkItem(root_key, default_icon); - items->AddSetRegValueWorkItem(root_key, default_icon, L"", - chrome_icon, true); - std::wstring open_cmd = html_prog_id + ShellUtil::kRegShellOpen; - items->AddCreateRegKeyWorkItem(root_key, open_cmd); - items->AddSetRegValueWorkItem(root_key, open_cmd, L"", - chrome_open, true); - - // file extension associations - for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) { - std::wstring key_path = classes_path + L"\\" + - ShellUtil::kFileAssociations[i]; - items->AddCreateRegKeyWorkItem(root_key, key_path); - items->AddSetRegValueWorkItem(root_key, key_path, L"", - ShellUtil::kChromeHTMLProgId, true); - } - - // protocols associations - for (int i = 0; ShellUtil::kProtocolAssociations[i] != NULL; i++) { - std::wstring key_path = classes_path + L"\\" + - ShellUtil::kProtocolAssociations[i]; - // \Software\Classes\\DefaultIcon - std::wstring icon_path = key_path + ShellUtil::kRegDefaultIcon; - items->AddCreateRegKeyWorkItem(root_key, icon_path); - items->AddSetRegValueWorkItem(root_key, icon_path, L"", - chrome_icon, true); - // \Software\Classes\\shell\open\command - std::wstring shell_path = key_path + ShellUtil::kRegShellOpen; - items->AddCreateRegKeyWorkItem(root_key, shell_path); - items->AddSetRegValueWorkItem(root_key, shell_path, L"", - chrome_open, true); - // \Software\Classes\\shell\open\ddeexec - std::wstring dde_path = key_path + L"\\shell\\open\\ddeexec"; - items->AddCreateRegKeyWorkItem(root_key, dde_path); - items->AddSetRegValueWorkItem(root_key, dde_path, L"", L"", true); - // \Software\Classes\\shell\@ - std::wstring protocol_shell_path = key_path + ShellUtil::kRegShellPath; - items->AddSetRegValueWorkItem(root_key, protocol_shell_path, L"", - L"open", true); - } - - // start->Internet shortcut. - std::wstring start_internet(ShellUtil::kRegStartMenuInternet); - items->AddCreateRegKeyWorkItem(root_key, start_internet); - items->AddSetRegValueWorkItem(root_key, start_internet, L"", - exe_name, true); - - // Apply all the registry changes and if there is a problem, rollback - if (!items->Do()) { - LOG(ERROR) << "Error while registering Chrome as default browser"; - items->Rollback(); - return false; - } - return true; -} - -// This method creates the registry entries required for Add/Remove Programs-> -// Set Program Access and Defaults, Start->Default Programs on Windows Vista -// and Chrome ProgIds for file extension and protocol handler. root_key is -// the root registry (HKLM or HKCU). -bool SetAccessDefaultRegEntries(HKEY root_key, - const std::wstring& chrome_exe) { - LOG(INFO) << "Registering Chrome browser " << chrome_exe; - // Create a list of registry entries work items so that we can rollback - // in case of problem. - scoped_ptr items(WorkItem::CreateWorkItemList()); - - std::list entries = RegistryEntry::GetAllEntries(chrome_exe); - for (std::list::iterator itr = entries.begin(); - itr != entries.end(); ++itr) { - (*itr)->AddToWorkItemList(root_key, items.get()); - delete (*itr); - } - - // Apply all the registry changes and if there is a problem, rollback. - if (!items->Do()) { - LOG(ERROR) << "Failed to add Chrome to Set Program Access and Defaults"; - items->Rollback(); - return false; - } - - return true; -} - - -// This method registers Chrome on Vista. It checks if we are currently -// running as admin and if not, it launches setup.exe as administrator which -// will show user standard Vista elevation prompt. If user accepts it -// the new process will make the necessary changes and return SUCCESS that -// we capture and return. -ShellUtil::RegisterStatus RegisterOnVista(const std::wstring& chrome_exe, - bool skip_if_not_admin) { - if (IsUserAnAdmin() && - SetAccessDefaultRegEntries(HKEY_LOCAL_MACHINE, chrome_exe)) - return ShellUtil::SUCCESS; - - if (!skip_if_not_admin) { - std::wstring exe_path(file_util::GetDirectoryFromPath(chrome_exe)); - file_util::AppendToPath(&exe_path, installer_util::kSetupExe); - if (!file_util::PathExists(exe_path)) { - BrowserDistribution* dist = BrowserDistribution::GetDistribution(); - RegKey key(HKEY_CURRENT_USER, dist->GetUninstallRegPath().c_str()); - key.ReadValue(installer_util::kUninstallStringField, &exe_path); - exe_path = exe_path.substr(0, exe_path.find_first_of(L" --")); - TrimString(exe_path, L" \"", &exe_path); - } - if (file_util::PathExists(exe_path)) { - std::wstring params(L"--"); - params.append(installer_util::switches::kRegisterChromeBrowser); - params.append(L"=\"" + chrome_exe + L"\""); - DWORD ret_val = ShellUtil::SUCCESS; - InstallUtil::ExecuteExeAsAdmin(exe_path, params, &ret_val); - if (ret_val == ShellUtil::SUCCESS) - return ShellUtil::SUCCESS; - } - } - return ShellUtil::FAILURE; -} - -} // namespace - - -const wchar_t* ShellUtil::kRegDefaultIcon = L"\\DefaultIcon"; -const wchar_t* ShellUtil::kRegShellPath = L"\\shell"; -const wchar_t* ShellUtil::kRegShellOpen = L"\\shell\\open\\command"; -const wchar_t* ShellUtil::kRegStartMenuInternet = - L"Software\\Clients\\StartMenuInternet"; -const wchar_t* ShellUtil::kRegClasses = L"Software\\Classes"; -const wchar_t* ShellUtil::kRegRegisteredApplications = - L"Software\\RegisteredApplications"; -const wchar_t* ShellUtil::kRegShellChromeHTML = L"\\shell\\ChromeHTML"; -const wchar_t* ShellUtil::kRegShellChromeHTMLCommand = - L"\\shell\\ChromeHTML\\command"; - -const wchar_t* ShellUtil::kChromeHTMLProgId = L"ChromeHTML"; -const wchar_t* ShellUtil::kFileAssociations[] = {L".htm", L".html", L".shtml", - L".xht", L".xhtml", NULL}; -const wchar_t* ShellUtil::kProtocolAssociations[] = {L"ftp", L"http", L"https", - NULL}; - -ShellUtil::RegisterStatus ShellUtil::AddChromeToSetAccessDefaults( - const std::wstring& chrome_exe, bool skip_if_not_admin) { - if (IsChromeRegistered(chrome_exe)) - return ShellUtil::SUCCESS; - - if (win_util::GetWinVersion() == win_util::WINVERSION_VISTA) - return RegisterOnVista(chrome_exe, skip_if_not_admin); - - // Try adding these entries to HKLM first and if that fails try adding - // to HKCU. - if (SetAccessDefaultRegEntries(HKEY_LOCAL_MACHINE, chrome_exe)) - return ShellUtil::SUCCESS; - - if (!skip_if_not_admin && - SetAccessDefaultRegEntries(HKEY_CURRENT_USER, chrome_exe)) - return ShellUtil::REGISTERED_PER_USER; - - return ShellUtil::FAILURE; -} - -bool ShellUtil::GetChromeIcon(std::wstring& chrome_icon) { - if (chrome_icon.empty()) - return false; - - chrome_icon.append(L",0"); - return true; -} - +// 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. +// +// This file defines functions that integrate Chrome in Windows shell. These +// functions can be used by Chrome as well as Chrome installer. All of the +// work is done by the local functions defined in anonymous namespace in +// this class. + +#include +#include +#include + +#include "shell_util.h" + +#include "base/file_util.h" +#include "base/logging.h" +#include "base/path_service.h" +#include "base/registry.h" +#include "base/scoped_ptr.h" +#include "base/string_util.h" +#include "base/win_util.h" +#include "chrome/common/chrome_constants.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/installer/util/browser_distribution.h" +#include "chrome/installer/util/create_reg_key_work_item.h" +#include "chrome/installer/util/install_util.h" +#include "chrome/installer/util/l10n_string_util.h" +#include "chrome/installer/util/set_reg_value_work_item.h" +#include "chrome/installer/util/util_constants.h" +#include "chrome/installer/util/work_item.h" + +#include "installer_util_strings.h" + +namespace { + +// This class represents a single registry entry. The objective is to +// encapsulate all the registry entries required for registering Chrome at one +// place. This class can not be instantiated outside the class and the objects +// of this class type can be obtained only by calling a static method of this +// class. +class RegistryEntry { + public: + // This method returns a list of all the registry entries that are needed + // to register Chrome. + static std::list GetAllEntries(const std::wstring& chrome_exe) { + std::list entries; + std::wstring icon_path(chrome_exe); + ShellUtil::GetChromeIcon(icon_path); + std::wstring quoted_exe_path = L"\"" + chrome_exe + L"\""; + std::wstring open_cmd = ShellUtil::GetChromeShellOpenCmd(chrome_exe); + + entries.push_front(new RegistryEntry(L"Software\\Classes\\ChromeHTML", + L"Chrome HTML")); + entries.push_front(new RegistryEntry( + L"Software\\Classes\\ChromeHTML\\DefaultIcon", icon_path)); + entries.push_front(new RegistryEntry( + L"Software\\Classes\\ChromeHTML\\shell\\open\\command", open_cmd)); + + BrowserDistribution* dist = BrowserDistribution::GetDistribution(); + entries.push_front(new RegistryEntry( + L"Software\\Clients\\StartMenuInternet\\chrome.exe", + dist->GetApplicationName())); + entries.push_front(new RegistryEntry( + L"Software\\Clients\\StartMenuInternet\\chrome.exe\\shell\\open\\command", + quoted_exe_path)); + entries.push_front(new RegistryEntry( + L"Software\\Clients\\StartMenuInternet\\chrome.exe\\DefaultIcon", + icon_path)); + entries.push_front(new RegistryEntry( + L"Software\\Clients\\StartMenuInternet\\chrome.exe\\InstallInfo", + L"ReinstallCommand", + quoted_exe_path + L" --" + switches::kMakeDefaultBrowser)); + entries.push_front(new RegistryEntry( + L"Software\\Clients\\StartMenuInternet\\chrome.exe\\InstallInfo", + L"HideIconsCommand", + quoted_exe_path + L" --" + switches::kHideIcons)); + entries.push_front(new RegistryEntry( + L"Software\\Clients\\StartMenuInternet\\chrome.exe\\InstallInfo", + L"ShowIconsCommand", + quoted_exe_path + L" --" + switches::kShowIcons)); + entries.push_front(new RegistryEntry( + L"Software\\Clients\\StartMenuInternet\\chrome.exe\\InstallInfo", + L"IconsVisible", 1)); + + entries.push_front(new RegistryEntry( + ShellUtil::kRegRegisteredApplications, + dist->GetApplicationName(), + L"Software\\Clients\\StartMenuInternet\\chrome.exe\\Capabilities")); + entries.push_front(new RegistryEntry( + L"Software\\Clients\\StartMenuInternet\\chrome.exe\\Capabilities", + L"ApplicationDescription", dist->GetApplicationName())); + entries.push_front(new RegistryEntry( + L"Software\\Clients\\StartMenuInternet\\chrome.exe\\Capabilities", + L"ApplicationIcon", icon_path)); + entries.push_front(new RegistryEntry( + L"Software\\Clients\\StartMenuInternet\\chrome.exe\\Capabilities", + L"ApplicationName", dist->GetApplicationName())); + + entries.push_front(new RegistryEntry( + L"Software\\Clients\\StartMenuInternet\\chrome.exe\\Capabilities\\StartMenu", + L"StartMenuInternet", L"chrome.exe")); + for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) { + entries.push_front(new RegistryEntry( + L"Software\\Clients\\StartMenuInternet\\chrome.exe\\Capabilities\\FileAssociations", + ShellUtil::kFileAssociations[i], ShellUtil::kChromeHTMLProgId)); + } + for (int i = 0; ShellUtil::kProtocolAssociations[i] != NULL; i++) { + entries.push_front(new RegistryEntry( + L"Software\\Clients\\StartMenuInternet\\chrome.exe\\Capabilities\\URLAssociations", + ShellUtil::kProtocolAssociations[i], ShellUtil::kChromeHTMLProgId)); + } + return entries; + } + + // Generate work_item tasks required to create current regitry entry and + // add them to the given work item list. + void AddToWorkItemList(HKEY root, WorkItemList *items) { + items->AddCreateRegKeyWorkItem(root, _key_path); + if (_is_string) { + items->AddSetRegValueWorkItem(root, _key_path, _name, _value, true); + } else { + items->AddSetRegValueWorkItem(root, _key_path, _name, _int_value, true); + } + } + + // Check if the current registry entry exists in HKLM registry. + bool ExistsInHKLM() { + RegKey key(HKEY_LOCAL_MACHINE, _key_path.c_str()); + bool found = false; + if (_is_string) { + std::wstring read_value; + found = key.ReadValue(_name.c_str(), &read_value) && + read_value == _value; + } else { + DWORD read_value; + found = key.ReadValueDW(_name.c_str(), &read_value) && + read_value == _int_value; + } + key.Close(); + return found; + } + + private: + // Create a object that represent default value of a key + RegistryEntry(const std::wstring& key_path, const std::wstring& value) : + _key_path(key_path), _name(L""), _value(value), + _is_string(true) { + } + + // Create a object that represent a key of type REG_SZ + RegistryEntry(const std::wstring& key_path, const std::wstring& name, + const std::wstring& value) : _key_path(key_path), + _name(name), _value(value), _is_string(true) { + } + + // Create a object that represent a key of integer type + RegistryEntry(const std::wstring& key_path, const std::wstring& name, + DWORD value) : _key_path(key_path), + _name(name), _int_value(value), _is_string(false) { + } + + bool _is_string; // true if current registry entry is of type REG_SZ + std::wstring _key_path; // key path for the registry entry + std::wstring _name; // name of the registry entry + std::wstring _value; // string value (useful if _is_string = true) + DWORD _int_value; // integer value (useful if _is_string = false) +}; // class RegistryEntry + + +// This method checks if Chrome is already registered on the local machine. +// It gets all the required registry entries for Chrome and then checks if +// they exist in HKLM. Returns true if all the entries exist, otherwise false. +bool IsChromeRegistered(const std::wstring& chrome_exe) { + bool registered = true; + std::list entries = RegistryEntry::GetAllEntries(chrome_exe); + for (std::list::iterator itr = entries.begin(); + itr != entries.end(); ++itr) { + if (registered && !(*itr)->ExistsInHKLM()) + registered = false; + delete (*itr); + } + LOG(INFO) << "Check for Chrome registeration returned " << registered; + return registered; +} + +bool CreateChromeRegKeysForXP(HKEY root_key, const std::wstring& chrome_exe) { + // Create a list of registry entries to create so that we can rollback + // in case of problem. + scoped_ptr items(WorkItem::CreateWorkItemList()); + std::wstring classes_path(ShellUtil::kRegClasses); + + std::wstring exe_name = file_util::GetFilenameFromPath(chrome_exe); + std::wstring chrome_open = ShellUtil::GetChromeShellOpenCmd(chrome_exe); + std::wstring chrome_icon(chrome_exe); + ShellUtil::GetChromeIcon(chrome_icon); + + // Create Software\Classes\ChromeHTML + std::wstring html_prog_id = classes_path + L"\\" + + ShellUtil::kChromeHTMLProgId; + items->AddCreateRegKeyWorkItem(root_key, html_prog_id); + std::wstring default_icon = html_prog_id + ShellUtil::kRegDefaultIcon; + items->AddCreateRegKeyWorkItem(root_key, default_icon); + items->AddSetRegValueWorkItem(root_key, default_icon, L"", + chrome_icon, true); + std::wstring open_cmd = html_prog_id + ShellUtil::kRegShellOpen; + items->AddCreateRegKeyWorkItem(root_key, open_cmd); + items->AddSetRegValueWorkItem(root_key, open_cmd, L"", + chrome_open, true); + + // file extension associations + for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) { + std::wstring key_path = classes_path + L"\\" + + ShellUtil::kFileAssociations[i]; + items->AddCreateRegKeyWorkItem(root_key, key_path); + items->AddSetRegValueWorkItem(root_key, key_path, L"", + ShellUtil::kChromeHTMLProgId, true); + } + + // protocols associations + for (int i = 0; ShellUtil::kProtocolAssociations[i] != NULL; i++) { + std::wstring key_path = classes_path + L"\\" + + ShellUtil::kProtocolAssociations[i]; + // \Software\Classes\\DefaultIcon + std::wstring icon_path = key_path + ShellUtil::kRegDefaultIcon; + items->AddCreateRegKeyWorkItem(root_key, icon_path); + items->AddSetRegValueWorkItem(root_key, icon_path, L"", + chrome_icon, true); + // \Software\Classes\\shell\open\command + std::wstring shell_path = key_path + ShellUtil::kRegShellOpen; + items->AddCreateRegKeyWorkItem(root_key, shell_path); + items->AddSetRegValueWorkItem(root_key, shell_path, L"", + chrome_open, true); + // \Software\Classes\\shell\open\ddeexec + std::wstring dde_path = key_path + L"\\shell\\open\\ddeexec"; + items->AddCreateRegKeyWorkItem(root_key, dde_path); + items->AddSetRegValueWorkItem(root_key, dde_path, L"", L"", true); + // \Software\Classes\\shell\@ + std::wstring protocol_shell_path = key_path + ShellUtil::kRegShellPath; + items->AddSetRegValueWorkItem(root_key, protocol_shell_path, L"", + L"open", true); + } + + // start->Internet shortcut. + std::wstring start_internet(ShellUtil::kRegStartMenuInternet); + items->AddCreateRegKeyWorkItem(root_key, start_internet); + items->AddSetRegValueWorkItem(root_key, start_internet, L"", + exe_name, true); + + // Apply all the registry changes and if there is a problem, rollback + if (!items->Do()) { + LOG(ERROR) << "Error while registering Chrome as default browser"; + items->Rollback(); + return false; + } + return true; +} + +// This method creates the registry entries required for Add/Remove Programs-> +// Set Program Access and Defaults, Start->Default Programs on Windows Vista +// and Chrome ProgIds for file extension and protocol handler. root_key is +// the root registry (HKLM or HKCU). +bool SetAccessDefaultRegEntries(HKEY root_key, + const std::wstring& chrome_exe) { + LOG(INFO) << "Registering Chrome browser " << chrome_exe; + // Create a list of registry entries work items so that we can rollback + // in case of problem. + scoped_ptr items(WorkItem::CreateWorkItemList()); + + std::list entries = RegistryEntry::GetAllEntries(chrome_exe); + for (std::list::iterator itr = entries.begin(); + itr != entries.end(); ++itr) { + (*itr)->AddToWorkItemList(root_key, items.get()); + delete (*itr); + } + + // Apply all the registry changes and if there is a problem, rollback. + if (!items->Do()) { + LOG(ERROR) << "Failed to add Chrome to Set Program Access and Defaults"; + items->Rollback(); + return false; + } + + return true; +} + + +// This method registers Chrome on Vista. It checks if we are currently +// running as admin and if not, it launches setup.exe as administrator which +// will show user standard Vista elevation prompt. If user accepts it +// the new process will make the necessary changes and return SUCCESS that +// we capture and return. +ShellUtil::RegisterStatus RegisterOnVista(const std::wstring& chrome_exe, + bool skip_if_not_admin) { + if (IsUserAnAdmin() && + SetAccessDefaultRegEntries(HKEY_LOCAL_MACHINE, chrome_exe)) + return ShellUtil::SUCCESS; + + if (!skip_if_not_admin) { + std::wstring exe_path(file_util::GetDirectoryFromPath(chrome_exe)); + file_util::AppendToPath(&exe_path, installer_util::kSetupExe); + if (!file_util::PathExists(exe_path)) { + BrowserDistribution* dist = BrowserDistribution::GetDistribution(); + RegKey key(HKEY_CURRENT_USER, dist->GetUninstallRegPath().c_str()); + key.ReadValue(installer_util::kUninstallStringField, &exe_path); + exe_path = exe_path.substr(0, exe_path.find_first_of(L" --")); + TrimString(exe_path, L" \"", &exe_path); + } + if (file_util::PathExists(exe_path)) { + std::wstring params(L"--"); + params.append(installer_util::switches::kRegisterChromeBrowser); + params.append(L"=\"" + chrome_exe + L"\""); + DWORD ret_val = ShellUtil::SUCCESS; + InstallUtil::ExecuteExeAsAdmin(exe_path, params, &ret_val); + if (ret_val == ShellUtil::SUCCESS) + return ShellUtil::SUCCESS; + } + } + return ShellUtil::FAILURE; +} + +} // namespace + + +const wchar_t* ShellUtil::kRegDefaultIcon = L"\\DefaultIcon"; +const wchar_t* ShellUtil::kRegShellPath = L"\\shell"; +const wchar_t* ShellUtil::kRegShellOpen = L"\\shell\\open\\command"; +const wchar_t* ShellUtil::kRegStartMenuInternet = + L"Software\\Clients\\StartMenuInternet"; +const wchar_t* ShellUtil::kRegClasses = L"Software\\Classes"; +const wchar_t* ShellUtil::kRegRegisteredApplications = + L"Software\\RegisteredApplications"; +const wchar_t* ShellUtil::kRegShellChromeHTML = L"\\shell\\ChromeHTML"; +const wchar_t* ShellUtil::kRegShellChromeHTMLCommand = + L"\\shell\\ChromeHTML\\command"; + +const wchar_t* ShellUtil::kChromeHTMLProgId = L"ChromeHTML"; +const wchar_t* ShellUtil::kFileAssociations[] = {L".htm", L".html", L".shtml", + L".xht", L".xhtml", NULL}; +const wchar_t* ShellUtil::kProtocolAssociations[] = {L"ftp", L"http", L"https", + NULL}; + +ShellUtil::RegisterStatus ShellUtil::AddChromeToSetAccessDefaults( + const std::wstring& chrome_exe, bool skip_if_not_admin) { + if (IsChromeRegistered(chrome_exe)) + return ShellUtil::SUCCESS; + + if (win_util::GetWinVersion() == win_util::WINVERSION_VISTA) + return RegisterOnVista(chrome_exe, skip_if_not_admin); + + // Try adding these entries to HKLM first and if that fails try adding + // to HKCU. + if (SetAccessDefaultRegEntries(HKEY_LOCAL_MACHINE, chrome_exe)) + return ShellUtil::SUCCESS; + + if (!skip_if_not_admin && + SetAccessDefaultRegEntries(HKEY_CURRENT_USER, chrome_exe)) + return ShellUtil::REGISTERED_PER_USER; + + return ShellUtil::FAILURE; +} + +bool ShellUtil::GetChromeIcon(std::wstring& chrome_icon) { + if (chrome_icon.empty()) + return false; + + chrome_icon.append(L",0"); + return true; +} + std::wstring ShellUtil::GetChromeShellOpenCmd(const std::wstring& chrome_exe) { return L"\"" + chrome_exe + L"\" -- \"%1\""; } - -bool ShellUtil::GetChromeShortcutName(std::wstring* shortcut) { - BrowserDistribution* dist = BrowserDistribution::GetDistribution(); - shortcut->assign(dist->GetApplicationName()); - shortcut->append(L".lnk"); - return true; -} - -bool ShellUtil::GetDesktopPath(bool system_level, std::wstring* path) { - wchar_t desktop[MAX_PATH]; - int dir = system_level ? CSIDL_COMMON_DESKTOPDIRECTORY : CSIDL_DESKTOP; - if (FAILED(SHGetFolderPath(NULL, dir, NULL, SHGFP_TYPE_CURRENT, desktop))) - return false; - *path = desktop; - return true; -} - -bool ShellUtil::GetQuickLaunchPath(bool system_level, std::wstring* path) { - const static wchar_t* kQuickLaunchPath = - L"Microsoft\\Internet Explorer\\Quick Launch"; - wchar_t qlaunch[MAX_PATH]; - if (system_level) { - // We are accessing GetDefaultUserProfileDirectory this way so that we do - // not have to declare dependency to Userenv.lib for chrome.exe - typedef BOOL (WINAPI *PROFILE_FUNC)(LPWSTR, LPDWORD); - HMODULE module = LoadLibrary(L"Userenv.dll"); - PROFILE_FUNC p = reinterpret_cast(GetProcAddress(module, - "GetDefaultUserProfileDirectoryW")); - DWORD size = _countof(qlaunch); - if ((p == NULL) || ((p)(qlaunch, &size) != TRUE)) - return false; - *path = qlaunch; - if (win_util::GetWinVersion() == win_util::WINVERSION_VISTA) { - file_util::AppendToPath(path, L"AppData\\Roaming"); - } else { - file_util::AppendToPath(path, L"Application Data"); - } - } else { - if (FAILED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, - SHGFP_TYPE_CURRENT, qlaunch))) - return false; - *path = qlaunch; - } - file_util::AppendToPath(path, kQuickLaunchPath); - return true; -} - -bool ShellUtil::CreateChromeDesktopShortcut(const std::wstring& chrome_exe, - int shell_change, - bool create_new) { - std::wstring shortcut_name; - if (!ShellUtil::GetChromeShortcutName(&shortcut_name)) - return false; - - bool ret = true; - if (shell_change & ShellUtil::CURRENT_USER) { - std::wstring shortcut_path; - if (ShellUtil::GetDesktopPath(false, &shortcut_path)) { - file_util::AppendToPath(&shortcut_path, shortcut_name); - ret = ret && ShellUtil::UpdateChromeShortcut(chrome_exe, shortcut_path, - create_new); - } else { - ret = false; - } - } - if (shell_change & ShellUtil::SYSTEM_LEVEL) { - std::wstring shortcut_path; - if (ShellUtil::GetDesktopPath(true, &shortcut_path)) { - file_util::AppendToPath(&shortcut_path, shortcut_name); - ret = ret && ShellUtil::UpdateChromeShortcut(chrome_exe, shortcut_path, - create_new); - } else { - ret = false; - } - } - return ret; -} - -bool ShellUtil::CreateChromeQuickLaunchShortcut(const std::wstring& chrome_exe, - int shell_change, - bool create_new) { - std::wstring shortcut_name; - if (!ShellUtil::GetChromeShortcutName(&shortcut_name)) - return false; - - bool ret = true; - // First create shortcut for the current user. - if (shell_change & ShellUtil::CURRENT_USER) { - std::wstring user_ql_path; - if (ShellUtil::GetQuickLaunchPath(false, &user_ql_path)) { - file_util::AppendToPath(&user_ql_path, shortcut_name); - ret = ret && ShellUtil::UpdateChromeShortcut(chrome_exe, user_ql_path, - create_new); - } else { - ret = false; - } - } - - // Add a shortcut to Default User's profile so that all new user profiles - // get it. - if (shell_change & ShellUtil::SYSTEM_LEVEL) { - std::wstring default_ql_path; - if (ShellUtil::GetQuickLaunchPath(true, &default_ql_path)) { - file_util::AppendToPath(&default_ql_path, shortcut_name); - ret = ret && ShellUtil::UpdateChromeShortcut(chrome_exe, default_ql_path, - create_new); - } else { - ret = false; - } - } - - return ret; -} - -bool ShellUtil::MakeChromeDefault(int shell_change, - const std::wstring chrome_exe) { - bool ret = true; - if (win_util::GetWinVersion() == win_util::WINVERSION_VISTA) { - LOG(INFO) << "Registering Chrome as default browser on Vista."; - IApplicationAssociationRegistration* pAAR; - HRESULT hr = CoCreateInstance(CLSID_ApplicationAssociationRegistration, - NULL, CLSCTX_INPROC, __uuidof(IApplicationAssociationRegistration), - (void**)&pAAR); - if (SUCCEEDED(hr)) { - BrowserDistribution* dist = BrowserDistribution::GetDistribution(); - hr = pAAR->SetAppAsDefaultAll(dist->GetApplicationName().c_str()); - pAAR->Release(); - } - if (!SUCCEEDED(hr)) { - ret = false; - LOG(ERROR) << "Could not make Chrome default browser."; - } - } else { - // Change the default browser for current user. - if ((shell_change & ShellUtil::CURRENT_USER) && - !CreateChromeRegKeysForXP(HKEY_CURRENT_USER, chrome_exe)) - ret = false; - - // Chrome as default browser at system level. - if ((shell_change & ShellUtil::SYSTEM_LEVEL) && - !CreateChromeRegKeysForXP(HKEY_LOCAL_MACHINE, chrome_exe)) - ret = false; - } - - // Send Windows notification event so that it can update icons for - // file associations. - SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); - return ret; -} - -bool ShellUtil::RemoveChromeDesktopShortcut(int shell_change) { - std::wstring shortcut_name; - if (!ShellUtil::GetChromeShortcutName(&shortcut_name)) - return false; - - bool ret = true; - if (shell_change & ShellUtil::CURRENT_USER) { - std::wstring shortcut_path; - if (ShellUtil::GetDesktopPath(false, &shortcut_path)) { - file_util::AppendToPath(&shortcut_path, shortcut_name); - ret = ret && file_util::Delete(shortcut_path, false); - } else { - ret = false; - } - } - - if (shell_change & ShellUtil::SYSTEM_LEVEL) { - std::wstring shortcut_path; - if (ShellUtil::GetDesktopPath(true, &shortcut_path)) { - file_util::AppendToPath(&shortcut_path, shortcut_name); - ret = ret && file_util::Delete(shortcut_path, false); - } else { - ret = false; - } - } - return ret; -} - -bool ShellUtil::RemoveChromeQuickLaunchShortcut(int shell_change) { - std::wstring shortcut_name; - if (!ShellUtil::GetChromeShortcutName(&shortcut_name)) - return false; - - bool ret = true; - // First remove shortcut for the current user. - if (shell_change & ShellUtil::CURRENT_USER) { - std::wstring user_ql_path; - if (ShellUtil::GetQuickLaunchPath(false, &user_ql_path)) { - file_util::AppendToPath(&user_ql_path, shortcut_name); - ret = ret && file_util::Delete(user_ql_path, false); - } else { - ret = false; - } - } - - // Delete shortcut in Default User's profile - if (shell_change & ShellUtil::SYSTEM_LEVEL) { - std::wstring default_ql_path; - if (ShellUtil::GetQuickLaunchPath(true, &default_ql_path)) { - file_util::AppendToPath(&default_ql_path, shortcut_name); - ret = ret && file_util::Delete(default_ql_path, false); - } else { - ret = false; - } - } - - return ret; -} - -bool ShellUtil::UpdateChromeShortcut(const std::wstring& chrome_exe, - const std::wstring& shortcut, - bool create_new) { - std::wstring chrome_path = file_util::GetDirectoryFromPath(chrome_exe); - if (create_new) { - return file_util::CreateShortcutLink(chrome_exe.c_str(), // target - shortcut.c_str(), // shortcut - chrome_path.c_str(), // working dir - NULL, // arguments - NULL, // description - chrome_exe.c_str(), // icon file - 0); // icon index - } else { - return file_util::UpdateShortcutLink(chrome_exe.c_str(), // target - shortcut.c_str(), // shortcut - chrome_path.c_str(), // working dir - NULL, // arguments - NULL, // description - chrome_exe.c_str(), // icon file - 0); // icon index - } -} - + +bool ShellUtil::GetChromeShortcutName(std::wstring* shortcut) { + BrowserDistribution* dist = BrowserDistribution::GetDistribution(); + shortcut->assign(dist->GetApplicationName()); + shortcut->append(L".lnk"); + return true; +} + +bool ShellUtil::GetDesktopPath(bool system_level, std::wstring* path) { + wchar_t desktop[MAX_PATH]; + int dir = system_level ? CSIDL_COMMON_DESKTOPDIRECTORY : CSIDL_DESKTOP; + if (FAILED(SHGetFolderPath(NULL, dir, NULL, SHGFP_TYPE_CURRENT, desktop))) + return false; + *path = desktop; + return true; +} + +bool ShellUtil::GetQuickLaunchPath(bool system_level, std::wstring* path) { + const static wchar_t* kQuickLaunchPath = + L"Microsoft\\Internet Explorer\\Quick Launch"; + wchar_t qlaunch[MAX_PATH]; + if (system_level) { + // We are accessing GetDefaultUserProfileDirectory this way so that we do + // not have to declare dependency to Userenv.lib for chrome.exe + typedef BOOL (WINAPI *PROFILE_FUNC)(LPWSTR, LPDWORD); + HMODULE module = LoadLibrary(L"Userenv.dll"); + PROFILE_FUNC p = reinterpret_cast(GetProcAddress(module, + "GetDefaultUserProfileDirectoryW")); + DWORD size = _countof(qlaunch); + if ((p == NULL) || ((p)(qlaunch, &size) != TRUE)) + return false; + *path = qlaunch; + if (win_util::GetWinVersion() == win_util::WINVERSION_VISTA) { + file_util::AppendToPath(path, L"AppData\\Roaming"); + } else { + file_util::AppendToPath(path, L"Application Data"); + } + } else { + if (FAILED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, + SHGFP_TYPE_CURRENT, qlaunch))) + return false; + *path = qlaunch; + } + file_util::AppendToPath(path, kQuickLaunchPath); + return true; +} + +bool ShellUtil::CreateChromeDesktopShortcut(const std::wstring& chrome_exe, + int shell_change, + bool create_new) { + std::wstring shortcut_name; + if (!ShellUtil::GetChromeShortcutName(&shortcut_name)) + return false; + + bool ret = true; + if (shell_change & ShellUtil::CURRENT_USER) { + std::wstring shortcut_path; + if (ShellUtil::GetDesktopPath(false, &shortcut_path)) { + file_util::AppendToPath(&shortcut_path, shortcut_name); + ret = ret && ShellUtil::UpdateChromeShortcut(chrome_exe, shortcut_path, + create_new); + } else { + ret = false; + } + } + if (shell_change & ShellUtil::SYSTEM_LEVEL) { + std::wstring shortcut_path; + if (ShellUtil::GetDesktopPath(true, &shortcut_path)) { + file_util::AppendToPath(&shortcut_path, shortcut_name); + ret = ret && ShellUtil::UpdateChromeShortcut(chrome_exe, shortcut_path, + create_new); + } else { + ret = false; + } + } + return ret; +} + +bool ShellUtil::CreateChromeQuickLaunchShortcut(const std::wstring& chrome_exe, + int shell_change, + bool create_new) { + std::wstring shortcut_name; + if (!ShellUtil::GetChromeShortcutName(&shortcut_name)) + return false; + + bool ret = true; + // First create shortcut for the current user. + if (shell_change & ShellUtil::CURRENT_USER) { + std::wstring user_ql_path; + if (ShellUtil::GetQuickLaunchPath(false, &user_ql_path)) { + file_util::AppendToPath(&user_ql_path, shortcut_name); + ret = ret && ShellUtil::UpdateChromeShortcut(chrome_exe, user_ql_path, + create_new); + } else { + ret = false; + } + } + + // Add a shortcut to Default User's profile so that all new user profiles + // get it. + if (shell_change & ShellUtil::SYSTEM_LEVEL) { + std::wstring default_ql_path; + if (ShellUtil::GetQuickLaunchPath(true, &default_ql_path)) { + file_util::AppendToPath(&default_ql_path, shortcut_name); + ret = ret && ShellUtil::UpdateChromeShortcut(chrome_exe, default_ql_path, + create_new); + } else { + ret = false; + } + } + + return ret; +} + +bool ShellUtil::MakeChromeDefault(int shell_change, + const std::wstring chrome_exe) { + bool ret = true; + if (win_util::GetWinVersion() == win_util::WINVERSION_VISTA) { + LOG(INFO) << "Registering Chrome as default browser on Vista."; + IApplicationAssociationRegistration* pAAR; + HRESULT hr = CoCreateInstance(CLSID_ApplicationAssociationRegistration, + NULL, CLSCTX_INPROC, __uuidof(IApplicationAssociationRegistration), + (void**)&pAAR); + if (SUCCEEDED(hr)) { + BrowserDistribution* dist = BrowserDistribution::GetDistribution(); + hr = pAAR->SetAppAsDefaultAll(dist->GetApplicationName().c_str()); + pAAR->Release(); + } + if (!SUCCEEDED(hr)) { + ret = false; + LOG(ERROR) << "Could not make Chrome default browser."; + } + } else { + // Change the default browser for current user. + if ((shell_change & ShellUtil::CURRENT_USER) && + !CreateChromeRegKeysForXP(HKEY_CURRENT_USER, chrome_exe)) + ret = false; + + // Chrome as default browser at system level. + if ((shell_change & ShellUtil::SYSTEM_LEVEL) && + !CreateChromeRegKeysForXP(HKEY_LOCAL_MACHINE, chrome_exe)) + ret = false; + } + + // Send Windows notification event so that it can update icons for + // file associations. + SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); + return ret; +} + +bool ShellUtil::RemoveChromeDesktopShortcut(int shell_change) { + std::wstring shortcut_name; + if (!ShellUtil::GetChromeShortcutName(&shortcut_name)) + return false; + + bool ret = true; + if (shell_change & ShellUtil::CURRENT_USER) { + std::wstring shortcut_path; + if (ShellUtil::GetDesktopPath(false, &shortcut_path)) { + file_util::AppendToPath(&shortcut_path, shortcut_name); + ret = ret && file_util::Delete(shortcut_path, false); + } else { + ret = false; + } + } + + if (shell_change & ShellUtil::SYSTEM_LEVEL) { + std::wstring shortcut_path; + if (ShellUtil::GetDesktopPath(true, &shortcut_path)) { + file_util::AppendToPath(&shortcut_path, shortcut_name); + ret = ret && file_util::Delete(shortcut_path, false); + } else { + ret = false; + } + } + return ret; +} + +bool ShellUtil::RemoveChromeQuickLaunchShortcut(int shell_change) { + std::wstring shortcut_name; + if (!ShellUtil::GetChromeShortcutName(&shortcut_name)) + return false; + + bool ret = true; + // First remove shortcut for the current user. + if (shell_change & ShellUtil::CURRENT_USER) { + std::wstring user_ql_path; + if (ShellUtil::GetQuickLaunchPath(false, &user_ql_path)) { + file_util::AppendToPath(&user_ql_path, shortcut_name); + ret = ret && file_util::Delete(user_ql_path, false); + } else { + ret = false; + } + } + + // Delete shortcut in Default User's profile + if (shell_change & ShellUtil::SYSTEM_LEVEL) { + std::wstring default_ql_path; + if (ShellUtil::GetQuickLaunchPath(true, &default_ql_path)) { + file_util::AppendToPath(&default_ql_path, shortcut_name); + ret = ret && file_util::Delete(default_ql_path, false); + } else { + ret = false; + } + } + + return ret; +} + +bool ShellUtil::UpdateChromeShortcut(const std::wstring& chrome_exe, + const std::wstring& shortcut, + bool create_new) { + std::wstring chrome_path = file_util::GetDirectoryFromPath(chrome_exe); + if (create_new) { + return file_util::CreateShortcutLink(chrome_exe.c_str(), // target + shortcut.c_str(), // shortcut + chrome_path.c_str(), // working dir + NULL, // arguments + NULL, // description + chrome_exe.c_str(), // icon file + 0); // icon index + } else { + return file_util::UpdateShortcutLink(chrome_exe.c_str(), // target + shortcut.c_str(), // shortcut + chrome_path.c_str(), // working dir + NULL, // arguments + NULL, // description + chrome_exe.c_str(), // icon file + 0); // icon index + } +} + diff --git a/chrome/installer/util/util_constants.cc b/chrome/installer/util/util_constants.cc old mode 100644 new mode 100755 index b2ee77e..8642cc6 --- a/chrome/installer/util/util_constants.cc +++ b/chrome/installer/util/util_constants.cc @@ -1,65 +1,68 @@ -// 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 "chrome/installer/util/util_constants.h" - -namespace installer_util { - -namespace switches { - -// Create Desktop and QuickLaunch shortcuts -const wchar_t kCreateAllShortcuts[] = L"create-all-shortcuts"; - -// Disable logging -const wchar_t kDisableLogging[] = L"disable-logging"; - -// By default we remove all shared (between users) files, registry entries etc -// during uninstall. If this option is specified together with kUninstall option -// we do not clean up shared entries otherwise this option is ignored. -const wchar_t kDoNotRemoveSharedItems[] = L"do-not-remove-shared-items"; - -// Enable logging at the error level. This is the default behavior. -const wchar_t kEnableLogging[] = L"enable-logging"; - -// If present, setup will uninstall chrome without asking for any -// confirmation from user. -const wchar_t kForceUninstall[] = L"force-uninstall"; - -// Specify the file path of Chrome archive for install. -const wchar_t kInstallArchive[] = L"install-archive"; - -// If present, specify file path to write logging info. -const wchar_t kLogFile[] = L"log-file"; - -// Register Chrome as a valid browser on the current sytem. This option -// requires that setup.exe is running as admin. If this option is specified, -// options kInstallArchive and kUninstall are ignored. -const wchar_t kRegisterChromeBrowser[] = L"register-chrome-browser"; - -// Register Chrome as default browser on the system. Usually this will require -// that setup is running as admin. If running as admin we try to register -// as default browser at system level, if running as non-admin we try to -// register as default browser only for the current user. -const wchar_t kMakeChromeDefault[] = L"make-chrome-default"; - -// Install Chrome to system wise location. The default is per user install. -const wchar_t kSystemLevel[] = L"system-level"; - -// If present, setup will uninstall chrome. -const wchar_t kUninstall[] = L"uninstall"; - -// Enable verbose logging (info level). -const wchar_t kVerboseLogging[] = L"verbose-logging"; - -} // namespace switches - -const wchar_t kInstallBinaryDir[] = L"Application"; -const wchar_t kChromeExe[] = L"chrome.exe"; -const wchar_t kChromeDll[] = L"chrome.dll"; -const wchar_t kSetupExe[] = L"setup.exe"; - -const wchar_t kUninstallStringField[] = L"UninstallString"; -const wchar_t kUninstallDisplayNameField[] = L"DisplayName"; -} // namespace installer_util - +// 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 "chrome/installer/util/util_constants.h" + +namespace installer_util { + +namespace switches { + +// Create Desktop and QuickLaunch shortcuts +const wchar_t kCreateAllShortcuts[] = L"create-all-shortcuts"; + +// Disable logging +const wchar_t kDisableLogging[] = L"disable-logging"; + +// Prevent installer from launching Chrome after a successful first install. +const wchar_t kDoNotLaunchChrome[] = L"do-not-launch-chrome"; + +// By default we remove all shared (between users) files, registry entries etc +// during uninstall. If this option is specified together with kUninstall option +// we do not clean up shared entries otherwise this option is ignored. +const wchar_t kDoNotRemoveSharedItems[] = L"do-not-remove-shared-items"; + +// Enable logging at the error level. This is the default behavior. +const wchar_t kEnableLogging[] = L"enable-logging"; + +// If present, setup will uninstall chrome without asking for any +// confirmation from user. +const wchar_t kForceUninstall[] = L"force-uninstall"; + +// Specify the file path of Chrome archive for install. +const wchar_t kInstallArchive[] = L"install-archive"; + +// If present, specify file path to write logging info. +const wchar_t kLogFile[] = L"log-file"; + +// Register Chrome as default browser on the system. Usually this will require +// that setup is running as admin. If running as admin we try to register +// as default browser at system level, if running as non-admin we try to +// register as default browser only for the current user. +const wchar_t kMakeChromeDefault[] = L"make-chrome-default"; + +// Register Chrome as a valid browser on the current sytem. This option +// requires that setup.exe is running as admin. If this option is specified, +// options kInstallArchive and kUninstall are ignored. +const wchar_t kRegisterChromeBrowser[] = L"register-chrome-browser"; + +// Install Chrome to system wise location. The default is per user install. +const wchar_t kSystemLevel[] = L"system-level"; + +// If present, setup will uninstall chrome. +const wchar_t kUninstall[] = L"uninstall"; + +// Enable verbose logging (info level). +const wchar_t kVerboseLogging[] = L"verbose-logging"; + +} // namespace switches + +const wchar_t kInstallBinaryDir[] = L"Application"; +const wchar_t kChromeExe[] = L"chrome.exe"; +const wchar_t kChromeDll[] = L"chrome.dll"; +const wchar_t kSetupExe[] = L"setup.exe"; + +const wchar_t kUninstallStringField[] = L"UninstallString"; +const wchar_t kUninstallDisplayNameField[] = L"DisplayName"; +} // namespace installer_util + diff --git a/chrome/installer/util/util_constants.h b/chrome/installer/util/util_constants.h old mode 100644 new mode 100755 index e5b6aa3..459dff2 --- a/chrome/installer/util/util_constants.h +++ b/chrome/installer/util/util_constants.h @@ -1,61 +1,62 @@ -// 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. -// -// Defines all install related constants that need to be used by Chrome as -// well as Chrome Installer. - -#ifndef CHROME_INSTALLER_UTIL_UTIL_CONSTANTS_H__ -#define CHROME_INSTALLER_UTIL_UTIL_CONSTANTS_H__ - -namespace installer_util { - -// Return status of installer -enum InstallStatus { - FIRST_INSTALL_SUCCESS, // Successfully installed Chrome for the first time - INSTALL_REPAIRED, // Same version reinstalled for repair - 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 - 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 - TEMP_DIR_FAILED, // Unable to get Temp directory - UNCOMPRESSION_FAILED, // Failed to uncompress Chrome archive - INVALID_ARCHIVE, // Something wrong with the installer archive - CHROME_NOT_INSTALLED, // Chrome not installed (returned in case of uninstall) - CHROME_RUNNING, // Chrome currently running (when trying to uninstall) - UNINSTALL_CONFIRMED, // User has confirmed Chrome uninstall - UNINSTALL_SUCCESSFUL, // Chrome successfully uninstalled - UNINSTALL_FAILED, // Chrome uninstallation failed - UNINSTALL_CANCELLED, // User cancelled Chrome uninstallation - UNKNOWN_STATUS, // Unknown status (this should never happen) -}; - -namespace switches { -extern const wchar_t kCreateAllShortcuts[]; -extern const wchar_t kDisableLogging[]; -extern const wchar_t kDoNotRemoveSharedItems[]; -extern const wchar_t kEnableLogging[]; -extern const wchar_t kForceUninstall[]; -extern const wchar_t kInstallArchive[]; -extern const wchar_t kLogFile[]; -extern const wchar_t kRegisterChromeBrowser[]; -extern const wchar_t kMakeChromeDefault[]; -extern const wchar_t kSystemLevel[]; -extern const wchar_t kUninstall[]; -extern const wchar_t kVerboseLogging[]; -} // namespace switches - -extern const wchar_t kInstallBinaryDir[]; -extern const wchar_t kChromeExe[]; -extern const wchar_t kChromeDll[]; -extern const wchar_t kSetupExe[]; - -extern const wchar_t kUninstallStringField[]; -extern const wchar_t kUninstallDisplayNameField[]; -} // namespace installer_util - -#endif // CHROME_INSTALLER_UTIL_UTIL_CONSTANTS_H__ - +// 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. +// +// Defines all install related constants that need to be used by Chrome as +// well as Chrome Installer. + +#ifndef CHROME_INSTALLER_UTIL_UTIL_CONSTANTS_H__ +#define CHROME_INSTALLER_UTIL_UTIL_CONSTANTS_H__ + +namespace installer_util { + +// Return status of installer +enum InstallStatus { + FIRST_INSTALL_SUCCESS, // Successfully installed Chrome for the first time + INSTALL_REPAIRED, // Same version reinstalled for repair + 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 + 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 + TEMP_DIR_FAILED, // Unable to get Temp directory + UNCOMPRESSION_FAILED, // Failed to uncompress Chrome archive + INVALID_ARCHIVE, // Something wrong with the installer archive + CHROME_NOT_INSTALLED, // Chrome not installed (returned in case of uninstall) + CHROME_RUNNING, // Chrome currently running (when trying to uninstall) + UNINSTALL_CONFIRMED, // User has confirmed Chrome uninstall + UNINSTALL_SUCCESSFUL, // Chrome successfully uninstalled + UNINSTALL_FAILED, // Chrome uninstallation failed + UNINSTALL_CANCELLED, // User cancelled Chrome uninstallation + UNKNOWN_STATUS, // Unknown status (this should never happen) +}; + +namespace switches { +extern const wchar_t kCreateAllShortcuts[]; +extern const wchar_t kDisableLogging[]; +extern const wchar_t kDoNotLaunchChrome[]; +extern const wchar_t kDoNotRemoveSharedItems[]; +extern const wchar_t kEnableLogging[]; +extern const wchar_t kForceUninstall[]; +extern const wchar_t kInstallArchive[]; +extern const wchar_t kLogFile[]; +extern const wchar_t kMakeChromeDefault[]; +extern const wchar_t kRegisterChromeBrowser[]; +extern const wchar_t kSystemLevel[]; +extern const wchar_t kUninstall[]; +extern const wchar_t kVerboseLogging[]; +} // namespace switches + +extern const wchar_t kInstallBinaryDir[]; +extern const wchar_t kChromeExe[]; +extern const wchar_t kChromeDll[]; +extern const wchar_t kSetupExe[]; + +extern const wchar_t kUninstallStringField[]; +extern const wchar_t kUninstallDisplayNameField[]; +} // namespace installer_util + +#endif // CHROME_INSTALLER_UTIL_UTIL_CONSTANTS_H__ + -- cgit v1.1