blob: acf4308444becffcac0f5f2649c04bd1928a522b [file] [log] [blame]
// 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/chromedriver/chrome/chrome_finder.h"
#include <stddef.h>
#include <string>
#include <vector>
#include "base/base_paths.h"
#include "base/bind.h"
#include "base/callback.h"
#include "base/environment.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/path_service.h"
#include "base/stl_util.h"
#include "base/strings/string_split.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#if defined(OS_WIN)
#include "base/base_paths_win.h"
#include "base/win/windows_version.h"
#endif
namespace {
#if defined(OS_WIN)
void GetApplicationDirs(std::vector<base::FilePath>* locations) {
std::vector<base::FilePath> installation_locations;
base::FilePath local_app_data, program_files, program_files_x86;
if (base::PathService::Get(base::DIR_LOCAL_APP_DATA, &local_app_data))
installation_locations.push_back(local_app_data);
if (base::PathService::Get(base::DIR_PROGRAM_FILES, &program_files))
installation_locations.push_back(program_files);
if (base::PathService::Get(base::DIR_PROGRAM_FILESX86, &program_files_x86))
installation_locations.push_back(program_files_x86);
for (size_t i = 0; i < installation_locations.size(); ++i) {
locations->push_back(
installation_locations[i].Append(L"Google\\Chrome\\Application"));
}
for (size_t i = 0; i < installation_locations.size(); ++i) {
locations->push_back(
installation_locations[i].Append(L"Chromium\\Application"));
}
}
#elif defined(OS_LINUX)
void GetApplicationDirs(std::vector<base::FilePath>* locations) {
// TODO: Respect users' PATH variables.
// Until then, we use an approximation of the most common defaults.
locations->push_back(base::FilePath("/usr/local/sbin"));
locations->push_back(base::FilePath("/usr/local/bin"));
locations->push_back(base::FilePath("/usr/sbin"));
locations->push_back(base::FilePath("/usr/bin"));
locations->push_back(base::FilePath("/sbin"));
locations->push_back(base::FilePath("/bin"));
// Lastly, try the default installation location.
locations->push_back(base::FilePath("/opt/google/chrome"));
}
#elif defined(OS_ANDROID)
void GetApplicationDirs(std::vector<base::FilePath>* locations) {
// On Android we won't be able to find Chrome executable
}
#endif
void GetPathsFromEnvironment(std::vector<base::FilePath>* paths) {
base::FilePath::StringType delimiter;
base::FilePath::StringType commonPath;
std::string path;
std::unique_ptr<base::Environment> env(base::Environment::Create());
if (!env->GetVar("PATH", &path)) {
return;
}
#if defined(OS_WIN)
commonPath = base::UTF8ToWide(path);
delimiter = L";";
#else
commonPath = path;
delimiter = ":";
#endif
std::vector<base::FilePath::StringType> path_entries = base::SplitString(
commonPath, delimiter, base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
for (auto& path_entry : path_entries) {
#if defined(OS_WIN)
size_t size = path_entry.size();
if (size >= 2 && path_entry[0] == '"' && path_entry[size - 1] == '"') {
path_entry.erase(0, 1);
path_entry.erase(size - 2, 1);
}
#endif
if (path_entry.size() > 0)
paths->emplace_back(path_entry);
}
}
} // namespace
namespace internal {
bool FindExe(
const base::Callback<bool(const base::FilePath&)>& exists_func,
const std::vector<base::FilePath>& rel_paths,
const std::vector<base::FilePath>& locations,
base::FilePath* out_path) {
for (size_t i = 0; i < rel_paths.size(); ++i) {
for (size_t j = 0; j < locations.size(); ++j) {
base::FilePath path = locations[j].Append(rel_paths[i]);
if (exists_func.Run(path)) {
*out_path = path;
return true;
}
}
}
return false;
}
} // namespace internal
#if defined(OS_MACOSX)
void GetApplicationDirs(std::vector<base::FilePath>* locations);
#endif
bool FindChrome(base::FilePath* browser_exe) {
base::FilePath browser_exes_array[] = {
#if defined(OS_WIN)
base::FilePath(L"chrome.exe")
#elif defined(OS_MACOSX)
base::FilePath("Google Chrome.app/Contents/MacOS/Google Chrome"),
base::FilePath("Chromium.app/Contents/MacOS/Chromium")
#elif defined(OS_LINUX)
base::FilePath("google-chrome"),
base::FilePath("chrome"),
base::FilePath("chromium"),
base::FilePath("chromium-browser")
#else
// it will compile but won't work on other OSes
base::FilePath()
#endif
};
std::vector<base::FilePath> browser_exes(
browser_exes_array, browser_exes_array + base::size(browser_exes_array));
base::FilePath module_dir;
if (base::PathService::Get(base::DIR_MODULE, &module_dir)) {
for (size_t i = 0; i < browser_exes.size(); ++i) {
base::FilePath path = module_dir.Append(browser_exes[i]);
if (base::PathExists(path)) {
*browser_exe = path;
return true;
}
}
}
std::vector<base::FilePath> locations;
GetApplicationDirs(&locations);
GetPathsFromEnvironment(&locations);
return internal::FindExe(
base::Bind(&base::PathExists),
browser_exes,
locations,
browser_exe);
}