logging_chrome.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "build/build_config.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Need to include this before most other files because it defines
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// IPC_MESSAGE_LOG_ENABLED. We need to use it to define
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// IPC_MESSAGE_MACROS_LOG_ENABLED so render_messages.h will generate the
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ViewMsgLog et al. functions.
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_message.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// On Windows, the about:ipc dialog shows IPCs; on POSIX, we hook up a
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// logger in this file.  (We implement about:ipc on Mac but implement
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the loggers here anyway).  We need to do this real early to be sure
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// IPC_MESSAGE_MACROS_LOG_ENABLED doesn't get undefined.
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX) && defined(IPC_MESSAGE_LOG_ENABLED)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define IPC_MESSAGE_MACROS_LOG_ENABLED
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/content_ipc_logging.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define IPC_LOG_TABLE_ADD_ENTRY(msg_id, logger) \
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::RegisterIPCLogger(msg_id, logger)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/all_messages.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h>
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <fstream>
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/logging_chrome.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/debugger.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/environment.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h"
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h"
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/string_util.h"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stringprintf.h"
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread_restrictions.h"
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/time.h"
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/utf_string_conversions.h"
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_constants.h"
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_paths.h"
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h"
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/dump_without_crashing.h"
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/env_vars.h"
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_logging.h"
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <initguid.h>
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging_win.h"
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// When true, this means that error dialogs should not be shown.
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool dialogs_are_suppressed_ = false;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This should be true for exactly the period between the end of
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// InitChromeLogging() and the beginning of CleanupChromeLogging().
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool chrome_logging_initialized_ = false;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Set if we called InitChromeLogging() but failed to initialize.
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool chrome_logging_failed_ = false;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This should be true for exactly the period between the end of
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// InitChromeLogging() and the beginning of CleanupChromeLogging().
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool chrome_logging_redirected_ = false;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// {7FE69228-633E-4f06-80C1-527FEA23E3A7}
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const GUID kChromeTraceProviderName = {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0x7fe69228, 0x633e, 0x4f06,
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        { 0x80, 0xc1, 0x52, 0x7f, 0xea, 0x23, 0xe3, 0xa7 } };
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Assertion handler for logging errors that occur when dialogs are
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// silenced.  To record a new error, pass the log string associated
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// with that error in the str parameter.
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MSVC_DISABLE_OPTIMIZE();
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SilentRuntimeAssertHandler(const std::string& str) {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::debug::BreakDebugger();
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SilentRuntimeReportHandler(const std::string& str) {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Handler to silently dump the current process when there is an assert in
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// chrome.
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DumpProcessAssertHandler(const std::string& str) {
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  logging::DumpWithoutCrashing();
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // OS_WIN
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MSVC_ENABLE_OPTIMIZE();
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Suppresses error/assertion dialogs and enables the logging of
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// those errors into silenced_errors_.
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SuppressDialogs() {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (dialogs_are_suppressed_)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  logging::SetLogAssertHandler(SilentRuntimeAssertHandler);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  logging::SetLogReportHandler(SilentRuntimeReportHandler);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UINT new_flags = SEM_FAILCRITICALERRORS |
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   SEM_NOGPFAULTERRORBOX |
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   SEM_NOOPENFILEERRORBOX;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Preserve existing error mode, as discussed at http://t/dmea
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UINT existing_flags = SetErrorMode(new_flags);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetErrorMode(existing_flags | new_flags);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dialogs_are_suppressed_ = true;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // anonymous namespace
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace logging {
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LoggingDestination DetermineLogMode(const CommandLine& command_line) {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // only use OutputDebugString in debug mode
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef NDEBUG
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool enable_logging = false;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *kInvertLoggingSwitch = switches::kEnableLogging;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const logging::LoggingDestination kDefaultLoggingMode =
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      logging::LOG_ONLY_TO_FILE;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool enable_logging = true;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *kInvertLoggingSwitch = switches::kDisableLogging;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const logging::LoggingDestination kDefaultLoggingMode =
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      logging::LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (command_line.HasSwitch(kInvertLoggingSwitch))
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    enable_logging = !enable_logging;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  logging::LoggingDestination log_mode;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (enable_logging) {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Let --enable-logging=stderr force only stderr, particularly useful for
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // non-debug builds where otherwise you can't get logs to stderr at all.
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (command_line.GetSwitchValueASCII(switches::kEnableLogging) == "stderr")
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      log_mode = logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      log_mode = kDefaultLoggingMode;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    log_mode = logging::LOG_NONE;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return log_mode;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath SetUpSymlinkIfNeeded(const base::FilePath& symlink_path,
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    bool new_log) {
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!symlink_path.empty());
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If not starting a new log, then just log through the existing
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // symlink, but if the symlink doesn't exist, create it.  If
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // starting a new log, then delete the old symlink and make a new
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // one to a fresh log file.
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath target_path;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool symlink_exists = file_util::PathExists(symlink_path);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (new_log || !symlink_exists) {
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    target_path = GenerateTimestampedName(symlink_path, base::Time::Now());
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We don't care if the unlink fails; we're going to continue anyway.
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (::unlink(symlink_path.value().c_str()) == -1) {
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (symlink_exists) // only warn if we might expect it to succeed.
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DPLOG(WARNING) << "Unable to unlink " << symlink_path.value();
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!file_util::CreateSymbolicLink(target_path, symlink_path)) {
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DPLOG(ERROR) << "Unable to create symlink " << symlink_path.value()
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   << " pointing at " << target_path.value();
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!file_util::ReadSymbolicLink(symlink_path, &target_path))
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DPLOG(ERROR) << "Unable to read symlink " << symlink_path.value();
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return target_path;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void RemoveSymlinkAndLog(const base::FilePath& link_path,
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         const base::FilePath& target_path) {
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (::unlink(link_path.value().c_str()) == -1)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DPLOG(WARNING) << "Unable to unlink symlink " << link_path.value();
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (::unlink(target_path.value().c_str()) == -1)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DPLOG(WARNING) << "Unable to unlink log file " << target_path.value();
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // anonymous namespace
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath GetSessionLogFile(const CommandLine& command_line) {
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath log_dir;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string log_dir_str;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<base::Environment> env(base::Environment::Create());
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (env->GetVar(env_vars::kSessionLogDir, &log_dir_str) &&
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !log_dir_str.empty()) {
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    log_dir = base::FilePath(log_dir_str);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PathService::Get(chrome::DIR_USER_DATA, &log_dir);
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath login_profile =
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        command_line.GetSwitchValuePath(switches::kLoginProfile);
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    log_dir = log_dir.Append(login_profile);
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return log_dir.Append(GetLogFileName().BaseName());
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RedirectChromeLogging(const CommandLine& command_line) {
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!chrome_logging_redirected_) <<
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Attempted to redirect logging when it was already initialized.";
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Redirect logs to the session log directory, if set.  Otherwise
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // defaults to the profile dir.
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath log_path = GetSessionLogFile(command_line);
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Creating symlink causes us to do blocking IO on UI thread.
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Temporarily allow it until we fix http://crbug.com/61143
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::ThreadRestrictions::ScopedAllowIO allow_io;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Always force a new symlink when redirecting.
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath target_path = SetUpSymlinkIfNeeded(log_path, true);
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  logging::DcheckState dcheck_state =
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      command_line.HasSwitch(switches::kEnableDCHECK) ?
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      logging::ENABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS :
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      logging::DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS;
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ChromeOS always logs through the symlink, so it shouldn't be
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // deleted if it already exists.
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!InitLogging(log_path.value().c_str(),
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   DetermineLogMode(command_line),
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   logging::LOCK_LOG_FILE,
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   logging::APPEND_TO_OLD_LOG_FILE,
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   dcheck_state)) {
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(ERROR) << "Unable to initialize logging to " << log_path.value();
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RemoveSymlinkAndLog(log_path, target_path);
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    chrome_logging_redirected_ = true;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // OS_CHROMEOS
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InitChromeLogging(const CommandLine& command_line,
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       OldFileDeletionState delete_old_log_file) {
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!chrome_logging_initialized_) <<
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Attempted to initialize logging when it was already initialized.";
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LoggingDestination logging_dest = DetermineLogMode(command_line);
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogLockingState log_locking_state = LOCK_LOG_FILE;
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath log_path;
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS)
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath target_path;
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't resolve the log path unless we need to. Otherwise we leave an open
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ALPC handle after sandbox lockdown on Windows.
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (logging_dest == LOG_ONLY_TO_FILE ||
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      logging_dest == LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG) {
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    log_path = GetLogFileName();
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // For BWSI (Incognito) logins, we want to put the logs in the user
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // profile directory that is created for the temporary session instead
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // of in the system log directory, for privacy reasons.
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (command_line.HasSwitch(switches::kGuestSession))
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      log_path = GetSessionLogFile(command_line);
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // On ChromeOS we log to the symlink.  We force creation of a new
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // symlink if we've been asked to delete the old log, since that
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // indicates the start of a new session.
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    target_path = SetUpSymlinkIfNeeded(
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        log_path, delete_old_log_file == logging::DELETE_OLD_LOG_FILE);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Because ChromeOS manages the move to a new session by redirecting
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the link, it shouldn't remove the old file in the logging code,
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // since that will remove the newly created link instead.
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete_old_log_file = logging::APPEND_TO_OLD_LOG_FILE;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    log_locking_state = DONT_LOCK_LOG_FILE;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  logging::DcheckState dcheck_state =
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      command_line.HasSwitch(switches::kEnableDCHECK) ?
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      logging::ENABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS :
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      logging::DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS;
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool success = InitLogging(log_path.value().c_str(),
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             logging_dest,
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             log_locking_state,
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             delete_old_log_file,
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             dcheck_state);
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!success) {
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DPLOG(ERROR) << "Unable to initialize logging to " << log_path.value()
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                << " (which should be a link to " << target_path.value() << ")";
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RemoveSymlinkAndLog(log_path, target_path);
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    chrome_logging_failed_ = true;
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!success) {
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DPLOG(ERROR) << "Unable to initialize logging to " << log_path.value();
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    chrome_logging_failed_ = true;
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Default to showing error dialogs.
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoErrorDialogs))
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    logging::SetShowErrorDialogs(true);
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we want process and thread IDs because we have a lot of things running
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  logging::SetLogItems(true,  // enable_process_id
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       true,  // enable_thread_id
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       true,  // enable_timestamp
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       false);  // enable_tickcount
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We call running in unattended mode "headless", and allow
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // headless mode to be configured either by the Environment
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Variable or by the Command Line Switch.  This is for
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // automated test purposes.
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<base::Environment> env(base::Environment::Create());
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (env->HasVar(env_vars::kHeadless) ||
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      command_line.HasSwitch(switches::kNoErrorDialogs))
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SuppressDialogs();
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use a minimum log level if the command line asks for one,
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // otherwise leave it at the default level (INFO).
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (command_line.HasSwitch(switches::kLoggingLevel)) {
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string log_level = command_line.GetSwitchValueASCII(
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        switches::kLoggingLevel);
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int level = 0;
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (base::StringToInt(log_level, &level) &&
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        level >= 0 && level < LOG_NUM_SEVERITIES) {
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      logging::SetMinLogLevel(level);
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DLOG(WARNING) << "Bad log level: " << log_level;
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Enable trace control and transport through event tracing for Windows.
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  logging::LogEventProvider::Initialize(kChromeTraceProviderName);
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef NDEBUG
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (command_line.HasSwitch(switches::kSilentDumpOnDCHECK) &&
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      command_line.HasSwitch(switches::kEnableDCHECK)) {
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    logging::SetLogReportHandler(DumpProcessAssertHandler);
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // NDEBUG
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  chrome_logging_initialized_ = true;
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is a no-op, but we'll keep it around in case
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// we need to do more cleanup in the future.
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CleanupChromeLogging() {
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (chrome_logging_failed_)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // We failed to initiailize logging, no cleanup.
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(chrome_logging_initialized_) <<
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Attempted to clean up logging when it wasn't initialized.";
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CloseLogFile();
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  chrome_logging_initialized_ = false;
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  chrome_logging_redirected_ = false;
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath GetLogFileName() {
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string filename;
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<base::Environment> env(base::Environment::Create());
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (env->GetVar(env_vars::kLogFileName, &filename) && !filename.empty()) {
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return base::FilePath(UTF8ToWide(filename));
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_POSIX)
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return base::FilePath(filename);
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::FilePath log_filename(FILE_PATH_LITERAL("chrome_debug.log"));
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath log_path;
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (PathService::Get(chrome::DIR_LOGS, &log_path)) {
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    log_path = log_path.Append(log_filename);
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return log_path;
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // error with path service, just use some default file somewhere
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return log_filename;
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DialogsAreSuppressed() {
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return dialogs_are_suppressed_;
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t GetFatalAssertions(AssertionList* assertions) {
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In this function, we don't assume that assertions is non-null, so
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // that if you just want an assertion count, you can pass in NULL.
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (assertions)
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assertions->clear();
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t assertion_count = 0;
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::ifstream log_file;
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  log_file.open(GetLogFileName().value().c_str());
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!log_file.is_open())
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string utf8_line;
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring wide_line;
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (!log_file.eof()) {
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    getline(log_file, utf8_line);
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (utf8_line.find(":FATAL:") != std::string::npos) {
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      wide_line = UTF8ToWide(utf8_line);
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (assertions)
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assertions->push_back(wide_line);
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++assertion_count;
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  log_file.close();
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return assertion_count;
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath GenerateTimestampedName(const base::FilePath& base_path,
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       base::Time timestamp) {
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Time::Exploded time_deets;
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timestamp.LocalExplode(&time_deets);
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string suffix = base::StringPrintf("_%02d%02d%02d-%02d%02d%02d",
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          time_deets.year,
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          time_deets.month,
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          time_deets.day_of_month,
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          time_deets.hour,
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          time_deets.minute,
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          time_deets.second);
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return base_path.InsertBeforeExtensionASCII(suffix);
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace logging
451