1 // Copyright (c) 2012 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.
5 #include "chrome/browser/feedback/feedback_data.h"
7 #include "base/file_util.h"
8 #include "base/json/json_string_value_serializer.h"
9 #include "base/strings/string_util.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/values.h"
12 #include "chrome/browser/browser_process.h"
13 #include "chrome/browser/chromeos/settings/cros_settings.h"
14 #include "chrome/browser/feedback/feedback_util.h"
15 #include "chrome/browser/feedback/tracing_manager.h"
16 #include "chrome/browser/profiles/profile_manager.h"
17 #include "content/public/browser/browser_thread.h"
20 #include "ash/shell.h"
21 #include "ash/shell_delegate.h"
24 using content::BrowserThread
;
28 const char kMultilineIndicatorString
[] = "<multiline>\n";
29 const char kMultilineStartString
[] = "---------- START ----------\n";
30 const char kMultilineEndString
[] = "---------- END ----------\n\n";
32 const size_t kFeedbackMaxLength
= 4 * 1024;
33 const size_t kFeedbackMaxLineCount
= 40;
35 const char kTraceFilename
[] = "tracing.zip\n";
36 const char kPerformanceCategoryTag
[] = "Performance";
38 const char kZipExt
[] = ".zip";
40 const base::FilePath::CharType kLogsFilename
[] =
41 FILE_PATH_LITERAL("system_logs.txt");
42 const base::FilePath::CharType kHistogramsFilename
[] =
43 FILE_PATH_LITERAL("histograms.txt");
45 // Converts the system logs into a string that we can compress and send
46 // with the report. This method only converts those logs that we want in
47 // the compressed zip file sent with the report, hence it ignores any logs
48 // below the size threshold of what we want compressed.
49 std::string
LogsToString(const FeedbackData::SystemLogsMap
& sys_info
) {
50 std::string syslogs_string
;
51 for (FeedbackData::SystemLogsMap::const_iterator it
= sys_info
.begin();
52 it
!= sys_info
.end(); ++it
) {
53 std::string key
= it
->first
;
54 std::string value
= it
->second
;
56 if (FeedbackData::BelowCompressionThreshold(value
))
59 base::TrimString(key
, "\n ", &key
);
60 base::TrimString(value
, "\n ", &value
);
62 if (value
.find("\n") != std::string::npos
) {
63 syslogs_string
.append(
64 key
+ "=" + kMultilineIndicatorString
+
65 kMultilineStartString
+
69 syslogs_string
.append(key
+ "=" + value
+ "\n");
72 return syslogs_string
;
75 void ZipFile(const base::FilePath
& filename
,
76 const std::string
& data
, std::string
* compressed_data
) {
77 if (!feedback_util::ZipString(filename
, data
, compressed_data
))
78 compressed_data
->clear();
81 void ZipLogs(const FeedbackData::SystemLogsMap
& sys_info
,
82 std::string
* compressed_logs
) {
83 DCHECK(compressed_logs
);
84 std::string logs_string
= LogsToString(sys_info
);
85 if (logs_string
.empty() ||
86 !feedback_util::ZipString(
87 base::FilePath(kLogsFilename
), logs_string
, compressed_logs
)) {
88 compressed_logs
->clear();
92 void ZipHistograms(const std::string
& histograms
,
93 std::string
* compressed_histograms
) {
94 DCHECK(compressed_histograms
);
95 if (histograms
.empty() ||
96 !feedback_util::ZipString(
97 base::FilePath(kHistogramsFilename
),
99 compressed_histograms
)) {
100 compressed_histograms
->clear();
107 bool FeedbackData::BelowCompressionThreshold(const std::string
& content
) {
108 if (content
.length() > kFeedbackMaxLength
)
110 const size_t line_count
= std::count(content
.begin(), content
.end(), '\n');
111 if (line_count
> kFeedbackMaxLineCount
)
116 FeedbackData::FeedbackData() : profile_(NULL
),
118 feedback_page_data_complete_(false),
119 syslogs_compression_complete_(false),
120 histograms_compression_complete_(false),
121 attached_file_compression_complete_(false),
122 report_sent_(false) {
125 FeedbackData::~FeedbackData() {
128 void FeedbackData::OnFeedbackPageDataComplete() {
129 feedback_page_data_complete_
= true;
133 void FeedbackData::SetAndCompressSystemInfo(
134 scoped_ptr
<FeedbackData::SystemLogsMap
> sys_info
) {
135 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
137 if (trace_id_
!= 0) {
138 TracingManager
* manager
= TracingManager::Get();
140 !manager
->GetTraceData(
142 base::Bind(&FeedbackData::OnGetTraceData
, this, trace_id_
))) {
147 sys_info_
= sys_info
.Pass();
148 if (sys_info_
.get()) {
149 std::string
* compressed_logs_ptr
= new std::string
;
150 scoped_ptr
<std::string
> compressed_logs(compressed_logs_ptr
);
151 BrowserThread::PostBlockingPoolTaskAndReply(
155 compressed_logs_ptr
),
156 base::Bind(&FeedbackData::OnCompressLogsComplete
,
158 base::Passed(&compressed_logs
)));
162 void FeedbackData::SetAndCompressHistograms(
163 scoped_ptr
<std::string
> histograms
) {
164 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
166 histograms_
= histograms
.Pass();
167 if (histograms_
.get()) {
168 std::string
* compressed_histograms_ptr
= new std::string
;
169 scoped_ptr
<std::string
> compressed_histograms(compressed_histograms_ptr
);
170 BrowserThread::PostBlockingPoolTaskAndReply(
172 base::Bind(&ZipHistograms
,
174 compressed_histograms_ptr
),
175 base::Bind(&FeedbackData::OnCompressHistogramsComplete
,
177 base::Passed(&compressed_histograms
)));
181 void FeedbackData::AttachAndCompressFileData(
182 scoped_ptr
<std::string
> attached_filedata
) {
183 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
185 attached_filedata_
= attached_filedata
.Pass();
187 if (!attached_filename_
.empty() && attached_filedata_
.get()) {
188 std::string
* compressed_file_ptr
= new std::string
;
189 scoped_ptr
<std::string
> compressed_file(compressed_file_ptr
);
191 base::FilePath
attached_file(base::UTF8ToWide(attached_filename_
));
193 base::FilePath
attached_file(attached_filename_
);
195 BrowserThread::PostBlockingPoolTaskAndReply(
199 *(attached_filedata_
.get()),
200 compressed_file_ptr
),
201 base::Bind(&FeedbackData::OnCompressFileComplete
,
203 base::Passed(&compressed_file
)));
207 void FeedbackData::OnGetTraceData(
209 scoped_refptr
<base::RefCountedString
> trace_data
) {
210 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
211 TracingManager
* manager
= TracingManager::Get();
213 manager
->DiscardTraceData(trace_id
);
215 scoped_ptr
<std::string
> data(new std::string
);
216 data
->swap(trace_data
->data());
218 attached_filename_
= kTraceFilename
;
219 attached_filedata_
= data
.Pass();
220 attached_file_compression_complete_
= true;
223 set_category_tag(kPerformanceCategoryTag
);
228 void FeedbackData::OnCompressLogsComplete(
229 scoped_ptr
<std::string
> compressed_logs
) {
230 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
232 compressed_logs_
= compressed_logs
.Pass();
233 syslogs_compression_complete_
= true;
238 void FeedbackData::OnCompressHistogramsComplete(
239 scoped_ptr
<std::string
> compressed_histograms
) {
240 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
242 compressed_histograms_
= compressed_histograms
.Pass();
243 histograms_compression_complete_
= true;
248 void FeedbackData::OnCompressFileComplete(
249 scoped_ptr
<std::string
> compressed_file
) {
250 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
252 if (compressed_file
.get()) {
253 attached_filedata_
= compressed_file
.Pass();
254 attached_filename_
.append(kZipExt
);
255 attached_file_compression_complete_
= true;
257 attached_filename_
.clear();
258 attached_filedata_
.reset(NULL
);
264 bool FeedbackData::IsDataComplete() {
265 return (!sys_info_
.get() || syslogs_compression_complete_
) &&
266 (!histograms_
.get() || histograms_compression_complete_
) &&
267 (!attached_filedata_
.get() || attached_file_compression_complete_
) &&
269 feedback_page_data_complete_
;
272 void FeedbackData::SendReport() {
273 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
274 if (IsDataComplete() && !report_sent_
) {
276 feedback_util::SendReport(this);