diff options
Diffstat (limited to 'chrome/common/logging_chrome.cc')
| -rw-r--r-- | chrome/common/logging_chrome.cc | 179 |
1 files changed, 136 insertions, 43 deletions
diff --git a/chrome/common/logging_chrome.cc b/chrome/common/logging_chrome.cc index beab5b8..196c581 100644 --- a/chrome/common/logging_chrome.cc +++ b/chrome/common/logging_chrome.cc @@ -32,7 +32,7 @@ #include "base/command_line.h" #include "base/compiler_specific.h" -#include "base/debug_util.h" +#include "base/debug/debugger.h" #include "base/environment.h" #include "base/file_path.h" #include "base/file_util.h" @@ -64,8 +64,9 @@ static bool chrome_logging_redirected_ = false; #if defined(OS_WIN) // {7FE69228-633E-4f06-80C1-527FEA23E3A7} -DEFINE_GUID(kChromeTraceProviderName, - 0x7fe69228, 0x633e, 0x4f06, 0x80, 0xc1, 0x52, 0x7f, 0xea, 0x23, 0xe3, 0xa7); +static const GUID kChromeTraceProviderName = { + 0x7fe69228, 0x633e, 0x4f06, + { 0x80, 0xc1, 0x52, 0x7f, 0xea, 0x23, 0xe3, 0xa7 } }; #endif // Assertion handler for logging errors that occur when dialogs are @@ -73,7 +74,7 @@ DEFINE_GUID(kChromeTraceProviderName, // with that error in the str parameter. MSVC_DISABLE_OPTIMIZE(); static void SilentRuntimeAssertHandler(const std::string& str) { - DebugUtil::BreakDebugger(); + base::debug::BreakDebugger(); } static void SilentRuntimeReportHandler(const std::string& str) { } @@ -135,47 +136,106 @@ LoggingDestination DetermineLogMode(const CommandLine& command_line) { } #if defined(OS_CHROMEOS) -void SetUpSymlink(const FilePath& symlink_path, const FilePath& new_log_path) { - // We don't care if the unlink fails; we're going to continue anyway. - if (unlink(symlink_path.value().c_str()) == -1) - PLOG(WARNING) << "Unable to unlink " << symlink_path.value(); - if (symlink(new_log_path.value().c_str(), - symlink_path.value().c_str()) == -1) { - PLOG(ERROR) << "Unable to create symlink " << symlink_path.value() - << " pointing at " << new_log_path.value(); +namespace { +FilePath GenerateTimestampedName(const FilePath& base_path, + base::Time timestamp) { + base::Time::Exploded time_deets; + timestamp.LocalExplode(&time_deets); + std::string suffix = base::StringPrintf("_%02d%02d%02d-%02d%02d%02d", + time_deets.year, + time_deets.month, + time_deets.day_of_month, + time_deets.hour, + time_deets.minute, + time_deets.second); + return base_path.InsertBeforeExtension(suffix); +} + +FilePath SetUpSymlinkIfNeeded(const FilePath& symlink_path, bool new_log) { + DCHECK(!symlink_path.empty()); + + // If not starting a new log, then just log through the existing + // symlink, but if the symlink doesn't exist, create it. If + // starting a new log, then delete the old symlink and make a new + // one to a fresh log file. + FilePath target_path; + bool symlink_exists = file_util::PathExists(symlink_path); + if (new_log || !symlink_exists) { + target_path = GenerateTimestampedName(symlink_path, base::Time::Now()); + + // We don't care if the unlink fails; we're going to continue anyway. + if (unlink(symlink_path.value().c_str()) == -1) { + if (symlink_exists) // only warn if we might expect it to succeed. + PLOG(WARNING) << "Unable to unlink " << symlink_path.value(); + } + if (symlink(target_path.value().c_str(), + symlink_path.value().c_str()) == -1) { + PLOG(ERROR) << "Unable to create symlink " << symlink_path.value() + << " pointing at " << target_path.value(); + } + } else { + char buf[PATH_MAX]; + ssize_t count = readlink(symlink_path.value().c_str(), buf, arraysize(buf)); + if (count > 0) { + target_path = FilePath(FilePath::StringType(buf, count)); + } else { + PLOG(ERROR) << "Unable to read symlink " << symlink_path.value(); + } } + return target_path; } -FilePath TimestampLog(const FilePath& new_log_file, base::Time timestamp) { - base::Time::Exploded time_deets; - timestamp.LocalExplode(&time_deets); - std::string suffix = StringPrintf("_%02d%02d%02d-%02d%02d%02d", - time_deets.year, - time_deets.month, - time_deets.day_of_month, - time_deets.hour, - time_deets.minute, - time_deets.second); - FilePath new_log_path = new_log_file.InsertBeforeExtension(suffix); - SetUpSymlink(new_log_file, new_log_path); - - return new_log_path; +void RemoveSymlinkAndLog(const FilePath& link_path, + const FilePath& target_path) { + if (::unlink(link_path.value().c_str()) == -1) + PLOG(WARNING) << "Unable to unlink symlink " << link_path.value(); + if (::unlink(target_path.value().c_str()) == -1) + PLOG(WARNING) << "Unable to unlink log file " << target_path.value(); } -void RedirectChromeLogging(const FilePath& new_log_dir, - const CommandLine& command_line, - OldFileDeletionState delete_old_log_file) { +} // anonymous namespace + +FilePath GetSessionLogFile(const CommandLine& command_line) { + FilePath log_dir; + std::string log_dir_str; + scoped_ptr<base::Environment> env(base::Environment::Create()); + if (env->GetVar(env_vars::kSessionLogDir, &log_dir_str) && + !log_dir_str.empty()) { + log_dir = FilePath(log_dir_str); + } else { + PathService::Get(chrome::DIR_USER_DATA, &log_dir); + FilePath login_profile = + command_line.GetSwitchValuePath(switches::kLoginProfile); + log_dir = log_dir.Append(login_profile); + } + return log_dir.Append(GetLogFileName().BaseName()); +} + +void RedirectChromeLogging(const CommandLine& command_line) { DCHECK(!chrome_logging_redirected_) << "Attempted to redirect logging when it was already initialized."; - FilePath log_file_name = GetLogFileName().BaseName(); - FilePath new_log_path = - TimestampLog(new_log_dir.Append(log_file_name), base::Time::Now()); - InitLogging(new_log_path.value().c_str(), - DetermineLogMode(command_line), - logging::LOCK_LOG_FILE, - delete_old_log_file); - chrome_logging_redirected_ = true; + + // Redirect logs to the session log directory, if set. Otherwise + // defaults to the profile dir. + FilePath log_path = GetSessionLogFile(command_line); + + // Always force a new symlink when redirecting. + FilePath target_path = SetUpSymlinkIfNeeded(log_path, true); + + // ChromeOS always logs through the symlink, so it shouldn't be + // deleted if it already exists. + if (!InitLogging(log_path.value().c_str(), + DetermineLogMode(command_line), + logging::LOCK_LOG_FILE, + logging::APPEND_TO_OLD_LOG_FILE)) { + LOG(ERROR) << "Unable to initialize logging to " << log_path.value(); + RemoveSymlinkAndLog(log_path, target_path); + } else { + chrome_logging_redirected_ = true; + } } + + #endif void InitChromeLogging(const CommandLine& command_line, @@ -188,21 +248,54 @@ void InitChromeLogging(const CommandLine& command_line, #endif FilePath log_path = GetLogFileName(); + #if defined(OS_CHROMEOS) - log_path = TimestampLog(log_path, base::Time::Now()); + // For BWSI (Incognito) logins, we want to put the logs in the user + // profile directory that is created for the temporary session instead + // of in the system log directory, for privacy reasons. + if (command_line.HasSwitch(switches::kGuestSession)) + log_path = GetSessionLogFile(command_line); + + // On ChromeOS we log to the symlink. We force creation of a new + // symlink if we've been asked to delete the old log, since that + // indicates the start of a new session. + FilePath target_path = SetUpSymlinkIfNeeded( + log_path, delete_old_log_file == logging::DELETE_OLD_LOG_FILE); + + // Because ChromeOS manages the move to a new session by redirecting + // the link, it shouldn't remove the old file in the logging code, + // since that will remove the newly created link instead. + delete_old_log_file = logging::APPEND_TO_OLD_LOG_FILE; #endif - logging::InitLogging(log_path.value().c_str(), - DetermineLogMode(command_line), - logging::LOCK_LOG_FILE, - delete_old_log_file); + bool success = InitLogging(log_path.value().c_str(), + DetermineLogMode(command_line), + logging::LOCK_LOG_FILE, + delete_old_log_file); + +#if defined(OS_CHROMEOS) + if (!success) { + PLOG(ERROR) << "Unable to initialize logging to " << log_path.value() + << " (which should be a link to " << target_path.value() << ")"; + RemoveSymlinkAndLog(log_path, target_path); + return; + } +#else + if (!success) { + PLOG(ERROR) << "Unable to initialize logging to " << log_path.value(); + return; + } +#endif // Default to showing error dialogs. if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoErrorDialogs)) logging::SetShowErrorDialogs(true); // we want process and thread IDs because we have a lot of things running - logging::SetLogItems(true, true, false, true); + logging::SetLogItems(true, // enable_process_id + true, // enable_thread_id + false, // enable_timestamp + true); // enable_tickcount // We call running in unattended mode "headless", and allow // headless mode to be configured either by the Environment |
