| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/ntp_snippets/remote/ntp_snippets_fetcher.h" | 5 #include "components/ntp_snippets/remote/ntp_snippets_fetcher.h" |
| 6 | 6 |
| 7 #include <cstdlib> | 7 #include <cstdlib> |
| 8 | 8 |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" |
| 11 #include "base/files/file_util.h" | 11 #include "base/files/file_util.h" |
| 12 #include "base/json/json_writer.h" | 12 #include "base/json/json_writer.h" |
| 13 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" |
| 14 #include "base/metrics/histogram_macros.h" | 14 #include "base/metrics/histogram_macros.h" |
| 15 #include "base/metrics/sparse_histogram.h" | 15 #include "base/metrics/sparse_histogram.h" |
| 16 #include "base/path_service.h" | 16 #include "base/path_service.h" |
| 17 #include "base/strings/string_number_conversions.h" | 17 #include "base/strings/string_number_conversions.h" |
| 18 #include "base/strings/string_util.h" | 18 #include "base/strings/string_util.h" |
| 19 #include "base/strings/stringprintf.h" | 19 #include "base/strings/stringprintf.h" |
| 20 #include "base/strings/utf_string_conversions.h" | 20 #include "base/strings/utf_string_conversions.h" |
| 21 #include "base/time/default_tick_clock.h" | 21 #include "base/time/default_tick_clock.h" |
| 22 #include "base/values.h" | 22 #include "base/values.h" |
| 23 #include "components/data_use_measurement/core/data_use_user_data.h" | 23 #include "components/data_use_measurement/core/data_use_user_data.h" |
| 24 #include "components/ntp_snippets/category_factory.h" | 24 #include "components/ntp_snippets/category_factory.h" |
| 25 #include "components/ntp_snippets/ntp_snippets_constants.h" | 25 #include "components/ntp_snippets/ntp_snippets_constants.h" |
| 26 #include "components/ntp_snippets/user_classifier.h" |
| 26 #include "components/signin/core/browser/profile_oauth2_token_service.h" | 27 #include "components/signin/core/browser/profile_oauth2_token_service.h" |
| 27 #include "components/signin/core/browser/signin_manager.h" | 28 #include "components/signin/core/browser/signin_manager.h" |
| 28 #include "components/signin/core/browser/signin_manager_base.h" | 29 #include "components/signin/core/browser/signin_manager_base.h" |
| 29 #include "components/variations/net/variations_http_headers.h" | 30 #include "components/variations/net/variations_http_headers.h" |
| 30 #include "components/variations/variations_associated_data.h" | 31 #include "components/variations/variations_associated_data.h" |
| 31 #include "net/base/load_flags.h" | 32 #include "net/base/load_flags.h" |
| 32 #include "net/http/http_request_headers.h" | 33 #include "net/http/http_request_headers.h" |
| 33 #include "net/http/http_response_headers.h" | 34 #include "net/http/http_response_headers.h" |
| 34 #include "net/http/http_status_code.h" | 35 #include "net/http/http_status_code.h" |
| 35 #include "net/url_request/url_fetcher.h" | 36 #include "net/url_request/url_fetcher.h" |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 161 char locale[ULOC_FULLNAME_CAPACITY]; | 162 char locale[ULOC_FULLNAME_CAPACITY]; |
| 162 UErrorCode error = U_ZERO_ERROR; | 163 UErrorCode error = U_ZERO_ERROR; |
| 163 // Translate the input to a posix locale. | 164 // Translate the input to a posix locale. |
| 164 uloc_forLanguageTag(language_code.c_str(), locale, ULOC_FULLNAME_CAPACITY, | 165 uloc_forLanguageTag(language_code.c_str(), locale, ULOC_FULLNAME_CAPACITY, |
| 165 nullptr, &error); | 166 nullptr, &error); |
| 166 DLOG_IF(WARNING, U_ZERO_ERROR != error) | 167 DLOG_IF(WARNING, U_ZERO_ERROR != error) |
| 167 << "Error in translating language code to a locale string: " << error; | 168 << "Error in translating language code to a locale string: " << error; |
| 168 return locale; | 169 return locale; |
| 169 } | 170 } |
| 170 | 171 |
| 172 std::string GetUserClassString(UserClassifier::UserClass user_class) { |
| 173 switch (user_class) { |
| 174 case UserClassifier::UserClass::RARE_NTP_USER: |
| 175 return "RARE_NTP_USER"; |
| 176 case UserClassifier::UserClass::ACTIVE_NTP_USER: |
| 177 return "ACTIVE_NTP_USER"; |
| 178 case UserClassifier::UserClass::ACTIVE_SUGGESTIONS_CONSUMER: |
| 179 return "ACTIVE_SUGGESTIONS_CONSUMER"; |
| 180 } |
| 181 NOTREACHED(); |
| 182 return std::string(); |
| 183 } |
| 184 |
| 171 } // namespace | 185 } // namespace |
| 172 | 186 |
| 173 NTPSnippetsFetcher::FetchedCategory::FetchedCategory(Category c) | 187 NTPSnippetsFetcher::FetchedCategory::FetchedCategory(Category c) |
| 174 : category(c) {} | 188 : category(c) {} |
| 175 | 189 |
| 176 NTPSnippetsFetcher::FetchedCategory::FetchedCategory(FetchedCategory&&) = | 190 NTPSnippetsFetcher::FetchedCategory::FetchedCategory(FetchedCategory&&) = |
| 177 default; | 191 default; |
| 178 NTPSnippetsFetcher::FetchedCategory::~FetchedCategory() = default; | 192 NTPSnippetsFetcher::FetchedCategory::~FetchedCategory() = default; |
| 179 NTPSnippetsFetcher::FetchedCategory& NTPSnippetsFetcher::FetchedCategory:: | 193 NTPSnippetsFetcher::FetchedCategory& NTPSnippetsFetcher::FetchedCategory:: |
| 180 operator=(FetchedCategory&&) = default; | 194 operator=(FetchedCategory&&) = default; |
| 181 | 195 |
| 182 NTPSnippetsFetcher::NTPSnippetsFetcher( | 196 NTPSnippetsFetcher::NTPSnippetsFetcher( |
| 183 SigninManagerBase* signin_manager, | 197 SigninManagerBase* signin_manager, |
| 184 OAuth2TokenService* token_service, | 198 OAuth2TokenService* token_service, |
| 185 scoped_refptr<URLRequestContextGetter> url_request_context_getter, | 199 scoped_refptr<URLRequestContextGetter> url_request_context_getter, |
| 186 PrefService* pref_service, | 200 PrefService* pref_service, |
| 187 CategoryFactory* category_factory, | 201 CategoryFactory* category_factory, |
| 188 const ParseJSONCallback& parse_json_callback, | 202 const ParseJSONCallback& parse_json_callback, |
| 189 const std::string& api_key) | 203 const std::string& api_key, |
| 204 const UserClassifier* user_classifier) |
| 190 : OAuth2TokenService::Consumer("ntp_snippets"), | 205 : OAuth2TokenService::Consumer("ntp_snippets"), |
| 191 signin_manager_(signin_manager), | 206 signin_manager_(signin_manager), |
| 192 token_service_(token_service), | 207 token_service_(token_service), |
| 193 waiting_for_refresh_token_(false), | 208 waiting_for_refresh_token_(false), |
| 194 url_request_context_getter_(std::move(url_request_context_getter)), | 209 url_request_context_getter_(std::move(url_request_context_getter)), |
| 195 category_factory_(category_factory), | 210 category_factory_(category_factory), |
| 196 parse_json_callback_(parse_json_callback), | 211 parse_json_callback_(parse_json_callback), |
| 197 count_to_fetch_(0), | 212 count_to_fetch_(0), |
| 198 fetch_url_(GetFetchEndpoint()), | 213 fetch_url_(GetFetchEndpoint()), |
| 199 fetch_api_(UsesChromeContentSuggestionsAPI(fetch_url_) | 214 fetch_api_(UsesChromeContentSuggestionsAPI(fetch_url_) |
| 200 ? CHROME_CONTENT_SUGGESTIONS_API | 215 ? CHROME_CONTENT_SUGGESTIONS_API |
| 201 : CHROME_READER_API), | 216 : CHROME_READER_API), |
| 202 api_key_(api_key), | 217 api_key_(api_key), |
| 203 interactive_request_(false), | 218 interactive_request_(false), |
| 204 tick_clock_(new base::DefaultTickClock()), | 219 tick_clock_(new base::DefaultTickClock()), |
| 205 request_throttler_( | 220 user_classifier_(user_classifier), |
| 221 request_throttler_rare_ntp_user_( |
| 206 pref_service, | 222 pref_service, |
| 207 RequestThrottler::RequestType::CONTENT_SUGGESTION_FETCHER), | 223 RequestThrottler::RequestType:: |
| 224 CONTENT_SUGGESTION_FETCHER_RARE_NTP_USER), |
| 225 request_throttler_active_ntp_user_( |
| 226 pref_service, |
| 227 RequestThrottler::RequestType:: |
| 228 CONTENT_SUGGESTION_FETCHER_ACTIVE_NTP_USER), |
| 229 request_throttler_active_suggestions_consumer_( |
| 230 pref_service, |
| 231 RequestThrottler::RequestType:: |
| 232 CONTENT_SUGGESTION_FETCHER_ACTIVE_SUGGESTIONS_CONSUMER), |
| 208 oauth_token_retried_(false), | 233 oauth_token_retried_(false), |
| 209 weak_ptr_factory_(this) { | 234 weak_ptr_factory_(this) { |
| 210 // Parse the variation parameters and set the defaults if missing. | 235 // Parse the variation parameters and set the defaults if missing. |
| 211 std::string personalization = variations::GetVariationParamValue( | 236 std::string personalization = variations::GetVariationParamValue( |
| 212 ntp_snippets::kStudyName, kPersonalizationName); | 237 ntp_snippets::kStudyName, kPersonalizationName); |
| 213 if (personalization == kPersonalizationNonPersonalString) { | 238 if (personalization == kPersonalizationNonPersonalString) { |
| 214 personalization_ = Personalization::kNonPersonal; | 239 personalization_ = Personalization::kNonPersonal; |
| 215 } else if (personalization == kPersonalizationPersonalString) { | 240 } else if (personalization == kPersonalizationPersonalString) { |
| 216 personalization_ = Personalization::kPersonal; | 241 personalization_ = Personalization::kPersonal; |
| 217 } else { | 242 } else { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 232 const SnippetsAvailableCallback& callback) { | 257 const SnippetsAvailableCallback& callback) { |
| 233 snippets_available_callback_ = callback; | 258 snippets_available_callback_ = callback; |
| 234 } | 259 } |
| 235 | 260 |
| 236 void NTPSnippetsFetcher::FetchSnippetsFromHosts( | 261 void NTPSnippetsFetcher::FetchSnippetsFromHosts( |
| 237 const std::set<std::string>& hosts, | 262 const std::set<std::string>& hosts, |
| 238 const std::string& language_code, | 263 const std::string& language_code, |
| 239 const std::set<std::string>& excluded_ids, | 264 const std::set<std::string>& excluded_ids, |
| 240 int count, | 265 int count, |
| 241 bool interactive_request) { | 266 bool interactive_request) { |
| 242 if (!request_throttler_.DemandQuotaForRequest(interactive_request)) { | 267 if (!DemandQuotaForRequest(interactive_request)) { |
| 243 FetchFinished(OptionalFetchedCategories(), | 268 FetchFinished(OptionalFetchedCategories(), |
| 244 interactive_request | 269 interactive_request |
| 245 ? FetchResult::INTERACTIVE_QUOTA_ERROR | 270 ? FetchResult::INTERACTIVE_QUOTA_ERROR |
| 246 : FetchResult::NON_INTERACTIVE_QUOTA_ERROR, | 271 : FetchResult::NON_INTERACTIVE_QUOTA_ERROR, |
| 247 /*extra_message=*/std::string()); | 272 /*extra_message=*/std::string()); |
| 248 return; | 273 return; |
| 249 } | 274 } |
| 250 | 275 |
| 251 hosts_ = hosts; | 276 hosts_ = hosts; |
| 252 fetch_start_time_ = tick_clock_->NowTicks(); | 277 fetch_start_time_ = tick_clock_->NowTicks(); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 276 } | 301 } |
| 277 } | 302 } |
| 278 | 303 |
| 279 NTPSnippetsFetcher::RequestParams::RequestParams() | 304 NTPSnippetsFetcher::RequestParams::RequestParams() |
| 280 : fetch_api(), | 305 : fetch_api(), |
| 281 obfuscated_gaia_id(), | 306 obfuscated_gaia_id(), |
| 282 only_return_personalized_results(), | 307 only_return_personalized_results(), |
| 283 user_locale(), | 308 user_locale(), |
| 284 host_restricts(), | 309 host_restricts(), |
| 285 count_to_fetch(), | 310 count_to_fetch(), |
| 286 interactive_request() {} | 311 interactive_request(), |
| 312 user_class() {} |
| 287 | 313 |
| 288 NTPSnippetsFetcher::RequestParams::~RequestParams() = default; | 314 NTPSnippetsFetcher::RequestParams::~RequestParams() = default; |
| 289 | 315 |
| 290 std::string NTPSnippetsFetcher::RequestParams::BuildRequest() { | 316 std::string NTPSnippetsFetcher::RequestParams::BuildRequest() { |
| 291 auto request = base::MakeUnique<base::DictionaryValue>(); | 317 auto request = base::MakeUnique<base::DictionaryValue>(); |
| 292 switch (fetch_api) { | 318 switch (fetch_api) { |
| 293 case CHROME_READER_API: { | 319 case CHROME_READER_API: { |
| 294 auto content_params = base::MakeUnique<base::DictionaryValue>(); | 320 auto content_params = base::MakeUnique<base::DictionaryValue>(); |
| 295 content_params->SetBoolean("only_return_personalized_results", | 321 content_params->SetBoolean("only_return_personalized_results", |
| 296 only_return_personalized_results); | 322 only_return_personalized_results); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 351 ? "USER_ACTION" | 377 ? "USER_ACTION" |
| 352 : "BACKGROUND_PREFETCH"); | 378 : "BACKGROUND_PREFETCH"); |
| 353 | 379 |
| 354 auto excluded = base::MakeUnique<base::ListValue>(); | 380 auto excluded = base::MakeUnique<base::ListValue>(); |
| 355 for (const auto& id : excluded_ids) { | 381 for (const auto& id : excluded_ids) { |
| 356 excluded->AppendString(id); | 382 excluded->AppendString(id); |
| 357 if (excluded->GetSize() >= kMaxExcludedIds) | 383 if (excluded->GetSize() >= kMaxExcludedIds) |
| 358 break; | 384 break; |
| 359 } | 385 } |
| 360 request->Set("excludedSuggestionIds", std::move(excluded)); | 386 request->Set("excludedSuggestionIds", std::move(excluded)); |
| 387 request->SetString("user_activeness_class", user_class); |
| 361 | 388 |
| 362 // TODO(sfiera): support authentication and personalization | 389 // TODO(sfiera): support authentication and personalization |
| 363 // TODO(sfiera): support count_to_fetch | 390 // TODO(sfiera): support count_to_fetch |
| 364 break; | 391 break; |
| 365 } | 392 } |
| 366 } | 393 } |
| 367 | 394 |
| 368 std::string request_json; | 395 std::string request_json; |
| 369 bool success = base::JSONWriter::WriteWithOptions( | 396 bool success = base::JSONWriter::WriteWithOptions( |
| 370 *request, base::JSONWriter::OPTIONS_PRETTY_PRINT, &request_json); | 397 *request, base::JSONWriter::OPTIONS_PRETTY_PRINT, &request_json); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 432 RequestParams params; | 459 RequestParams params; |
| 433 params.fetch_api = fetch_api_; | 460 params.fetch_api = fetch_api_; |
| 434 params.obfuscated_gaia_id = account_id; | 461 params.obfuscated_gaia_id = account_id; |
| 435 params.only_return_personalized_results = | 462 params.only_return_personalized_results = |
| 436 personalization_ == Personalization::kPersonal; | 463 personalization_ == Personalization::kPersonal; |
| 437 params.user_locale = locale_; | 464 params.user_locale = locale_; |
| 438 params.host_restricts = hosts_; | 465 params.host_restricts = hosts_; |
| 439 params.excluded_ids = excluded_ids_; | 466 params.excluded_ids = excluded_ids_; |
| 440 params.count_to_fetch = count_to_fetch_; | 467 params.count_to_fetch = count_to_fetch_; |
| 441 params.interactive_request = interactive_request_; | 468 params.interactive_request = interactive_request_; |
| 469 params.user_class = GetUserClassString(user_classifier_->GetUserClass()); |
| 442 // TODO(jkrcal, treib): Add unit-tests for authenticated fetches. | 470 // TODO(jkrcal, treib): Add unit-tests for authenticated fetches. |
| 443 FetchSnippetsImpl(fetch_url_, | 471 FetchSnippetsImpl(fetch_url_, |
| 444 base::StringPrintf(kAuthorizationRequestHeaderFormat, | 472 base::StringPrintf(kAuthorizationRequestHeaderFormat, |
| 445 oauth_access_token.c_str()), | 473 oauth_access_token.c_str()), |
| 446 params.BuildRequest()); | 474 params.BuildRequest()); |
| 447 } | 475 } |
| 448 | 476 |
| 449 void NTPSnippetsFetcher::StartTokenRequest() { | 477 void NTPSnippetsFetcher::StartTokenRequest() { |
| 450 OAuth2TokenService::ScopeSet scopes; | 478 OAuth2TokenService::ScopeSet scopes; |
| 451 scopes.insert(fetch_api_ == CHROME_CONTENT_SUGGESTIONS_API | 479 scopes.insert(fetch_api_ == CHROME_CONTENT_SUGGESTIONS_API |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 635 } | 663 } |
| 636 UMA_HISTOGRAM_ENUMERATION("NewTabPage.Snippets.FetchResult", | 664 UMA_HISTOGRAM_ENUMERATION("NewTabPage.Snippets.FetchResult", |
| 637 static_cast<int>(result), | 665 static_cast<int>(result), |
| 638 static_cast<int>(FetchResult::RESULT_MAX)); | 666 static_cast<int>(FetchResult::RESULT_MAX)); |
| 639 | 667 |
| 640 DVLOG(1) << "Fetch finished: " << last_status_; | 668 DVLOG(1) << "Fetch finished: " << last_status_; |
| 641 if (!snippets_available_callback_.is_null()) | 669 if (!snippets_available_callback_.is_null()) |
| 642 snippets_available_callback_.Run(std::move(fetched_categories)); | 670 snippets_available_callback_.Run(std::move(fetched_categories)); |
| 643 } | 671 } |
| 644 | 672 |
| 673 bool NTPSnippetsFetcher::DemandQuotaForRequest(bool interactive_request) { |
| 674 switch (user_classifier_->GetUserClass()) { |
| 675 case UserClassifier::UserClass::RARE_NTP_USER: |
| 676 return request_throttler_rare_ntp_user_.DemandQuotaForRequest( |
| 677 interactive_request); |
| 678 case UserClassifier::UserClass::ACTIVE_NTP_USER: |
| 679 return request_throttler_active_ntp_user_.DemandQuotaForRequest( |
| 680 interactive_request); |
| 681 case UserClassifier::UserClass::ACTIVE_SUGGESTIONS_CONSUMER: |
| 682 return request_throttler_active_suggestions_consumer_ |
| 683 .DemandQuotaForRequest(interactive_request); |
| 684 } |
| 685 NOTREACHED(); |
| 686 return false; |
| 687 } |
| 688 |
| 645 } // namespace ntp_snippets | 689 } // namespace ntp_snippets |
| OLD | NEW |