[email protected] | 4306df76 | 2012-04-20 18:58:57 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
[email protected] | d43970a7 | 2011-07-10 06:24:52 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "chrome/browser/chromeos/system/syslogs_provider.h" |
| 6 | |
[email protected] | 40c21bd | 2013-02-02 02:07:45 | [diff] [blame] | 7 | #include "ash/shell.h" |
[email protected] | 51d0215 | 2011-12-24 05:55:22 | [diff] [blame] | 8 | #include "base/bind.h" |
| 9 | #include "base/bind_helpers.h" |
[email protected] | d43970a7 | 2011-07-10 06:24:52 | [diff] [blame] | 10 | #include "base/command_line.h" |
[email protected] | 0defb7b | 2012-12-05 23:27:07 | [diff] [blame] | 11 | #include "base/compiler_specific.h" |
[email protected] | d43970a7 | 2011-07-10 06:24:52 | [diff] [blame] | 12 | #include "base/file_util.h" |
[email protected] | 5799981 | 2013-02-24 05:40:52 | [diff] [blame] | 13 | #include "base/files/file_path.h" |
[email protected] | d43970a7 | 2011-07-10 06:24:52 | [diff] [blame] | 14 | #include "base/logging.h" |
| 15 | #include "base/memory/scoped_ptr.h" |
| 16 | #include "base/memory/singleton.h" |
[email protected] | 76ae8a6 | 2013-05-10 05:34:22 | [diff] [blame] | 17 | #include "base/message_loop/message_loop_proxy.h" |
[email protected] | 5c07332 | 2013-06-11 08:03:30 | [diff] [blame] | 18 | #include "base/strings/string_util.h" |
[email protected] | 0defb7b | 2012-12-05 23:27:07 | [diff] [blame] | 19 | #include "base/task_runner.h" |
| 20 | #include "base/threading/sequenced_worker_pool.h" |
[email protected] | 40c21bd | 2013-02-02 02:07:45 | [diff] [blame] | 21 | #include "chrome/browser/feedback/feedback_util.h" |
[email protected] | 9bb480ee | 2011-08-03 21:41:16 | [diff] [blame] | 22 | #include "chrome/browser/memory_details.h" |
[email protected] | d43970a7 | 2011-07-10 06:24:52 | [diff] [blame] | 23 | #include "chrome/common/chrome_switches.h" |
[email protected] | 669b0010 | 2012-11-21 01:38:01 | [diff] [blame] | 24 | #include "chromeos/network/network_event_log.h" |
[email protected] | c38831a1 | 2011-10-28 12:44:49 | [diff] [blame] | 25 | #include "content/public/browser/browser_thread.h" |
[email protected] | 669b0010 | 2012-11-21 01:38:01 | [diff] [blame] | 26 | #include "dbus/dbus_statistics.h" |
[email protected] | d43970a7 | 2011-07-10 06:24:52 | [diff] [blame] | 27 | |
[email protected] | 631bb74 | 2011-11-02 11:29:39 | [diff] [blame] | 28 | using content::BrowserThread; |
| 29 | |
[email protected] | d43970a7 | 2011-07-10 06:24:52 | [diff] [blame] | 30 | namespace chromeos { |
| 31 | namespace system { |
[email protected] | 52c6db3 | 2012-11-22 03:19:25 | [diff] [blame] | 32 | |
| 33 | const size_t kFeedbackMaxLength = 4 * 1024; |
| 34 | const size_t kFeedbackMaxLineCount = 40; |
| 35 | |
[email protected] | d43970a7 | 2011-07-10 06:24:52 | [diff] [blame] | 36 | namespace { |
| 37 | |
| 38 | const char kSysLogsScript[] = |
| 39 | "/usr/share/userfeedback/scripts/sysinfo_script_runner"; |
| 40 | const char kBzip2Command[] = |
| 41 | "/bin/bzip2"; |
| 42 | const char kMultilineQuote[] = "\"\"\""; |
| 43 | const char kNewLineChars[] = "\r\n"; |
| 44 | const char kInvalidLogEntry[] = "<invalid characters in log entry>"; |
| 45 | const char kEmptyLogEntry[] = "<no value>"; |
| 46 | |
| 47 | const char kContextFeedback[] = "feedback"; |
| 48 | const char kContextSysInfo[] = "sysinfo"; |
| 49 | const char kContextNetwork[] = "network"; |
| 50 | |
| 51 | // Reads a key from the input string erasing the read values + delimiters read |
| 52 | // from the initial string |
| 53 | std::string ReadKey(std::string* data) { |
[email protected] | 3006639 | 2014-01-30 05:38:53 | [diff] [blame] | 54 | std::string key; |
[email protected] | d43970a7 | 2011-07-10 06:24:52 | [diff] [blame] | 55 | size_t equal_sign = data->find("="); |
| 56 | if (equal_sign == std::string::npos) |
[email protected] | d43970a7 | 2011-07-10 06:24:52 | [diff] [blame] | 57 | return key; |
[email protected] | 3006639 | 2014-01-30 05:38:53 | [diff] [blame] | 58 | key = data->substr(0, equal_sign); |
| 59 | data->erase(0, equal_sign); |
| 60 | if (data->empty()) |
| 61 | return key; |
| 62 | // erase the equal to sign also |
| 63 | data->erase(0, 1); |
| 64 | return key; |
[email protected] | d43970a7 | 2011-07-10 06:24:52 | [diff] [blame] | 65 | } |
| 66 | |
| 67 | // Reads a value from the input string; erasing the read values from |
| 68 | // the initial string; detects if the value is multiline and reads |
| 69 | // accordingly |
| 70 | std::string ReadValue(std::string* data) { |
| 71 | // Trim the leading spaces and tabs. In order to use a multi-line |
| 72 | // value, you have to place the multi-line quote on the same line as |
| 73 | // the equal sign. |
| 74 | // |
| 75 | // Why not use TrimWhitespace? Consider the following input: |
| 76 | // |
| 77 | // KEY1= |
| 78 | // KEY2=VALUE |
| 79 | // |
| 80 | // If we use TrimWhitespace, we will incorrectly trim the new line |
| 81 | // and assume that KEY1's value is "KEY2=VALUE" rather than empty. |
[email protected] | 466c986 | 2013-12-03 22:05:28 | [diff] [blame] | 82 | base::TrimString(*data, " \t", data); |
[email protected] | d43970a7 | 2011-07-10 06:24:52 | [diff] [blame] | 83 | |
| 84 | // If multiline value |
| 85 | if (StartsWithASCII(*data, std::string(kMultilineQuote), false)) { |
| 86 | data->erase(0, strlen(kMultilineQuote)); |
| 87 | size_t next_multi = data->find(kMultilineQuote); |
| 88 | if (next_multi == std::string::npos) { |
| 89 | // Error condition, clear data to stop further processing |
| 90 | data->erase(); |
| 91 | return std::string(); |
| 92 | } |
| 93 | std::string value = data->substr(0, next_multi); |
| 94 | data->erase(0, next_multi + 3); |
| 95 | return value; |
[email protected] | 3006639 | 2014-01-30 05:38:53 | [diff] [blame] | 96 | } else { |
| 97 | // single line value |
[email protected] | d43970a7 | 2011-07-10 06:24:52 | [diff] [blame] | 98 | size_t endl_pos = data->find_first_of(kNewLineChars); |
| 99 | // if we don't find a new line, we just return the rest of the data |
| 100 | std::string value = data->substr(0, endl_pos); |
| 101 | data->erase(0, endl_pos); |
| 102 | return value; |
| 103 | } |
| 104 | } |
| 105 | |
| 106 | // Returns a map of system log keys and values. |
| 107 | // |
| 108 | // Parameters: |
| 109 | // temp_filename: This is an out parameter that holds the name of a file in |
| 110 | // Reads a value from the input string; erasing the read values from |
| 111 | // the initial string; detects if the value is multiline and reads |
| 112 | // accordingly |
| 113 | // /tmp that contains the system logs in a KEY=VALUE format. |
| 114 | // If this parameter is NULL, system logs are not retained on |
| 115 | // the filesystem after this call completes. |
| 116 | // context: This is an in parameter specifying what context should be |
| 117 | // passed to the syslog collection script; currently valid |
| 118 | // values are "sysinfo" or "feedback"; in case of an invalid |
| 119 | // value, the script will currently default to "sysinfo" |
| 120 | |
[email protected] | 650b2d5 | 2013-02-10 03:41:45 | [diff] [blame] | 121 | LogDictionaryType* GetSystemLogs(base::FilePath* zip_file_name, |
[email protected] | d43970a7 | 2011-07-10 06:24:52 | [diff] [blame] | 122 | const std::string& context) { |
| 123 | // Create the temp file, logs will go here |
[email protected] | 650b2d5 | 2013-02-10 03:41:45 | [diff] [blame] | 124 | base::FilePath temp_filename; |
[email protected] | d43970a7 | 2011-07-10 06:24:52 | [diff] [blame] | 125 | |
[email protected] | 03d9afc0 | 2013-12-03 17:55:52 | [diff] [blame] | 126 | if (!base::CreateTemporaryFile(&temp_filename)) |
[email protected] | d43970a7 | 2011-07-10 06:24:52 | [diff] [blame] | 127 | return NULL; |
| 128 | |
| 129 | std::string cmd = std::string(kSysLogsScript) + " " + context + " >> " + |
| 130 | temp_filename.value(); |
| 131 | |
| 132 | // Ignore the return value - if the script execution didn't work |
| 133 | // stderr won't go into the output file anyway. |
| 134 | if (::system(cmd.c_str()) == -1) |
| 135 | LOG(WARNING) << "Command " << cmd << " failed to run"; |
| 136 | |
| 137 | // Compress the logs file if requested. |
| 138 | if (zip_file_name) { |
| 139 | cmd = std::string(kBzip2Command) + " -c " + temp_filename.value() + " > " + |
| 140 | zip_file_name->value(); |
| 141 | if (::system(cmd.c_str()) == -1) |
| 142 | LOG(WARNING) << "Command " << cmd << " failed to run"; |
| 143 | } |
| 144 | // Read logs from the temp file |
| 145 | std::string data; |
[email protected] | 82f84b9 | 2013-08-30 18:23:50 | [diff] [blame] | 146 | bool read_success = base::ReadFileToString(temp_filename, &data); |
[email protected] | d43970a7 | 2011-07-10 06:24:52 | [diff] [blame] | 147 | // if we were using an internal temp file, the user does not need the |
| 148 | // logs to stay past the ReadFile call - delete the file |
[email protected] | dd3aa79 | 2013-07-16 19:10:23 | [diff] [blame] | 149 | base::DeleteFile(temp_filename, false); |
[email protected] | d43970a7 | 2011-07-10 06:24:52 | [diff] [blame] | 150 | |
| 151 | if (!read_success) |
| 152 | return NULL; |
| 153 | |
| 154 | // Parse the return data into a dictionary |
| 155 | LogDictionaryType* logs = new LogDictionaryType(); |
| 156 | while (data.length() > 0) { |
| 157 | std::string key = ReadKey(&data); |
[email protected] | 8af69c6c | 2014-03-03 19:05:31 | [diff] [blame] | 158 | base::TrimWhitespaceASCII(key, base::TRIM_ALL, &key); |
[email protected] | d43970a7 | 2011-07-10 06:24:52 | [diff] [blame] | 159 | if (!key.empty()) { |
| 160 | std::string value = ReadValue(&data); |
[email protected] | bd6fc2f | 2014-03-17 23:55:43 | [diff] [blame] | 161 | if (IsStringUTF8(value)) { |
[email protected] | 8af69c6c | 2014-03-03 19:05:31 | [diff] [blame] | 162 | base::TrimWhitespaceASCII(value, base::TRIM_ALL, &value); |
[email protected] | d43970a7 | 2011-07-10 06:24:52 | [diff] [blame] | 163 | if (value.empty()) |
| 164 | (*logs)[key] = kEmptyLogEntry; |
| 165 | else |
| 166 | (*logs)[key] = value; |
| 167 | } else { |
| 168 | LOG(WARNING) << "Invalid characters in system log entry: " << key; |
| 169 | (*logs)[key] = kInvalidLogEntry; |
| 170 | } |
| 171 | } else { |
| 172 | // no more keys, we're done |
| 173 | break; |
| 174 | } |
| 175 | } |
| 176 | |
| 177 | return logs; |
| 178 | } |
| 179 | |
| 180 | } // namespace |
| 181 | |
| 182 | class SyslogsProviderImpl : public SyslogsProvider { |
| 183 | public: |
| 184 | // SyslogsProvider implementation: |
[email protected] | e95b717f | 2014-02-06 13:47:13 | [diff] [blame] | 185 | virtual base::CancelableTaskTracker::TaskId RequestSyslogs( |
[email protected] | d43970a7 | 2011-07-10 06:24:52 | [diff] [blame] | 186 | bool compress_logs, |
| 187 | SyslogsContext context, |
[email protected] | 0defb7b | 2012-12-05 23:27:07 | [diff] [blame] | 188 | const ReadCompleteCallback& callback, |
[email protected] | e95b717f | 2014-02-06 13:47:13 | [diff] [blame] | 189 | base::CancelableTaskTracker* tracker) OVERRIDE; |
[email protected] | d43970a7 | 2011-07-10 06:24:52 | [diff] [blame] | 190 | |
| 191 | static SyslogsProviderImpl* GetInstance(); |
| 192 | |
| 193 | private: |
| 194 | friend struct DefaultSingletonTraits<SyslogsProviderImpl>; |
| 195 | |
[email protected] | 0defb7b | 2012-12-05 23:27:07 | [diff] [blame] | 196 | // Reads system logs, compresses content if requested. |
| 197 | // Called from blocking pool thread. |
| 198 | void ReadSyslogs( |
[email protected] | e95b717f | 2014-02-06 13:47:13 | [diff] [blame] | 199 | const base::CancelableTaskTracker::IsCanceledCallback& is_canceled, |
[email protected] | 0defb7b | 2012-12-05 23:27:07 | [diff] [blame] | 200 | bool compress_logs, |
| 201 | SyslogsContext context, |
| 202 | const ReadCompleteCallback& callback); |
| 203 | |
| 204 | // Loads compressed logs and writes into |zip_content|. |
[email protected] | 650b2d5 | 2013-02-10 03:41:45 | [diff] [blame] | 205 | void LoadCompressedLogs(const base::FilePath& zip_file, |
[email protected] | 0defb7b | 2012-12-05 23:27:07 | [diff] [blame] | 206 | std::string* zip_content); |
| 207 | |
[email protected] | d43970a7 | 2011-07-10 06:24:52 | [diff] [blame] | 208 | SyslogsProviderImpl(); |
| 209 | |
| 210 | // Gets syslogs context string from the enum value. |
| 211 | const char* GetSyslogsContextString(SyslogsContext context); |
| 212 | |
[email protected] | 0defb7b | 2012-12-05 23:27:07 | [diff] [blame] | 213 | // If not canceled, run callback on originating thread (the thread on which |
| 214 | // ReadSyslogs was run). |
| 215 | static void RunCallbackIfNotCanceled( |
[email protected] | e95b717f | 2014-02-06 13:47:13 | [diff] [blame] | 216 | const base::CancelableTaskTracker::IsCanceledCallback& is_canceled, |
[email protected] | 0defb7b | 2012-12-05 23:27:07 | [diff] [blame] | 217 | base::TaskRunner* origin_runner, |
| 218 | const ReadCompleteCallback& callback, |
| 219 | LogDictionaryType* logs, |
| 220 | std::string* zip_content); |
| 221 | |
[email protected] | d43970a7 | 2011-07-10 06:24:52 | [diff] [blame] | 222 | DISALLOW_COPY_AND_ASSIGN(SyslogsProviderImpl); |
| 223 | }; |
| 224 | |
| 225 | SyslogsProviderImpl::SyslogsProviderImpl() { |
| 226 | } |
| 227 | |
[email protected] | e95b717f | 2014-02-06 13:47:13 | [diff] [blame] | 228 | base::CancelableTaskTracker::TaskId SyslogsProviderImpl::RequestSyslogs( |
[email protected] | d43970a7 | 2011-07-10 06:24:52 | [diff] [blame] | 229 | bool compress_logs, |
| 230 | SyslogsContext context, |
[email protected] | 0defb7b | 2012-12-05 23:27:07 | [diff] [blame] | 231 | const ReadCompleteCallback& callback, |
[email protected] | e95b717f | 2014-02-06 13:47:13 | [diff] [blame] | 232 | base::CancelableTaskTracker* tracker) { |
| 233 | base::CancelableTaskTracker::IsCanceledCallback is_canceled; |
| 234 | base::CancelableTaskTracker::TaskId id = |
| 235 | tracker->NewTrackedTaskId(&is_canceled); |
[email protected] | d43970a7 | 2011-07-10 06:24:52 | [diff] [blame] | 236 | |
[email protected] | 0defb7b | 2012-12-05 23:27:07 | [diff] [blame] | 237 | ReadCompleteCallback callback_runner = |
| 238 | base::Bind(&SyslogsProviderImpl::RunCallbackIfNotCanceled, |
| 239 | is_canceled, base::MessageLoopProxy::current(), callback); |
| 240 | |
| 241 | // Schedule a task which will run the callback later when complete. |
| 242 | BrowserThread::PostBlockingPoolTask( |
| 243 | FROM_HERE, |
[email protected] | 51d0215 | 2011-12-24 05:55:22 | [diff] [blame] | 244 | base::Bind(&SyslogsProviderImpl::ReadSyslogs, base::Unretained(this), |
[email protected] | 0defb7b | 2012-12-05 23:27:07 | [diff] [blame] | 245 | is_canceled, compress_logs, context, callback_runner)); |
| 246 | return id; |
[email protected] | d43970a7 | 2011-07-10 06:24:52 | [diff] [blame] | 247 | } |
| 248 | |
[email protected] | 9bb480ee | 2011-08-03 21:41:16 | [diff] [blame] | 249 | // Derived class from memoryDetails converts the results into a single string |
| 250 | // and adds a "mem_usage" entry to the logs, then forwards the result. |
| 251 | // Format of entry is (one process per line, reverse-sorted by size): |
| 252 | // Tab [Title1|Title2]: 50 MB |
| 253 | // Browser: 30 MB |
| 254 | // Tab [Title]: 20 MB |
| 255 | // Extension [Title]: 10 MB |
| 256 | // ... |
| 257 | class SyslogsMemoryHandler : public MemoryDetails { |
| 258 | public: |
| 259 | typedef SyslogsProvider::ReadCompleteCallback ReadCompleteCallback; |
| 260 | |
| 261 | // |logs| is modified (see comment above) and passed to |request|. |
| 262 | // |zip_content| is passed to |request|. |
[email protected] | 0defb7b | 2012-12-05 23:27:07 | [diff] [blame] | 263 | SyslogsMemoryHandler(const ReadCompleteCallback& callback, |
| 264 | LogDictionaryType* logs, |
| 265 | std::string* zip_content); |
[email protected] | 9bb480ee | 2011-08-03 21:41:16 | [diff] [blame] | 266 | |
[email protected] | 0defb7b | 2012-12-05 23:27:07 | [diff] [blame] | 267 | virtual void OnDetailsAvailable() OVERRIDE; |
[email protected] | 9bb480ee | 2011-08-03 21:41:16 | [diff] [blame] | 268 | |
| 269 | private: |
[email protected] | 0defb7b | 2012-12-05 23:27:07 | [diff] [blame] | 270 | virtual ~SyslogsMemoryHandler(); |
[email protected] | 9bb480ee | 2011-08-03 21:41:16 | [diff] [blame] | 271 | |
[email protected] | 0defb7b | 2012-12-05 23:27:07 | [diff] [blame] | 272 | ReadCompleteCallback callback_; |
| 273 | |
[email protected] | 9bb480ee | 2011-08-03 21:41:16 | [diff] [blame] | 274 | LogDictionaryType* logs_; |
| 275 | std::string* zip_content_; |
[email protected] | 0defb7b | 2012-12-05 23:27:07 | [diff] [blame] | 276 | |
[email protected] | 9bb480ee | 2011-08-03 21:41:16 | [diff] [blame] | 277 | DISALLOW_COPY_AND_ASSIGN(SyslogsMemoryHandler); |
| 278 | }; |
| 279 | |
[email protected] | 0defb7b | 2012-12-05 23:27:07 | [diff] [blame] | 280 | SyslogsMemoryHandler::SyslogsMemoryHandler( |
| 281 | const ReadCompleteCallback& callback, |
| 282 | LogDictionaryType* logs, |
| 283 | std::string* zip_content) |
| 284 | : callback_(callback), |
| 285 | logs_(logs), |
| 286 | zip_content_(zip_content) { |
| 287 | DCHECK(!callback_.is_null()); |
| 288 | } |
[email protected] | d43970a7 | 2011-07-10 06:24:52 | [diff] [blame] | 289 | |
[email protected] | 0defb7b | 2012-12-05 23:27:07 | [diff] [blame] | 290 | void SyslogsMemoryHandler::OnDetailsAvailable() { |
| 291 | (*logs_)["mem_usage"] = ToLogString(); |
| 292 | callback_.Run(logs_, zip_content_); |
| 293 | } |
| 294 | |
| 295 | SyslogsMemoryHandler::~SyslogsMemoryHandler() {} |
| 296 | |
| 297 | // Called from blocking pool thread. |
| 298 | void SyslogsProviderImpl::ReadSyslogs( |
[email protected] | e95b717f | 2014-02-06 13:47:13 | [diff] [blame] | 299 | const base::CancelableTaskTracker::IsCanceledCallback& is_canceled, |
[email protected] | 0defb7b | 2012-12-05 23:27:07 | [diff] [blame] | 300 | bool compress_logs, |
| 301 | SyslogsContext context, |
| 302 | const ReadCompleteCallback& callback) { |
| 303 | DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); |
| 304 | |
| 305 | if (is_canceled.Run()) |
[email protected] | d43970a7 | 2011-07-10 06:24:52 | [diff] [blame] | 306 | return; |
| 307 | |
[email protected] | d43970a7 | 2011-07-10 06:24:52 | [diff] [blame] | 308 | // Create temp file. |
[email protected] | 650b2d5 | 2013-02-10 03:41:45 | [diff] [blame] | 309 | base::FilePath zip_file; |
[email protected] | 03d9afc0 | 2013-12-03 17:55:52 | [diff] [blame] | 310 | if (compress_logs && !base::CreateTemporaryFile(&zip_file)) { |
[email protected] | d43970a7 | 2011-07-10 06:24:52 | [diff] [blame] | 311 | LOG(ERROR) << "Cannot create temp file"; |
| 312 | compress_logs = false; |
| 313 | } |
| 314 | |
| 315 | LogDictionaryType* logs = NULL; |
| 316 | logs = GetSystemLogs( |
| 317 | compress_logs ? &zip_file : NULL, |
| 318 | GetSyslogsContextString(context)); |
| 319 | |
| 320 | std::string* zip_content = NULL; |
| 321 | if (compress_logs) { |
| 322 | // Load compressed logs. |
| 323 | zip_content = new std::string(); |
| 324 | LoadCompressedLogs(zip_file, zip_content); |
[email protected] | dd3aa79 | 2013-07-16 19:10:23 | [diff] [blame] | 325 | base::DeleteFile(zip_file, false); |
[email protected] | d43970a7 | 2011-07-10 06:24:52 | [diff] [blame] | 326 | } |
| 327 | |
[email protected] | 52c6db3 | 2012-11-22 03:19:25 | [diff] [blame] | 328 | // Include dbus statistics summary |
| 329 | (*logs)["dbus"] = dbus::statistics::GetAsString( |
| 330 | dbus::statistics::SHOW_INTERFACE, |
| 331 | dbus::statistics::FORMAT_ALL); |
| 332 | |
[email protected] | 669b0010 | 2012-11-21 01:38:01 | [diff] [blame] | 333 | // Include recent network log events |
[email protected] | 5092ea87 | 2013-05-16 21:56:08 | [diff] [blame] | 334 | (*logs)["network_event_log"] = network_event_log::GetAsString( |
| 335 | network_event_log::OLDEST_FIRST, |
| 336 | "time,file,desc", |
| 337 | network_event_log::kDefaultLogLevel, |
| 338 | system::kFeedbackMaxLineCount); |
[email protected] | 669b0010 | 2012-11-21 01:38:01 | [diff] [blame] | 339 | |
[email protected] | 9bb480ee | 2011-08-03 21:41:16 | [diff] [blame] | 340 | // SyslogsMemoryHandler will clean itself up. |
| 341 | // SyslogsMemoryHandler::OnDetailsAvailable() will modify |logs| and call |
| 342 | // request->ForwardResult(logs, zip_content). |
| 343 | scoped_refptr<SyslogsMemoryHandler> |
[email protected] | 0defb7b | 2012-12-05 23:27:07 | [diff] [blame] | 344 | handler(new SyslogsMemoryHandler(callback, logs, zip_content)); |
[email protected] | 4306df76 | 2012-04-20 18:58:57 | [diff] [blame] | 345 | // TODO(jamescook): Maybe we don't need to update histograms here? |
| 346 | handler->StartFetch(MemoryDetails::UPDATE_USER_METRICS); |
[email protected] | d43970a7 | 2011-07-10 06:24:52 | [diff] [blame] | 347 | } |
| 348 | |
[email protected] | 650b2d5 | 2013-02-10 03:41:45 | [diff] [blame] | 349 | void SyslogsProviderImpl::LoadCompressedLogs(const base::FilePath& zip_file, |
[email protected] | d43970a7 | 2011-07-10 06:24:52 | [diff] [blame] | 350 | std::string* zip_content) { |
| 351 | DCHECK(zip_content); |
[email protected] | 82f84b9 | 2013-08-30 18:23:50 | [diff] [blame] | 352 | if (!base::ReadFileToString(zip_file, zip_content)) { |
[email protected] | d43970a7 | 2011-07-10 06:24:52 | [diff] [blame] | 353 | LOG(ERROR) << "Cannot read compressed logs file from " << |
| 354 | zip_file.value().c_str(); |
| 355 | } |
| 356 | } |
| 357 | |
| 358 | const char* SyslogsProviderImpl::GetSyslogsContextString( |
| 359 | SyslogsContext context) { |
| 360 | switch (context) { |
| 361 | case(SYSLOGS_FEEDBACK): |
| 362 | return kContextFeedback; |
| 363 | case(SYSLOGS_SYSINFO): |
| 364 | return kContextSysInfo; |
| 365 | case(SYSLOGS_NETWORK): |
| 366 | return kContextNetwork; |
| 367 | case(SYSLOGS_DEFAULT): |
| 368 | return kContextSysInfo; |
| 369 | default: |
| 370 | NOTREACHED(); |
| 371 | return ""; |
| 372 | } |
| 373 | } |
| 374 | |
[email protected] | 0defb7b | 2012-12-05 23:27:07 | [diff] [blame] | 375 | // static |
| 376 | void SyslogsProviderImpl::RunCallbackIfNotCanceled( |
[email protected] | e95b717f | 2014-02-06 13:47:13 | [diff] [blame] | 377 | const base::CancelableTaskTracker::IsCanceledCallback& is_canceled, |
[email protected] | 0defb7b | 2012-12-05 23:27:07 | [diff] [blame] | 378 | base::TaskRunner* origin_runner, |
| 379 | const ReadCompleteCallback& callback, |
| 380 | LogDictionaryType* logs, |
| 381 | std::string* zip_content) { |
| 382 | DCHECK(!is_canceled.is_null() && !callback.is_null()); |
| 383 | |
| 384 | if (is_canceled.Run()) { |
| 385 | delete logs; |
| 386 | delete zip_content; |
| 387 | return; |
| 388 | } |
| 389 | |
| 390 | // TODO([email protected]): Maybe always run callback asynchronously? |
| 391 | if (origin_runner->RunsTasksOnCurrentThread()) { |
| 392 | callback.Run(logs, zip_content); |
| 393 | } else { |
| 394 | origin_runner->PostTask(FROM_HERE, base::Bind(callback, logs, zip_content)); |
| 395 | } |
| 396 | } |
| 397 | |
[email protected] | d43970a7 | 2011-07-10 06:24:52 | [diff] [blame] | 398 | SyslogsProviderImpl* SyslogsProviderImpl::GetInstance() { |
| 399 | return Singleton<SyslogsProviderImpl, |
| 400 | DefaultSingletonTraits<SyslogsProviderImpl> >::get(); |
| 401 | } |
| 402 | |
| 403 | SyslogsProvider* SyslogsProvider::GetInstance() { |
| 404 | return SyslogsProviderImpl::GetInstance(); |
| 405 | } |
| 406 | |
| 407 | } // namespace system |
| 408 | } // namespace chromeos |