1/* 2 * Copyright 2018 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11#import "RTCCallbackLogger.h" 12 13#import "helpers/NSString+StdString.h" 14 15#include <memory> 16 17#include "absl/strings/string_view.h" 18#include "rtc_base/checks.h" 19#include "rtc_base/log_sinks.h" 20#include "rtc_base/logging.h" 21 22namespace { 23 24class CallbackLogSink final : public rtc::LogSink { 25 public: 26 CallbackLogSink(RTCCallbackLoggerMessageHandler callbackHandler) 27 : callback_handler_(callbackHandler) {} 28 29 void OnLogMessage(const std::string& message) override { 30 OnLogMessage(absl::string_view(message)); 31 } 32 33 void OnLogMessage(absl::string_view message) override { 34 if (callback_handler_) { 35 callback_handler_([NSString stringForAbslStringView:message]); 36 } 37 } 38 39 private: 40 RTCCallbackLoggerMessageHandler callback_handler_; 41}; 42 43class CallbackWithSeverityLogSink final : public rtc::LogSink { 44 public: 45 CallbackWithSeverityLogSink(RTCCallbackLoggerMessageAndSeverityHandler callbackHandler) 46 : callback_handler_(callbackHandler) {} 47 48 void OnLogMessage(const std::string& message) override { RTC_DCHECK_NOTREACHED(); } 49 50 void OnLogMessage(const std::string& message, rtc::LoggingSeverity severity) override { 51 OnLogMessage(absl::string_view(message), severity); 52 } 53 54 void OnLogMessage(absl::string_view message, rtc::LoggingSeverity severity) override { 55 if (callback_handler_) { 56 RTCLoggingSeverity loggingSeverity = NativeSeverityToObjcSeverity(severity); 57 callback_handler_([NSString stringForAbslStringView:message], loggingSeverity); 58 } 59 } 60 61 private: 62 static RTCLoggingSeverity NativeSeverityToObjcSeverity(rtc::LoggingSeverity severity) { 63 switch (severity) { 64 case rtc::LS_VERBOSE: 65 return RTCLoggingSeverityVerbose; 66 case rtc::LS_INFO: 67 return RTCLoggingSeverityInfo; 68 case rtc::LS_WARNING: 69 return RTCLoggingSeverityWarning; 70 case rtc::LS_ERROR: 71 return RTCLoggingSeverityError; 72 case rtc::LS_NONE: 73 return RTCLoggingSeverityNone; 74 } 75 } 76 77 RTCCallbackLoggerMessageAndSeverityHandler callback_handler_; 78}; 79 80} 81 82@implementation RTC_OBJC_TYPE (RTCCallbackLogger) { 83 BOOL _hasStarted; 84 std::unique_ptr<rtc::LogSink> _logSink; 85} 86 87@synthesize severity = _severity; 88 89- (instancetype)init { 90 self = [super init]; 91 if (self != nil) { 92 _severity = RTCLoggingSeverityInfo; 93 } 94 return self; 95} 96 97- (void)dealloc { 98 [self stop]; 99} 100 101- (void)start:(nullable RTCCallbackLoggerMessageHandler)handler { 102 if (_hasStarted) { 103 return; 104 } 105 106 _logSink.reset(new CallbackLogSink(handler)); 107 108 rtc::LogMessage::AddLogToStream(_logSink.get(), [self rtcSeverity]); 109 _hasStarted = YES; 110} 111 112- (void)startWithMessageAndSeverityHandler: 113 (nullable RTCCallbackLoggerMessageAndSeverityHandler)handler { 114 if (_hasStarted) { 115 return; 116 } 117 118 _logSink.reset(new CallbackWithSeverityLogSink(handler)); 119 120 rtc::LogMessage::AddLogToStream(_logSink.get(), [self rtcSeverity]); 121 _hasStarted = YES; 122} 123 124- (void)stop { 125 if (!_hasStarted) { 126 return; 127 } 128 RTC_DCHECK(_logSink); 129 rtc::LogMessage::RemoveLogToStream(_logSink.get()); 130 _hasStarted = NO; 131 _logSink.reset(); 132} 133 134#pragma mark - Private 135 136- (rtc::LoggingSeverity)rtcSeverity { 137 switch (_severity) { 138 case RTCLoggingSeverityVerbose: 139 return rtc::LS_VERBOSE; 140 case RTCLoggingSeverityInfo: 141 return rtc::LS_INFO; 142 case RTCLoggingSeverityWarning: 143 return rtc::LS_WARNING; 144 case RTCLoggingSeverityError: 145 return rtc::LS_ERROR; 146 case RTCLoggingSeverityNone: 147 return rtc::LS_NONE; 148 } 149} 150 151@end 152