Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef MOZILLA_GFX_LOGGING_H_
7 #define MOZILLA_GFX_LOGGING_H_
9 #include <string>
10 #include <sstream>
11 #include <stdio.h>
13 #include "nsDebug.h"
14 #include "Point.h"
15 #include "BaseRect.h"
16 #include "Matrix.h"
17 #include "mozilla/TypedEnum.h"
19 #ifdef WIN32
20 // This file gets included from nsGlobalWindow.cpp, which doesn't like
21 // having windows.h included in it. Since OutputDebugStringA is the only
22 // thing we need from windows.h, we just declare it here directly.
23 // Note: the function's documented signature is
24 // WINBASEAPI void WINAPI OutputDebugStringA(LPCSTR lpOutputString)
25 // but if we don't include windows.h, the macros WINBASEAPI, WINAPI, and
26 // LPCSTR are not defined, so we need to replace them with their expansions.
27 extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA(const char* lpOutputString);
28 #endif
30 #if defined(DEBUG) || defined(PR_LOGGING)
31 #include <prlog.h>
33 extern GFX2D_API PRLogModuleInfo *GetGFX2DLog();
34 #endif
36 namespace mozilla {
37 namespace gfx {
39 const int LOG_DEBUG = 1;
40 const int LOG_WARNING = 2;
42 #if defined(DEBUG) || defined(PR_LOGGING)
44 inline PRLogModuleLevel PRLogLevelForLevel(int aLevel) {
45 switch (aLevel) {
46 case LOG_DEBUG:
47 return PR_LOG_DEBUG;
48 case LOG_WARNING:
49 return PR_LOG_WARNING;
50 }
51 return PR_LOG_DEBUG;
52 }
54 #endif
56 extern GFX2D_API int sGfxLogLevel;
58 static inline void OutputMessage(const std::string &aString, int aLevel) {
59 #if defined(WIN32) && !defined(PR_LOGGING)
60 if (aLevel >= sGfxLogLevel) {
61 ::OutputDebugStringA(aString.c_str());
62 }
63 #elif defined(PR_LOGGING) && !(defined(MOZ_WIDGET_GONK) || defined(MOZ_WIDGET_ANDROID))
64 if (PR_LOG_TEST(GetGFX2DLog(), PRLogLevelForLevel(aLevel))) {
65 PR_LogPrint(aString.c_str());
66 }
67 #else
68 if (aLevel >= sGfxLogLevel) {
69 printf_stderr("%s", aString.c_str());
70 }
71 #endif
72 }
74 class NoLog
75 {
76 public:
77 NoLog() {}
78 ~NoLog() {}
80 template<typename T>
81 NoLog &operator <<(const T &aLogText) { return *this; }
82 };
84 MOZ_BEGIN_ENUM_CLASS(LogOptions, int)
85 NoNewline = 0x01
86 MOZ_END_ENUM_CLASS(LogOptions)
88 template<int L>
89 class Log
90 {
91 public:
92 Log(LogOptions aOptions = LogOptions(0)) : mOptions(aOptions) {}
93 ~Log() {
94 Flush();
95 }
97 void Flush() {
98 if (!(int(mOptions) & int(LogOptions::NoNewline))) {
99 mMessage << '\n';
100 }
101 std::string str = mMessage.str();
102 if (!str.empty()) {
103 WriteLog(str);
104 }
105 mMessage.str("");
106 mMessage.clear();
107 }
109 Log &operator <<(char aChar) { mMessage << aChar; return *this; }
110 Log &operator <<(const std::string &aLogText) { mMessage << aLogText; return *this; }
111 Log &operator <<(const char aStr[]) { mMessage << static_cast<const char*>(aStr); return *this; }
112 Log &operator <<(bool aBool) { mMessage << (aBool ? "true" : "false"); return *this; }
113 Log &operator <<(int aInt) { mMessage << aInt; return *this; }
114 Log &operator <<(unsigned int aInt) { mMessage << aInt; return *this; }
115 Log &operator <<(long aLong) { mMessage << aLong; return *this; }
116 Log &operator <<(unsigned long aLong) { mMessage << aLong; return *this; }
117 Log &operator <<(long long aLong) { mMessage << aLong; return *this; }
118 Log &operator <<(unsigned long long aLong) { mMessage << aLong; return *this; }
119 Log &operator <<(Float aFloat) { mMessage << aFloat; return *this; }
120 Log &operator <<(double aDouble) { mMessage << aDouble; return *this; }
121 template <typename T, typename Sub>
122 Log &operator <<(const BasePoint<T, Sub>& aPoint)
123 { mMessage << "Point(" << aPoint.x << "," << aPoint.y << ")"; return *this; }
124 template <typename T, typename Sub>
125 Log &operator <<(const BaseSize<T, Sub>& aSize)
126 { mMessage << "Size(" << aSize.width << "," << aSize.height << ")"; return *this; }
127 template <typename T, typename Sub, typename Point, typename SizeT, typename Margin>
128 Log &operator <<(const BaseRect<T, Sub, Point, SizeT, Margin>& aRect)
129 { mMessage << "Rect(" << aRect.x << "," << aRect.y << "," << aRect.width << "," << aRect.height << ")"; return *this; }
130 Log &operator<<(const Matrix& aMatrix)
131 { mMessage << "Matrix(" << aMatrix._11 << " " << aMatrix._12 << " ; " << aMatrix._21 << " " << aMatrix._22 << " ; " << aMatrix._31 << " " << aMatrix._32 << ")"; return *this; }
134 private:
136 void WriteLog(const std::string &aString) {
137 OutputMessage(aString, L);
138 }
140 std::stringstream mMessage;
141 LogOptions mOptions;
142 };
144 typedef Log<LOG_DEBUG> DebugLog;
145 typedef Log<LOG_WARNING> WarningLog;
147 #ifdef GFX_LOG_DEBUG
148 #define gfxDebug DebugLog
149 #else
150 #define gfxDebug if (1) ; else NoLog
151 #endif
152 #ifdef GFX_LOG_WARNING
153 #define gfxWarning WarningLog
154 #else
155 #define gfxWarning if (1) ; else NoLog
156 #endif
158 const int INDENT_PER_LEVEL = 2;
160 class TreeLog
161 {
162 public:
163 TreeLog(const std::string& aPrefix = "")
164 : mLog(LogOptions::NoNewline),
165 mPrefix(aPrefix),
166 mDepth(0),
167 mStartOfLine(true),
168 mConditionedOnPref(false),
169 mPref(nullptr) {}
171 template <typename T>
172 TreeLog& operator<<(const T& aObject) {
173 if (mConditionedOnPref && !*mPref) {
174 return *this;
175 }
176 if (mStartOfLine) {
177 mLog << '[' << mPrefix << "] " << std::string(mDepth * INDENT_PER_LEVEL, ' ');
178 mStartOfLine = false;
179 }
180 mLog << aObject;
181 if (EndsInNewline(aObject)) {
182 // Don't indent right here as the user may change the indent
183 // between now and the first output to the next line.
184 mLog.Flush();
185 mStartOfLine = true;
186 }
187 return *this;
188 }
190 void IncreaseIndent() { ++mDepth; }
191 void DecreaseIndent() { --mDepth; }
193 void ConditionOnPref(bool* aPref) {
194 mConditionedOnPref = true;
195 mPref = aPref;
196 }
197 private:
198 Log<LOG_DEBUG> mLog;
199 std::string mPrefix;
200 uint32_t mDepth;
201 bool mStartOfLine;
202 bool mConditionedOnPref;
203 bool* mPref;
205 template <typename T>
206 static bool EndsInNewline(const T& aObject) {
207 return false;
208 }
210 static bool EndsInNewline(const std::string& aString) {
211 return !aString.empty() && aString[aString.length() - 1] == '\n';
212 }
214 static bool EndsInNewline(char aChar) {
215 return aChar == '\n';
216 }
218 static bool EndsInNewline(const char* aString) {
219 return EndsInNewline(std::string(aString));
220 }
221 };
223 class TreeAutoIndent
224 {
225 public:
226 TreeAutoIndent(TreeLog& aTreeLog) : mTreeLog(aTreeLog) {
227 mTreeLog.IncreaseIndent();
228 }
229 ~TreeAutoIndent() {
230 mTreeLog.DecreaseIndent();
231 }
232 private:
233 TreeLog& mTreeLog;
234 };
236 }
237 }
239 #endif /* MOZILLA_GFX_LOGGING_H_ */