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 3// found in the LICENSE file. 4 5#include "components/feedback/feedback_data.h" 6 7#include "base/bind.h" 8#include "base/files/file_util.h" 9#include "base/json/json_string_value_serializer.h" 10#include "base/memory/ref_counted_memory.h" 11#include "base/strings/string_util.h" 12#include "base/strings/utf_string_conversions.h" 13#include "base/values.h" 14#include "components/feedback/feedback_util.h" 15#include "components/feedback/tracing_manager.h" 16#include "content/public/browser/browser_thread.h" 17 18using content::BrowserThread; 19 20namespace feedback { 21namespace { 22 23const char kTraceFilename[] = "tracing.zip\n"; 24const char kPerformanceCategoryTag[] = "Performance"; 25 26const base::FilePath::CharType kHistogramsFilename[] = 27 FILE_PATH_LITERAL("histograms.txt"); 28 29const char kHistogramsAttachmentName[] = "histograms.zip"; 30 31} // namespace 32 33FeedbackData::FeedbackData() 34 : send_report_(base::Bind(&feedback_util::SendReport)), context_(NULL), 35 trace_id_(0), pending_op_count_(1), report_sent_(false) {} 36 37FeedbackData::~FeedbackData() { 38} 39 40void FeedbackData::OnFeedbackPageDataComplete() { 41 pending_op_count_--; 42 SendReport(); 43} 44 45void FeedbackData::SetAndCompressSystemInfo( 46 scoped_ptr<FeedbackData::SystemLogsMap> sys_info) { 47 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 48 49 if (trace_id_ != 0) { 50 TracingManager* manager = TracingManager::Get(); 51 ++pending_op_count_; 52 if (!manager || 53 !manager->GetTraceData( 54 trace_id_, 55 base::Bind(&FeedbackData::OnGetTraceData, this, trace_id_))) { 56 pending_op_count_--; 57 trace_id_ = 0; 58 } 59 } 60 61 if (sys_info.get()) { 62 ++pending_op_count_; 63 AddLogs(sys_info.Pass()); 64 BrowserThread::PostBlockingPoolTaskAndReply( 65 FROM_HERE, 66 base::Bind(&FeedbackCommon::CompressLogs, this), 67 base::Bind(&FeedbackData::OnCompressComplete, this)); 68 } 69} 70 71void FeedbackData::SetAndCompressHistograms( 72 scoped_ptr<std::string> histograms) { 73 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 74 75 if (!histograms.get()) 76 return; 77 ++pending_op_count_; 78 BrowserThread::PostBlockingPoolTaskAndReply( 79 FROM_HERE, 80 base::Bind(&FeedbackCommon::CompressFile, 81 this, 82 base::FilePath(kHistogramsFilename), 83 kHistogramsAttachmentName, 84 base::Passed(&histograms)), 85 base::Bind(&FeedbackData::OnCompressComplete, this)); 86} 87 88void FeedbackData::AttachAndCompressFileData( 89 scoped_ptr<std::string> attached_filedata) { 90 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 91 92 if (!attached_filedata.get() || attached_filedata->empty()) 93 return; 94 ++pending_op_count_; 95#if defined(OS_WIN) 96 base::FilePath attached_file(base::UTF8ToWide(attached_filename_)); 97#else 98 base::FilePath attached_file(attached_filename_); 99#endif 100 BrowserThread::PostBlockingPoolTaskAndReply( 101 FROM_HERE, 102 base::Bind(&FeedbackCommon::CompressFile, 103 this, 104 attached_file, 105 std::string(), 106 base::Passed(&attached_filedata)), 107 base::Bind(&FeedbackData::OnCompressComplete, this)); 108} 109 110void FeedbackData::OnGetTraceData( 111 int trace_id, 112 scoped_refptr<base::RefCountedString> trace_data) { 113 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 114 TracingManager* manager = TracingManager::Get(); 115 if (manager) 116 manager->DiscardTraceData(trace_id); 117 118 scoped_ptr<std::string> data(new std::string); 119 data->swap(trace_data->data()); 120 121 AddFile(kTraceFilename, data.Pass()); 122 123 set_category_tag(kPerformanceCategoryTag); 124 --pending_op_count_; 125 trace_id_ = 0; 126 SendReport(); 127} 128 129void FeedbackData::OnCompressComplete() { 130 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 131 --pending_op_count_; 132 SendReport(); 133} 134 135bool FeedbackData::IsDataComplete() { 136 return pending_op_count_ == 0; 137} 138 139void FeedbackData::SendReport() { 140 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 141 if (IsDataComplete() && !report_sent_) { 142 report_sent_ = true; 143 send_report_.Run(this); 144 } 145} 146 147} // namespace feedback 148