Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(73)

Side by Side Diff: components/feedback/feedback_data.cc

Issue 296173003: Refactor FeedbackData and add tests. Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: add feedback.gypi to OWNERS file Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « components/feedback/feedback_data.h ('k') | components/feedback/feedback_data_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/feedback/feedback_data.h" 5 #include "components/feedback/feedback_data.h"
6 6
7 #include "base/bind.h"
7 #include "base/file_util.h" 8 #include "base/file_util.h"
8 #include "base/json/json_string_value_serializer.h" 9 #include "base/json/json_string_value_serializer.h"
9 #include "base/memory/ref_counted_memory.h" 10 #include "base/memory/ref_counted_memory.h"
10 #include "base/strings/string_util.h" 11 #include "base/strings/string_util.h"
11 #include "base/strings/utf_string_conversions.h" 12 #include "base/strings/utf_string_conversions.h"
12 #include "base/values.h" 13 #include "base/values.h"
13 #include "components/feedback/feedback_util.h" 14 #include "components/feedback/feedback_util.h"
14 #include "components/feedback/tracing_manager.h" 15 #include "components/feedback/tracing_manager.h"
15 #include "content/public/browser/browser_thread.h" 16 #include "content/public/browser/browser_thread.h"
16 17
17 using content::BrowserThread; 18 using content::BrowserThread;
18 19
19 namespace feedback { 20 namespace feedback {
20 namespace { 21 namespace {
21 22
22 const char kMultilineIndicatorString[] = "<multiline>\n";
23 const char kMultilineStartString[] = "---------- START ----------\n";
24 const char kMultilineEndString[] = "---------- END ----------\n\n";
25
26 const size_t kFeedbackMaxLength = 4 * 1024;
27 const size_t kFeedbackMaxLineCount = 40;
28
29 const char kTraceFilename[] = "tracing.zip\n"; 23 const char kTraceFilename[] = "tracing.zip\n";
30 const char kPerformanceCategoryTag[] = "Performance"; 24 const char kPerformanceCategoryTag[] = "Performance";
31 25
32 const char kZipExt[] = ".zip";
33
34 const base::FilePath::CharType kLogsFilename[] =
35 FILE_PATH_LITERAL("system_logs.txt");
36 const base::FilePath::CharType kHistogramsFilename[] = 26 const base::FilePath::CharType kHistogramsFilename[] =
37 FILE_PATH_LITERAL("histograms.txt"); 27 FILE_PATH_LITERAL("histograms.txt");
38 28
39 // Converts the system logs into a string that we can compress and send 29 const char kHistogramsAttachmentName[] = "histograms.zip";
40 // with the report. This method only converts those logs that we want in
41 // the compressed zip file sent with the report, hence it ignores any logs
42 // below the size threshold of what we want compressed.
43 std::string LogsToString(const FeedbackData::SystemLogsMap& sys_info) {
44 std::string syslogs_string;
45 for (FeedbackData::SystemLogsMap::const_iterator it = sys_info.begin();
46 it != sys_info.end(); ++it) {
47 std::string key = it->first;
48 std::string value = it->second;
49
50 if (FeedbackData::BelowCompressionThreshold(value))
51 continue;
52
53 base::TrimString(key, "\n ", &key);
54 base::TrimString(value, "\n ", &value);
55
56 if (value.find("\n") != std::string::npos) {
57 syslogs_string.append(
58 key + "=" + kMultilineIndicatorString +
59 kMultilineStartString +
60 value + "\n" +
61 kMultilineEndString);
62 } else {
63 syslogs_string.append(key + "=" + value + "\n");
64 }
65 }
66 return syslogs_string;
67 }
68
69 void ZipFile(const base::FilePath& filename,
70 const std::string& data, std::string* compressed_data) {
71 if (!feedback_util::ZipString(filename, data, compressed_data))
72 compressed_data->clear();
73 }
74
75 void ZipLogs(const FeedbackData::SystemLogsMap& sys_info,
76 std::string* compressed_logs) {
77 DCHECK(compressed_logs);
78 std::string logs_string = LogsToString(sys_info);
79 if (logs_string.empty() ||
80 !feedback_util::ZipString(
81 base::FilePath(kLogsFilename), logs_string, compressed_logs)) {
82 compressed_logs->clear();
83 }
84 }
85
86 void ZipHistograms(const std::string& histograms,
87 std::string* compressed_histograms) {
88 DCHECK(compressed_histograms);
89 if (histograms.empty() ||
90 !feedback_util::ZipString(
91 base::FilePath(kHistogramsFilename),
92 histograms,
93 compressed_histograms)) {
94 compressed_histograms->clear();
95 }
96 }
97 30
98 } // namespace 31 } // namespace
99 32
100 // static 33 FeedbackData::FeedbackData()
101 bool FeedbackData::BelowCompressionThreshold(const std::string& content) { 34 : send_report_(base::Bind(&feedback_util::SendReport)), context_(NULL),
102 if (content.length() > kFeedbackMaxLength) 35 trace_id_(0), pending_op_count_(1), report_sent_(false) {}
103 return false;
104 const size_t line_count = std::count(content.begin(), content.end(), '\n');
105 if (line_count > kFeedbackMaxLineCount)
106 return false;
107 return true;
108 }
109
110 FeedbackData::FeedbackData() : context_(NULL),
111 trace_id_(0),
112 feedback_page_data_complete_(false),
113 syslogs_compression_complete_(false),
114 histograms_compression_complete_(false),
115 attached_file_compression_complete_(false),
116 report_sent_(false) {
117 }
118 36
119 FeedbackData::~FeedbackData() { 37 FeedbackData::~FeedbackData() {
120 } 38 }
121 39
122 void FeedbackData::OnFeedbackPageDataComplete() { 40 void FeedbackData::OnFeedbackPageDataComplete() {
123 feedback_page_data_complete_ = true; 41 pending_op_count_--;
124 SendReport(); 42 SendReport();
125 } 43 }
126 44
127 void FeedbackData::SetAndCompressSystemInfo( 45 void FeedbackData::SetAndCompressSystemInfo(
128 scoped_ptr<FeedbackData::SystemLogsMap> sys_info) { 46 scoped_ptr<FeedbackData::SystemLogsMap> sys_info) {
129 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 47 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
130 48
131 if (trace_id_ != 0) { 49 if (trace_id_ != 0) {
132 TracingManager* manager = TracingManager::Get(); 50 TracingManager* manager = TracingManager::Get();
51 ++pending_op_count_;
133 if (!manager || 52 if (!manager ||
134 !manager->GetTraceData( 53 !manager->GetTraceData(
135 trace_id_, 54 trace_id_,
136 base::Bind(&FeedbackData::OnGetTraceData, this, trace_id_))) { 55 base::Bind(&FeedbackData::OnGetTraceData, this, trace_id_))) {
56 pending_op_count_--;
137 trace_id_ = 0; 57 trace_id_ = 0;
138 } 58 }
139 } 59 }
140 60
141 sys_info_ = sys_info.Pass(); 61 AddLogs(sys_info.Pass());
142 if (sys_info_.get()) { 62 if (sys_info.get()) {
143 std::string* compressed_logs_ptr = new std::string; 63 ++pending_op_count_;
144 scoped_ptr<std::string> compressed_logs(compressed_logs_ptr);
145 BrowserThread::PostBlockingPoolTaskAndReply( 64 BrowserThread::PostBlockingPoolTaskAndReply(
146 FROM_HERE, 65 FROM_HERE,
147 base::Bind(&ZipLogs, 66 base::Bind(&FeedbackCommon::CompressLogs, this),
148 *sys_info_, 67 base::Bind(&FeedbackData::OnCompressComplete, this));
149 compressed_logs_ptr),
150 base::Bind(&FeedbackData::OnCompressLogsComplete,
151 this,
152 base::Passed(&compressed_logs)));
153 } 68 }
154 } 69 }
155 70
156 void FeedbackData::SetAndCompressHistograms( 71 void FeedbackData::SetAndCompressHistograms(
157 scoped_ptr<std::string> histograms) { 72 scoped_ptr<std::string> histograms) {
158 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 73 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
159 74
160 histograms_ = histograms.Pass(); 75 if (!histograms.get())
161 if (histograms_.get()) { 76 return;
162 std::string* compressed_histograms_ptr = new std::string; 77 ++pending_op_count_;
163 scoped_ptr<std::string> compressed_histograms(compressed_histograms_ptr); 78 BrowserThread::PostBlockingPoolTaskAndReply(
164 BrowserThread::PostBlockingPoolTaskAndReply( 79 FROM_HERE,
165 FROM_HERE, 80 base::Bind(&FeedbackCommon::CompressFile,
166 base::Bind(&ZipHistograms, 81 this,
167 *histograms_, 82 base::FilePath(kHistogramsFilename),
168 compressed_histograms_ptr), 83 kHistogramsAttachmentName,
169 base::Bind(&FeedbackData::OnCompressHistogramsComplete, 84 base::Passed(&histograms)),
170 this, 85 base::Bind(&FeedbackData::OnCompressComplete, this));
171 base::Passed(&compressed_histograms)));
172 }
173 } 86 }
174 87
175 void FeedbackData::AttachAndCompressFileData( 88 void FeedbackData::AttachAndCompressFileData(
176 scoped_ptr<std::string> attached_filedata) { 89 scoped_ptr<std::string> attached_filedata) {
177 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 90 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
178 91
179 attached_filedata_ = attached_filedata.Pass(); 92 if (!attached_filedata.get() || attached_filedata->empty())
180 93 return;
181 if (!attached_filename_.empty() && attached_filedata_.get()) { 94 ++pending_op_count_;
182 std::string* compressed_file_ptr = new std::string;
183 scoped_ptr<std::string> compressed_file(compressed_file_ptr);
184 #if defined(OS_WIN) 95 #if defined(OS_WIN)
185 base::FilePath attached_file(base::UTF8ToWide(attached_filename_)); 96 base::FilePath attached_file(base::UTF8ToWide(attached_filename_));
186 #else 97 #else
187 base::FilePath attached_file(attached_filename_); 98 base::FilePath attached_file(attached_filename_);
188 #endif 99 #endif
189 BrowserThread::PostBlockingPoolTaskAndReply( 100 BrowserThread::PostBlockingPoolTaskAndReply(
190 FROM_HERE, 101 FROM_HERE,
191 base::Bind(&ZipFile, 102 base::Bind(&FeedbackCommon::CompressFile,
192 attached_file, 103 this,
193 *(attached_filedata_.get()), 104 attached_file,
194 compressed_file_ptr), 105 std::string(),
195 base::Bind(&FeedbackData::OnCompressFileComplete, 106 base::Passed(&attached_filedata)),
196 this, 107 base::Bind(&FeedbackData::OnCompressComplete, this));
197 base::Passed(&compressed_file)));
198 }
199 } 108 }
200 109
201 void FeedbackData::OnGetTraceData( 110 void FeedbackData::OnGetTraceData(
202 int trace_id, 111 int trace_id,
203 scoped_refptr<base::RefCountedString> trace_data) { 112 scoped_refptr<base::RefCountedString> trace_data) {
204 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 113 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
205 TracingManager* manager = TracingManager::Get(); 114 TracingManager* manager = TracingManager::Get();
206 if (manager) 115 if (manager)
207 manager->DiscardTraceData(trace_id); 116 manager->DiscardTraceData(trace_id);
208 117
209 scoped_ptr<std::string> data(new std::string); 118 scoped_ptr<std::string> data(new std::string);
210 data->swap(trace_data->data()); 119 data->swap(trace_data->data());
211 120
212 attached_filename_ = kTraceFilename; 121 AddFile(kTraceFilename, data.Pass());
213 attached_filedata_ = data.Pass();
214 attached_file_compression_complete_ = true;
215 trace_id_ = 0;
216 122
217 set_category_tag(kPerformanceCategoryTag); 123 set_category_tag(kPerformanceCategoryTag);
218 124 --pending_op_count_;
125 trace_id_ = 0;
219 SendReport(); 126 SendReport();
220 } 127 }
221 128
222 void FeedbackData::OnCompressLogsComplete( 129 void FeedbackData::OnCompressComplete() {
223 scoped_ptr<std::string> compressed_logs) {
224 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 130 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
225 131 --pending_op_count_;
226 compressed_logs_ = compressed_logs.Pass();
227 syslogs_compression_complete_ = true;
228
229 SendReport();
230 }
231
232 void FeedbackData::OnCompressHistogramsComplete(
233 scoped_ptr<std::string> compressed_histograms) {
234 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
235
236 compressed_histograms_ = compressed_histograms.Pass();
237 histograms_compression_complete_ = true;
238
239 SendReport();
240 }
241
242 void FeedbackData::OnCompressFileComplete(
243 scoped_ptr<std::string> compressed_file) {
244 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
245
246 if (compressed_file.get()) {
247 attached_filedata_ = compressed_file.Pass();
248 attached_filename_.append(kZipExt);
249 attached_file_compression_complete_ = true;
250 } else {
251 attached_filename_.clear();
252 attached_filedata_.reset(NULL);
253 }
254
255 SendReport(); 132 SendReport();
256 } 133 }
257 134
258 bool FeedbackData::IsDataComplete() { 135 bool FeedbackData::IsDataComplete() {
259 return (!sys_info_.get() || syslogs_compression_complete_) && 136 return pending_op_count_ == 0;
260 (!histograms_.get() || histograms_compression_complete_) &&
261 (!attached_filedata_.get() || attached_file_compression_complete_) &&
262 !trace_id_ &&
263 feedback_page_data_complete_;
264 } 137 }
265 138
266 void FeedbackData::SendReport() { 139 void FeedbackData::SendReport() {
267 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 140 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
268 if (IsDataComplete() && !report_sent_) { 141 if (IsDataComplete() && !report_sent_) {
269 report_sent_ = true; 142 report_sent_ = true;
270 feedback_util::SendReport(this); 143 send_report_.Run(this);
271 } 144 }
272 } 145 }
273 146
274 } // namespace feedback 147 } // namespace feedback
OLDNEW
« no previous file with comments | « components/feedback/feedback_data.h ('k') | components/feedback/feedback_data_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698