1// Copyright (c) 2010 The Chromium Authors. All rights reserved.
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/cros/syslogs_library.h"
6
7#include "base/command_line.h"
8#include "base/file_util.h"
9#include "base/string_util.h"
10#include "chrome/browser/chromeos/cros/cros_library.h"
11#include "chrome/common/chrome_switches.h"
12#include "content/browser/browser_thread.h"
13
14namespace chromeos {
15
16const char kContextFeedback[] = "feedback";
17const char kContextSysInfo[] = "sysinfo";
18
19
20class SyslogsLibraryImpl : public SyslogsLibrary {
21 public:
22  SyslogsLibraryImpl() {}
23  virtual ~SyslogsLibraryImpl() {}
24
25  virtual Handle RequestSyslogs(
26      bool compress_logs, bool add_feedback_context,
27      CancelableRequestConsumerBase* consumer,
28      ReadCompleteCallback* callback);
29
30  // Reads system logs, compresses content if requested.
31  // Called from FILE thread.
32  void ReadSyslogs(
33      scoped_refptr<CancelableRequest<ReadCompleteCallback> > request,
34      bool compress_logs, bool add_feedback_context);
35
36  void LoadCompressedLogs(const FilePath& zip_file,
37                          std::string* zip_content);
38
39  DISALLOW_COPY_AND_ASSIGN(SyslogsLibraryImpl);
40};
41
42class SyslogsLibraryStubImpl : public SyslogsLibrary {
43 public:
44  SyslogsLibraryStubImpl() {}
45  virtual ~SyslogsLibraryStubImpl() {}
46
47  virtual Handle RequestSyslogs(bool compress_logs, bool add_feedback_context,
48                                CancelableRequestConsumerBase* consumer,
49                                ReadCompleteCallback* callback) {
50    if (callback)
51      callback->Run(Tuple2<LogDictionaryType*, std::string*>(NULL , NULL));
52
53    return 0;
54  }
55};
56
57// static
58SyslogsLibrary* SyslogsLibrary::GetImpl(bool stub) {
59  if (stub)
60    return new SyslogsLibraryStubImpl();
61  else
62    return new SyslogsLibraryImpl();
63}
64
65
66CancelableRequestProvider::Handle SyslogsLibraryImpl::RequestSyslogs(
67    bool compress_logs, bool add_feedback_context,
68    CancelableRequestConsumerBase* consumer,
69    ReadCompleteCallback* callback) {
70  // Register the callback request.
71  scoped_refptr<CancelableRequest<ReadCompleteCallback> > request(
72         new CancelableRequest<ReadCompleteCallback>(callback));
73  AddRequest(request, consumer);
74
75  // Schedule a task on the FILE thread which will then trigger a request
76  // callback on the calling thread (e.g. UI) when complete.
77  BrowserThread::PostTask(
78      BrowserThread::FILE, FROM_HERE,
79      NewRunnableMethod(
80          this, &SyslogsLibraryImpl::ReadSyslogs, request,
81          compress_logs, add_feedback_context));
82
83  return request->handle();
84}
85
86// Called from FILE thread.
87void SyslogsLibraryImpl::ReadSyslogs(
88    scoped_refptr<CancelableRequest<ReadCompleteCallback> > request,
89    bool compress_logs, bool add_feedback_context) {
90  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
91
92  if (request->canceled())
93    return;
94
95  if (compress_logs && !CommandLine::ForCurrentProcess()->HasSwitch(
96          switches::kCompressSystemFeedback))
97    compress_logs = false;
98
99  // Create temp file.
100  FilePath zip_file;
101  if (compress_logs && !file_util::CreateTemporaryFile(&zip_file)) {
102    LOG(ERROR) << "Cannot create temp file";
103    compress_logs = false;
104  }
105
106  LogDictionaryType* logs = NULL;
107  if (CrosLibrary::Get()->EnsureLoaded())
108    logs = chromeos::GetSystemLogs(
109        compress_logs ? &zip_file : NULL,
110        add_feedback_context ? kContextFeedback : kContextSysInfo);
111
112  std::string* zip_content = NULL;
113  if (compress_logs) {
114    // Load compressed logs.
115    zip_content = new std::string();
116    LoadCompressedLogs(zip_file, zip_content);
117    file_util::Delete(zip_file, false);
118  }
119
120  // Will call the callback on the calling thread.
121  request->ForwardResult(Tuple2<LogDictionaryType*,
122                                std::string*>(logs, zip_content));
123}
124
125
126void SyslogsLibraryImpl::LoadCompressedLogs(const FilePath& zip_file,
127                                            std::string* zip_content) {
128  DCHECK(zip_content);
129  if (!file_util::ReadFileToString(zip_file, zip_content)) {
130    LOG(ERROR) << "Cannot read compressed logs file from " <<
131        zip_file.value().c_str();
132  }
133}
134
135}  // namespace chromeos
136
137// Allows InvokeLater without adding refcounting. SyslogsLibraryImpl is a
138// Singleton and won't be deleted until it's last InvokeLater is run.
139DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::SyslogsLibraryImpl);
140