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_report.h"
6
7#include "base/files/file.h"
8#include "base/files/file_enumerator.h"
9#include "base/files/file_util.h"
10#include "base/files/important_file_writer.h"
11#include "base/guid.h"
12#include "base/sequenced_task_runner.h"
13#include "base/strings/string_number_conversions.h"
14#include "base/threading/sequenced_worker_pool.h"
15
16namespace {
17
18const base::FilePath::CharType kFeedbackReportFilenameWildcard[] =
19    FILE_PATH_LITERAL("Feedback Report.*");
20
21const char kFeedbackReportFilenamePrefix[] = "Feedback Report.";
22
23void WriteReportOnBlockingPool(const base::FilePath reports_path,
24                               const base::FilePath& file,
25                               const std::string& data) {
26  DCHECK(reports_path.IsParent(file));
27  if (!base::DirectoryExists(reports_path)) {
28    base::File::Error error;
29    if (!base::CreateDirectoryAndGetError(reports_path, &error))
30      return;
31  }
32  base::ImportantFileWriter::WriteFileAtomically(file, data);
33}
34
35}  // namespace
36
37namespace feedback {
38
39FeedbackReport::FeedbackReport(
40    const base::FilePath& path,
41    const base::Time& upload_at,
42    const std::string& data,
43    scoped_refptr<base::SequencedTaskRunner> task_runner)
44    : reports_path_(path),
45      upload_at_(upload_at),
46      data_(data),
47      reports_task_runner_(task_runner) {
48  if (reports_path_.empty())
49    return;
50  file_ = reports_path_.AppendASCII(
51      kFeedbackReportFilenamePrefix + base::GenerateGUID());
52
53  reports_task_runner_->PostTask(FROM_HERE, base::Bind(
54      &WriteReportOnBlockingPool, reports_path_, file_, data_));
55}
56
57FeedbackReport::~FeedbackReport() {}
58
59void FeedbackReport::DeleteReportOnDisk() {
60  reports_task_runner_->PostTask(FROM_HERE, base::Bind(
61      base::IgnoreResult(&base::DeleteFile), file_, false));
62}
63
64// static
65void FeedbackReport::LoadReportsAndQueue(
66    const base::FilePath& user_dir, QueueCallback callback) {
67  if (user_dir.empty())
68    return;
69
70  base::FileEnumerator enumerator(user_dir,
71                                  false,
72                                  base::FileEnumerator::FILES,
73                                  kFeedbackReportFilenameWildcard);
74  for (base::FilePath name = enumerator.Next();
75       !name.empty();
76       name = enumerator.Next()) {
77    std::string data;
78    if (ReadFileToString(name, &data))
79      callback.Run(data);
80    base::DeleteFile(name, false);
81  }
82}
83
84}  // namespace feedback
85