From 2531b852ff0085a9ed95f3fe1d60808e98f0ade7 Mon Sep 17 00:00:00 2001 From: Bertrand SIMONNET Date: Wed, 26 Aug 2015 16:31:56 -0700 Subject: libchromeos: remove libchromeos-ui. libchromeos-ui is moving back to src/platform2 as it is only used on chromeos. BUG=chromium:525211 TEST=manual: `emerge-gizmo libchromeos` does not install libchromeos-ui. TEST=trybots. Change-Id: Id16af4b9f4aa090ef2c9805f6e963773bd62a881 --- chromeos/ui/OWNERS | 3 - chromeos/ui/chromium_command_builder.cc | 504 ----------------------- chromeos/ui/chromium_command_builder.h | 183 -------- chromeos/ui/chromium_command_builder_unittest.cc | 351 ---------------- chromeos/ui/util.cc | 89 ---- chromeos/ui/util.h | 47 --- chromeos/ui/x_server_runner.cc | 317 -------------- chromeos/ui/x_server_runner.h | 87 ---- chromeos/ui/x_server_runner_unittest.cc | 207 ---------- libchromeos.gypi | 22 - 10 files changed, 1810 deletions(-) delete mode 100644 chromeos/ui/OWNERS delete mode 100644 chromeos/ui/chromium_command_builder.cc delete mode 100644 chromeos/ui/chromium_command_builder.h delete mode 100644 chromeos/ui/chromium_command_builder_unittest.cc delete mode 100644 chromeos/ui/util.cc delete mode 100644 chromeos/ui/util.h delete mode 100644 chromeos/ui/x_server_runner.cc delete mode 100644 chromeos/ui/x_server_runner.h delete mode 100644 chromeos/ui/x_server_runner_unittest.cc diff --git a/chromeos/ui/OWNERS b/chromeos/ui/OWNERS deleted file mode 100644 index 994075a..0000000 --- a/chromeos/ui/OWNERS +++ /dev/null @@ -1,3 +0,0 @@ -set noparent -derat@chromium.org -vapier@chromium.org diff --git a/chromeos/ui/chromium_command_builder.cc b/chromeos/ui/chromium_command_builder.cc deleted file mode 100644 index 9b4b620..0000000 --- a/chromeos/ui/chromium_command_builder.cc +++ /dev/null @@ -1,504 +0,0 @@ -// Copyright 2014 The Chromium OS 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 "chromeos/ui/chromium_command_builder.h" - -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "chromeos/ui/util.h" - -namespace chromeos { -namespace ui { - -namespace { - -// Prefix for the USE flag containing the name of the board. -const char kBoardUseFlagPrefix[] = "board_use_"; - -// Location where GPU debug information is bind-mounted. -const char kDebugfsGpuPath[] = "/var/run/debugfs_gpu"; - -// Returns the value associated with |key| in |pairs| or an empty string if the -// key isn't present. If the value is encapsulated in single or double quotes, -// they are removed. -std::string LookUpInStringPairs(const base::StringPairs& pairs, - const std::string& key) { - for (size_t i = 0; i < pairs.size(); ++i) { - if (key != pairs[i].first) - continue; - - // Strip quotes. - // TODO(derat): Remove quotes from Pepper .info files after - // session_manager_setup.sh is no longer interpreting them as shell scripts. - std::string value = pairs[i].second; - if (value.size() >= 2U && - ((value[0] == '"' && value[value.size()-1] == '"') || - (value[0] == '\'' && value[value.size()-1] == '\''))) - value = value.substr(1, value.size() - 2); - - return value; - } - return std::string(); -} - -// Returns true if |name| matches /^[A-Z][_A-Z0-9]+$/. -bool IsEnvironmentVariableName(const std::string& name) { - if (name.empty() || !(name[0] >= 'A' && name[0] <= 'Z')) - return false; - for (size_t i = 1; i < name.size(); ++i) { - char ch = name[i]; - if (ch != '_' && !(ch >= '0' && ch <= '9') && !(ch >= 'A' && ch <= 'Z')) - return false; - } - return true; -} - -} // namespace - -const char ChromiumCommandBuilder::kUser[] = "chronos"; -const char ChromiumCommandBuilder::kUseFlagsPath[] = "/etc/ui_use_flags.txt"; -const char ChromiumCommandBuilder::kLsbReleasePath[] = "/etc/lsb-release"; -const char ChromiumCommandBuilder::kTimeZonePath[] = - "/var/lib/timezone/localtime"; -const char ChromiumCommandBuilder::kDefaultZoneinfoPath[] = - "/usr/share/zoneinfo/US/Pacific"; -const char ChromiumCommandBuilder::kPepperPluginsPath[] = - "/opt/google/chrome/pepper"; -const char ChromiumCommandBuilder::kDeepMemoryProfilerPrefixPath[] = - "/var/tmp/deep_memory_profiler_prefix.txt"; -const char ChromiumCommandBuilder::kDeepMemoryProfilerTimeIntervalPath[] = - "/var/tmp/deep_memory_profiler_time_interval.txt"; - -ChromiumCommandBuilder::ChromiumCommandBuilder() - : uid_(0), - gid_(0), - is_chrome_os_hardware_(false), - is_developer_end_user_(false), - vmodule_argument_index_(-1) { -} - -ChromiumCommandBuilder::~ChromiumCommandBuilder() {} - -bool ChromiumCommandBuilder::Init() { - if (!userdb::GetUserInfo(kUser, &uid_, &gid_)) - return false; - - // Read the list of USE flags that were set at build time. - std::string data; - if (!base::ReadFileToString(GetPath(kUseFlagsPath), &data)) { - PLOG(ERROR) << "Unable to read " << kUseFlagsPath; - return false; - } - std::vector lines; - base::SplitString(data, '\n', &lines); - for (size_t i = 0; i < lines.size(); ++i) { - if (!lines[i].empty() && lines[i][0] != '#') - use_flags_.insert(lines[i]); - } - - base::CommandLine cl(base::FilePath("crossystem")); - cl.AppendArg("mainfw_type"); - std::string output; - if (base::GetAppOutput(cl, &output)) { - base::TrimWhitespace(output, base::TRIM_TRAILING, &output); - is_chrome_os_hardware_ = (output != "nonchrome"); - } - - is_developer_end_user_ = base::GetAppOutput( - base::CommandLine(base::FilePath("is_developer_end_user")), &output); - - return true; -} - -bool ChromiumCommandBuilder::SetUpChromium(const base::FilePath& xauth_path) { - AddEnvVar("USER", kUser); - AddEnvVar("LOGNAME", kUser); - AddEnvVar("SHELL", "/bin/sh"); - AddEnvVar("PATH", "/bin:/usr/bin"); - AddEnvVar("LC_ALL", "en_US.utf8"); - - const base::FilePath data_dir(GetPath("/home").Append(kUser)); - AddEnvVar("DATA_DIR", data_dir.value()); - if (!util::EnsureDirectoryExists(data_dir, uid_, gid_, 0755)) - return false; - - // Provide /etc/lsb-release contents and timestamp so that they are available - // to Chrome immediately without requiring a blocking file read. - const base::FilePath lsb_path(GetPath(kLsbReleasePath)); - std::string lsb_data; - base::File::Info info; - if (!base::ReadFileToString(lsb_path, &lsb_data) || - !base::GetFileInfo(lsb_path, &info)) { - LOG(ERROR) << "Unable to read or stat " << kLsbReleasePath; - return false; - } - AddEnvVar("LSB_RELEASE", lsb_data); - AddEnvVar("LSB_RELEASE_TIME", - base::IntToString(info.creation_time.ToTimeT())); - - // By default, libdbus treats all warnings as fatal errors. That's too strict. - AddEnvVar("DBUS_FATAL_WARNINGS", "0"); - - // Prevent Flash asserts from crashing the plugin process. - AddEnvVar("DONT_CRASH_ON_ASSERT", "1"); - - // Create the target for the /etc/localtime symlink. This allows the Chromium - // process to change the time zone. - const base::FilePath time_zone_symlink(GetPath(kTimeZonePath)); - // TODO(derat): Move this back into the !base::PathExists() block in M39 or - // later, after http://crbug.com/390188 has had time to be cleaned up. - CHECK(util::EnsureDirectoryExists( - time_zone_symlink.DirName(), uid_, gid_, 0755)); - if (!base::PathExists(time_zone_symlink)) { - // base::PathExists() dereferences symlinks, so make sure that there's not a - // dangling symlink there before we create a new link. - base::DeleteFile(time_zone_symlink, false); - PCHECK(base::CreateSymbolicLink( - base::FilePath(kDefaultZoneinfoPath), time_zone_symlink)); - } - - // Increase maximum file descriptors to 2048 (default is otherwise 1024). - // Some offline websites using IndexedDB are particularly hungry for - // descriptors, so the default is insufficient. See crbug.com/251385. - struct rlimit limit; - limit.rlim_cur = limit.rlim_max = 2048; - if (setrlimit(RLIMIT_NOFILE, &limit) < 0) - PLOG(ERROR) << "Setting max FDs with setrlimit() failed"; - - if (!xauth_path.empty() && !SetUpX11(xauth_path)) - return false; - - // Disable sandboxing as it causes crashes in ASAN: crbug.com/127536 - bool disable_sandbox = false; - disable_sandbox |= SetUpASAN(); - disable_sandbox |= SetUpDeepMemoryProfiler(); - if (disable_sandbox) - AddArg("--no-sandbox"); - - SetUpPepperPlugins(); - AddUiFlags(); - - AddArg("--enable-logging"); - AddArg("--log-level=1"); - AddArg("--use-cras"); - - return true; -} - -void ChromiumCommandBuilder::EnableCoreDumps() { - if (!util::EnsureDirectoryExists( - base::FilePath("/var/coredumps"), uid_, gid_, 0700)) - return; - - struct rlimit limit = { RLIM_INFINITY, RLIM_INFINITY }; - if (setrlimit(RLIMIT_CORE, &limit) != 0) - PLOG(ERROR) << "Setting unlimited coredumps with setrlimit() failed"; - const std::string kPattern("/var/coredumps/core.%e.%p"); - base::WriteFile(base::FilePath("/proc/sys/kernel/core_pattern"), - kPattern.c_str(), kPattern.size()); -} - -bool ChromiumCommandBuilder::ApplyUserConfig(const base::FilePath& path) { - std::string data; - if (!base::ReadFileToString(path, &data)) { - PLOG(WARNING) << "Unable to read " << path.value(); - return false; - } - - std::vector lines; - base::SplitString(data, '\n', &lines); - - for (size_t i = 0; i < lines.size(); ++i) { - std::string line; - base::TrimWhitespace(lines[i], base::TRIM_ALL, &line); - if (line.empty() || line[0] == '#') - continue; - - if (line[0] == '!' && line.size() > 1) { - const std::string pattern = line.substr(1, line.size() - 1); - size_t num_copied = 0; - for (size_t src_index = 0; src_index < arguments_.size(); ++src_index) { - if (arguments_[src_index].find(pattern) == 0) { - // Drop the argument and shift |vmodule_argument_index_| forward if - // the argument precedes it (or reset the index if the --vmodule flag - // itself is being deleted). - if (vmodule_argument_index_ > static_cast(src_index)) - vmodule_argument_index_--; - else if (vmodule_argument_index_ == static_cast(src_index)) - vmodule_argument_index_ = -1; - } else { - arguments_[num_copied] = arguments_[src_index]; - num_copied++; - } - } - arguments_.resize(num_copied); - } else { - base::StringPairs pairs; - base::SplitStringIntoKeyValuePairs(line, '=', '\n', &pairs); - if (pairs.size() == 1U && pairs[0].first == "vmodule") - AddVmodulePattern(pairs[0].second); - else if (pairs.size() == 1U && IsEnvironmentVariableName(pairs[0].first)) - AddEnvVar(pairs[0].first, pairs[0].second); - else - AddArg(line); - } - } - - return true; -} - -bool ChromiumCommandBuilder::UseFlagIsSet(const std::string& flag) const { - return use_flags_.count(flag) > 0; -} - -bool ChromiumCommandBuilder::IsBoard(const std::string& board) const { - return UseFlagIsSet(kBoardUseFlagPrefix + board); -} - -void ChromiumCommandBuilder::AddEnvVar(const std::string& name, - const std::string& value) { - environment_variables_[name] = value; -} - -std::string ChromiumCommandBuilder::ReadEnvVar(const std::string& name) const { - StringMap::const_iterator it = environment_variables_.find(name); - CHECK(it != environment_variables_.end()) << name << " hasn't been set"; - return it->second; -} - -void ChromiumCommandBuilder::AddArg(const std::string& arg) { - arguments_.push_back(arg); -} - -void ChromiumCommandBuilder::AddVmodulePattern(const std::string& pattern) { - if (pattern.empty()) - return; - - if (vmodule_argument_index_ < 0) { - AddArg("--vmodule=" + pattern); - vmodule_argument_index_ = arguments_.size() - 1; - } else { - arguments_[vmodule_argument_index_] += "," + pattern; - } -} - -base::FilePath ChromiumCommandBuilder::GetPath(const std::string& path) const { - return util::GetReparentedPath(path, base_path_for_testing_); -} - -bool ChromiumCommandBuilder::SetUpX11(const base::FilePath& xauth_file) { - const base::FilePath user_xauth_file( - base::FilePath(ReadEnvVar("DATA_DIR")).Append(".Xauthority")); - if (!base::CopyFile(xauth_file, user_xauth_file)) { - PLOG(ERROR) << "Unable to copy " << xauth_file.value() << " to " - << user_xauth_file.value(); - return false; - } - if (!util::SetPermissions(user_xauth_file, uid_, gid_, 0600)) - return false; - - AddEnvVar("XAUTHORITY", user_xauth_file.value()); - AddEnvVar("DISPLAY", ":0.0"); - return true; -} - -bool ChromiumCommandBuilder::SetUpASAN() { - if (!UseFlagIsSet("asan")) - return false; - - // Make glib use system malloc. - AddEnvVar("G_SLICE", "always-malloc"); - - // Make nss use system malloc. - AddEnvVar("NSS_DISABLE_ARENA_FREE_LIST", "1"); - - // Make nss skip dlclosing dynamically loaded modules, which would result in - // "obj:*" in backtraces. - AddEnvVar("NSS_DISABLE_UNLOAD", "1"); - - // Make ASAN output to the file because Chrome stderr is /dev/null now - // (crbug.com/156308). - // TODO(derat): It's weird that this lives in a Chrome directory that's - // created by ChromeInitializer; move it somewhere else, maybe. - AddEnvVar("ASAN_OPTIONS", "log_path=/var/log/chrome/asan_log"); - - return true; -} - -bool ChromiumCommandBuilder::SetUpDeepMemoryProfiler() { - if (!UseFlagIsSet("deep_memory_profiler")) - return false; - - // Dump heap profiles to /tmp/dmprof.*. - std::string prefix; - if (!base::ReadFileToString( - GetPath(kDeepMemoryProfilerPrefixPath), &prefix)) { - return false; - } - base::TrimWhitespaceASCII(prefix, base::TRIM_TRAILING, &prefix); - AddEnvVar("HEAPPROFILE", prefix); - - // Dump every |interval| seconds. - std::string interval; - base::ReadFileToString( - GetPath(kDeepMemoryProfilerTimeIntervalPath), &interval); - base::TrimWhitespaceASCII(interval, base::TRIM_TRAILING, &interval); - AddEnvVar("HEAP_PROFILE_TIME_INTERVAL", interval); - - // Turn on profiling mmap. - AddEnvVar("HEAP_PROFILE_MMAP", "1"); - - // Turn on Deep Memory Profiler. - AddEnvVar("DEEP_HEAP_PROFILE", "1"); - - return true; -} - -void ChromiumCommandBuilder::SetUpPepperPlugins() { - std::vector register_plugins; - - base::FileEnumerator enumerator(GetPath(kPepperPluginsPath), - false /* recursive */, base::FileEnumerator::FILES); - while (true) { - const base::FilePath path = enumerator.Next(); - if (path.empty()) - break; - - if (path.Extension() != ".info") - continue; - - std::string data; - if (!base::ReadFileToString(path, &data)) { - PLOG(ERROR) << "Unable to read " << path.value(); - continue; - } - - // .info files are full of shell junk like #-prefixed comments, so don't - // check that SplitStringIntoKeyValuePairs() successfully parses every line. - base::StringPairs pairs; - base::SplitStringIntoKeyValuePairs(data, '=', '\n', &pairs); - - const std::string file_name = LookUpInStringPairs(pairs, "FILE_NAME"); - const std::string plugin_name = LookUpInStringPairs(pairs, "PLUGIN_NAME"); - const std::string version = LookUpInStringPairs(pairs, "VERSION"); - - if (file_name.empty()) { - LOG(ERROR) << "Missing FILE_NAME in " << path.value(); - continue; - } - - if (plugin_name == "Shockwave Flash") { - AddArg("--ppapi-flash-path=" + file_name); - AddArg("--ppapi-flash-version=" + version); - // TODO(ihf): Remove once crbug.com/441782 is fixed. - const bool is_atom = IsBoard("x86-alex") || IsBoard("x86-alex_he") || - IsBoard("x86-mario") || IsBoard("x86-zgb") || IsBoard("x86-zgb_he"); - if (is_atom) { - AddArg("--ppapi-flash-args=enable_hw_video_decode=1" - ",enable_low_latency_audio=0"); - } else { - AddArg("--ppapi-flash-args=enable_hw_video_decode=1"); - } - } else { - const std::string description = LookUpInStringPairs(pairs, "DESCRIPTION"); - const std::string mime_types = LookUpInStringPairs(pairs, "MIME_TYPES"); - - std::string plugin_string = file_name; - if (!plugin_name.empty()) { - plugin_string += "#" + plugin_name; - if (!description.empty()) { - plugin_string += "#" + description; - if (!version.empty()) { - plugin_string += "#" + version; - } - } - } - plugin_string += ";" + mime_types; - register_plugins.push_back(plugin_string); - } - } - - if (!register_plugins.empty()) { - std::sort(register_plugins.begin(), register_plugins.end()); - AddArg("--register-pepper-plugins=" + JoinString(register_plugins, ",")); - } -} - -void ChromiumCommandBuilder::AddUiFlags() { - AddArg("--enable-fixed-position-compositing"); - AddArg("--enable-impl-side-painting"); - AddArg("--max-tiles-for-interest-area=512"); - AddArg("--ui-enable-per-tile-painting"); - AddArg("--ui-prioritize-in-gpu-process"); - - if (UseFlagIsSet("opengles")) - AddArg("--use-gl=egl"); - - // On boards with ARM NEON support, force libvpx to use the NEON-optimized - // code paths. Remove once http://crbug.com/161834 is fixed. - // This is needed because libvpx cannot check cpuinfo within the sandbox. - if (UseFlagIsSet("neon")) - AddEnvVar("VPX_SIMD_CAPS", "0xf"); - - if (IsBoard("link") || IsBoard("link_freon")) { - AddArg("--touch-calibration=0,0,0,50"); - AddArg("--touch-noise-filtering"); - } - - // TODO(hshi): Fix GPU hang on sandybridge (crbug.com/521249). - if (IsBoard("lumpy") || IsBoard("stumpy") || IsBoard("parrot") || IsBoard("butterfly")) - AddArg("--disable-accelerated-video-decode"); - - AddArg(std::string("--gpu-sandbox-failures-fatal=") + - (is_chrome_os_hardware() ? "yes" : "no")); - - if (UseFlagIsSet("gpu_sandbox_allow_sysv_shm")) - AddArg("--gpu-sandbox-allow-sysv-shm"); - - if (UseFlagIsSet("gpu_sandbox_start_early")) - AddArg("--gpu-sandbox-start-early"); - - // Ozone platform configuration. - if (UseFlagIsSet("ozone_platform_gbm")) { - AddArg("--ozone-platform=gbm"); - AddArg("--ozone-use-surfaceless"); - } else if (UseFlagIsSet("ozone_platform_drm")) { - AddArg("--ozone-platform=drm"); - - // TODO(spang): Fix hardware acceleration. - AddArg("--disable-gpu"); - AddArg("--ui-disable-threaded-compositing"); - } - - // Allow Chrome to access GPU memory information despite /sys/kernel/debug - // being owned by debugd. This limits the security attack surface versus - // leaving the whole debug directory world-readable: http://crbug.com/175828 - // (Only do this if we're running as root, i.e. not in a test.) - const base::FilePath debugfs_gpu_path(GetPath(kDebugfsGpuPath)); - if (getuid() == 0 && !base::DirectoryExists(debugfs_gpu_path)) { - if (base::CreateDirectory(debugfs_gpu_path)) { - util::Run("mount", "-o", "bind", "/sys/kernel/debug/dri/0", - kDebugfsGpuPath, nullptr); - } else { - PLOG(ERROR) << "Unable to create " << kDebugfsGpuPath; - } - } -} - -} // namespace ui -} // namespace chromeos diff --git a/chromeos/ui/chromium_command_builder.h b/chromeos/ui/chromium_command_builder.h deleted file mode 100644 index f29fbcd..0000000 --- a/chromeos/ui/chromium_command_builder.h +++ /dev/null @@ -1,183 +0,0 @@ -// Copyright 2014 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef LIBCHROMEOS_CHROMEOS_UI_CHROMIUM_COMMAND_BUILDER_H_ -#define LIBCHROMEOS_CHROMEOS_UI_CHROMIUM_COMMAND_BUILDER_H_ - -#include - -#include -#include -#include -#include - -#include -#include - -namespace chromeos { -namespace ui { - -// ChromiumCommandBuilder facilitates building a command line for running a -// Chromium-derived binary and performing related setup. -class ChromiumCommandBuilder { - public: - typedef std::map StringMap; - typedef std::vector StringVector; - - // Name of user account used to run the binary. - static const char kUser[]; - - // Location of the file containing newline-separated USE flags that were set - // when the system was built. - static const char kUseFlagsPath[]; - - // Location of the file containing .info files describing Pepper plugins. - static const char kPepperPluginsPath[]; - - // Location of the lsb-release file describing the system image. - static const char kLsbReleasePath[]; - - // Location of the user-writable target of the /etc/localtime symlink. - static const char kTimeZonePath[]; - - // Default zoneinfo file used if the time zone hasn't been explicitly set. - static const char kDefaultZoneinfoPath[]; - - // Deep-memory-profiler-related files. - static const char kDeepMemoryProfilerPrefixPath[]; - static const char kDeepMemoryProfilerTimeIntervalPath[]; - - ChromiumCommandBuilder(); - ~ChromiumCommandBuilder(); - - uid_t uid() const { return uid_; } - gid_t gid() const { return gid_; } - bool is_chrome_os_hardware() const { return is_chrome_os_hardware_; } - bool is_developer_end_user() const { return is_developer_end_user_; } - const StringMap& environment_variables() const { - return environment_variables_; - } - const StringVector& arguments() const { return arguments_; } - - void set_base_path_for_testing(const base::FilePath& path) { - base_path_for_testing_ = path; - } - - // Performs just the basic initialization needed before UseFlagIsSet() and - // IsBoard() can be used. Returns true on success. - bool Init(); - - // Determines the environment variables and arguments that should be set for - // all Chromium-derived binaries and updates |environment_variables_| and - // |arguments_| accordingly. Also creates necessary directories, sets resource - // limits, etc. - // - // If |xauth_path| is non-empty, Chromium will be configured to connect to an - // X server at :0. The authority file will be copied to a |uid_|-owned file - // within the data dir. - // - // Returns true on success. - bool SetUpChromium(const base::FilePath& xauth_path); - - // Configures the environment so a core dump will be written when the binary - // crashes. - void EnableCoreDumps(); - - // Reads a user-supplied file requesting modifications to the current set of - // arguments. The following directives are supported: - // - // # This is a comment. - // Lines beginning with '#' are skipped. - // - // --some-flag=some-value - // Calls AddArg("--some-flag=some-value"). - // - // !--flag-prefix - // Remove all arguments beginning with "--flag-prefix". - // - // NAME=VALUE - // Calls AddEnvVar("NAME", "VALUE"). - // - // Returns true on success. - bool ApplyUserConfig(const base::FilePath& path); - - // Returns true if a USE flag named |flag| was set when the system image was - // built. - bool UseFlagIsSet(const std::string& flag) const; - - // Returns true if the system image was compiled for |board|. - bool IsBoard(const std::string& board) const; - - // Adds an environment variable to |environment_variables_|. Note that this - // method does not call setenv(); it is the caller's responsibility to - // actually export the variables. - void AddEnvVar(const std::string& name, const std::string& value); - - // Returns the value of an environment variable previously added via - // AddEnvVar(). Crashes if the variable isn't set. Note that this method does - // not call getenv(). - std::string ReadEnvVar(const std::string& name) const; - - // Adds a command-line argument. - void AddArg(const std::string& arg); - - // Adds |pattern| to the --vmodule flag in |arguments_|. - void AddVmodulePattern(const std::string& pattern); - - private: - // Converts absolute path |path| into a base::FilePath, rooting it under - // |base_path_for_testing_| if it's non-empty. - base::FilePath GetPath(const std::string& path) const; - - // Performs X11-specific setup and returns true on success. Called by - // InitChromium(). - bool SetUpX11(const base::FilePath& xauth_path); - - // Checks if an ASAN or deep-memory-profiler build was requested, doing - // appropriate initialization and returning true if so. Called by - // InitChromium(). - bool SetUpASAN(); - bool SetUpDeepMemoryProfiler(); - - // Reads .info files in |pepper_plugins_path_| and adds the appropriate - // arguments to |arguments_|. Called by InitChromium(). - void SetUpPepperPlugins(); - - // Add UI- and compositing-related flags to |arguments_|. - void AddUiFlags(); - - // Path under which files are created when running in a test. - base::FilePath base_path_for_testing_; - - // UID and GID of the user used to run the binary. - uid_t uid_; - gid_t gid_; - - // USE flags that were set when the system was built. - std::set use_flags_; - - // True if official Chrome OS hardware is being used. - bool is_chrome_os_hardware_; - - // True if this is a developer system, per the is_developer_end_user command. - bool is_developer_end_user_; - - // Environment variables that the caller should export before starting the - // executable. - StringMap environment_variables_; - - // Command-line arguments that the caller should pass to the executable. - StringVector arguments_; - - // Index in |arguments_| of the --vmodule flag. -1 if the flag hasn't been - // set. - int vmodule_argument_index_; - - DISALLOW_COPY_AND_ASSIGN(ChromiumCommandBuilder); -}; - -} // namespace ui -} // namespace chromeos - -#endif // LIBCHROMEOS_CHROMEOS_UI_CHROMIUM_COMMAND_BUILDER_H_ diff --git a/chromeos/ui/chromium_command_builder_unittest.cc b/chromeos/ui/chromium_command_builder_unittest.cc deleted file mode 100644 index 70fddd8..0000000 --- a/chromeos/ui/chromium_command_builder_unittest.cc +++ /dev/null @@ -1,351 +0,0 @@ -// Copyright 2014 The Chromium OS 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 "chromeos/ui/chromium_command_builder.h" - -#include -#include -#include -#include -#include - -#include "chromeos/ui/util.h" - -namespace chromeos { -namespace ui { - -class ChromiumCommandBuilderTest : public testing::Test { - public: - ChromiumCommandBuilderTest() - : write_use_flags_file_(true), - write_lsb_release_file_(true) { - PCHECK(temp_dir_.CreateUniqueTempDir()); - base_path_ = temp_dir_.path(); - builder_.set_base_path_for_testing(base_path_); - - pepper_dir_ = util::GetReparentedPath( - ChromiumCommandBuilder::kPepperPluginsPath, base_path_); - PCHECK(base::CreateDirectory(pepper_dir_)); - } - virtual ~ChromiumCommandBuilderTest() {} - - - // Does testing-related initialization and returns the result of |builder_|'s - // Init() method. - bool Init() { - if (write_use_flags_file_) { - WriteFileUnderBasePath(ChromiumCommandBuilder::kUseFlagsPath, - use_flags_data_); - } - if (write_lsb_release_file_) { - WriteFileUnderBasePath(ChromiumCommandBuilder::kLsbReleasePath, - lsb_release_data_); - } - return builder_.Init(); - } - - // Writes |data| to |path| underneath |base_path_|. - void WriteFileUnderBasePath(const std::string& path, - const std::string& data) { - base::FilePath reparented_path(util::GetReparentedPath(path, base_path_)); - if (!base::DirectoryExists(reparented_path.DirName())) - PCHECK(base::CreateDirectory(reparented_path.DirName())); - PCHECK(base::WriteFile(reparented_path, data.data(), data.size()) == - static_cast(data.size())); - } - - // Looks up |name| in |builder_|'s list of environment variables, returning - // its value if present or an empty string otherwise. - std::string ReadEnvVar(const std::string& name) { - const ChromiumCommandBuilder::StringMap& vars = - builder_.environment_variables(); - ChromiumCommandBuilder::StringMap::const_iterator it = vars.find(name); - return it != vars.end() ? it->second : std::string(); - } - - // Returns the first argument in |builder_| that starts with |prefix|, or an - // empty string if no matching argument is found. - std::string GetFirstArgWithPrefix(const std::string& prefix) { - const ChromiumCommandBuilder::StringVector& args = builder_.arguments(); - for (size_t i = 0; i < args.size(); ++i) { - if (args[i].find(prefix) == 0) - return args[i]; - } - return std::string(); - } - - protected: - base::ScopedTempDir temp_dir_; - base::FilePath base_path_; - - bool write_use_flags_file_; - std::string use_flags_data_; - - bool write_lsb_release_file_; - std::string lsb_release_data_; - - base::FilePath pepper_dir_; - - ChromiumCommandBuilder builder_; - - private: - DISALLOW_COPY_AND_ASSIGN(ChromiumCommandBuilderTest); -}; - -TEST_F(ChromiumCommandBuilderTest, MissingUseFlagsFile) { - write_use_flags_file_ = false; - EXPECT_FALSE(Init()); -} - -TEST_F(ChromiumCommandBuilderTest, UseFlags) { - use_flags_data_ = "# Here's a comment.\nfoo\nbar\nboard_use_blah\n"; - ASSERT_TRUE(Init()); - - EXPECT_TRUE(builder_.UseFlagIsSet("foo")); - EXPECT_TRUE(builder_.UseFlagIsSet("bar")); - EXPECT_FALSE(builder_.UseFlagIsSet("food")); - EXPECT_FALSE(builder_.UseFlagIsSet("# Here's a comment.")); - EXPECT_FALSE(builder_.UseFlagIsSet("#")); - EXPECT_FALSE(builder_.UseFlagIsSet("a")); - - EXPECT_TRUE(builder_.IsBoard("blah")); - EXPECT_FALSE(builder_.IsBoard("foo")); - EXPECT_FALSE(builder_.IsBoard("blah1")); -} - -TEST_F(ChromiumCommandBuilderTest, MissingLsbReleaseFile) { - write_lsb_release_file_ = false; - ASSERT_TRUE(Init()); - EXPECT_FALSE(builder_.SetUpChromium(base::FilePath())); -} - -TEST_F(ChromiumCommandBuilderTest, LsbRelease) { - lsb_release_data_ = "abc\ndef"; - ASSERT_TRUE(Init()); - ASSERT_TRUE(builder_.SetUpChromium(base::FilePath())); - - EXPECT_EQ(lsb_release_data_, ReadEnvVar("LSB_RELEASE")); - EXPECT_FALSE(ReadEnvVar("LSB_RELEASE_TIME").empty()); -} - -TEST_F(ChromiumCommandBuilderTest, TimeZone) { - // Test that the builder creates a symlink for the time zone. - ASSERT_TRUE(Init()); - ASSERT_TRUE(builder_.SetUpChromium(base::FilePath())); - const base::FilePath kSymlink(util::GetReparentedPath( - ChromiumCommandBuilder::kTimeZonePath, base_path_)); - base::FilePath target; - ASSERT_TRUE(base::ReadSymbolicLink(kSymlink, &target)); - EXPECT_EQ(ChromiumCommandBuilder::kDefaultZoneinfoPath, target.value()); - - // Delete the old symlink and create a new one with a different target. - // Arbitrarily use |base_path_| (we need a path that exists). - ASSERT_TRUE(base::DeleteFile(kSymlink, false)); - const base::FilePath kNewTarget(base_path_); - ASSERT_TRUE(base::CreateSymbolicLink(kNewTarget, kSymlink)); - - // Initialize a second builder and check that it leaves the existing symlink - // alone. - ChromiumCommandBuilder second_builder; - second_builder.set_base_path_for_testing(base_path_); - ASSERT_TRUE(second_builder.Init()); - ASSERT_TRUE(second_builder.SetUpChromium(base::FilePath())); - ASSERT_TRUE(base::ReadSymbolicLink(kSymlink, &target)); - EXPECT_EQ(kNewTarget.value(), target.value()); -} - -TEST_F(ChromiumCommandBuilderTest, BasicEnvironment) { - ASSERT_TRUE(Init()); - ASSERT_TRUE(builder_.SetUpChromium(base::FilePath())); - - EXPECT_EQ("chronos", ReadEnvVar("USER")); - EXPECT_EQ("chronos", ReadEnvVar("LOGNAME")); - EXPECT_EQ("/bin/sh", ReadEnvVar("SHELL")); - EXPECT_FALSE(ReadEnvVar("PATH").empty()); - EXPECT_EQ("en_US.utf8", ReadEnvVar("LC_ALL")); - base::FilePath data_dir(util::GetReparentedPath("/home/chronos", base_path_)); - EXPECT_EQ(data_dir.value(), ReadEnvVar("DATA_DIR")); - EXPECT_TRUE(base::DirectoryExists(data_dir)); -} - -TEST_F(ChromiumCommandBuilderTest, VmoduleFlag) { - ASSERT_TRUE(Init()); - ASSERT_TRUE(builder_.SetUpChromium(base::FilePath())); - - const char kVmodulePrefix[] = "--vmodule="; - ASSERT_EQ("", GetFirstArgWithPrefix(kVmodulePrefix)); - builder_.AddVmodulePattern("foo=1"); - ASSERT_EQ("--vmodule=foo=1", GetFirstArgWithPrefix(kVmodulePrefix)); - builder_.AddVmodulePattern("bar=2"); - ASSERT_EQ("--vmodule=foo=1,bar=2", GetFirstArgWithPrefix(kVmodulePrefix)); - - // Add another argument and check that --vmodule still gets updated. - builder_.AddArg("--blah"); - builder_.AddVmodulePattern("baz=1"); - ASSERT_EQ("--vmodule=foo=1,bar=2,baz=1", - GetFirstArgWithPrefix(kVmodulePrefix)); -} - -TEST_F(ChromiumCommandBuilderTest, UserConfig) { - ASSERT_TRUE(Init()); - builder_.AddArg("--baz=4"); - builder_.AddArg("--blah-a"); - builder_.AddArg("--blah-b"); - - const char kConfig[] = - "# Here's a comment followed by a blank line and some whitespace.\n" - "\n" - " \n" - "--foo=1\n" - "--bar=2\n" - "FOO=3\n" - "BAR=4\n" - "!--bar\n" - "!--baz\n" - "--bar=3\n" - "!--blah\n"; - base::FilePath path(util::GetReparentedPath("/config.txt", base_path_)); - ASSERT_EQ(strlen(kConfig), base::WriteFile(path, kConfig, strlen(kConfig))); - - ASSERT_TRUE(builder_.ApplyUserConfig(path)); - ASSERT_EQ(2U, builder_.arguments().size()); - EXPECT_EQ("--foo=1", builder_.arguments()[0]); - EXPECT_EQ("--bar=3", builder_.arguments()[1]); - EXPECT_EQ("3", ReadEnvVar("FOO")); - EXPECT_EQ("4", ReadEnvVar("BAR")); -} - -TEST_F(ChromiumCommandBuilderTest, UserConfigVmodule) { - ASSERT_TRUE(Init()); - builder_.AddArg("--foo"); - builder_.AddVmodulePattern("a=2"); - builder_.AddArg("--bar"); - - // Check that we don't get confused when deleting flags surrounding the - // vmodule flag. - const char kConfig[] = "!--foo\n!--bar"; - base::FilePath path(util::GetReparentedPath("/config.txt", base_path_)); - ASSERT_EQ(strlen(kConfig), base::WriteFile(path, kConfig, strlen(kConfig))); - ASSERT_TRUE(builder_.ApplyUserConfig(path)); - builder_.AddVmodulePattern("b=1"); - ASSERT_EQ("--vmodule=a=2,b=1", GetFirstArgWithPrefix("--vmodule=")); - - // Delete the --vmodule flag. - const char kConfig2[] = "!--vmodule="; - ASSERT_EQ(strlen(kConfig2), - base::WriteFile(path, kConfig2, strlen(kConfig2))); - ASSERT_TRUE(builder_.ApplyUserConfig(path)); - EXPECT_TRUE(builder_.arguments().empty()); - - // Now add another vmodule pattern and check that the flag is re-added. - builder_.AddVmodulePattern("c=1"); - ASSERT_EQ("--vmodule=c=1", GetFirstArgWithPrefix("--vmodule=")); - - // Check that vmodule directives in config files are handled. - const char kConfig3[] = "vmodule=a=1\nvmodule=b=2"; - ASSERT_EQ(strlen(kConfig3), - base::WriteFile(path, kConfig3, strlen(kConfig3))); - ASSERT_TRUE(builder_.ApplyUserConfig(path)); - ASSERT_EQ("--vmodule=c=1,a=1,b=2", GetFirstArgWithPrefix("--vmodule=")); -} - -TEST_F(ChromiumCommandBuilderTest, PepperPlugins) { - const char kFlash[] = - "# Here's a comment.\n" - "FILE_NAME=/opt/google/chrome/pepper/flash.so\n" - "PLUGIN_NAME=\"Shockwave Flash\"\n" - "VERSION=1.2.3.4\n"; - ASSERT_EQ(strlen(kFlash), - base::WriteFile(pepper_dir_.Append("flash.info"), kFlash, - strlen(kFlash))); - - const char kNetflix[] = - "FILE_NAME=/opt/google/chrome/pepper/netflix.so\n" - "PLUGIN_NAME=\"Netflix\"\n" - "VERSION=2.0.0\n" - "DESCRIPTION=Helper for the Netflix application\n" - "MIME_TYPES=\"application/netflix\"\n"; - ASSERT_EQ(strlen(kNetflix), - base::WriteFile(pepper_dir_.Append("netflix.info"), kNetflix, - strlen(kNetflix))); - - const char kOther[] = - "PLUGIN_NAME=Some other plugin\n" - "FILE_NAME=/opt/google/chrome/pepper/other.so\n"; - ASSERT_EQ(strlen(kOther), - base::WriteFile(pepper_dir_.Append("other.info"), kOther, - strlen(kOther))); - - const char kMissingFileName[] = - "PLUGIN_NAME=Foo\n" - "VERSION=2.3\n"; - ASSERT_EQ(strlen(kMissingFileName), - base::WriteFile(pepper_dir_.Append("broken.info"), kMissingFileName, - strlen(kMissingFileName))); - - ASSERT_TRUE(Init()); - ASSERT_TRUE(builder_.SetUpChromium(base::FilePath())); - - EXPECT_EQ("--ppapi-flash-path=/opt/google/chrome/pepper/flash.so", - GetFirstArgWithPrefix("--ppapi-flash-path")); - EXPECT_EQ("--ppapi-flash-version=1.2.3.4", - GetFirstArgWithPrefix("--ppapi-flash-version")); - - // Plugins are ordered alphabetically by registration info. - const char kExpected[] = - "--register-pepper-plugins=" - "/opt/google/chrome/pepper/netflix.so#Netflix#" - "Helper for the Netflix application#2.0.0;application/netflix," - "/opt/google/chrome/pepper/other.so#Some other plugin;"; - EXPECT_EQ(kExpected, GetFirstArgWithPrefix("--register-pepper-plugins")); -} - -TEST_F(ChromiumCommandBuilderTest, DeepMemoryProfiler) { - use_flags_data_ = "deep_memory_profiler"; - WriteFileUnderBasePath( - ChromiumCommandBuilder::kDeepMemoryProfilerPrefixPath, "/foo\n"); - WriteFileUnderBasePath( - ChromiumCommandBuilder::kDeepMemoryProfilerTimeIntervalPath, "5\n"); - ASSERT_TRUE(Init()); - ASSERT_TRUE(builder_.SetUpChromium(base::FilePath())); - - EXPECT_EQ("/foo", ReadEnvVar("HEAPPROFILE")); - EXPECT_EQ("5", ReadEnvVar("HEAP_PROFILE_TIME_INTERVAL")); - EXPECT_EQ("1", ReadEnvVar("HEAP_PROFILE_MMAP")); - EXPECT_EQ("1", ReadEnvVar("DEEP_HEAP_PROFILE")); - EXPECT_EQ("--no-sandbox", GetFirstArgWithPrefix("--no-sandbox")); -} - -TEST_F(ChromiumCommandBuilderTest, SetUpX11) { - const base::FilePath kXauthPath(base_path_.Append("test_xauth")); - const char kXauthData[] = "foo"; - ASSERT_EQ(strlen(kXauthData), - base::WriteFile(kXauthPath, kXauthData, strlen(kXauthData))); - - ASSERT_TRUE(Init()); - ASSERT_TRUE(builder_.SetUpChromium(kXauthPath)); - - // XAUTHORITY should point at a copy of the original authority file. - std::string user_xauth_data; - base::FilePath user_xauth_path(ReadEnvVar("XAUTHORITY")); - ASSERT_FALSE(user_xauth_path.empty()); - EXPECT_NE(kXauthPath.value(), user_xauth_path.value()); - ASSERT_TRUE(ReadFileToString(user_xauth_path, &user_xauth_data)); - EXPECT_EQ(kXauthData, user_xauth_data); - - // Check that the file is only accessible by its owner. - int mode = 0; - ASSERT_TRUE(base::GetPosixFilePermissions(user_xauth_path, &mode)); - EXPECT_EQ(base::FILE_PERMISSION_READ_BY_USER | - base::FILE_PERMISSION_WRITE_BY_USER, mode); -} - -TEST_F(ChromiumCommandBuilderTest, MissingXauthFile) { - // SetUpChromium() should barf when instructed to use a nonexistent file. - ASSERT_TRUE(Init()); - EXPECT_FALSE(builder_.SetUpChromium(base_path_.Append("bogus_xauth"))); -} - -} // namespace ui -} // namespace chromeos diff --git a/chromeos/ui/util.cc b/chromeos/ui/util.cc deleted file mode 100644 index 686a945..0000000 --- a/chromeos/ui/util.cc +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2014 The Chromium OS 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 "chromeos/ui/util.h" - -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -namespace chromeos { -namespace ui { -namespace util { - -base::FilePath GetReparentedPath(const std::string& path, - const base::FilePath& parent) { - if (parent.empty()) - return base::FilePath(path); - - CHECK(!path.empty() && path[0] == '/'); - base::FilePath relative_path(path.substr(1)); - CHECK(!relative_path.IsAbsolute()); - return parent.Append(relative_path); -} - -bool SetPermissions(const base::FilePath& path, - uid_t uid, - gid_t gid, - mode_t mode) { - if (getuid() == 0) { - if (chown(path.value().c_str(), uid, gid) != 0) { - PLOG(ERROR) << "Couldn't chown " << path.value() << " to " - << uid << ":" << gid; - return false; - } - } - if (chmod(path.value().c_str(), mode) != 0) { - PLOG(ERROR) << "Unable to chmod " << path.value() << " to " - << std::oct << mode; - return false; - } - return true; -} - -bool EnsureDirectoryExists(const base::FilePath& path, - uid_t uid, - gid_t gid, - mode_t mode) { - if (!base::CreateDirectory(path)) { - PLOG(ERROR) << "Unable to create " << path.value(); - return false; - } - return SetPermissions(path, uid, gid, mode); -} - -bool Run(const char* command, - const char* arg, ...) { - // Extra parentheses because yay C++ most vexing parse. - base::CommandLine cl((base::FilePath(command))); - va_list list; - va_start(list, arg); - while (arg) { - cl.AppendArg(const_cast(arg)); - arg = va_arg(list, char*); - } - va_end(list); - - std::string output; - int exit_code = 0; - if (!base::GetAppOutputWithExitCode(cl, &output, &exit_code)) { - LOG(WARNING) << "\"" << cl.GetCommandLineString() << "\" failed with " - << exit_code << ": " << output; - return false; - } - - return true; -} - -} // namespace util -} // namespace ui -} // namespace chromeos diff --git a/chromeos/ui/util.h b/chromeos/ui/util.h deleted file mode 100644 index e059095..0000000 --- a/chromeos/ui/util.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2014 The Chromium OS 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 - -#include - -#ifndef LIBCHROMEOS_CHROMEOS_UI_UTIL_H_ -#define LIBCHROMEOS_CHROMEOS_UI_UTIL_H_ - -namespace chromeos { -namespace ui { -namespace util { - -// Converts an absolute path |path| into a base::FilePath. If |parent| is -// non-empty, |path| is rooted within it. For example, GetPath("/usr/bin/bar", -// base::FilePath("/tmp/foo")) returns base::FilePath("/tmp/foo/usr/bin/bar")). -base::FilePath GetReparentedPath(const std::string& path, - const base::FilePath& parent); - -// Changes the ownership of |path| to |uid|:|gid| and sets its mode to |mode|. -// Skips updating ownership when not running as root (for use in tests). -bool SetPermissions(const base::FilePath& path, - uid_t uid, - gid_t gid, - mode_t mode); - -// Ensures that |path| exists with the requested ownership and permissions, -// creating and/or updating it if needed. Returns true on success. -bool EnsureDirectoryExists(const base::FilePath& path, - uid_t uid, - gid_t gid, - mode_t mode); - -// Runs the passed-in command and arguments synchronously, returning true on -// success. On failure, the command's output is logged. The path will be -// searched for |command|. -bool Run(const char* command, const char* arg, ...); - -} // namespace util -} // namespace ui -} // namespace chromeos - -#endif // LIBCHROMEOS_CHROMEOS_UI_UTIL_H_ diff --git a/chromeos/ui/x_server_runner.cc b/chromeos/ui/x_server_runner.cc deleted file mode 100644 index 5a68507..0000000 --- a/chromeos/ui/x_server_runner.cc +++ /dev/null @@ -1,317 +0,0 @@ -// Copyright 2014 The Chromium OS 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 "chromeos/ui/x_server_runner.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "chromeos/ui/util.h" - -namespace chromeos { -namespace ui { - -namespace { - -// Path to the X server binary. -const char kXServerCommand[] = "/usr/bin/X"; - -// Writes |data| to |file|, returning true on success. -bool WriteString(base::File* file, const std::string& data) { - return file->WriteAtCurrentPos(data.data(), data.size()) == - static_cast(data.size()); -} - -// Writes |value| to |file| in big-endian order, returning true on success. -bool WriteUint16(base::File* file, uint16_t value) { - value = htons(value); - return file->WriteAtCurrentPos( - reinterpret_cast(&value), sizeof(value)) == - static_cast(sizeof(value)); -} - -// Creates a new X authority file at |path|, returning true on success. -bool CreateXauthFile(const base::FilePath& path, uid_t uid, gid_t gid) { - base::File file(path, - base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE); - if (!file.IsValid()) { - PLOG(ERROR) << "Couldn't open " << path.value(); - return false; - } - if (!util::SetPermissions(path, uid, gid, 0600)) - return false; - - const int kCookieSize = 16; - // TODO(derat): base/rand_util.h says not to use RandBytesAsString() for - // security-related purposes, but crypto::RandBytes() (which we don't package) - // just wraps RandBytes(). The base implementation uses /dev/urandom, which is - // fine for our purposes (see e.g. http://www.2uo.de/myths-about-urandom/), - // but to make this code self-documenting, this call should be changed to - // crypto::RandBytes() if/when that gets packaged for Chrome OS. - const std::string kCookie(base::RandBytesAsString(kCookieSize)); - const uint16_t kFamily = 0x100; - const std::string kAddress = "localhost"; - const std::string kNumber = "0"; - const std::string kName = "MIT-MAGIC-COOKIE-1"; - - if (!WriteUint16(&file, kFamily) || - !WriteUint16(&file, kAddress.size()) || - !WriteString(&file, kAddress) || - !WriteUint16(&file, kNumber.size()) || - !WriteString(&file, kNumber) || - !WriteUint16(&file, kName.size()) || - !WriteString(&file, kName) || - !WriteUint16(&file, kCookie.size()) || - !WriteString(&file, kCookie)) { - PLOG(ERROR) << "Couldn't write to " << path.value(); - return false; - } - - return true; -} - -// Runs the X server, replacing the current process. -void ExecServer(int vt, - int max_vt, - const base::FilePath& xauth_file, - const base::FilePath& log_file) { - std::vector args; - args.push_back(kXServerCommand); - args.push_back("-nohwaccess"); - args.push_back("-noreset"); - args.push_back("-maxvt"); - args.push_back(base::IntToString(max_vt)); - args.push_back("-nolisten"); - args.push_back("tcp"); - args.push_back(base::StringPrintf("vt%d", vt)); - args.push_back("-auth"); - args.push_back(xauth_file.value()); - args.push_back("-logfile"); - args.push_back(log_file.value()); - - const size_t kMaxArgs = 32; - char* argv[kMaxArgs + 1]; - CHECK_LE(args.size(), kMaxArgs); - for (size_t i = 0; i < args.size(); ++i) - argv[i] = const_cast(args[i].c_str()); - argv[args.size()] = nullptr; - - // This call doesn't return on success. - PCHECK(execv(argv[0], argv) == 0) << "execv() failed"; -} - -// Helper for ExecAndWaitForServer() that reads signals sent from |server_pid| -// via signalfd-created |fd|. Returns true if the server started successfully. -bool WaitForSignalFromServer(pid_t server_pid, int fd) { - LOG(INFO) << "X server started with PID " << server_pid; - while (true) { - struct signalfd_siginfo siginfo; - int bytes_read = HANDLE_EINTR(read(fd, &siginfo, sizeof(siginfo))); - PCHECK(bytes_read >= 0); - if (bytes_read != sizeof(siginfo)) { - LOG(ERROR) << "Read " << bytes_read << " byte(s); expected " - << sizeof(siginfo); - return false; - } - - switch (siginfo.ssi_signo) { - case SIGUSR1: - LOG(INFO) << "X server is ready for connections"; - return true; - case SIGCHLD: { - int status = 0; - int result = waitpid(server_pid, &status, WNOHANG); - if (result != 0) { - PCHECK(result == server_pid) << "waitpid() returned " << result; - if (WIFEXITED(status)) { - LOG(ERROR) << "X server exited with " << WEXITSTATUS(status) - << " before sending SIGUSR1"; - return false; - } else if (WIFSIGNALED(status)) { - LOG(ERROR) << "X server was terminated with signal " - << WTERMSIG(status) << " before sending SIGUSR1"; - return false; - } - } - // In the event of a non-exit SIGCHLD, ignore it and loop to - // read the next signal. - LOG(INFO) << "Ignoring non-exit SIGCHLD"; - continue; - } - default: - CHECK(false) << "Unexpected signal " << siginfo.ssi_signo; - } - } - return false; -} - -// Drops privileges, forks-and-execs the X server, waits for it to emit SIGUSR1 -// to indicate that it's ready for connections, and returns true on success. -bool ExecAndWaitForServer(const std::string& user, - uid_t uid, - gid_t gid, - const base::Closure& closure) { - // Avoid some syscalls when not running as root in tests. - if (getuid() == 0) { - if (setpriority(PRIO_PROCESS, 0, -20) != 0) - PLOG(WARNING) << "setpriority() failed"; - - PCHECK(initgroups(user.c_str(), gid) == 0); - PCHECK(setgid(gid) == 0); - PCHECK(setuid(uid) == 0); - } - - sigset_t mask; - PCHECK(sigemptyset(&mask) == 0); - PCHECK(sigaddset(&mask, SIGUSR1) == 0); - PCHECK(sigaddset(&mask, SIGCHLD) == 0); - const int fd = signalfd(-1, &mask, 0); - PCHECK(fd != -1) << "signalfd() failed"; - PCHECK(sigprocmask(SIG_BLOCK, &mask, nullptr) == 0); - - bool success = false; - switch (pid_t pid = fork()) { - case -1: - PLOG(ERROR) << "fork() failed"; - break; - case 0: - // Forked process: exec the X server. - base::CloseSuperfluousFds(base::InjectiveMultimap()); - PCHECK(sigprocmask(SIG_UNBLOCK, &mask, nullptr) == 0); - - // Set SIGUSR1's disposition to SIG_IGN before exec-ing so that X will - // emit SIGUSR1 once it's ready to accept connections. - PCHECK(signal(SIGUSR1, SIG_IGN) != SIG_ERR); - - closure.Run(); - - // We should never reach this point, but crash just in case to avoid - // double-closing the FD. - LOG(FATAL) << "Server closure returned unexpectedly"; - break; - default: - // Original process: wait for the forked process to become ready or exit. - success = WaitForSignalFromServer(pid, fd); - break; - } - - close(fd); - return success; -} - -} // namespace - -const char XServerRunner::kDefaultUser[] = "xorg"; -const int XServerRunner::kDefaultVt = 1; -const char XServerRunner::kSocketDir[] = "/tmp/.X11-unix"; -const char XServerRunner::kIceDir[] = "/tmp/.ICE-unix"; -const char XServerRunner::kLogFile[] = "/var/log/xorg/Xorg.0.log"; -const char XServerRunner::kXkbDir[] = "/var/lib/xkb"; - -XServerRunner::XServerRunner() : child_pid_(0) {} - -XServerRunner::~XServerRunner() {} - -bool XServerRunner::StartServer(const std::string& user, - int vt, - bool allow_vt_switching, - const base::FilePath& xauth_file) { - uid_t uid = 0; - gid_t gid = 0; - if (!userdb::GetUserInfo(user, &uid, &gid)) - return false; - - if (!CreateXauthFile(xauth_file, uid, gid)) - return false; - - if (!util::EnsureDirectoryExists(GetPath(kSocketDir), 0, 0, 01777) || - !util::EnsureDirectoryExists(GetPath(kIceDir), 0, 0, 01777)) - return false; - - const base::FilePath log_file(GetPath(kLogFile)); - if (!util::EnsureDirectoryExists(log_file.DirName(), uid, gid, 0755) || - !util::EnsureDirectoryExists(GetPath(kXkbDir), uid, gid, 0755)) - return false; - - // Create a relative symlink from one directory above |log_file| to the file - // itself (e.g. /var/log/Xorg.0.log -> xorg/Xorg.0.log). - base::CreateSymbolicLink( - log_file.DirName().BaseName().Append(log_file.BaseName()), - log_file.DirName().DirName().Append(log_file.BaseName())); - - // Disable all the Ctrl-Alt-Fn shortcuts for switching between virtual - // terminals if requested. Otherwise, disable only Fn (n>=3) keys. - int max_vt = allow_vt_switching ? 2 : 0; - - switch (child_pid_ = fork()) { - case -1: - PLOG(ERROR) << "fork() failed"; - return false; - case 0: { - base::Closure closure = !callback_for_testing_.is_null() ? - callback_for_testing_ : - base::Bind(&ExecServer, vt, max_vt, xauth_file, log_file); - // The child process waits for the server to start and exits with 0. - exit(ExecAndWaitForServer(user, uid, gid, closure) ? 0 : 1); - } - default: - LOG(INFO) << "Child process " << child_pid_ - << " starting X server in background"; - } - return true; -} - -bool XServerRunner::WaitForServer() { - CHECK_GT(child_pid_, 0); - int status = 0; - if (waitpid(child_pid_, &status, 0) != child_pid_) { - PLOG(ERROR) << "waitpid() on " << child_pid_ << " failed"; - return false; - } - if (!WIFEXITED(status)) { - LOG(ERROR) << "Child process " << child_pid_ << " didn't exit normally"; - return false; - } - if (WEXITSTATUS(status) != 0) { - LOG(ERROR) << "Child process " << child_pid_ << " exited with " - << WEXITSTATUS(status); - return false; - } - - if (getuid() == 0) { - // TODO(derat): Move session_manager's UpstartSignalEmitter into libchromeos - // and use it here. - util::Run("initctl", "emit", "x-started", nullptr); - bootstat_log("x-started"); - } - - return true; -} - -base::FilePath XServerRunner::GetPath(const std::string& path) const { - return util::GetReparentedPath(path, base_path_for_testing_); -} - -} // namespace ui -} // namespace chromeos diff --git a/chromeos/ui/x_server_runner.h b/chromeos/ui/x_server_runner.h deleted file mode 100644 index 2ea194d..0000000 --- a/chromeos/ui/x_server_runner.h +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2014 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef LIBCHROMEOS_CHROMEOS_UI_X_SERVER_RUNNER_H_ -#define LIBCHROMEOS_CHROMEOS_UI_X_SERVER_RUNNER_H_ - -#include - -#include - -#include -#include -#include - -namespace chromeos { -namespace ui { - -// XServerRunner can be used to start the X server asynchronously and later -// block until the server is ready to accept connections from clients. -// -// In more detail: -// -// - StartServer() performs necessary setup and forks |child_pid_|. -// - |child_pid_| setuids to |user| and forks another process |x_pid|. -// - |x_pid| execs the X server. -// - The X server sends SIGUSR1 to |child_pid_| after initialization. -// - |child_pid_| exits, resulting in the original process receiving SIGCHLD. -// - WaitForServer() blocks until SIGCHLD has been received. -class XServerRunner { - public: - // Default constructor values for Chrome OS. - static const char kDefaultUser[]; - static const int kDefaultVt; - - // Various hard-coded paths exposed here for tests. - static const char kSocketDir[]; - static const char kIceDir[]; - static const char kLogFile[]; - static const char kXkbDir[]; - - XServerRunner(); - ~XServerRunner(); - - void set_base_path_for_testing(const base::FilePath& path) { - base_path_for_testing_ = path; - } - void set_callback_for_testing(const base::Closure& callback) { - callback_for_testing_ = callback; - } - - // Creates necessary directories and starts the X server in the background - // running as |user| on |vt|. |xauth_file| will be created to permit - // connections to the server. Returns true if the setup was successful and the - // child process that starts the server was forked sucessfully. - bool StartServer(const std::string& user, - int vt, - bool allow_vt_switching, - const base::FilePath& xauth_file); - - // Blocks until the previously-started X server is ready to accept - // connections. Handles announcing the server's readiness to Upstart and - // recording a bootstat event. - bool WaitForServer(); - - private: - // Converts absolute path |path| into a base::FilePath, rooting it under - // |base_path_for_testing_| if it's non-empty. - base::FilePath GetPath(const std::string& path) const; - - // Path under which files are created when running in a test. - base::FilePath base_path_for_testing_; - - // If non-null, run instead of actually starting the X server. - base::Closure callback_for_testing_; - - // PID of the child process that will exit once the X server is ready to - // accept connections. - pid_t child_pid_; - - DISALLOW_COPY_AND_ASSIGN(XServerRunner); -}; - -} // namespace ui -} // namespace chromeos - -#endif // LIBCHROMEOS_CHROMEOS_UI_X_SERVER_RUNNER_H_ diff --git a/chromeos/ui/x_server_runner_unittest.cc b/chromeos/ui/x_server_runner_unittest.cc deleted file mode 100644 index 1f22eec..0000000 --- a/chromeos/ui/x_server_runner_unittest.cc +++ /dev/null @@ -1,207 +0,0 @@ -// Copyright 2014 The Chromium OS 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 "chromeos/ui/x_server_runner.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "chromeos/ui/util.h" - -namespace chromeos { -namespace ui { - -namespace { - -// Passed to XServerRunner as a callback that should be run instead of actually -// starting the X server. Writes the current process's PID to |pipe_path|. If -// |exit_delay| is non-zero, sleeps and exits without sending SIGUSR1. -// Otherwise, sleeps for |signal_delay|, sends SIGUSR1 to its parent process, -// and then sleeps for a long time. -void ExecServer(const base::FilePath& pipe_path, - const base::TimeDelta& signal_delay, - const base::TimeDelta& exit_delay) { - // Write our PID so the test (our grandparent process) can clean us up. - pid_t pid = getpid(); - PCHECK(base::WriteFile(pipe_path, reinterpret_cast(&pid), - sizeof(pid)) == sizeof(pid)); - - // Check that the child process didn't inherit any blocked signals: - // http://crbug.com/380713 - sigset_t old_signals; - PCHECK(sigemptyset(&old_signals) == 0); - PCHECK(sigprocmask(SIG_SETMASK, nullptr, &old_signals) == 0); - CHECK(sigisemptyset(&old_signals)) << "Child inherited blocked signals"; - - if (exit_delay > base::TimeDelta()) { - base::PlatformThread::Sleep(exit_delay); - exit(1); - } - - if (signal_delay > base::TimeDelta()) - base::PlatformThread::Sleep(signal_delay); - PCHECK(kill(getppid(), SIGUSR1) == 0); - - base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(60)); -} - -} // namespace - -class XServerRunnerTest : public testing::Test { - public: - XServerRunnerTest() : server_pid_(0) { - CHECK(temp_dir_.CreateUniqueTempDir()); - base_path_ = temp_dir_.path(); - runner_.set_base_path_for_testing(base_path_); - xauth_path_ = base_path_.Append("xauth"); - } - virtual ~XServerRunnerTest() {} - - // Calls StartServer(). See ExecServer() for descriptions of the arguments. - void StartServer(const base::TimeDelta& signal_delay, - const base::TimeDelta& exit_delay) { - // Named pipe used by ExecServer() to pass its PID back to the test process. - base::FilePath pipe_path = base_path_.Append("pipe"); - PCHECK(mkfifo(pipe_path.value().c_str(), 0600) == 0); - - runner_.set_callback_for_testing( - base::Bind(&ExecServer, pipe_path, signal_delay, exit_delay)); - passwd* user_info = getpwuid(getuid()); - ASSERT_TRUE(user_info) << "getpwuid() didn't find UID " << getuid(); - ASSERT_TRUE(runner_.StartServer(user_info->pw_name, 1, false, xauth_path_)); - - // Open the pipe and read ExecServer()'s PID. - int pipe_fd = open(pipe_path.value().c_str(), O_RDONLY); - PCHECK(pipe_fd >= 0) << "Failed to open " << pipe_path.value(); - PCHECK(HANDLE_EINTR(read(pipe_fd, &server_pid_, sizeof(server_pid_))) == - sizeof(server_pid_)); - close(pipe_fd); - } - - // Calls WaitForServer() and returns its result. If it returns true (i.e. the - // X server process sent SIGUSR1), additionally kills the process before - // returning. - bool WaitForServer() { - // No need to kill the process if it already exited on its own. - if (!runner_.WaitForServer()) - return false; - - LOG(INFO) << "Killing server process " << server_pid_; - kill(server_pid_, SIGTERM); - return true; - } - - protected: - base::ScopedTempDir temp_dir_; - base::FilePath base_path_; - base::FilePath xauth_path_; - - XServerRunner runner_; - - // PID of the process running ExecServer(). - pid_t server_pid_; - - private: - DISALLOW_COPY_AND_ASSIGN(XServerRunnerTest); -}; - -TEST_F(XServerRunnerTest, FastSuccess) { - StartServer(base::TimeDelta(), base::TimeDelta()); - EXPECT_TRUE(WaitForServer()); -} - -TEST_F(XServerRunnerTest, SlowSuccess) { - StartServer(base::TimeDelta::FromSeconds(1), base::TimeDelta()); - EXPECT_TRUE(WaitForServer()); -} - -TEST_F(XServerRunnerTest, FastCrash) { - StartServer(base::TimeDelta(), base::TimeDelta::FromMicroseconds(1)); - EXPECT_FALSE(WaitForServer()); -} - -TEST_F(XServerRunnerTest, SlowCrash) { - StartServer(base::TimeDelta(), base::TimeDelta::FromSeconds(1)); - EXPECT_FALSE(WaitForServer()); -} - -TEST_F(XServerRunnerTest, TermServer) { - StartServer(base::TimeDelta::FromSeconds(60), base::TimeDelta()); - PCHECK(kill(server_pid_, SIGTERM) == 0); - EXPECT_FALSE(WaitForServer()); -} - -TEST_F(XServerRunnerTest, StopAndContinueServer) { - // Test that SIGCHLD signals that are sent in response to the process being - // stopped or continued are ignored. - StartServer(base::TimeDelta::FromSeconds(1), base::TimeDelta()); - PCHECK(kill(server_pid_, SIGSTOP) == 0); - base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); - PCHECK(kill(server_pid_, SIGCONT) == 0); - EXPECT_TRUE(WaitForServer()); -} - -TEST_F(XServerRunnerTest, XauthFile) { - StartServer(base::TimeDelta(), base::TimeDelta()); - EXPECT_TRUE(WaitForServer()); - - std::string data; - ASSERT_TRUE(base::ReadFileToString(xauth_path_, &data)); - - const char kExpected[] = - "\x01" "\x00" - "\x00" "\x09" "localhost" - "\x00" "\x01" "0" - "\x00" "\x12" "MIT-MAGIC-COOKIE-1" - "\x00" "\x10" /* random 16-byte cookie data goes here */; - const size_t kExpectedSize = arraysize(kExpected) - 1; - const size_t kCookieSize = 16; - - ASSERT_EQ(kExpectedSize + kCookieSize, data.size()); - EXPECT_EQ(base::HexEncode(kExpected, kExpectedSize), - base::HexEncode(data.data(), kExpectedSize)); -} - -TEST_F(XServerRunnerTest, CreateDirectories) { - StartServer(base::TimeDelta(), base::TimeDelta()); - EXPECT_TRUE(WaitForServer()); - - EXPECT_TRUE(base::DirectoryExists(util::GetReparentedPath( - XServerRunner::kSocketDir, base_path_))); - EXPECT_TRUE(base::DirectoryExists(util::GetReparentedPath( - XServerRunner::kIceDir, base_path_))); - EXPECT_TRUE(base::DirectoryExists(util::GetReparentedPath( - XServerRunner::kXkbDir, base_path_))); - - base::FilePath log_file(util::GetReparentedPath( - XServerRunner::kLogFile, base_path_)); - base::FilePath log_dir(log_file.DirName()); - EXPECT_TRUE(base::DirectoryExists(log_dir)); - - // Check that a relative symlink is created in the directory above the one - // where the log file is written. - base::FilePath link; - EXPECT_TRUE(base::ReadSymbolicLink( - log_dir.DirName().Append(log_file.BaseName()), &link)); - EXPECT_EQ(log_dir.BaseName().Append(log_file.BaseName()).value(), - link.value()); -} - -} // namespace ui -} // namespace chromeos diff --git a/libchromeos.gypi b/libchromeos.gypi index e6857ae..a2ff98f 100644 --- a/libchromeos.gypi +++ b/libchromeos.gypi @@ -19,7 +19,6 @@ 'libchromeos-http-<(libbase_ver)', 'libchromeos-minijail-<(libbase_ver)', 'libchromeos-streams-<(libbase_ver)', - 'libchromeos-ui-<(libbase_ver)', 'libpolicy-<(libbase_ver)', ], 'direct_dependent_settings': { @@ -203,24 +202,6 @@ 'chromeos/minijail/minijail.cc', ], }, - { - 'target_name': 'libchromeos-ui-<(libbase_ver)', - 'type': 'shared_library', - 'dependencies': [ - 'libchromeos-core-<(libbase_ver)', - ], - 'libraries': [ - '-lbootstat', - ], - 'cflags': [ - '-fvisibility=default', - ], - 'sources': [ - 'chromeos/ui/chromium_command_builder.cc', - 'chromeos/ui/util.cc', - 'chromeos/ui/x_server_runner.cc', - ], - }, { 'target_name': 'libpolicy-<(libbase_ver)', 'type': 'shared_library', @@ -294,7 +275,6 @@ 'dependencies': [ 'libchromeos-<(libbase_ver)', 'libchromeos-test-<(libbase_ver)', - 'libchromeos-ui-<(libbase_ver)', 'libchromeos-glib-<(libbase_ver)', ], 'variables': { @@ -367,8 +347,6 @@ 'chromeos/streams/stream_unittest.cc', 'chromeos/streams/stream_utils_unittest.cc', 'chromeos/strings/string_utils_unittest.cc', - 'chromeos/ui/chromium_command_builder_unittest.cc', - 'chromeos/ui/x_server_runner_unittest.cc', 'chromeos/url_utils_unittest.cc', 'chromeos/variant_dictionary_unittest.cc', 'testrunner.cc', -- cgit v1.2.3