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 |