feedback_uploader.h 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  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. #ifndef COMPONENTS_FEEDBACK_FEEDBACK_UPLOADER_H_
  5. #define COMPONENTS_FEEDBACK_FEEDBACK_UPLOADER_H_
  6. #include <list>
  7. #include <queue>
  8. #include <vector>
  9. #include "base/callback.h"
  10. #include "base/files/file_path.h"
  11. #include "base/memory/ref_counted.h"
  12. #include "base/memory/weak_ptr.h"
  13. #include "base/task/single_thread_task_runner.h"
  14. #include "base/time/time.h"
  15. #include "base/timer/timer.h"
  16. #include "components/keyed_service/core/keyed_service.h"
  17. #include "services/network/public/cpp/shared_url_loader_factory.h"
  18. #include "url/gurl.h"
  19. namespace network {
  20. struct ResourceRequest;
  21. class SimpleURLLoader;
  22. } // namespace network
  23. namespace feedback {
  24. class FeedbackReport;
  25. // FeedbackUploader is used to add a feedback report to the queue of reports
  26. // being uploaded. In case uploading a report fails, it is written to disk and
  27. // tried again when it's turn comes up next in the queue.
  28. class FeedbackUploader : public KeyedService,
  29. public base::SupportsWeakPtr<FeedbackUploader> {
  30. public:
  31. // Some embedders want to delay the creation of the SharedURLLoaderFactory
  32. // until it is required as the creation could be expensive. In that case,
  33. // they can pass a callback that will be used to initialise the instance
  34. // out of the object creation code path.
  35. using SharedURLLoaderFactoryGetter =
  36. base::OnceCallback<scoped_refptr<network::SharedURLLoaderFactory>()>;
  37. FeedbackUploader(
  38. bool is_off_the_record,
  39. const base::FilePath& state_path,
  40. SharedURLLoaderFactoryGetter shared_url_loader_factory_getter);
  41. FeedbackUploader(
  42. bool is_off_the_record,
  43. const base::FilePath& state_path,
  44. scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory);
  45. FeedbackUploader(const FeedbackUploader&) = delete;
  46. FeedbackUploader& operator=(const FeedbackUploader&) = delete;
  47. ~FeedbackUploader() override;
  48. static void SetMinimumRetryDelayForTesting(base::TimeDelta delay);
  49. // Queues a report for uploading.
  50. // |data|: The serialized userfeedback::ExtensionSubmit proto to send.
  51. // |has_email|: True iff the user included their email address in the report.
  52. // virtual for testing.
  53. virtual void QueueReport(std::unique_ptr<std::string> data, bool has_email);
  54. // Re-queues an existing report from disk for uploading.
  55. void RequeueReport(scoped_refptr<FeedbackReport> report);
  56. bool QueueEmpty() const { return reports_queue_.empty(); }
  57. const base::FilePath& feedback_reports_path() const {
  58. return feedback_reports_path_;
  59. }
  60. scoped_refptr<base::SingleThreadTaskRunner> task_runner() const {
  61. return task_runner_;
  62. }
  63. base::TimeDelta retry_delay() const { return retry_delay_; }
  64. protected:
  65. // Virtual to give implementers a chance to do work before the report is
  66. // disptached. Implementers can then call
  67. // FeedbackUploader::StartSendingReport() when ready so that the report is
  68. // dispatched.
  69. virtual void StartDispatchingReport();
  70. // Invoked when a feedback report upload succeeds. It will reset the
  71. // |retry_delay_| to its minimum value and schedules the next report upload if
  72. // any.
  73. void OnReportUploadSuccess();
  74. // Invoked when |report_being_dispatched_| fails to upload. If |should_retry|
  75. // is true, it will double the |retry_delay_| and reenqueue
  76. // |report_being_dispatched_| with the new delay. All subsequent retries will
  77. // keep increasing the delay until a successful upload is encountered.
  78. void OnReportUploadFailure(bool should_retry);
  79. const scoped_refptr<FeedbackReport>& report_being_dispatched() const {
  80. return report_being_dispatched_;
  81. }
  82. private:
  83. friend class FeedbackUploaderTest;
  84. // This is a std::list so that iterators remain valid during modifications.
  85. using UrlLoaderList = std::list<std::unique_ptr<network::SimpleURLLoader>>;
  86. struct ReportsUploadTimeComparator {
  87. bool operator()(const scoped_refptr<FeedbackReport>& a,
  88. const scoped_refptr<FeedbackReport>& b) const;
  89. };
  90. // Internal constructor. Exactly one of |url_loader_factory_getter| and
  91. // |url_loader_factory| can be non-null.
  92. FeedbackUploader(
  93. bool is_off_the_record,
  94. const base::FilePath& state_path,
  95. SharedURLLoaderFactoryGetter url_loader_factory_getter,
  96. scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
  97. // Called from DispatchReport() to give implementers a chance to add extra
  98. // headers to the upload request before it's sent.
  99. virtual void AppendExtraHeadersToUploadRequest(
  100. network::ResourceRequest* resource_request);
  101. // Uploads the |report_being_dispatched_| to be uploaded. It must
  102. // call either OnReportUploadSuccess() or OnReportUploadFailure() so that
  103. // dispatching reports can progress.
  104. void DispatchReport();
  105. void OnDispatchComplete(UrlLoaderList::iterator it,
  106. std::unique_ptr<std::string> response_body);
  107. // Update our timer for uploading the next report.
  108. void UpdateUploadTimer();
  109. // Callback used to initialise |url_loader_factory_| lazily.
  110. SharedURLLoaderFactoryGetter url_loader_factory_getter_;
  111. // URLLoaderFactory used for network requests. May be null initially if the
  112. // creation is delayed (see |url_loader_factory_getter_|).
  113. scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
  114. const base::FilePath feedback_reports_path_;
  115. // Timer to upload the next report at.
  116. base::OneShotTimer upload_timer_;
  117. // See comment of |FeedbackUploaderFactory::task_runner_|.
  118. scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
  119. scoped_refptr<FeedbackReport> report_being_dispatched_;
  120. const GURL feedback_post_url_;
  121. // Priority queue of reports prioritized by the time the report is supposed
  122. // to be uploaded at.
  123. std::priority_queue<scoped_refptr<FeedbackReport>,
  124. std::vector<scoped_refptr<FeedbackReport>>,
  125. ReportsUploadTimeComparator>
  126. reports_queue_;
  127. base::TimeDelta retry_delay_;
  128. // True when a report is currently being dispatched. Only a single report
  129. // at-a-time should be dispatched.
  130. bool is_dispatching_ = false;
  131. // Whether the feedback is associated with off-the-record context.
  132. const bool is_off_the_record_ = false;
  133. UrlLoaderList uploads_in_progress_;
  134. };
  135. } // namespace feedback
  136. #endif // COMPONENTS_FEEDBACK_FEEDBACK_UPLOADER_H_