json_request.h 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. // Copyright 2016 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_NTP_SNIPPETS_REMOTE_JSON_REQUEST_H_
  5. #define COMPONENTS_NTP_SNIPPETS_REMOTE_JSON_REQUEST_H_
  6. #include <memory>
  7. #include <string>
  8. #include <utility>
  9. #include "base/callback.h"
  10. #include "base/memory/raw_ptr.h"
  11. #include "base/memory/weak_ptr.h"
  12. #include "base/time/time.h"
  13. #include "components/language/core/browser/url_language_histogram.h"
  14. #include "components/ntp_snippets/remote/request_params.h"
  15. #include "components/ntp_snippets/status.h"
  16. #include "google_apis/gaia/core_account_id.h"
  17. #include "services/network/public/cpp/resource_request.h"
  18. #include "third_party/abseil-cpp/absl/types/optional.h"
  19. #include "url/gurl.h"
  20. namespace base {
  21. class Value;
  22. class Clock;
  23. } // namespace base
  24. namespace network {
  25. class SharedURLLoaderFactory;
  26. class SimpleURLLoader;
  27. } // namespace network
  28. namespace ntp_snippets {
  29. class UserClassifier;
  30. namespace internal {
  31. // Enumeration listing all possible outcomes for fetch attempts. Used for UMA
  32. // histograms, so do not change existing values. Insert new values at the end,
  33. // and update the histogram definition.
  34. enum class FetchResult {
  35. SUCCESS = 0,
  36. // DEPRECATED_EMPTY_HOSTS = 1,
  37. URL_REQUEST_STATUS_ERROR = 2,
  38. HTTP_ERROR = 3,
  39. JSON_PARSE_ERROR = 4,
  40. INVALID_SNIPPET_CONTENT_ERROR = 5,
  41. OAUTH_TOKEN_ERROR = 6,
  42. // DEPRECATED_INTERACTIVE_QUOTA_ERROR = 7,
  43. // DEPRECATED_NON_INTERACTIVE_QUOTA_ERROR = 8,
  44. MISSING_API_KEY = 9,
  45. HTTP_ERROR_UNAUTHORIZED = 10,
  46. RESULT_MAX = 11,
  47. };
  48. // A single request to query remote suggestions. On success, the suggestions are
  49. // returned in parsed JSON form (base::Value).
  50. class JsonRequest {
  51. public:
  52. // A client can expect error_details only, if there was any error during the
  53. // fetching or parsing. In successful cases, it will be an empty string.
  54. using CompletedCallback =
  55. base::OnceCallback<void(base::Value result,
  56. FetchResult result_code,
  57. const std::string& error_details)>;
  58. // Builds authenticated and non-authenticated JsonRequests.
  59. class Builder {
  60. public:
  61. Builder();
  62. Builder(Builder&&);
  63. ~Builder();
  64. Builder(const Builder&) = delete;
  65. Builder& operator=(const Builder&) = delete;
  66. // Builds a Request object that contains all data to fetch new snippets.
  67. std::unique_ptr<JsonRequest> Build() const;
  68. Builder& SetAuthentication(const std::string& auth_header);
  69. Builder& SetCreationTime(base::TimeTicks creation_time);
  70. // The language_histogram borrowed from the fetcher needs to stay alive
  71. // until the request body is built.
  72. Builder& SetLanguageHistogram(
  73. const language::UrlLanguageHistogram* language_histogram);
  74. Builder& SetParams(const RequestParams& params);
  75. Builder& SetParseJsonCallback(ParseJSONCallback callback);
  76. // The clock borrowed from the fetcher will be injected into the
  77. // request. It will be used at build time and after the fetch returned.
  78. // It has to be alive until the request is destroyed.
  79. Builder& SetClock(const base::Clock* clock);
  80. Builder& SetUrl(const GURL& url);
  81. Builder& SetUrlLoaderFactory(
  82. scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
  83. Builder& SetUserClassifier(const UserClassifier& user_classifier);
  84. Builder& SetOptionalImagesCapability(bool supports_optional_images);
  85. // These preview methods allow to inspect the Request without exposing it
  86. // publicly.
  87. // TODO(fhorschig): Remove these when moving the Builder to
  88. // snippets::internal and trigger the request to intercept the request.
  89. std::string PreviewRequestBodyForTesting() { return BuildBody(); }
  90. std::string PreviewRequestHeadersForTesting() {
  91. return BuildResourceRequest()->headers.ToString();
  92. }
  93. Builder& SetUserClassForTesting(const std::string& user_class) {
  94. user_class_ = user_class;
  95. return *this;
  96. }
  97. bool is_interactive_request() const { return params_.interactive_request; }
  98. private:
  99. std::unique_ptr<network::ResourceRequest> BuildResourceRequest() const;
  100. std::string BuildBody() const;
  101. std::unique_ptr<network::SimpleURLLoader> BuildURLLoader(
  102. const std::string& body) const;
  103. void PrepareLanguages(
  104. language::UrlLanguageHistogram::LanguageInfo* ui_language,
  105. language::UrlLanguageHistogram::LanguageInfo* other_top_language) const;
  106. // Only required, if the request needs to be sent.
  107. std::string auth_header_;
  108. raw_ptr<const base::Clock> clock_;
  109. RequestParams params_;
  110. ParseJSONCallback parse_json_callback_;
  111. GURL url_;
  112. scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
  113. // Optional properties.
  114. std::string user_class_;
  115. std::string display_capability_;
  116. raw_ptr<const language::UrlLanguageHistogram> language_histogram_;
  117. };
  118. JsonRequest(absl::optional<Category> exclusive_category,
  119. const base::Clock* clock,
  120. const ParseJSONCallback& callback);
  121. JsonRequest(JsonRequest&&);
  122. JsonRequest(const JsonRequest&) = delete;
  123. JsonRequest& operator=(const JsonRequest&) = delete;
  124. ~JsonRequest();
  125. void Start(CompletedCallback callback);
  126. static int Get5xxRetryCount(bool interactive_request);
  127. const absl::optional<Category>& exclusive_category() const {
  128. return exclusive_category_;
  129. }
  130. base::TimeDelta GetFetchDuration() const;
  131. std::string GetResponseString() const;
  132. private:
  133. void OnSimpleLoaderComplete(std::unique_ptr<std::string> response_body);
  134. void ParseJsonResponse();
  135. void OnJsonParsed(base::Value result);
  136. void OnJsonError(const std::string& error);
  137. // The loader for downloading the snippets. Only non-null if a load is
  138. // currently ongoing.
  139. std::unique_ptr<network::SimpleURLLoader> simple_url_loader_;
  140. // The loader factory for downloading the snippets.
  141. scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
  142. // If set, only return results for this category.
  143. absl::optional<Category> exclusive_category_;
  144. // Use the Clock from the Fetcher to measure the fetch time. It will be
  145. // used on creation and after the fetch returned. It has to be alive until the
  146. // request is destroyed.
  147. raw_ptr<const base::Clock> clock_;
  148. base::Time creation_time_;
  149. // This callback is called to parse a json string. It contains callbacks for
  150. // error and success cases.
  151. ParseJSONCallback parse_json_callback_;
  152. // The callback to notify when URLFetcher finished and results are available.
  153. CompletedCallback request_completed_callback_;
  154. // The last response string
  155. std::string last_response_string_;
  156. base::WeakPtrFactory<JsonRequest> weak_ptr_factory_{this};
  157. };
  158. } // namespace internal
  159. } // namespace ntp_snippets
  160. #endif // COMPONENTS_NTP_SNIPPETS_REMOTE_JSON_REQUEST_H_