WebRtcLog.cpp (5616B)
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/Preferences.h" 9 #include "nsDirectoryServiceDefs.h" 10 #include "nsDirectoryServiceUtils.h" 11 #include "nsIFile.h" 12 #include "nsStringFwd.h" 13 #include "nsThreadUtils.h" 14 #include "nsXULAppAPI.h" 15 #include "nscore.h" 16 #include "rtc_base/logging.h" 17 18 #ifdef XP_WIN 19 # include "nsNativeCharsetUtils.h" 20 #endif 21 22 using mozilla::LogLevel; 23 24 #define WEBRTC_LOG_MODULE_NAME "webrtc_trace" 25 #define WEBRTC_LOG_PREF "logging." WEBRTC_LOG_MODULE_NAME 26 static mozilla::LazyLogModule sWebRtcLog(WEBRTC_LOG_MODULE_NAME); 27 28 static webrtc::LoggingSeverity LevelToSeverity(mozilla::LogLevel aLevel) { 29 switch (aLevel) { 30 case mozilla::LogLevel::Verbose: 31 return webrtc::LoggingSeverity::LS_VERBOSE; 32 case mozilla::LogLevel::Debug: 33 case mozilla::LogLevel::Info: 34 return webrtc::LoggingSeverity::LS_INFO; 35 case mozilla::LogLevel::Warning: 36 return webrtc::LoggingSeverity::LS_WARNING; 37 case mozilla::LogLevel::Error: 38 return webrtc::LoggingSeverity::LS_ERROR; 39 case mozilla::LogLevel::Disabled: 40 return webrtc::LoggingSeverity::LS_NONE; 41 } 42 MOZ_ASSERT_UNREACHABLE("Unexpected log level"); 43 return webrtc::LoggingSeverity::LS_NONE; 44 } 45 46 static LogLevel SeverityToLevel(webrtc::LoggingSeverity aSeverity) { 47 switch (aSeverity) { 48 case webrtc::LoggingSeverity::LS_VERBOSE: 49 return mozilla::LogLevel::Verbose; 50 case webrtc::LoggingSeverity::LS_INFO: 51 return mozilla::LogLevel::Debug; 52 case webrtc::LoggingSeverity::LS_WARNING: 53 return mozilla::LogLevel::Warning; 54 case webrtc::LoggingSeverity::LS_ERROR: 55 return mozilla::LogLevel::Error; 56 case webrtc::LoggingSeverity::LS_NONE: 57 return mozilla::LogLevel::Disabled; 58 } 59 MOZ_ASSERT_UNREACHABLE("Unexpected severity"); 60 return LogLevel::Disabled; 61 } 62 63 /** 64 * Implementation of webrtc::LogSink that forwards RTC_LOG() to MOZ_LOG(). 65 */ 66 class LogSinkImpl : public WebrtcLogSinkHandle, public webrtc::LogSink { 67 NS_INLINE_DECL_REFCOUNTING(LogSinkImpl, override) 68 69 public: 70 static already_AddRefed<WebrtcLogSinkHandle> EnsureLogSink() { 71 mozilla::AssertIsOnMainThread(); 72 if (sSingleton) { 73 return do_AddRef(sSingleton); 74 } 75 return mozilla::MakeAndAddRef<LogSinkImpl>(); 76 } 77 78 static void OnPrefChanged(const char* aPref, void* aData) { 79 mozilla::AssertIsOnMainThread(); 80 MOZ_ASSERT(strcmp(aPref, WEBRTC_LOG_PREF) == 0); 81 MOZ_ASSERT(aData == sSingleton); 82 83 // Bounce to main thread again so the LogModule can settle on the new level 84 // via its own observer. 85 NS_DispatchToMainThread(mozilla::NewRunnableMethod( 86 __func__, sSingleton, &LogSinkImpl::UpdateLogLevels)); 87 } 88 89 LogSinkImpl() { 90 mozilla::AssertIsOnMainThread(); 91 MOZ_RELEASE_ASSERT(!sSingleton); 92 93 webrtc::LogMessage::AddLogToStream(this, LevelToSeverity(mLevel)); 94 sSingleton = this; 95 96 mozilla::Preferences::RegisterCallbackAndCall(&LogSinkImpl::OnPrefChanged, 97 WEBRTC_LOG_PREF, this); 98 } 99 100 private: 101 ~LogSinkImpl() { 102 mozilla::AssertIsOnMainThread(); 103 MOZ_RELEASE_ASSERT(sSingleton == this); 104 105 mozilla::Preferences::UnregisterCallback(&LogSinkImpl::OnPrefChanged, 106 WEBRTC_LOG_PREF, this); 107 webrtc::LogMessage::RemoveLogToStream(this); 108 sSingleton = nullptr; 109 } 110 111 void UpdateLogLevels() { 112 mozilla::AssertIsOnMainThread(); 113 mozilla::LogModule* webrtcModule = sWebRtcLog; 114 mozilla::LogLevel webrtcLevel = webrtcModule->Level(); 115 116 if (webrtcLevel == mLevel) { 117 return; 118 } 119 120 mLevel = webrtcLevel; 121 122 webrtc::LogMessage::RemoveLogToStream(this); 123 webrtc::LogMessage::AddLogToStream(this, LevelToSeverity(mLevel)); 124 } 125 126 void OnLogMessage(const webrtc::LogLineRef& aLogLine) override { 127 MOZ_LOG(sWebRtcLog, SeverityToLevel(aLogLine.severity()), 128 ("%s", aLogLine.DefaultLogLine().data())); 129 } 130 131 void OnLogMessage(const std::string&) override { 132 MOZ_CRASH( 133 "Called overriden OnLogMessage that is inexplicably pure virtual"); 134 } 135 136 static LogSinkImpl* sSingleton MOZ_GUARDED_BY(mozilla::sMainThreadCapability); 137 LogLevel mLevel MOZ_GUARDED_BY(mozilla::sMainThreadCapability) = 138 LogLevel::Disabled; 139 }; 140 141 LogSinkImpl* LogSinkImpl::sSingleton = nullptr; 142 143 already_AddRefed<WebrtcLogSinkHandle> EnsureWebrtcLogging() { 144 mozilla::AssertIsOnMainThread(); 145 return LogSinkImpl::EnsureLogSink(); 146 } 147 148 nsCString ConfigAecLog() { 149 nsCString aecLogDir; 150 if (webrtc::LogMessage::aec_debug()) { 151 return ""_ns; 152 } 153 #if defined(ANDROID) 154 const char* default_tmp_dir = "/dev/null"; 155 aecLogDir.Assign(default_tmp_dir); 156 #else 157 nsCOMPtr<nsIFile> tempDir; 158 nsresult rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(tempDir)); 159 if (NS_SUCCEEDED(rv)) { 160 # ifdef XP_WIN 161 // WebRTC wants a path encoded in the native charset, not UTF-8. 162 nsAutoString temp; 163 tempDir->GetPath(temp); 164 NS_CopyUnicodeToNative(temp, aecLogDir); 165 # else 166 tempDir->GetNativePath(aecLogDir); 167 # endif 168 } 169 #endif 170 webrtc::LogMessage::set_aec_debug_filename(aecLogDir.get()); 171 172 return aecLogDir; 173 } 174 175 nsCString StartAecLog() { 176 nsCString aecLogDir; 177 if (webrtc::LogMessage::aec_debug()) { 178 return ""_ns; 179 } 180 181 aecLogDir = ConfigAecLog(); 182 183 webrtc::LogMessage::set_aec_debug(true); 184 185 return aecLogDir; 186 } 187 188 void StopAecLog() { webrtc::LogMessage::set_aec_debug(false); }