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_uploader.h"
      6 
      7 #include "base/callback.h"
      8 #include "base/command_line.h"
      9 #include "base/files/file_path.h"
     10 #include "base/sequenced_task_runner.h"
     11 #include "base/task_runner_util.h"
     12 #include "base/threading/sequenced_worker_pool.h"
     13 #include "components/feedback/feedback_report.h"
     14 
     15 namespace feedback {
     16 namespace {
     17 
     18 const char kFeedbackPostUrl[] =
     19     "https://www.google.com/tools/feedback/chrome/__submit";
     20 
     21 const int64 kRetryDelayMinutes = 60;
     22 
     23 const base::FilePath::CharType kFeedbackReportPath[] =
     24     FILE_PATH_LITERAL("Feedback Reports");
     25 
     26 }  // namespace
     27 
     28 bool FeedbackUploader::ReportsUploadTimeComparator::operator()(
     29     const scoped_refptr<FeedbackReport>& a,
     30     const scoped_refptr<FeedbackReport>& b) const {
     31   return a->upload_at() > b->upload_at();
     32 }
     33 
     34 FeedbackUploader::FeedbackUploader(const base::FilePath& path,
     35                                    base::SequencedWorkerPool* pool)
     36     : report_path_(path.Append(kFeedbackReportPath)),
     37       retry_delay_(base::TimeDelta::FromMinutes(kRetryDelayMinutes)),
     38       url_(kFeedbackPostUrl),
     39       pool_(pool) {
     40   Init();
     41 }
     42 
     43 FeedbackUploader::FeedbackUploader(const base::FilePath& path,
     44                                    base::SequencedWorkerPool* pool,
     45                                    const std::string& url)
     46     : report_path_(path.Append(kFeedbackReportPath)),
     47       retry_delay_(base::TimeDelta::FromMinutes(kRetryDelayMinutes)),
     48       url_(url),
     49       pool_(pool) {
     50   Init();
     51 }
     52 
     53 FeedbackUploader::~FeedbackUploader() {}
     54 
     55 void FeedbackUploader::Init() {
     56   dispatch_callback_ = base::Bind(&FeedbackUploader::DispatchReport,
     57                                   AsWeakPtr());
     58 }
     59 
     60 void FeedbackUploader::QueueReport(const std::string& data) {
     61   QueueReportWithDelay(data, base::TimeDelta());
     62 }
     63 
     64 void FeedbackUploader::UpdateUploadTimer() {
     65   if (reports_queue_.empty())
     66     return;
     67 
     68   scoped_refptr<FeedbackReport> report = reports_queue_.top();
     69   base::Time now = base::Time::Now();
     70   if (report->upload_at() <= now) {
     71     reports_queue_.pop();
     72     dispatch_callback_.Run(report->data());
     73     report->DeleteReportOnDisk();
     74   } else {
     75     // Stop the old timer and start an updated one.
     76     if (upload_timer_.IsRunning())
     77       upload_timer_.Stop();
     78     upload_timer_.Start(
     79         FROM_HERE, report->upload_at() - now, this,
     80         &FeedbackUploader::UpdateUploadTimer);
     81   }
     82 }
     83 
     84 void FeedbackUploader::RetryReport(const std::string& data) {
     85   QueueReportWithDelay(data, retry_delay_);
     86 }
     87 
     88 void FeedbackUploader::QueueReportWithDelay(const std::string& data,
     89                                             base::TimeDelta delay) {
     90   // Uses a BLOCK_SHUTDOWN file task runner because we really don't want to
     91   // lose reports.
     92   scoped_refptr<base::SequencedTaskRunner> task_runner =
     93       pool_->GetSequencedTaskRunnerWithShutdownBehavior(
     94           pool_->GetSequenceToken(),
     95           base::SequencedWorkerPool::BLOCK_SHUTDOWN);
     96 
     97   reports_queue_.push(new FeedbackReport(report_path_,
     98                                          base::Time::Now() + delay,
     99                                          data,
    100                                          task_runner));
    101   UpdateUploadTimer();
    102 }
    103 
    104 void FeedbackUploader::setup_for_test(
    105     const ReportDataCallback& dispatch_callback,
    106     const base::TimeDelta& retry_delay) {
    107   dispatch_callback_ = dispatch_callback;
    108   retry_delay_ = retry_delay;
    109 }
    110 
    111 }  // namespace feedback
    112