// 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 "base/bind.h" #include "base/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/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\n"; 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( scoped_ptr sys_info) { DCHECK(BrowserThread::CurrentlyOn(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.get()) { ++pending_op_count_; AddLogs(sys_info.Pass()); BrowserThread::PostBlockingPoolTaskAndReply( FROM_HERE, base::Bind(&FeedbackCommon::CompressLogs, this), base::Bind(&FeedbackData::OnCompressComplete, this)); } } void FeedbackData::SetAndCompressHistograms( scoped_ptr histograms) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); if (!histograms.get()) return; ++pending_op_count_; BrowserThread::PostBlockingPoolTaskAndReply( FROM_HERE, base::Bind(&FeedbackCommon::CompressFile, this, base::FilePath(kHistogramsFilename), kHistogramsAttachmentName, base::Passed(&histograms)), base::Bind(&FeedbackData::OnCompressComplete, this)); } void FeedbackData::AttachAndCompressFileData( scoped_ptr attached_filedata) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); if (!attached_filedata.get() || attached_filedata->empty()) return; ++pending_op_count_; #if defined(OS_WIN) base::FilePath attached_file(base::UTF8ToWide(attached_filename_)); #else base::FilePath attached_file(attached_filename_); #endif BrowserThread::PostBlockingPoolTaskAndReply( FROM_HERE, base::Bind(&FeedbackCommon::CompressFile, this, attached_file, std::string(), base::Passed(&attached_filedata)), base::Bind(&FeedbackData::OnCompressComplete, this)); } void FeedbackData::OnGetTraceData( int trace_id, scoped_refptr trace_data) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); TracingManager* manager = TracingManager::Get(); if (manager) manager->DiscardTraceData(trace_id); scoped_ptr data(new std::string); data->swap(trace_data->data()); AddFile(kTraceFilename, data.Pass()); set_category_tag(kPerformanceCategoryTag); --pending_op_count_; trace_id_ = 0; SendReport(); } void FeedbackData::OnCompressComplete() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); --pending_op_count_; SendReport(); } bool FeedbackData::IsDataComplete() { return pending_op_count_ == 0; } void FeedbackData::SendReport() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); if (IsDataComplete() && !report_sent_) { report_sent_ = true; send_report_.Run(this); } } } // namespace feedback