blob: 6b34cbe44daea7b14d529f61e4367b7e0943a21b [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"
27
28// When true, this means that error dialogs should not be shown.
29static bool dialogs_are_suppressed_ = false;
30
31// This should be true for exactly the period between the end of
32// InitChromeLogging() and the beginning of CleanupChromeLogging().
33static bool chrome_logging_initialized_ = false;
34
35// Assertion handler for logging errors that occur when dialogs are
36// silenced. To record a new error, pass the log string associated
37// with that error in the str parameter.
[email protected]0eb9f4342008-11-21 18:48:5238MSVC_DISABLE_OPTIMIZE();
initial.commit09911bf2008-07-26 23:55:2939static void SilentRuntimeAssertHandler(const std::string& str) {
[email protected]ec657802008-11-07 20:05:3940 DebugUtil::BreakDebugger();
initial.commit09911bf2008-07-26 23:55:2941}
[email protected]6cc67d7f2009-02-12 06:48:2442static void SilentRuntimeReportHandler(const std::string& str) {
43}
[email protected]0eb9f4342008-11-21 18:48:5244MSVC_ENABLE_OPTIMIZE();
initial.commit09911bf2008-07-26 23:55:2945
46// Suppresses error/assertion dialogs and enables the logging of
47// those errors into silenced_errors_.
48static void SuppressDialogs() {
49 if (dialogs_are_suppressed_)
50 return;
51
52 logging::SetLogAssertHandler(SilentRuntimeAssertHandler);
[email protected]6cc67d7f2009-02-12 06:48:2453 logging::SetLogReportHandler(SilentRuntimeReportHandler);
initial.commit09911bf2008-07-26 23:55:2954
[email protected]ec657802008-11-07 20:05:3955#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:2956 UINT new_flags = SEM_FAILCRITICALERRORS |
57 SEM_NOGPFAULTERRORBOX |
58 SEM_NOOPENFILEERRORBOX;
59
60 // Preserve existing error mode, as discussed at http://t/dmea
61 UINT existing_flags = SetErrorMode(new_flags);
62 SetErrorMode(existing_flags | new_flags);
[email protected]ec657802008-11-07 20:05:3963#endif
initial.commit09911bf2008-07-26 23:55:2964
65 dialogs_are_suppressed_ = true;
66}
67
68namespace logging {
69
70void InitChromeLogging(const CommandLine& command_line,
71 OldFileDeletionState delete_old_log_file) {
72 DCHECK(!chrome_logging_initialized_) <<
73 "Attempted to initialize logging when it was already initialized.";
74
75 // only use OutputDebugString in debug mode
76#ifdef NDEBUG
77 bool enable_logging = false;
78 const wchar_t *kInvertLoggingSwitch = switches::kEnableLogging;
79 const logging::LoggingDestination kDefaultLoggingMode =
80 logging::LOG_ONLY_TO_FILE;
81#else
82 bool enable_logging = true;
83 const wchar_t *kInvertLoggingSwitch = switches::kDisableLogging;
84 const logging::LoggingDestination kDefaultLoggingMode =
85 logging::LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG;
86#endif
87
88 if (command_line.HasSwitch(kInvertLoggingSwitch))
89 enable_logging = !enable_logging;
90
91 logging::LoggingDestination log_mode;
92 if (enable_logging) {
93 log_mode = kDefaultLoggingMode;
94 } else {
95 log_mode = logging::LOG_NONE;
96 }
97
[email protected]ec657802008-11-07 20:05:3998#if defined(OS_POSIX)
99 std::string log_file_name = WideToUTF8(GetLogFileName());
100#elif defined(OS_WIN)
101 std::wstring log_file_name = GetLogFileName();
102#endif
103
104 logging::InitLogging(log_file_name.c_str(),
initial.commit09911bf2008-07-26 23:55:29105 log_mode,
106 logging::LOCK_LOG_FILE,
107 delete_old_log_file);
108
109 // we want process and thread IDs because we have a lot of things running
110 logging::SetLogItems(true, true, false, true);
111
112 // We call running in unattended mode "headless", and allow
113 // headless mode to be configured either by the Environment
114 // Variable or by the Command Line Switch. This is for
115 // automated test purposes.
[email protected]05f9b682008-09-29 22:18:01116 if (base::SysInfo::HasEnvVar(env_vars::kHeadless) ||
initial.commit09911bf2008-07-26 23:55:29117 command_line.HasSwitch(switches::kNoErrorDialogs))
118 SuppressDialogs();
119
120 std::wstring log_filter_prefix =
121 command_line.GetSwitchValue(switches::kLogFilterPrefix);
122 logging::SetLogFilterPrefix(WideToUTF8(log_filter_prefix).c_str());
123
[email protected]bb5185c52008-08-29 19:51:06124 // Use a minimum log level if the command line has one, otherwise set the
125 // default to LOG_WARNING.
126 std::wstring log_level = command_line.GetSwitchValue(switches::kLoggingLevel);
127 int level = 0;
128 if (StringToInt(log_level, &level)) {
129 if ((level >= 0) && (level < LOG_NUM_SEVERITIES))
130 logging::SetMinLogLevel(level);
131 } else {
132 logging::SetMinLogLevel(LOG_WARNING);
133 }
134
initial.commit09911bf2008-07-26 23:55:29135 chrome_logging_initialized_ = true;
136}
137
138// This is a no-op, but we'll keep it around in case
139// we need to do more cleanup in the future.
140void CleanupChromeLogging() {
141 DCHECK(chrome_logging_initialized_) <<
142 "Attempted to clean up logging when it wasn't initialized.";
143
144 CloseLogFile();
145
146 chrome_logging_initialized_ = false;
147}
148
149std::wstring GetLogFileName() {
[email protected]ec657802008-11-07 20:05:39150 std::wstring filename = base::SysInfo::GetEnvVar(env_vars::kLogFileName);
151 if (filename != L"")
152 return filename;
initial.commit09911bf2008-07-26 23:55:29153
154 const std::wstring log_filename(L"chrome_debug.log");
155 std::wstring log_path;
156
157 if (PathService::Get(chrome::DIR_LOGS, &log_path)) {
158 file_util::AppendToPath(&log_path, log_filename);
159 return log_path;
160 } else {
161 // error with path service, just use some default file somewhere
162 return log_filename;
163 }
164}
165
166bool DialogsAreSuppressed() {
167 return dialogs_are_suppressed_;
168}
169
170size_t GetFatalAssertions(AssertionList* assertions) {
171 // In this function, we don't assume that assertions is non-null, so
172 // that if you just want an assertion count, you can pass in NULL.
173 if (assertions)
174 assertions->clear();
175 size_t assertion_count = 0;
176
177 std::ifstream log_file;
[email protected]ec657802008-11-07 20:05:39178#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:29179 log_file.open(GetLogFileName().c_str());
[email protected]ec657802008-11-07 20:05:39180#elif defined(OS_POSIX)
181 log_file.open(WideToUTF8(GetLogFileName()).c_str());
182#endif
initial.commit09911bf2008-07-26 23:55:29183 if (!log_file.is_open())
184 return 0;
185
186 std::string utf8_line;
187 std::wstring wide_line;
188 while(!log_file.eof()) {
189 getline(log_file, utf8_line);
190 if (utf8_line.find(":FATAL:") != std::string::npos) {
191 wide_line = UTF8ToWide(utf8_line);
192 if (assertions)
193 assertions->push_back(wide_line);
194 ++assertion_count;
195 }
196 }
197 log_file.close();
198
199 return assertion_count;
200}
201
202} // namespace logging
license.botbf09a502008-08-24 00:55:55203