Source code

Revision control

Copy as Markdown

Other Tools

/* 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 "nsThreadUtils.h"
#include "mozilla/Logging.h"
#include "rtc_base/logging.h"
#include "nscore.h"
#include "nsStringFwd.h"
#include "nsXULAppAPI.h"
#include "mozilla/Preferences.h"
#include "nsIFile.h"
#include "nsDirectoryServiceUtils.h"
#include "nsDirectoryServiceDefs.h"
#ifdef XP_WIN
# include "nsNativeCharsetUtils.h"
#endif
using mozilla::LogLevel;
#define WEBRTC_LOG_MODULE_NAME "webrtc_trace"
#define WEBRTC_LOG_PREF "logging." WEBRTC_LOG_MODULE_NAME
static mozilla::LazyLogModule sWebRtcLog(WEBRTC_LOG_MODULE_NAME);
static rtc::LoggingSeverity LevelToSeverity(mozilla::LogLevel aLevel) {
switch (aLevel) {
case mozilla::LogLevel::Verbose:
return rtc::LoggingSeverity::LS_VERBOSE;
case mozilla::LogLevel::Debug:
case mozilla::LogLevel::Info:
return rtc::LoggingSeverity::LS_INFO;
case mozilla::LogLevel::Warning:
return rtc::LoggingSeverity::LS_WARNING;
case mozilla::LogLevel::Error:
return rtc::LoggingSeverity::LS_ERROR;
case mozilla::LogLevel::Disabled:
return rtc::LoggingSeverity::LS_NONE;
}
MOZ_ASSERT_UNREACHABLE("Unexpected log level");
return rtc::LoggingSeverity::LS_NONE;
}
static LogLevel SeverityToLevel(rtc::LoggingSeverity aSeverity) {
switch (aSeverity) {
case rtc::LoggingSeverity::LS_VERBOSE:
return mozilla::LogLevel::Verbose;
case rtc::LoggingSeverity::LS_INFO:
return mozilla::LogLevel::Debug;
case rtc::LoggingSeverity::LS_WARNING:
return mozilla::LogLevel::Warning;
case rtc::LoggingSeverity::LS_ERROR:
return mozilla::LogLevel::Error;
case rtc::LoggingSeverity::LS_NONE:
return mozilla::LogLevel::Disabled;
}
MOZ_ASSERT_UNREACHABLE("Unexpected severity");
return LogLevel::Disabled;
}
/**
* Implementation of rtc::LogSink that forwards RTC_LOG() to MOZ_LOG().
*/
class LogSinkImpl : public WebrtcLogSinkHandle, public rtc::LogSink {
NS_INLINE_DECL_REFCOUNTING(LogSinkImpl, override)
public:
static already_AddRefed<WebrtcLogSinkHandle> EnsureLogSink() {
mozilla::AssertIsOnMainThread();
if (sSingleton) {
return do_AddRef(sSingleton);
}
return mozilla::MakeAndAddRef<LogSinkImpl>();
}
static void OnPrefChanged(const char* aPref, void* aData) {
mozilla::AssertIsOnMainThread();
MOZ_ASSERT(strcmp(aPref, WEBRTC_LOG_PREF) == 0);
MOZ_ASSERT(aData == sSingleton);
// Bounce to main thread again so the LogModule can settle on the new level
// via its own observer.
NS_DispatchToMainThread(mozilla::NewRunnableMethod(
__func__, sSingleton, &LogSinkImpl::UpdateLogLevels));
}
LogSinkImpl() {
mozilla::AssertIsOnMainThread();
MOZ_RELEASE_ASSERT(!sSingleton);
rtc::LogMessage::AddLogToStream(this, LevelToSeverity(mLevel));
sSingleton = this;
mozilla::Preferences::RegisterCallbackAndCall(&LogSinkImpl::OnPrefChanged,
WEBRTC_LOG_PREF, this);
}
private:
~LogSinkImpl() {
mozilla::AssertIsOnMainThread();
MOZ_RELEASE_ASSERT(sSingleton == this);
mozilla::Preferences::UnregisterCallback(&LogSinkImpl::OnPrefChanged,
WEBRTC_LOG_PREF, this);
rtc::LogMessage::RemoveLogToStream(this);
sSingleton = nullptr;
}
void UpdateLogLevels() {
mozilla::AssertIsOnMainThread();
mozilla::LogModule* webrtcModule = sWebRtcLog;
mozilla::LogLevel webrtcLevel = webrtcModule->Level();
if (webrtcLevel == mLevel) {
return;
}
mLevel = webrtcLevel;
rtc::LogMessage::RemoveLogToStream(this);
rtc::LogMessage::AddLogToStream(this, LevelToSeverity(mLevel));
}
void OnLogMessage(const rtc::LogLineRef& aLogLine) override {
MOZ_LOG(sWebRtcLog, SeverityToLevel(aLogLine.severity()),
("%s", aLogLine.DefaultLogLine().data()));
}
void OnLogMessage(const std::string&) override {
MOZ_CRASH(
"Called overriden OnLogMessage that is inexplicably pure virtual");
}
static LogSinkImpl* sSingleton MOZ_GUARDED_BY(mozilla::sMainThreadCapability);
LogLevel mLevel MOZ_GUARDED_BY(mozilla::sMainThreadCapability) =
LogLevel::Disabled;
};
LogSinkImpl* LogSinkImpl::sSingleton = nullptr;
already_AddRefed<WebrtcLogSinkHandle> EnsureWebrtcLogging() {
mozilla::AssertIsOnMainThread();
return LogSinkImpl::EnsureLogSink();
}
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<nsIFile> 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;
}
aecLogDir = ConfigAecLog();
rtc::LogMessage::set_aec_debug(true);
return aecLogDir;
}
void StopAecLog() { rtc::LogMessage::set_aec_debug(false); }