// Copyright (c) 2012 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/test/mini_installer_test/installer_path_provider.h" #include #include "base/command_line.h" #include "base/file_util.h" #include "base/files/file_enumerator.h" #include "base/path_service.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "chrome/test/mini_installer_test/installer_test_util.h" #include "chrome/test/mini_installer_test/mini_installer_test_constants.h" #include "testing/gtest/include/gtest/gtest.h" namespace { struct FilePathInfo { base::FileEnumerator::FileInfo info; base::FilePath path; }; bool CompareDate(const FilePathInfo& a, const FilePathInfo& b) { return a.info.GetLastModifiedTime() > b.info.GetLastModifiedTime(); } // Get list of file |type| matching |pattern| in |root|. // The list is sorted in last modified date order. // Return true if files/directories are found. bool FindMatchingFiles(const base::FilePath& root, const std::string& pattern, base::FileEnumerator::FileType type, std::vector* paths) { base::FileEnumerator files(root, false, type, base::FilePath().AppendASCII(pattern).value()); std::vector matches; for (base::FilePath current = files.Next(); !current.empty(); current = files.Next()) { FilePathInfo entry; entry.info = files.GetInfo(); entry.path = current; matches.push_back(entry); } if (matches.empty()) return false; std::sort(matches.begin(), matches.end(), CompareDate); std::vector::iterator current; for (current = matches.begin(); current != matches.end(); ++current) { paths->push_back(current->path); } return true; } bool FindNewestMatchingFile(const base::FilePath& root, const std::string& pattern, base::FileEnumerator::FileType type, base::FilePath* path) { std::vector paths; if (FindMatchingFiles(root, pattern, type, &paths)) { *path = paths[0]; return true; } return false; } } // namespace namespace installer_test { InstallerPathProvider::InstallerPathProvider() { base::FilePath full_installer, previous_installer; if (!GetFullInstaller(&full_installer) || !GetPreviousInstaller(&previous_installer)) return; current_build_ = full_installer.DirName().DirName().BaseName().MaybeAsASCII(); previous_build_ = previous_installer.DirName().DirName().BaseName().MaybeAsASCII(); } InstallerPathProvider::InstallerPathProvider( const std::string& build_under_test) : current_build_(build_under_test) { base::FilePath full_installer, previous_installer; if (!GetFullInstaller(&full_installer) || !GetPreviousInstaller(&previous_installer)) return; previous_build_ = previous_installer.DirName().DirName().BaseName().MaybeAsASCII(); } InstallerPathProvider::~InstallerPathProvider() {} bool InstallerPathProvider::GetFullInstaller(base::FilePath* path) { std::string full_installer_pattern("*_chrome_installer*"); return GetInstaller(full_installer_pattern, path); } bool InstallerPathProvider::GetDiffInstaller(base::FilePath* path) { std::string diff_installer_pattern("*_from_*"); return GetInstaller(diff_installer_pattern, path); } bool InstallerPathProvider::GetMiniInstaller(base::FilePath* path) { // Use local copy of installer, else fall back to filer. base::FilePath mini_installer = PathFromExeDir( mini_installer_constants::kChromeMiniInstallerExecutable); if (base::PathExists(mini_installer)) { *path = mini_installer; return true; } std::string mini_installer_pattern("mini_installer.exe"); return GetInstaller(mini_installer_pattern, path); } bool InstallerPathProvider::GetPreviousInstaller(base::FilePath* path) { std::string diff_installer_pattern("*_from_*"); std::string full_installer_pattern("*_chrome_installer*"); base::FilePath diff_installer; if (!GetInstaller(diff_installer_pattern, &diff_installer)) return false; base::FilePath previous_installer; std::vector tokenized_name; Tokenize(diff_installer.BaseName().MaybeAsASCII(), "_", &tokenized_name); std::string build_pattern = base::StringPrintf( "*%s", tokenized_name[2].c_str()); std::vector previous_build; if (FindMatchingFiles(diff_installer.DirName().DirName().DirName(), build_pattern, base::FileEnumerator::DIRECTORIES, &previous_build)) { base::FilePath windir = previous_build.at(0).Append( mini_installer_constants::kWinFolder); FindNewestMatchingFile(windir, full_installer_pattern, base::FileEnumerator::FILES, &previous_installer); } if (previous_installer.empty()) return false; *path = previous_installer; return true; } bool InstallerPathProvider::GetStandaloneInstaller(base::FilePath* path) { // Get standalone installer. base::FilePath standalone_installer( mini_installer_constants::kChromeStandAloneInstallerLocation); // Get the file name. std::vector tokenized_build_number; if (current_build_.empty()) return false; Tokenize(current_build_, ".", &tokenized_build_number); std::string standalone_installer_filename = base::StringPrintf( "%s%s_%s.exe", base::FilePath(mini_installer_constants::kUntaggedInstallerPattern) .MaybeAsASCII().c_str(), tokenized_build_number[2].c_str(), tokenized_build_number[3].c_str()); standalone_installer = standalone_installer.AppendASCII(current_build_) .Append(mini_installer_constants::kWinFolder) .AppendASCII(standalone_installer_filename); *path = standalone_installer; return base::PathExists(standalone_installer); } bool InstallerPathProvider::GetSignedStandaloneInstaller(base::FilePath* path) { base::FilePath standalone_installer; if (!GetStandaloneInstaller(&standalone_installer)) return false; base::FilePath tagged_installer = PathFromExeDir( mini_installer_constants::kStandaloneInstaller); CommandLine sign_command = CommandLine::FromString( base::StringPrintf(L"%ls %ls %ls %ls", mini_installer_constants::kChromeApplyTagExe, standalone_installer.value().c_str(), tagged_installer.value().c_str(), mini_installer_constants::kChromeApplyTagParameters)); if (!installer_test::RunAndWaitForCommandToFinish(sign_command)) return false; *path = PathFromExeDir(mini_installer_constants::kStandaloneInstaller); return true; } base::FilePath InstallerPathProvider::PathFromExeDir( const base::FilePath::StringType& name) { base::FilePath path; PathService::Get(base::DIR_EXE, &path); path = path.Append(name); return path; } bool InstallerPathProvider::GetInstaller(const std::string& pattern, base::FilePath* path) { base::FilePath installer; // Search filer for installer binary. base::FilePath root(mini_installer_constants::kChromeInstallersLocation); std::vector paths; if (!FindMatchingFiles(root, current_build_, base::FileEnumerator::DIRECTORIES, &paths)) { return false; } std::vector::const_iterator dir; for (dir = paths.begin(); dir != paths.end(); ++dir) { base::FilePath windir = dir->Append( mini_installer_constants::kWinFolder); if (FindNewestMatchingFile(windir, pattern, base::FileEnumerator::FILES, &installer)) { break; } } if (installer.empty()) { LOG(WARNING) << "Failed to find installer with pattern: " << pattern; return false; } *path = installer; return true; } std::string InstallerPathProvider::GetCurrentBuild() { return current_build_; } std::string InstallerPathProvider::GetPreviousBuild() { return previous_build_; } } // namespace