/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "WebRtcLog.h" #include "mozilla/Logging.h" #include "mozilla/StaticPtr.h" #include "prenv.h" #include "rtc_base/logging.h" #include "nscore.h" #include "nsString.h" #include "nsXULAppAPI.h" #include "mozilla/Preferences.h" #include "nsIFile.h" #include "nsDirectoryServiceUtils.h" #include "nsDirectoryServiceDefs.h" #include "nsNativeCharsetUtils.h" using mozilla::LogLevel; static mozilla::LazyLogModule sWebRtcLog("webrtc_trace"); static mozilla::LazyLogModule sLogAEC("AEC"); class LogSinkImpl : public rtc::LogSink { public: LogSinkImpl() {} private: void OnLogMessage(const std::string& message) override { MOZ_LOG(sWebRtcLog, LogLevel::Debug, ("%s", message.data())); } }; // For RTC_LOG() static mozilla::StaticAutoPtr sSink; void GetWebRtcLogPrefs() { rtc::LogMessage::set_aec_debug_size( mozilla::Preferences::GetUint("media.webrtc.debug.aec_dump_max_size")); } mozilla::LogLevel CheckOverrides() { mozilla::LogModule* log_info = sWebRtcLog; mozilla::LogLevel log_level = log_info->Level(); log_info = sLogAEC; if (sLogAEC && (log_info->Level() != mozilla::LogLevel::Disabled)) { rtc::LogMessage::set_aec_debug(true); } return log_level; } void ConfigWebRtcLog(mozilla::LogLevel level) { rtc::LoggingSeverity log_level; switch (level) { case mozilla::LogLevel::Verbose: log_level = rtc::LoggingSeverity::LS_VERBOSE; break; case mozilla::LogLevel::Debug: case mozilla::LogLevel::Info: log_level = rtc::LoggingSeverity::LS_INFO; break; case mozilla::LogLevel::Warning: log_level = rtc::LoggingSeverity::LS_WARNING; break; case mozilla::LogLevel::Error: log_level = rtc::LoggingSeverity::LS_ERROR; break; case mozilla::LogLevel::Disabled: log_level = rtc::LoggingSeverity::LS_NONE; break; default: MOZ_ASSERT(false); break; } rtc::LogMessage::LogToDebug(log_level); if (level != mozilla::LogLevel::Disabled) { // always capture LOG(...) << ... logging in webrtc.org code to nspr logs if (!sSink) { sSink = new LogSinkImpl(); rtc::LogMessage::AddLogToStream(sSink, log_level); // it's ok if this leaks to program end } } else if (sSink) { rtc::LogMessage::RemoveLogToStream(sSink); sSink = nullptr; } } void StartWebRtcLog(mozilla::LogLevel log_level) { if (log_level == mozilla::LogLevel::Disabled) { return; } GetWebRtcLogPrefs(); mozilla::LogLevel level = CheckOverrides(); ConfigWebRtcLog(level); } void EnableWebRtcLog() { GetWebRtcLogPrefs(); mozilla::LogLevel level = CheckOverrides(); ConfigWebRtcLog(level); } // Called when we destroy the singletons from PeerConnectionCtx or if the // user changes logging in about:webrtc void StopWebRtcLog() { if (sSink) { rtc::LogMessage::RemoveLogToStream(sSink); sSink = nullptr; } } nsCString ConfigAecLog() { nsCString aecLogDir; if (rtc::LogMessage::aec_debug()) { return ""_ns; } #if defined(ANDROID) const char* default_tmp_dir = "/dev/null"; aecLogDir.Assign(default_tmp_dir); #else nsCOMPtr tempDir; nsresult rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(tempDir)); if (NS_SUCCEEDED(rv)) { # ifdef XP_WIN // WebRTC wants a path encoded in the native charset, not UTF-8. nsAutoString temp; tempDir->GetPath(temp); NS_CopyUnicodeToNative(temp, aecLogDir); # else tempDir->GetNativePath(aecLogDir); # endif } #endif rtc::LogMessage::set_aec_debug_filename(aecLogDir.get()); return aecLogDir; } nsCString StartAecLog() { nsCString aecLogDir; if (rtc::LogMessage::aec_debug()) { return ""_ns; } GetWebRtcLogPrefs(); CheckOverrides(); aecLogDir = ConfigAecLog(); rtc::LogMessage::set_aec_debug(true); return aecLogDir; } void StopAecLog() { rtc::LogMessage::set_aec_debug(false); }