OLD | NEW |
1 /* | 1 /* |
2 * This file is part of Adblock Plus <https://adblockplus.org/>, | 2 * This file is part of Adblock Plus <https://adblockplus.org/>, |
3 * Copyright (C) 2006-2015 Eyeo GmbH | 3 * Copyright (C) 2006-2015 Eyeo GmbH |
4 * | 4 * |
5 * Adblock Plus is free software: you can redistribute it and/or modify | 5 * Adblock Plus is free software: you can redistribute it and/or modify |
6 * it under the terms of the GNU General Public License version 3 as | 6 * it under the terms of the GNU General Public License version 3 as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
8 * | 8 * |
9 * Adblock Plus is distributed in the hope that it will be useful, | 9 * Adblock Plus is distributed in the hope that it will be useful, |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 * GNU General Public License for more details. | 12 * GNU General Public License for more details. |
13 * | 13 * |
14 * You should have received a copy of the GNU General Public License | 14 * You should have received a copy of the GNU General Public License |
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. | 15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. |
16 */ | 16 */ |
17 | 17 |
18 #include "PluginStdAfx.h" | 18 #include "PluginStdAfx.h" |
19 #include "PluginDebug.h" | 19 #include "PluginDebug.h" |
20 #include "PluginClientBase.h" | 20 #include "PluginClientBase.h" |
21 #include "PluginMutex.h" | 21 #include "PluginMutex.h" |
22 #include "PluginSettings.h" | 22 #include "PluginClientBase.h" |
23 | 23 #include "../shared/Utils.h" |
24 class CPluginDebugLock : public CPluginMutex | 24 #include <iomanip> |
25 { | 25 #include <memory> |
26 | 26 |
27 private: | 27 namespace |
28 | 28 { |
29 static CComAutoCriticalSection s_criticalSectionDebugLock; | 29 class CPluginDebugLock |
30 | 30 : public CPluginMutex |
31 public: | 31 { |
32 | 32 private: |
33 CPluginDebugLock() : CPluginMutex(L"DebugFile", PLUGIN_ERROR_MUTEX_DEBUG_FILE) | 33 static CComAutoCriticalSection s_criticalSectionDebugLock; |
34 { | 34 |
35 s_criticalSectionDebugLock.Lock(); | 35 public: |
| 36 CPluginDebugLock() |
| 37 : CPluginMutex(L"DebugFile", PLUGIN_ERROR_MUTEX_DEBUG_FILE) |
| 38 { |
| 39 s_criticalSectionDebugLock.Lock(); |
| 40 } |
| 41 |
| 42 ~CPluginDebugLock() |
| 43 { |
| 44 s_criticalSectionDebugLock.Unlock(); |
| 45 } |
| 46 }; |
| 47 |
| 48 CComAutoCriticalSection CPluginDebugLock::s_criticalSectionDebugLock; |
| 49 |
| 50 class LogText |
| 51 { |
| 52 public: |
| 53 virtual std::string Text() const = 0; |
| 54 }; |
| 55 |
| 56 class LogTextFixed |
| 57 : public LogText |
| 58 { |
| 59 protected: |
| 60 const std::string fixedText; |
| 61 |
| 62 public: |
| 63 explicit LogTextFixed(const std::string& text) |
| 64 : fixedText(text) |
| 65 {} |
| 66 |
| 67 explicit LogTextFixed(const std::exception& ex) |
| 68 : fixedText(std::string("!!! Exception: ") + ex.what()) |
| 69 {} |
| 70 |
| 71 virtual std::string Text() const override |
| 72 { |
| 73 return fixedText; |
| 74 } |
| 75 }; |
| 76 |
| 77 class LogTextErrorCode |
| 78 : public LogTextFixed |
| 79 { |
| 80 protected: |
| 81 const DWORD errorCode; |
| 82 |
| 83 public: |
| 84 LogTextErrorCode(DWORD errorCode, const std::string& text) |
| 85 : LogTextFixed(text), errorCode(errorCode) |
| 86 {} |
| 87 |
| 88 virtual std::string Text() const override |
| 89 { |
| 90 std::ostringstream ss; |
| 91 ss << fixedText << ". error = " << errorCode << " (0x"; |
| 92 ss << std::setfill('0') << std::setw(2 * sizeof(DWORD)) << std::hex << err
orCode; |
| 93 ss << ")"; |
| 94 return ss.str(); |
| 95 } |
| 96 }; |
| 97 |
| 98 /** |
| 99 * Wrapper around SYSTEMTIME allows initialization of 'const' instances. |
| 100 */ |
| 101 struct SystemTime |
| 102 : public SYSTEMTIME |
| 103 { |
| 104 SystemTime() |
| 105 { |
| 106 ::GetSystemTime(static_cast<SYSTEMTIME*>(this)); |
| 107 } |
| 108 }; |
| 109 |
| 110 class LogEntry |
| 111 { |
| 112 const std::unique_ptr<LogText> text; |
| 113 |
| 114 std::string InitialPrefix() const |
| 115 { |
| 116 std::stringstream ss; |
| 117 ss << std::setfill('0') << std::setw(2) << st.wHour; |
| 118 ss << ":"; |
| 119 ss << std::setfill('0') << std::setw(2) << st.wMinute; |
| 120 ss << ":"; |
| 121 ss << std::setfill('0') << std::setw(2) << st.wSecond; |
| 122 ss << "."; |
| 123 ss << std::setfill('0') << std::setw(3) << st.wMilliseconds; |
| 124 ss << " ["; |
| 125 ss << std::setfill(' ') << std::setw(5) << threadId; |
| 126 ss << "] - "; |
| 127 return ss.str(); |
| 128 } |
| 129 |
| 130 std::string SubsequentPrefix() const |
| 131 { |
| 132 return " + "; |
| 133 } |
| 134 |
| 135 public: |
| 136 /** |
| 137 * The time at which the log-generating statement executes. |
| 138 */ |
| 139 const SystemTime st; |
| 140 |
| 141 /** |
| 142 * The process within which the log-generating statement executes. |
| 143 */ |
| 144 const DWORD processId; |
| 145 |
| 146 /** |
| 147 * The thread within which the log-generating statement executes. |
| 148 */ |
| 149 const DWORD threadId; |
| 150 |
| 151 explicit LogEntry(LogText* text) |
| 152 : processId(::GetCurrentProcessId()), threadId(::GetCurrentThreadId()), te
xt(text) |
| 153 {} |
| 154 |
| 155 LogEntry(LogText* text, DWORD processId, DWORD threadId) |
| 156 : processId(processId), threadId(threadId), text(text) |
| 157 {} |
| 158 |
| 159 void Write(std::ostream& out) const |
| 160 { |
| 161 CPluginDebugLock lock; |
| 162 if (lock.IsLocked()) |
| 163 { |
| 164 auto lines = text->Text(); |
| 165 size_t linePosition = 0; |
| 166 while (true) |
| 167 { |
| 168 auto eolPosition = lines.find('\n', linePosition); |
| 169 auto prefix = linePosition == 0 ? InitialPrefix() : SubsequentPrefix()
; |
| 170 out << prefix; |
| 171 if (eolPosition == std::string::npos) |
| 172 { |
| 173 out << lines.substr(linePosition) << "\n"; |
| 174 break; |
| 175 } |
| 176 else |
| 177 { |
| 178 out << lines.substr(linePosition, eolPosition - linePosition) << "\n
"; |
| 179 linePosition = eolPosition + 1; |
| 180 } |
| 181 } |
| 182 out.flush(); |
| 183 } |
| 184 } |
| 185 |
| 186 void WriteFile(const std::wstring& logFileName) const |
| 187 { |
| 188 std::ofstream out; |
| 189 out.open(logFileName, std::ios::app); |
| 190 Write(out); |
| 191 } |
| 192 }; |
| 193 |
| 194 std::wstring GetDataPath(const std::wstring& filename) |
| 195 { |
| 196 return GetAppDataPath() + L"\\" + filename; |
36 } | 197 } |
37 | 198 |
38 ~CPluginDebugLock() | 199 void LogWriteDefault(const LogEntry& le) |
39 { | 200 { |
40 s_criticalSectionDebugLock.Unlock(); | 201 std::wstring debugFileName = GetDataPath(L"debug_" + std::to_wstring(le.proc
essId) + L".txt"); |
| 202 le.WriteFile(debugFileName); |
41 } | 203 } |
42 }; | 204 |
43 | 205 void LogWriteResult(const LogEntry& le) |
44 CComAutoCriticalSection CPluginDebugLock::s_criticalSectionDebugLock; | 206 { |
| 207 std::wstring debugFileName = GetDataPath(L"debug_result.txt"); |
| 208 le.WriteFile(debugFileName); |
| 209 } |
| 210 } |
| 211 |
| 212 #ifdef ENABLE_DEBUG_INFO |
| 213 |
| 214 void CPluginDebug::Debug(const std::string& text) |
| 215 { |
| 216 LogWriteDefault(LogEntry(new LogTextFixed(text))); |
| 217 } |
| 218 |
| 219 void CPluginDebug::Debug(const std::wstring& text) |
| 220 { |
| 221 Debug(ToUtf8String(text)); |
| 222 } |
| 223 |
| 224 #endif |
45 | 225 |
46 void CPluginDebug::DebugSystemException(const std::system_error& ex, int errorId
, int errorSubid, const std::string& description) | 226 void CPluginDebug::DebugSystemException(const std::system_error& ex, int errorId
, int errorSubid, const std::string& description) |
47 { | 227 { |
48 std::string message = description + ", " + ex.code().message() + ", " + ex.wha
t(); | 228 std::string message = description + ", " + ex.code().message() + ", " + ex.wha
t(); |
49 DEBUG_ERROR_LOG(ex.code().value(), errorId, errorSubid, message); | 229 DEBUG_ERROR_LOG(ex.code().value(), errorId, errorSubid, message); |
50 } | 230 } |
51 | 231 |
52 #ifdef ENABLE_DEBUG_INFO | |
53 | |
54 void DebugLegacy(const CString& text, DWORD dwProcessId, DWORD dwThreadId) | |
55 { | |
56 #ifdef USE_CONSOLE | |
57 CONSOLE("%s", CT2A(text.GetString(), CP_UTF8)); | |
58 #endif | |
59 | |
60 if (CPluginSettings::HasInstance()) | |
61 { | |
62 #ifdef ENABLE_DEBUG_SPLIT_FILE | |
63 CPluginSettings* settings = CPluginSettings::GetInstance(); | |
64 | |
65 bool isWorkingThread = settings->IsWorkingThread(dwThreadId); | |
66 | |
67 std::wstring processor; | |
68 wchar_t tmp[10]; | |
69 _itow_s(::GetCurrentProcessId(), tmp, 10); | |
70 if (isWorkingThread) | |
71 processor = L"tab" + std::wstring(tmp) + L"_thread"; | |
72 else | |
73 processor = L"tab" + std::wstring(tmp) + L"_ui"; | |
74 #else | |
75 if (dwProcessId == 0) | |
76 { | |
77 dwProcessId = ::GetCurrentProcessId(); | |
78 } | |
79 if (dwThreadId == 0) | |
80 { | |
81 dwThreadId = ::GetCurrentThreadId(); | |
82 } | |
83 | |
84 CStringA processInfo; | |
85 processInfo.Format("%4.4u.%4.4u - ", dwProcessId, dwThreadId); | |
86 #endif | |
87 SYSTEMTIME st; | |
88 ::GetSystemTime(&st); | |
89 | |
90 CStringA sysTime; | |
91 sysTime.Format("%2.2d:%2.2d:%2.2d.%3.3d - ", st.wHour, st.wMinute, st.wSecon
d, st.wMilliseconds); | |
92 | |
93 CPluginDebugLock lock; | |
94 if (lock.IsLocked()) | |
95 { | |
96 std::ofstream debugFile; | |
97 | |
98 #ifdef ENABLE_DEBUG_SPLIT_FILE | |
99 debugFile.open(GetDataPath(L"debug_" + processor + L".txt"), std::ios::app
); | |
100 #else | |
101 debugFile.open(GetDataPath(L"debug.txt"), std::ios::app); | |
102 #endif | |
103 int pos = 0; | |
104 CStringA line = text.Tokenize(L"\n\r", pos); | |
105 | |
106 while (pos >= 0) | |
107 { | |
108 debugFile.write(sysTime.GetBuffer(), sysTime.GetLength()); | |
109 #ifndef ENABLE_DEBUG_SPLIT_FILE | |
110 debugFile.write(processInfo.GetBuffer(), processInfo.GetLength()); | |
111 #endif | |
112 debugFile.write(line.GetBuffer(), line.GetLength()); | |
113 debugFile.write("\n", 1); | |
114 | |
115 line = text.Tokenize(L"\n\r", pos); | |
116 } | |
117 | |
118 debugFile.flush(); | |
119 } | |
120 } | |
121 } | |
122 | |
123 void CPluginDebug::Debug(const std::string& text, DWORD processId, DWORD threadI
d) | |
124 { | |
125 DebugLegacy(CString(text.c_str()), processId, threadId); | |
126 } | |
127 | |
128 void CPluginDebug::Debug(const std::wstring& text, DWORD processId, DWORD thread
Id) | |
129 { | |
130 DebugLegacy(ToCString(text), processId, threadId); | |
131 } | |
132 | |
133 #endif | |
134 | |
135 #if (defined ENABLE_DEBUG_INFO) | 232 #if (defined ENABLE_DEBUG_INFO) |
136 | 233 |
137 void CPluginDebug::DebugException(const std::exception& ex) | 234 void CPluginDebug::DebugException(const std::exception& ex) |
138 { | 235 { |
139 auto error = std::string("!!! Exception:") + ex.what(); | 236 auto lt = new LogTextFixed(ex); |
| 237 LogEntry le(lt); |
140 #ifdef ENABLE_DEBUG_ERROR | 238 #ifdef ENABLE_DEBUG_ERROR |
141 Debug(error); | 239 LogWriteDefault(le); |
142 #endif | 240 #endif |
143 | 241 DEBUG_SELFTEST( |
144 DEBUG_SELFTEST("**************************************************************
******************\n" + error + "\n*********************************************
***********************************") | 242 "***************************************************************************
*****\n" |
145 } | 243 + lt->text() + "\n" |
146 | 244 "***************************************************************************
*****") |
147 void DebugErrorCodeLegacy(DWORD errorCode, const CString& error, DWORD dwProcess
Id, DWORD dwThreadId) | 245 } |
148 { | 246 |
149 CString errorCodeText; | 247 void CPluginDebug::DebugErrorCode(DWORD errorCode, const std::string& error, DWO
RD processId, DWORD threadId) |
150 errorCodeText.Format(L"%u (0x%8.8x)", errorCode, errorCode); | 248 { |
151 | 249 auto lt = new LogTextErrorCode(errorCode, error); |
152 CString finalError = error + L". error=" + errorCodeText; | 250 LogEntry le(lt, processId, threadId); |
153 | |
154 #ifdef ENABLE_DEBUG_ERROR | 251 #ifdef ENABLE_DEBUG_ERROR |
155 DebugLegacy(finalError, dwProcessId, dwThreadId); | 252 LogWriteDefault(le); |
156 #endif | 253 #endif |
157 | 254 DEBUG_SELFTEST( |
158 DEBUG_SELFTEST(L"*************************************************************
*******************\n" + finalError + "\n***************************************
*****************************************") | 255 "***************************************************************************
*****\n" |
159 } | 256 + lt->text() + "\n" |
160 | 257 "***************************************************************************
*****") |
161 void CPluginDebug::DebugErrorCode(DWORD errorCode, const std::string& error, DWO
RD processId, DWORD threadId) | 258 } |
162 { | 259 |
163 DebugErrorCodeLegacy(errorCode, CString(error.c_str()), processId, threadId); | 260 #endif |
164 } | |
165 | |
166 #endif | |
167 | 261 |
168 // ============================================================================ | 262 // ============================================================================ |
169 // Debug result | 263 // Debug result |
170 // ============================================================================ | 264 // ============================================================================ |
171 | 265 |
172 #ifdef ENABLE_DEBUG_RESULT | 266 #ifdef ENABLE_DEBUG_RESULT |
173 | 267 |
174 void DebugResultLegacy(const CString& text) | |
175 { | |
176 SYSTEMTIME st; | |
177 ::GetSystemTime(&st); | |
178 | |
179 CStringA sysTime; | |
180 sysTime.Format("%2.2d:%2.2d:%2.2d.%3.3d - ", st.wHour, st.wMinute, st.wSecond,
st.wMilliseconds); | |
181 | |
182 CStringA textA = text; | |
183 | |
184 CPluginDebugLock lock; | |
185 if (lock.IsLocked()) | |
186 { | |
187 std::ofstream debugFile; | |
188 | |
189 debugFile.open(GetDataPath(L"debug_result.txt"), std::ios::app); | |
190 debugFile.write(sysTime.GetBuffer(), sysTime.GetLength()); | |
191 debugFile.write(LPCSTR(textA), textA.GetLength()); | |
192 debugFile.write("\n", 1); | |
193 debugFile.flush(); | |
194 } | |
195 } | |
196 | |
197 void CPluginDebug::DebugResult(const std::wstring& text) | 268 void CPluginDebug::DebugResult(const std::wstring& text) |
198 { | 269 { |
199 DebugResultLegacy(ToCString(text)); | 270 LogWriteResult(LogEntry(new LogTextFixed(ToUtf8String(text)))); |
200 } | 271 } |
201 | 272 |
202 void CPluginDebug::DebugResultDomain(const std::wstring& domain) | 273 void CPluginDebug::DebugResultDomain(const std::wstring& domain) |
203 { | 274 { |
204 DebugResult(L"================================================================
================================================================================
==========================================="); | 275 DebugResult( |
205 DebugResult(domain); | 276 L"==========================================================================
===============\n" |
206 DebugResult(L"================================================================
================================================================================
==========================================="); | 277 + domain + L"\n" |
| 278 L"==========================================================================
==============="); |
207 } | 279 } |
208 | 280 |
| 281 namespace |
| 282 { |
| 283 void DebugResultFormat(const std::wstring& action, const std::wstring& type, c
onst std::wstring& param1, const std::wstring& param2) |
| 284 { |
| 285 std::wostringstream ss; |
| 286 ss << std::setw(7) << std::setiosflags(std::ios::left) << action; |
| 287 ss << L" "; |
| 288 ss << std::setw(12) << std::setiosflags(std::ios::left) << type; |
| 289 ss << L" " << param1 << L" " << param2; |
| 290 CPluginDebug::DebugResult(ss.str()); |
| 291 } |
| 292 |
| 293 std::wstring Shorten(const std::wstring& s) |
| 294 { |
| 295 auto n = s.length(); |
| 296 if (n <= 100) return s; |
| 297 auto r = s.substr(0, 67); |
| 298 r += L"..."; |
| 299 r += s.substr(n - 30, 30); |
| 300 return r; |
| 301 } |
| 302 } |
209 | 303 |
210 void CPluginDebug::DebugResultBlocking(const std::wstring& type, const std::wstr
ing& src, const std::wstring& domain) | 304 void CPluginDebug::DebugResultBlocking(const std::wstring& type, const std::wstr
ing& src, const std::wstring& domain) |
211 { | 305 { |
212 CString srcTrunc = ToCString(src); | 306 DebugResultFormat(L"Blocked", type, domain.empty() ? L"-" : domain, Shorten(sr
c)); |
213 if (src.length() > 100) | |
214 { | |
215 srcTrunc = srcTrunc.Left(67) + L"..." + srcTrunc.Right(30); | |
216 } | |
217 | |
218 CString blocking; | |
219 blocking.Format(L"Blocked %-12s %-20s %s", ToCString(type), domain.empty()?
L"-" : ToCString(domain), srcTrunc); | |
220 | |
221 DebugResultLegacy(blocking); | |
222 } | 307 } |
223 | 308 |
224 | 309 |
225 void CPluginDebug::DebugResultHiding(const std::wstring& tag, const std::wstring
& id, const std::wstring& filter) | 310 void CPluginDebug::DebugResultHiding(const std::wstring& tag, const std::wstring
& id, const std::wstring& filter) |
226 { | 311 { |
227 CString srcTrunc = ToCString(id); | 312 DebugResultFormat(L"Hidden", tag, L"- " + Shorten(id), filter); |
228 if (srcTrunc.GetLength() > 100) | |
229 { | |
230 srcTrunc = srcTrunc.Left(67) + L"..." + srcTrunc.Right(30); | |
231 } | |
232 | |
233 CString blocking; | |
234 blocking.Format(L"Hidden %-12s - %s %s", ToCString(tag), srcTrunc, ToCStri
ng(filter)); | |
235 | |
236 DebugResultLegacy(blocking); | |
237 } | 313 } |
238 | 314 |
239 #endif // ENABLE_DEBUG_RESULT | 315 #endif // ENABLE_DEBUG_RESULT |
240 | 316 |
241 | 317 |
242 #ifdef ENABLE_DEBUG_RESULT_IGNORED | 318 #ifdef ENABLE_DEBUG_RESULT_IGNORED |
243 | 319 |
244 void CPluginDebug::DebugResultIgnoring(const std::wstring& type, const std::wstr
ing& src, const std::wstring& domain) | 320 void CPluginDebug::DebugResultIgnoring(const std::wstring& type, const std::wstr
ing& src, const std::wstring& domain) |
245 { | 321 { |
246 CString srcTrunc = ToCString(src); | 322 DebugResultFormat(L"Ignored", type, domain.empty() ? L"-" : domain, Shorten(sr
c)); |
247 if (src.length() > 100) | |
248 { | |
249 srcTrunc = srcTrunc.Left(67) + L"..." + srcTrunc.Right(30); | |
250 } | |
251 | |
252 CString blocking; | |
253 blocking.Format(L"Ignored %-12s %s %s", ToCString(type), domain.empty()? L"
-" : ToCString(domain), srcTrunc); | |
254 | |
255 DebugResultLegacy(blocking); | |
256 } | 323 } |
257 | 324 |
258 #endif // ENABLE_DEBUG_RESULT_IGNORED | 325 #endif // ENABLE_DEBUG_RESULT_IGNORED |
OLD | NEW |