// 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 #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/thread_pool.h" #include "base/values.h" #include "components/feedback/feedback_util.h" #include "components/feedback/proto/extension.pb.h" #include "components/feedback/tracing_manager.h" 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(base::WeakPtr uploader, TracingManager* tracing_manager) : uploader_(std::move(uploader)), tracing_manager_(tracing_manager) {} FeedbackData::~FeedbackData() = default; void FeedbackData::OnFeedbackPageDataComplete() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); pending_op_count_--; SendReport(); } void FeedbackData::CompressSystemInfo() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (trace_id_ != 0) { ++pending_op_count_; if (!tracing_manager_ || !tracing_manager_->GetTraceData( trace_id_, base::BindOnce(&FeedbackData::OnGetTraceData, this, trace_id_))) { pending_op_count_--; trace_id_ = 0; } } ++pending_op_count_; base::ThreadPool::PostTaskAndReply( FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT}, base::BindOnce(&FeedbackData::CompressLogs, this), base::BindOnce(&FeedbackData::OnCompressComplete, this)); } void FeedbackData::SetAndCompressHistograms(std::string histograms) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); ++pending_op_count_; base::ThreadPool::PostTaskAndReply( FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT}, base::BindOnce(&FeedbackData::CompressFile, this, base::FilePath(kHistogramsFilename), kHistogramsAttachmentName, std::move(histograms)), base::BindOnce(&FeedbackData::OnCompressComplete, this)); } void FeedbackData::AttachAndCompressFileData(std::string attached_filedata) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (attached_filedata.empty()) return; ++pending_op_count_; base::FilePath attached_file = base::FilePath::FromUTF8Unsafe(attached_filename_); base::ThreadPool::PostTaskAndReply( FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT}, base::BindOnce(&FeedbackData::CompressFile, this, attached_file, std::string(), std::move(attached_filedata)), base::BindOnce(&FeedbackData::OnCompressComplete, this)); } void FeedbackData::OnGetTraceData( int trace_id, scoped_refptr trace_data) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (tracing_manager_) tracing_manager_->DiscardTraceData(trace_id); AddFile(kTraceFilename, std::move(trace_data->data())); set_category_tag(kPerformanceCategoryTag); --pending_op_count_; trace_id_ = 0; SendReport(); } void FeedbackData::OnCompressComplete() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); --pending_op_count_; SendReport(); } bool FeedbackData::IsDataComplete() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return pending_op_count_ == 0; } void FeedbackData::SendReport() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (uploader_ && IsDataComplete() && !report_sent_) { report_sent_ = true; userfeedback::ExtensionSubmit feedback_data; PrepareReport(&feedback_data); auto post_body = std::make_unique(); feedback_data.SerializeToString(post_body.get()); uploader_->QueueReport(std::move(post_body), /*has_email=*/!user_email().empty()); } } } // namespace feedback