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/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 18 using content::BrowserThread; 19 20 namespace feedback { 21 namespace { 22 23 const char kTraceFilename[] = "tracing.zip\n"; 24 const char kPerformanceCategoryTag[] = "Performance"; 25 26 const base::FilePath::CharType kHistogramsFilename[] = 27 FILE_PATH_LITERAL("histograms.txt"); 28 29 const char kHistogramsAttachmentName[] = "histograms.zip"; 30 31 } // namespace 32 33 FeedbackData::FeedbackData() 34 : send_report_(base::Bind(&feedback_util::SendReport)), context_(NULL), 35 trace_id_(0), pending_op_count_(1), report_sent_(false) {} 36 37 FeedbackData::~FeedbackData() { 38 } 39 40 void FeedbackData::OnFeedbackPageDataComplete() { 41 pending_op_count_--; 42 SendReport(); 43 } 44 45 void 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 71 void 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 88 void 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 110 void 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 129 void FeedbackData::OnCompressComplete() { 130 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 131 --pending_op_count_; 132 SendReport(); 133 } 134 135 bool FeedbackData::IsDataComplete() { 136 return pending_op_count_ == 0; 137 } 138 139 void 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