syslogs_provider.cc revision 5e3f23d412006dc4db4e659864679f29341e113f
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/system/syslogs_provider.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/shell.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/compiler_specific.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/singleton.h"
17b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
185e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/task_runner.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/threading/sequenced_worker_pool.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/feedback/feedback_util.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/memory_details.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromeos/network/network_event_log.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "dbus/dbus_statistics.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chromeos {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace system {
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const size_t kFeedbackMaxLength = 4 * 1024;
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const size_t kFeedbackMaxLineCount = 40;
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kSysLogsScript[] =
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "/usr/share/userfeedback/scripts/sysinfo_script_runner";
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kBzip2Command[] =
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "/bin/bzip2";
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kMultilineQuote[] = "\"\"\"";
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kNewLineChars[] = "\r\n";
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kInvalidLogEntry[] = "<invalid characters in log entry>";
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kEmptyLogEntry[] = "<no value>";
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kContextFeedback[] = "feedback";
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kContextSysInfo[] = "sysinfo";
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kContextNetwork[] = "network";
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Reads a key from the input string erasing the read values + delimiters read
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// from the initial string
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ReadKey(std::string* data) {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t equal_sign = data->find("=");
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (equal_sign == std::string::npos)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return std::string("");
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string key = data->substr(0, equal_sign);
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data->erase(0, equal_sign);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (data->size() > 0) {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // erase the equal to sign also
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data->erase(0,1);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return key;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return std::string();
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Reads a value from the input string; erasing the read values from
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the initial string; detects if the value is multiline and reads
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// accordingly
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ReadValue(std::string* data) {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Trim the leading spaces and tabs. In order to use a multi-line
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // value, you have to place the multi-line quote on the same line as
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the equal sign.
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Why not use TrimWhitespace? Consider the following input:
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // KEY1=
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // KEY2=VALUE
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we use TrimWhitespace, we will incorrectly trim the new line
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and assume that KEY1's value is "KEY2=VALUE" rather than empty.
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TrimString(*data, " \t", data);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If multiline value
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (StartsWithASCII(*data, std::string(kMultilineQuote), false)) {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data->erase(0, strlen(kMultilineQuote));
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t next_multi = data->find(kMultilineQuote);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (next_multi == std::string::npos) {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Error condition, clear data to stop further processing
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data->erase();
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return std::string();
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string value = data->substr(0, next_multi);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data->erase(0, next_multi + 3);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return value;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else { // single line value
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t endl_pos = data->find_first_of(kNewLineChars);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // if we don't find a new line, we just return the rest of the data
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string value = data->substr(0, endl_pos);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data->erase(0, endl_pos);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return value;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns a map of system log keys and values.
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Parameters:
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// temp_filename: This is an out parameter that holds the name of a file in
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Reads a value from the input string; erasing the read values from
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the initial string; detects if the value is multiline and reads
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// accordingly
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                /tmp that contains the system logs in a KEY=VALUE format.
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                If this parameter is NULL, system logs are not retained on
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                the filesystem after this call completes.
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// context:       This is an in parameter specifying what context should be
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                passed to the syslog collection script; currently valid
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                values are "sysinfo" or "feedback"; in case of an invalid
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                value, the script will currently default to "sysinfo"
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)LogDictionaryType* GetSystemLogs(base::FilePath* zip_file_name,
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const std::string& context) {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create the temp file, logs will go here
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath temp_filename;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!file_util::CreateTemporaryFile(&temp_filename))
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string cmd = std::string(kSysLogsScript) + " " + context + " >> " +
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      temp_filename.value();
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ignore the return value - if the script execution didn't work
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // stderr won't go into the output file anyway.
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (::system(cmd.c_str()) == -1)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Command " << cmd << " failed to run";
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Compress the logs file if requested.
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (zip_file_name) {
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cmd = std::string(kBzip2Command) + " -c " + temp_filename.value() + " > " +
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        zip_file_name->value();
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (::system(cmd.c_str()) == -1)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "Command " << cmd << " failed to run";
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read logs from the temp file
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string data;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool read_success = file_util::ReadFileToString(temp_filename,
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  &data);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // if we were using an internal temp file, the user does not need the
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // logs to stay past the ReadFile call - delete the file
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_util::Delete(temp_filename, false);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!read_success)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parse the return data into a dictionary
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogDictionaryType* logs = new LogDictionaryType();
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (data.length() > 0) {
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string key = ReadKey(&data);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TrimWhitespaceASCII(key, TRIM_ALL, &key);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!key.empty()) {
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string value = ReadValue(&data);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (IsStringUTF8(value)) {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        TrimWhitespaceASCII(value, TRIM_ALL, &value);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (value.empty())
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (*logs)[key] = kEmptyLogEntry;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (*logs)[key] = value;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(WARNING) << "Invalid characters in system log entry: " << key;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (*logs)[key] = kInvalidLogEntry;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // no more keys, we're done
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return logs;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SyslogsProviderImpl : public SyslogsProvider {
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SyslogsProvider implementation:
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual CancelableTaskTracker::TaskId RequestSyslogs(
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool compress_logs,
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SyslogsContext context,
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const ReadCompleteCallback& callback,
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CancelableTaskTracker* tracker) OVERRIDE;
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static SyslogsProviderImpl* GetInstance();
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  friend struct DefaultSingletonTraits<SyslogsProviderImpl>;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reads system logs, compresses content if requested.
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Called from blocking pool thread.
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ReadSyslogs(
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const CancelableTaskTracker::IsCanceledCallback& is_canceled,
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool compress_logs,
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SyslogsContext context,
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const ReadCompleteCallback& callback);
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Loads compressed logs and writes into |zip_content|.
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void LoadCompressedLogs(const base::FilePath& zip_file,
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          std::string* zip_content);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SyslogsProviderImpl();
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Gets syslogs context string from the enum value.
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* GetSyslogsContextString(SyslogsContext context);
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If not canceled, run callback on originating thread (the thread on which
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // ReadSyslogs was run).
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static void RunCallbackIfNotCanceled(
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const CancelableTaskTracker::IsCanceledCallback& is_canceled,
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::TaskRunner* origin_runner,
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const ReadCompleteCallback& callback,
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LogDictionaryType* logs,
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      std::string* zip_content);
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SyslogsProviderImpl);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyslogsProviderImpl::SyslogsProviderImpl() {
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)CancelableTaskTracker::TaskId SyslogsProviderImpl::RequestSyslogs(
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool compress_logs,
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SyslogsContext context,
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ReadCompleteCallback& callback,
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CancelableTaskTracker* tracker) {
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CancelableTaskTracker::IsCanceledCallback is_canceled;
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CancelableTaskTracker::TaskId id = tracker->NewTrackedTaskId(&is_canceled);
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ReadCompleteCallback callback_runner =
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&SyslogsProviderImpl::RunCallbackIfNotCanceled,
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 is_canceled, base::MessageLoopProxy::current(), callback);
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Schedule a task which will run the callback later when complete.
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BrowserThread::PostBlockingPoolTask(
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&SyslogsProviderImpl::ReadSyslogs, base::Unretained(this),
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 is_canceled, compress_logs, context, callback_runner));
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return id;
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Derived class from memoryDetails converts the results into a single string
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and adds a "mem_usage" entry to the logs, then forwards the result.
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Format of entry is (one process per line, reverse-sorted by size):
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   Tab [Title1|Title2]: 50 MB
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   Browser: 30 MB
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   Tab [Title]: 20 MB
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   Extension [Title]: 10 MB
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ...
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SyslogsMemoryHandler : public MemoryDetails {
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef SyslogsProvider::ReadCompleteCallback ReadCompleteCallback;
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |logs| is modified (see comment above) and passed to |request|.
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |zip_content| is passed to |request|.
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SyslogsMemoryHandler(const ReadCompleteCallback& callback,
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       LogDictionaryType* logs,
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       std::string* zip_content);
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnDetailsAvailable() OVERRIDE;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~SyslogsMemoryHandler();
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ReadCompleteCallback callback_;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogDictionaryType* logs_;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string* zip_content_;
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SyslogsMemoryHandler);
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SyslogsMemoryHandler::SyslogsMemoryHandler(
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ReadCompleteCallback& callback,
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LogDictionaryType* logs,
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string* zip_content)
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : callback_(callback),
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      logs_(logs),
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      zip_content_(zip_content) {
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!callback_.is_null());
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyslogsMemoryHandler::OnDetailsAvailable() {
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    (*logs_)["mem_usage"] = ToLogString();
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    callback_.Run(logs_, zip_content_);
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SyslogsMemoryHandler::~SyslogsMemoryHandler() {}
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Called from blocking pool thread.
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyslogsProviderImpl::ReadSyslogs(
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const CancelableTaskTracker::IsCanceledCallback& is_canceled,
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool compress_logs,
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SyslogsContext context,
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ReadCompleteCallback& callback) {
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (is_canceled.Run())
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create temp file.
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath zip_file;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (compress_logs && !file_util::CreateTemporaryFile(&zip_file)) {
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Cannot create temp file";
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    compress_logs = false;
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogDictionaryType* logs = NULL;
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  logs = GetSystemLogs(
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      compress_logs ? &zip_file : NULL,
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetSyslogsContextString(context));
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string* zip_content = NULL;
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (compress_logs) {
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Load compressed logs.
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zip_content = new std::string();
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LoadCompressedLogs(zip_file, zip_content);
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file_util::Delete(zip_file, false);
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Include dbus statistics summary
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  (*logs)["dbus"] = dbus::statistics::GetAsString(
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      dbus::statistics::SHOW_INTERFACE,
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      dbus::statistics::FORMAT_ALL);
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Include recent network log events
33390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  (*logs)["network_event_log"] = network_event_log::GetAsString(
33490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      network_event_log::OLDEST_FIRST,
33590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      "time,file,desc",
33690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      network_event_log::kDefaultLogLevel,
33790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      system::kFeedbackMaxLineCount);
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SyslogsMemoryHandler will clean itself up.
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SyslogsMemoryHandler::OnDetailsAvailable() will modify |logs| and call
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // request->ForwardResult(logs, zip_content).
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SyslogsMemoryHandler>
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      handler(new SyslogsMemoryHandler(callback, logs, zip_content));
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(jamescook): Maybe we don't need to update histograms here?
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  handler->StartFetch(MemoryDetails::UPDATE_USER_METRICS);
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyslogsProviderImpl::LoadCompressedLogs(const base::FilePath& zip_file,
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            std::string* zip_content) {
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(zip_content);
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!file_util::ReadFileToString(zip_file, zip_content)) {
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Cannot read compressed logs file from " <<
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        zip_file.value().c_str();
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* SyslogsProviderImpl::GetSyslogsContextString(
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SyslogsContext context) {
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (context) {
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case(SYSLOGS_FEEDBACK):
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return kContextFeedback;
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case(SYSLOGS_SYSINFO):
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return kContextSysInfo;
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case(SYSLOGS_NETWORK):
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return kContextNetwork;
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case(SYSLOGS_DEFAULT):
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return kContextSysInfo;
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "";
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyslogsProviderImpl::RunCallbackIfNotCanceled(
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const CancelableTaskTracker::IsCanceledCallback& is_canceled,
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::TaskRunner* origin_runner,
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ReadCompleteCallback& callback,
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LogDictionaryType* logs,
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string* zip_content) {
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!is_canceled.is_null() && !callback.is_null());
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (is_canceled.Run()) {
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    delete logs;
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    delete zip_content;
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(achuith@chromium.org): Maybe always run callback asynchronously?
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (origin_runner->RunsTasksOnCurrentThread()) {
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    callback.Run(logs, zip_content);
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    origin_runner->PostTask(FROM_HERE, base::Bind(callback, logs, zip_content));
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyslogsProviderImpl* SyslogsProviderImpl::GetInstance() {
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Singleton<SyslogsProviderImpl,
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   DefaultSingletonTraits<SyslogsProviderImpl> >::get();
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyslogsProvider* SyslogsProvider::GetInstance() {
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SyslogsProviderImpl::GetInstance();
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace system
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace chromeos
408