Detach base/logging.* from base/stream.*.
This is being done in preparation of moving base/logging.* to rtc_base_approved. base/stream.* has libjingle dependencies that webrtc can't use, so logging.* can't depend on streams. It does look like stream.* isn't used much, so cleaning that up as well as cleaning up usage of the actual stream support (now LogStream) in the logging code, is in order, but I'll leave that to another cl.

BUG=
R=pthatcher@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/54529004

Cr-Original-Commit-Position: refs/heads/master@{#9269}
Cr-Mirrored-From: https://chromium.googlesource.com/external/webrtc
Cr-Mirrored-Commit: 0eefb4d5c3a11ec44360ca1fc144a5288fe4d6d0
diff --git a/base/httpbase_unittest.cc b/base/httpbase_unittest.cc
index fd5f867..d4dd775 100644
--- a/base/httpbase_unittest.cc
+++ b/base/httpbase_unittest.cc
@@ -404,7 +404,7 @@
 TEST_F(HttpBaseTest, DISABLED_AllowsCloseStreamBeforeDocumentIsComplete) {
 
   // TODO: Remove extra logging once test failure is understood
-  int old_sev = rtc::LogMessage::GetLogToDebug();
+  LoggingSeverity old_sev = rtc::LogMessage::GetLogToDebug();
   rtc::LogMessage::LogToDebug(LS_VERBOSE);
 
 
diff --git a/base/logging.cc b/base/logging.cc
index 2cf567c..ea7c0ff 100644
--- a/base/logging.cc
+++ b/base/logging.cc
@@ -35,7 +35,7 @@
 #include <vector>
 
 #include "webrtc/base/logging.h"
-#include "webrtc/base/stream.h"
+#include "webrtc/base/scoped_ptr.h"
 #include "webrtc/base/stringencode.h"
 #include "webrtc/base/stringutils.h"
 #include "webrtc/base/timeutils.h"
@@ -73,24 +73,18 @@
 // LogMessage
 /////////////////////////////////////////////////////////////////////////////
 
-const int LogMessage::NO_LOGGING = LS_ERROR + 1;
-
+// By default, release builds don't log, debug builds at info level
 #if _DEBUG
-static const int LOG_DEFAULT = LS_INFO;
+LoggingSeverity LogMessage::min_sev_ = LS_INFO;
+LoggingSeverity LogMessage::dbg_sev_ = LS_INFO;
 #else  // !_DEBUG
-static const int LOG_DEFAULT = LogMessage::NO_LOGGING;
+LoggingSeverity LogMessage::min_sev_ = LS_NONE;
+LoggingSeverity LogMessage::dbg_sev_ = LS_NONE;
 #endif  // !_DEBUG
 
 // Global lock for log subsystem, only needed to serialize access to streams_.
 CriticalSection LogMessage::crit_;
 
-// By default, release builds don't log, debug builds at info level
-int LogMessage::min_sev_ = LOG_DEFAULT;
-int LogMessage::dbg_sev_ = LOG_DEFAULT;
-
-// Don't bother printing context for the ubiquitous INFO log messages
-int LogMessage::ctx_sev_ = LS_WARNING;
-
 // The list of logging streams currently configured.
 // Note: we explicitly do not clean this up, because of the uncertain ordering
 // of destructors at program exit.  Let the person who sets the stream trigger
@@ -121,12 +115,7 @@
 #if defined(WEBRTC_WIN)
     DWORD id = GetCurrentThreadId();
     print_stream_ << "[" << std::hex << id << std::dec << "] ";
-#endif  // WEBRTC_WIN 
-  }
-
-  if (severity_ >= ctx_sev_) {
-    print_stream_ << Describe(sev) << "(" << DescribeFile(file)
-                  << ":" << line << "): ";
+#endif  // WEBRTC_WIN
   }
 
   if (err_ctx != ERRCTX_NONE) {
@@ -155,7 +144,7 @@
         }
         break;
       }
-#endif  // WEBRTC_WIN 
+#endif  // WEBRTC_WIN
 #if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
       case ERRCTX_OSSTATUS: {
         tmp << " " << nonnull(GetMacOSStatusErrorString(err), "Unknown error");
@@ -187,7 +176,7 @@
   CritScope cs(&crit_);
   for (StreamList::iterator it = streams_.begin(); it != streams_.end(); ++it) {
     if (severity_ >= it->second) {
-      OutputToStream(it->first, str);
+      it->first->OnLogMessage(str);
     }
   }
   uint32 delay = TimeSince(before);
@@ -213,10 +202,6 @@
   return g_start_wallclock;
 }
 
-void LogMessage::LogContext(int min_sev) {
-  ctx_sev_ = min_sev;
-}
-
 void LogMessage::LogThreads(bool on) {
   thread_ = on;
 }
@@ -225,12 +210,12 @@
   timestamp_ = on;
 }
 
-void LogMessage::LogToDebug(int min_sev) {
+void LogMessage::LogToDebug(LoggingSeverity min_sev) {
   dbg_sev_ = min_sev;
   UpdateMinLogSeverity();
 }
 
-void LogMessage::LogToStream(StreamInterface* stream, int min_sev) {
+void LogMessage::LogToStream(LogSink* stream, LoggingSeverity min_sev) {
   CritScope cs(&crit_);
   // Discard and delete all previously installed streams
   for (StreamList::iterator it = streams_.begin(); it != streams_.end(); ++it) {
@@ -243,9 +228,9 @@
   }
 }
 
-int LogMessage::GetLogToStream(StreamInterface* stream) {
+int LogMessage::GetLogToStream(LogSink* stream) {
   CritScope cs(&crit_);
-  int sev = NO_LOGGING;
+  LoggingSeverity sev = LS_NONE;
   for (StreamList::iterator it = streams_.begin(); it != streams_.end(); ++it) {
     if (!stream || stream == it->first) {
       sev = std::min(sev, it->second);
@@ -254,13 +239,13 @@
   return sev;
 }
 
-void LogMessage::AddLogToStream(StreamInterface* stream, int min_sev) {
+void LogMessage::AddLogToStream(LogSink* stream, LoggingSeverity min_sev) {
   CritScope cs(&crit_);
   streams_.push_back(std::make_pair(stream, min_sev));
   UpdateMinLogSeverity();
 }
 
-void LogMessage::RemoveLogToStream(StreamInterface* stream) {
+void LogMessage::RemoveLogToStream(LogSink* stream) {
   CritScope cs(&crit_);
   for (StreamList::iterator it = streams_.begin(); it != streams_.end(); ++it) {
     if (stream == it->first) {
@@ -271,48 +256,45 @@
   UpdateMinLogSeverity();
 }
 
-void LogMessage::ConfigureLogging(const char* params, const char* filename) {
-  int current_level = LS_VERBOSE;
-  int debug_level = GetLogToDebug();
-  int file_level = GetLogToStream();
+void LogMessage::ConfigureLogging(const char* params) {
+  LoggingSeverity current_level = LS_VERBOSE;
+  LoggingSeverity debug_level = GetLogToDebug();
 
   std::vector<std::string> tokens;
   tokenize(params, ' ', &tokens);
 
-  for (size_t i = 0; i < tokens.size(); ++i) {
-    if (tokens[i].empty())
+  for (const std::string& token : tokens) {
+    if (token.empty())
       continue;
 
     // Logging features
-    if (tokens[i] == "tstamp") {
+    if (token == "tstamp") {
       LogTimestamps();
-    } else if (tokens[i] == "thread") {
+    } else if (token == "thread") {
       LogThreads();
 
     // Logging levels
-    } else if (tokens[i] == "sensitive") {
+    } else if (token == "sensitive") {
       current_level = LS_SENSITIVE;
-    } else if (tokens[i] == "verbose") {
+    } else if (token == "verbose") {
       current_level = LS_VERBOSE;
-    } else if (tokens[i] == "info") {
+    } else if (token == "info") {
       current_level = LS_INFO;
-    } else if (tokens[i] == "warning") {
+    } else if (token == "warning") {
       current_level = LS_WARNING;
-    } else if (tokens[i] == "error") {
+    } else if (token == "error") {
       current_level = LS_ERROR;
-    } else if (tokens[i] == "none") {
-      current_level = NO_LOGGING;
+    } else if (token == "none") {
+      current_level = LS_NONE;
 
     // Logging targets
-    } else if (tokens[i] == "file") {
-      file_level = current_level;
-    } else if (tokens[i] == "debug") {
+    } else if (token == "debug") {
       debug_level = current_level;
     }
   }
 
 #if defined(WEBRTC_WIN)
-  if ((NO_LOGGING != debug_level) && !::IsDebuggerPresent()) {
+  if ((LS_NONE != debug_level) && !::IsDebuggerPresent()) {
     // First, attempt to attach to our parent's console... so if you invoke
     // from the command line, we'll see the output there.  Otherwise, create
     // our own console window.
@@ -331,69 +313,19 @@
       ::AllocConsole();
     }
   }
-#endif  // WEBRTC_WIN 
+#endif  // WEBRTC_WIN
 
   LogToDebug(debug_level);
-
-#if !defined(__native_client__)  // No logging to file in NaCl.
-  scoped_ptr<FileStream> stream;
-  if (NO_LOGGING != file_level) {
-    stream.reset(new FileStream);
-    if (!stream->Open(filename, "wb", NULL) || !stream->DisableBuffering()) {
-      stream.reset();
-    }
-  }
-
-  LogToStream(stream.release(), file_level);
-#endif
-}
-
-int LogMessage::ParseLogSeverity(const std::string& value) {
-  int level = NO_LOGGING;
-  if (value == "LS_SENSITIVE") {
-    level = LS_SENSITIVE;
-  } else if (value == "LS_VERBOSE") {
-    level = LS_VERBOSE;
-  } else if (value == "LS_INFO") {
-    level = LS_INFO;
-  } else if (value == "LS_WARNING") {
-    level = LS_WARNING;
-  } else if (value == "LS_ERROR") {
-    level = LS_ERROR;
-  } else if (isdigit(value[0])) {
-    level = atoi(value.c_str());  // NOLINT
-  }
-  return level;
 }
 
 void LogMessage::UpdateMinLogSeverity() {
-  int min_sev = dbg_sev_;
+  LoggingSeverity min_sev = dbg_sev_;
   for (StreamList::iterator it = streams_.begin(); it != streams_.end(); ++it) {
     min_sev = std::min(dbg_sev_, it->second);
   }
   min_sev_ = min_sev;
 }
 
-const char* LogMessage::Describe(LoggingSeverity sev) {
-  switch (sev) {
-  case LS_SENSITIVE: return "Sensitive";
-  case LS_VERBOSE:   return "Verbose";
-  case LS_INFO:      return "Info";
-  case LS_WARNING:   return "Warning";
-  case LS_ERROR:     return "Error";
-  default:           return "<unknown>";
-  }
-}
-
-const char* LogMessage::DescribeFile(const char* file) {
-  const char* end1 = ::strrchr(file, '/');
-  const char* end2 = ::strrchr(file, '\\');
-  if (!end1 && !end2)
-    return file;
-  else
-    return (end1 > end2) ? end1 + 1 : end2 + 1;
-}
-
 void LogMessage::OutputToDebug(const std::string& str,
                                LoggingSeverity severity) {
   bool log_to_stderr = true;
@@ -430,7 +362,7 @@
                   &written, 0);
     }
   }
-#endif  // WEBRTC_WIN 
+#endif  // WEBRTC_WIN
 #if defined(WEBRTC_ANDROID)
   // Android's logging facility uses severity to log messages but we
   // need to map libjingle's severity levels to Android ones first.
@@ -487,12 +419,6 @@
   }
 }
 
-void LogMessage::OutputToStream(StreamInterface* stream,
-                                const std::string& str) {
-  // If write isn't fully successful, what are we going to do, log it? :)
-  stream->WriteAll(str.data(), str.size(), NULL, NULL);
-}
-
 //////////////////////////////////////////////////////////////////////
 // Logging Helpers
 //////////////////////////////////////////////////////////////////////
diff --git a/base/logging.h b/base/logging.h
index c1315ae..2fb6f3e 100644
--- a/base/logging.h
+++ b/base/logging.h
@@ -10,7 +10,7 @@
 
 //   LOG(...) an ostream target that can be used to send formatted
 // output to a variety of logging targets, such as debugger console, stderr,
-// file, or any StreamInterface.
+// or any LogSink.
 //   The severity level passed as the first argument to the LOGging
 // functions is used as a filter, to limit the verbosity of the logging.
 //   Static members of LogMessage documented below are used to control the
@@ -59,8 +59,6 @@
 
 namespace rtc {
 
-class StreamInterface;
-
 ///////////////////////////////////////////////////////////////////////////////
 // ConstantLabel can be used to easily generate string names from constant
 // values.  This can be useful for logging descriptive names of error messages.
@@ -96,10 +94,18 @@
 //   in debug builds.
 //  LS_WARNING: Something that may warrant investigation.
 //  LS_ERROR: Something that should not have occurred.
-enum LoggingSeverity { LS_SENSITIVE, LS_VERBOSE, LS_INFO, LS_WARNING, LS_ERROR,
-                       INFO = LS_INFO,
-                       WARNING = LS_WARNING,
-                       LERROR = LS_ERROR };
+//  LS_NONE: Don't log.
+enum LoggingSeverity {
+  LS_SENSITIVE,
+  LS_VERBOSE,
+  LS_INFO,
+  LS_WARNING,
+  LS_ERROR,
+  LS_NONE,
+  INFO = LS_INFO,
+  WARNING = LS_WARNING,
+  LERROR = LS_ERROR
+};
 
 // LogErrorContext assists in interpreting the meaning of an error value.
 enum LogErrorContext {
@@ -114,9 +120,16 @@
   ERRCTX_OS = ERRCTX_OSSTATUS,  // LOG_E(sev, OS, x)
 };
 
+// Virtual sink interface that can receive log messages.
+class LogSink {
+ public:
+  LogSink() {}
+  virtual ~LogSink() {}
+  virtual void OnLogMessage(const std::string& message) = 0;
+};
+
 class LogMessage {
  public:
-  static const int NO_LOGGING;
   static const uint32 WARN_SLOW_LOGS_DELAY = 50;  // ms
 
   LogMessage(const char* file, int line, LoggingSeverity sev,
@@ -138,9 +151,6 @@
   // epoch.
   static uint32 WallClockStartTime();
 
-  // These are attributes which apply to all logging channels
-  //  LogContext: Display the file and line number of the message
-  static void LogContext(int min_sev);
   //  LogThreads: Display the thread identifier of the current thread
   static void LogThreads(bool on = true);
   //  LogTimestamps: Display the elapsed time of the program
@@ -148,8 +158,8 @@
 
   // These are the available logging channels
   //  Debug: Debug console on Windows, otherwise stderr
-  static void LogToDebug(int min_sev);
-  static int GetLogToDebug() { return dbg_sev_; }
+  static void LogToDebug(LoggingSeverity min_sev);
+  static LoggingSeverity GetLogToDebug() { return dbg_sev_; }
 
   //  Stream: Any non-blocking stream interface.  LogMessage takes ownership of
   //   the stream. Multiple streams may be specified by using AddLogToStream.
@@ -158,10 +168,10 @@
   //   GetLogToStream gets the severity for the specified stream, of if none
   //   is specified, the minimum stream severity.
   //   RemoveLogToStream removes the specified stream, without destroying it.
-  static void LogToStream(StreamInterface* stream, int min_sev);
-  static int GetLogToStream(StreamInterface* stream = NULL);
-  static void AddLogToStream(StreamInterface* stream, int min_sev);
-  static void RemoveLogToStream(StreamInterface* stream);
+  static void LogToStream(LogSink* stream, LoggingSeverity min_sev);
+  static int GetLogToStream(LogSink* stream = NULL);
+  static void AddLogToStream(LogSink* stream, LoggingSeverity min_sev);
+  static void RemoveLogToStream(LogSink* stream);
 
   // Testing against MinLogSeverity allows code to avoid potentially expensive
   // logging operations by pre-checking the logging level.
@@ -171,26 +181,18 @@
   static bool IsDiagnosticMode() { return is_diagnostic_mode_; }
 
   // Parses the provided parameter stream to configure the options above.
-  // Useful for configuring logging from the command line.  If file logging
-  // is enabled, it is output to the specified filename.
-  static void ConfigureLogging(const char* params, const char* filename);
-
-  // Convert the string to a LS_ value; also accept numeric values.
-  static int ParseLogSeverity(const std::string& value);
+  // Useful for configuring logging from the command line.
+  static void ConfigureLogging(const char* params);
 
  private:
-  typedef std::list<std::pair<StreamInterface*, int> > StreamList;
+  typedef std::pair<LogSink*, LoggingSeverity> StreamAndSeverity;
+  typedef std::list<StreamAndSeverity> StreamList;
 
   // Updates min_sev_ appropriately when debug sinks change.
   static void UpdateMinLogSeverity();
 
-  // These assist in formatting some parts of the debug output.
-  static const char* Describe(LoggingSeverity sev);
-  static const char* DescribeFile(const char* file);
-
   // These write out the actual log messages.
   static void OutputToDebug(const std::string& msg, LoggingSeverity severity_);
-  static void OutputToStream(StreamInterface* stream, const std::string& msg);
 
   // The ostream that buffers the formatted message before output
   std::ostringstream print_stream_;
@@ -214,7 +216,7 @@
   //  as a short-circuit in the logging macros to identify messages that won't
   //  be logged.
   // ctx_sev_ is the minimum level at which file context is displayed
-  static int min_sev_, dbg_sev_, ctx_sev_;
+  static LoggingSeverity min_sev_, dbg_sev_, ctx_sev_;
 
   // The output streams and their associated severities
   static StreamList streams_;
@@ -335,7 +337,7 @@
   LOG_ERRNO(sev)
 #define LAST_SYSTEM_ERROR \
   (errno)
-#endif  // WEBRTC_WIN 
+#endif  // WEBRTC_WIN
 
 #define PLOG(sev, err) \
   LOG_ERR_EX(sev, err)
diff --git a/base/logging_unittest.cc b/base/logging_unittest.cc
index 7d7c97e..db744b5 100644
--- a/base/logging_unittest.cc
+++ b/base/logging_unittest.cc
@@ -18,13 +18,35 @@
 
 namespace rtc {
 
+template <typename Base>
+class LogSinkImpl
+    : public LogSink,
+      public Base {
+ public:
+  LogSinkImpl() {}
+
+  // The non-const reference constructor is required because of StringStream.
+  // TODO(tommi): Fix StringStream to accept a pointer for non-const.
+  template<typename P>
+  explicit LogSinkImpl(P& p) : Base(p) {}
+
+  template<typename P>
+  explicit LogSinkImpl(const P& p) : Base(p) {}
+
+ private:
+  void OnLogMessage(const std::string& message) override {
+    static_cast<Base*>(this)->WriteAll(
+        message.data(), message.size(), nullptr, nullptr);
+  }
+};
+
 // Test basic logging operation. We should get the INFO log but not the VERBOSE.
 // We should restore the correct global state at the end.
 TEST(LogTest, SingleStream) {
   int sev = LogMessage::GetLogToStream(NULL);
 
   std::string str;
-  StringStream stream(str);
+  LogSinkImpl<StringStream> stream(str);
   LogMessage::AddLogToStream(&stream, LS_INFO);
   EXPECT_EQ(LS_INFO, LogMessage::GetLogToStream(&stream));
 
@@ -34,7 +56,7 @@
   EXPECT_EQ(std::string::npos, str.find("VERBOSE"));
 
   LogMessage::RemoveLogToStream(&stream);
-  EXPECT_EQ(LogMessage::NO_LOGGING, LogMessage::GetLogToStream(&stream));
+  EXPECT_EQ(LS_NONE, LogMessage::GetLogToStream(&stream));
 
   EXPECT_EQ(sev, LogMessage::GetLogToStream(NULL));
 }
@@ -46,7 +68,7 @@
   int sev = LogMessage::GetLogToStream(NULL);
 
   std::string str1, str2;
-  StringStream stream1(str1), stream2(str2);
+  LogSinkImpl<StringStream> stream1(str1), stream2(str2);
   LogMessage::AddLogToStream(&stream1, LS_INFO);
   LogMessage::AddLogToStream(&stream2, LS_VERBOSE);
   EXPECT_EQ(LS_INFO, LogMessage::GetLogToStream(&stream1));
@@ -62,8 +84,8 @@
 
   LogMessage::RemoveLogToStream(&stream2);
   LogMessage::RemoveLogToStream(&stream1);
-  EXPECT_EQ(LogMessage::NO_LOGGING, LogMessage::GetLogToStream(&stream2));
-  EXPECT_EQ(LogMessage::NO_LOGGING, LogMessage::GetLogToStream(&stream1));
+  EXPECT_EQ(LS_NONE, LogMessage::GetLogToStream(&stream2));
+  EXPECT_EQ(LS_NONE, LogMessage::GetLogToStream(&stream1));
 
   EXPECT_EQ(sev, LogMessage::GetLogToStream(NULL));
 }
@@ -91,7 +113,7 @@
   thread2.Start();
   thread3.Start();
 
-  NullStream stream1, stream2, stream3;
+  LogSinkImpl<NullStream> stream1, stream2, stream3;
   for (int i = 0; i < 1000; ++i) {
     LogMessage::AddLogToStream(&stream1, LS_INFO);
     LogMessage::AddLogToStream(&stream2, LS_VERBOSE);
@@ -117,7 +139,7 @@
   EXPECT_TRUE(Filesystem::GetTemporaryFolder(path, true, NULL));
   path.SetPathname(Filesystem::TempFilename(path, "ut"));
 
-  FileStream stream;
+  LogSinkImpl<FileStream> stream;
   EXPECT_TRUE(stream.Open(path.pathname(), "wb", NULL));
   stream.DisableBuffering();
   LogMessage::AddLogToStream(&stream, LS_SENSITIVE);
diff --git a/base/unittest_main.cc b/base/unittest_main.cc
index c9864fe..e243c52 100644
--- a/base/unittest_main.cc
+++ b/base/unittest_main.cc
@@ -51,7 +51,7 @@
     return TRUE;
   }
 }
-#endif  // WEBRTC_WIN 
+#endif  // WEBRTC_WIN
 
 int main(int argc, char** argv) {
   testing::InitGoogleTest(&argc, argv);
@@ -75,7 +75,7 @@
     _crtBreakAlloc = FLAG_crt_break_alloc;
   }
 #endif  // _DEBUG
-#endif  // WEBRTC_WIN 
+#endif  // WEBRTC_WIN
 
   rtc::Filesystem::SetOrganizationName("google");
   rtc::Filesystem::SetApplicationName("unittest");
@@ -83,7 +83,7 @@
   // By default, log timestamps. Allow overrides by used of a --log flag.
   rtc::LogMessage::LogTimestamps();
   if (*FLAG_log != '\0') {
-    rtc::LogMessage::ConfigureLogging(FLAG_log, "unittest.log");
+    rtc::LogMessage::ConfigureLogging(FLAG_log);
   }
 
   // Initialize SSL which are used by several tests.
@@ -94,7 +94,7 @@
   rtc::CleanupSSL();
 
   // clean up logging so we don't appear to leak memory.
-  rtc::LogMessage::ConfigureLogging("", "");
+  rtc::LogMessage::ConfigureLogging("");
 
 #if defined(WEBRTC_WIN)
   // Unhook crt function so that we don't ever log after statics have been