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"
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread_restrictions.h"
46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.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)
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(OS_CHROMEOS)
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/chromeos_switches.h"
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <initguid.h>
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging_win.h"
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// When true, this means that error dialogs should not be shown.
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool dialogs_are_suppressed_ = false;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This should be true for exactly the period between the end of
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// InitChromeLogging() and the beginning of CleanupChromeLogging().
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool chrome_logging_initialized_ = false;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Set if we called InitChromeLogging() but failed to initialize.
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool chrome_logging_failed_ = false;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This should be true for exactly the period between the end of
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// InitChromeLogging() and the beginning of CleanupChromeLogging().
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool chrome_logging_redirected_ = false;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// {7FE69228-633E-4f06-80C1-527FEA23E3A7}
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const GUID kChromeTraceProviderName = {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0x7fe69228, 0x633e, 0x4f06,
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        { 0x80, 0xc1, 0x52, 0x7f, 0xea, 0x23, 0xe3, 0xa7 } };
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Assertion handler for logging errors that occur when dialogs are
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// silenced.  To record a new error, pass the log string associated
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// with that error in the str parameter.
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MSVC_DISABLE_OPTIMIZE();
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SilentRuntimeAssertHandler(const std::string& str) {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::debug::BreakDebugger();
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SilentRuntimeReportHandler(const std::string& str) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Handler to silently dump the current process when there is an assert in
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// chrome.
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DumpProcessAssertHandler(const std::string& str) {
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  logging::DumpWithoutCrashing();
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // OS_WIN
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MSVC_ENABLE_OPTIMIZE();
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Suppresses error/assertion dialogs and enables the logging of
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// those errors into silenced_errors_.
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SuppressDialogs() {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (dialogs_are_suppressed_)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  logging::SetLogAssertHandler(SilentRuntimeAssertHandler);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  logging::SetLogReportHandler(SilentRuntimeReportHandler);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UINT new_flags = SEM_FAILCRITICALERRORS |
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   SEM_NOGPFAULTERRORBOX |
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   SEM_NOOPENFILEERRORBOX;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Preserve existing error mode, as discussed at http://t/dmea
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UINT existing_flags = SetErrorMode(new_flags);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetErrorMode(existing_flags | new_flags);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dialogs_are_suppressed_ = true;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // anonymous namespace
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace logging {
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LoggingDestination DetermineLogMode(const CommandLine& command_line) {
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // only use OutputDebugString in debug mode
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef NDEBUG
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool enable_logging = false;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *kInvertLoggingSwitch = switches::kEnableLogging;
135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const logging::LoggingDestination kDefaultLoggingMode = logging::LOG_TO_FILE;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool enable_logging = true;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *kInvertLoggingSwitch = switches::kDisableLogging;
139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const logging::LoggingDestination kDefaultLoggingMode = logging::LOG_TO_ALL;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (command_line.HasSwitch(kInvertLoggingSwitch))
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    enable_logging = !enable_logging;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  logging::LoggingDestination log_mode;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (enable_logging) {
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Let --enable-logging=stderr force only stderr, particularly useful for
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // non-debug builds where otherwise you can't get logs to stderr at all.
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (command_line.GetSwitchValueASCII(switches::kEnableLogging) == "stderr")
150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      log_mode = logging::LOG_TO_SYSTEM_DEBUG_LOG;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      log_mode = kDefaultLoggingMode;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    log_mode = logging::LOG_NONE;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return log_mode;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath SetUpSymlinkIfNeeded(const base::FilePath& symlink_path,
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    bool new_log) {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!symlink_path.empty());
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If not starting a new log, then just log through the existing
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // symlink, but if the symlink doesn't exist, create it.  If
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // starting a new log, then delete the old symlink and make a new
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // one to a fresh log file.
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath target_path;
1707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  bool symlink_exists = base::PathExists(symlink_path);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (new_log || !symlink_exists) {
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    target_path = GenerateTimestampedName(symlink_path, base::Time::Now());
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We don't care if the unlink fails; we're going to continue anyway.
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (::unlink(symlink_path.value().c_str()) == -1) {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (symlink_exists) // only warn if we might expect it to succeed.
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DPLOG(WARNING) << "Unable to unlink " << symlink_path.value();
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!file_util::CreateSymbolicLink(target_path, symlink_path)) {
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DPLOG(ERROR) << "Unable to create symlink " << symlink_path.value()
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   << " pointing at " << target_path.value();
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!file_util::ReadSymbolicLink(symlink_path, &target_path))
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DPLOG(ERROR) << "Unable to read symlink " << symlink_path.value();
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return target_path;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void RemoveSymlinkAndLog(const base::FilePath& link_path,
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         const base::FilePath& target_path) {
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (::unlink(link_path.value().c_str()) == -1)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DPLOG(WARNING) << "Unable to unlink symlink " << link_path.value();
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (::unlink(target_path.value().c_str()) == -1)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DPLOG(WARNING) << "Unable to unlink log file " << target_path.value();
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // anonymous namespace
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath GetSessionLogFile(const CommandLine& command_line) {
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath log_dir;
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string log_dir_str;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<base::Environment> env(base::Environment::Create());
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (env->GetVar(env_vars::kSessionLogDir, &log_dir_str) &&
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !log_dir_str.empty()) {
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    log_dir = base::FilePath(log_dir_str);
20790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else if (command_line.HasSwitch(chromeos::switches::kLoginProfile)) {
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PathService::Get(chrome::DIR_USER_DATA, &log_dir);
20990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    base::FilePath profile_dir;
21090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (command_line.HasSwitch(switches::kMultiProfiles)) {
21190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // We could not use g_browser_process > profile_helper() here.
21290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      std::string profile_dir_str = chrome::kProfileDirPrefix;
21390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      profile_dir_str.append(
21490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          command_line.GetSwitchValueASCII(chromeos::switches::kLoginProfile));
21590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      profile_dir = base::FilePath(profile_dir_str);
21690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    } else {
21790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      profile_dir =
21890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          command_line.GetSwitchValuePath(chromeos::switches::kLoginProfile);
21990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
22090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    log_dir = log_dir.Append(profile_dir);
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return log_dir.Append(GetLogFileName().BaseName());
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RedirectChromeLogging(const CommandLine& command_line) {
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kMultiProfiles) &&
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      chrome_logging_redirected_) {
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // TODO(nkostylev): Support multiple active users. http://crbug.com/230345
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(ERROR) << "NOT redirecting logging for multi-profiles case.";
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!chrome_logging_redirected_) <<
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Attempted to redirect logging when it was already initialized.";
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Redirect logs to the session log directory, if set.  Otherwise
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // defaults to the profile dir.
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath log_path = GetSessionLogFile(command_line);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Creating symlink causes us to do blocking IO on UI thread.
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Temporarily allow it until we fix http://crbug.com/61143
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::ThreadRestrictions::ScopedAllowIO allow_io;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Always force a new symlink when redirecting.
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath target_path = SetUpSymlinkIfNeeded(log_path, true);
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  logging::DcheckState dcheck_state =
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      command_line.HasSwitch(switches::kEnableDCHECK) ?
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      logging::ENABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS :
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      logging::DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ChromeOS always logs through the symlink, so it shouldn't be
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // deleted if it already exists.
253eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  logging::LoggingSettings settings;
254eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  settings.logging_dest = DetermineLogMode(command_line);
255eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  settings.log_file = log_path.value().c_str();
256eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  settings.dcheck_state = dcheck_state;
257eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!logging::InitLogging(settings)) {
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(ERROR) << "Unable to initialize logging to " << log_path.value();
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RemoveSymlinkAndLog(log_path, target_path);
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    chrome_logging_redirected_ = true;
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // OS_CHROMEOS
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InitChromeLogging(const CommandLine& command_line,
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       OldFileDeletionState delete_old_log_file) {
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!chrome_logging_initialized_) <<
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Attempted to initialize logging when it was already initialized.";
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LoggingDestination logging_dest = DetermineLogMode(command_line);
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogLockingState log_locking_state = LOCK_LOG_FILE;
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath log_path;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS)
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath target_path;
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't resolve the log path unless we need to. Otherwise we leave an open
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ALPC handle after sandbox lockdown on Windows.
281eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if ((logging_dest & LOG_TO_FILE) != 0) {
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    log_path = GetLogFileName();
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // For BWSI (Incognito) logins, we want to put the logs in the user
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // profile directory that is created for the temporary session instead
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // of in the system log directory, for privacy reasons.
288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (command_line.HasSwitch(chromeos::switches::kGuestSession))
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      log_path = GetSessionLogFile(command_line);
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // On ChromeOS we log to the symlink.  We force creation of a new
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // symlink if we've been asked to delete the old log, since that
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // indicates the start of a new session.
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    target_path = SetUpSymlinkIfNeeded(
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        log_path, delete_old_log_file == logging::DELETE_OLD_LOG_FILE);
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Because ChromeOS manages the move to a new session by redirecting
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the link, it shouldn't remove the old file in the logging code,
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // since that will remove the newly created link instead.
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete_old_log_file = logging::APPEND_TO_OLD_LOG_FILE;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    log_locking_state = DONT_LOCK_LOG_FILE;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  logging::DcheckState dcheck_state =
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      command_line.HasSwitch(switches::kEnableDCHECK) ?
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      logging::ENABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS :
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      logging::DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS;
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
311eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  logging::LoggingSettings settings;
312eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  settings.logging_dest = logging_dest;
313eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  settings.log_file = log_path.value().c_str();
314eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  settings.lock_log = log_locking_state;
315eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  settings.delete_old = delete_old_log_file;
316eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  settings.dcheck_state = dcheck_state;
317eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  bool success = logging::InitLogging(settings);
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!success) {
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DPLOG(ERROR) << "Unable to initialize logging to " << log_path.value()
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                << " (which should be a link to " << target_path.value() << ")";
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RemoveSymlinkAndLog(log_path, target_path);
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    chrome_logging_failed_ = true;
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!success) {
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DPLOG(ERROR) << "Unable to initialize logging to " << log_path.value();
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    chrome_logging_failed_ = true;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Default to showing error dialogs.
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoErrorDialogs))
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    logging::SetShowErrorDialogs(true);
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we want process and thread IDs because we have a lot of things running
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  logging::SetLogItems(true,  // enable_process_id
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       true,  // enable_thread_id
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       true,  // enable_timestamp
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       false);  // enable_tickcount
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We call running in unattended mode "headless", and allow
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // headless mode to be configured either by the Environment
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Variable or by the Command Line Switch.  This is for
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // automated test purposes.
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<base::Environment> env(base::Environment::Create());
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (env->HasVar(env_vars::kHeadless) ||
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      command_line.HasSwitch(switches::kNoErrorDialogs))
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SuppressDialogs();
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use a minimum log level if the command line asks for one,
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // otherwise leave it at the default level (INFO).
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (command_line.HasSwitch(switches::kLoggingLevel)) {
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string log_level = command_line.GetSwitchValueASCII(
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        switches::kLoggingLevel);
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int level = 0;
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (base::StringToInt(log_level, &level) &&
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        level >= 0 && level < LOG_NUM_SEVERITIES) {
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      logging::SetMinLogLevel(level);
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DLOG(WARNING) << "Bad log level: " << log_level;
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Enable trace control and transport through event tracing for Windows.
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  logging::LogEventProvider::Initialize(kChromeTraceProviderName);
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef NDEBUG
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (command_line.HasSwitch(switches::kSilentDumpOnDCHECK) &&
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      command_line.HasSwitch(switches::kEnableDCHECK)) {
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    logging::SetLogReportHandler(DumpProcessAssertHandler);
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // NDEBUG
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  chrome_logging_initialized_ = true;
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is a no-op, but we'll keep it around in case
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// we need to do more cleanup in the future.
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CleanupChromeLogging() {
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (chrome_logging_failed_)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // We failed to initiailize logging, no cleanup.
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(chrome_logging_initialized_) <<
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Attempted to clean up logging when it wasn't initialized.";
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CloseLogFile();
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  chrome_logging_initialized_ = false;
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  chrome_logging_redirected_ = false;
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath GetLogFileName() {
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string filename;
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<base::Environment> env(base::Environment::Create());
403868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (env->GetVar(env_vars::kLogFileName, &filename) && !filename.empty())
404868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return base::FilePath::FromUTF8Unsafe(filename);
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::FilePath log_filename(FILE_PATH_LITERAL("chrome_debug.log"));
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath log_path;
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (PathService::Get(chrome::DIR_LOGS, &log_path)) {
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    log_path = log_path.Append(log_filename);
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return log_path;
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // error with path service, just use some default file somewhere
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return log_filename;
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DialogsAreSuppressed() {
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return dialogs_are_suppressed_;
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t GetFatalAssertions(AssertionList* assertions) {
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In this function, we don't assume that assertions is non-null, so
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // that if you just want an assertion count, you can pass in NULL.
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (assertions)
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assertions->clear();
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t assertion_count = 0;
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::ifstream log_file;
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  log_file.open(GetLogFileName().value().c_str());
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!log_file.is_open())
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string utf8_line;
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring wide_line;
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (!log_file.eof()) {
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    getline(log_file, utf8_line);
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (utf8_line.find(":FATAL:") != std::string::npos) {
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      wide_line = UTF8ToWide(utf8_line);
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (assertions)
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assertions->push_back(wide_line);
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++assertion_count;
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  log_file.close();
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return assertion_count;
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath GenerateTimestampedName(const base::FilePath& base_path,
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       base::Time timestamp) {
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Time::Exploded time_deets;
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timestamp.LocalExplode(&time_deets);
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string suffix = base::StringPrintf("_%02d%02d%02d-%02d%02d%02d",
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          time_deets.year,
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          time_deets.month,
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          time_deets.day_of_month,
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          time_deets.hour,
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          time_deets.minute,
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          time_deets.second);
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return base_path.InsertBeforeExtensionASCII(suffix);
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace logging
465