summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/command_line.cc417
-rw-r--r--base/command_line.h70
-rw-r--r--base/command_line_unittest.cc202
-rw-r--r--chrome/browser/browser_main_win.cc3
-rw-r--r--chrome/browser/process_info_snapshot_mac.cc81
-rw-r--r--chrome/browser/safe_browsing/safe_browsing_test.cc5
-rw-r--r--chrome/browser/ui/browser_init.cc2
-rw-r--r--chrome/common/switch_utils_unittest.cc37
-rw-r--r--chrome/installer/util/install_util.cc19
-rw-r--r--chrome/installer/util/install_util.h4
-rw-r--r--chrome/installer/util/product_state_unittest.cc19
-rw-r--r--chrome/test/live_sync/live_sync_test.cc8
-rw-r--r--chrome/test/ui/ui_test.cc20
-rw-r--r--chrome/test/ui_test_utils.cc23
-rw-r--r--net/test/test_server.cc25
-rw-r--r--net/test/test_server_posix.cc5
-rw-r--r--net/test/test_server_win.cc3
17 files changed, 473 insertions, 470 deletions
diff --git a/base/command_line.cc b/base/command_line.cc
index b027d2a..b3a79eb 100644
--- a/base/command_line.cc
+++ b/base/command_line.cc
@@ -23,29 +23,79 @@
CommandLine* CommandLine::current_process_commandline_ = NULL;
namespace {
-typedef CommandLine::StringType::value_type CharType;
-
-const CharType kSwitchTerminator[] = FILE_PATH_LITERAL("--");
-const CharType kSwitchValueSeparator[] = FILE_PATH_LITERAL("=");
+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 CharType* const kSwitchPrefixes[] = {L"--", L"-", L"/"};
+const CommandLine::CharType* const kSwitchPrefixes[] = {L"--", L"-", L"/"};
#elif defined(OS_POSIX)
// Unixes don't use slash as a switch.
-const CharType* const kSwitchPrefixes[] = {"--", "-"};
+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.find(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();
+ if (GetSwitchPrefixLength(string) == 0)
+ 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)
-// Lowercase a string for case-insensitivity of switches.
-// Is this desirable? It exists for backwards compatibility on Windows.
-void Lowercase(std::string* arg) {
- transform(arg->begin(), arg->end(), arg->begin(), tolower);
+ 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
}
-// Quote a string if necessary, such that CommandLineToArgvW() will always
-// process it as a single argument.
-std::wstring WindowsStyleQuote(const std::wstring& arg) {
+
+#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) {
@@ -88,73 +138,30 @@ std::wstring WindowsStyleQuote(const std::wstring& arg) {
}
#endif
-// Returns true and fills in |switch_string| and |switch_value| if
-// |parameter_string| represents a switch.
-bool IsSwitch(const CommandLine::StringType& parameter_string,
- std::string* switch_string,
- CommandLine::StringType* switch_value) {
- switch_string->clear();
- switch_value->clear();
-
- for (size_t i = 0; i < arraysize(kSwitchPrefixes); ++i) {
- CommandLine::StringType prefix(kSwitchPrefixes[i]);
- if (parameter_string.find(prefix) != 0)
- continue;
-
- const size_t switch_start = prefix.length();
- const size_t equals_position = parameter_string.find(
- kSwitchValueSeparator, switch_start);
- CommandLine::StringType switch_native;
- if (equals_position == CommandLine::StringType::npos) {
- switch_native = parameter_string.substr(switch_start);
- } else {
- switch_native = parameter_string.substr(
- switch_start, equals_position - switch_start);
- *switch_value = parameter_string.substr(equals_position + 1);
- }
-#if defined(OS_WIN)
- *switch_string = WideToASCII(switch_native);
- Lowercase(switch_string);
-#else
- *switch_string = switch_native;
-#endif
-
- return true;
- }
-
- return false;
-}
-
} // namespace
-CommandLine::CommandLine(NoProgram no_program) {
-#if defined(OS_POSIX)
- // Push an empty argument, because we always assume argv_[0] is a program.
- argv_.push_back("");
-#endif
+CommandLine::CommandLine(NoProgram no_program)
+ : argv_(1),
+ begin_args_(1) {
}
-CommandLine::CommandLine(const FilePath& program) {
-#if defined(OS_WIN)
- if (!program.empty()) {
- program_ = program.value();
- // TODO(evanm): proper quoting here.
- command_line_string_ = L'"' + program.value() + L'"';
- }
-#elif defined(OS_POSIX)
- argv_.push_back(program.value());
-#endif
+CommandLine::CommandLine(const FilePath& program)
+ : argv_(1),
+ begin_args_(1) {
+ SetProgram(program);
}
-#if defined(OS_POSIX)
-CommandLine::CommandLine(int argc, const char* const* argv) {
+CommandLine::CommandLine(int argc, const CommandLine::CharType* const* argv)
+ : argv_(1),
+ begin_args_(1) {
InitFromArgv(argc, argv);
}
-CommandLine::CommandLine(const StringVector& argv) {
+CommandLine::CommandLine(const StringVector& argv)
+ : argv_(1),
+ begin_args_(1) {
InitFromArgv(argv);
}
-#endif // OS_POSIX
CommandLine::~CommandLine() {
}
@@ -162,7 +169,7 @@ CommandLine::~CommandLine() {
// static
void CommandLine::Init(int argc, const char* const* argv) {
delete current_process_commandline_;
- current_process_commandline_ = new CommandLine;
+ current_process_commandline_ = new CommandLine(NO_PROGRAM);
#if defined(OS_WIN)
current_process_commandline_->ParseFromString(::GetCommandLineW());
#elif defined(OS_POSIX)
@@ -186,76 +193,76 @@ CommandLine* CommandLine::ForCurrentProcess() {
#if defined(OS_WIN)
// static
CommandLine CommandLine::FromString(const std::wstring& command_line) {
- CommandLine cmd;
+ CommandLine cmd(NO_PROGRAM);
cmd.ParseFromString(command_line);
return cmd;
}
-#endif // OS_WIN
+#endif
-#if defined(OS_POSIX)
-void CommandLine::InitFromArgv(int argc, const char* const* argv) {
+void CommandLine::InitFromArgv(int argc,
+ const CommandLine::CharType* const* argv) {
+ StringVector new_argv;
for (int i = 0; i < argc; ++i)
- argv_.push_back(argv[i]);
- InitFromArgv(argv_);
+ new_argv.push_back(argv[i]);
+ InitFromArgv(new_argv);
}
void CommandLine::InitFromArgv(const StringVector& argv) {
- argv_ = argv;
- bool parse_switches = true;
- for (size_t i = 1; i < argv_.size(); ++i) {
- const std::string& arg = argv_[i];
-
- if (!parse_switches) {
- args_.push_back(arg);
- continue;
- }
-
- if (arg == kSwitchTerminator) {
- parse_switches = false;
- continue;
- }
-
- std::string switch_string;
- StringType switch_value;
- if (IsSwitch(arg, &switch_string, &switch_value)) {
- switches_[switch_string] = switch_value;
- } else {
- args_.push_back(arg);
- }
- }
+ argv_ = StringVector(1);
+ begin_args_ = 1;
+ SetProgram(argv.empty() ? FilePath() : FilePath(argv[0]));
+ AppendSwitchesAndArguments(*this, argv);
}
-#endif // OS_POSIX
CommandLine::StringType CommandLine::command_line_string() const {
+ StringType string(argv_[0]);
#if defined(OS_WIN)
- return command_line_string_;
-#elif defined(OS_POSIX)
- return JoinString(argv_, ' ');
+ string = QuoteForCommandLineToArgvW(string);
+#endif
+ // Append switches and arguments.
+ bool parse_switches = true;
+ for (size_t i = 1; i < argv_.size(); ++i) {
+ CommandLine::StringType arg = argv_[i];
+ CommandLine::StringType switch_string;
+ CommandLine::StringType switch_value;
+ parse_switches &= arg != kSwitchTerminator;
+ string.append(StringType(FILE_PATH_LITERAL(" ")));
+ if (parse_switches && IsSwitch(arg, &switch_string, &switch_value)) {
+ string.append(switch_string);
+ if (!switch_value.empty()) {
+#if defined(OS_WIN)
+ switch_value = QuoteForCommandLineToArgvW(switch_value);
+#endif
+ string.append(kSwitchValueSeparator + switch_value);
+ }
+ }
+ else {
+#if defined(OS_WIN)
+ arg = QuoteForCommandLineToArgvW(arg);
#endif
+ string.append(arg);
+ }
+ }
+ return string;
}
FilePath CommandLine::GetProgram() const {
-#if defined(OS_WIN)
- return FilePath(program_);
-#else
- DCHECK_GT(argv_.size(), 0U);
return FilePath(argv_[0]);
-#endif
+}
+
+void CommandLine::SetProgram(const FilePath& program) {
+ TrimWhitespace(program.value(), TRIM_ALL, &argv_[0]);
}
bool CommandLine::HasSwitch(const std::string& switch_string) const {
- std::string lowercased_switch(switch_string);
-#if defined(OS_WIN)
- Lowercase(&lowercased_switch);
-#endif
- return switches_.find(lowercased_switch) != switches_.end();
+ return switches_.find(LowerASCIIOnWindows(switch_string)) != switches_.end();
}
std::string CommandLine::GetSwitchValueASCII(
const std::string& switch_string) const {
- CommandLine::StringType value = GetSwitchValueNative(switch_string);
+ StringType value = GetSwitchValueNative(switch_string);
if (!IsStringASCII(value)) {
- LOG(WARNING) << "Value of --" << switch_string << " must be ASCII.";
+ LOG(WARNING) << "Value of switch (" << switch_string << ") must be ASCII.";
return "";
}
#if defined(OS_WIN)
@@ -272,18 +279,9 @@ FilePath CommandLine::GetSwitchValuePath(
CommandLine::StringType CommandLine::GetSwitchValueNative(
const std::string& switch_string) const {
- std::string lowercased_switch(switch_string);
-#if defined(OS_WIN)
- Lowercase(&lowercased_switch);
-#endif
-
- SwitchMap::const_iterator result = switches_.find(lowercased_switch);
-
- if (result == switches_.end()) {
- return CommandLine::StringType();
- } else {
- return result->second;
- }
+ SwitchMap::const_iterator result = switches_.end();
+ result = switches_.find(LowerASCIIOnWindows(switch_string));
+ return result == switches_.end() ? StringType() : result->second;
}
size_t CommandLine::GetSwitchCount() const {
@@ -291,14 +289,7 @@ size_t CommandLine::GetSwitchCount() const {
}
void CommandLine::AppendSwitch(const std::string& switch_string) {
-#if defined(OS_WIN)
- command_line_string_.append(L" ");
- command_line_string_.append(kSwitchPrefixes[0] + ASCIIToWide(switch_string));
- switches_[switch_string] = L"";
-#elif defined(OS_POSIX)
- argv_.push_back(kSwitchPrefixes[0] + switch_string);
- switches_[switch_string] = "";
-#endif
+ AppendSwitchNative(switch_string, StringType());
}
void CommandLine::AppendSwitchPath(const std::string& switch_string,
@@ -308,23 +299,21 @@ void CommandLine::AppendSwitchPath(const std::string& switch_string,
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 =
- kSwitchPrefixes[0] + ASCIIToWide(switch_string);
- if (!value.empty())
- combined_switch_string += kSwitchValueSeparator + WindowsStyleQuote(value);
-
- command_line_string_.append(L" ");
- command_line_string_.append(combined_switch_string);
-
- switches_[switch_string] = value;
+ StringType combined_switch_string(ASCIIToWide(switch_key));
#elif defined(OS_POSIX)
- StringType combined_switch_string = kSwitchPrefixes[0] + switch_string;
+ 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;
- argv_.push_back(combined_switch_string);
- switches_[switch_string] = value;
-#endif
+ // 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,
@@ -336,23 +325,26 @@ void CommandLine::AppendSwitchASCII(const std::string& switch_string,
#endif
}
-void CommandLine::AppendSwitches(const CommandLine& other) {
- SwitchMap::const_iterator i;
- for (i = other.switches_.begin(); i != other.switches_.end(); ++i)
- AppendSwitchNative(i->first, i->second);
-}
-
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])) {
- StringType value = source.GetSwitchValueNative(switches[i]);
- AppendSwitchNative(switches[i], value);
- }
+ if (source.HasSwitch(switches[i]))
+ AppendSwitchNative(switches[i], source.GetSwitchValueNative(switches[i]));
}
}
+CommandLine::StringVector CommandLine::args() 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));
@@ -367,117 +359,42 @@ void CommandLine::AppendArgPath(const FilePath& path) {
}
void CommandLine::AppendArgNative(const CommandLine::StringType& value) {
-#if defined(OS_WIN)
- command_line_string_.append(L" ");
- command_line_string_.append(WindowsStyleQuote(value));
- args_.push_back(value);
-#elif defined(OS_POSIX)
- DCHECK(IsStringUTF8(value));
argv_.push_back(value);
-#endif
-}
-
-void CommandLine::AppendArgs(const CommandLine& other) {
- if(other.args_.size() <= 0)
- return;
-#if defined(OS_WIN)
- command_line_string_.append(L" --");
-#endif // OS_WIN
- StringVector::const_iterator i;
- for (i = other.args_.begin(); i != other.args_.end(); ++i)
- AppendArgNative(*i);
}
void CommandLine::AppendArguments(const CommandLine& other,
bool include_program) {
-#if defined(OS_WIN)
- // Verify include_program is used correctly.
- DCHECK(!include_program || !other.GetProgram().empty());
if (include_program)
- program_ = other.program_;
-
- if (!command_line_string_.empty())
- command_line_string_ += L' ';
-
- command_line_string_ += other.command_line_string_;
-#elif defined(OS_POSIX)
- // Verify include_program is used correctly.
- // Logic could be shorter but this is clearer.
- DCHECK_EQ(include_program, !other.GetProgram().empty());
-
- if (include_program)
- argv_[0] = other.argv_[0];
-
- // Skip the first arg when copying since it's the program but push all
- // arguments to our arg vector.
- for (size_t i = 1; i < other.argv_.size(); ++i)
- argv_.push_back(other.argv_[i]);
-#endif
-
- SwitchMap::const_iterator i;
- for (i = other.switches_.begin(); i != other.switches_.end(); ++i)
- switches_[i->first] = i->second;
+ SetProgram(other.GetProgram());
+ AppendSwitchesAndArguments(*this, other.argv());
}
void CommandLine::PrependWrapper(const CommandLine::StringType& wrapper) {
- // 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.
if (wrapper.empty())
return;
- StringVector wrapper_and_args;
-#if defined(OS_WIN)
- base::SplitString(wrapper, ' ', &wrapper_and_args);
- program_ = wrapper_and_args[0];
- command_line_string_ = wrapper + L" " + command_line_string_;
-#elif defined(OS_POSIX)
- base::SplitString(wrapper, ' ', &wrapper_and_args);
- argv_.insert(argv_.begin(), wrapper_and_args.begin(), wrapper_and_args.end());
-#endif
+ // 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) {
- TrimWhitespace(command_line, TRIM_ALL, &command_line_string_);
-
- if (command_line_string_.empty())
+ 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);
- args = CommandLineToArgvW(command_line_string_.c_str(), &num_args);
-
- // Populate program_ with the trimmed version of the first arg.
- TrimWhitespace(args[0], TRIM_ALL, &program_);
-
- bool parse_switches = true;
- for (int i = 1; i < num_args; ++i) {
- std::wstring arg;
- TrimWhitespace(args[i], TRIM_ALL, &arg);
-
- if (!parse_switches) {
- args_.push_back(arg);
- continue;
- }
-
- if (arg == kSwitchTerminator) {
- parse_switches = false;
- continue;
- }
-
- std::string switch_string;
- std::wstring switch_value;
- if (IsSwitch(arg, &switch_string, &switch_value)) {
- switches_[switch_string] = switch_value;
- } else {
- args_.push_back(arg);
- }
- }
-
- if (args)
- LocalFree(args);
+ PLOG_IF(FATAL, !args) << "CommandLineToArgvW failed on command line: " <<
+ command_line;
+ InitFromArgv(num_args, args);
+ LocalFree(args);
}
#endif
-
-CommandLine::CommandLine() {
-}
diff --git a/base/command_line.h b/base/command_line.h
index 970e4a7..d9f3138 100644
--- a/base/command_line.h
+++ b/base/command_line.h
@@ -3,10 +3,11 @@
// found in the LICENSE file.
// This class works with command lines: building and parsing.
-// Switches can optionally have a value attached using an equals sign, as in
-// "-switch=value". Arguments that aren't prefixed with a switch prefix are
-// saved as extra arguments. An argument of "--" will terminate switch parsing,
-// causing everything after to be considered as extra arguments.
+// 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().
@@ -34,8 +35,8 @@ class BASE_API CommandLine {
typedef std::string StringType;
#endif
+ typedef StringType::value_type CharType;
typedef std::vector<StringType> StringVector;
- // The type of map for parsed-out switch key and values.
typedef std::map<std::string, StringType> SwitchMap;
// A constructor for CommandLines that only carry switches and arguments.
@@ -45,10 +46,9 @@ class BASE_API CommandLine {
// Construct a new command line with |program| as argv[0].
explicit CommandLine(const FilePath& program);
-#if defined(OS_POSIX)
- CommandLine(int argc, const char* const* argv);
+ // Construct a new command line from an argument list.
+ CommandLine(int argc, const CharType* const* argv);
explicit CommandLine(const StringVector& argv);
-#endif
~CommandLine();
@@ -73,23 +73,21 @@ class BASE_API CommandLine {
static CommandLine FromString(const std::wstring& command_line);
#endif
-#if defined(OS_POSIX)
// Initialize from an argv vector.
- void InitFromArgv(int argc, const char* const* argv);
+ void InitFromArgv(int argc, const CharType* const* argv);
void InitFromArgv(const StringVector& argv);
-#endif
- // Returns the represented command line string.
+ // Constructs and returns the represented command line string.
// CAUTION! This should be avoided because quoting behavior is unclear.
+ // TODO(msw): Rename GetCommandLineString.
StringType command_line_string() const;
-#if defined(OS_POSIX)
// Returns the original command line string as a vector of strings.
const StringVector& argv() const { return argv_; }
-#endif
- // Returns the program part of the command line string (the first item).
+ // Get and Set the program part of the command line string (the first item).
FilePath GetProgram() const;
+ void SetProgram(const FilePath& program);
// Returns true if this command line contains the given switch.
// (Switch names are case-insensitive).
@@ -109,35 +107,35 @@ class BASE_API CommandLine {
const SwitchMap& GetSwitches() const { return switches_; }
// Append a switch [with optional value] to the command line.
- // CAUTION! Appending a switch after the "--" switch terminator is futile!
+ // Note: Switches will precede arguments regardless of appending order.
void AppendSwitch(const std::string& switch_string);
void AppendSwitchPath(const std::string& switch_string, const FilePath& path);
void AppendSwitchNative(const std::string& switch_string,
const StringType& value);
void AppendSwitchASCII(const std::string& switch_string,
const std::string& value);
- void AppendSwitches(const CommandLine& other);
// 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[],
+ void CopySwitchesFrom(const CommandLine& source,
+ const char* const switches[],
size_t count);
// Get the remaining arguments to the command.
- const StringVector& args() const { return args_; }
+ // TODO(msw): Rename GetArgs.
+ StringVector args() 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 FilePath& value);
void AppendArgNative(const StringType& value);
- void AppendArgs(const CommandLine& other);
- // Append the arguments from another command line to this one.
+ // 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);
+ void AppendArguments(const CommandLine& other, bool include_program);
// Insert a command before the current command.
// Common for debuggers, like "valgrind" or "gdb --args".
@@ -150,34 +148,24 @@ class BASE_API CommandLine {
#endif
private:
- // Disallow public default construction; a program name must be specified.
+ // 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_;
- // We store a platform-native version of the command line, used when building
- // up a new command line to be executed. This ifdef delimits that code.
-#if defined(OS_WIN)
- // The quoted, space-separated command line string.
- StringType command_line_string_;
- // The name of the program.
- StringType program_;
-#elif defined(OS_POSIX)
- // The argv array, with the program name in argv_[0].
+ // The argv array: { program, [(--|-|/)switch[=value]]*, [--], [argument]* }
StringVector argv_;
-#endif
// Parsed-out switch keys and values.
SwitchMap switches_;
- // Non-switch command line arguments.
- StringVector args_;
-
- // Allow the copy constructor. A common pattern is to copy the current
- // process's command line and then add some flags to it. For example:
- // CommandLine cl(*CommandLine::ForCurrentProcess());
- // cl.AppendSwitch(...);
+ // The index after the program and switches, any arguments start here.
+ size_t begin_args_;
};
#endif // BASE_COMMAND_LINE_H_
diff --git a/base/command_line_unittest.cc b/base/command_line_unittest.cc
index 5ce6911..a8d1eed 100644
--- a/base/command_line_unittest.cc
+++ b/base/command_line_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// 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.
@@ -15,32 +15,34 @@
// and quotes.
// Consider the command-line argument: q\"bs1\bs2\\bs3q\\\"
// Here it is with C-style escapes.
-#define TRICKY_QUOTED L"q\\\"bs1\\bs2\\\\bs3q\\\\\\\""
+static const CommandLine::StringType kTrickyQuoted =
+ FILE_PATH_LITERAL("q\\\"bs1\\bs2\\\\bs3q\\\\\\\"");
// It should be parsed by Windows as: q"bs1\bs2\\bs3q\"
// Here that is with C-style escapes.
-#define TRICKY L"q\"bs1\\bs2\\\\bs3q\\\""
+static const CommandLine::StringType kTricky =
+ FILE_PATH_LITERAL("q\"bs1\\bs2\\\\bs3q\\\"");
TEST(CommandLineTest, CommandLineConstructor) {
-#if defined(OS_WIN)
- CommandLine cl = CommandLine::FromString(
- L"program --foo= -bAr /Spaetzel=pierogi /Baz flim "
- L"--other-switches=\"--dog=canine --cat=feline\" "
- L"-spaetzle=Crepe -=loosevalue flan "
- L"--input-translation=\"45\"--output-rotation "
- L"--quotes=" TRICKY_QUOTED L" "
- L"-- -- --not-a-switch "
- L"\"in the time of submarines...\"");
- EXPECT_FALSE(cl.command_line_string().empty());
-#elif defined(OS_POSIX)
- const char* argv[] = {"program", "--foo=", "-bar",
- "-spaetzel=pierogi", "-baz", "flim",
- "--other-switches=--dog=canine --cat=feline",
- "-spaetzle=Crepe", "-=loosevalue", "flan",
- "--input-translation=45--output-rotation",
- "--", "--", "--not-a-switch",
- "in the time of submarines..."};
+ const CommandLine::CharType* argv[] = {
+ FILE_PATH_LITERAL("program"),
+ FILE_PATH_LITERAL("--foo="),
+ FILE_PATH_LITERAL("-bAr"),
+ FILE_PATH_LITERAL("-spaetzel=pierogi"),
+ FILE_PATH_LITERAL("-baz"),
+ FILE_PATH_LITERAL("flim"),
+ FILE_PATH_LITERAL("--other-switches=--dog=canine --cat=feline"),
+ FILE_PATH_LITERAL("-spaetzle=Crepe"),
+ FILE_PATH_LITERAL("-=loosevalue"),
+ FILE_PATH_LITERAL("FLAN"),
+ FILE_PATH_LITERAL("--input-translation=45--output-rotation"),
+ FILE_PATH_LITERAL("--"),
+ FILE_PATH_LITERAL("--"),
+ FILE_PATH_LITERAL("--not-a-switch"),
+ FILE_PATH_LITERAL("\"in the time of submarines...\""),
+ FILE_PATH_LITERAL("unquoted arg-with-space")};
CommandLine cl(arraysize(argv), argv);
-#endif
+
+ EXPECT_FALSE(cl.command_line_string().empty());
EXPECT_FALSE(cl.HasSwitch("cruller"));
EXPECT_FALSE(cl.HasSwitch("flim"));
EXPECT_FALSE(cl.HasSwitch("program"));
@@ -54,7 +56,7 @@ TEST(CommandLineTest, CommandLineConstructor) {
cl.GetProgram().value());
EXPECT_TRUE(cl.HasSwitch("foo"));
- EXPECT_TRUE(cl.HasSwitch("bar"));
+ EXPECT_TRUE(cl.HasSwitch("bAr"));
EXPECT_TRUE(cl.HasSwitch("baz"));
EXPECT_TRUE(cl.HasSwitch("spaetzle"));
#if defined(OS_WIN)
@@ -62,9 +64,66 @@ TEST(CommandLineTest, CommandLineConstructor) {
#endif
EXPECT_TRUE(cl.HasSwitch("other-switches"));
EXPECT_TRUE(cl.HasSwitch("input-translation"));
+
+ EXPECT_EQ("Crepe", cl.GetSwitchValueASCII("spaetzle"));
+ EXPECT_EQ("", cl.GetSwitchValueASCII("Foo"));
+ EXPECT_EQ("", cl.GetSwitchValueASCII("bar"));
+ EXPECT_EQ("", cl.GetSwitchValueASCII("cruller"));
+ EXPECT_EQ("--dog=canine --cat=feline", cl.GetSwitchValueASCII(
+ "other-switches"));
+ EXPECT_EQ("45--output-rotation", cl.GetSwitchValueASCII("input-translation"));
+
+ const std::vector<CommandLine::StringType>& args = cl.args();
+ ASSERT_EQ(6U, args.size());
+
+ std::vector<CommandLine::StringType>::const_iterator iter = args.begin();
+ EXPECT_EQ(FILE_PATH_LITERAL("flim"), *iter);
+ ++iter;
+ EXPECT_EQ(FILE_PATH_LITERAL("FLAN"), *iter);
+ ++iter;
+ EXPECT_EQ(FILE_PATH_LITERAL("--"), *iter);
+ ++iter;
+ EXPECT_EQ(FILE_PATH_LITERAL("--not-a-switch"), *iter);
+ ++iter;
+ EXPECT_EQ(FILE_PATH_LITERAL("\"in the time of submarines...\""), *iter);
+ ++iter;
+ EXPECT_EQ(FILE_PATH_LITERAL("unquoted arg-with-space"), *iter);
+ ++iter;
+ EXPECT_TRUE(iter == args.end());
+}
+
+TEST(CommandLineTest, CommandLineFromString) {
#if defined(OS_WIN)
+ CommandLine cl = CommandLine::FromString(
+ L"program --foo= -bAr /Spaetzel=pierogi /Baz flim "
+ L"--other-switches=\"--dog=canine --cat=feline\" "
+ L"-spaetzle=Crepe -=loosevalue FLAN "
+ L"--input-translation=\"45\"--output-rotation "
+ L"--quotes=" + kTrickyQuoted + L" "
+ L"-- -- --not-a-switch "
+ L"\"in the time of submarines...\"");
+
+ EXPECT_FALSE(cl.command_line_string().empty());
+ EXPECT_FALSE(cl.HasSwitch("cruller"));
+ EXPECT_FALSE(cl.HasSwitch("flim"));
+ EXPECT_FALSE(cl.HasSwitch("program"));
+ EXPECT_FALSE(cl.HasSwitch("dog"));
+ EXPECT_FALSE(cl.HasSwitch("cat"));
+ EXPECT_FALSE(cl.HasSwitch("output-rotation"));
+ EXPECT_FALSE(cl.HasSwitch("not-a-switch"));
+ EXPECT_FALSE(cl.HasSwitch("--"));
+
+ EXPECT_EQ(FilePath(FILE_PATH_LITERAL("program")).value(),
+ cl.GetProgram().value());
+
+ EXPECT_TRUE(cl.HasSwitch("foo"));
+ EXPECT_TRUE(cl.HasSwitch("bar"));
+ EXPECT_TRUE(cl.HasSwitch("baz"));
+ EXPECT_TRUE(cl.HasSwitch("spaetzle"));
+ EXPECT_TRUE(cl.HasSwitch("SPAETZLE"));
+ EXPECT_TRUE(cl.HasSwitch("other-switches"));
+ EXPECT_TRUE(cl.HasSwitch("input-translation"));
EXPECT_TRUE(cl.HasSwitch("quotes"));
-#endif
EXPECT_EQ("Crepe", cl.GetSwitchValueASCII("spaetzle"));
EXPECT_EQ("", cl.GetSwitchValueASCII("Foo"));
@@ -73,9 +132,7 @@ TEST(CommandLineTest, CommandLineConstructor) {
EXPECT_EQ("--dog=canine --cat=feline", cl.GetSwitchValueASCII(
"other-switches"));
EXPECT_EQ("45--output-rotation", cl.GetSwitchValueASCII("input-translation"));
-#if defined(OS_WIN)
- EXPECT_EQ(TRICKY, cl.GetSwitchValueNative("quotes"));
-#endif
+ EXPECT_EQ(kTricky, cl.GetSwitchValueNative("quotes"));
const std::vector<CommandLine::StringType>& args = cl.args();
ASSERT_EQ(5U, args.size());
@@ -83,7 +140,7 @@ TEST(CommandLineTest, CommandLineConstructor) {
std::vector<CommandLine::StringType>::const_iterator iter = args.begin();
EXPECT_EQ(FILE_PATH_LITERAL("flim"), *iter);
++iter;
- EXPECT_EQ(FILE_PATH_LITERAL("flan"), *iter);
+ EXPECT_EQ(FILE_PATH_LITERAL("FLAN"), *iter);
++iter;
EXPECT_EQ(FILE_PATH_LITERAL("--"), *iter);
++iter;
@@ -92,69 +149,92 @@ TEST(CommandLineTest, CommandLineConstructor) {
EXPECT_EQ(FILE_PATH_LITERAL("in the time of submarines..."), *iter);
++iter;
EXPECT_TRUE(iter == args.end());
-#if defined(OS_POSIX)
- const std::vector<std::string>& argvec = cl.argv();
- for (size_t i = 0; i < argvec.size(); i++) {
- EXPECT_EQ(0, argvec[i].compare(argv[i]));
- }
+ // Check that a generated string produces an equivalent command line.
+ CommandLine cl_duplicate = CommandLine::FromString(cl.command_line_string());
+ EXPECT_EQ(cl.command_line_string(), cl_duplicate.command_line_string());
#endif
}
// Tests behavior with an empty input string.
TEST(CommandLineTest, EmptyString) {
#if defined(OS_WIN)
- CommandLine cl = CommandLine::FromString(L"");
- EXPECT_TRUE(cl.command_line_string().empty());
- EXPECT_TRUE(cl.GetProgram().empty());
-#elif defined(OS_POSIX)
- CommandLine cl(0, NULL);
- EXPECT_TRUE(cl.argv().empty());
+ CommandLine cl_from_string = CommandLine::FromString(L"");
+ EXPECT_TRUE(cl_from_string.command_line_string().empty());
+ EXPECT_TRUE(cl_from_string.GetProgram().empty());
+ EXPECT_EQ(1U, cl_from_string.argv().size());
+ EXPECT_TRUE(cl_from_string.args().empty());
#endif
- EXPECT_TRUE(cl.args().empty());
+ CommandLine cl_from_argv(0, NULL);
+ EXPECT_TRUE(cl_from_argv.command_line_string().empty());
+ EXPECT_TRUE(cl_from_argv.GetProgram().empty());
+ EXPECT_EQ(1U, cl_from_argv.argv().size());
+ EXPECT_TRUE(cl_from_argv.args().empty());
}
// Test methods for appending switches to a command line.
TEST(CommandLineTest, AppendSwitches) {
std::string switch1 = "switch1";
std::string switch2 = "switch2";
- std::string value = "value";
+ std::string value2 = "value";
std::string switch3 = "switch3";
std::string value3 = "a value with spaces";
std::string switch4 = "switch4";
std::string value4 = "\"a value with quotes\"";
std::string switch5 = "quotes";
- std::string value5 = WideToUTF8(TRICKY);
+ CommandLine::StringType value5 = kTricky;
CommandLine cl(FilePath(FILE_PATH_LITERAL("Program")));
cl.AppendSwitch(switch1);
- cl.AppendSwitchASCII(switch2, value);
+ cl.AppendSwitchASCII(switch2, value2);
cl.AppendSwitchASCII(switch3, value3);
cl.AppendSwitchASCII(switch4, value4);
- cl.AppendSwitchASCII(switch5, value5);
+ cl.AppendSwitchNative(switch5, value5);
EXPECT_TRUE(cl.HasSwitch(switch1));
EXPECT_TRUE(cl.HasSwitch(switch2));
- EXPECT_EQ(value, cl.GetSwitchValueASCII(switch2));
+ EXPECT_EQ(value2, cl.GetSwitchValueASCII(switch2));
EXPECT_TRUE(cl.HasSwitch(switch3));
EXPECT_EQ(value3, cl.GetSwitchValueASCII(switch3));
EXPECT_TRUE(cl.HasSwitch(switch4));
EXPECT_EQ(value4, cl.GetSwitchValueASCII(switch4));
EXPECT_TRUE(cl.HasSwitch(switch5));
- EXPECT_EQ(value5, cl.GetSwitchValueASCII(switch5));
+ EXPECT_EQ(value5, cl.GetSwitchValueNative(switch5));
#if defined(OS_WIN)
- EXPECT_EQ(L"\"Program\" "
+ EXPECT_EQ(L"Program "
L"--switch1 "
L"--switch2=value "
L"--switch3=\"a value with spaces\" "
L"--switch4=\"\\\"a value with quotes\\\"\" "
- L"--quotes=\"" TRICKY_QUOTED L"\"",
+ L"--quotes=\"" + kTrickyQuoted + L"\"",
cl.command_line_string());
#endif
}
+TEST(CommandLineTest, AppendSwitchesDashDash) {
+ const CommandLine::CharType* raw_argv[] = { FILE_PATH_LITERAL("prog"),
+ FILE_PATH_LITERAL("--"),
+ FILE_PATH_LITERAL("--arg1") };
+ CommandLine cl(arraysize(raw_argv), raw_argv);
+
+ cl.AppendSwitch("switch1");
+ cl.AppendSwitchASCII("switch2", "foo");
+
+ cl.AppendArg("--arg2");
+
+ EXPECT_EQ(FILE_PATH_LITERAL("prog --switch1 --switch2=foo -- --arg1 --arg2"),
+ cl.command_line_string());
+ CommandLine::StringVector cl_argv = cl.argv();
+ EXPECT_EQ(FILE_PATH_LITERAL("prog"), cl_argv[0]);
+ EXPECT_EQ(FILE_PATH_LITERAL("--switch1"), cl_argv[1]);
+ EXPECT_EQ(FILE_PATH_LITERAL("--switch2=foo"), cl_argv[2]);
+ EXPECT_EQ(FILE_PATH_LITERAL("--"), cl_argv[3]);
+ EXPECT_EQ(FILE_PATH_LITERAL("--arg1"), cl_argv[4]);
+ EXPECT_EQ(FILE_PATH_LITERAL("--arg2"), cl_argv[5]);
+}
+
// Tests that when AppendArguments is called that the program is set correctly
// on the target CommandLine object and the switches from the source
// CommandLine are added to the target.
@@ -180,21 +260,27 @@ TEST(CommandLineTest, AppendArguments) {
}
#if defined(OS_WIN)
-// Make sure that the program part of a command line is always quoted.
+// Make sure that program paths of command_line_string are quoted as necessary.
// This only makes sense on Windows and the test is basically here to guard
// against regressions.
TEST(CommandLineTest, ProgramQuotes) {
+ // Check that quotes are not added for paths without spaces.
const FilePath kProgram(L"Program");
+ CommandLine cl_program(kProgram);
+ EXPECT_EQ(kProgram.value(), cl_program.GetProgram().value());
+ EXPECT_EQ(kProgram.value(), cl_program.command_line_string());
+
+ const FilePath kProgramPath(L"Program Path");
// Check that quotes are not returned from GetProgram().
- CommandLine cl(kProgram);
- EXPECT_EQ(kProgram.value(), cl.GetProgram().value());
-
- // Verify that in the command line string, the program part is always quoted.
- CommandLine::StringType cmd(cl.command_line_string());
- CommandLine::StringType program(cl.GetProgram().value());
- EXPECT_EQ('"', cmd[0]);
- EXPECT_EQ(program, cmd.substr(1, program.length()));
- EXPECT_EQ('"', cmd[program.length() + 1]);
+ CommandLine cl_program_path(kProgramPath);
+ EXPECT_EQ(kProgramPath.value(), cl_program_path.GetProgram().value());
+
+ // Check that quotes are added to command line string paths containing spaces.
+ CommandLine::StringType cmd_string(cl_program_path.command_line_string());
+ CommandLine::StringType program_string(cl_program_path.GetProgram().value());
+ EXPECT_EQ('"', cmd_string[0]);
+ EXPECT_EQ(program_string, cmd_string.substr(1, program_string.length()));
+ EXPECT_EQ('"', cmd_string[program_string.length() + 1]);
}
#endif
diff --git a/chrome/browser/browser_main_win.cc b/chrome/browser/browser_main_win.cc
index 6ecea52..ad74709 100644
--- a/chrome/browser/browser_main_win.cc
+++ b/chrome/browser/browser_main_win.cc
@@ -230,8 +230,7 @@ bool RegisterApplicationRestart(const CommandLine& parsed_command_line) {
// The Windows Restart Manager expects a string of command line flags only,
// without the program.
CommandLine command_line(CommandLine::NO_PROGRAM);
- command_line.AppendSwitches(parsed_command_line);
- command_line.AppendArgs(parsed_command_line);
+ command_line.AppendArguments(parsed_command_line, false);
// Ensure restore last session is set.
if (!command_line.HasSwitch(switches::kRestoreLastSession))
command_line.AppendSwitch(switches::kRestoreLastSession);
diff --git a/chrome/browser/process_info_snapshot_mac.cc b/chrome/browser/process_info_snapshot_mac.cc
index 10fc77b..d0387b0 100644
--- a/chrome/browser/process_info_snapshot_mac.cc
+++ b/chrome/browser/process_info_snapshot_mac.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// 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.
@@ -127,25 +127,23 @@ static bool ConvertByteUnitToScale(char unit, uint64_t* out_scale) {
static bool GetProcessMemoryInfoUsingPS(
const std::vector<base::ProcessId>& pid_list,
std::map<int,ProcessInfoSnapshot::ProcInfoEntry>& proc_info_entries) {
- const char kPsPathName[] = "/bin/ps";
- std::vector<std::string> argv;
- argv.push_back(kPsPathName);
+ const FilePath kProgram("/bin/ps");
+ CommandLine command_line(kProgram);
// Get resident set size, virtual memory size.
- argv.push_back("-o");
- argv.push_back("pid=,rss=,vsz=");
+ command_line.AppendArg("-o");
+ command_line.AppendArg("pid=,rss=,vsz=");
// Only display the specified PIDs.
for (std::vector<base::ProcessId>::const_iterator it = pid_list.begin();
- it != pid_list.end(); ++it) {
- argv.push_back("-p");
- argv.push_back(base::Int64ToString(static_cast<int64>(*it)));
+ it != pid_list.end(); ++it) {
+ command_line.AppendArg("-p");
+ command_line.AppendArg(base::Int64ToString(static_cast<int64>(*it)));
}
std::string output;
- CommandLine command_line(argv);
// Limit output read to a megabyte for safety.
if (!base::GetAppOutputRestricted(command_line, &output, 1024 * 1024)) {
- LOG(ERROR) << "Failure running " << kPsPathName << " to acquire data.";
+ LOG(ERROR) << "Failure running " << kProgram.value() << " to acquire data.";
return false;
}
@@ -172,12 +170,12 @@ static bool GetProcessMemoryInfoUsingPS(
in.ignore(1, ' '); // Eat the space.
std::getline(in, proc_info.command); // Get the rest of the line.
if (!in.good()) {
- LOG(ERROR) << "Error parsing output from " << kPsPathName << ".";
+ LOG(ERROR) << "Error parsing output from " << kProgram.value() << ".";
return false;
}
if (!proc_info.pid || ! proc_info.vsize) {
- LOG(WARNING) << "Invalid data from " << kPsPathName << ".";
+ LOG(WARNING) << "Invalid data from " << kProgram.value() << ".";
return false;
}
@@ -190,29 +188,27 @@ static bool GetProcessMemoryInfoUsingPS(
static bool GetProcessMemoryInfoUsingTop(
std::map<int,ProcessInfoSnapshot::ProcInfoEntry>& proc_info_entries) {
- const char kTopPathName[] = "/usr/bin/top";
- std::vector<std::string> argv;
- argv.push_back(kTopPathName);
+ const FilePath kProgram("/usr/bin/top");
+ CommandLine command_line(kProgram);
// -stats tells top to print just the given fields as ordered.
- argv.push_back("-stats");
- argv.push_back("pid," // Process ID
- "rsize," // Resident memory
- "rshrd," // Resident shared memory
- "rprvt," // Resident private memory
- "vsize"); // Total virtual memory
+ command_line.AppendArg("-stats");
+ command_line.AppendArg("pid," // Process ID
+ "rsize," // Resident memory
+ "rshrd," // Resident shared memory
+ "rprvt," // Resident private memory
+ "vsize"); // Total virtual memory
// Run top in logging (non-interactive) mode.
- argv.push_back("-l");
- argv.push_back("1");
+ command_line.AppendArg("-l");
+ command_line.AppendArg("1");
// Set the delay between updates to 0.
- argv.push_back("-s");
- argv.push_back("0");
+ command_line.AppendArg("-s");
+ command_line.AppendArg("0");
std::string output;
- CommandLine command_line(argv);
// Limit output read to a megabyte for safety.
if (!base::GetAppOutputRestricted(command_line, &output, 1024 * 1024)) {
- LOG(ERROR) << "Failure running " << kTopPathName << " to acquire data.";
+ LOG(ERROR) << "Failure running " << kProgram.value() << " to acquire data.";
return false;
}
@@ -274,29 +270,28 @@ static bool GetProcessMemoryInfoUsingTop(
static bool GetProcessMemoryInfoUsingTop_10_5(
std::map<int,ProcessInfoSnapshot::ProcInfoEntry>& proc_info_entries) {
- const char kTopPathName[] = "/usr/bin/top";
- std::vector<std::string> argv;
- argv.push_back(kTopPathName);
+ const FilePath kProgram("/usr/bin/top");
+ CommandLine command_line(kProgram);
// -p tells top to print just the given fields as ordered.
- argv.push_back("-p");
- argv.push_back("^aaaaaaaaaaaaaaaaaaaa " // Process ID (PID)
- "^jjjjjjjjjjjjjjjjjjjj " // Resident memory (RSIZE)
- "^iiiiiiiiiiiiiiiiiiii " // Resident shared memory (RSHRD)
- "^hhhhhhhhhhhhhhhhhhhh " // Resident private memory (RPRVT)
- "^llllllllllllllllllll"); // Total virtual memory (VSIZE)
+ command_line.AppendArg("-p");
+ command_line.AppendArg(
+ "^aaaaaaaaaaaaaaaaaaaa " // Process ID (PID)
+ "^jjjjjjjjjjjjjjjjjjjj " // Resident memory (RSIZE)
+ "^iiiiiiiiiiiiiiiiiiii " // Resident shared memory (RSHRD)
+ "^hhhhhhhhhhhhhhhhhhhh " // Resident private memory (RPRVT)
+ "^llllllllllllllllllll"); // Total virtual memory (VSIZE)
// Run top in logging (non-interactive) mode.
- argv.push_back("-l");
- argv.push_back("1");
+ command_line.AppendArg("-l");
+ command_line.AppendArg("1");
// Set the delay between updates to 0.
- argv.push_back("-s");
- argv.push_back("0");
+ command_line.AppendArg("-s");
+ command_line.AppendArg("0");
std::string output;
- CommandLine command_line(argv);
// Limit output read to a megabyte for safety.
if (!base::GetAppOutputRestricted(command_line, &output, 1024 * 1024)) {
- LOG(ERROR) << "Failure running " << kTopPathName << " to acquire data.";
+ LOG(ERROR) << "Failure running " << kProgram.value() << " to acquire data.";
return false;
}
diff --git a/chrome/browser/safe_browsing/safe_browsing_test.cc b/chrome/browser/safe_browsing/safe_browsing_test.cc
index 3c8a0aa2..a13d2f4 100644
--- a/chrome/browser/safe_browsing/safe_browsing_test.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_test.cc
@@ -141,8 +141,9 @@ class SafeBrowsingTestServer {
CommandLine cmd_line(python_runtime);
FilePath datafile = testserver_path.Append(datafile_);
cmd_line.AppendArgPath(testserver);
- cmd_line.AppendSwitchASCII("port", base::StringPrintf("%d", kPort_));
- cmd_line.AppendSwitchPath("datafile", datafile);
+ cmd_line.AppendArg(base::StringPrintf("--port=%d", kPort_));
+ cmd_line.AppendArgNative(FILE_PATH_LITERAL("--datafile=") +
+ datafile.value());
if (!base::LaunchApp(cmd_line, false, true, &server_handle_)) {
LOG(ERROR) << "Failed to launch server: "
diff --git a/chrome/browser/ui/browser_init.cc b/chrome/browser/ui/browser_init.cc
index a01a4ae..3a72032 100644
--- a/chrome/browser/ui/browser_init.cc
+++ b/chrome/browser/ui/browser_init.cc
@@ -1204,7 +1204,7 @@ std::vector<GURL> BrowserInit::GetURLsFromCommandLine(
const FilePath& cur_dir,
Profile* profile) {
std::vector<GURL> urls;
- const std::vector<CommandLine::StringType>& params = command_line.args();
+ CommandLine::StringVector params = command_line.args();
for (size_t i = 0; i < params.size(); ++i) {
FilePath param = FilePath(params[i]);
diff --git a/chrome/common/switch_utils_unittest.cc b/chrome/common/switch_utils_unittest.cc
index 528030e..49f2c38 100644
--- a/chrome/common/switch_utils_unittest.cc
+++ b/chrome/common/switch_utils_unittest.cc
@@ -6,10 +6,34 @@
#include "base/basictypes.h"
#include "base/command_line.h"
+#include "base/file_path.h"
#include "testing/gtest/include/gtest/gtest.h"
TEST(SwitchUtilsTest, RemoveSwitches) {
+ const CommandLine::CharType* argv[] = {
+ FILE_PATH_LITERAL("program"),
+ FILE_PATH_LITERAL("--app=http://www.google.com/"),
+ FILE_PATH_LITERAL("--first-run"),
+ FILE_PATH_LITERAL("--import"),
+ FILE_PATH_LITERAL("--import-from-file=c:\\test.html"),
+ FILE_PATH_LITERAL("--make-default-browser"),
+ FILE_PATH_LITERAL("--foo"),
+ FILE_PATH_LITERAL("--bar")};
+ CommandLine cmd_line(arraysize(argv), argv);
+ EXPECT_FALSE(cmd_line.command_line_string().empty());
+
+ std::map<std::string, CommandLine::StringType> switches =
+ cmd_line.GetSwitches();
+ EXPECT_EQ(7U, switches.size());
+
+ switches::RemoveSwitchesForAutostart(&switches);
+ EXPECT_EQ(2U, switches.size());
+ EXPECT_TRUE(cmd_line.HasSwitch("foo"));
+ EXPECT_TRUE(cmd_line.HasSwitch("bar"));
+}
+
#if defined(OS_WIN)
+TEST(SwitchUtilsTest, RemoveSwitchesFromString) {
// All these command line args (except foo and bar) will
// be removed after RemoveSwitchesForAutostart:
CommandLine cmd_line = CommandLine::FromString(
@@ -22,18 +46,6 @@ TEST(SwitchUtilsTest, RemoveSwitches) {
L" --foo"
L" --bar");
EXPECT_FALSE(cmd_line.command_line_string().empty());
-#elif defined(OS_POSIX)
- const char* argv[] = {
- "program",
- "--app=http://www.google.com/",
- "--first-run",
- "--import",
- "--import-from-file=c:\\test.html",
- "--make-default-browser",
- "--foo",
- "--bar"};
- CommandLine cmd_line(arraysize(argv), argv);
-#endif
std::map<std::string, CommandLine::StringType> switches =
cmd_line.GetSwitches();
@@ -44,3 +56,4 @@ TEST(SwitchUtilsTest, RemoveSwitches) {
EXPECT_TRUE(cmd_line.HasSwitch("foo"));
EXPECT_TRUE(cmd_line.HasSwitch("bar"));
}
+#endif
diff --git a/chrome/installer/util/install_util.cc b/chrome/installer/util/install_util.cc
index 480e5df..6724ca2 100644
--- a/chrome/installer/util/install_util.cc
+++ b/chrome/installer/util/install_util.cc
@@ -356,25 +356,10 @@ int InstallUtil::GetInstallReturnCode(installer::InstallStatus status) {
}
// static
-void InstallUtil::MakeUninstallCommand(const std::wstring& exe_path,
+void InstallUtil::MakeUninstallCommand(const std::wstring& program,
const std::wstring& arguments,
CommandLine* command_line) {
- const bool no_program = exe_path.empty();
-
- // Return a bunch of nothingness.
- if (no_program && arguments.empty()) {
- *command_line = CommandLine(CommandLine::NO_PROGRAM);
- } else {
- // Form a full command line string.
- std::wstring command;
- command.append(1, L'"')
- .append(no_program ? L"" : exe_path)
- .append(L"\" ")
- .append(arguments);
-
- // If we have a program name, return this complete command line.
- *command_line = CommandLine::FromString(command);
- }
+ *command_line = CommandLine::FromString(L"\"" + program + L"\" " + arguments);
}
std::wstring InstallUtil::GetCurrentDate() {
diff --git a/chrome/installer/util/install_util.h b/chrome/installer/util/install_util.h
index 5592b40..9fa9576 100644
--- a/chrome/installer/util/install_util.h
+++ b/chrome/installer/util/install_util.h
@@ -151,8 +151,8 @@ class InstallUtil {
// Returns zero on install success, or an InstallStatus value otherwise.
static int GetInstallReturnCode(installer::InstallStatus install_status);
- // Composes |exe_path| and |arguments| into |command_line|.
- static void MakeUninstallCommand(const std::wstring& exe_path,
+ // Composes |program| and |arguments| into |command_line|.
+ static void MakeUninstallCommand(const std::wstring& program,
const std::wstring& arguments,
CommandLine* command_line);
diff --git a/chrome/installer/util/product_state_unittest.cc b/chrome/installer/util/product_state_unittest.cc
index c6031359..b6c228f 100644
--- a/chrome/installer/util/product_state_unittest.cc
+++ b/chrome/installer/util/product_state_unittest.cc
@@ -303,8 +303,7 @@ TEST_F(ProductStateTest, InitializeUninstallCommand) {
ApplyUninstallCommand(NULL, L"--uninstall");
EXPECT_TRUE(state.Initialize(system_install_, dist_));
EXPECT_TRUE(state.GetSetupPath().empty());
- EXPECT_EQ(L"\"\" --uninstall",
- state.uninstall_command().command_line_string());
+ EXPECT_EQ(L" --uninstall", state.uninstall_command().command_line_string());
EXPECT_EQ(1U, state.uninstall_command().GetSwitchCount());
}
@@ -314,8 +313,18 @@ TEST_F(ProductStateTest, InitializeUninstallCommand) {
ApplyUninstallCommand(L"setup.exe", NULL);
EXPECT_TRUE(state.Initialize(system_install_, dist_));
EXPECT_EQ(L"setup.exe", state.GetSetupPath().value());
- EXPECT_EQ(L"\"setup.exe\"",
- state.uninstall_command().command_line_string());
+ EXPECT_EQ(L"setup.exe", state.uninstall_command().command_line_string());
+ EXPECT_EQ(0U, state.uninstall_command().GetSwitchCount());
+ }
+
+ // Uninstall command with exe that requires quoting.
+ {
+ ProductState state;
+ ApplyUninstallCommand(L"set up.exe", NULL);
+ EXPECT_TRUE(state.Initialize(system_install_, dist_));
+ EXPECT_EQ(L"set up.exe", state.GetSetupPath().value());
+ EXPECT_EQ(L"\"set up.exe\"",
+ state.uninstall_command().command_line_string());
EXPECT_EQ(0U, state.uninstall_command().GetSwitchCount());
}
@@ -325,7 +334,7 @@ TEST_F(ProductStateTest, InitializeUninstallCommand) {
ApplyUninstallCommand(L"setup.exe", L"--uninstall");
EXPECT_TRUE(state.Initialize(system_install_, dist_));
EXPECT_EQ(L"setup.exe", state.GetSetupPath().value());
- EXPECT_EQ(L"\"setup.exe\" --uninstall",
+ EXPECT_EQ(L"setup.exe --uninstall",
state.uninstall_command().command_line_string());
EXPECT_EQ(1U, state.uninstall_command().GetSwitchCount());
}
diff --git a/chrome/test/live_sync/live_sync_test.cc b/chrome/test/live_sync/live_sync_test.cc
index 2372f73..4bfc981 100644
--- a/chrome/test/live_sync/live_sync_test.cc
+++ b/chrome/test/live_sync/live_sync_test.cc
@@ -401,14 +401,10 @@ bool LiveSyncTest::SetUpLocalTestServer() {
CommandLine* cl = CommandLine::ForCurrentProcess();
CommandLine::StringType server_cmdline_string = cl->GetSwitchValueNative(
switches::kSyncServerCommandLine);
-#if defined(OS_WIN)
- CommandLine server_cmdline = CommandLine::FromString(server_cmdline_string);
-#else
- std::vector<std::string> server_cmdline_vector;
- std::string delimiters(" ");
+ CommandLine::StringVector server_cmdline_vector;
+ CommandLine::StringType delimiters(FILE_PATH_LITERAL(" "));
Tokenize(server_cmdline_string, delimiters, &server_cmdline_vector);
CommandLine server_cmdline(server_cmdline_vector);
-#endif
if (!base::LaunchApp(server_cmdline, false, true, &test_server_handle_))
LOG(ERROR) << "Could not launch local test server.";
diff --git a/chrome/test/ui/ui_test.cc b/chrome/test/ui/ui_test.cc
index f30fdc1..0eca725 100644
--- a/chrome/test/ui/ui_test.cc
+++ b/chrome/test/ui/ui_test.cc
@@ -521,6 +521,8 @@ ProxyLauncher* UITest::CreateProxyLauncher() {
}
static CommandLine* CreatePythonCommandLine() {
+ // Note: Python's first argument must be the script; do not append CommandLine
+ // switches, as they would precede the script path and break this CommandLine.
return new CommandLine(FilePath(FILE_PATH_LITERAL("python")));
}
@@ -547,11 +549,13 @@ void UITest::StartHttpServer(const FilePath& root_directory) {
void UITest::StartHttpServerWithPort(const FilePath& root_directory,
int port) {
+ // Append CommandLine arguments after the server script, switches won't work.
scoped_ptr<CommandLine> cmd_line(CreateHttpServerCommandLine());
ASSERT_TRUE(cmd_line.get());
- cmd_line->AppendSwitchASCII("server", "start");
- cmd_line->AppendSwitch("register_cygwin");
- cmd_line->AppendSwitchPath("root", root_directory);
+ cmd_line->AppendArg("--server=start");
+ cmd_line->AppendArg("--register_cygwin");
+ cmd_line->AppendArgNative(FILE_PATH_LITERAL("--root=") +
+ root_directory.value());
FilePath layout_tests_dir;
PathService::Get(base::DIR_SOURCE_ROOT, &layout_tests_dir);
@@ -560,18 +564,19 @@ void UITest::StartHttpServerWithPort(const FilePath& root_directory,
.AppendASCII("data")
.AppendASCII("layout_tests")
.AppendASCII("LayoutTests");
- cmd_line->AppendSwitchPath("layout_tests_dir", layout_tests_dir);
+ cmd_line->AppendArgNative(FILE_PATH_LITERAL("--layout_tests_dir=") +
+ layout_tests_dir.value());
// For Windows 7, if we start the lighttpd server on the foreground mode,
// it will mess up with the command window and cause conhost.exe to crash. To
// work around this, we start the http server on the background mode.
#if defined(OS_WIN)
if (base::win::GetVersion() >= base::win::VERSION_WIN7)
- cmd_line->AppendSwitch("run_background");
+ cmd_line->AppendArg("--run_background");
#endif
if (port)
- cmd_line->AppendSwitchASCII("port", base::IntToString(port));
+ cmd_line->AppendArg("--port=" + base::IntToString(port));
#if defined(OS_WIN)
// TODO(phajdan.jr): is this needed?
@@ -585,9 +590,10 @@ void UITest::StartHttpServerWithPort(const FilePath& root_directory,
}
void UITest::StopHttpServer() {
+ // Append CommandLine arguments after the server script, switches won't work.
scoped_ptr<CommandLine> cmd_line(CreateHttpServerCommandLine());
ASSERT_TRUE(cmd_line.get());
- cmd_line->AppendSwitchASCII("server", "stop");
+ cmd_line->AppendArg("--server=stop");
#if defined(OS_WIN)
// TODO(phajdan.jr): is this needed?
diff --git a/chrome/test/ui_test_utils.cc b/chrome/test/ui_test_utils.cc
index e7c84aa..77ce4ff 100644
--- a/chrome/test/ui_test_utils.cc
+++ b/chrome/test/ui_test_utils.cc
@@ -750,17 +750,20 @@ TestWebSocketServer::TestWebSocketServer() : started_(false) {
bool TestWebSocketServer::Start(const FilePath& root_directory) {
if (started_)
return true;
+ // Append CommandLine arguments after the server script, switches won't work.
scoped_ptr<CommandLine> cmd_line(CreateWebSocketServerCommandLine());
- cmd_line->AppendSwitchASCII("server", "start");
- cmd_line->AppendSwitch("chromium");
- cmd_line->AppendSwitch("register_cygwin");
- cmd_line->AppendSwitchPath("root", root_directory);
+ cmd_line->AppendArg("--server=start");
+ cmd_line->AppendArg("--chromium");
+ cmd_line->AppendArg("--register_cygwin");
+ cmd_line->AppendArgNative(FILE_PATH_LITERAL("--root=") +
+ root_directory.value());
if (!temp_dir_.CreateUniqueTempDir()) {
LOG(ERROR) << "Unable to create a temporary directory.";
return false;
}
websocket_pid_file_ = temp_dir_.path().AppendASCII("websocket.pid");
- cmd_line->AppendSwitchPath("pidfile", websocket_pid_file_);
+ cmd_line->AppendArgNative(FILE_PATH_LITERAL("--pidfile=") +
+ websocket_pid_file_.value());
SetPythonPath();
if (!base::LaunchApp(*cmd_line.get(), true, false, NULL)) {
LOG(ERROR) << "Unable to launch websocket server.";
@@ -771,6 +774,8 @@ bool TestWebSocketServer::Start(const FilePath& root_directory) {
}
CommandLine* TestWebSocketServer::CreatePythonCommandLine() {
+ // Note: Python's first argument must be the script; do not append CommandLine
+ // switches, as they would precede the script path and break this CommandLine.
return new CommandLine(FilePath(FILE_PATH_LITERAL("python")));
}
@@ -806,10 +811,12 @@ CommandLine* TestWebSocketServer::CreateWebSocketServerCommandLine() {
TestWebSocketServer::~TestWebSocketServer() {
if (!started_)
return;
+ // Append CommandLine arguments after the server script, switches won't work.
scoped_ptr<CommandLine> cmd_line(CreateWebSocketServerCommandLine());
- cmd_line->AppendSwitchASCII("server", "stop");
- cmd_line->AppendSwitch("chromium");
- cmd_line->AppendSwitchPath("pidfile", websocket_pid_file_);
+ cmd_line->AppendArg("--server=stop");
+ cmd_line->AppendArg("--chromium");
+ cmd_line->AppendArgNative(FILE_PATH_LITERAL("--pidfile=") +
+ websocket_pid_file_.value());
base::LaunchApp(*cmd_line.get(), true, false, NULL);
}
diff --git a/net/test/test_server.cc b/net/test/test_server.cc
index 528d08e..bd24f73 100644
--- a/net/test/test_server.cc
+++ b/net/test/test_server.cc
@@ -342,9 +342,10 @@ bool TestServer::LoadTestRootCert() {
}
bool TestServer::AddCommandLineArguments(CommandLine* command_line) const {
- command_line->AppendSwitchASCII("port",
- base::IntToString(host_port_pair_.port()));
- command_line->AppendSwitchPath("data-dir", document_root_);
+ command_line->AppendArg("--port=" +
+ base::IntToString(host_port_pair_.port()));
+ command_line->AppendArgNative(FILE_PATH_LITERAL("--data-dir=") +
+ document_root_.value());
if (logging::GetMinLogLevel() == logging::LOG_VERBOSE) {
command_line->AppendArg("--log-to-console");
@@ -363,10 +364,11 @@ bool TestServer::AddCommandLineArguments(CommandLine* command_line) const {
<< " doesn't exist. Can't launch https server.";
return false;
}
- command_line->AppendSwitchPath("https", certificate_path);
+ command_line->AppendArgNative(FILE_PATH_LITERAL("--https=") +
+ certificate_path.value());
if (https_options_.request_client_certificate)
- command_line->AppendSwitch("ssl-client-auth");
+ command_line->AppendArg("--ssl-client-auth");
for (std::vector<FilePath>::const_iterator it =
https_options_.client_authorities.begin();
@@ -377,18 +379,19 @@ bool TestServer::AddCommandLineArguments(CommandLine* command_line) const {
return false;
}
- command_line->AppendSwitchPath("ssl-client-ca", *it);
+ command_line->AppendArgNative(FILE_PATH_LITERAL("--ssl-client-ca=") +
+ it->value());
}
- const char kBulkCipherSwitch[] = "ssl-bulk-cipher";
+ const std::string kBulkCipherSwitch("--ssl-bulk-cipher");
if (https_options_.bulk_ciphers & HTTPSOptions::BULK_CIPHER_RC4)
- command_line->AppendSwitchASCII(kBulkCipherSwitch, "rc4");
+ command_line->AppendArg(kBulkCipherSwitch + "=rc4");
if (https_options_.bulk_ciphers & HTTPSOptions::BULK_CIPHER_AES128)
- command_line->AppendSwitchASCII(kBulkCipherSwitch, "aes128");
+ command_line->AppendArg(kBulkCipherSwitch + "=aes128");
if (https_options_.bulk_ciphers & HTTPSOptions::BULK_CIPHER_AES256)
- command_line->AppendSwitchASCII(kBulkCipherSwitch, "aes256");
+ command_line->AppendArg(kBulkCipherSwitch + "=aes256");
if (https_options_.bulk_ciphers & HTTPSOptions::BULK_CIPHER_3DES)
- command_line->AppendSwitchASCII(kBulkCipherSwitch, "3des");
+ command_line->AppendArg(kBulkCipherSwitch + "=3des");
}
return true;
diff --git a/net/test/test_server_posix.cc b/net/test/test_server_posix.cc
index de42fb3..10e5b8b 100644
--- a/net/test/test_server_posix.cc
+++ b/net/test/test_server_posix.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// 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.
@@ -112,8 +112,7 @@ bool TestServer::LaunchPython(const FilePath& testserver_path) {
base::file_handle_mapping_vector map_write_fd;
map_write_fd.push_back(std::make_pair(pipefd[1], pipefd[1]));
- python_command.AppendSwitchASCII("startup-pipe",
- base::IntToString(pipefd[1]));
+ python_command.AppendArg("--startup-pipe=" + base::IntToString(pipefd[1]));
// Try to kill any orphaned testserver processes that may be running.
OrphanedTestServerFilter filter(testserver_path.value(),
diff --git a/net/test/test_server_win.cc b/net/test/test_server_win.cc
index 9fc13cd..96c899e 100644
--- a/net/test/test_server_win.cc
+++ b/net/test/test_server_win.cc
@@ -176,8 +176,7 @@ bool TestServer::LaunchPython(const FilePath& testserver_path) {
// safe to truncate the handle (when passing it from 64-bit to
// 32-bit) or sign-extend the handle (when passing it from 32-bit to
// 64-bit)."
- python_command.AppendSwitchASCII(
- "startup-pipe",
+ python_command.AppendArg("--startup-pipe=" +
base::IntToString(reinterpret_cast<uintptr_t>(child_write)));
if (!LaunchTestServerAsJob(python_command,