diff options
Diffstat (limited to 'chromeos/ui/chromium_command_builder.cc')
-rw-r--r-- | chromeos/ui/chromium_command_builder.cc | 504 |
1 files changed, 0 insertions, 504 deletions
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 <sys/resource.h> - -#include <algorithm> -#include <cstdarg> -#include <ctime> - -#include <base/command_line.h> -#include <base/files/file_enumerator.h> -#include <base/files/file_util.h> -#include <base/logging.h> -#include <base/process/launch.h> -#include <base/strings/string_number_conversions.h> -#include <base/strings/string_split.h> -#include <base/strings/string_util.h> -#include <chromeos/userdb_utils.h> - -#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<std::string> 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<std::string> 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<int>(src_index)) - vmodule_argument_index_--; - else if (vmodule_argument_index_ == static_cast<int>(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<std::string> 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 |