[email protected] | 1eab4e9 | 2014-05-09 02:17:19 | [diff] [blame] | 1 | // Copyright 2014 The Chromium Authors. All rights reserved. |
[email protected] | 4837225 | 2013-12-20 12:18:01 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
[email protected] | 1eab4e9 | 2014-05-09 02:17:19 | [diff] [blame] | 5 | #ifndef COMPONENTS_FEEDBACK_FEEDBACK_UPLOADER_H_ |
| 6 | #define COMPONENTS_FEEDBACK_FEEDBACK_UPLOADER_H_ |
[email protected] | 4837225 | 2013-12-20 12:18:01 | [diff] [blame] | 7 | |
Robbie McElrath | d956f86 | 2018-07-09 22:01:02 | [diff] [blame] | 8 | #include <list> |
[email protected] | 4837225 | 2013-12-20 12:18:01 | [diff] [blame] | 9 | #include <queue> |
Ahmed Fakhry | af8ab05 | 2017-07-21 21:39:07 | [diff] [blame] | 10 | #include <vector> |
[email protected] | 4837225 | 2013-12-20 12:18:01 | [diff] [blame] | 11 | |
Ahmed Fakhry | af8ab05 | 2017-07-21 21:39:07 | [diff] [blame] | 12 | #include "base/files/file_path.h" |
avi | bc5337b | 2015-12-25 23:16:33 | [diff] [blame] | 13 | #include "base/macros.h" |
Ahmed Fakhry | af8ab05 | 2017-07-21 21:39:07 | [diff] [blame] | 14 | #include "base/memory/ref_counted.h" |
[email protected] | 4837225 | 2013-12-20 12:18:01 | [diff] [blame] | 15 | #include "base/memory/weak_ptr.h" |
Ahmed Fakhry | af8ab05 | 2017-07-21 21:39:07 | [diff] [blame] | 16 | #include "base/single_thread_task_runner.h" |
[email protected] | 4837225 | 2013-12-20 12:18:01 | [diff] [blame] | 17 | #include "base/time/time.h" |
| 18 | #include "base/timer/timer.h" |
Ahmed Fakhry | 7ff0cdb | 2017-08-22 20:11:45 | [diff] [blame] | 19 | #include "components/keyed_service/core/keyed_service.h" |
Ahmed Fakhry | af8ab05 | 2017-07-21 21:39:07 | [diff] [blame] | 20 | #include "url/gurl.h" |
[email protected] | 4837225 | 2013-12-20 12:18:01 | [diff] [blame] | 21 | |
Ahmed Fakhry | 7ff0cdb | 2017-08-22 20:11:45 | [diff] [blame] | 22 | namespace content { |
| 23 | class BrowserContext; |
| 24 | } // namespace content |
| 25 | |
Robbie McElrath | d956f86 | 2018-07-09 22:01:02 | [diff] [blame] | 26 | namespace network { |
| 27 | struct ResourceRequest; |
| 28 | class SimpleURLLoader; |
| 29 | class SharedURLLoaderFactory; |
| 30 | } // namespace network |
Ahmed Fakhry | 7ff0cdb | 2017-08-22 20:11:45 | [diff] [blame] | 31 | |
[email protected] | 4837225 | 2013-12-20 12:18:01 | [diff] [blame] | 32 | namespace feedback { |
| 33 | |
[email protected] | 90cc2a9a | 2014-02-28 22:05:55 | [diff] [blame] | 34 | class FeedbackReport; |
[email protected] | 4837225 | 2013-12-20 12:18:01 | [diff] [blame] | 35 | |
| 36 | // FeedbackUploader is used to add a feedback report to the queue of reports |
| 37 | // being uploaded. In case uploading a report fails, it is written to disk and |
| 38 | // tried again when it's turn comes up next in the queue. |
Ahmed Fakhry | 7ff0cdb | 2017-08-22 20:11:45 | [diff] [blame] | 39 | class FeedbackUploader : public KeyedService, |
| 40 | public base::SupportsWeakPtr<FeedbackUploader> { |
[email protected] | 4837225 | 2013-12-20 12:18:01 | [diff] [blame] | 41 | public: |
Robbie McElrath | d956f86 | 2018-07-09 22:01:02 | [diff] [blame] | 42 | FeedbackUploader( |
| 43 | scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, |
| 44 | content::BrowserContext* context, |
| 45 | scoped_refptr<base::SingleThreadTaskRunner> task_runner); |
Ahmed Fakhry | 7ff0cdb | 2017-08-22 20:11:45 | [diff] [blame] | 46 | ~FeedbackUploader() override; |
[email protected] | 4837225 | 2013-12-20 12:18:01 | [diff] [blame] | 47 | |
Ahmed Fakhry | af8ab05 | 2017-07-21 21:39:07 | [diff] [blame] | 48 | static void SetMinimumRetryDelayForTesting(base::TimeDelta delay); |
[email protected] | 4837225 | 2013-12-20 12:18:01 | [diff] [blame] | 49 | |
Ahmed Fakhry | af8ab05 | 2017-07-21 21:39:07 | [diff] [blame] | 50 | // Queues a report for uploading. |
Ahmed Fakhry | daa7d423 | 2018-07-02 18:11:36 | [diff] [blame] | 51 | void QueueReport(std::unique_ptr<std::string> data); |
[email protected] | 77f7fe89 | 2014-03-18 00:00:06 | [diff] [blame] | 52 | |
[email protected] | 1eab4e9 | 2014-05-09 02:17:19 | [diff] [blame] | 53 | bool QueueEmpty() const { return reports_queue_.empty(); } |
| 54 | |
Ahmed Fakhry | 7ff0cdb | 2017-08-22 20:11:45 | [diff] [blame] | 55 | content::BrowserContext* context() { return context_; } |
| 56 | |
Ahmed Fakhry | af8ab05 | 2017-07-21 21:39:07 | [diff] [blame] | 57 | const base::FilePath& feedback_reports_path() const { |
| 58 | return feedback_reports_path_; |
| 59 | } |
| 60 | |
| 61 | scoped_refptr<base::SingleThreadTaskRunner> task_runner() const { |
| 62 | return task_runner_; |
| 63 | } |
| 64 | |
| 65 | base::TimeDelta retry_delay() const { return retry_delay_; } |
| 66 | |
[email protected] | 77f7fe89 | 2014-03-18 00:00:06 | [diff] [blame] | 67 | protected: |
Ahmed Fakhry | 7ff0cdb | 2017-08-22 20:11:45 | [diff] [blame] | 68 | // Virtual to give implementers a chance to do work before the report is |
| 69 | // disptached. Implementers can then call |
| 70 | // FeedbackUploader::StartSendingReport() when ready so that the report is |
| 71 | // dispatched. |
| 72 | virtual void StartDispatchingReport(); |
| 73 | |
Ahmed Fakhry | af8ab05 | 2017-07-21 21:39:07 | [diff] [blame] | 74 | // Invoked when a feedback report upload succeeds. It will reset the |
| 75 | // |retry_delay_| to its minimum value and schedules the next report upload if |
| 76 | // any. |
| 77 | void OnReportUploadSuccess(); |
| 78 | |
Ahmed Fakhry | 7ff0cdb | 2017-08-22 20:11:45 | [diff] [blame] | 79 | // Invoked when |report_being_dispatched_| fails to upload. If |should_retry| |
| 80 | // is true, it will double the |retry_delay_| and reenqueue |
| 81 | // |report_being_dispatched_| with the new delay. All subsequent retries will |
| 82 | // keep increasing the delay until a successful upload is encountered. |
| 83 | void OnReportUploadFailure(bool should_retry); |
| 84 | |
| 85 | const scoped_refptr<FeedbackReport>& report_being_dispatched() const { |
| 86 | return report_being_dispatched_; |
| 87 | } |
Ahmed Fakhry | af8ab05 | 2017-07-21 21:39:07 | [diff] [blame] | 88 | |
| 89 | private: |
[email protected] | 4837225 | 2013-12-20 12:18:01 | [diff] [blame] | 90 | friend class FeedbackUploaderTest; |
[email protected] | 1eab4e9 | 2014-05-09 02:17:19 | [diff] [blame] | 91 | |
Robbie McElrath | d956f86 | 2018-07-09 22:01:02 | [diff] [blame] | 92 | // This is a std::list so that iterators remain valid during modifications. |
| 93 | using UrlLoaderList = std::list<std::unique_ptr<network::SimpleURLLoader>>; |
| 94 | |
[email protected] | 4837225 | 2013-12-20 12:18:01 | [diff] [blame] | 95 | struct ReportsUploadTimeComparator { |
dcheng | 972bc39f | 2014-09-04 04:22:38 | [diff] [blame] | 96 | bool operator()(const scoped_refptr<FeedbackReport>& a, |
| 97 | const scoped_refptr<FeedbackReport>& b) const; |
[email protected] | 4837225 | 2013-12-20 12:18:01 | [diff] [blame] | 98 | }; |
| 99 | |
Ahmed Fakhry | 7ff0cdb | 2017-08-22 20:11:45 | [diff] [blame] | 100 | // Called from DispatchReport() to give implementers a chance to add extra |
| 101 | // headers to the upload request before it's sent. |
Robbie McElrath | d956f86 | 2018-07-09 22:01:02 | [diff] [blame] | 102 | virtual void AppendExtraHeadersToUploadRequest( |
| 103 | network::ResourceRequest* resource_request); |
Ahmed Fakhry | 7ff0cdb | 2017-08-22 20:11:45 | [diff] [blame] | 104 | |
| 105 | // Uploads the |report_being_dispatched_| to be uploaded. It must |
| 106 | // call either OnReportUploadSuccess() or OnReportUploadFailure() so that |
| 107 | // dispatching reports can progress. |
| 108 | void DispatchReport(); |
[email protected] | 90cc2a9a | 2014-02-28 22:05:55 | [diff] [blame] | 109 | |
Robbie McElrath | d956f86 | 2018-07-09 22:01:02 | [diff] [blame] | 110 | void OnDispatchComplete(UrlLoaderList::iterator it, |
| 111 | std::unique_ptr<std::string> response_body); |
| 112 | |
[email protected] | 4837225 | 2013-12-20 12:18:01 | [diff] [blame] | 113 | // Update our timer for uploading the next report. |
| 114 | void UpdateUploadTimer(); |
| 115 | |
Ahmed Fakhry | daa7d423 | 2018-07-02 18:11:36 | [diff] [blame] | 116 | void QueueReportWithDelay(std::unique_ptr<std::string> data, |
| 117 | base::TimeDelta delay); |
[email protected] | 77f7fe89 | 2014-03-18 00:00:06 | [diff] [blame] | 118 | |
Robbie McElrath | d956f86 | 2018-07-09 22:01:02 | [diff] [blame] | 119 | // URLLoaderFactory used for network requests. |
| 120 | scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_; |
| 121 | |
Ahmed Fakhry | 7ff0cdb | 2017-08-22 20:11:45 | [diff] [blame] | 122 | // Browser context this uploader was created for. |
| 123 | content::BrowserContext* context_; |
| 124 | |
Ahmed Fakhry | af8ab05 | 2017-07-21 21:39:07 | [diff] [blame] | 125 | const base::FilePath feedback_reports_path_; |
[email protected] | 4837225 | 2013-12-20 12:18:01 | [diff] [blame] | 126 | |
[email protected] | 4837225 | 2013-12-20 12:18:01 | [diff] [blame] | 127 | // Timer to upload the next report at. |
danakj | 8c3eb80 | 2015-09-24 07:53:00 | [diff] [blame] | 128 | base::OneShotTimer upload_timer_; |
Ahmed Fakhry | af8ab05 | 2017-07-21 21:39:07 | [diff] [blame] | 129 | |
| 130 | // See comment of |FeedbackUploaderFactory::task_runner_|. |
| 131 | scoped_refptr<base::SingleThreadTaskRunner> task_runner_; |
| 132 | |
Ahmed Fakhry | 7ff0cdb | 2017-08-22 20:11:45 | [diff] [blame] | 133 | scoped_refptr<FeedbackReport> report_being_dispatched_; |
| 134 | |
| 135 | const GURL feedback_post_url_; |
| 136 | |
[email protected] | 4837225 | 2013-12-20 12:18:01 | [diff] [blame] | 137 | // Priority queue of reports prioritized by the time the report is supposed |
| 138 | // to be uploaded at. |
[email protected] | 90cc2a9a | 2014-02-28 22:05:55 | [diff] [blame] | 139 | std::priority_queue<scoped_refptr<FeedbackReport>, |
Ahmed Fakhry | af8ab05 | 2017-07-21 21:39:07 | [diff] [blame] | 140 | std::vector<scoped_refptr<FeedbackReport>>, |
| 141 | ReportsUploadTimeComparator> |
| 142 | reports_queue_; |
[email protected] | 4837225 | 2013-12-20 12:18:01 | [diff] [blame] | 143 | |
[email protected] | 4837225 | 2013-12-20 12:18:01 | [diff] [blame] | 144 | base::TimeDelta retry_delay_; |
Ahmed Fakhry | 7ff0cdb | 2017-08-22 20:11:45 | [diff] [blame] | 145 | |
| 146 | // True when a report is currently being dispatched. Only a single report |
| 147 | // at-a-time should be dispatched. |
| 148 | bool is_dispatching_; |
[email protected] | 4837225 | 2013-12-20 12:18:01 | [diff] [blame] | 149 | |
Robbie McElrath | d956f86 | 2018-07-09 22:01:02 | [diff] [blame] | 150 | UrlLoaderList uploads_in_progress_; |
| 151 | |
[email protected] | 4837225 | 2013-12-20 12:18:01 | [diff] [blame] | 152 | DISALLOW_COPY_AND_ASSIGN(FeedbackUploader); |
| 153 | }; |
| 154 | |
| 155 | } // namespace feedback |
| 156 | |
[email protected] | 1eab4e9 | 2014-05-09 02:17:19 | [diff] [blame] | 157 | #endif // COMPONENTS_FEEDBACK_FEEDBACK_UPLOADER_H_ |