Home | History | Annotate | Download | only in feedback
      1 // Copyright (c) 2012 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 "chrome/browser/feedback/feedback_data.h"
      6 
      7 #include "base/file_util.h"
      8 #include "base/json/json_string_value_serializer.h"
      9 #include "base/strings/string_util.h"
     10 #include "base/values.h"
     11 #include "chrome/browser/browser_process.h"
     12 #include "chrome/browser/chromeos/settings/cros_settings.h"
     13 #include "chrome/browser/feedback/feedback_util.h"
     14 #include "chrome/browser/feedback/tracing_manager.h"
     15 #include "chrome/browser/profiles/profile_manager.h"
     16 #include "content/public/browser/browser_thread.h"
     17 
     18 #if defined(USE_ASH)
     19 #include "ash/shell.h"
     20 #include "ash/shell_delegate.h"
     21 #endif
     22 
     23 using content::BrowserThread;
     24 
     25 #if defined(OS_CHROMEOS)
     26 namespace {
     27 
     28 const char kMultilineIndicatorString[] = "<multiline>\n";
     29 const char kMultilineStartString[] = "---------- START ----------\n";
     30 const char kMultilineEndString[] = "---------- END ----------\n\n";
     31 
     32 const char kTraceFilename[] = "tracing.log\n";
     33 
     34 std::string LogsToString(chromeos::SystemLogsResponse* sys_info) {
     35   std::string syslogs_string;
     36   for (chromeos::SystemLogsResponse::const_iterator it = sys_info->begin();
     37       it != sys_info->end(); ++it) {
     38     std::string key = it->first;
     39     std::string value = it->second;
     40 
     41     TrimString(key, "\n ", &key);
     42     TrimString(value, "\n ", &value);
     43 
     44     if (value.find("\n") != std::string::npos) {
     45       syslogs_string.append(
     46           key + "=" + kMultilineIndicatorString +
     47           kMultilineStartString +
     48           value + "\n" +
     49           kMultilineEndString);
     50     } else {
     51       syslogs_string.append(key + "=" + value + "\n");
     52     }
     53   }
     54   return syslogs_string;
     55 }
     56 
     57 void ZipLogs(chromeos::SystemLogsResponse* sys_info,
     58              std::string* compressed_logs) {
     59   DCHECK(compressed_logs);
     60   std::string logs_string = LogsToString(sys_info);
     61   if (!FeedbackUtil::ZipString(logs_string, compressed_logs)) {
     62     compressed_logs->clear();
     63   }
     64 }
     65 
     66 }  // namespace
     67 #endif // OS_CHROMEOS
     68 
     69 FeedbackData::FeedbackData() : profile_(NULL),
     70                                feedback_page_data_complete_(false) {
     71 #if defined(OS_CHROMEOS)
     72   sys_info_.reset(NULL);
     73   trace_id_ = 0;
     74   attached_filedata_.reset(NULL);
     75   send_sys_info_ = true;
     76   read_attached_file_complete_ = false;
     77   syslogs_collection_complete_ = false;
     78 #endif
     79 }
     80 
     81 FeedbackData::~FeedbackData() {
     82 }
     83 
     84 bool FeedbackData::DataCollectionComplete() {
     85 #if defined(OS_CHROMEOS)
     86   return (syslogs_collection_complete_ || !send_sys_info_) &&
     87       read_attached_file_complete_ &&
     88       feedback_page_data_complete_;
     89 #else
     90   return feedback_page_data_complete_;
     91 #endif
     92 }
     93 void FeedbackData::SendReport() {
     94   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     95   if (DataCollectionComplete())
     96     FeedbackUtil::SendReport(this);
     97 }
     98 
     99 void FeedbackData::FeedbackPageDataComplete() {
    100 #if defined(OS_CHROMEOS)
    101   if (trace_id_ != 0) {
    102     TracingManager* manager = TracingManager::Get();
    103     // When there is a trace id attached to this report, fetch it and attach it
    104     // as a file.  In this case, return early and retry this function later.
    105     if (manager &&
    106         manager->GetTraceData(
    107             trace_id_,
    108             base::Bind(&FeedbackData::OnGetTraceData, this))) {
    109       return;
    110     } else {
    111       trace_id_ = 0;
    112     }
    113   }
    114   if (attached_filename_.size() &&
    115       base::FilePath::IsSeparator(attached_filename_[0]) &&
    116       !attached_filedata_.get()) {
    117     // Read the attached file and then send this report. The allocated string
    118     // will be freed in FeedbackUtil::SendReport.
    119     attached_filedata_.reset(new std::string);
    120 
    121     base::FilePath root =
    122         ash::Shell::GetInstance()->delegate()->
    123             GetCurrentBrowserContext()->GetPath();
    124     base::FilePath filepath = root.Append(attached_filename_.substr(1));
    125     attached_filename_ = filepath.BaseName().value();
    126 
    127     // Read the file into file_data, then call send report again with the
    128     // stripped filename and file data (which will skip this code path).
    129     content::BrowserThread::PostTaskAndReply(
    130         content::BrowserThread::FILE, FROM_HERE,
    131         base::Bind(&FeedbackData::ReadAttachedFile, this, filepath),
    132         base::Bind(&FeedbackData::ReadFileComplete, this));
    133   } else {
    134     read_attached_file_complete_ = true;
    135   }
    136 #endif
    137   feedback_page_data_complete_ = true;
    138   SendReport();
    139 }
    140 
    141 #if defined(OS_CHROMEOS)
    142 void FeedbackData::set_sys_info(
    143     scoped_ptr<chromeos::SystemLogsResponse> sys_info) {
    144   if (sys_info.get())
    145     CompressSyslogs(sys_info.Pass());
    146 }
    147 
    148 void FeedbackData::CompressSyslogs(
    149     scoped_ptr<chromeos::SystemLogsResponse> sys_info) {
    150   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    151 
    152   // We get the pointer first since base::Passed will nullify the scoper, hence
    153   // it's not safe to use <scoper>.get() as a parameter to PostTaskAndReply.
    154   chromeos::SystemLogsResponse* sys_info_ptr = sys_info.get();
    155   std::string* compressed_logs_ptr = new std::string;
    156   scoped_ptr<std::string> compressed_logs(compressed_logs_ptr);
    157   BrowserThread::PostBlockingPoolTaskAndReply(
    158       FROM_HERE,
    159       base::Bind(&ZipLogs,
    160                  sys_info_ptr,
    161                  compressed_logs_ptr),
    162       base::Bind(&FeedbackData::SyslogsComplete,
    163                  this,
    164                  base::Passed(&sys_info),
    165                  base::Passed(&compressed_logs)));
    166 }
    167 
    168 void FeedbackData::SyslogsComplete(
    169     scoped_ptr<chromeos::SystemLogsResponse> sys_info,
    170     scoped_ptr<std::string> compressed_logs) {
    171   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    172 
    173   if (send_sys_info_) {
    174     sys_info_ = sys_info.Pass();
    175     compressed_logs_ = compressed_logs.Pass();
    176     syslogs_collection_complete_ = true;
    177     SendReport();
    178   }
    179 }
    180 
    181 void FeedbackData::ReadFileComplete() {
    182   read_attached_file_complete_ = true;
    183   SendReport();
    184 }
    185 
    186 void FeedbackData::StartSyslogsCollection() {
    187   chromeos::ScrubbedSystemLogsFetcher* fetcher =
    188       new chromeos::ScrubbedSystemLogsFetcher();
    189   fetcher->Fetch(base::Bind(&FeedbackData::CompressSyslogs, this));
    190 }
    191 
    192 // private
    193 void FeedbackData::ReadAttachedFile(const base::FilePath& from) {
    194   if (!file_util::ReadFileToString(from, attached_filedata_.get())) {
    195     if (attached_filedata_.get())
    196       attached_filedata_->clear();
    197   }
    198 }
    199 
    200 void FeedbackData::OnGetTraceData(
    201     scoped_refptr<base::RefCountedString> trace_data) {
    202   scoped_ptr<std::string> data(new std::string(trace_data->data()));
    203 
    204   set_attached_filename(kTraceFilename);
    205   set_attached_filedata(data.Pass());
    206   trace_id_ = 0;
    207   FeedbackPageDataComplete();
    208 }
    209 
    210 #endif
    211