Bug 1035275 - Remove unused base Chromium code. r=bbondy

This commit is contained in:
Bob Owen 2014-07-07 13:59:11 +01:00
parent e02ddd1af3
commit d1da9cff99
26 changed files with 0 additions and 4050 deletions

View File

@ -1,47 +0,0 @@
// Copyright (c) 2006-2008 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 "base/base_paths.h"
#include "base/file_util.h"
#include "base/files/file_path.h"
#include "base/path_service.h"
namespace base {
bool PathProvider(int key, FilePath* result) {
// NOTE: DIR_CURRENT is a special case in PathService::Get
FilePath cur;
switch (key) {
case DIR_EXE:
PathService::Get(FILE_EXE, &cur);
cur = cur.DirName();
break;
case DIR_MODULE:
PathService::Get(FILE_MODULE, &cur);
cur = cur.DirName();
break;
case DIR_TEMP:
if (!file_util::GetTempDir(&cur))
return false;
break;
case DIR_TEST_DATA:
if (!PathService::Get(DIR_SOURCE_ROOT, &cur))
return false;
cur = cur.Append(FILE_PATH_LITERAL("base"));
cur = cur.Append(FILE_PATH_LITERAL("test"));
cur = cur.Append(FILE_PATH_LITERAL("data"));
if (!base::PathExists(cur)) // We don't want to create this.
return false;
break;
default:
return false;
}
*result = cur;
return true;
}
} // namespace base

View File

@ -1,208 +0,0 @@
// 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 <windows.h>
#include <shlobj.h>
#include "base/base_paths.h"
#include "base/files/file_path.h"
#include "base/path_service.h"
#include "base/win/scoped_co_mem.h"
#include "base/win/windows_version.h"
// http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx
extern "C" IMAGE_DOS_HEADER __ImageBase;
using base::FilePath;
namespace {
bool GetQuickLaunchPath(bool default_user, FilePath* result) {
if (default_user) {
wchar_t system_buffer[MAX_PATH];
system_buffer[0] = 0;
// As per MSDN, passing -1 for |hToken| indicates the Default user:
// http://msdn.microsoft.com/library/windows/desktop/bb762181.aspx
if (FAILED(SHGetFolderPath(NULL, CSIDL_APPDATA,
reinterpret_cast<HANDLE>(-1), SHGFP_TYPE_CURRENT,
system_buffer))) {
return false;
}
*result = FilePath(system_buffer);
} else if (!PathService::Get(base::DIR_APP_DATA, result)) {
// For the current user, grab the APPDATA directory directly from the
// PathService cache.
return false;
}
// According to various sources, appending
// "Microsoft\Internet Explorer\Quick Launch" to %appdata% is the only
// reliable way to get the quick launch folder across all versions of Windows.
// http://stackoverflow.com/questions/76080/how-do-you-reliably-get-the-quick-
// http://www.microsoft.com/technet/scriptcenter/resources/qanda/sept05/hey0901.mspx
*result = result->AppendASCII("Microsoft");
*result = result->AppendASCII("Internet Explorer");
*result = result->AppendASCII("Quick Launch");
return true;
}
} // namespace
namespace base {
bool PathProviderWin(int key, FilePath* result) {
// We need to go compute the value. It would be nice to support paths with
// names longer than MAX_PATH, but the system functions don't seem to be
// designed for it either, with the exception of GetTempPath (but other
// things will surely break if the temp path is too long, so we don't bother
// handling it.
wchar_t system_buffer[MAX_PATH];
system_buffer[0] = 0;
FilePath cur;
switch (key) {
case base::FILE_EXE:
GetModuleFileName(NULL, system_buffer, MAX_PATH);
cur = FilePath(system_buffer);
break;
case base::FILE_MODULE: {
// the resource containing module is assumed to be the one that
// this code lives in, whether that's a dll or exe
HMODULE this_module = reinterpret_cast<HMODULE>(&__ImageBase);
GetModuleFileName(this_module, system_buffer, MAX_PATH);
cur = FilePath(system_buffer);
break;
}
case base::DIR_WINDOWS:
GetWindowsDirectory(system_buffer, MAX_PATH);
cur = FilePath(system_buffer);
break;
case base::DIR_SYSTEM:
GetSystemDirectory(system_buffer, MAX_PATH);
cur = FilePath(system_buffer);
break;
case base::DIR_PROGRAM_FILESX86:
if (base::win::OSInfo::GetInstance()->architecture() !=
base::win::OSInfo::X86_ARCHITECTURE) {
if (FAILED(SHGetFolderPath(NULL, CSIDL_PROGRAM_FILESX86, NULL,
SHGFP_TYPE_CURRENT, system_buffer)))
return false;
cur = FilePath(system_buffer);
break;
}
// Fall through to base::DIR_PROGRAM_FILES if we're on an X86 machine.
case base::DIR_PROGRAM_FILES:
if (FAILED(SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES, NULL,
SHGFP_TYPE_CURRENT, system_buffer)))
return false;
cur = FilePath(system_buffer);
break;
case base::DIR_IE_INTERNET_CACHE:
if (FAILED(SHGetFolderPath(NULL, CSIDL_INTERNET_CACHE, NULL,
SHGFP_TYPE_CURRENT, system_buffer)))
return false;
cur = FilePath(system_buffer);
break;
case base::DIR_COMMON_START_MENU:
if (FAILED(SHGetFolderPath(NULL, CSIDL_COMMON_PROGRAMS, NULL,
SHGFP_TYPE_CURRENT, system_buffer)))
return false;
cur = FilePath(system_buffer);
break;
case base::DIR_START_MENU:
if (FAILED(SHGetFolderPath(NULL, CSIDL_PROGRAMS, NULL,
SHGFP_TYPE_CURRENT, system_buffer)))
return false;
cur = FilePath(system_buffer);
break;
case base::DIR_APP_DATA:
if (FAILED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT,
system_buffer)))
return false;
cur = FilePath(system_buffer);
break;
case base::DIR_COMMON_APP_DATA:
if (FAILED(SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL,
SHGFP_TYPE_CURRENT, system_buffer)))
return false;
cur = FilePath(system_buffer);
break;
case base::DIR_PROFILE:
if (FAILED(SHGetFolderPath(NULL, CSIDL_PROFILE, NULL, SHGFP_TYPE_CURRENT,
system_buffer)))
return false;
cur = FilePath(system_buffer);
break;
case base::DIR_LOCAL_APP_DATA_LOW:
if (win::GetVersion() < win::VERSION_VISTA)
return false;
// TODO(nsylvain): We should use SHGetKnownFolderPath instead. Bug 1281128
if (FAILED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT,
system_buffer)))
return false;
cur = FilePath(system_buffer).DirName().AppendASCII("LocalLow");
break;
case base::DIR_LOCAL_APP_DATA:
if (FAILED(SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL,
SHGFP_TYPE_CURRENT, system_buffer)))
return false;
cur = FilePath(system_buffer);
break;
case base::DIR_SOURCE_ROOT: {
FilePath executableDir;
// On Windows, unit tests execute two levels deep from the source root.
// For example: chrome/{Debug|Release}/ui_tests.exe
PathService::Get(base::DIR_EXE, &executableDir);
cur = executableDir.DirName().DirName();
break;
}
case base::DIR_APP_SHORTCUTS: {
if (win::GetVersion() < win::VERSION_WIN8)
return false;
base::win::ScopedCoMem<wchar_t> path_buf;
if (FAILED(SHGetKnownFolderPath(FOLDERID_ApplicationShortcuts, 0, NULL,
&path_buf)))
return false;
cur = FilePath(string16(path_buf));
break;
}
case base::DIR_USER_DESKTOP:
if (FAILED(SHGetFolderPath(NULL, CSIDL_DESKTOPDIRECTORY, NULL,
SHGFP_TYPE_CURRENT, system_buffer))) {
return false;
}
cur = FilePath(system_buffer);
break;
case base::DIR_COMMON_DESKTOP:
if (FAILED(SHGetFolderPath(NULL, CSIDL_COMMON_DESKTOPDIRECTORY, NULL,
SHGFP_TYPE_CURRENT, system_buffer))) {
return false;
}
cur = FilePath(system_buffer);
break;
case base::DIR_USER_QUICK_LAUNCH:
if (!GetQuickLaunchPath(false, &cur))
return false;
break;
case base::DIR_DEFAULT_USER_QUICK_LAUNCH:
if (!GetQuickLaunchPath(true, &cur))
return false;
break;
case base::DIR_TASKBAR_PINS:
if (!PathService::Get(base::DIR_USER_QUICK_LAUNCH, &cur))
return false;
cur = cur.AppendASCII("User Pinned");
cur = cur.AppendASCII("TaskBar");
break;
default:
return false;
}
*result = cur;
return true;
}
} // namespace base

View File

@ -1,424 +0,0 @@
// 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 "base/command_line.h"
#include <algorithm>
#include <ostream>
#include "base/basictypes.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#if defined(OS_WIN)
#include <windows.h>
#include <shellapi.h>
#endif
using base::FilePath;
CommandLine* CommandLine::current_process_commandline_ = NULL;
namespace {
const CommandLine::CharType kSwitchTerminator[] = FILE_PATH_LITERAL("--");
const CommandLine::CharType kSwitchValueSeparator[] = FILE_PATH_LITERAL("=");
// Since we use a lazy match, make sure that longer versions (like "--") are
// listed before shorter versions (like "-") of similar prefixes.
#if defined(OS_WIN)
const CommandLine::CharType* const kSwitchPrefixes[] = {L"--", L"-", L"/"};
#elif defined(OS_POSIX)
// Unixes don't use slash as a switch.
const CommandLine::CharType* const kSwitchPrefixes[] = {"--", "-"};
#endif
size_t GetSwitchPrefixLength(const CommandLine::StringType& string) {
for (size_t i = 0; i < arraysize(kSwitchPrefixes); ++i) {
CommandLine::StringType prefix(kSwitchPrefixes[i]);
if (string.compare(0, prefix.length(), prefix) == 0)
return prefix.length();
}
return 0;
}
// Fills in |switch_string| and |switch_value| if |string| is a switch.
// This will preserve the input switch prefix in the output |switch_string|.
bool IsSwitch(const CommandLine::StringType& string,
CommandLine::StringType* switch_string,
CommandLine::StringType* switch_value) {
switch_string->clear();
switch_value->clear();
size_t prefix_length = GetSwitchPrefixLength(string);
if (prefix_length == 0 || prefix_length == string.length())
return false;
const size_t equals_position = string.find(kSwitchValueSeparator);
*switch_string = string.substr(0, equals_position);
if (equals_position != CommandLine::StringType::npos)
*switch_value = string.substr(equals_position + 1);
return true;
}
// Append switches and arguments, keeping switches before arguments.
void AppendSwitchesAndArguments(CommandLine& command_line,
const CommandLine::StringVector& argv) {
bool parse_switches = true;
for (size_t i = 1; i < argv.size(); ++i) {
CommandLine::StringType arg = argv[i];
TrimWhitespace(arg, TRIM_ALL, &arg);
CommandLine::StringType switch_string;
CommandLine::StringType switch_value;
parse_switches &= (arg != kSwitchTerminator);
if (parse_switches && IsSwitch(arg, &switch_string, &switch_value)) {
#if defined(OS_WIN)
command_line.AppendSwitchNative(WideToASCII(switch_string), switch_value);
#elif defined(OS_POSIX)
command_line.AppendSwitchNative(switch_string, switch_value);
#endif
} else {
command_line.AppendArgNative(arg);
}
}
}
// Lowercase switches for backwards compatiblity *on Windows*.
std::string LowerASCIIOnWindows(const std::string& string) {
#if defined(OS_WIN)
return StringToLowerASCII(string);
#elif defined(OS_POSIX)
return string;
#endif
}
#if defined(OS_WIN)
// Quote a string as necessary for CommandLineToArgvW compatiblity *on Windows*.
std::wstring QuoteForCommandLineToArgvW(const std::wstring& arg) {
// We follow the quoting rules of CommandLineToArgvW.
// http://msdn.microsoft.com/en-us/library/17w5ykft.aspx
if (arg.find_first_of(L" \\\"") == std::wstring::npos) {
// No quoting necessary.
return arg;
}
std::wstring out;
out.push_back(L'"');
for (size_t i = 0; i < arg.size(); ++i) {
if (arg[i] == '\\') {
// Find the extent of this run of backslashes.
size_t start = i, end = start + 1;
for (; end < arg.size() && arg[end] == '\\'; ++end)
/* empty */;
size_t backslash_count = end - start;
// Backslashes are escapes only if the run is followed by a double quote.
// Since we also will end the string with a double quote, we escape for
// either a double quote or the end of the string.
if (end == arg.size() || arg[end] == '"') {
// To quote, we need to output 2x as many backslashes.
backslash_count *= 2;
}
for (size_t j = 0; j < backslash_count; ++j)
out.push_back('\\');
// Advance i to one before the end to balance i++ in loop.
i = end - 1;
} else if (arg[i] == '"') {
out.push_back('\\');
out.push_back('"');
} else {
out.push_back(arg[i]);
}
}
out.push_back('"');
return out;
}
#endif
} // namespace
CommandLine::CommandLine(NoProgram no_program)
: argv_(1),
begin_args_(1) {
}
CommandLine::CommandLine(const FilePath& program)
: argv_(1),
begin_args_(1) {
SetProgram(program);
}
CommandLine::CommandLine(int argc, const CommandLine::CharType* const* argv)
: argv_(1),
begin_args_(1) {
InitFromArgv(argc, argv);
}
CommandLine::CommandLine(const StringVector& argv)
: argv_(1),
begin_args_(1) {
InitFromArgv(argv);
}
CommandLine::~CommandLine() {
}
// static
bool CommandLine::Init(int argc, const char* const* argv) {
if (current_process_commandline_) {
// If this is intentional, Reset() must be called first. If we are using
// the shared build mode, we have to share a single object across multiple
// shared libraries.
return false;
}
current_process_commandline_ = new CommandLine(NO_PROGRAM);
#if defined(OS_WIN)
current_process_commandline_->ParseFromString(::GetCommandLineW());
#elif defined(OS_POSIX)
current_process_commandline_->InitFromArgv(argc, argv);
#endif
return true;
}
// static
void CommandLine::Reset() {
DCHECK(current_process_commandline_);
delete current_process_commandline_;
current_process_commandline_ = NULL;
}
// static
CommandLine* CommandLine::ForCurrentProcess() {
DCHECK(current_process_commandline_);
return current_process_commandline_;
}
// static
bool CommandLine::InitializedForCurrentProcess() {
return !!current_process_commandline_;
}
#if defined(OS_WIN)
// static
CommandLine CommandLine::FromString(const std::wstring& command_line) {
CommandLine cmd(NO_PROGRAM);
cmd.ParseFromString(command_line);
return cmd;
}
#endif
void CommandLine::InitFromArgv(int argc,
const CommandLine::CharType* const* argv) {
StringVector new_argv;
for (int i = 0; i < argc; ++i)
new_argv.push_back(argv[i]);
InitFromArgv(new_argv);
}
void CommandLine::InitFromArgv(const StringVector& argv) {
argv_ = StringVector(1);
switches_.clear();
begin_args_ = 1;
SetProgram(argv.empty() ? FilePath() : FilePath(argv[0]));
AppendSwitchesAndArguments(*this, argv);
}
CommandLine::StringType CommandLine::GetCommandLineString() const {
StringType string(argv_[0]);
#if defined(OS_WIN)
string = QuoteForCommandLineToArgvW(string);
#endif
StringType params(GetArgumentsString());
if (!params.empty()) {
string.append(StringType(FILE_PATH_LITERAL(" ")));
string.append(params);
}
return string;
}
CommandLine::StringType CommandLine::GetArgumentsString() const {
StringType params;
// Append switches and arguments.
bool parse_switches = true;
for (size_t i = 1; i < argv_.size(); ++i) {
StringType arg = argv_[i];
StringType switch_string;
StringType switch_value;
parse_switches &= arg != kSwitchTerminator;
if (i > 1)
params.append(StringType(FILE_PATH_LITERAL(" ")));
if (parse_switches && IsSwitch(arg, &switch_string, &switch_value)) {
params.append(switch_string);
if (!switch_value.empty()) {
#if defined(OS_WIN)
switch_value = QuoteForCommandLineToArgvW(switch_value);
#endif
params.append(kSwitchValueSeparator + switch_value);
}
}
else {
#if defined(OS_WIN)
arg = QuoteForCommandLineToArgvW(arg);
#endif
params.append(arg);
}
}
return params;
}
FilePath CommandLine::GetProgram() const {
return FilePath(argv_[0]);
}
void CommandLine::SetProgram(const FilePath& program) {
TrimWhitespace(program.value(), TRIM_ALL, &argv_[0]);
}
bool CommandLine::HasSwitch(const std::string& switch_string) const {
return switches_.find(LowerASCIIOnWindows(switch_string)) != switches_.end();
}
std::string CommandLine::GetSwitchValueASCII(
const std::string& switch_string) const {
StringType value = GetSwitchValueNative(switch_string);
if (!IsStringASCII(value)) {
DLOG(WARNING) << "Value of switch (" << switch_string << ") must be ASCII.";
return std::string();
}
#if defined(OS_WIN)
return WideToASCII(value);
#else
return value;
#endif
}
FilePath CommandLine::GetSwitchValuePath(
const std::string& switch_string) const {
return FilePath(GetSwitchValueNative(switch_string));
}
CommandLine::StringType CommandLine::GetSwitchValueNative(
const std::string& switch_string) const {
SwitchMap::const_iterator result = switches_.end();
result = switches_.find(LowerASCIIOnWindows(switch_string));
return result == switches_.end() ? StringType() : result->second;
}
void CommandLine::AppendSwitch(const std::string& switch_string) {
AppendSwitchNative(switch_string, StringType());
}
void CommandLine::AppendSwitchPath(const std::string& switch_string,
const FilePath& path) {
AppendSwitchNative(switch_string, path.value());
}
void CommandLine::AppendSwitchNative(const std::string& switch_string,
const CommandLine::StringType& value) {
std::string switch_key(LowerASCIIOnWindows(switch_string));
#if defined(OS_WIN)
StringType combined_switch_string(ASCIIToWide(switch_key));
#elif defined(OS_POSIX)
StringType combined_switch_string(switch_string);
#endif
size_t prefix_length = GetSwitchPrefixLength(combined_switch_string);
switches_[switch_key.substr(prefix_length)] = value;
// Preserve existing switch prefixes in |argv_|; only append one if necessary.
if (prefix_length == 0)
combined_switch_string = kSwitchPrefixes[0] + combined_switch_string;
if (!value.empty())
combined_switch_string += kSwitchValueSeparator + value;
// Append the switch and update the switches/arguments divider |begin_args_|.
argv_.insert(argv_.begin() + begin_args_++, combined_switch_string);
}
void CommandLine::AppendSwitchASCII(const std::string& switch_string,
const std::string& value_string) {
#if defined(OS_WIN)
AppendSwitchNative(switch_string, ASCIIToWide(value_string));
#elif defined(OS_POSIX)
AppendSwitchNative(switch_string, value_string);
#endif
}
void CommandLine::CopySwitchesFrom(const CommandLine& source,
const char* const switches[],
size_t count) {
for (size_t i = 0; i < count; ++i) {
if (source.HasSwitch(switches[i]))
AppendSwitchNative(switches[i], source.GetSwitchValueNative(switches[i]));
}
}
CommandLine::StringVector CommandLine::GetArgs() const {
// Gather all arguments after the last switch (may include kSwitchTerminator).
StringVector args(argv_.begin() + begin_args_, argv_.end());
// Erase only the first kSwitchTerminator (maybe "--" is a legitimate page?)
StringVector::iterator switch_terminator =
std::find(args.begin(), args.end(), kSwitchTerminator);
if (switch_terminator != args.end())
args.erase(switch_terminator);
return args;
}
void CommandLine::AppendArg(const std::string& value) {
#if defined(OS_WIN)
DCHECK(IsStringUTF8(value));
AppendArgNative(UTF8ToWide(value));
#elif defined(OS_POSIX)
AppendArgNative(value);
#endif
}
void CommandLine::AppendArgPath(const FilePath& path) {
AppendArgNative(path.value());
}
void CommandLine::AppendArgNative(const CommandLine::StringType& value) {
argv_.push_back(value);
}
void CommandLine::AppendArguments(const CommandLine& other,
bool include_program) {
if (include_program)
SetProgram(other.GetProgram());
AppendSwitchesAndArguments(*this, other.argv());
}
void CommandLine::PrependWrapper(const CommandLine::StringType& wrapper) {
if (wrapper.empty())
return;
// The wrapper may have embedded arguments (like "gdb --args"). In this case,
// we don't pretend to do anything fancy, we just split on spaces.
StringVector wrapper_argv;
base::SplitString(wrapper, FILE_PATH_LITERAL(' '), &wrapper_argv);
// Prepend the wrapper and update the switches/arguments |begin_args_|.
argv_.insert(argv_.begin(), wrapper_argv.begin(), wrapper_argv.end());
begin_args_ += wrapper_argv.size();
}
#if defined(OS_WIN)
void CommandLine::ParseFromString(const std::wstring& command_line) {
std::wstring command_line_string;
TrimWhitespace(command_line, TRIM_ALL, &command_line_string);
if (command_line_string.empty())
return;
int num_args = 0;
wchar_t** args = NULL;
args = ::CommandLineToArgvW(command_line_string.c_str(), &num_args);
DPLOG_IF(FATAL, !args) << "CommandLineToArgvW failed on command line: "
<< command_line;
InitFromArgv(num_args, args);
LocalFree(args);
}
#endif

View File

@ -1,178 +0,0 @@
// 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.
// This class works with command lines: building and parsing.
// Arguments with prefixes ('--', '-', and on Windows, '/') are switches.
// Switches will precede all other arguments without switch prefixes.
// Switches can optionally have values, delimited by '=', e.g., "-switch=value".
// An argument of "--" will terminate switch parsing during initialization,
// interpreting subsequent tokens as non-switch arguments, regardless of prefix.
// There is a singleton read-only CommandLine that represents the command line
// that the current process was started with. It must be initialized in main().
#ifndef BASE_COMMAND_LINE_H_
#define BASE_COMMAND_LINE_H_
#include <stddef.h>
#include <map>
#include <string>
#include <vector>
#include "base/base_export.h"
#include "build/build_config.h"
namespace base {
class FilePath;
}
class BASE_EXPORT CommandLine {
public:
#if defined(OS_WIN)
// The native command line string type.
typedef std::wstring StringType;
#elif defined(OS_POSIX)
typedef std::string StringType;
#endif
typedef StringType::value_type CharType;
typedef std::vector<StringType> StringVector;
typedef std::map<std::string, StringType> SwitchMap;
// A constructor for CommandLines that only carry switches and arguments.
enum NoProgram { NO_PROGRAM };
explicit CommandLine(NoProgram no_program);
// Construct a new command line with |program| as argv[0].
explicit CommandLine(const base::FilePath& program);
// Construct a new command line from an argument list.
CommandLine(int argc, const CharType* const* argv);
explicit CommandLine(const StringVector& argv);
~CommandLine();
// Initialize the current process CommandLine singleton. On Windows, ignores
// its arguments (we instead parse GetCommandLineW() directly) because we
// don't trust the CRT's parsing of the command line, but it still must be
// called to set up the command line. Returns false if initialization has
// already occurred, and true otherwise. Only the caller receiving a 'true'
// return value should take responsibility for calling Reset.
static bool Init(int argc, const char* const* argv);
// Destroys the current process CommandLine singleton. This is necessary if
// you want to reset the base library to its initial state (for example, in an
// outer library that needs to be able to terminate, and be re-initialized).
// If Init is called only once, as in main(), Reset() is not necessary.
static void Reset();
// Get the singleton CommandLine representing the current process's
// command line. Note: returned value is mutable, but not thread safe;
// only mutate if you know what you're doing!
static CommandLine* ForCurrentProcess();
// Returns true if the CommandLine has been initialized for the given process.
static bool InitializedForCurrentProcess();
#if defined(OS_WIN)
static CommandLine FromString(const std::wstring& command_line);
#endif
// Initialize from an argv vector.
void InitFromArgv(int argc, const CharType* const* argv);
void InitFromArgv(const StringVector& argv);
// Constructs and returns the represented command line string.
// CAUTION! This should be avoided on POSIX because quoting behavior is
// unclear.
StringType GetCommandLineString() const;
// Constructs and returns the represented arguments string.
// CAUTION! This should be avoided on POSIX because quoting behavior is
// unclear.
StringType GetArgumentsString() const;
// Returns the original command line string as a vector of strings.
const StringVector& argv() const { return argv_; }
// Get and Set the program part of the command line string (the first item).
base::FilePath GetProgram() const;
void SetProgram(const base::FilePath& program);
// Returns true if this command line contains the given switch.
// (Switch names are case-insensitive).
bool HasSwitch(const std::string& switch_string) const;
// Returns the value associated with the given switch. If the switch has no
// value or isn't present, this method returns the empty string.
std::string GetSwitchValueASCII(const std::string& switch_string) const;
base::FilePath GetSwitchValuePath(const std::string& switch_string) const;
StringType GetSwitchValueNative(const std::string& switch_string) const;
// Get a copy of all switches, along with their values.
const SwitchMap& GetSwitches() const { return switches_; }
// Append a switch [with optional value] to the command line.
// Note: Switches will precede arguments regardless of appending order.
void AppendSwitch(const std::string& switch_string);
void AppendSwitchPath(const std::string& switch_string,
const base::FilePath& path);
void AppendSwitchNative(const std::string& switch_string,
const StringType& value);
void AppendSwitchASCII(const std::string& switch_string,
const std::string& value);
// Copy a set of switches (and any values) from another command line.
// Commonly used when launching a subprocess.
void CopySwitchesFrom(const CommandLine& source,
const char* const switches[],
size_t count);
// Get the remaining arguments to the command.
StringVector GetArgs() const;
// Append an argument to the command line. Note that the argument is quoted
// properly such that it is interpreted as one argument to the target command.
// AppendArg is primarily for ASCII; non-ASCII input is interpreted as UTF-8.
// Note: Switches will precede arguments regardless of appending order.
void AppendArg(const std::string& value);
void AppendArgPath(const base::FilePath& value);
void AppendArgNative(const StringType& value);
// Append the switches and arguments from another command line to this one.
// If |include_program| is true, include |other|'s program as well.
void AppendArguments(const CommandLine& other, bool include_program);
// Insert a command before the current command.
// Common for debuggers, like "valgrind" or "gdb --args".
void PrependWrapper(const StringType& wrapper);
#if defined(OS_WIN)
// Initialize by parsing the given command line string.
// The program name is assumed to be the first item in the string.
void ParseFromString(const std::wstring& command_line);
#endif
private:
// Disallow default constructor; a program name must be explicitly specified.
CommandLine();
// Allow the copy constructor. A common pattern is to copy of the current
// process's command line and then add some flags to it. For example:
// CommandLine cl(*CommandLine::ForCurrentProcess());
// cl.AppendSwitch(...);
// The singleton CommandLine representing the current process's command line.
static CommandLine* current_process_commandline_;
// The argv array: { program, [(--|-|/)switch[=value]]*, [--], [argument]* }
StringVector argv_;
// Parsed-out switch keys and values.
SwitchMap switches_;
// The index after the program and switches, any arguments start here.
size_t begin_args_;
};
#endif // BASE_COMMAND_LINE_H_

View File

@ -1,37 +0,0 @@
// 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.
#ifndef BASE_CRITICAL_CLOSURE_H_
#define BASE_CRITICAL_CLOSURE_H_
#include "base/callback.h"
namespace base {
// Returns a closure that will continue to run for a period of time when the
// application goes to the background if possible on platforms where
// applications don't execute while backgrounded, otherwise the original task is
// returned.
//
// Example:
// file_message_loop_proxy_->PostTask(
// FROM_HERE,
// MakeCriticalClosure(base::Bind(&WriteToDiskTask, path_, data)));
//
// Note new closures might be posted in this closure. If the new closures need
// background running time, |MakeCriticalClosure| should be applied on them
// before posting.
#if defined(OS_IOS)
base::Closure MakeCriticalClosure(const base::Closure& closure);
#else
inline base::Closure MakeCriticalClosure(const base::Closure& closure) {
// No-op for platforms where the application does not need to acquire
// background time for closures to finish when it goes into the background.
return closure;
}
#endif // !defined(OS_IOS)
} // namespace base
#endif // BASE_CRITICAL_CLOSURE_H_

View File

@ -1,90 +0,0 @@
// Copyright (c) 2011 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.
#ifndef BASE_ENVIRONMENT_H_
#define BASE_ENVIRONMENT_H_
#include <map>
#include <string>
#include "base/base_export.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string16.h"
#include "build/build_config.h"
namespace base {
namespace env_vars {
#if defined(OS_POSIX)
BASE_EXPORT extern const char kHome[];
#endif
} // namespace env_vars
class BASE_EXPORT Environment {
public:
virtual ~Environment();
// Static factory method that returns the implementation that provide the
// appropriate platform-specific instance.
static Environment* Create();
// Gets an environment variable's value and stores it in |result|.
// Returns false if the key is unset.
virtual bool GetVar(const char* variable_name, std::string* result) = 0;
// Syntactic sugar for GetVar(variable_name, NULL);
virtual bool HasVar(const char* variable_name);
// Returns true on success, otherwise returns false.
virtual bool SetVar(const char* variable_name,
const std::string& new_value) = 0;
// Returns true on success, otherwise returns false.
virtual bool UnSetVar(const char* variable_name) = 0;
};
#if defined(OS_WIN)
typedef string16 NativeEnvironmentString;
typedef std::map<NativeEnvironmentString, NativeEnvironmentString>
EnvironmentMap;
// Returns a modified environment vector constructed from the given environment
// and the list of changes given in |changes|. Each key in the environment is
// matched against the first element of the pairs. In the event of a match, the
// value is replaced by the second of the pair, unless the second is empty, in
// which case the key-value is removed.
//
// This Windows version takes and returns a Windows-style environment block
// which is a concatenated list of null-terminated 16-bit strings. The end is
// marked by a double-null terminator. The size of the returned string will
// include the terminators.
BASE_EXPORT string16 AlterEnvironment(const wchar_t* env,
const EnvironmentMap& changes);
#elif defined(OS_POSIX)
typedef std::string NativeEnvironmentString;
typedef std::map<NativeEnvironmentString, NativeEnvironmentString>
EnvironmentMap;
// See general comments for the Windows version above.
//
// This Posix version takes and returns a Posix-style environment block, which
// is a null-terminated list of pointers to null-terminated strings. The
// returned array will have appended to it the storage for the array itself so
// there is only one pointer to manage, but this means that you can't copy the
// array without keeping the original around.
BASE_EXPORT scoped_ptr<char*[]> AlterEnvironment(
const char* const* env,
const EnvironmentMap& changes);
#endif
} // namespace base
#endif // BASE_ENVIRONMENT_H_

View File

@ -1,264 +0,0 @@
// 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 "base/file_util.h"
#if defined(OS_WIN)
#include <io.h>
#endif
#include <stdio.h>
#include <fstream>
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
namespace base {
namespace {
const FilePath::CharType kExtensionSeparator = FILE_PATH_LITERAL('.');
// The maximum number of 'uniquified' files we will try to create.
// This is used when the filename we're trying to download is already in use,
// so we create a new unique filename by appending " (nnn)" before the
// extension, where 1 <= nnn <= kMaxUniqueFiles.
// Also used by code that cleans up said files.
static const int kMaxUniqueFiles = 100;
} // namespace
bool g_bug108724_debug = false;
int64 ComputeDirectorySize(const FilePath& root_path) {
int64 running_size = 0;
FileEnumerator file_iter(root_path, true, FileEnumerator::FILES);
while (!file_iter.Next().empty())
running_size += file_iter.GetInfo().GetSize();
return running_size;
}
bool Move(const FilePath& from_path, const FilePath& to_path) {
if (from_path.ReferencesParent() || to_path.ReferencesParent())
return false;
return internal::MoveUnsafe(from_path, to_path);
}
bool CopyFile(const FilePath& from_path, const FilePath& to_path) {
if (from_path.ReferencesParent() || to_path.ReferencesParent())
return false;
return internal::CopyFileUnsafe(from_path, to_path);
}
bool ContentsEqual(const FilePath& filename1, const FilePath& filename2) {
// We open the file in binary format even if they are text files because
// we are just comparing that bytes are exactly same in both files and not
// doing anything smart with text formatting.
std::ifstream file1(filename1.value().c_str(),
std::ios::in | std::ios::binary);
std::ifstream file2(filename2.value().c_str(),
std::ios::in | std::ios::binary);
// Even if both files aren't openable (and thus, in some sense, "equal"),
// any unusable file yields a result of "false".
if (!file1.is_open() || !file2.is_open())
return false;
const int BUFFER_SIZE = 2056;
char buffer1[BUFFER_SIZE], buffer2[BUFFER_SIZE];
do {
file1.read(buffer1, BUFFER_SIZE);
file2.read(buffer2, BUFFER_SIZE);
if ((file1.eof() != file2.eof()) ||
(file1.gcount() != file2.gcount()) ||
(memcmp(buffer1, buffer2, file1.gcount()))) {
file1.close();
file2.close();
return false;
}
} while (!file1.eof() || !file2.eof());
file1.close();
file2.close();
return true;
}
bool TextContentsEqual(const FilePath& filename1, const FilePath& filename2) {
std::ifstream file1(filename1.value().c_str(), std::ios::in);
std::ifstream file2(filename2.value().c_str(), std::ios::in);
// Even if both files aren't openable (and thus, in some sense, "equal"),
// any unusable file yields a result of "false".
if (!file1.is_open() || !file2.is_open())
return false;
do {
std::string line1, line2;
getline(file1, line1);
getline(file2, line2);
// Check for mismatched EOF states, or any error state.
if ((file1.eof() != file2.eof()) ||
file1.bad() || file2.bad()) {
return false;
}
// Trim all '\r' and '\n' characters from the end of the line.
std::string::size_type end1 = line1.find_last_not_of("\r\n");
if (end1 == std::string::npos)
line1.clear();
else if (end1 + 1 < line1.length())
line1.erase(end1 + 1);
std::string::size_type end2 = line2.find_last_not_of("\r\n");
if (end2 == std::string::npos)
line2.clear();
else if (end2 + 1 < line2.length())
line2.erase(end2 + 1);
if (line1 != line2)
return false;
} while (!file1.eof() || !file2.eof());
return true;
}
bool ReadFileToString(const FilePath& path, std::string* contents) {
if (path.ReferencesParent())
return false;
FILE* file = file_util::OpenFile(path, "rb");
if (!file) {
return false;
}
char buf[1 << 16];
size_t len;
while ((len = fread(buf, 1, sizeof(buf), file)) > 0) {
if (contents)
contents->append(buf, len);
}
file_util::CloseFile(file);
return true;
}
} // namespace base
// -----------------------------------------------------------------------------
namespace file_util {
using base::FileEnumerator;
using base::FilePath;
using base::kExtensionSeparator;
using base::kMaxUniqueFiles;
bool IsDirectoryEmpty(const FilePath& dir_path) {
FileEnumerator files(dir_path, false,
FileEnumerator::FILES | FileEnumerator::DIRECTORIES);
if (files.Next().empty())
return true;
return false;
}
FILE* CreateAndOpenTemporaryFile(FilePath* path) {
FilePath directory;
if (!GetTempDir(&directory))
return NULL;
return CreateAndOpenTemporaryFileInDir(directory, path);
}
bool CreateDirectory(const base::FilePath& full_path) {
return CreateDirectoryAndGetError(full_path, NULL);
}
bool GetFileSize(const FilePath& file_path, int64* file_size) {
base::PlatformFileInfo info;
if (!GetFileInfo(file_path, &info))
return false;
*file_size = info.size;
return true;
}
bool TouchFile(const FilePath& path,
const base::Time& last_accessed,
const base::Time& last_modified) {
int flags = base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE_ATTRIBUTES;
#if defined(OS_WIN)
// On Windows, FILE_FLAG_BACKUP_SEMANTICS is needed to open a directory.
if (DirectoryExists(path))
flags |= base::PLATFORM_FILE_BACKUP_SEMANTICS;
#endif // OS_WIN
const base::PlatformFile file =
base::CreatePlatformFile(path, flags, NULL, NULL);
if (file != base::kInvalidPlatformFileValue) {
bool result = base::TouchPlatformFile(file, last_accessed, last_modified);
base::ClosePlatformFile(file);
return result;
}
return false;
}
bool SetLastModifiedTime(const FilePath& path,
const base::Time& last_modified) {
return TouchFile(path, last_modified, last_modified);
}
bool CloseFile(FILE* file) {
if (file == NULL)
return true;
return fclose(file) == 0;
}
bool TruncateFile(FILE* file) {
if (file == NULL)
return false;
long current_offset = ftell(file);
if (current_offset == -1)
return false;
#if defined(OS_WIN)
int fd = _fileno(file);
if (_chsize(fd, current_offset) != 0)
return false;
#else
int fd = fileno(file);
if (ftruncate(fd, current_offset) != 0)
return false;
#endif
return true;
}
int GetUniquePathNumber(
const FilePath& path,
const FilePath::StringType& suffix) {
bool have_suffix = !suffix.empty();
if (!PathExists(path) &&
(!have_suffix || !PathExists(FilePath(path.value() + suffix)))) {
return 0;
}
FilePath new_path;
for (int count = 1; count <= kMaxUniqueFiles; ++count) {
new_path =
path.InsertBeforeExtensionASCII(base::StringPrintf(" (%d)", count));
if (!PathExists(new_path) &&
(!have_suffix || !PathExists(FilePath(new_path.value() + suffix)))) {
return count;
}
}
return -1;
}
} // namespace file_util

View File

@ -1,87 +0,0 @@
// Copyright (c) 2011 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.
#ifndef BASE_FILE_VERSION_INFO_H__
#define BASE_FILE_VERSION_INFO_H__
#include "build/build_config.h"
#if defined(OS_WIN)
#include <windows.h>
// http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx
extern "C" IMAGE_DOS_HEADER __ImageBase;
#endif // OS_WIN
#include <string>
#include "base/base_export.h"
#include "base/strings/string16.h"
namespace base {
class FilePath;
}
// Provides an interface for accessing the version information for a file. This
// is the information you access when you select a file in the Windows Explorer,
// right-click select Properties, then click the Version tab, and on the Mac
// when you select a file in the Finder and do a Get Info.
//
// This list of properties is straight out of Win32's VerQueryValue
// <http://msdn.microsoft.com/en-us/library/ms647464.aspx> and the Mac
// version returns values from the Info.plist as appropriate. TODO(avi): make
// this a less-obvious Windows-ism.
class FileVersionInfo {
public:
virtual ~FileVersionInfo() {}
#if defined(OS_WIN) || defined(OS_MACOSX)
// Creates a FileVersionInfo for the specified path. Returns NULL if something
// goes wrong (typically the file does not exit or cannot be opened). The
// returned object should be deleted when you are done with it.
BASE_EXPORT static FileVersionInfo* CreateFileVersionInfo(
const base::FilePath& file_path);
#endif // OS_WIN || OS_MACOSX
#if defined(OS_WIN)
// Creates a FileVersionInfo for the specified module. Returns NULL in case
// of error. The returned object should be deleted when you are done with it.
BASE_EXPORT static FileVersionInfo* CreateFileVersionInfoForModule(
HMODULE module);
// Creates a FileVersionInfo for the current module. Returns NULL in case
// of error. The returned object should be deleted when you are done with it.
// This function should be inlined so that the "current module" is evaluated
// correctly, instead of being the module that contains base.
__forceinline static FileVersionInfo*
CreateFileVersionInfoForCurrentModule() {
HMODULE module = reinterpret_cast<HMODULE>(&__ImageBase);
return CreateFileVersionInfoForModule(module);
}
#else
// Creates a FileVersionInfo for the current module. Returns NULL in case
// of error. The returned object should be deleted when you are done with it.
BASE_EXPORT static FileVersionInfo* CreateFileVersionInfoForCurrentModule();
#endif // OS_WIN
// Accessors to the different version properties.
// Returns an empty string if the property is not found.
virtual string16 company_name() = 0;
virtual string16 company_short_name() = 0;
virtual string16 product_name() = 0;
virtual string16 product_short_name() = 0;
virtual string16 internal_name() = 0;
virtual string16 product_version() = 0;
virtual string16 private_build() = 0;
virtual string16 special_build() = 0;
virtual string16 comments() = 0;
virtual string16 original_filename() = 0;
virtual string16 file_description() = 0;
virtual string16 file_version() = 0;
virtual string16 legal_copyright() = 0;
virtual string16 legal_trademarks() = 0;
virtual string16 last_change() = 0;
virtual bool is_official_build() = 0;
};
#endif // BASE_FILE_VERSION_INFO_H__

View File

@ -1,62 +0,0 @@
// Copyright (c) 2011 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.
#ifndef BASE_FILE_VERSION_INFO_WIN_H_
#define BASE_FILE_VERSION_INFO_WIN_H_
#include <string>
#include "base/base_export.h"
#include "base/basictypes.h"
#include "base/file_version_info.h"
#include "base/memory/scoped_ptr.h"
struct tagVS_FIXEDFILEINFO;
typedef tagVS_FIXEDFILEINFO VS_FIXEDFILEINFO;
class FileVersionInfoWin : public FileVersionInfo {
public:
BASE_EXPORT FileVersionInfoWin(void* data, int language, int code_page);
BASE_EXPORT ~FileVersionInfoWin();
// Accessors to the different version properties.
// Returns an empty string if the property is not found.
virtual string16 company_name() OVERRIDE;
virtual string16 company_short_name() OVERRIDE;
virtual string16 product_name() OVERRIDE;
virtual string16 product_short_name() OVERRIDE;
virtual string16 internal_name() OVERRIDE;
virtual string16 product_version() OVERRIDE;
virtual string16 private_build() OVERRIDE;
virtual string16 special_build() OVERRIDE;
virtual string16 comments() OVERRIDE;
virtual string16 original_filename() OVERRIDE;
virtual string16 file_description() OVERRIDE;
virtual string16 file_version() OVERRIDE;
virtual string16 legal_copyright() OVERRIDE;
virtual string16 legal_trademarks() OVERRIDE;
virtual string16 last_change() OVERRIDE;
virtual bool is_official_build() OVERRIDE;
// Lets you access other properties not covered above.
BASE_EXPORT bool GetValue(const wchar_t* name, std::wstring* value);
// Similar to GetValue but returns a wstring (empty string if the property
// does not exist).
BASE_EXPORT std::wstring GetStringValue(const wchar_t* name);
// Get the fixed file info if it exists. Otherwise NULL
VS_FIXEDFILEINFO* fixed_file_info() { return fixed_file_info_; }
private:
scoped_ptr_malloc<char> data_;
int language_;
int code_page_;
// This is a pointer into the data_ if it exists. Otherwise NULL.
VS_FIXEDFILEINFO* fixed_file_info_;
DISALLOW_COPY_AND_ASSIGN(FileVersionInfoWin);
};
#endif // BASE_FILE_VERSION_INFO_WIN_H_

View File

@ -1,73 +0,0 @@
// Copyright (c) 2009 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.
#ifndef BASE_FORMAT_MACROS_H_
#define BASE_FORMAT_MACROS_H_
// This file defines the format macros for some integer types.
// To print a 64-bit value in a portable way:
// int64_t value;
// printf("xyz:%" PRId64, value);
// The "d" in the macro corresponds to %d; you can also use PRIu64 etc.
//
// For wide strings, prepend "Wide" to the macro:
// int64_t value;
// StringPrintf(L"xyz: %" WidePRId64, value);
//
// To print a size_t value in a portable way:
// size_t size;
// printf("xyz: %" PRIuS, size);
// The "u" in the macro corresponds to %u, and S is for "size".
#include "build/build_config.h"
#if defined(OS_POSIX)
#if (defined(_INTTYPES_H) || defined(_INTTYPES_H_)) && !defined(PRId64)
#error "inttypes.h has already been included before this header file, but "
#error "without __STDC_FORMAT_MACROS defined."
#endif
#if !defined(__STDC_FORMAT_MACROS)
#define __STDC_FORMAT_MACROS
#endif
#include <inttypes.h>
// GCC will concatenate wide and narrow strings correctly, so nothing needs to
// be done here.
#define WidePRId64 PRId64
#define WidePRIu64 PRIu64
#define WidePRIx64 PRIx64
#if !defined(PRIuS)
#define PRIuS "zu"
#endif
#else // OS_WIN
#if !defined(PRId64)
#define PRId64 "I64d"
#endif
#if !defined(PRIu64)
#define PRIu64 "I64u"
#endif
#if !defined(PRIx64)
#define PRIx64 "I64x"
#endif
#define WidePRId64 L"I64d"
#define WidePRIu64 L"I64u"
#define WidePRIx64 L"I64x"
#if !defined(PRIuS)
#define PRIuS "Iu"
#endif
#endif
#endif // BASE_FORMAT_MACROS_H_

View File

@ -1,866 +0,0 @@
// 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 "base/logging.h"
#if defined(OS_WIN)
#include <io.h>
#include <windows.h>
typedef HANDLE FileHandle;
typedef HANDLE MutexHandle;
// Windows warns on using write(). It prefers _write().
#define write(fd, buf, count) _write(fd, buf, static_cast<unsigned int>(count))
// Windows doesn't define STDERR_FILENO. Define it here.
#define STDERR_FILENO 2
#elif defined(OS_MACOSX)
#include <mach/mach.h>
#include <mach/mach_time.h>
#include <mach-o/dyld.h>
#elif defined(OS_POSIX)
#if defined(OS_NACL)
#include <sys/time.h> // timespec doesn't seem to be in <time.h>
#else
#include <sys/syscall.h>
#endif
#include <time.h>
#endif
#if defined(OS_POSIX)
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define MAX_PATH PATH_MAX
typedef FILE* FileHandle;
typedef pthread_mutex_t* MutexHandle;
#endif
#include <algorithm>
#include <cstring>
#include <ctime>
#include <iomanip>
#include <ostream>
#include "base/base_switches.h"
#include "base/command_line.h"
#include "base/debug/alias.h"
#include "base/debug/debugger.h"
#include "base/debug/stack_trace.h"
#include "base/posix/eintr_wrapper.h"
#include "base/strings/string_piece.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/lock_impl.h"
#include "base/threading/platform_thread.h"
#include "base/vlog.h"
#if defined(OS_POSIX)
#include "base/safe_strerror_posix.h"
#endif
#if defined(OS_ANDROID)
#include <android/log.h>
#endif
namespace logging {
DcheckState g_dcheck_state = DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS;
DcheckState get_dcheck_state() {
return g_dcheck_state;
}
void set_dcheck_state(DcheckState state) {
g_dcheck_state = state;
}
namespace {
VlogInfo* g_vlog_info = NULL;
VlogInfo* g_vlog_info_prev = NULL;
const char* const log_severity_names[LOG_NUM_SEVERITIES] = {
"INFO", "WARNING", "ERROR", "ERROR_REPORT", "FATAL" };
int min_log_level = 0;
LoggingDestination logging_destination = LOG_DEFAULT;
// For LOG_ERROR and above, always print to stderr.
const int kAlwaysPrintErrorLevel = LOG_ERROR;
// Which log file to use? This is initialized by InitLogging or
// will be lazily initialized to the default value when it is
// first needed.
#if defined(OS_WIN)
typedef std::wstring PathString;
#else
typedef std::string PathString;
#endif
PathString* log_file_name = NULL;
// this file is lazily opened and the handle may be NULL
FileHandle log_file = NULL;
// what should be prepended to each message?
bool log_process_id = false;
bool log_thread_id = false;
bool log_timestamp = true;
bool log_tickcount = false;
// Should we pop up fatal debug messages in a dialog?
bool show_error_dialogs = false;
// An assert handler override specified by the client to be called instead of
// the debug message dialog and process termination.
LogAssertHandlerFunction log_assert_handler = NULL;
// An report handler override specified by the client to be called instead of
// the debug message dialog.
LogReportHandlerFunction log_report_handler = NULL;
// A log message handler that gets notified of every log message we process.
LogMessageHandlerFunction log_message_handler = NULL;
// Helper functions to wrap platform differences.
int32 CurrentProcessId() {
#if defined(OS_WIN)
return GetCurrentProcessId();
#elif defined(OS_POSIX)
return getpid();
#endif
}
uint64 TickCount() {
#if defined(OS_WIN)
return GetTickCount();
#elif defined(OS_MACOSX)
return mach_absolute_time();
#elif defined(OS_NACL)
// NaCl sadly does not have _POSIX_TIMERS enabled in sys/features.h
// So we have to use clock() for now.
return clock();
#elif defined(OS_POSIX)
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
uint64 absolute_micro =
static_cast<int64>(ts.tv_sec) * 1000000 +
static_cast<int64>(ts.tv_nsec) / 1000;
return absolute_micro;
#endif
}
void DeleteFilePath(const PathString& log_name) {
#if defined(OS_WIN)
DeleteFile(log_name.c_str());
#elif defined (OS_NACL)
// Do nothing; unlink() isn't supported on NaCl.
#else
unlink(log_name.c_str());
#endif
}
PathString GetDefaultLogFile() {
#if defined(OS_WIN)
// On Windows we use the same path as the exe.
wchar_t module_name[MAX_PATH];
GetModuleFileName(NULL, module_name, MAX_PATH);
PathString log_file = module_name;
PathString::size_type last_backslash =
log_file.rfind('\\', log_file.size());
if (last_backslash != PathString::npos)
log_file.erase(last_backslash + 1);
log_file += L"debug.log";
return log_file;
#elif defined(OS_POSIX)
// On other platforms we just use the current directory.
return PathString("debug.log");
#endif
}
// This class acts as a wrapper for locking the logging files.
// LoggingLock::Init() should be called from the main thread before any logging
// is done. Then whenever logging, be sure to have a local LoggingLock
// instance on the stack. This will ensure that the lock is unlocked upon
// exiting the frame.
// LoggingLocks can not be nested.
class LoggingLock {
public:
LoggingLock() {
LockLogging();
}
~LoggingLock() {
UnlockLogging();
}
static void Init(LogLockingState lock_log, const PathChar* new_log_file) {
if (initialized)
return;
lock_log_file = lock_log;
if (lock_log_file == LOCK_LOG_FILE) {
#if defined(OS_WIN)
if (!log_mutex) {
std::wstring safe_name;
if (new_log_file)
safe_name = new_log_file;
else
safe_name = GetDefaultLogFile();
// \ is not a legal character in mutex names so we replace \ with /
std::replace(safe_name.begin(), safe_name.end(), '\\', '/');
std::wstring t(L"Global\\");
t.append(safe_name);
log_mutex = ::CreateMutex(NULL, FALSE, t.c_str());
if (log_mutex == NULL) {
#if DEBUG
// Keep the error code for debugging
int error = GetLastError(); // NOLINT
base::debug::BreakDebugger();
#endif
// Return nicely without putting initialized to true.
return;
}
}
#endif
} else {
log_lock = new base::internal::LockImpl();
}
initialized = true;
}
private:
static void LockLogging() {
if (lock_log_file == LOCK_LOG_FILE) {
#if defined(OS_WIN)
::WaitForSingleObject(log_mutex, INFINITE);
// WaitForSingleObject could have returned WAIT_ABANDONED. We don't
// abort the process here. UI tests might be crashy sometimes,
// and aborting the test binary only makes the problem worse.
// We also don't use LOG macros because that might lead to an infinite
// loop. For more info see http://crbug.com/18028.
#elif defined(OS_POSIX)
pthread_mutex_lock(&log_mutex);
#endif
} else {
// use the lock
log_lock->Lock();
}
}
static void UnlockLogging() {
if (lock_log_file == LOCK_LOG_FILE) {
#if defined(OS_WIN)
ReleaseMutex(log_mutex);
#elif defined(OS_POSIX)
pthread_mutex_unlock(&log_mutex);
#endif
} else {
log_lock->Unlock();
}
}
// The lock is used if log file locking is false. It helps us avoid problems
// with multiple threads writing to the log file at the same time. Use
// LockImpl directly instead of using Lock, because Lock makes logging calls.
static base::internal::LockImpl* log_lock;
// When we don't use a lock, we are using a global mutex. We need to do this
// because LockFileEx is not thread safe.
#if defined(OS_WIN)
static MutexHandle log_mutex;
#elif defined(OS_POSIX)
static pthread_mutex_t log_mutex;
#endif
static bool initialized;
static LogLockingState lock_log_file;
};
// static
bool LoggingLock::initialized = false;
// static
base::internal::LockImpl* LoggingLock::log_lock = NULL;
// static
LogLockingState LoggingLock::lock_log_file = LOCK_LOG_FILE;
#if defined(OS_WIN)
// static
MutexHandle LoggingLock::log_mutex = NULL;
#elif defined(OS_POSIX)
pthread_mutex_t LoggingLock::log_mutex = PTHREAD_MUTEX_INITIALIZER;
#endif
// Called by logging functions to ensure that debug_file is initialized
// and can be used for writing. Returns false if the file could not be
// initialized. debug_file will be NULL in this case.
bool InitializeLogFileHandle() {
if (log_file)
return true;
if (!log_file_name) {
// Nobody has called InitLogging to specify a debug log file, so here we
// initialize the log file name to a default.
log_file_name = new PathString(GetDefaultLogFile());
}
if ((logging_destination & LOG_TO_FILE) != 0) {
#if defined(OS_WIN)
log_file = CreateFile(log_file_name->c_str(), GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (log_file == INVALID_HANDLE_VALUE || log_file == NULL) {
// try the current directory
log_file = CreateFile(L".\\debug.log", GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (log_file == INVALID_HANDLE_VALUE || log_file == NULL) {
log_file = NULL;
return false;
}
}
SetFilePointer(log_file, 0, 0, FILE_END);
#elif defined(OS_POSIX)
log_file = fopen(log_file_name->c_str(), "a");
if (log_file == NULL)
return false;
#endif
}
return true;
}
void CloseFile(FileHandle log) {
#if defined(OS_WIN)
CloseHandle(log);
#else
fclose(log);
#endif
}
void CloseLogFileUnlocked() {
if (!log_file)
return;
CloseFile(log_file);
log_file = NULL;
}
} // namespace
LoggingSettings::LoggingSettings()
: logging_dest(LOG_DEFAULT),
log_file(NULL),
lock_log(LOCK_LOG_FILE),
delete_old(APPEND_TO_OLD_LOG_FILE),
dcheck_state(DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS) {}
bool BaseInitLoggingImpl(const LoggingSettings& settings) {
#if defined(OS_NACL)
// Can log only to the system debug log.
CHECK_EQ(settings.logging_dest & ~LOG_TO_SYSTEM_DEBUG_LOG, 0);
#endif
g_dcheck_state = settings.dcheck_state;
CommandLine* command_line = CommandLine::ForCurrentProcess();
// Don't bother initializing g_vlog_info unless we use one of the
// vlog switches.
if (command_line->HasSwitch(switches::kV) ||
command_line->HasSwitch(switches::kVModule)) {
// NOTE: If g_vlog_info has already been initialized, it might be in use
// by another thread. Don't delete the old VLogInfo, just create a second
// one. We keep track of both to avoid memory leak warnings.
CHECK(!g_vlog_info_prev);
g_vlog_info_prev = g_vlog_info;
g_vlog_info =
new VlogInfo(command_line->GetSwitchValueASCII(switches::kV),
command_line->GetSwitchValueASCII(switches::kVModule),
&min_log_level);
}
logging_destination = settings.logging_dest;
// ignore file options unless logging to file is set.
if ((logging_destination & LOG_TO_FILE) == 0)
return true;
LoggingLock::Init(settings.lock_log, settings.log_file);
LoggingLock logging_lock;
// Calling InitLogging twice or after some log call has already opened the
// default log file will re-initialize to the new options.
CloseLogFileUnlocked();
if (!log_file_name)
log_file_name = new PathString();
*log_file_name = settings.log_file;
if (settings.delete_old == DELETE_OLD_LOG_FILE)
DeleteFilePath(*log_file_name);
return InitializeLogFileHandle();
}
void SetMinLogLevel(int level) {
min_log_level = std::min(LOG_ERROR_REPORT, level);
}
int GetMinLogLevel() {
return min_log_level;
}
int GetVlogVerbosity() {
return std::max(-1, LOG_INFO - GetMinLogLevel());
}
int GetVlogLevelHelper(const char* file, size_t N) {
DCHECK_GT(N, 0U);
// Note: g_vlog_info may change on a different thread during startup
// (but will always be valid or NULL).
VlogInfo* vlog_info = g_vlog_info;
return vlog_info ?
vlog_info->GetVlogLevel(base::StringPiece(file, N - 1)) :
GetVlogVerbosity();
}
void SetLogItems(bool enable_process_id, bool enable_thread_id,
bool enable_timestamp, bool enable_tickcount) {
log_process_id = enable_process_id;
log_thread_id = enable_thread_id;
log_timestamp = enable_timestamp;
log_tickcount = enable_tickcount;
}
void SetShowErrorDialogs(bool enable_dialogs) {
show_error_dialogs = enable_dialogs;
}
void SetLogAssertHandler(LogAssertHandlerFunction handler) {
log_assert_handler = handler;
}
void SetLogReportHandler(LogReportHandlerFunction handler) {
log_report_handler = handler;
}
void SetLogMessageHandler(LogMessageHandlerFunction handler) {
log_message_handler = handler;
}
LogMessageHandlerFunction GetLogMessageHandler() {
return log_message_handler;
}
// MSVC doesn't like complex extern templates and DLLs.
#if !defined(COMPILER_MSVC)
// Explicit instantiations for commonly used comparisons.
template std::string* MakeCheckOpString<int, int>(
const int&, const int&, const char* names);
template std::string* MakeCheckOpString<unsigned long, unsigned long>(
const unsigned long&, const unsigned long&, const char* names);
template std::string* MakeCheckOpString<unsigned long, unsigned int>(
const unsigned long&, const unsigned int&, const char* names);
template std::string* MakeCheckOpString<unsigned int, unsigned long>(
const unsigned int&, const unsigned long&, const char* names);
template std::string* MakeCheckOpString<std::string, std::string>(
const std::string&, const std::string&, const char* name);
#endif
// Displays a message box to the user with the error message in it.
// Used for fatal messages, where we close the app simultaneously.
// This is for developers only; we don't use this in circumstances
// (like release builds) where users could see it, since users don't
// understand these messages anyway.
void DisplayDebugMessageInDialog(const std::string& str) {
if (str.empty())
return;
if (!show_error_dialogs)
return;
#if defined(OS_WIN)
// For Windows programs, it's possible that the message loop is
// messed up on a fatal error, and creating a MessageBox will cause
// that message loop to be run. Instead, we try to spawn another
// process that displays its command line. We look for "Debug
// Message.exe" in the same directory as the application. If it
// exists, we use it, otherwise, we use a regular message box.
wchar_t prog_name[MAX_PATH];
GetModuleFileNameW(NULL, prog_name, MAX_PATH);
wchar_t* backslash = wcsrchr(prog_name, '\\');
if (backslash)
backslash[1] = 0;
wcscat_s(prog_name, MAX_PATH, L"debug_message.exe");
std::wstring cmdline = UTF8ToWide(str);
if (cmdline.empty())
return;
STARTUPINFO startup_info;
memset(&startup_info, 0, sizeof(startup_info));
startup_info.cb = sizeof(startup_info);
PROCESS_INFORMATION process_info;
if (CreateProcessW(prog_name, &cmdline[0], NULL, NULL, false, 0, NULL,
NULL, &startup_info, &process_info)) {
WaitForSingleObject(process_info.hProcess, INFINITE);
CloseHandle(process_info.hThread);
CloseHandle(process_info.hProcess);
} else {
// debug process broken, let's just do a message box
MessageBoxW(NULL, &cmdline[0], L"Fatal error",
MB_OK | MB_ICONHAND | MB_TOPMOST);
}
#else
// We intentionally don't implement a dialog on other platforms.
// You can just look at stderr.
#endif
}
#if defined(OS_WIN)
LogMessage::SaveLastError::SaveLastError() : last_error_(::GetLastError()) {
}
LogMessage::SaveLastError::~SaveLastError() {
::SetLastError(last_error_);
}
#endif // defined(OS_WIN)
LogMessage::LogMessage(const char* file, int line, LogSeverity severity,
int ctr)
: severity_(severity), file_(file), line_(line) {
Init(file, line);
}
LogMessage::LogMessage(const char* file, int line)
: severity_(LOG_INFO), file_(file), line_(line) {
Init(file, line);
}
LogMessage::LogMessage(const char* file, int line, LogSeverity severity)
: severity_(severity), file_(file), line_(line) {
Init(file, line);
}
LogMessage::LogMessage(const char* file, int line, std::string* result)
: severity_(LOG_FATAL), file_(file), line_(line) {
Init(file, line);
stream_ << "Check failed: " << *result;
delete result;
}
LogMessage::LogMessage(const char* file, int line, LogSeverity severity,
std::string* result)
: severity_(severity), file_(file), line_(line) {
Init(file, line);
stream_ << "Check failed: " << *result;
delete result;
}
LogMessage::~LogMessage() {
#if !defined(NDEBUG) && !defined(OS_NACL)
if (severity_ == LOG_FATAL) {
// Include a stack trace on a fatal.
base::debug::StackTrace trace;
stream_ << std::endl; // Newline to separate from log message.
trace.OutputToStream(&stream_);
}
#endif
stream_ << std::endl;
std::string str_newline(stream_.str());
// Give any log message handler first dibs on the message.
if (log_message_handler &&
log_message_handler(severity_, file_, line_,
message_start_, str_newline)) {
// The handler took care of it, no further processing.
return;
}
if ((logging_destination & LOG_TO_SYSTEM_DEBUG_LOG) != 0) {
#if defined(OS_WIN)
OutputDebugStringA(str_newline.c_str());
#elif defined(OS_ANDROID)
android_LogPriority priority =
(severity_ < 0) ? ANDROID_LOG_VERBOSE : ANDROID_LOG_UNKNOWN;
switch (severity_) {
case LOG_INFO:
priority = ANDROID_LOG_INFO;
break;
case LOG_WARNING:
priority = ANDROID_LOG_WARN;
break;
case LOG_ERROR:
case LOG_ERROR_REPORT:
priority = ANDROID_LOG_ERROR;
break;
case LOG_FATAL:
priority = ANDROID_LOG_FATAL;
break;
}
__android_log_write(priority, "chromium", str_newline.c_str());
#endif
fprintf(stderr, "%s", str_newline.c_str());
fflush(stderr);
} else if (severity_ >= kAlwaysPrintErrorLevel) {
// When we're only outputting to a log file, above a certain log level, we
// should still output to stderr so that we can better detect and diagnose
// problems with unit tests, especially on the buildbots.
fprintf(stderr, "%s", str_newline.c_str());
fflush(stderr);
}
// write to log file
if ((logging_destination & LOG_TO_FILE) != 0) {
// We can have multiple threads and/or processes, so try to prevent them
// from clobbering each other's writes.
// If the client app did not call InitLogging, and the lock has not
// been created do it now. We do this on demand, but if two threads try
// to do this at the same time, there will be a race condition to create
// the lock. This is why InitLogging should be called from the main
// thread at the beginning of execution.
LoggingLock::Init(LOCK_LOG_FILE, NULL);
LoggingLock logging_lock;
if (InitializeLogFileHandle()) {
#if defined(OS_WIN)
SetFilePointer(log_file, 0, 0, SEEK_END);
DWORD num_written;
WriteFile(log_file,
static_cast<const void*>(str_newline.c_str()),
static_cast<DWORD>(str_newline.length()),
&num_written,
NULL);
#else
fprintf(log_file, "%s", str_newline.c_str());
fflush(log_file);
#endif
}
}
if (severity_ == LOG_FATAL) {
// Ensure the first characters of the string are on the stack so they
// are contained in minidumps for diagnostic purposes.
char str_stack[1024];
str_newline.copy(str_stack, arraysize(str_stack));
base::debug::Alias(str_stack);
// display a message or break into the debugger on a fatal error
if (base::debug::BeingDebugged()) {
base::debug::BreakDebugger();
} else {
if (log_assert_handler) {
// make a copy of the string for the handler out of paranoia
log_assert_handler(std::string(stream_.str()));
} else {
// Don't use the string with the newline, get a fresh version to send to
// the debug message process. We also don't display assertions to the
// user in release mode. The enduser can't do anything with this
// information, and displaying message boxes when the application is
// hosed can cause additional problems.
#ifndef NDEBUG
DisplayDebugMessageInDialog(stream_.str());
#endif
// Crash the process to generate a dump.
base::debug::BreakDebugger();
}
}
} else if (severity_ == LOG_ERROR_REPORT) {
// We are here only if the user runs with --enable-dcheck in release mode.
if (log_report_handler) {
log_report_handler(std::string(stream_.str()));
} else {
DisplayDebugMessageInDialog(stream_.str());
}
}
}
// writes the common header info to the stream
void LogMessage::Init(const char* file, int line) {
base::StringPiece filename(file);
size_t last_slash_pos = filename.find_last_of("\\/");
if (last_slash_pos != base::StringPiece::npos)
filename.remove_prefix(last_slash_pos + 1);
// TODO(darin): It might be nice if the columns were fixed width.
stream_ << '[';
if (log_process_id)
stream_ << CurrentProcessId() << ':';
if (log_thread_id)
stream_ << base::PlatformThread::CurrentId() << ':';
if (log_timestamp) {
time_t t = time(NULL);
struct tm local_time = {0};
#if _MSC_VER >= 1400
localtime_s(&local_time, &t);
#else
localtime_r(&t, &local_time);
#endif
struct tm* tm_time = &local_time;
stream_ << std::setfill('0')
<< std::setw(2) << 1 + tm_time->tm_mon
<< std::setw(2) << tm_time->tm_mday
<< '/'
<< std::setw(2) << tm_time->tm_hour
<< std::setw(2) << tm_time->tm_min
<< std::setw(2) << tm_time->tm_sec
<< ':';
}
if (log_tickcount)
stream_ << TickCount() << ':';
if (severity_ >= 0)
stream_ << log_severity_names[severity_];
else
stream_ << "VERBOSE" << -severity_;
stream_ << ":" << filename << "(" << line << ")] ";
message_start_ = stream_.tellp();
}
#if defined(OS_WIN)
// This has already been defined in the header, but defining it again as DWORD
// ensures that the type used in the header is equivalent to DWORD. If not,
// the redefinition is a compile error.
typedef DWORD SystemErrorCode;
#endif
SystemErrorCode GetLastSystemErrorCode() {
#if defined(OS_WIN)
return ::GetLastError();
#elif defined(OS_POSIX)
return errno;
#else
#error Not implemented
#endif
}
#if defined(OS_WIN)
Win32ErrorLogMessage::Win32ErrorLogMessage(const char* file,
int line,
LogSeverity severity,
SystemErrorCode err,
const char* module)
: err_(err),
module_(module),
log_message_(file, line, severity) {
}
Win32ErrorLogMessage::Win32ErrorLogMessage(const char* file,
int line,
LogSeverity severity,
SystemErrorCode err)
: err_(err),
module_(NULL),
log_message_(file, line, severity) {
}
Win32ErrorLogMessage::~Win32ErrorLogMessage() {
const int error_message_buffer_size = 256;
char msgbuf[error_message_buffer_size];
DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
HMODULE hmod;
if (module_) {
hmod = GetModuleHandleA(module_);
if (hmod) {
flags |= FORMAT_MESSAGE_FROM_HMODULE;
} else {
// This makes a nested Win32ErrorLogMessage. It will have module_ of NULL
// so it will not call GetModuleHandle, so recursive errors are
// impossible.
DPLOG(WARNING) << "Couldn't open module " << module_
<< " for error message query";
}
} else {
hmod = NULL;
}
DWORD len = FormatMessageA(flags,
hmod,
err_,
0,
msgbuf,
sizeof(msgbuf) / sizeof(msgbuf[0]),
NULL);
if (len) {
while ((len > 0) &&
isspace(static_cast<unsigned char>(msgbuf[len - 1]))) {
msgbuf[--len] = 0;
}
stream() << ": " << msgbuf;
} else {
stream() << ": Error " << GetLastError() << " while retrieving error "
<< err_;
}
// We're about to crash (CHECK). Put |err_| on the stack (by placing it in a
// field) and use Alias in hopes that it makes it into crash dumps.
DWORD last_error = err_;
base::debug::Alias(&last_error);
}
#elif defined(OS_POSIX)
ErrnoLogMessage::ErrnoLogMessage(const char* file,
int line,
LogSeverity severity,
SystemErrorCode err)
: err_(err),
log_message_(file, line, severity) {
}
ErrnoLogMessage::~ErrnoLogMessage() {
stream() << ": " << safe_strerror(err_);
}
#endif // OS_WIN
void CloseLogFile() {
LoggingLock logging_lock;
CloseLogFileUnlocked();
}
void RawLog(int level, const char* message) {
if (level >= min_log_level) {
size_t bytes_written = 0;
const size_t message_len = strlen(message);
int rv;
while (bytes_written < message_len) {
rv = HANDLE_EINTR(
write(STDERR_FILENO, message + bytes_written,
message_len - bytes_written));
if (rv < 0) {
// Give up, nothing we can do now.
break;
}
bytes_written += rv;
}
if (message_len > 0 && message[message_len - 1] != '\n') {
do {
rv = HANDLE_EINTR(write(STDERR_FILENO, "\n", 1));
if (rv < 0) {
// Give up, nothing we can do now.
break;
}
} while (rv != 1);
}
}
if (level == LOG_FATAL)
base::debug::BreakDebugger();
}
// This was defined at the beginning of this file.
#undef write
#if defined(OS_WIN)
std::wstring GetLogFileFullPath() {
if (log_file_name)
return *log_file_name;
return std::wstring();
}
#endif
} // namespace logging
std::ostream& operator<<(std::ostream& out, const wchar_t* wstr) {
return out << WideToUTF8(std::wstring(wstr));
}

View File

@ -1,139 +0,0 @@
// Copyright (c) 2011 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 "base/logging_win.h"
#include "base/memory/singleton.h"
#include <initguid.h> // NOLINT
namespace logging {
using base::win::EtwEventLevel;
using base::win::EtwMofEvent;
DEFINE_GUID(kLogEventId,
0x7fe69228, 0x633e, 0x4f06, 0x80, 0xc1, 0x52, 0x7f, 0xea, 0x23, 0xe3, 0xa7);
LogEventProvider::LogEventProvider() : old_log_level_(LOG_NONE) {
}
LogEventProvider* LogEventProvider::GetInstance() {
return Singleton<LogEventProvider,
StaticMemorySingletonTraits<LogEventProvider> >::get();
}
bool LogEventProvider::LogMessage(logging::LogSeverity severity,
const char* file, int line, size_t message_start,
const std::string& message) {
EtwEventLevel level = TRACE_LEVEL_NONE;
// Convert the log severity to the most appropriate ETW trace level.
if (severity >= 0) {
switch (severity) {
case LOG_INFO:
level = TRACE_LEVEL_INFORMATION;
break;
case LOG_WARNING:
level = TRACE_LEVEL_WARNING;
break;
case LOG_ERROR:
case LOG_ERROR_REPORT:
level = TRACE_LEVEL_ERROR;
break;
case LOG_FATAL:
level = TRACE_LEVEL_FATAL;
break;
}
} else { // severity < 0 is VLOG verbosity levels.
level = TRACE_LEVEL_INFORMATION - severity;
}
// Bail if we're not logging, not at that level,
// or if we're post-atexit handling.
LogEventProvider* provider = LogEventProvider::GetInstance();
if (provider == NULL || level > provider->enable_level())
return false;
// And now log the event.
if (provider->enable_flags() & ENABLE_LOG_MESSAGE_ONLY) {
EtwMofEvent<1> event(kLogEventId, LOG_MESSAGE, level);
event.SetField(0, message.length() + 1 - message_start,
message.c_str() + message_start);
provider->Log(event.get());
} else {
const size_t kMaxBacktraceDepth = 32;
void* backtrace[kMaxBacktraceDepth];
DWORD depth = 0;
// Capture a stack trace if one is requested.
// requested per our enable flags.
if (provider->enable_flags() & ENABLE_STACK_TRACE_CAPTURE)
depth = CaptureStackBackTrace(2, kMaxBacktraceDepth, backtrace, NULL);
EtwMofEvent<5> event(kLogEventId, LOG_MESSAGE_FULL, level);
if (file == NULL)
file = "";
// Add the stack trace.
event.SetField(0, sizeof(depth), &depth);
event.SetField(1, sizeof(backtrace[0]) * depth, &backtrace);
// The line.
event.SetField(2, sizeof(line), &line);
// The file.
event.SetField(3, strlen(file) + 1, file);
// And finally the message.
event.SetField(4, message.length() + 1 - message_start,
message.c_str() + message_start);
provider->Log(event.get());
}
// Don't increase verbosity in other log destinations.
if (severity < provider->old_log_level_)
return true;
return false;
}
void LogEventProvider::Initialize(const GUID& provider_name) {
LogEventProvider* provider = LogEventProvider::GetInstance();
provider->set_provider_name(provider_name);
provider->Register();
// Register our message handler with logging.
SetLogMessageHandler(LogMessage);
}
void LogEventProvider::Uninitialize() {
LogEventProvider::GetInstance()->Unregister();
}
void LogEventProvider::OnEventsEnabled() {
// Grab the old log level so we can restore it later.
old_log_level_ = GetMinLogLevel();
// Convert the new trace level to a logging severity
// and enable logging at that level.
EtwEventLevel level = enable_level();
if (level == TRACE_LEVEL_NONE || level == TRACE_LEVEL_FATAL) {
SetMinLogLevel(LOG_FATAL);
} else if (level == TRACE_LEVEL_ERROR) {
SetMinLogLevel(LOG_ERROR);
} else if (level == TRACE_LEVEL_WARNING) {
SetMinLogLevel(LOG_WARNING);
} else if (level == TRACE_LEVEL_INFORMATION) {
SetMinLogLevel(LOG_INFO);
} else if (level >= TRACE_LEVEL_VERBOSE) {
// Above INFO, we enable verbose levels with negative severities.
SetMinLogLevel(TRACE_LEVEL_INFORMATION - level);
}
}
void LogEventProvider::OnEventsDisabled() {
// Restore the old log level.
SetMinLogLevel(old_log_level_);
}
} // namespace logging

View File

@ -1,80 +0,0 @@
// 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.
#ifndef BASE_LOGGING_WIN_H_
#define BASE_LOGGING_WIN_H_
#include <string>
#include "base/base_export.h"
#include "base/basictypes.h"
#include "base/win/event_trace_provider.h"
#include "base/logging.h"
template <typename Type>
struct StaticMemorySingletonTraits;
namespace logging {
// Event ID for the log messages we generate.
EXTERN_C BASE_EXPORT const GUID kLogEventId;
// Feature enable mask for LogEventProvider.
enum LogEnableMask {
// If this bit is set in our provider enable mask, we will include
// a stack trace with every log message.
ENABLE_STACK_TRACE_CAPTURE = 0x0001,
// If this bit is set in our provider enable mask, the provider will log
// a LOG message with only the textual content of the message, and no
// stack trace.
ENABLE_LOG_MESSAGE_ONLY = 0x0002,
};
// The message types our log event provider generates.
// ETW likes user message types to start at 10.
enum LogMessageTypes {
// A textual only log message, contains a zero-terminated string.
LOG_MESSAGE = 10,
// A message with a stack trace, followed by the zero-terminated
// message text.
LOG_MESSAGE_WITH_STACKTRACE = 11,
// A message with:
// a stack trace,
// the line number as a four byte integer,
// the file as a zero terminated UTF8 string,
// the zero-terminated UTF8 message text.
LOG_MESSAGE_FULL = 12,
};
// Trace provider class to drive log control and transport
// with Event Tracing for Windows.
class BASE_EXPORT LogEventProvider : public base::win::EtwTraceProvider {
public:
static LogEventProvider* GetInstance();
static bool LogMessage(logging::LogSeverity severity, const char* file,
int line, size_t message_start, const std::string& str);
static void Initialize(const GUID& provider_name);
static void Uninitialize();
protected:
// Overridden to manipulate the log level on ETW control callbacks.
virtual void OnEventsEnabled();
virtual void OnEventsDisabled();
private:
LogEventProvider();
// The log severity prior to OnEventsEnabled,
// restored in OnEventsDisabled.
logging::LogSeverity old_log_level_;
friend struct StaticMemorySingletonTraits<LogEventProvider>;
DISALLOW_COPY_AND_ASSIGN(LogEventProvider);
};
} // namespace logging
#endif // BASE_LOGGING_WIN_H_

View File

@ -1,217 +0,0 @@
// Copyright (c) 2011 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.
#ifndef BASE_OBSERVER_LIST_H__
#define BASE_OBSERVER_LIST_H__
#include <algorithm>
#include <limits>
#include <vector>
#include "base/basictypes.h"
#include "base/logging.h"
#include "base/memory/weak_ptr.h"
///////////////////////////////////////////////////////////////////////////////
//
// OVERVIEW:
//
// A container for a list of observers. Unlike a normal STL vector or list,
// this container can be modified during iteration without invalidating the
// iterator. So, it safely handles the case of an observer removing itself
// or other observers from the list while observers are being notified.
//
// TYPICAL USAGE:
//
// class MyWidget {
// public:
// ...
//
// class Observer {
// public:
// virtual void OnFoo(MyWidget* w) = 0;
// virtual void OnBar(MyWidget* w, int x, int y) = 0;
// };
//
// void AddObserver(Observer* obs) {
// observer_list_.AddObserver(obs);
// }
//
// void RemoveObserver(Observer* obs) {
// observer_list_.RemoveObserver(obs);
// }
//
// void NotifyFoo() {
// FOR_EACH_OBSERVER(Observer, observer_list_, OnFoo(this));
// }
//
// void NotifyBar(int x, int y) {
// FOR_EACH_OBSERVER(Observer, observer_list_, OnBar(this, x, y));
// }
//
// private:
// ObserverList<Observer> observer_list_;
// };
//
//
///////////////////////////////////////////////////////////////////////////////
template <typename ObserverType>
class ObserverListThreadSafe;
template <class ObserverType>
class ObserverListBase
: public base::SupportsWeakPtr<ObserverListBase<ObserverType> > {
public:
// Enumeration of which observers are notified.
enum NotificationType {
// Specifies that any observers added during notification are notified.
// This is the default type if non type is provided to the constructor.
NOTIFY_ALL,
// Specifies that observers added while sending out notification are not
// notified.
NOTIFY_EXISTING_ONLY
};
// An iterator class that can be used to access the list of observers. See
// also the FOR_EACH_OBSERVER macro defined below.
class Iterator {
public:
Iterator(ObserverListBase<ObserverType>& list)
: list_(list.AsWeakPtr()),
index_(0),
max_index_(list.type_ == NOTIFY_ALL ?
std::numeric_limits<size_t>::max() :
list.observers_.size()) {
++list_->notify_depth_;
}
~Iterator() {
if (list_.get() && --list_->notify_depth_ == 0)
list_->Compact();
}
ObserverType* GetNext() {
if (!list_.get())
return NULL;
ListType& observers = list_->observers_;
// Advance if the current element is null
size_t max_index = std::min(max_index_, observers.size());
while (index_ < max_index && !observers[index_])
++index_;
return index_ < max_index ? observers[index_++] : NULL;
}
private:
base::WeakPtr<ObserverListBase<ObserverType> > list_;
size_t index_;
size_t max_index_;
};
ObserverListBase() : notify_depth_(0), type_(NOTIFY_ALL) {}
explicit ObserverListBase(NotificationType type)
: notify_depth_(0), type_(type) {}
// Add an observer to the list. An observer should not be added to
// the same list more than once.
void AddObserver(ObserverType* obs) {
if (std::find(observers_.begin(), observers_.end(), obs)
!= observers_.end()) {
NOTREACHED() << "Observers can only be added once!";
return;
}
observers_.push_back(obs);
}
// Remove an observer from the list if it is in the list.
void RemoveObserver(ObserverType* obs) {
typename ListType::iterator it =
std::find(observers_.begin(), observers_.end(), obs);
if (it != observers_.end()) {
if (notify_depth_) {
*it = 0;
} else {
observers_.erase(it);
}
}
}
bool HasObserver(ObserverType* observer) const {
for (size_t i = 0; i < observers_.size(); ++i) {
if (observers_[i] == observer)
return true;
}
return false;
}
void Clear() {
if (notify_depth_) {
for (typename ListType::iterator it = observers_.begin();
it != observers_.end(); ++it) {
*it = 0;
}
} else {
observers_.clear();
}
}
protected:
size_t size() const { return observers_.size(); }
void Compact() {
observers_.erase(
std::remove(observers_.begin(), observers_.end(),
static_cast<ObserverType*>(NULL)), observers_.end());
}
private:
friend class ObserverListThreadSafe<ObserverType>;
typedef std::vector<ObserverType*> ListType;
ListType observers_;
int notify_depth_;
NotificationType type_;
friend class ObserverListBase::Iterator;
DISALLOW_COPY_AND_ASSIGN(ObserverListBase);
};
template <class ObserverType, bool check_empty = false>
class ObserverList : public ObserverListBase<ObserverType> {
public:
typedef typename ObserverListBase<ObserverType>::NotificationType
NotificationType;
ObserverList() {}
explicit ObserverList(NotificationType type)
: ObserverListBase<ObserverType>(type) {}
~ObserverList() {
// When check_empty is true, assert that the list is empty on destruction.
if (check_empty) {
ObserverListBase<ObserverType>::Compact();
DCHECK_EQ(ObserverListBase<ObserverType>::size(), 0U);
}
}
bool might_have_observers() const {
return ObserverListBase<ObserverType>::size() != 0;
}
};
#define FOR_EACH_OBSERVER(ObserverType, observer_list, func) \
do { \
if ((observer_list).might_have_observers()) { \
ObserverListBase<ObserverType>::Iterator \
it_inside_observer_macro(observer_list); \
ObserverType* obs; \
while ((obs = it_inside_observer_macro.GetNext()) != NULL) \
obs->func; \
} \
} while (0)
#endif // BASE_OBSERVER_LIST_H__

View File

@ -1,295 +0,0 @@
// 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.
#ifndef BASE_OBSERVER_LIST_THREADSAFE_H_
#define BASE_OBSERVER_LIST_THREADSAFE_H_
#include <algorithm>
#include <map>
#include "base/basictypes.h"
#include "base/bind.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/message_loop/message_loop.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/observer_list.h"
#include "base/stl_util.h"
#include "base/threading/platform_thread.h"
///////////////////////////////////////////////////////////////////////////////
//
// OVERVIEW:
//
// A thread-safe container for a list of observers.
// This is similar to the observer_list (see observer_list.h), but it
// is more robust for multi-threaded situations.
//
// The following use cases are supported:
// * Observers can register for notifications from any thread.
// Callbacks to the observer will occur on the same thread where
// the observer initially called AddObserver() from.
// * Any thread may trigger a notification via Notify().
// * Observers can remove themselves from the observer list inside
// of a callback.
// * If one thread is notifying observers concurrently with an observer
// removing itself from the observer list, the notifications will
// be silently dropped.
//
// The drawback of the threadsafe observer list is that notifications
// are not as real-time as the non-threadsafe version of this class.
// Notifications will always be done via PostTask() to another thread,
// whereas with the non-thread-safe observer_list, notifications happen
// synchronously and immediately.
//
// IMPLEMENTATION NOTES
// The ObserverListThreadSafe maintains an ObserverList for each thread
// which uses the ThreadSafeObserver. When Notifying the observers,
// we simply call PostTask to each registered thread, and then each thread
// will notify its regular ObserverList.
//
///////////////////////////////////////////////////////////////////////////////
// Forward declaration for ObserverListThreadSafeTraits.
template <class ObserverType>
class ObserverListThreadSafe;
// An UnboundMethod is a wrapper for a method where the actual object is
// provided at Run dispatch time.
template <class T, class Method, class Params>
class UnboundMethod {
public:
UnboundMethod(Method m, const Params& p) : m_(m), p_(p) {
COMPILE_ASSERT(
(base::internal::ParamsUseScopedRefptrCorrectly<Params>::value),
badunboundmethodparams);
}
void Run(T* obj) const {
DispatchToMethod(obj, m_, p_);
}
private:
Method m_;
Params p_;
};
// This class is used to work around VS2005 not accepting:
//
// friend class
// base::RefCountedThreadSafe<ObserverListThreadSafe<ObserverType> >;
//
// Instead of friending the class, we could friend the actual function
// which calls delete. However, this ends up being
// RefCountedThreadSafe::DeleteInternal(), which is private. So we
// define our own templated traits class so we can friend it.
template <class T>
struct ObserverListThreadSafeTraits {
static void Destruct(const ObserverListThreadSafe<T>* x) {
delete x;
}
};
template <class ObserverType>
class ObserverListThreadSafe
: public base::RefCountedThreadSafe<
ObserverListThreadSafe<ObserverType>,
ObserverListThreadSafeTraits<ObserverType> > {
public:
typedef typename ObserverList<ObserverType>::NotificationType
NotificationType;
ObserverListThreadSafe()
: type_(ObserverListBase<ObserverType>::NOTIFY_ALL) {}
explicit ObserverListThreadSafe(NotificationType type) : type_(type) {}
// Add an observer to the list. An observer should not be added to
// the same list more than once.
void AddObserver(ObserverType* obs) {
// If there is not a current MessageLoop, it is impossible to notify on it,
// so do not add the observer.
if (!base::MessageLoop::current())
return;
ObserverList<ObserverType>* list = NULL;
base::PlatformThreadId thread_id = base::PlatformThread::CurrentId();
{
base::AutoLock lock(list_lock_);
if (observer_lists_.find(thread_id) == observer_lists_.end())
observer_lists_[thread_id] = new ObserverListContext(type_);
list = &(observer_lists_[thread_id]->list);
}
list->AddObserver(obs);
}
// Remove an observer from the list if it is in the list.
// If there are pending notifications in-transit to the observer, they will
// be aborted.
// If the observer to be removed is in the list, RemoveObserver MUST
// be called from the same thread which called AddObserver.
void RemoveObserver(ObserverType* obs) {
ObserverListContext* context = NULL;
ObserverList<ObserverType>* list = NULL;
base::PlatformThreadId thread_id = base::PlatformThread::CurrentId();
{
base::AutoLock lock(list_lock_);
typename ObserversListMap::iterator it = observer_lists_.find(thread_id);
if (it == observer_lists_.end()) {
// This will happen if we try to remove an observer on a thread
// we never added an observer for.
return;
}
context = it->second;
list = &context->list;
// If we're about to remove the last observer from the list,
// then we can remove this observer_list entirely.
if (list->HasObserver(obs) && list->size() == 1)
observer_lists_.erase(it);
}
list->RemoveObserver(obs);
// If RemoveObserver is called from a notification, the size will be
// nonzero. Instead of deleting here, the NotifyWrapper will delete
// when it finishes iterating.
if (list->size() == 0)
delete context;
}
// Verifies that the list is currently empty (i.e. there are no observers).
void AssertEmpty() const {
base::AutoLock lock(list_lock_);
DCHECK(observer_lists_.empty());
}
// Notify methods.
// Make a thread-safe callback to each Observer in the list.
// Note, these calls are effectively asynchronous. You cannot assume
// that at the completion of the Notify call that all Observers have
// been Notified. The notification may still be pending delivery.
template <class Method>
void Notify(Method m) {
UnboundMethod<ObserverType, Method, Tuple0> method(m, MakeTuple());
Notify<Method, Tuple0>(method);
}
template <class Method, class A>
void Notify(Method m, const A& a) {
UnboundMethod<ObserverType, Method, Tuple1<A> > method(m, MakeTuple(a));
Notify<Method, Tuple1<A> >(method);
}
template <class Method, class A, class B>
void Notify(Method m, const A& a, const B& b) {
UnboundMethod<ObserverType, Method, Tuple2<A, B> > method(
m, MakeTuple(a, b));
Notify<Method, Tuple2<A, B> >(method);
}
template <class Method, class A, class B, class C>
void Notify(Method m, const A& a, const B& b, const C& c) {
UnboundMethod<ObserverType, Method, Tuple3<A, B, C> > method(
m, MakeTuple(a, b, c));
Notify<Method, Tuple3<A, B, C> >(method);
}
template <class Method, class A, class B, class C, class D>
void Notify(Method m, const A& a, const B& b, const C& c, const D& d) {
UnboundMethod<ObserverType, Method, Tuple4<A, B, C, D> > method(
m, MakeTuple(a, b, c, d));
Notify<Method, Tuple4<A, B, C, D> >(method);
}
// TODO(mbelshe): Add more wrappers for Notify() with more arguments.
private:
// See comment above ObserverListThreadSafeTraits' definition.
friend struct ObserverListThreadSafeTraits<ObserverType>;
struct ObserverListContext {
explicit ObserverListContext(NotificationType type)
: loop(base::MessageLoopProxy::current()),
list(type) {
}
scoped_refptr<base::MessageLoopProxy> loop;
ObserverList<ObserverType> list;
DISALLOW_COPY_AND_ASSIGN(ObserverListContext);
};
~ObserverListThreadSafe() {
STLDeleteValues(&observer_lists_);
}
template <class Method, class Params>
void Notify(const UnboundMethod<ObserverType, Method, Params>& method) {
base::AutoLock lock(list_lock_);
typename ObserversListMap::iterator it;
for (it = observer_lists_.begin(); it != observer_lists_.end(); ++it) {
ObserverListContext* context = (*it).second;
context->loop->PostTask(
FROM_HERE,
base::Bind(&ObserverListThreadSafe<ObserverType>::
template NotifyWrapper<Method, Params>, this, context, method));
}
}
// Wrapper which is called to fire the notifications for each thread's
// ObserverList. This function MUST be called on the thread which owns
// the unsafe ObserverList.
template <class Method, class Params>
void NotifyWrapper(ObserverListContext* context,
const UnboundMethod<ObserverType, Method, Params>& method) {
// Check that this list still needs notifications.
{
base::AutoLock lock(list_lock_);
typename ObserversListMap::iterator it =
observer_lists_.find(base::PlatformThread::CurrentId());
// The ObserverList could have been removed already. In fact, it could
// have been removed and then re-added! If the master list's loop
// does not match this one, then we do not need to finish this
// notification.
if (it == observer_lists_.end() || it->second != context)
return;
}
{
typename ObserverList<ObserverType>::Iterator it(context->list);
ObserverType* obs;
while ((obs = it.GetNext()) != NULL)
method.Run(obs);
}
// If there are no more observers on the list, we can now delete it.
if (context->list.size() == 0) {
{
base::AutoLock lock(list_lock_);
// Remove |list| if it's not already removed.
// This can happen if multiple observers got removed in a notification.
// See http://crbug.com/55725.
typename ObserversListMap::iterator it =
observer_lists_.find(base::PlatformThread::CurrentId());
if (it != observer_lists_.end() && it->second == context)
observer_lists_.erase(it);
}
delete context;
}
}
// Key by PlatformThreadId because in tests, clients can attempt to remove
// observers without a MessageLoop. If this were keyed by MessageLoop, that
// operation would be silently ignored, leaving garbage in the ObserverList.
typedef std::map<base::PlatformThreadId, ObserverListContext*>
ObserversListMap;
mutable base::Lock list_lock_; // Protects the observer_lists_.
ObserversListMap observer_lists_;
const NotificationType type_;
DISALLOW_COPY_AND_ASSIGN(ObserverListThreadSafe);
};
#endif // BASE_OBSERVER_LIST_THREADSAFE_H_

View File

@ -1,16 +0,0 @@
// 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.
#ifndef BASE_OS_COMPAT_NACL_H_
#define BASE_OS_COMPAT_NACL_H_
#include <sys/types.h>
#if !defined (__GLIBC__)
// NaCl has no timegm().
extern "C" time_t timegm(struct tm* const t);
#endif // !defined (__GLIBC__)
#endif // BASE_OS_COMPAT_NACL_H_

View File

@ -1,336 +0,0 @@
// 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 "base/path_service.h"
#if defined(OS_WIN)
#include <windows.h>
#include <shellapi.h>
#include <shlobj.h>
#endif
#include "base/containers/hash_tables.h"
#include "base/file_util.h"
#include "base/files/file_path.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/synchronization/lock.h"
using base::FilePath;
using base::MakeAbsoluteFilePath;
namespace base {
bool PathProvider(int key, FilePath* result);
#if defined(OS_WIN)
bool PathProviderWin(int key, FilePath* result);
#elif defined(OS_MACOSX)
bool PathProviderMac(int key, FilePath* result);
#elif defined(OS_ANDROID)
bool PathProviderAndroid(int key, FilePath* result);
#elif defined(OS_POSIX)
// PathProviderPosix is the default path provider on POSIX OSes other than
// Mac and Android.
bool PathProviderPosix(int key, FilePath* result);
#endif
}
namespace {
typedef base::hash_map<int, FilePath> PathMap;
// We keep a linked list of providers. In a debug build we ensure that no two
// providers claim overlapping keys.
struct Provider {
PathService::ProviderFunc func;
struct Provider* next;
#ifndef NDEBUG
int key_start;
int key_end;
#endif
bool is_static;
};
Provider base_provider = {
base::PathProvider,
NULL,
#ifndef NDEBUG
base::PATH_START,
base::PATH_END,
#endif
true
};
#if defined(OS_WIN)
Provider base_provider_win = {
base::PathProviderWin,
&base_provider,
#ifndef NDEBUG
base::PATH_WIN_START,
base::PATH_WIN_END,
#endif
true
};
#endif
#if defined(OS_MACOSX)
Provider base_provider_mac = {
base::PathProviderMac,
&base_provider,
#ifndef NDEBUG
base::PATH_MAC_START,
base::PATH_MAC_END,
#endif
true
};
#endif
#if defined(OS_ANDROID)
Provider base_provider_android = {
base::PathProviderAndroid,
&base_provider,
#ifndef NDEBUG
base::PATH_ANDROID_START,
base::PATH_ANDROID_END,
#endif
true
};
#endif
#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
Provider base_provider_posix = {
base::PathProviderPosix,
&base_provider,
#ifndef NDEBUG
base::PATH_POSIX_START,
base::PATH_POSIX_END,
#endif
true
};
#endif
struct PathData {
base::Lock lock;
PathMap cache; // Cache mappings from path key to path value.
PathMap overrides; // Track path overrides.
Provider* providers; // Linked list of path service providers.
bool cache_disabled; // Don't use cache if true;
PathData() : cache_disabled(false) {
#if defined(OS_WIN)
providers = &base_provider_win;
#elif defined(OS_MACOSX)
providers = &base_provider_mac;
#elif defined(OS_ANDROID)
providers = &base_provider_android;
#elif defined(OS_POSIX)
providers = &base_provider_posix;
#endif
}
~PathData() {
Provider* p = providers;
while (p) {
Provider* next = p->next;
if (!p->is_static)
delete p;
p = next;
}
}
};
static base::LazyInstance<PathData> g_path_data = LAZY_INSTANCE_INITIALIZER;
static PathData* GetPathData() {
return g_path_data.Pointer();
}
// Tries to find |key| in the cache. |path_data| should be locked by the caller!
bool LockedGetFromCache(int key, const PathData* path_data, FilePath* result) {
if (path_data->cache_disabled)
return false;
// check for a cached version
PathMap::const_iterator it = path_data->cache.find(key);
if (it != path_data->cache.end()) {
*result = it->second;
return true;
}
return false;
}
// Tries to find |key| in the overrides map. |path_data| should be locked by the
// caller!
bool LockedGetFromOverrides(int key, PathData* path_data, FilePath* result) {
// check for an overridden version.
PathMap::const_iterator it = path_data->overrides.find(key);
if (it != path_data->overrides.end()) {
if (!path_data->cache_disabled)
path_data->cache[key] = it->second;
*result = it->second;
return true;
}
return false;
}
} // namespace
// TODO(brettw): this function does not handle long paths (filename > MAX_PATH)
// characters). This isn't supported very well by Windows right now, so it is
// moot, but we should keep this in mind for the future.
// static
bool PathService::Get(int key, FilePath* result) {
PathData* path_data = GetPathData();
DCHECK(path_data);
DCHECK(result);
DCHECK_GE(key, base::DIR_CURRENT);
// special case the current directory because it can never be cached
if (key == base::DIR_CURRENT)
return file_util::GetCurrentDirectory(result);
Provider* provider = NULL;
{
base::AutoLock scoped_lock(path_data->lock);
if (LockedGetFromCache(key, path_data, result))
return true;
if (LockedGetFromOverrides(key, path_data, result))
return true;
// Get the beginning of the list while it is still locked.
provider = path_data->providers;
}
FilePath path;
// Iterating does not need the lock because only the list head might be
// modified on another thread.
while (provider) {
if (provider->func(key, &path))
break;
DCHECK(path.empty()) << "provider should not have modified path";
provider = provider->next;
}
if (path.empty())
return false;
if (path.ReferencesParent()) {
// Make sure path service never returns a path with ".." in it.
path = MakeAbsoluteFilePath(path);
if (path.empty())
return false;
}
*result = path;
base::AutoLock scoped_lock(path_data->lock);
if (!path_data->cache_disabled)
path_data->cache[key] = path;
return true;
}
// static
bool PathService::Override(int key, const FilePath& path) {
// Just call the full function with true for the value of |create|.
return OverrideAndCreateIfNeeded(key, path, true);
}
// static
bool PathService::OverrideAndCreateIfNeeded(int key,
const FilePath& path,
bool create) {
PathData* path_data = GetPathData();
DCHECK(path_data);
DCHECK_GT(key, base::DIR_CURRENT) << "invalid path key";
FilePath file_path = path;
// For some locations this will fail if called from inside the sandbox there-
// fore we protect this call with a flag.
if (create) {
// Make sure the directory exists. We need to do this before we translate
// this to the absolute path because on POSIX, MakeAbsoluteFilePath fails
// if called on a non-existent path.
if (!base::PathExists(file_path) &&
!file_util::CreateDirectory(file_path))
return false;
}
// We need to have an absolute path.
file_path = MakeAbsoluteFilePath(file_path);
if (file_path.empty())
return false;
base::AutoLock scoped_lock(path_data->lock);
// Clear the cache now. Some of its entries could have depended
// on the value we are overriding, and are now out of sync with reality.
path_data->cache.clear();
path_data->overrides[key] = file_path;
return true;
}
// static
bool PathService::RemoveOverride(int key) {
PathData* path_data = GetPathData();
DCHECK(path_data);
base::AutoLock scoped_lock(path_data->lock);
if (path_data->overrides.find(key) == path_data->overrides.end())
return false;
// Clear the cache now. Some of its entries could have depended on the value
// we are going to remove, and are now out of sync.
path_data->cache.clear();
path_data->overrides.erase(key);
return true;
}
// static
void PathService::RegisterProvider(ProviderFunc func, int key_start,
int key_end) {
PathData* path_data = GetPathData();
DCHECK(path_data);
DCHECK_GT(key_end, key_start);
Provider* p;
p = new Provider;
p->is_static = false;
p->func = func;
#ifndef NDEBUG
p->key_start = key_start;
p->key_end = key_end;
#endif
base::AutoLock scoped_lock(path_data->lock);
#ifndef NDEBUG
Provider *iter = path_data->providers;
while (iter) {
DCHECK(key_start >= iter->key_end || key_end <= iter->key_start) <<
"path provider collision";
iter = iter->next;
}
#endif
p->next = path_data->providers;
path_data->providers = p;
}
// static
void PathService::DisableCache() {
PathData* path_data = GetPathData();
DCHECK(path_data);
base::AutoLock scoped_lock(path_data->lock);
path_data->cache.clear();
path_data->cache_disabled = true;
}

View File

@ -1,60 +0,0 @@
// Copyright (c) 2011 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.
#ifndef PENDING_TASK_H_
#define PENDING_TASK_H_
#include <queue>
#include "base/base_export.h"
#include "base/callback.h"
#include "base/location.h"
#include "base/time/time.h"
#include "base/tracking_info.h"
namespace base {
// Contains data about a pending task. Stored in TaskQueue and DelayedTaskQueue
// for use by classes that queue and execute tasks.
struct BASE_EXPORT PendingTask : public TrackingInfo {
#if _MSC_VER >= 1700
PendingTask();
#endif
PendingTask(const tracked_objects::Location& posted_from,
const Closure& task);
PendingTask(const tracked_objects::Location& posted_from,
const Closure& task,
TimeTicks delayed_run_time,
bool nestable);
~PendingTask();
// Used to support sorting.
bool operator<(const PendingTask& other) const;
// The task to run.
Closure task;
// The site this PendingTask was posted from.
tracked_objects::Location posted_from;
// Secondary sort key for run time.
int sequence_num;
// OK to dispatch from a nested loop.
bool nestable;
};
// Wrapper around std::queue specialized for PendingTask which adds a Swap
// helper method.
class BASE_EXPORT TaskQueue : public std::queue<PendingTask> {
public:
void Swap(TaskQueue* queue);
};
// PendingTasks are sorted by their |delayed_run_time| property.
typedef std::priority_queue<base::PendingTask> DelayedTaskQueue;
} // namespace base
#endif // PENDING_TASK_H_

View File

@ -1,31 +0,0 @@
// Copyright (c) 2011 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 "base/platform_file.h"
namespace base {
PlatformFileInfo::PlatformFileInfo()
: size(0),
is_directory(false),
is_symbolic_link(false) {
}
PlatformFileInfo::~PlatformFileInfo() {}
#if !defined(OS_NACL)
PlatformFile CreatePlatformFile(const FilePath& name,
int flags,
bool* created,
PlatformFileError* error) {
if (name.ReferencesParent()) {
if (error)
*error = PLATFORM_FILE_ERROR_ACCESS_DENIED;
return kInvalidPlatformFileValue;
}
return CreatePlatformFileUnsafe(name, flags, created, error);
}
#endif
} // namespace base

View File

@ -1,44 +0,0 @@
// 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.
// This is a glue file, which allows third party code to call into our profiler
// without having to include most any functions from base.
#ifndef BASE_PROFILER_ALTERNATE_TIMER_H_
#define BASE_PROFILER_ALTERNATE_TIMER_H_
#include "base/base_export.h"
namespace tracked_objects {
enum TimeSourceType {
TIME_SOURCE_TYPE_WALL_TIME,
TIME_SOURCE_TYPE_TCMALLOC
};
// Provide type for an alternate timer function.
typedef unsigned int NowFunction();
// Environment variable name that is used to activate alternate timer profiling
// (such as using TCMalloc allocations to provide a pseudo-timer) for tasks
// instead of wall clock profiling.
BASE_EXPORT extern const char kAlternateProfilerTime[];
// Set an alternate timer function to replace the OS time function when
// profiling. Typically this is called by an allocator that is providing a
// function that indicates how much memory has been allocated on any given
// thread.
BASE_EXPORT void SetAlternateTimeSource(NowFunction* now_function,
TimeSourceType type);
// Gets the pointer to a function that was set via SetAlternateTimeSource().
// Returns NULL if no set was done prior to calling GetAlternateTimeSource.
NowFunction* GetAlternateTimeSource();
// Returns the type of the currently set time source.
BASE_EXPORT TimeSourceType GetTimeSourceType();
} // namespace tracked_objects
#endif // BASE_PROFILER_ALTERNATE_TIMER_H_

View File

@ -1,71 +0,0 @@
// 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.
#ifndef BASE_PROFILER_TRACKED_TIME_H_
#define BASE_PROFILER_TRACKED_TIME_H_
#include "base/base_export.h"
#include "base/basictypes.h"
#include "base/time/time.h"
namespace tracked_objects {
//------------------------------------------------------------------------------
// TimeTicks maintains a wasteful 64 bits of data (we need less than 32), and on
// windows, a 64 bit timer is expensive to even obtain. We use a simple
// millisecond counter for most of our time values, as well as millisecond units
// of duration between those values. This means we can only handle durations
// up to 49 days (range), or 24 days (non-negative time durations).
// We only define enough methods to service the needs of the tracking classes,
// and our interfaces are modeled after what TimeTicks and TimeDelta use (so we
// can swap them into place if we want to use the "real" classes).
class BASE_EXPORT Duration { // Similar to base::TimeDelta.
public:
Duration();
Duration& operator+=(const Duration& other);
Duration operator+(const Duration& other) const;
bool operator==(const Duration& other) const;
bool operator!=(const Duration& other) const;
bool operator>(const Duration& other) const;
static Duration FromMilliseconds(int ms);
int32 InMilliseconds() const;
private:
friend class TrackedTime;
explicit Duration(int32 duration);
// Internal time is stored directly in milliseconds.
int32 ms_;
};
class BASE_EXPORT TrackedTime { // Similar to base::TimeTicks.
public:
TrackedTime();
explicit TrackedTime(const base::TimeTicks& time);
static TrackedTime Now();
Duration operator-(const TrackedTime& other) const;
TrackedTime operator+(const Duration& other) const;
bool is_null() const;
static TrackedTime FromMilliseconds(int32 ms) { return TrackedTime(ms); }
private:
friend class Duration;
explicit TrackedTime(int32 ms);
// Internal duration is stored directly in milliseconds.
uint32 ms_;
};
} // namespace tracked_objects
#endif // BASE_PROFILER_TRACKED_TIME_H_

View File

@ -1,124 +0,0 @@
// 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.
#ifndef BASE_RUN_LOOP_H_
#define BASE_RUN_LOOP_H_
#include "base/base_export.h"
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
namespace base {
#if defined(OS_ANDROID)
class MessagePumpForUI;
#endif
#if defined(OS_IOS)
class MessagePumpUIApplication;
#endif
// Helper class to Run a nested MessageLoop. Please do not use nested
// MessageLoops in production code! If you must, use this class instead of
// calling MessageLoop::Run/Quit directly. RunLoop::Run can only be called once
// per RunLoop lifetime. Create a RunLoop on the stack and call Run/Quit to run
// a nested MessageLoop.
class BASE_EXPORT RunLoop {
public:
RunLoop();
#if !defined(OS_MACOSX) && !defined(OS_ANDROID) && \
!defined(USE_GTK_MESSAGE_PUMP)
explicit RunLoop(MessageLoop::Dispatcher* dispatcher);
#endif
~RunLoop();
#if !defined(OS_MACOSX) && !defined(OS_ANDROID) && \
!defined(USE_GTK_MESSAGE_PUMP)
void set_dispatcher(MessageLoop::Dispatcher* dispatcher) {
dispatcher_ = dispatcher;
}
#endif
// Run the current MessageLoop. This blocks until Quit is called. Before
// calling Run, be sure to grab an AsWeakPtr or the QuitClosure in order to
// stop the MessageLoop asynchronously. MessageLoop::Quit and QuitNow will
// also trigger a return from Run, but those are deprecated.
void Run();
// Run the current MessageLoop until it doesn't find any tasks or messages in
// the queue (it goes idle). WARNING: This may never return! Only use this
// when repeating tasks such as animated web pages have been shut down.
void RunUntilIdle();
bool running() const { return running_; }
// Quit an earlier call to Run(). There can be other nested RunLoops servicing
// the same task queue (MessageLoop); Quitting one RunLoop has no bearing on
// the others. Quit can be called before, during or after Run. If called
// before Run, Run will return immediately when called. Calling Quit after the
// RunLoop has already finished running has no effect.
//
// WARNING: You must NEVER assume that a call to Quit will terminate the
// targetted message loop. If a nested message loop continues running, the
// target may NEVER terminate. It is very easy to livelock (run forever) in
// such a case.
void Quit();
// Convenience method to get a closure that safely calls Quit (has no effect
// if the RunLoop instance is gone).
//
// Example:
// RunLoop run_loop;
// PostTask(run_loop.QuitClosure());
// run_loop.Run();
base::Closure QuitClosure();
private:
friend class MessageLoop;
#if defined(OS_ANDROID)
// Android doesn't support the blocking MessageLoop::Run, so it calls
// BeforeRun and AfterRun directly.
friend class base::MessagePumpForUI;
#endif
#if defined(OS_IOS)
// iOS doesn't support the blocking MessageLoop::Run, so it calls
// BeforeRun directly.
friend class base::MessagePumpUIApplication;
#endif
// Return false to abort the Run.
bool BeforeRun();
void AfterRun();
MessageLoop* loop_;
// WeakPtrFactory for QuitClosure safety.
base::WeakPtrFactory<RunLoop> weak_factory_;
// Parent RunLoop or NULL if this is the top-most RunLoop.
RunLoop* previous_run_loop_;
#if !defined(OS_MACOSX) && !defined(OS_ANDROID) && \
!defined(USE_GTK_MESSAGE_PUMP)
MessageLoop::Dispatcher* dispatcher_;
#endif
// Used to count how many nested Run() invocations are on the stack.
int run_depth_;
bool run_called_;
bool quit_called_;
bool running_;
// Used to record that QuitWhenIdle() was called on the MessageLoop, meaning
// that we should quit Run once it becomes idle.
bool quit_when_idle_received_;
DISALLOW_COPY_AND_ASSIGN(RunLoop);
};
} // namespace base
#endif // BASE_RUN_LOOP_H_

View File

@ -1,113 +0,0 @@
// 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.
#ifndef BASE_SYS_INFO_H_
#define BASE_SYS_INFO_H_
#include <string>
#include "base/base_export.h"
#include "base/basictypes.h"
#include "base/files/file_path.h"
#include "build/build_config.h"
namespace base {
class BASE_EXPORT SysInfo {
public:
// Return the number of logical processors/cores on the current machine.
static int NumberOfProcessors();
// Return the number of bytes of physical memory on the current machine.
static int64 AmountOfPhysicalMemory();
// Return the number of bytes of current available physical memory on the
// machine.
static int64 AmountOfAvailablePhysicalMemory();
// Return the number of megabytes of physical memory on the current machine.
static int AmountOfPhysicalMemoryMB() {
return static_cast<int>(AmountOfPhysicalMemory() / 1024 / 1024);
}
// Return the available disk space in bytes on the volume containing |path|,
// or -1 on failure.
static int64 AmountOfFreeDiskSpace(const FilePath& path);
// Returns system uptime in milliseconds.
static int64 Uptime();
// Returns the name of the host operating system.
static std::string OperatingSystemName();
// Returns the version of the host operating system.
static std::string OperatingSystemVersion();
// Retrieves detailed numeric values for the OS version.
// TODO(port): Implement a Linux version of this method and enable the
// corresponding unit test.
// DON'T USE THIS ON THE MAC OR WINDOWS to determine the current OS release
// for OS version-specific feature checks and workarounds. If you must use
// an OS version check instead of a feature check, use the base::mac::IsOS*
// family from base/mac/mac_util.h, or base::win::GetVersion from
// base/win/windows_version.h.
static void OperatingSystemVersionNumbers(int32* major_version,
int32* minor_version,
int32* bugfix_version);
// Returns the architecture of the running operating system.
// Exact return value may differ across platforms.
// e.g. a 32-bit x86 kernel on a 64-bit capable CPU will return "x86",
// whereas a x86-64 kernel on the same CPU will return "x86_64"
static std::string OperatingSystemArchitecture();
// Avoid using this. Use base/cpu.h to get information about the CPU instead.
// http://crbug.com/148884
// Returns the CPU model name of the system. If it can not be figured out,
// an empty string is returned.
static std::string CPUModelName();
// Return the smallest amount of memory (in bytes) which the VM system will
// allocate.
static size_t VMAllocationGranularity();
#if defined(OS_POSIX) && !defined(OS_MACOSX)
// Returns the maximum SysV shared memory segment size.
static size_t MaxSharedMemorySize();
#endif // defined(OS_POSIX) && !defined(OS_MACOSX)
#if defined(OS_CHROMEOS)
// Returns the name of the version entry we wish to look up in the
// Linux Standard Base release information file.
static std::string GetLinuxStandardBaseVersionKey();
// Parses /etc/lsb-release to get version information for Google Chrome OS.
// Declared here so it can be exposed for unit testing.
static void ParseLsbRelease(const std::string& lsb_release,
int32* major_version,
int32* minor_version,
int32* bugfix_version);
// Returns the path to the lsb-release file.
static FilePath GetLsbReleaseFilePath();
#endif // defined(OS_CHROMEOS)
#if defined(OS_ANDROID)
// Returns the Android build's codename.
static std::string GetAndroidBuildCodename();
// Returns the Android build ID.
static std::string GetAndroidBuildID();
// Returns the device's name.
static std::string GetDeviceName();
static int DalvikHeapSizeMB();
static int DalvikHeapGrowthLimitMB();
#endif // defined(OS_ANDROID)
};
} // namespace base
#endif // BASE_SYS_INFO_H_

View File

@ -1,40 +0,0 @@
// 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.
#ifndef BASE_THREAD_TASK_RUNNER_HANDLE_H_
#define BASE_THREAD_TASK_RUNNER_HANDLE_H_
#include "base/base_export.h"
#include "base/memory/ref_counted.h"
namespace base {
class SingleThreadTaskRunner;
// ThreadTaskRunnerHandle stores a reference to a thread's TaskRunner
// in thread-local storage. Callers can then retrieve the TaskRunner
// for the current thread by calling ThreadTaskRunnerHandle::Get().
// At most one TaskRunner may be bound to each thread at a time.
class BASE_EXPORT ThreadTaskRunnerHandle {
public:
// Gets the SingleThreadTaskRunner for the current thread.
static scoped_refptr<SingleThreadTaskRunner> Get();
// Returns true if the SingleThreadTaskRunner is already created for
// the current thread.
static bool IsSet();
// Binds |task_runner| to the current thread. |task_runner| must belong
// to the current thread for this to succeed.
explicit ThreadTaskRunnerHandle(
const scoped_refptr<SingleThreadTaskRunner>& task_runner);
~ThreadTaskRunnerHandle();
private:
scoped_refptr<SingleThreadTaskRunner> task_runner_;
};
} // namespace base
#endif // BASE_THREAD_TASK_RUNNER_HANDLE_H_

View File

@ -1,93 +0,0 @@
// 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.
#ifndef BASE_THREADING_THREAD_LOCAL_STORAGE_H_
#define BASE_THREADING_THREAD_LOCAL_STORAGE_H_
#include "base/base_export.h"
#include "base/basictypes.h"
#if defined(OS_POSIX)
#include <pthread.h>
#endif
namespace base {
// Wrapper for thread local storage. This class doesn't do much except provide
// an API for portability.
class BASE_EXPORT ThreadLocalStorage {
public:
// Prototype for the TLS destructor function, which can be optionally used to
// cleanup thread local storage on thread exit. 'value' is the data that is
// stored in thread local storage.
typedef void (*TLSDestructorFunc)(void* value);
// StaticSlot uses its own struct initializer-list style static
// initialization, as base's LINKER_INITIALIZED requires a constructor and on
// some compilers (notably gcc 4.4) this still ends up needing runtime
// initialization.
#define TLS_INITIALIZER {0}
// A key representing one value stored in TLS.
// Initialize like
// ThreadLocalStorage::StaticSlot my_slot = TLS_INITIALIZER;
// If you're not using a static variable, use the convenience class
// ThreadLocalStorage::Slot (below) instead.
struct BASE_EXPORT StaticSlot {
// Set up the TLS slot. Called by the constructor.
// 'destructor' is a pointer to a function to perform per-thread cleanup of
// this object. If set to NULL, no cleanup is done for this TLS slot.
// Returns false on error.
bool Initialize(TLSDestructorFunc destructor);
// Free a previously allocated TLS 'slot'.
// If a destructor was set for this slot, removes
// the destructor so that remaining threads exiting
// will not free data.
void Free();
// Get the thread-local value stored in slot 'slot'.
// Values are guaranteed to initially be zero.
void* Get() const;
// Set the thread-local value stored in slot 'slot' to
// value 'value'.
void Set(void* value);
bool initialized() const { return initialized_; }
// The internals of this struct should be considered private.
bool initialized_;
#if defined(OS_WIN)
int slot_;
#elif defined(OS_POSIX)
pthread_key_t key_;
#endif
};
// A convenience wrapper around StaticSlot with a constructor. Can be used
// as a member variable.
class BASE_EXPORT Slot : public StaticSlot {
public:
// Calls StaticSlot::Initialize().
explicit Slot(TLSDestructorFunc destructor = NULL);
private:
using StaticSlot::initialized_;
#if defined(OS_WIN)
using StaticSlot::slot_;
#elif defined(OS_POSIX)
using StaticSlot::key_;
#endif
DISALLOW_COPY_AND_ASSIGN(Slot);
};
DISALLOW_COPY_AND_ASSIGN(ThreadLocalStorage);
};
} // namespace base
#endif // BASE_THREADING_THREAD_LOCAL_STORAGE_H_

View File

@ -1,55 +0,0 @@
// 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.
// This is a simple struct with tracking information that is stored
// with a PendingTask (when message_loop is handling the task).
// Only the information that is shared with the profiler in tracked_objects
// are included in this structure.
#ifndef BASE_TRACKING_INFO_H_
#define BASE_TRACKING_INFO_H_
#include "base/base_export.h"
#include "base/profiler/tracked_time.h"
#include "base/time/time.h"
namespace tracked_objects {
class Location;
class Births;
}
namespace base {
// This structure is copied around by value.
struct BASE_EXPORT TrackingInfo {
TrackingInfo();
TrackingInfo(const tracked_objects::Location& posted_from,
base::TimeTicks delayed_run_time);
~TrackingInfo();
// To avoid conflating our stats with the delay duration in a PostDelayedTask,
// we identify such tasks, and replace their post_time with the time they
// were scheduled (requested?) to emerge from the delayed task queue. This
// means that queuing delay for such tasks will show how long they went
// unserviced, after they *could* be serviced. This is the same stat as we
// have for non-delayed tasks, and we consistently call it queuing delay.
tracked_objects::TrackedTime EffectiveTimePosted() const {
return tracked_objects::TrackedTime(
delayed_run_time.is_null() ? time_posted : delayed_run_time);
}
// Record of location and thread that the task came from.
tracked_objects::Births* birth_tally;
// Time when the related task was posted.
base::TimeTicks time_posted;
// The time when the task should be run.
base::TimeTicks delayed_run_time;
};
} // namespace base
#endif // BASE_TRACKING_INFO_H_