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
14 namespace chromeos {
15
16 const char kContextFeedback[] = "feedback";
17 const char kContextSysInfo[] = "sysinfo";
18
19
20 class SyslogsLibraryImpl : public SyslogsLibrary {
21 public:
SyslogsLibraryImpl()22 SyslogsLibraryImpl() {}
~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
42 class SyslogsLibraryStubImpl : public SyslogsLibrary {
43 public:
SyslogsLibraryStubImpl()44 SyslogsLibraryStubImpl() {}
~SyslogsLibraryStubImpl()45 virtual ~SyslogsLibraryStubImpl() {}
46
RequestSyslogs(bool compress_logs,bool add_feedback_context,CancelableRequestConsumerBase * consumer,ReadCompleteCallback * callback)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
GetImpl(bool stub)58 SyslogsLibrary* SyslogsLibrary::GetImpl(bool stub) {
59 if (stub)
60 return new SyslogsLibraryStubImpl();
61 else
62 return new SyslogsLibraryImpl();
63 }
64
65
RequestSyslogs(bool compress_logs,bool add_feedback_context,CancelableRequestConsumerBase * consumer,ReadCompleteCallback * callback)66 CancelableRequestProvider::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.
ReadSyslogs(scoped_refptr<CancelableRequest<ReadCompleteCallback>> request,bool compress_logs,bool add_feedback_context)87 void 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
LoadCompressedLogs(const FilePath & zip_file,std::string * zip_content)126 void 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.
139 DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::SyslogsLibraryImpl);
140