blob: 3f497f3456d6d83af46615f6c3ba1c6e0c211f46 [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]0eb9f4342008-11-21 18:48:5217#include "base/compiler_specific.h"
[email protected]ec657802008-11-07 20:05:3918#include "base/debug_util.h"
initial.commit09911bf2008-07-26 23:55:2919#include "base/file_util.h"
20#include "base/logging.h"
21#include "base/path_service.h"
22#include "base/string_util.h"
[email protected]05f9b682008-09-29 22:18:0123#include "base/sys_info.h"
initial.commit09911bf2008-07-26 23:55:2924#include "chrome/common/chrome_paths.h"
25#include "chrome/common/chrome_switches.h"
initial.commit09911bf2008-07-26 23:55:2926#include "chrome/common/env_vars.h"
[email protected]51d5e162009-07-27 19:23:5427#include "ipc/ipc_message.h"
28
29// On Windows, the about:ipc dialog shows IPCs; on POSIX, we hook up a
30// logger in this file.
31#if defined(OS_POSIX) && defined(IPC_MESSAGE_LOG_ENABLED)
32#define IPC_MESSAGE_MACROS_LOG_ENABLED
33#include "ipc/ipc_logging.h"
34#include "chrome/common/plugin_messages.h"
35#include "chrome/common/render_messages.h"
36#endif
initial.commit09911bf2008-07-26 23:55:2937
38// When true, this means that error dialogs should not be shown.
39static bool dialogs_are_suppressed_ = false;
40
41// This should be true for exactly the period between the end of
42// InitChromeLogging() and the beginning of CleanupChromeLogging().
43static bool chrome_logging_initialized_ = false;
44
45// Assertion handler for logging errors that occur when dialogs are
46// silenced. To record a new error, pass the log string associated
47// with that error in the str parameter.
[email protected]0eb9f4342008-11-21 18:48:5248MSVC_DISABLE_OPTIMIZE();
initial.commit09911bf2008-07-26 23:55:2949static void SilentRuntimeAssertHandler(const std::string& str) {
[email protected]ec657802008-11-07 20:05:3950 DebugUtil::BreakDebugger();
initial.commit09911bf2008-07-26 23:55:2951}
[email protected]6cc67d7f2009-02-12 06:48:2452static void SilentRuntimeReportHandler(const std::string& str) {
53}
[email protected]0eb9f4342008-11-21 18:48:5254MSVC_ENABLE_OPTIMIZE();
initial.commit09911bf2008-07-26 23:55:2955
56// Suppresses error/assertion dialogs and enables the logging of
57// those errors into silenced_errors_.
58static void SuppressDialogs() {
59 if (dialogs_are_suppressed_)
60 return;
61
62 logging::SetLogAssertHandler(SilentRuntimeAssertHandler);
[email protected]6cc67d7f2009-02-12 06:48:2463 logging::SetLogReportHandler(SilentRuntimeReportHandler);
initial.commit09911bf2008-07-26 23:55:2964
[email protected]ec657802008-11-07 20:05:3965#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:2966 UINT new_flags = SEM_FAILCRITICALERRORS |
67 SEM_NOGPFAULTERRORBOX |
68 SEM_NOOPENFILEERRORBOX;
69
70 // Preserve existing error mode, as discussed at http://t/dmea
71 UINT existing_flags = SetErrorMode(new_flags);
72 SetErrorMode(existing_flags | new_flags);
[email protected]ec657802008-11-07 20:05:3973#endif
initial.commit09911bf2008-07-26 23:55:2974
75 dialogs_are_suppressed_ = true;
76}
77
78namespace logging {
79
80void InitChromeLogging(const CommandLine& command_line,
81 OldFileDeletionState delete_old_log_file) {
82 DCHECK(!chrome_logging_initialized_) <<
83 "Attempted to initialize logging when it was already initialized.";
84
[email protected]946d1b22009-07-22 23:57:2185#if defined(OS_POSIX) && defined(IPC_MESSAGE_LOG_ENABLED)
86 IPC::Logging::SetLoggerFunctions(g_log_function_mapping);
87#endif
88
initial.commit09911bf2008-07-26 23:55:2989 // only use OutputDebugString in debug mode
90#ifdef NDEBUG
91 bool enable_logging = false;
92 const wchar_t *kInvertLoggingSwitch = switches::kEnableLogging;
93 const logging::LoggingDestination kDefaultLoggingMode =
94 logging::LOG_ONLY_TO_FILE;
95#else
96 bool enable_logging = true;
97 const wchar_t *kInvertLoggingSwitch = switches::kDisableLogging;
98 const logging::LoggingDestination kDefaultLoggingMode =
99 logging::LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG;
100#endif
101
102 if (command_line.HasSwitch(kInvertLoggingSwitch))
103 enable_logging = !enable_logging;
104
105 logging::LoggingDestination log_mode;
106 if (enable_logging) {
[email protected]3bba9582009-08-05 01:29:12107 // Let --enable-logging=stderr force only stderr, particularly useful for
108 // non-debug builds where otherwise you can't get logs to stderr at all.
109 if (command_line.GetSwitchValue(switches::kEnableLogging) == L"stderr")
110 log_mode = logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG;
111 else
112 log_mode = kDefaultLoggingMode;
initial.commit09911bf2008-07-26 23:55:29113 } else {
114 log_mode = logging::LOG_NONE;
115 }
116
[email protected]ec657802008-11-07 20:05:39117#if defined(OS_POSIX)
118 std::string log_file_name = WideToUTF8(GetLogFileName());
119#elif defined(OS_WIN)
120 std::wstring log_file_name = GetLogFileName();
121#endif
122
123 logging::InitLogging(log_file_name.c_str(),
initial.commit09911bf2008-07-26 23:55:29124 log_mode,
125 logging::LOCK_LOG_FILE,
126 delete_old_log_file);
127
128 // we want process and thread IDs because we have a lot of things running
129 logging::SetLogItems(true, true, false, true);
130
131 // We call running in unattended mode "headless", and allow
132 // headless mode to be configured either by the Environment
133 // Variable or by the Command Line Switch. This is for
134 // automated test purposes.
[email protected]05f9b682008-09-29 22:18:01135 if (base::SysInfo::HasEnvVar(env_vars::kHeadless) ||
initial.commit09911bf2008-07-26 23:55:29136 command_line.HasSwitch(switches::kNoErrorDialogs))
137 SuppressDialogs();
138
139 std::wstring log_filter_prefix =
140 command_line.GetSwitchValue(switches::kLogFilterPrefix);
141 logging::SetLogFilterPrefix(WideToUTF8(log_filter_prefix).c_str());
142
[email protected]bb5185c52008-08-29 19:51:06143 // Use a minimum log level if the command line has one, otherwise set the
144 // default to LOG_WARNING.
145 std::wstring log_level = command_line.GetSwitchValue(switches::kLoggingLevel);
146 int level = 0;
[email protected]41fb1d72009-02-28 01:01:50147 if (StringToInt(WideToUTF16Hack(log_level), &level)) {
[email protected]bb5185c52008-08-29 19:51:06148 if ((level >= 0) && (level < LOG_NUM_SEVERITIES))
149 logging::SetMinLogLevel(level);
150 } else {
151 logging::SetMinLogLevel(LOG_WARNING);
152 }
153
initial.commit09911bf2008-07-26 23:55:29154 chrome_logging_initialized_ = true;
155}
156
157// This is a no-op, but we'll keep it around in case
158// we need to do more cleanup in the future.
159void CleanupChromeLogging() {
160 DCHECK(chrome_logging_initialized_) <<
161 "Attempted to clean up logging when it wasn't initialized.";
162
163 CloseLogFile();
164
165 chrome_logging_initialized_ = false;
166}
167
168std::wstring GetLogFileName() {
[email protected]ec657802008-11-07 20:05:39169 std::wstring filename = base::SysInfo::GetEnvVar(env_vars::kLogFileName);
170 if (filename != L"")
171 return filename;
initial.commit09911bf2008-07-26 23:55:29172
173 const std::wstring log_filename(L"chrome_debug.log");
174 std::wstring log_path;
175
176 if (PathService::Get(chrome::DIR_LOGS, &log_path)) {
177 file_util::AppendToPath(&log_path, log_filename);
178 return log_path;
179 } else {
180 // error with path service, just use some default file somewhere
181 return log_filename;
182 }
183}
184
185bool DialogsAreSuppressed() {
186 return dialogs_are_suppressed_;
187}
188
189size_t GetFatalAssertions(AssertionList* assertions) {
190 // In this function, we don't assume that assertions is non-null, so
191 // that if you just want an assertion count, you can pass in NULL.
192 if (assertions)
193 assertions->clear();
194 size_t assertion_count = 0;
195
196 std::ifstream log_file;
[email protected]ec657802008-11-07 20:05:39197#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:29198 log_file.open(GetLogFileName().c_str());
[email protected]ec657802008-11-07 20:05:39199#elif defined(OS_POSIX)
200 log_file.open(WideToUTF8(GetLogFileName()).c_str());
201#endif
initial.commit09911bf2008-07-26 23:55:29202 if (!log_file.is_open())
203 return 0;
204
205 std::string utf8_line;
206 std::wstring wide_line;
207 while(!log_file.eof()) {
208 getline(log_file, utf8_line);
209 if (utf8_line.find(":FATAL:") != std::string::npos) {
210 wide_line = UTF8ToWide(utf8_line);
211 if (assertions)
212 assertions->push_back(wide_line);
213 ++assertion_count;
214 }
215 }
216 log_file.close();
217
218 return assertion_count;
219}
220
221} // namespace logging