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 186 187 188 189 190 191 192 193 194
|
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_NTP_SNIPPETS_REMOTE_JSON_REQUEST_H_
#define COMPONENTS_NTP_SNIPPETS_REMOTE_JSON_REQUEST_H_
#include <memory>
#include <string>
#include <utility>
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/time/time.h"
#include "components/language/core/browser/url_language_histogram.h"
#include "components/ntp_snippets/remote/request_params.h"
#include "components/ntp_snippets/status.h"
#include "services/network/public/cpp/resource_request.h"
#include "url/gurl.h"
namespace base {
class Value;
class Clock;
} // namespace base
namespace network {
class SharedURLLoaderFactory;
class SimpleURLLoader;
} // namespace network
namespace ntp_snippets {
class UserClassifier;
namespace internal {
// Enumeration listing all possible outcomes for fetch attempts. Used for UMA
// histograms, so do not change existing values. Insert new values at the end,
// and update the histogram definition.
enum class FetchResult {
SUCCESS = 0,
// DEPRECATED_EMPTY_HOSTS = 1,
URL_REQUEST_STATUS_ERROR = 2,
HTTP_ERROR = 3,
JSON_PARSE_ERROR = 4,
INVALID_SNIPPET_CONTENT_ERROR = 5,
OAUTH_TOKEN_ERROR = 6,
// DEPRECATED_INTERACTIVE_QUOTA_ERROR = 7,
// DEPRECATED_NON_INTERACTIVE_QUOTA_ERROR = 8,
MISSING_API_KEY = 9,
HTTP_ERROR_UNAUTHORIZED = 10,
RESULT_MAX = 11,
};
// A single request to query remote suggestions. On success, the suggestions are
// returned in parsed JSON form (base::Value).
class JsonRequest {
public:
// A client can expect error_details only, if there was any error during the
// fetching or parsing. In successful cases, it will be an empty string.
using CompletedCallback =
base::OnceCallback<void(std::unique_ptr<base::Value> result,
FetchResult result_code,
const std::string& error_details)>;
// Builds authenticated and non-authenticated JsonRequests.
class Builder {
public:
Builder();
Builder(Builder&&);
~Builder();
// Builds a Request object that contains all data to fetch new snippets.
std::unique_ptr<JsonRequest> Build() const;
Builder& SetAuthentication(const std::string& account_id,
const std::string& auth_header);
Builder& SetCreationTime(base::TimeTicks creation_time);
// The language_histogram borrowed from the fetcher needs to stay alive
// until the request body is built.
Builder& SetLanguageHistogram(
const language::UrlLanguageHistogram* language_histogram);
Builder& SetParams(const RequestParams& params);
Builder& SetParseJsonCallback(ParseJSONCallback callback);
// The clock borrowed from the fetcher will be injected into the
// request. It will be used at build time and after the fetch returned.
// It has to be alive until the request is destroyed.
Builder& SetClock(base::Clock* clock);
Builder& SetUrl(const GURL& url);
Builder& SetUrlLoaderFactory(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
Builder& SetUserClassifier(const UserClassifier& user_classifier);
// These preview methods allow to inspect the Request without exposing it
// publicly.
// TODO(fhorschig): Remove these when moving the Builder to
// snippets::internal and trigger the request to intercept the request.
std::string PreviewRequestBodyForTesting() { return BuildBody(); }
std::string PreviewRequestHeadersForTesting() {
return BuildResourceRequest()->headers.ToString();
}
Builder& SetUserClassForTesting(const std::string& user_class) {
user_class_ = user_class;
return *this;
}
bool is_interactive_request() const { return params_.interactive_request; }
private:
std::unique_ptr<network::ResourceRequest> BuildResourceRequest() const;
std::string BuildBody() const;
std::unique_ptr<network::SimpleURLLoader> BuildURLLoader(
const std::string& body) const;
void PrepareLanguages(
language::UrlLanguageHistogram::LanguageInfo* ui_language,
language::UrlLanguageHistogram::LanguageInfo* other_top_language) const;
// Only required, if the request needs to be sent.
std::string auth_header_;
base::Clock* clock_;
RequestParams params_;
ParseJSONCallback parse_json_callback_;
GURL url_;
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
// Optional properties.
std::string obfuscated_gaia_id_;
std::string user_class_;
const language::UrlLanguageHistogram* language_histogram_;
DISALLOW_COPY_AND_ASSIGN(Builder);
};
JsonRequest(base::Optional<Category> exclusive_category,
base::Clock* clock,
const ParseJSONCallback& callback);
JsonRequest(JsonRequest&&);
~JsonRequest();
void Start(CompletedCallback callback);
static int Get5xxRetryCount(bool interactive_request);
const base::Optional<Category>& exclusive_category() const {
return exclusive_category_;
}
base::TimeDelta GetFetchDuration() const;
std::string GetResponseString() const;
private:
void OnSimpleLoaderComplete(std::unique_ptr<std::string> response_body);
void ParseJsonResponse();
void OnJsonParsed(std::unique_ptr<base::Value> result);
void OnJsonError(const std::string& error);
// The loader for downloading the snippets. Only non-null if a load is
// currently ongoing.
std::unique_ptr<network::SimpleURLLoader> simple_url_loader_;
// The loader factory for downloading the snippets.
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
// If set, only return results for this category.
base::Optional<Category> exclusive_category_;
// Use the Clock from the Fetcher to measure the fetch time. It will be
// used on creation and after the fetch returned. It has to be alive until the
// request is destroyed.
base::Clock* clock_;
base::Time creation_time_;
// This callback is called to parse a json string. It contains callbacks for
// error and success cases.
ParseJSONCallback parse_json_callback_;
// The callback to notify when URLFetcher finished and results are available.
CompletedCallback request_completed_callback_;
// The last response string
std::string last_response_string_;
base::WeakPtrFactory<JsonRequest> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(JsonRequest);
};
} // namespace internal
} // namespace ntp_snippets
#endif // COMPONENTS_NTP_SNIPPETS_REMOTE_JSON_REQUEST_H_
|