1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 #include "WebRtcLog.h"
6 
7 #include "mozilla/Logging.h"
8 #include "mozilla/StaticPtr.h"
9 #include "prenv.h"
10 #include "rtc_base/logging.h"
11 
12 #include "nscore.h"
13 #include "nsString.h"
14 #include "nsXULAppAPI.h"
15 #include "mozilla/Preferences.h"
16 
17 #include "nsIFile.h"
18 #include "nsDirectoryServiceUtils.h"
19 #include "nsDirectoryServiceDefs.h"
20 #include "nsNativeCharsetUtils.h"
21 
22 using mozilla::LogLevel;
23 
24 static mozilla::LazyLogModule sWebRtcLog("webrtc_trace");
25 static mozilla::LazyLogModule sLogAEC("AEC");
26 
27 class LogSinkImpl : public rtc::LogSink {
28  public:
LogSinkImpl()29   LogSinkImpl() {}
30 
31  private:
OnLogMessage(const std::string & message)32   void OnLogMessage(const std::string& message) override {
33     MOZ_LOG(sWebRtcLog, LogLevel::Debug, ("%s", message.data()));
34   }
35 };
36 
37 // For RTC_LOG()
38 static mozilla::StaticAutoPtr<LogSinkImpl> sSink;
39 
GetWebRtcLogPrefs()40 void GetWebRtcLogPrefs() {
41   rtc::LogMessage::set_aec_debug_size(
42       mozilla::Preferences::GetUint("media.webrtc.debug.aec_dump_max_size"));
43 }
44 
CheckOverrides()45 mozilla::LogLevel CheckOverrides() {
46   mozilla::LogModule* log_info = sWebRtcLog;
47   mozilla::LogLevel log_level = log_info->Level();
48 
49   log_info = sLogAEC;
50   if (sLogAEC && (log_info->Level() != mozilla::LogLevel::Disabled)) {
51     rtc::LogMessage::set_aec_debug(true);
52   }
53 
54   return log_level;
55 }
56 
ConfigWebRtcLog(mozilla::LogLevel level)57 void ConfigWebRtcLog(mozilla::LogLevel level) {
58   rtc::LoggingSeverity log_level;
59   switch (level) {
60     case mozilla::LogLevel::Verbose:
61       log_level = rtc::LoggingSeverity::LS_VERBOSE;
62       break;
63     case mozilla::LogLevel::Debug:
64     case mozilla::LogLevel::Info:
65       log_level = rtc::LoggingSeverity::LS_INFO;
66       break;
67     case mozilla::LogLevel::Warning:
68       log_level = rtc::LoggingSeverity::LS_WARNING;
69       break;
70     case mozilla::LogLevel::Error:
71       log_level = rtc::LoggingSeverity::LS_ERROR;
72       break;
73     case mozilla::LogLevel::Disabled:
74       log_level = rtc::LoggingSeverity::LS_NONE;
75       break;
76     default:
77       MOZ_ASSERT(false);
78       break;
79   }
80   rtc::LogMessage::LogToDebug(log_level);
81   if (level != mozilla::LogLevel::Disabled) {
82     // always capture LOG(...) << ... logging in webrtc.org code to nspr logs
83     if (!sSink) {
84       sSink = new LogSinkImpl();
85       rtc::LogMessage::AddLogToStream(sSink, log_level);
86       // it's ok if this leaks to program end
87     }
88   } else if (sSink) {
89     rtc::LogMessage::RemoveLogToStream(sSink);
90     sSink = nullptr;
91   }
92 }
93 
StartWebRtcLog(mozilla::LogLevel log_level)94 void StartWebRtcLog(mozilla::LogLevel log_level) {
95   if (log_level == mozilla::LogLevel::Disabled) {
96     return;
97   }
98 
99   GetWebRtcLogPrefs();
100   mozilla::LogLevel level = CheckOverrides();
101 
102   ConfigWebRtcLog(level);
103 }
104 
EnableWebRtcLog()105 void EnableWebRtcLog() {
106   GetWebRtcLogPrefs();
107   mozilla::LogLevel level = CheckOverrides();
108   ConfigWebRtcLog(level);
109 }
110 
111 // Called when we destroy the singletons from PeerConnectionCtx or if the
112 // user changes logging in about:webrtc
StopWebRtcLog()113 void StopWebRtcLog() {
114   if (sSink) {
115     rtc::LogMessage::RemoveLogToStream(sSink);
116     sSink = nullptr;
117   }
118 }
119 
ConfigAecLog()120 nsCString ConfigAecLog() {
121   nsCString aecLogDir;
122   if (rtc::LogMessage::aec_debug()) {
123     return ""_ns;
124   }
125 #if defined(ANDROID)
126   const char* default_tmp_dir = "/dev/null";
127   aecLogDir.Assign(default_tmp_dir);
128 #else
129   nsCOMPtr<nsIFile> tempDir;
130   nsresult rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(tempDir));
131   if (NS_SUCCEEDED(rv)) {
132 #  ifdef XP_WIN
133     // WebRTC wants a path encoded in the native charset, not UTF-8.
134     nsAutoString temp;
135     tempDir->GetPath(temp);
136     NS_CopyUnicodeToNative(temp, aecLogDir);
137 #  else
138     tempDir->GetNativePath(aecLogDir);
139 #  endif
140   }
141 #endif
142   rtc::LogMessage::set_aec_debug_filename(aecLogDir.get());
143 
144   return aecLogDir;
145 }
146 
StartAecLog()147 nsCString StartAecLog() {
148   nsCString aecLogDir;
149   if (rtc::LogMessage::aec_debug()) {
150     return ""_ns;
151   }
152 
153   GetWebRtcLogPrefs();
154   CheckOverrides();
155   aecLogDir = ConfigAecLog();
156 
157   rtc::LogMessage::set_aec_debug(true);
158 
159   return aecLogDir;
160 }
161 
StopAecLog()162 void StopAecLog() { rtc::LogMessage::set_aec_debug(false); }
163