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