syslogs_provider.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_path.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/singleton.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/string_util.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/memory_details.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chromeos {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace system {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kSysLogsScript[] =
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "/usr/share/userfeedback/scripts/sysinfo_script_runner";
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kBzip2Command[] =
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "/bin/bzip2";
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kMultilineQuote[] = "\"\"\"";
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kNewLineChars[] = "\r\n";
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kInvalidLogEntry[] = "<invalid characters in log entry>";
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kEmptyLogEntry[] = "<no value>";
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kContextFeedback[] = "feedback";
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kContextSysInfo[] = "sysinfo";
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kContextNetwork[] = "network";
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Reads a key from the input string erasing the read values + delimiters read
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// from the initial string
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ReadKey(std::string* data) {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t equal_sign = data->find("=");
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (equal_sign == std::string::npos)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return std::string("");
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string key = data->substr(0, equal_sign);
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data->erase(0, equal_sign);
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (data->size() > 0) {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // erase the equal to sign also
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data->erase(0,1);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return key;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return std::string();
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Reads a value from the input string; erasing the read values from
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the initial string; detects if the value is multiline and reads
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// accordingly
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ReadValue(std::string* data) {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Trim the leading spaces and tabs. In order to use a multi-line
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // value, you have to place the multi-line quote on the same line as
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the equal sign.
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Why not use TrimWhitespace? Consider the following input:
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // KEY1=
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // KEY2=VALUE
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we use TrimWhitespace, we will incorrectly trim the new line
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and assume that KEY1's value is "KEY2=VALUE" rather than empty.
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TrimString(*data, " \t", data);
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If multiline value
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (StartsWithASCII(*data, std::string(kMultilineQuote), false)) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data->erase(0, strlen(kMultilineQuote));
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t next_multi = data->find(kMultilineQuote);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (next_multi == std::string::npos) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Error condition, clear data to stop further processing
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data->erase();
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return std::string();
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string value = data->substr(0, next_multi);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data->erase(0, next_multi + 3);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return value;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else { // single line value
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t endl_pos = data->find_first_of(kNewLineChars);
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // if we don't find a new line, we just return the rest of the data
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string value = data->substr(0, endl_pos);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data->erase(0, endl_pos);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return value;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns a map of system log keys and values.
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Parameters:
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// temp_filename: This is an out parameter that holds the name of a file in
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Reads a value from the input string; erasing the read values from
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the initial string; detects if the value is multiline and reads
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// accordingly
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                /tmp that contains the system logs in a KEY=VALUE format.
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                If this parameter is NULL, system logs are not retained on
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                the filesystem after this call completes.
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// context:       This is an in parameter specifying what context should be
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                passed to the syslog collection script; currently valid
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                values are "sysinfo" or "feedback"; in case of an invalid
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                value, the script will currently default to "sysinfo"
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LogDictionaryType* GetSystemLogs(FilePath* zip_file_name,
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const std::string& context) {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create the temp file, logs will go here
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FilePath temp_filename;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!file_util::CreateTemporaryFile(&temp_filename))
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string cmd = std::string(kSysLogsScript) + " " + context + " >> " +
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      temp_filename.value();
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ignore the return value - if the script execution didn't work
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // stderr won't go into the output file anyway.
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (::system(cmd.c_str()) == -1)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Command " << cmd << " failed to run";
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Compress the logs file if requested.
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (zip_file_name) {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cmd = std::string(kBzip2Command) + " -c " + temp_filename.value() + " > " +
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        zip_file_name->value();
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (::system(cmd.c_str()) == -1)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "Command " << cmd << " failed to run";
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read logs from the temp file
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string data;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool read_success = file_util::ReadFileToString(temp_filename,
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  &data);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // if we were using an internal temp file, the user does not need the
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // logs to stay past the ReadFile call - delete the file
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_util::Delete(temp_filename, false);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!read_success)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parse the return data into a dictionary
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogDictionaryType* logs = new LogDictionaryType();
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (data.length() > 0) {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string key = ReadKey(&data);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TrimWhitespaceASCII(key, TRIM_ALL, &key);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!key.empty()) {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string value = ReadValue(&data);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (IsStringUTF8(value)) {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        TrimWhitespaceASCII(value, TRIM_ALL, &value);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (value.empty())
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (*logs)[key] = kEmptyLogEntry;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (*logs)[key] = value;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(WARNING) << "Invalid characters in system log entry: " << key;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (*logs)[key] = kInvalidLogEntry;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // no more keys, we're done
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return logs;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SyslogsProviderImpl : public SyslogsProvider {
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SyslogsProvider implementation:
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual Handle RequestSyslogs(
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool compress_logs,
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SyslogsContext context,
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CancelableRequestConsumerBase* consumer,
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const ReadCompleteCallback& callback);
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reads system logs, compresses content if requested.
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called from FILE thread.
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ReadSyslogs(
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scoped_refptr<CancelableRequest<ReadCompleteCallback> > request,
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool compress_logs,
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SyslogsContext context);
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Loads compressed logs and writes into |zip_content|.
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void LoadCompressedLogs(const FilePath& zip_file,
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          std::string* zip_content);
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static SyslogsProviderImpl* GetInstance();
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend struct DefaultSingletonTraits<SyslogsProviderImpl>;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SyslogsProviderImpl();
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Gets syslogs context string from the enum value.
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* GetSyslogsContextString(SyslogsContext context);
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SyslogsProviderImpl);
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyslogsProviderImpl::SyslogsProviderImpl() {
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CancelableRequestProvider::Handle SyslogsProviderImpl::RequestSyslogs(
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool compress_logs,
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SyslogsContext context,
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CancelableRequestConsumerBase* consumer,
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ReadCompleteCallback& callback) {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Register the callback request.
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<CancelableRequest<ReadCompleteCallback> > request(
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         new CancelableRequest<ReadCompleteCallback>(callback));
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddRequest(request, consumer);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Schedule a task on the FILE thread which will then trigger a request
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // callback on the calling thread (e.g. UI) when complete.
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::FILE, FROM_HERE,
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&SyslogsProviderImpl::ReadSyslogs, base::Unretained(this),
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 request, compress_logs, context));
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return request->handle();
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Derived class from memoryDetails converts the results into a single string
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and adds a "mem_usage" entry to the logs, then forwards the result.
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Format of entry is (one process per line, reverse-sorted by size):
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   Tab [Title1|Title2]: 50 MB
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   Browser: 30 MB
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   Tab [Title]: 20 MB
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   Extension [Title]: 10 MB
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ...
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SyslogsMemoryHandler : public MemoryDetails {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef SyslogsProvider::ReadCompleteCallback ReadCompleteCallback;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |logs| is modified (see comment above) and passed to |request|.
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |zip_content| is passed to |request|.
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SyslogsMemoryHandler(
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scoped_refptr<CancelableRequest<ReadCompleteCallback> > request,
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LogDictionaryType* logs,
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string* zip_content)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : request_(request),
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        logs_(logs),
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        zip_content_(zip_content) {
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnDetailsAvailable() OVERRIDE {
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*logs_)["mem_usage"] = ToLogString();
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This will call the callback on the calling thread.
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request_->ForwardResult(logs_, zip_content_);
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~SyslogsMemoryHandler() {}
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<CancelableRequest<ReadCompleteCallback> > request_;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogDictionaryType* logs_;
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string* zip_content_;
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SyslogsMemoryHandler);
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Called from FILE thread.
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyslogsProviderImpl::ReadSyslogs(
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<CancelableRequest<ReadCompleteCallback> > request,
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool compress_logs,
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SyslogsContext context) {
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (request->canceled())
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create temp file.
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FilePath zip_file;
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (compress_logs && !file_util::CreateTemporaryFile(&zip_file)) {
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Cannot create temp file";
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    compress_logs = false;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogDictionaryType* logs = NULL;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  logs = GetSystemLogs(
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      compress_logs ? &zip_file : NULL,
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetSyslogsContextString(context));
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string* zip_content = NULL;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (compress_logs) {
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Load compressed logs.
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zip_content = new std::string();
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LoadCompressedLogs(zip_file, zip_content);
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file_util::Delete(zip_file, false);
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SyslogsMemoryHandler will clean itself up.
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SyslogsMemoryHandler::OnDetailsAvailable() will modify |logs| and call
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // request->ForwardResult(logs, zip_content).
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SyslogsMemoryHandler>
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      handler(new SyslogsMemoryHandler(request, logs, zip_content));
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(jamescook): Maybe we don't need to update histograms here?
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  handler->StartFetch(MemoryDetails::UPDATE_USER_METRICS);
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyslogsProviderImpl::LoadCompressedLogs(const FilePath& zip_file,
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            std::string* zip_content) {
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(zip_content);
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!file_util::ReadFileToString(zip_file, zip_content)) {
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Cannot read compressed logs file from " <<
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        zip_file.value().c_str();
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* SyslogsProviderImpl::GetSyslogsContextString(
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SyslogsContext context) {
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (context) {
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case(SYSLOGS_FEEDBACK):
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return kContextFeedback;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case(SYSLOGS_SYSINFO):
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return kContextSysInfo;
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case(SYSLOGS_NETWORK):
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return kContextNetwork;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case(SYSLOGS_DEFAULT):
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return kContextSysInfo;
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "";
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyslogsProviderImpl* SyslogsProviderImpl::GetInstance() {
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Singleton<SyslogsProviderImpl,
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   DefaultSingletonTraits<SyslogsProviderImpl> >::get();
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyslogsProvider* SyslogsProvider::GetInstance() {
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SyslogsProviderImpl::GetInstance();
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace system
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace chromeos
341