Chromium Code Reviews| Index: components/ntp_snippets/remote/ntp_snippets_fetcher.cc |
| diff --git a/components/ntp_snippets/remote/ntp_snippets_fetcher.cc b/components/ntp_snippets/remote/ntp_snippets_fetcher.cc |
| index 4ba1451b564dab8ca9830dec513eae47e2392afd..9807b43af7a06c8c230abb027fd956437ff92f57 100644 |
| --- a/components/ntp_snippets/remote/ntp_snippets_fetcher.cc |
| +++ b/components/ntp_snippets/remote/ntp_snippets_fetcher.cc |
| @@ -4,20 +4,15 @@ |
| #include "components/ntp_snippets/remote/ntp_snippets_fetcher.h" |
| -#include <algorithm> |
| #include <cstdlib> |
| #include <utility> |
| -#include "base/command_line.h" |
| #include "base/files/file_path.h" |
| #include "base/files/file_util.h" |
| -#include "base/json/json_writer.h" |
| #include "base/memory/ptr_util.h" |
| #include "base/metrics/histogram_macros.h" |
| #include "base/metrics/sparse_histogram.h" |
| #include "base/path_service.h" |
| -#include "base/strings/string_number_conversions.h" |
| -#include "base/strings/string_util.h" |
| #include "base/strings/stringprintf.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/time/default_tick_clock.h" |
| @@ -27,19 +22,13 @@ |
| #include "components/ntp_snippets/category.h" |
| #include "components/ntp_snippets/features.h" |
| #include "components/ntp_snippets/ntp_snippets_constants.h" |
| +#include "components/ntp_snippets/remote/ntp_snippets_request_params.h" |
| #include "components/ntp_snippets/user_classifier.h" |
| -#include "components/signin/core/browser/profile_oauth2_token_service.h" |
| #include "components/signin/core/browser/signin_manager.h" |
| #include "components/signin/core/browser/signin_manager_base.h" |
| -#include "components/variations/net/variations_http_headers.h" |
| #include "components/variations/variations_associated_data.h" |
| #include "grit/components_strings.h" |
| -#include "net/base/load_flags.h" |
| -#include "net/http/http_response_headers.h" |
| -#include "net/http/http_status_code.h" |
| #include "net/url_request/url_fetcher.h" |
| -#include "third_party/icu/source/common/unicode/uloc.h" |
| -#include "third_party/icu/source/common/unicode/utypes.h" |
| #include "ui/base/l10n/l10n_util.h" |
| using net::URLFetcher; |
| @@ -50,6 +39,10 @@ using translate::LanguageModel; |
| namespace ntp_snippets { |
| +using internal::NTPSnippetsJsonRequest; |
| +using internal::FetchAPI; |
| +using internal::FetchResult; |
| + |
| namespace { |
| const char kChromeReaderApiScope[] = |
| @@ -62,9 +55,6 @@ const char kAuthorizationRequestHeaderFormat[] = "Bearer %s"; |
| // Variation parameter for personalizing fetching of snippets. |
| const char kPersonalizationName[] = "fetching_personalization"; |
| -// Variation parameter for disabling the retry. |
| -const char kBackground5xxRetriesName[] = "background_5xx_retries_count"; |
| - |
| // Variation parameter for chrome-content-suggestions backend. |
| const char kContentSuggestionsBackend[] = "content_suggestions_backend"; |
| @@ -73,66 +63,55 @@ const char kPersonalizationPersonalString[] = "personal"; |
| const char kPersonalizationNonPersonalString[] = "non_personal"; |
| const char kPersonalizationBothString[] = "both"; // the default value |
| -const int kMaxExcludedIds = 100; |
| - |
| -// Variation parameter for sending LanguageModel info to the server. |
| -const char kSendTopLanguagesName[] = "send_top_languages"; |
| - |
| -// Variation parameter for sending UserClassifier info to the server. |
| -const char kSendUserClassName[] = "send_user_class"; |
| - |
| -const char kBooleanParameterEnabled[] = "true"; |
| -const char kBooleanParameterDisabled[] = "false"; |
| - |
| const int kFetchTimeHistogramResolution = 5; |
| -std::string FetchResultToString(NTPSnippetsFetcher::FetchResult result) { |
| +std::string FetchResultToString(FetchResult result) { |
| switch (result) { |
| - case NTPSnippetsFetcher::FetchResult::SUCCESS: |
| + case FetchResult::SUCCESS: |
| return "OK"; |
| - case NTPSnippetsFetcher::FetchResult::DEPRECATED_EMPTY_HOSTS: |
| + case FetchResult::DEPRECATED_EMPTY_HOSTS: |
| return "Cannot fetch for empty hosts list."; |
| - case NTPSnippetsFetcher::FetchResult::URL_REQUEST_STATUS_ERROR: |
| + case FetchResult::URL_REQUEST_STATUS_ERROR: |
| return "URLRequestStatus error"; |
| - case NTPSnippetsFetcher::FetchResult::HTTP_ERROR: |
| + case FetchResult::HTTP_ERROR: |
| return "HTTP error"; |
| - case NTPSnippetsFetcher::FetchResult::JSON_PARSE_ERROR: |
| + case FetchResult::JSON_PARSE_ERROR: |
| return "Received invalid JSON"; |
| - case NTPSnippetsFetcher::FetchResult::INVALID_SNIPPET_CONTENT_ERROR: |
| + case FetchResult::INVALID_SNIPPET_CONTENT_ERROR: |
| return "Invalid / empty list."; |
| - case NTPSnippetsFetcher::FetchResult::OAUTH_TOKEN_ERROR: |
| + case FetchResult::OAUTH_TOKEN_ERROR: |
| return "Error in obtaining an OAuth2 access token."; |
| - case NTPSnippetsFetcher::FetchResult::INTERACTIVE_QUOTA_ERROR: |
| + case FetchResult::INTERACTIVE_QUOTA_ERROR: |
| return "Out of interactive quota."; |
| - case NTPSnippetsFetcher::FetchResult::NON_INTERACTIVE_QUOTA_ERROR: |
| + case FetchResult::NON_INTERACTIVE_QUOTA_ERROR: |
| return "Out of non-interactive quota."; |
| - case NTPSnippetsFetcher::FetchResult::RESULT_MAX: |
| + case FetchResult::RESULT_MAX: |
| break; |
| } |
| NOTREACHED(); |
| return "Unknown error"; |
| } |
| -Status FetchResultToStatus(NTPSnippetsFetcher::FetchResult result) { |
| +Status FetchResultToStatus(FetchResult result) { |
| switch (result) { |
| - case NTPSnippetsFetcher::FetchResult::SUCCESS: |
| + case FetchResult::SUCCESS: |
| return Status::Success(); |
| // Permanent errors occur if it is more likely that the error originated |
| // from the client. |
| - case NTPSnippetsFetcher::FetchResult::DEPRECATED_EMPTY_HOSTS: |
| - case NTPSnippetsFetcher::FetchResult::OAUTH_TOKEN_ERROR: |
| + case FetchResult::DEPRECATED_EMPTY_HOSTS: |
| + case FetchResult::OAUTH_TOKEN_ERROR: |
| return Status(StatusCode::PERMANENT_ERROR, FetchResultToString(result)); |
| // Temporary errors occur if it's more likely that the client behaved |
| // correctly but the server failed to respond as expected. |
| // TODO(fhorschig): Revisit HTTP_ERROR once the rescheduling was reworked. |
| - case NTPSnippetsFetcher::FetchResult::HTTP_ERROR: |
| - case NTPSnippetsFetcher::FetchResult::INTERACTIVE_QUOTA_ERROR: |
| - case NTPSnippetsFetcher::FetchResult::NON_INTERACTIVE_QUOTA_ERROR: |
| - case NTPSnippetsFetcher::FetchResult::URL_REQUEST_STATUS_ERROR: |
| - case NTPSnippetsFetcher::FetchResult::INVALID_SNIPPET_CONTENT_ERROR: |
| - case NTPSnippetsFetcher::FetchResult::JSON_PARSE_ERROR: |
| + case FetchResult::HTTP_ERROR: |
| + case FetchResult::INTERACTIVE_QUOTA_ERROR: |
| + case FetchResult::NON_INTERACTIVE_QUOTA_ERROR: |
| + case FetchResult::URL_REQUEST_STATUS_ERROR: |
| + case FetchResult::INVALID_SNIPPET_CONTENT_ERROR: |
| + case FetchResult::JSON_PARSE_ERROR: |
| return Status(StatusCode::TEMPORARY_ERROR, FetchResultToString(result)); |
| - case NTPSnippetsFetcher::FetchResult::RESULT_MAX: |
| + case FetchResult::RESULT_MAX: |
| break; |
| } |
| NOTREACHED(); |
| @@ -145,42 +124,6 @@ std::string GetFetchEndpoint() { |
| return endpoint.empty() ? kChromeReaderServer : endpoint; |
| } |
| -bool IsBooleanParameterEnabled(const std::string& param_name, |
| - bool default_value) { |
| - std::string param_value = variations::GetVariationParamValueByFeature( |
| - ntp_snippets::kArticleSuggestionsFeature, param_name); |
| - if (param_value == kBooleanParameterEnabled) { |
| - return true; |
| - } |
| - if (param_value == kBooleanParameterDisabled) { |
| - return false; |
| - } |
| - if (!param_value.empty()) { |
| - LOG(WARNING) << "Invalid value \"" << param_value |
| - << "\" for variation parameter " << param_name; |
| - } |
| - return default_value; |
| -} |
| - |
| -int Get5xxRetryCount(bool interactive_request) { |
| - if (interactive_request) { |
| - return 2; |
| - } |
| - return std::max(0, variations::GetVariationParamByFeatureAsInt( |
| - ntp_snippets::kArticleSuggestionsFeature, |
| - kBackground5xxRetriesName, 0)); |
| -} |
| - |
| -bool IsSendingTopLanguagesEnabled() { |
| - return IsBooleanParameterEnabled(kSendTopLanguagesName, |
| - /*default_value=*/false); |
| -} |
| - |
| -bool IsSendingUserClassEnabled() { |
| - return IsBooleanParameterEnabled(kSendUserClassName, |
| - /*default_value=*/false); |
| -} |
| - |
| bool UsesChromeContentSuggestionsAPI(const GURL& endpoint) { |
| if (endpoint == kChromeReaderServer) { |
| return false; |
| @@ -224,55 +167,6 @@ bool AddSnippetsFromListValue(bool content_suggestions_api, |
| return true; |
| } |
| -// Translate the BCP 47 |language_code| into a posix locale string. |
| -std::string PosixLocaleFromBCP47Language(const std::string& language_code) { |
| - char locale[ULOC_FULLNAME_CAPACITY]; |
| - UErrorCode error = U_ZERO_ERROR; |
| - // Translate the input to a posix locale. |
| - uloc_forLanguageTag(language_code.c_str(), locale, ULOC_FULLNAME_CAPACITY, |
| - nullptr, &error); |
| - if (error != U_ZERO_ERROR) { |
| - DLOG(WARNING) << "Error in translating language code to a locale string: " |
| - << error; |
| - return std::string(); |
| - } |
| - return locale; |
| -} |
| - |
| -std::string ISO639FromPosixLocale(const std::string& locale) { |
| - char language[ULOC_LANG_CAPACITY]; |
| - UErrorCode error = U_ZERO_ERROR; |
| - uloc_getLanguage(locale.c_str(), language, ULOC_LANG_CAPACITY, &error); |
| - if (error != U_ZERO_ERROR) { |
| - DLOG(WARNING) |
| - << "Error in translating locale string to a ISO639 language code: " |
| - << error; |
| - return std::string(); |
| - } |
| - return language; |
| -} |
| - |
| -void AppendLanguageInfoToList(base::ListValue* list, |
| - const LanguageModel::LanguageInfo& info) { |
| - auto lang = base::MakeUnique<base::DictionaryValue>(); |
| - lang->SetString("language", info.language_code); |
| - lang->SetDouble("frequency", info.frequency); |
| - list->Append(std::move(lang)); |
| -} |
| - |
| -std::string GetUserClassString(UserClassifier::UserClass user_class) { |
| - switch (user_class) { |
| - case UserClassifier::UserClass::RARE_NTP_USER: |
| - return "RARE_NTP_USER"; |
| - case UserClassifier::UserClass::ACTIVE_NTP_USER: |
| - return "ACTIVE_NTP_USER"; |
| - case UserClassifier::UserClass::ACTIVE_SUGGESTIONS_CONSUMER: |
| - return "ACTIVE_SUGGESTIONS_CONSUMER"; |
| - } |
| - NOTREACHED(); |
| - return std::string(); |
| -} |
| - |
| int GetMinuteOfTheDay(bool local_time, bool reduced_resolution) { |
| base::Time now(base::Time::Now()); |
| base::Time::Exploded now_exploded{}; |
| @@ -309,65 +203,7 @@ void FilterCategories(NTPSnippetsFetcher::FetchedCategoriesVector* categories, |
| } // namespace |
| -// A single request to query snippets. |
| -class NTPSnippetsFetcher::JsonRequest : public net::URLFetcherDelegate { |
| - public: |
| - JsonRequest(base::Optional<Category> exclusive_category, |
| - base::TickClock* tick_clock, |
| - const ParseJSONCallback& callback); |
| - JsonRequest(JsonRequest&&); |
| - ~JsonRequest() override; |
| - |
| - // 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)>; |
| - |
| - void Start(CompletedCallback callback); |
| - |
| - const base::Optional<Category>& exclusive_category() const { |
| - return exclusive_category_; |
| - } |
| - |
| - base::TimeDelta GetFetchDuration() const; |
| - std::string GetResponseString() const; |
| - |
| - private: |
| - friend class RequestBuilder; |
| - // URLFetcherDelegate implementation. |
| - void OnURLFetchComplete(const net::URLFetcher* source) override; |
| - |
| - void ParseJsonResponse(); |
| - void OnJsonParsed(std::unique_ptr<base::Value> result); |
| - void OnJsonError(const std::string& error); |
| - |
| - // The fetcher for downloading the snippets. Only non-null if a fetch is |
| - // currently ongoing. |
| - std::unique_ptr<net::URLFetcher> url_fetcher_; |
| - |
| - // If set, only return results for this category. |
| - base::Optional<Category> exclusive_category_; |
| - |
| - // Use the TickClock 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::TickClock* tick_clock_; |
| - base::TimeTicks 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_; |
| - |
| - base::WeakPtrFactory<JsonRequest> weak_ptr_factory_; |
| - |
| - DISALLOW_COPY_AND_ASSIGN(JsonRequest); |
| -}; |
| CategoryInfo BuildArticleCategoryInfo( |
| const base::Optional<base::string16>& title) { |
| @@ -414,10 +250,6 @@ NTPSnippetsFetcher::FetchedCategory::~FetchedCategory() = default; |
| NTPSnippetsFetcher::FetchedCategory& NTPSnippetsFetcher::FetchedCategory:: |
| operator=(FetchedCategory&&) = default; |
| -NTPSnippetsFetcher::Params::Params() = default; |
| -NTPSnippetsFetcher::Params::Params(const Params&) = default; |
| -NTPSnippetsFetcher::Params::~Params() = default; |
| - |
| NTPSnippetsFetcher::NTPSnippetsFetcher( |
| SigninManagerBase* signin_manager, |
| OAuth2TokenService* token_service, |
| @@ -474,7 +306,7 @@ NTPSnippetsFetcher::~NTPSnippetsFetcher() { |
| } |
| } |
| -void NTPSnippetsFetcher::FetchSnippets(const Params& params, |
| +void NTPSnippetsFetcher::FetchSnippets(const NTPSnippetsRequestParams& params, |
| SnippetsAvailableCallback callback) { |
| if (!DemandQuotaForRequest(params.interactive_request)) { |
| FetchFinished(OptionalFetchedCategories(), std::move(callback), |
| @@ -494,7 +326,7 @@ void NTPSnippetsFetcher::FetchSnippets(const Params& params, |
| /*reduced_resolution=*/true)); |
| } |
| - RequestBuilder builder; |
| + NTPSnippetsJsonRequest::Builder builder; |
| builder.SetFetchAPI(fetch_api_) |
| .SetFetchAPI(fetch_api_) |
| .SetLanguageModel(language_model_) |
| @@ -525,361 +357,8 @@ void NTPSnippetsFetcher::FetchSnippets(const Params& params, |
| } |
| } |
| -NTPSnippetsFetcher::JsonRequest::JsonRequest( |
| - base::Optional<Category> exclusive_category, |
| - base::TickClock* tick_clock, // Needed until destruction of the request. |
| - const ParseJSONCallback& callback) |
| - : exclusive_category_(exclusive_category), |
| - tick_clock_(tick_clock), |
| - parse_json_callback_(callback), |
| - weak_ptr_factory_(this) { |
| - creation_time_ = tick_clock_->NowTicks(); |
| -} |
| - |
| -NTPSnippetsFetcher::JsonRequest::~JsonRequest() { |
| - LOG_IF(DFATAL, !request_completed_callback_.is_null()) |
| - << "The CompletionCallback was never called!"; |
| -} |
| - |
| -void NTPSnippetsFetcher::JsonRequest::Start(CompletedCallback callback) { |
| - request_completed_callback_ = std::move(callback); |
| - url_fetcher_->Start(); |
| -} |
| - |
| -base::TimeDelta NTPSnippetsFetcher::JsonRequest::GetFetchDuration() const { |
| - return tick_clock_->NowTicks() - creation_time_; |
| -} |
| - |
| -std::string NTPSnippetsFetcher::JsonRequest::GetResponseString() const { |
| - std::string response; |
| - url_fetcher_->GetResponseAsString(&response); |
| - return response; |
| -} |
| - |
| -//////////////////////////////////////////////////////////////////////////////// |
| -// URLFetcherDelegate overrides |
| -void NTPSnippetsFetcher::JsonRequest::OnURLFetchComplete( |
| - const net::URLFetcher* source) { |
| - DCHECK_EQ(url_fetcher_.get(), source); |
| - const URLRequestStatus& status = url_fetcher_->GetStatus(); |
| - int response = url_fetcher_->GetResponseCode(); |
| - UMA_HISTOGRAM_SPARSE_SLOWLY( |
| - "NewTabPage.Snippets.FetchHttpResponseOrErrorCode", |
| - status.is_success() ? response : status.error()); |
| - |
| - if (!status.is_success()) { |
| - std::move(request_completed_callback_) |
| - .Run(/*result=*/nullptr, FetchResult::URL_REQUEST_STATUS_ERROR, |
| - /*error_details=*/base::StringPrintf(" %d", status.error())); |
| - } else if (response != net::HTTP_OK) { |
| - // TODO(jkrcal): https://crbug.com/609084 |
| - // We need to deal with the edge case again where the auth |
| - // token expires just before we send the request (in which case we need to |
| - // fetch a new auth token). We should extract that into a common class |
| - // instead of adding it to every single class that uses auth tokens. |
| - std::move(request_completed_callback_) |
| - .Run(/*result=*/nullptr, FetchResult::HTTP_ERROR, |
| - /*error_details=*/base::StringPrintf(" %d", response)); |
| - } else { |
| - ParseJsonResponse(); |
| - } |
| -} |
| - |
| -void NTPSnippetsFetcher::JsonRequest::ParseJsonResponse() { |
| - std::string json_string; |
| - bool stores_result_to_string = |
| - url_fetcher_->GetResponseAsString(&json_string); |
| - DCHECK(stores_result_to_string); |
| - |
| - parse_json_callback_.Run( |
| - json_string, |
| - base::Bind(&JsonRequest::OnJsonParsed, weak_ptr_factory_.GetWeakPtr()), |
| - base::Bind(&JsonRequest::OnJsonError, weak_ptr_factory_.GetWeakPtr())); |
| -} |
| - |
| -void NTPSnippetsFetcher::JsonRequest::OnJsonParsed( |
| - std::unique_ptr<base::Value> result) { |
| - std::move(request_completed_callback_) |
| - .Run(std::move(result), FetchResult::SUCCESS, |
| - /*error_details=*/std::string()); |
| -} |
| - |
| -void NTPSnippetsFetcher::JsonRequest::OnJsonError(const std::string& error) { |
| - std::string json_string; |
| - url_fetcher_->GetResponseAsString(&json_string); |
| - LOG(WARNING) << "Received invalid JSON (" << error << "): " << json_string; |
| - std::move(request_completed_callback_) |
| - .Run(/*result=*/nullptr, FetchResult::JSON_PARSE_ERROR, |
| - /*error_details=*/base::StringPrintf(" (error %s)", error.c_str())); |
| -} |
| - |
| -NTPSnippetsFetcher::RequestBuilder::RequestBuilder() |
| - : fetch_api_(CHROME_READER_API), |
| - personalization_(Personalization::kBoth), |
| - language_model_(nullptr) {} |
| -NTPSnippetsFetcher::RequestBuilder::RequestBuilder(RequestBuilder&&) = default; |
| -NTPSnippetsFetcher::RequestBuilder::~RequestBuilder() = default; |
| - |
| -std::unique_ptr<NTPSnippetsFetcher::JsonRequest> |
| -NTPSnippetsFetcher::RequestBuilder::Build() const { |
| - DCHECK(!url_.is_empty()); |
| - DCHECK(url_request_context_getter_); |
| - auto request = base::MakeUnique<JsonRequest>( |
| - params_.exclusive_category, tick_clock_, parse_json_callback_); |
| - std::string body = BuildBody(); |
| - std::string headers = BuildHeaders(); |
| - request->url_fetcher_ = BuildURLFetcher(request.get(), headers, body); |
| - |
| - // Log the request for debugging network issues. |
| - VLOG(1) << "Sending a NTP snippets request to " << url_ << ":\n" |
| - << headers << "\n" |
| - << body; |
| - |
| - return request; |
| -} |
| - |
| -NTPSnippetsFetcher::RequestBuilder& |
| -NTPSnippetsFetcher::RequestBuilder::SetAuthentication( |
| - const std::string& account_id, |
| - const std::string& auth_header) { |
| - obfuscated_gaia_id_ = account_id; |
| - auth_header_ = auth_header; |
| - return *this; |
| -} |
| - |
| -NTPSnippetsFetcher::RequestBuilder& |
| -NTPSnippetsFetcher::RequestBuilder::SetFetchAPI(FetchAPI fetch_api) { |
| - fetch_api_ = fetch_api; |
| - return *this; |
| -} |
| - |
| -NTPSnippetsFetcher::RequestBuilder& |
| -NTPSnippetsFetcher::RequestBuilder::SetLanguageModel( |
| - const translate::LanguageModel* language_model) { |
| - language_model_ = language_model; |
| - return *this; |
| -} |
| - |
| -NTPSnippetsFetcher::RequestBuilder& |
| -NTPSnippetsFetcher::RequestBuilder::SetParams(const Params& params) { |
| - params_ = params; |
| - return *this; |
| -} |
| - |
| -NTPSnippetsFetcher::RequestBuilder& |
| -NTPSnippetsFetcher::RequestBuilder::SetParseJsonCallback( |
| - ParseJSONCallback callback) { |
| - parse_json_callback_ = callback; |
| - return *this; |
| -} |
| - |
| -NTPSnippetsFetcher::RequestBuilder& |
| -NTPSnippetsFetcher::RequestBuilder::SetPersonalization( |
| - Personalization personalization) { |
| - personalization_ = personalization; |
| - return *this; |
| -} |
| - |
| -NTPSnippetsFetcher::RequestBuilder& |
| -NTPSnippetsFetcher::RequestBuilder::SetTickClock(base::TickClock* tick_clock) { |
| - tick_clock_ = tick_clock; |
| - return *this; |
| -} |
| - |
| -NTPSnippetsFetcher::RequestBuilder& NTPSnippetsFetcher::RequestBuilder::SetUrl( |
| - const GURL& url) { |
| - url_ = url; |
| - return *this; |
| -} |
| - |
| -NTPSnippetsFetcher::RequestBuilder& |
| -NTPSnippetsFetcher::RequestBuilder::SetUrlRequestContextGetter( |
| - const scoped_refptr<net::URLRequestContextGetter>& context_getter) { |
| - url_request_context_getter_ = context_getter; |
| - return *this; |
| -} |
| - |
| -NTPSnippetsFetcher::RequestBuilder& |
| -NTPSnippetsFetcher::RequestBuilder::SetUserClassifier( |
| - const UserClassifier& user_classifier) { |
| - if (IsSendingUserClassEnabled()) { |
| - user_class_ = GetUserClassString(user_classifier.GetUserClass()); |
| - } |
| - return *this; |
| -} |
| - |
| -std::string NTPSnippetsFetcher::RequestBuilder::BuildHeaders() const { |
| - net::HttpRequestHeaders headers; |
| - headers.SetHeader("Content-Type", "application/json; charset=UTF-8"); |
| - if (!auth_header_.empty()) { |
| - headers.SetHeader("Authorization", auth_header_); |
| - } |
| - // Add X-Client-Data header with experiment IDs from field trials. |
| - // Note: It's fine to pass in |is_signed_in| false, which does not affect |
| - // transmission of experiment ids coming from the variations server. |
| - bool is_signed_in = false; |
| - variations::AppendVariationHeaders(url_, |
| - false, // incognito |
| - false, // uma_enabled |
| - is_signed_in, &headers); |
| - return headers.ToString(); |
| -} |
| - |
| -std::string NTPSnippetsFetcher::RequestBuilder::BuildBody() const { |
| - auto request = base::MakeUnique<base::DictionaryValue>(); |
| - std::string user_locale = PosixLocaleFromBCP47Language(params_.language_code); |
| - switch (fetch_api_) { |
| - case NTPSnippetsFetcher::CHROME_READER_API: { |
| - auto content_params = base::MakeUnique<base::DictionaryValue>(); |
| - content_params->SetBoolean("only_return_personalized_results", |
| - ReturnOnlyPersonalizedResults()); |
| - |
| - auto content_restricts = base::MakeUnique<base::ListValue>(); |
| - for (const auto* metadata : {"TITLE", "SNIPPET", "THUMBNAIL"}) { |
| - auto entry = base::MakeUnique<base::DictionaryValue>(); |
| - entry->SetString("type", "METADATA"); |
| - entry->SetString("value", metadata); |
| - content_restricts->Append(std::move(entry)); |
| - } |
| - |
| - auto local_scoring_params = base::MakeUnique<base::DictionaryValue>(); |
| - local_scoring_params->Set("content_params", std::move(content_params)); |
| - local_scoring_params->Set("content_restricts", |
| - std::move(content_restricts)); |
| - |
| - auto global_scoring_params = base::MakeUnique<base::DictionaryValue>(); |
| - global_scoring_params->SetInteger("num_to_return", |
| - params_.count_to_fetch); |
| - global_scoring_params->SetInteger("sort_type", 1); |
| - |
| - auto advanced = base::MakeUnique<base::DictionaryValue>(); |
| - advanced->Set("local_scoring_params", std::move(local_scoring_params)); |
| - advanced->Set("global_scoring_params", std::move(global_scoring_params)); |
| - |
| - request->SetString("response_detail_level", "STANDARD"); |
| - request->Set("advanced_options", std::move(advanced)); |
| - if (!obfuscated_gaia_id_.empty()) { |
| - request->SetString("obfuscated_gaia_id", obfuscated_gaia_id_); |
| - } |
| - if (!user_locale.empty()) { |
| - request->SetString("user_locale", user_locale); |
| - } |
| - break; |
| - } |
| - |
| - case NTPSnippetsFetcher::CHROME_CONTENT_SUGGESTIONS_API: { |
| - if (!user_locale.empty()) { |
| - request->SetString("uiLanguage", user_locale); |
| - } |
| - |
| - request->SetString("priority", params_.interactive_request |
| - ? "USER_ACTION" |
| - : "BACKGROUND_PREFETCH"); |
| - |
| - auto excluded = base::MakeUnique<base::ListValue>(); |
| - for (const auto& id : params_.excluded_ids) { |
| - excluded->AppendString(id); |
| - if (excluded->GetSize() >= kMaxExcludedIds) { |
| - break; |
| - } |
| - } |
| - request->Set("excludedSuggestionIds", std::move(excluded)); |
| - |
| - if (!user_class_.empty()) { |
| - request->SetString("userActivenessClass", user_class_); |
| - } |
| - |
| - translate::LanguageModel::LanguageInfo ui_language; |
| - translate::LanguageModel::LanguageInfo other_top_language; |
| - PrepareLanguages(&ui_language, &other_top_language); |
| - |
| - if (ui_language.frequency == 0 && other_top_language.frequency == 0) { |
| - break; |
| - } |
| - |
| - auto language_list = base::MakeUnique<base::ListValue>(); |
| - if (ui_language.frequency > 0) { |
| - AppendLanguageInfoToList(language_list.get(), ui_language); |
| - } |
| - if (other_top_language.frequency > 0) { |
| - AppendLanguageInfoToList(language_list.get(), other_top_language); |
| - } |
| - request->Set("topLanguages", std::move(language_list)); |
| - |
| - // TODO(sfiera): Support only_return_personalized_results. |
| - // TODO(sfiera): Support count_to_fetch. |
| - break; |
| - } |
| - } |
| - |
| - std::string request_json; |
| - bool success = base::JSONWriter::WriteWithOptions( |
| - *request, base::JSONWriter::OPTIONS_PRETTY_PRINT, &request_json); |
| - DCHECK(success); |
| - return request_json; |
| -} |
| - |
| -std::unique_ptr<net::URLFetcher> |
| -NTPSnippetsFetcher::RequestBuilder::BuildURLFetcher( |
| - net::URLFetcherDelegate* delegate, |
| - const std::string& headers, |
| - const std::string& body) const { |
| - std::unique_ptr<net::URLFetcher> url_fetcher = |
| - net::URLFetcher::Create(url_, net::URLFetcher::POST, delegate); |
| - url_fetcher->SetRequestContext(url_request_context_getter_.get()); |
| - url_fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | |
| - net::LOAD_DO_NOT_SAVE_COOKIES); |
| - data_use_measurement::DataUseUserData::AttachToFetcher( |
| - url_fetcher.get(), data_use_measurement::DataUseUserData::NTP_SNIPPETS); |
| - |
| - url_fetcher->SetExtraRequestHeaders(headers); |
| - url_fetcher->SetUploadData("application/json", body); |
| - |
| - // Fetchers are sometimes cancelled because a network change was detected. |
| - url_fetcher->SetAutomaticallyRetryOnNetworkChanges(3); |
| - url_fetcher->SetMaxRetriesOn5xx( |
| - Get5xxRetryCount(params_.interactive_request)); |
| - return url_fetcher; |
| -} |
| - |
| -void NTPSnippetsFetcher::RequestBuilder::PrepareLanguages( |
| - translate::LanguageModel::LanguageInfo* ui_language, |
| - translate::LanguageModel::LanguageInfo* other_top_language) const { |
| - // TODO(jkrcal): Add language model factory for iOS and add fakes to tests so |
| - // that |language_model| is never nullptr. Remove this check and add a DCHECK |
| - // into the constructor. |
| - if (!language_model_ || !IsSendingTopLanguagesEnabled()) { |
| - return; |
| - } |
| - |
| - // TODO(jkrcal): Is this back-and-forth converting necessary? |
| - ui_language->language_code = ISO639FromPosixLocale( |
| - PosixLocaleFromBCP47Language(params_.language_code)); |
| - ui_language->frequency = |
| - language_model_->GetLanguageFrequency(ui_language->language_code); |
| - |
| - std::vector<LanguageModel::LanguageInfo> top_languages = |
| - language_model_->GetTopLanguages(); |
| - for (const LanguageModel::LanguageInfo& info : top_languages) { |
| - if (info.language_code != ui_language->language_code) { |
| - *other_top_language = info; |
| - |
| - // Report to UMA how important the UI language is. |
| - DCHECK_GT(other_top_language->frequency, 0) |
| - << "GetTopLanguages() should not return languages with 0 frequency"; |
| - float ratio_ui_in_both_languages = |
| - ui_language->frequency / |
| - (ui_language->frequency + other_top_language->frequency); |
| - UMA_HISTOGRAM_PERCENTAGE( |
| - "NewTabPage.Languages.UILanguageRatioInTwoTopLanguages", |
| - ratio_ui_in_both_languages * 100); |
| - break; |
| - } |
| - } |
| -} |
| - |
| void NTPSnippetsFetcher::FetchSnippetsNonAuthenticated( |
| - RequestBuilder builder, |
| + NTPSnippetsJsonRequest::Builder builder, |
| SnippetsAvailableCallback callback) { |
| // When not providing OAuth token, we need to pass the Google API key. |
| builder.SetUrl( |
| @@ -889,7 +368,7 @@ void NTPSnippetsFetcher::FetchSnippetsNonAuthenticated( |
| } |
| void NTPSnippetsFetcher::FetchSnippetsAuthenticated( |
| - RequestBuilder builder, |
| + NTPSnippetsJsonRequest::Builder builder, |
| SnippetsAvailableCallback callback, |
| const std::string& account_id, |
| const std::string& oauth_access_token) { |
| @@ -901,10 +380,10 @@ void NTPSnippetsFetcher::FetchSnippetsAuthenticated( |
| StartRequest(std::move(builder), std::move(callback)); |
| } |
| -void NTPSnippetsFetcher::StartRequest(RequestBuilder builder, |
| +void NTPSnippetsFetcher::StartRequest(NTPSnippetsJsonRequest::Builder builder, |
| SnippetsAvailableCallback callback) { |
| - std::unique_ptr<JsonRequest> request = builder.Build(); |
| - JsonRequest* raw_request = request.get(); |
| + std::unique_ptr<NTPSnippetsJsonRequest> request = builder.Build(); |
| + NTPSnippetsJsonRequest* raw_request = request.get(); |
| raw_request->Start(base::BindOnce(&NTPSnippetsFetcher::JsonRequestDone, |
| base::Unretained(this), std::move(request), |
| std::move(callback))); |
| @@ -932,8 +411,8 @@ void NTPSnippetsFetcher::OnGetTokenSuccess( |
| << "Got tokens from some previous request"; |
| while (!pending_requests_.empty()) { |
| - std::pair<RequestBuilder, SnippetsAvailableCallback> builder_and_callback = |
| - std::move(pending_requests_.front()); |
| + std::pair<NTPSnippetsJsonRequest::Builder, SnippetsAvailableCallback> |
| + builder_and_callback = std::move(pending_requests_.front()); |
| pending_requests_.pop(); |
| FetchSnippetsAuthenticated(std::move(builder_and_callback.first), |
| std::move(builder_and_callback.second), |
| @@ -957,8 +436,8 @@ void NTPSnippetsFetcher::OnGetTokenFailure( |
| DLOG(ERROR) << "Unable to get token: " << error.ToString(); |
| while (!pending_requests_.empty()) { |
| - std::pair<RequestBuilder, SnippetsAvailableCallback> builder_and_callback = |
| - std::move(pending_requests_.front()); |
| + std::pair<NTPSnippetsJsonRequest::Builder, SnippetsAvailableCallback> |
| + builder_and_callback = std::move(pending_requests_.front()); |
| FetchFinished(OptionalFetchedCategories(), |
| std::move(builder_and_callback.second), |
| @@ -984,11 +463,12 @@ void NTPSnippetsFetcher::OnRefreshTokenAvailable( |
| StartTokenRequest(); |
| } |
| -void NTPSnippetsFetcher::JsonRequestDone(std::unique_ptr<JsonRequest> request, |
| - SnippetsAvailableCallback callback, |
| - std::unique_ptr<base::Value> result, |
| - FetchResult status_code, |
| - const std::string& error_details) { |
| +void NTPSnippetsFetcher::JsonRequestDone( |
| + std::unique_ptr<NTPSnippetsJsonRequest> request, |
| + SnippetsAvailableCallback callback, |
| + std::unique_ptr<base::Value> result, |
| + FetchResult status_code, |
| + const std::string& error_details) { |
| DCHECK(request); |
| last_fetch_json_ = request->GetResponseString(); |
| @@ -1128,4 +608,20 @@ bool NTPSnippetsFetcher::NeedsAuthentication() const { |
| personalization_ == Personalization::kBoth); |
| } |
| +std::string NTPSnippetsFetcher::PersonalizationModeString() const { |
| + switch (personalization_) { |
| + case Personalization::kPersonal: |
| + return "Only personalized"; |
| + break; |
| + case Personalization::kBoth: |
| + return "Both personalized and non-personalized"; |
| + break; |
| + case Personalization::kNonPersonal: |
| + return "Only non-personalized"; |
| + break; |
| + } |
| + NOTREACHED(); |
| + return ""; |
|
Bernhard Bauer
2016/12/20 10:49:35
Nit: use the empty std::string() constructor (it s
fhorschig
2016/12/20 12:11:37
Thank you!
(Now I finally know the reason and was
|
| +} |
| + |
| } // namespace ntp_snippets |