| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "components/feedback/feedback_data.h" |
| |
| #include <utility> |
| |
| #include "base/bind.h" |
| #include "base/files/file_util.h" |
| #include "base/json/json_string_value_serializer.h" |
| #include "base/memory/ref_counted_memory.h" |
| #include "base/strings/string_util.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/task_scheduler/post_task.h" |
| #include "base/values.h" |
| #include "components/feedback/feedback_util.h" |
| #include "components/feedback/tracing_manager.h" |
| #include "content/public/browser/browser_thread.h" |
| |
| using content::BrowserThread; |
| |
| namespace feedback { |
| namespace { |
| |
| const char kTraceFilename[] = "tracing.zip"; |
| const char kPerformanceCategoryTag[] = "Performance"; |
| |
| const base::FilePath::CharType kHistogramsFilename[] = |
| FILE_PATH_LITERAL("histograms.txt"); |
| |
| const char kHistogramsAttachmentName[] = "histograms.zip"; |
| |
| } // namespace |
| |
| FeedbackData::FeedbackData() |
| : send_report_(base::Bind(&feedback_util::SendReport)), context_(NULL), |
| trace_id_(0), pending_op_count_(1), report_sent_(false) {} |
| |
| FeedbackData::~FeedbackData() { |
| } |
| |
| void FeedbackData::OnFeedbackPageDataComplete() { |
| pending_op_count_--; |
| SendReport(); |
| } |
| |
| void FeedbackData::SetAndCompressSystemInfo( |
| std::unique_ptr<FeedbackData::SystemLogsMap> sys_info) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| |
| if (trace_id_ != 0) { |
| TracingManager* manager = TracingManager::Get(); |
| ++pending_op_count_; |
| if (!manager || |
| !manager->GetTraceData( |
| trace_id_, |
| base::Bind(&FeedbackData::OnGetTraceData, this, trace_id_))) { |
| pending_op_count_--; |
| trace_id_ = 0; |
| } |
| } |
| |
| if (sys_info) { |
| ++pending_op_count_; |
| AddLogs(std::move(sys_info)); |
| base::PostTaskWithTraitsAndReply( |
| FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND}, |
| base::Bind(&FeedbackData::CompressLogs, this), |
| base::Bind(&FeedbackData::OnCompressComplete, this)); |
| } |
| } |
| |
| void FeedbackData::SetAndCompressHistograms( |
| std::unique_ptr<std::string> histograms) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| |
| if (!histograms) |
| return; |
| ++pending_op_count_; |
| base::PostTaskWithTraitsAndReply( |
| FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND}, |
| base::Bind(&FeedbackData::CompressFile, this, |
| base::FilePath(kHistogramsFilename), kHistogramsAttachmentName, |
| base::Passed(&histograms)), |
| base::Bind(&FeedbackData::OnCompressComplete, this)); |
| } |
| |
| void FeedbackData::AttachAndCompressFileData( |
| std::unique_ptr<std::string> attached_filedata) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| |
| if (!attached_filedata || attached_filedata->empty()) |
| return; |
| ++pending_op_count_; |
| base::FilePath attached_file = |
| base::FilePath::FromUTF8Unsafe(attached_filename_); |
| base::PostTaskWithTraitsAndReply( |
| FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND}, |
| base::Bind(&FeedbackData::CompressFile, this, attached_file, |
| std::string(), base::Passed(&attached_filedata)), |
| base::Bind(&FeedbackData::OnCompressComplete, this)); |
| } |
| |
| void FeedbackData::OnGetTraceData( |
| int trace_id, |
| scoped_refptr<base::RefCountedString> trace_data) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| TracingManager* manager = TracingManager::Get(); |
| if (manager) |
| manager->DiscardTraceData(trace_id); |
| |
| std::unique_ptr<std::string> data(new std::string); |
| data->swap(trace_data->data()); |
| |
| AddFile(kTraceFilename, std::move(data)); |
| |
| set_category_tag(kPerformanceCategoryTag); |
| --pending_op_count_; |
| trace_id_ = 0; |
| SendReport(); |
| } |
| |
| void FeedbackData::OnCompressComplete() { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| --pending_op_count_; |
| SendReport(); |
| } |
| |
| bool FeedbackData::IsDataComplete() { |
| return pending_op_count_ == 0; |
| } |
| |
| void FeedbackData::SendReport() { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| if (IsDataComplete() && !report_sent_) { |
| report_sent_ = true; |
| send_report_.Run(this); |
| } |
| } |
| |
| } // namespace feedback |