blob: 575283b627df02f883ccbafe6876c60dc88a08f4 [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]0eb9f4342008-11-21 18:48:5242MSVC_ENABLE_OPTIMIZE();
initial.commit09911bf2008-07-26 23:55:2943
44// Suppresses error/assertion dialogs and enables the logging of
45// those errors into silenced_errors_.
46static void SuppressDialogs() {
47 if (dialogs_are_suppressed_)
48 return;
49
50 logging::SetLogAssertHandler(SilentRuntimeAssertHandler);
51
[email protected]ec657802008-11-07 20:05:3952#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:2953 UINT new_flags = SEM_FAILCRITICALERRORS |
54 SEM_NOGPFAULTERRORBOX |
55 SEM_NOOPENFILEERRORBOX;
56
57 // Preserve existing error mode, as discussed at http://t/dmea
58 UINT existing_flags = SetErrorMode(new_flags);
59 SetErrorMode(existing_flags | new_flags);
[email protected]ec657802008-11-07 20:05:3960#endif
initial.commit09911bf2008-07-26 23:55:2961
62 dialogs_are_suppressed_ = true;
63}
64
65namespace logging {
66
67void InitChromeLogging(const CommandLine& command_line,
68 OldFileDeletionState delete_old_log_file) {
69 DCHECK(!chrome_logging_initialized_) <<
70 "Attempted to initialize logging when it was already initialized.";
71
72 // only use OutputDebugString in debug mode
73#ifdef NDEBUG
74 bool enable_logging = false;
75 const wchar_t *kInvertLoggingSwitch = switches::kEnableLogging;
76 const logging::LoggingDestination kDefaultLoggingMode =
77 logging::LOG_ONLY_TO_FILE;
78#else
79 bool enable_logging = true;
80 const wchar_t *kInvertLoggingSwitch = switches::kDisableLogging;
81 const logging::LoggingDestination kDefaultLoggingMode =
82 logging::LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG;
83#endif
84
85 if (command_line.HasSwitch(kInvertLoggingSwitch))
86 enable_logging = !enable_logging;
87
88 logging::LoggingDestination log_mode;
89 if (enable_logging) {
90 log_mode = kDefaultLoggingMode;
91 } else {
92 log_mode = logging::LOG_NONE;
93 }
94
[email protected]ec657802008-11-07 20:05:3995#if defined(OS_POSIX)
96 std::string log_file_name = WideToUTF8(GetLogFileName());
97#elif defined(OS_WIN)
98 std::wstring log_file_name = GetLogFileName();
99#endif
100
101 logging::InitLogging(log_file_name.c_str(),
initial.commit09911bf2008-07-26 23:55:29102 log_mode,
103 logging::LOCK_LOG_FILE,
104 delete_old_log_file);
105
106 // we want process and thread IDs because we have a lot of things running
107 logging::SetLogItems(true, true, false, true);
108
109 // We call running in unattended mode "headless", and allow
110 // headless mode to be configured either by the Environment
111 // Variable or by the Command Line Switch. This is for
112 // automated test purposes.
[email protected]05f9b682008-09-29 22:18:01113 if (base::SysInfo::HasEnvVar(env_vars::kHeadless) ||
initial.commit09911bf2008-07-26 23:55:29114 command_line.HasSwitch(switches::kNoErrorDialogs))
115 SuppressDialogs();
116
117 std::wstring log_filter_prefix =
118 command_line.GetSwitchValue(switches::kLogFilterPrefix);
119 logging::SetLogFilterPrefix(WideToUTF8(log_filter_prefix).c_str());
120
[email protected]bb5185c52008-08-29 19:51:06121 // Use a minimum log level if the command line has one, otherwise set the
122 // default to LOG_WARNING.
123 std::wstring log_level = command_line.GetSwitchValue(switches::kLoggingLevel);
124 int level = 0;
125 if (StringToInt(log_level, &level)) {
126 if ((level >= 0) && (level < LOG_NUM_SEVERITIES))
127 logging::SetMinLogLevel(level);
128 } else {
129 logging::SetMinLogLevel(LOG_WARNING);
130 }
131
initial.commit09911bf2008-07-26 23:55:29132 chrome_logging_initialized_ = true;
133}
134
135// This is a no-op, but we'll keep it around in case
136// we need to do more cleanup in the future.
137void CleanupChromeLogging() {
138 DCHECK(chrome_logging_initialized_) <<
139 "Attempted to clean up logging when it wasn't initialized.";
140
141 CloseLogFile();
142
143 chrome_logging_initialized_ = false;
144}
145
146std::wstring GetLogFileName() {
[email protected]ec657802008-11-07 20:05:39147 std::wstring filename = base::SysInfo::GetEnvVar(env_vars::kLogFileName);
148 if (filename != L"")
149 return filename;
initial.commit09911bf2008-07-26 23:55:29150
151 const std::wstring log_filename(L"chrome_debug.log");
152 std::wstring log_path;
153
154 if (PathService::Get(chrome::DIR_LOGS, &log_path)) {
155 file_util::AppendToPath(&log_path, log_filename);
156 return log_path;
157 } else {
158 // error with path service, just use some default file somewhere
159 return log_filename;
160 }
161}
162
163bool DialogsAreSuppressed() {
164 return dialogs_are_suppressed_;
165}
166
167size_t GetFatalAssertions(AssertionList* assertions) {
168 // In this function, we don't assume that assertions is non-null, so
169 // that if you just want an assertion count, you can pass in NULL.
170 if (assertions)
171 assertions->clear();
172 size_t assertion_count = 0;
173
174 std::ifstream log_file;
[email protected]ec657802008-11-07 20:05:39175#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:29176 log_file.open(GetLogFileName().c_str());
[email protected]ec657802008-11-07 20:05:39177#elif defined(OS_POSIX)
178 log_file.open(WideToUTF8(GetLogFileName()).c_str());
179#endif
initial.commit09911bf2008-07-26 23:55:29180 if (!log_file.is_open())
181 return 0;
182
183 std::string utf8_line;
184 std::wstring wide_line;
185 while(!log_file.eof()) {
186 getline(log_file, utf8_line);
187 if (utf8_line.find(":FATAL:") != std::string::npos) {
188 wide_line = UTF8ToWide(utf8_line);
189 if (assertions)
190 assertions->push_back(wide_line);
191 ++assertion_count;
192 }
193 }
194 log_file.close();
195
196 return assertion_count;
197}
198
199} // namespace logging
license.botbf09a502008-08-24 00:55:55200