blob: b2a83818e9753bd347754edf8e2bb0980ba79f79 [file] [log] [blame]
license.botbf09a502008-08-24 00:55:551// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
[email protected]ec657802008-11-07 20:05:395#include "build/build_config.h"
6
7#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:298#include <windows.h>
[email protected]ec657802008-11-07 20:05:399#endif
initial.commit09911bf2008-07-26 23:55:2910
11#include <iostream>
12#include <fstream>
13
14#include "chrome/common/logging_chrome.h"
15
16#include "base/command_line.h"
[email protected]ec657802008-11-07 20:05:3917#include "base/debug_util.h"
initial.commit09911bf2008-07-26 23:55:2918#include "base/file_util.h"
19#include "base/logging.h"
20#include "base/path_service.h"
21#include "base/string_util.h"
[email protected]05f9b682008-09-29 22:18:0122#include "base/sys_info.h"
initial.commit09911bf2008-07-26 23:55:2923#include "chrome/common/chrome_paths.h"
24#include "chrome/common/chrome_switches.h"
initial.commit09911bf2008-07-26 23:55:2925#include "chrome/common/env_vars.h"
26
27// When true, this means that error dialogs should not be shown.
28static bool dialogs_are_suppressed_ = false;
29
30// This should be true for exactly the period between the end of
31// InitChromeLogging() and the beginning of CleanupChromeLogging().
32static bool chrome_logging_initialized_ = false;
33
34// Assertion handler for logging errors that occur when dialogs are
35// silenced. To record a new error, pass the log string associated
36// with that error in the str parameter.
37#pragma optimize("", off)
38static void SilentRuntimeAssertHandler(const std::string& str) {
[email protected]ec657802008-11-07 20:05:3939 DebugUtil::BreakDebugger();
initial.commit09911bf2008-07-26 23:55:2940}
41#pragma optimize("", on)
42
43// Suppresses error/assertion dialogs and enables the logging of
44// those errors into silenced_errors_.
45static void SuppressDialogs() {
46 if (dialogs_are_suppressed_)
47 return;
48
49 logging::SetLogAssertHandler(SilentRuntimeAssertHandler);
50
[email protected]ec657802008-11-07 20:05:3951#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:2952 UINT new_flags = SEM_FAILCRITICALERRORS |
53 SEM_NOGPFAULTERRORBOX |
54 SEM_NOOPENFILEERRORBOX;
55
56 // Preserve existing error mode, as discussed at http://t/dmea
57 UINT existing_flags = SetErrorMode(new_flags);
58 SetErrorMode(existing_flags | new_flags);
[email protected]ec657802008-11-07 20:05:3959#endif
initial.commit09911bf2008-07-26 23:55:2960
61 dialogs_are_suppressed_ = true;
62}
63
64namespace logging {
65
66void InitChromeLogging(const CommandLine& command_line,
67 OldFileDeletionState delete_old_log_file) {
68 DCHECK(!chrome_logging_initialized_) <<
69 "Attempted to initialize logging when it was already initialized.";
70
71 // only use OutputDebugString in debug mode
72#ifdef NDEBUG
73 bool enable_logging = false;
74 const wchar_t *kInvertLoggingSwitch = switches::kEnableLogging;
75 const logging::LoggingDestination kDefaultLoggingMode =
76 logging::LOG_ONLY_TO_FILE;
77#else
78 bool enable_logging = true;
79 const wchar_t *kInvertLoggingSwitch = switches::kDisableLogging;
80 const logging::LoggingDestination kDefaultLoggingMode =
81 logging::LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG;
82#endif
83
84 if (command_line.HasSwitch(kInvertLoggingSwitch))
85 enable_logging = !enable_logging;
86
87 logging::LoggingDestination log_mode;
88 if (enable_logging) {
89 log_mode = kDefaultLoggingMode;
90 } else {
91 log_mode = logging::LOG_NONE;
92 }
93
[email protected]ec657802008-11-07 20:05:3994#if defined(OS_POSIX)
95 std::string log_file_name = WideToUTF8(GetLogFileName());
96#elif defined(OS_WIN)
97 std::wstring log_file_name = GetLogFileName();
98#endif
99
100 logging::InitLogging(log_file_name.c_str(),
initial.commit09911bf2008-07-26 23:55:29101 log_mode,
102 logging::LOCK_LOG_FILE,
103 delete_old_log_file);
104
105 // we want process and thread IDs because we have a lot of things running
106 logging::SetLogItems(true, true, false, true);
107
108 // We call running in unattended mode "headless", and allow
109 // headless mode to be configured either by the Environment
110 // Variable or by the Command Line Switch. This is for
111 // automated test purposes.
[email protected]05f9b682008-09-29 22:18:01112 if (base::SysInfo::HasEnvVar(env_vars::kHeadless) ||
initial.commit09911bf2008-07-26 23:55:29113 command_line.HasSwitch(switches::kNoErrorDialogs))
114 SuppressDialogs();
115
116 std::wstring log_filter_prefix =
117 command_line.GetSwitchValue(switches::kLogFilterPrefix);
118 logging::SetLogFilterPrefix(WideToUTF8(log_filter_prefix).c_str());
119
[email protected]bb5185c52008-08-29 19:51:06120 // Use a minimum log level if the command line has one, otherwise set the
121 // default to LOG_WARNING.
122 std::wstring log_level = command_line.GetSwitchValue(switches::kLoggingLevel);
123 int level = 0;
124 if (StringToInt(log_level, &level)) {
125 if ((level >= 0) && (level < LOG_NUM_SEVERITIES))
126 logging::SetMinLogLevel(level);
127 } else {
128 logging::SetMinLogLevel(LOG_WARNING);
129 }
130
initial.commit09911bf2008-07-26 23:55:29131 chrome_logging_initialized_ = true;
132}
133
134// This is a no-op, but we'll keep it around in case
135// we need to do more cleanup in the future.
136void CleanupChromeLogging() {
137 DCHECK(chrome_logging_initialized_) <<
138 "Attempted to clean up logging when it wasn't initialized.";
139
140 CloseLogFile();
141
142 chrome_logging_initialized_ = false;
143}
144
145std::wstring GetLogFileName() {
[email protected]ec657802008-11-07 20:05:39146 std::wstring filename = base::SysInfo::GetEnvVar(env_vars::kLogFileName);
147 if (filename != L"")
148 return filename;
initial.commit09911bf2008-07-26 23:55:29149
150 const std::wstring log_filename(L"chrome_debug.log");
151 std::wstring log_path;
152
153 if (PathService::Get(chrome::DIR_LOGS, &log_path)) {
154 file_util::AppendToPath(&log_path, log_filename);
155 return log_path;
156 } else {
157 // error with path service, just use some default file somewhere
158 return log_filename;
159 }
160}
161
162bool DialogsAreSuppressed() {
163 return dialogs_are_suppressed_;
164}
165
166size_t GetFatalAssertions(AssertionList* assertions) {
167 // In this function, we don't assume that assertions is non-null, so
168 // that if you just want an assertion count, you can pass in NULL.
169 if (assertions)
170 assertions->clear();
171 size_t assertion_count = 0;
172
173 std::ifstream log_file;
[email protected]ec657802008-11-07 20:05:39174#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:29175 log_file.open(GetLogFileName().c_str());
[email protected]ec657802008-11-07 20:05:39176#elif defined(OS_POSIX)
177 log_file.open(WideToUTF8(GetLogFileName()).c_str());
178#endif
initial.commit09911bf2008-07-26 23:55:29179 if (!log_file.is_open())
180 return 0;
181
182 std::string utf8_line;
183 std::wstring wide_line;
184 while(!log_file.eof()) {
185 getline(log_file, utf8_line);
186 if (utf8_line.find(":FATAL:") != std::string::npos) {
187 wide_line = UTF8ToWide(utf8_line);
188 if (assertions)
189 assertions->push_back(wide_line);
190 ++assertion_count;
191 }
192 }
193 log_file.close();
194
195 return assertion_count;
196}
197
198} // namespace logging
license.botbf09a502008-08-24 00:55:55199