File: feedback_uploader.h

package info (click to toggle)
chromium 138.0.7204.157-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,864 kB
  • sloc: cpp: 34,936,859; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,967; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (185 lines) | stat: -rw-r--r-- 6,710 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_FEEDBACK_FEEDBACK_UPLOADER_H_
#define COMPONENTS_FEEDBACK_FEEDBACK_UPLOADER_H_

#include <list>
#include <queue>
#include <vector>

#include "base/files/file_path.h"
#include "base/functional/callback.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/task/single_thread_task_runner.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "components/keyed_service/core/keyed_service.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "url/gurl.h"

namespace network {
struct ResourceRequest;
class SimpleURLLoader;
}  // namespace network

namespace feedback {

class FeedbackReport;

// FeedbackUploader is used to add a feedback report to the queue of reports
// being uploaded. In case uploading a report fails, it is written to disk and
// tried again when it's turn comes up next in the queue.
class FeedbackUploader : public KeyedService {
 public:
  // Some embedders want to delay the creation of the SharedURLLoaderFactory
  // until it is required as the creation could be expensive. In that case,
  // they can pass a callback that will be used to initialise the instance
  // out of the object creation code path.
  using SharedURLLoaderFactoryGetter =
      base::OnceCallback<scoped_refptr<network::SharedURLLoaderFactory>()>;

  FeedbackUploader(
      bool is_off_the_record,
      const base::FilePath& state_path,
      SharedURLLoaderFactoryGetter shared_url_loader_factory_getter);
  FeedbackUploader(
      bool is_off_the_record,
      const base::FilePath& state_path,
      scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory);

  FeedbackUploader(const FeedbackUploader&) = delete;
  FeedbackUploader& operator=(const FeedbackUploader&) = delete;

  ~FeedbackUploader() override;

  static void SetMinimumRetryDelayForTesting(base::TimeDelta delay);

  // Queues a report for uploading.
  // |data|: The serialized userfeedback::ExtensionSubmit proto to send.
  // |has_email|: True iff the user included their email address in the report.
  // |product_id|: The product ID for the report.
  // virtual for testing.
  virtual void QueueReport(std::unique_ptr<std::string> data,
                           bool has_email,
                           int product_id);

  // Re-queues an existing report from disk for uploading.
  void RequeueReport(scoped_refptr<FeedbackReport> report);

  bool QueueEmpty() const { return reports_queue_.empty(); }

  const base::FilePath& feedback_reports_path() const {
    return feedback_reports_path_;
  }

  scoped_refptr<base::SingleThreadTaskRunner> task_runner() const {
    return task_runner_;
  }

  base::TimeDelta retry_delay() const { return retry_delay_; }

  // Deriving classes must implement this and return the appropriate
  // WeakPtr.
  virtual base::WeakPtr<FeedbackUploader> AsWeakPtr() = 0;

 protected:
  // Virtual to give implementers a chance to do work before the report is
  // disptached. Implementers can then call
  // FeedbackUploader::StartSendingReport() when ready so that the report is
  // dispatched.
  virtual void StartDispatchingReport();

  // Invoked when a feedback report upload succeeds. It will reset the
  // |retry_delay_| to its minimum value and schedules the next report upload if
  // any.
  void OnReportUploadSuccess();

  // Invoked when |report_being_dispatched_| fails to upload. If |should_retry|
  // is true, it will double the |retry_delay_| and reenqueue
  // |report_being_dispatched_| with the new delay. All subsequent retries will
  // keep increasing the delay until a successful upload is encountered.
  void OnReportUploadFailure(bool should_retry);

  const scoped_refptr<FeedbackReport>& report_being_dispatched() const {
    return report_being_dispatched_;
  }

 private:
  friend class FeedbackUploaderTest;

  // This is a std::list so that iterators remain valid during modifications.
  using UrlLoaderList = std::list<std::unique_ptr<network::SimpleURLLoader>>;

  struct ReportsUploadTimeComparator {
    bool operator()(const scoped_refptr<FeedbackReport>& a,
                    const scoped_refptr<FeedbackReport>& b) const;
  };

  // Internal constructor. Exactly one of |url_loader_factory_getter| and
  // |url_loader_factory| can be non-null.
  FeedbackUploader(
      bool is_off_the_record,
      const base::FilePath& state_path,
      SharedURLLoaderFactoryGetter url_loader_factory_getter,
      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);

  // Called from DispatchReport() to give implementers a chance to add extra
  // headers to the upload request before it's sent.
  virtual void AppendExtraHeadersToUploadRequest(
      network::ResourceRequest* resource_request);

  // Uploads the |report_being_dispatched_| to be uploaded. It must
  // call either OnReportUploadSuccess() or OnReportUploadFailure() so that
  // dispatching reports can progress.
  void DispatchReport();

  void OnDispatchComplete(UrlLoaderList::iterator it,
                          std::unique_ptr<std::string> response_body);

  // Update our timer for uploading the next report.
  void UpdateUploadTimer();

  // Callback used to initialise |url_loader_factory_| lazily.
  SharedURLLoaderFactoryGetter url_loader_factory_getter_;

  // URLLoaderFactory used for network requests. May be null initially if the
  // creation is delayed (see |url_loader_factory_getter_|).
  scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;

  const base::FilePath feedback_reports_path_;

  // Timer to upload the next report at.
  base::OneShotTimer upload_timer_;

  // See comment of |FeedbackUploaderFactory::task_runner_|.
  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;

  scoped_refptr<FeedbackReport> report_being_dispatched_;

  const GURL feedback_post_url_;

  // Priority queue of reports prioritized by the time the report is supposed
  // to be uploaded at.
  std::priority_queue<scoped_refptr<FeedbackReport>,
                      std::vector<scoped_refptr<FeedbackReport>>,
                      ReportsUploadTimeComparator>
      reports_queue_;

  base::TimeDelta retry_delay_;

  // True when a report is currently being dispatched. Only a single report
  // at-a-time should be dispatched.
  bool is_dispatching_ = false;

  // Whether the feedback is associated with off-the-record context.
  const bool is_off_the_record_ = false;

  UrlLoaderList uploads_in_progress_;
};

}  // namespace feedback

#endif  // COMPONENTS_FEEDBACK_FEEDBACK_UPLOADER_H_