Home | History | Annotate | Download | only in feedback
      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 
     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