diff options
Diffstat (limited to 'chrome/installer/setup/install.cc')
-rw-r--r-- | chrome/installer/setup/install.cc | 269 |
1 files changed, 269 insertions, 0 deletions
diff --git a/chrome/installer/setup/install.cc b/chrome/installer/setup/install.cc new file mode 100644 index 0000000..5cd0f22 --- /dev/null +++ b/chrome/installer/setup/install.cc @@ -0,0 +1,269 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <time.h> + +#include "base/file_util.h" +#include "base/scoped_ptr.h" +#include "base/string_util.h" +#include "chrome/installer/setup/setup.h" +#include "chrome/installer/setup/setup_constants.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/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" + +namespace { +std::wstring AppendPath(const std::wstring parent_path, + const std::wstring path) { + std::wstring new_path(parent_path); + file_util::AppendToPath(&new_path, path); + return new_path; +} + + +// This method adds work items to create (or update) Chrome uninstall entry in +// Control Panel->Add/Remove Programs list. +void AddUninstallShortcutWorkItems(HKEY reg_root, + const std::wstring& exe_path, + const std::wstring& install_path, + const std::wstring& new_version, + WorkItemList* install_list) { + std::wstring uninstall_cmd(L"\""); + uninstall_cmd.append(installer::GetInstallerPathUnderChrome(install_path, + new_version)); + file_util::AppendToPath(&uninstall_cmd, + file_util::GetFilenameFromPath(exe_path)); + uninstall_cmd.append(L"\" --"); + uninstall_cmd.append(installer_util::switches::kUninstall); + + // Create DisplayName, UninstallString and InstallLocation keys + install_list->AddCreateRegKeyWorkItem(reg_root, + installer_util::kUninstallRegPath); + install_list->AddSetRegValueWorkItem( + reg_root, + installer_util::kUninstallRegPath, + installer_util::kUninstallDisplayNameField, + installer_util::kChrome, true); + install_list->AddSetRegValueWorkItem(reg_root, + installer_util::kUninstallRegPath, + installer_util::kUninstallStringField, + uninstall_cmd, true); + install_list->AddSetRegValueWorkItem(reg_root, + installer_util::kUninstallRegPath, + L"InstallLocation", install_path, true); + + // DisplayIcon, NoModify and NoRepair + std::wstring chrome_icon = AppendPath(install_path, + installer_util::kChromeExe); + ShellUtil::GetChromeIcon(chrome_icon); + install_list->AddSetRegValueWorkItem(reg_root, + installer_util::kUninstallRegPath, + L"DisplayIcon", chrome_icon, true); + install_list->AddSetRegValueWorkItem(reg_root, + installer_util::kUninstallRegPath, + L"NoModify", 1, true); + install_list->AddSetRegValueWorkItem(reg_root, + installer_util::kUninstallRegPath, + L"NoRepair", 1, true); + + install_list->AddSetRegValueWorkItem(reg_root, + installer_util::kUninstallRegPath, + L"Publisher", + installer_util::kPublisherName, true); + install_list->AddSetRegValueWorkItem(reg_root, + installer_util::kUninstallRegPath, + L"Version", new_version.c_str(), true); + install_list->AddSetRegValueWorkItem(reg_root, + installer_util::kUninstallRegPath, + L"DisplayVersion", + new_version.c_str(), true); + time_t rawtime = time(NULL); + struct tm timeinfo = {0}; + localtime_s(&timeinfo, &rawtime); + wchar_t buffer[9]; + if (wcsftime(buffer, 9, L"%Y%m%d", &timeinfo) == 8) { + install_list->AddSetRegValueWorkItem(reg_root, + installer_util::kUninstallRegPath, + L"InstallDate", + buffer, false); + } +} + +void AddInstallerCopyTasks(const std::wstring& exe_path, + const std::wstring& archive_path, + const std::wstring& temp_path, + const std::wstring& install_path, + const std::wstring& new_version, + WorkItemList* install_list) { + std::wstring installer_dir(installer::GetInstallerPathUnderChrome( + install_path, new_version)); + install_list->AddCreateDirWorkItem(installer_dir); + + std::wstring exe_dst(installer_dir); + std::wstring archive_dst(installer_dir); + file_util::AppendToPath(&exe_dst, + file_util::GetFilenameFromPath(exe_path)); + file_util::AppendToPath(&archive_dst, + file_util::GetFilenameFromPath(archive_path)); + + install_list->AddCopyTreeWorkItem(exe_path, exe_dst, temp_path, + WorkItem::ALWAYS); + install_list->AddCopyTreeWorkItem(archive_path, archive_dst, temp_path, + WorkItem::ALWAYS); +} + + +// This method tells if we are running on 64 bit platform so that we can copy +// one extra exe. If the API call to determine 64 bit fails, we play it safe +// and return true anyway so that the executable can be copied. +bool Is64bit() { + typedef BOOL (WINAPI *WOW_FUNC)(HANDLE, PBOOL); + BOOL is64 = FALSE; + + HANDLE handle = GetCurrentProcess(); + HMODULE module = GetModuleHandle(L"kernel32.dll"); + WOW_FUNC p = reinterpret_cast<WOW_FUNC>(GetProcAddress(module, + "IsWow64Process")); + if ((p != NULL) && (!(p)(handle, &is64) || (is64 != FALSE))) { + return true; + } + + return false; +} + +} + +bool installer::InstallNewVersion(const std::wstring& exe_path, + const std::wstring& archive_path, + const std::wstring& src_path, + const std::wstring& install_path, + const std::wstring& temp_dir, + const HKEY reg_root, + const Version& new_version) { + + if (reg_root != HKEY_LOCAL_MACHINE && reg_root != HKEY_CURRENT_USER) + return false; + + scoped_ptr<WorkItemList> install_list(WorkItem::CreateWorkItemList()); + // A temp directory that work items need and the actual install directory. + install_list->AddCreateDirWorkItem(temp_dir); + install_list->AddCreateDirWorkItem(install_path); + + // Browse for all the files in archive, add work items to copy them while + // handling special cases of executables. + LOG(INFO) << "Looking for Chrome installation files under " << src_path; + std::wstring root_path(src_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; + while (ret) { + LOG(INFO) << "directory found: " << find_file_data.cFileName; + // We do not want any directories starting with '.' + if ((wcslen(find_file_data.cFileName) <= 0) || + (find_file_data.cFileName[0] == '.')) { + LOG(INFO) << "Ignoring directory found: " << find_file_data.cFileName; + } else if (_wcsicmp(find_file_data.cFileName, + installer_util::kChromeExe) == 0) { + // Special case of chrome.exe. Delete any new_chrome.exe if present + // (we will create a new one if chrome.exe is in use) and then + // copy chrome.exe. + install_list->AddDeleteTreeWorkItem( + AppendPath(install_path, installer::kChromeNewExe), std::wstring()); + install_list->AddCopyTreeWorkItem( + AppendPath(src_path, installer_util::kChromeExe), + AppendPath(install_path, installer_util::kChromeExe), + temp_dir, WorkItem::RENAME_IF_IN_USE, + AppendPath(install_path, installer::kChromeNewExe)); + } else if (_wcsicmp(find_file_data.cFileName, + installer::kWowHelperExe) == 0) { + // Special case of wow_helper.exe which is required only on 64 bit + // systems. This exe runs only for a short time when Chrome starts so + // it should not be locked most of the times and can be overwritten + // directly. + if (Is64bit()) { + install_list->AddCopyTreeWorkItem( + AppendPath(src_path, installer::kWowHelperExe), + AppendPath(install_path, installer::kWowHelperExe), + temp_dir, WorkItem::ALWAYS); + } + } else { + // In all other cases just copy the file/directory to install location. + install_list->AddCopyTreeWorkItem( + AppendPath(src_path, find_file_data.cFileName), + AppendPath(install_path, find_file_data.cFileName), + temp_dir, WorkItem::ALWAYS); // Always overwrite. + } + ret = FindNextFile(file_handle, &find_file_data); + } + FindClose(file_handle); + + // Copy installer in install directory and + // add shortcut in Control Panel->Add/Remove Programs. + AddInstallerCopyTasks(exe_path, archive_path, temp_dir, install_path, + new_version.GetString(), install_list.get()); + AddUninstallShortcutWorkItems(reg_root, exe_path, install_path, + new_version.GetString(), install_list.get()); + + // Delete any old_chrome.exe if present. + install_list->AddDeleteTreeWorkItem( + AppendPath(install_path, installer::kChromeOldExe), std::wstring()); + + // Create Google Update key (if not already present) and set the new Chrome + // version as last step. + std::wstring chrome_google_update_key = + InstallUtil::GetChromeGoogleUpdateKey(); + install_list->AddCreateRegKeyWorkItem(reg_root, chrome_google_update_key); + install_list->AddSetRegValueWorkItem(reg_root, chrome_google_update_key, + google_update::kRegNameField, + installer_util::kChrome, + false); // Don't overwrite. + install_list->AddSetRegValueWorkItem(reg_root, chrome_google_update_key, + google_update::kRegVersionField, + new_version.GetString(), + true); // overwrite version + + // Perform install operations. + if (!install_list->Do()) { + LOG(ERROR) << "install failed, roll back... "; + install_list->Rollback(); + return false; + } + + return true; +} |