Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(548)

Side by Side Diff: components/ntp_snippets/remote/ntp_snippets_fetcher.cc

Issue 2400133002: Sending LanguageModel info to suggestions server (Closed)
Patch Set: Zero initialization #2 Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/features.h"
25 #include "components/ntp_snippets/ntp_snippets_constants.h" 26 #include "components/ntp_snippets/ntp_snippets_constants.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"
36 #include "third_party/icu/source/common/unicode/uloc.h" 37 #include "third_party/icu/source/common/unicode/uloc.h"
37 #include "third_party/icu/source/common/unicode/utypes.h" 38 #include "third_party/icu/source/common/unicode/utypes.h"
38 39
39 using net::URLFetcher; 40 using net::URLFetcher;
40 using net::URLRequestContextGetter; 41 using net::URLRequestContextGetter;
41 using net::HttpRequestHeaders; 42 using net::HttpRequestHeaders;
42 using net::URLRequestStatus; 43 using net::URLRequestStatus;
44 using translate::LanguageModel;
43 45
44 namespace ntp_snippets { 46 namespace ntp_snippets {
45 47
46 namespace { 48 namespace {
47 49
48 const char kChromeReaderApiScope[] = 50 const char kChromeReaderApiScope[] =
49 "https://www.googleapis.com/auth/webhistory"; 51 "https://www.googleapis.com/auth/webhistory";
50 const char kContentSuggestionsApiScope[] = 52 const char kContentSuggestionsApiScope[] =
51 "https://www.googleapis.com/auth/chrome-content-suggestions"; 53 "https://www.googleapis.com/auth/chrome-content-suggestions";
52 const char kSnippetsServerNonAuthorizedFormat[] = "%s?key=%s"; 54 const char kSnippetsServerNonAuthorizedFormat[] = "%s?key=%s";
53 const char kAuthorizationRequestHeaderFormat[] = "Bearer %s"; 55 const char kAuthorizationRequestHeaderFormat[] = "Bearer %s";
54 56
55 // Variation parameter for personalizing fetching of snippets. 57 // Variation parameter for personalizing fetching of snippets.
56 const char kPersonalizationName[] = "fetching_personalization"; 58 const char kPersonalizationName[] = "fetching_personalization";
57 59
58 // Variation parameter for chrome-content-suggestions backend. 60 // Variation parameter for chrome-content-suggestions backend.
59 const char kContentSuggestionsBackend[] = "content_suggestions_backend"; 61 const char kContentSuggestionsBackend[] = "content_suggestions_backend";
60 62
61 // Constants for possible values of the "fetching_personalization" parameter. 63 // Constants for possible values of the "fetching_personalization" parameter.
62 const char kPersonalizationPersonalString[] = "personal"; 64 const char kPersonalizationPersonalString[] = "personal";
63 const char kPersonalizationNonPersonalString[] = "non_personal"; 65 const char kPersonalizationNonPersonalString[] = "non_personal";
64 const char kPersonalizationBothString[] = "both"; // the default value 66 const char kPersonalizationBothString[] = "both"; // the default value
65 67
66 const int kMaxExcludedIds = 100; 68 const int kMaxExcludedIds = 100;
67 69
70 // Variation parameter for sending LanguageModel info to the server.
71 const char kSendTopLanguagesName[] = "send_top_languages";
72 const char kSendTopLanguagesEnabled[] = "true";
73 const char kSendTopLanguagesDisabled[] = "false";
74
68 std::string FetchResultToString(NTPSnippetsFetcher::FetchResult result) { 75 std::string FetchResultToString(NTPSnippetsFetcher::FetchResult result) {
69 switch (result) { 76 switch (result) {
70 case NTPSnippetsFetcher::FetchResult::SUCCESS: 77 case NTPSnippetsFetcher::FetchResult::SUCCESS:
71 return "OK"; 78 return "OK";
72 case NTPSnippetsFetcher::FetchResult::DEPRECATED_EMPTY_HOSTS: 79 case NTPSnippetsFetcher::FetchResult::DEPRECATED_EMPTY_HOSTS:
73 return "Cannot fetch for empty hosts list."; 80 return "Cannot fetch for empty hosts list.";
74 case NTPSnippetsFetcher::FetchResult::URL_REQUEST_STATUS_ERROR: 81 case NTPSnippetsFetcher::FetchResult::URL_REQUEST_STATUS_ERROR:
75 return "URLRequestStatus error"; 82 return "URLRequestStatus error";
76 case NTPSnippetsFetcher::FetchResult::HTTP_ERROR: 83 case NTPSnippetsFetcher::FetchResult::HTTP_ERROR:
77 return "HTTP error"; 84 return "HTTP error";
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
110 NOTREACHED(); 117 NOTREACHED();
111 return true; 118 return true;
112 } 119 }
113 120
114 std::string GetFetchEndpoint() { 121 std::string GetFetchEndpoint() {
115 std::string endpoint = variations::GetVariationParamValue( 122 std::string endpoint = variations::GetVariationParamValue(
116 ntp_snippets::kStudyName, kContentSuggestionsBackend); 123 ntp_snippets::kStudyName, kContentSuggestionsBackend);
117 return endpoint.empty() ? kChromeReaderServer : endpoint; 124 return endpoint.empty() ? kChromeReaderServer : endpoint;
118 } 125 }
119 126
127 bool IsSendingTopLanguagesEnabled() {
128 std::string send_top_languages = variations::GetVariationParamValueByFeature(
129 ntp_snippets::kArticleSuggestionsFeature, kSendTopLanguagesName);
130 if (send_top_languages == kSendTopLanguagesEnabled)
131 return true;
132 if (!send_top_languages.empty() &&
133 send_top_languages != kSendTopLanguagesDisabled) {
134 LOG(WARNING) << "Invalid value \"" << send_top_languages
135 << "\" for variation parameter " << kSendTopLanguagesName;
136 }
137 return false;
138 }
139
120 bool UsesChromeContentSuggestionsAPI(const GURL& endpoint) { 140 bool UsesChromeContentSuggestionsAPI(const GURL& endpoint) {
121 if (endpoint == GURL(kChromeReaderServer)) 141 if (endpoint == GURL(kChromeReaderServer))
122 return false; 142 return false;
123 143
124 if (endpoint != GURL(kContentSuggestionsServer) && 144 if (endpoint != GURL(kContentSuggestionsServer) &&
125 endpoint != GURL(kContentSuggestionsDevServer) && 145 endpoint != GURL(kContentSuggestionsDevServer) &&
126 endpoint != GURL(kContentSuggestionsAlphaServer)) { 146 endpoint != GURL(kContentSuggestionsAlphaServer)) {
127 LOG(WARNING) << "Unknown value for " << kContentSuggestionsBackend << ": " 147 LOG(WARNING) << "Unknown value for " << kContentSuggestionsBackend << ": "
128 << "assuming chromecontentsuggestions-style API"; 148 << "assuming chromecontentsuggestions-style API";
129 } 149 }
(...skipping 26 matching lines...) Expand all
156 return true; 176 return true;
157 } 177 }
158 178
159 // Translate the BCP 47 |language_code| into a posix locale string. 179 // Translate the BCP 47 |language_code| into a posix locale string.
160 std::string PosixLocaleFromBCP47Language(const std::string& language_code) { 180 std::string PosixLocaleFromBCP47Language(const std::string& language_code) {
161 char locale[ULOC_FULLNAME_CAPACITY]; 181 char locale[ULOC_FULLNAME_CAPACITY];
162 UErrorCode error = U_ZERO_ERROR; 182 UErrorCode error = U_ZERO_ERROR;
163 // Translate the input to a posix locale. 183 // Translate the input to a posix locale.
164 uloc_forLanguageTag(language_code.c_str(), locale, ULOC_FULLNAME_CAPACITY, 184 uloc_forLanguageTag(language_code.c_str(), locale, ULOC_FULLNAME_CAPACITY,
165 nullptr, &error); 185 nullptr, &error);
166 DLOG_IF(WARNING, U_ZERO_ERROR != error) 186 if (error != U_ZERO_ERROR) {
167 << "Error in translating language code to a locale string: " << error; 187 DLOG(WARNING) << "Error in translating language code to a locale string: "
188 << error;
189 return std::string();
190 }
168 return locale; 191 return locale;
169 } 192 }
170 193
194 std::string ISO639FromPosixLocale(const std::string& locale) {
195 char language[ULOC_LANG_CAPACITY];
196 UErrorCode error = U_ZERO_ERROR;
197 uloc_getLanguage(locale.c_str(), language, ULOC_LANG_CAPACITY, &error);
198 if (error != U_ZERO_ERROR) {
199 DLOG(WARNING)
200 << "Error in translating locale string to a ISO639 language code: "
201 << error;
202 return std::string();
203 }
204 return language;
205 }
206
207 void AppendLanguageInfoToList(base::ListValue* list,
208 const LanguageModel::LanguageInfo& info) {
209 auto lang = base::MakeUnique<base::DictionaryValue>();
210 lang->SetString("language", info.language_code);
211 lang->SetDouble("frequency", info.frequency);
212 list->Append(std::move(lang));
213 }
214
171 } // namespace 215 } // namespace
172 216
173 NTPSnippetsFetcher::FetchedCategory::FetchedCategory(Category c) 217 NTPSnippetsFetcher::FetchedCategory::FetchedCategory(Category c)
174 : category(c) {} 218 : category(c) {}
175 219
176 NTPSnippetsFetcher::FetchedCategory::FetchedCategory(FetchedCategory&&) = 220 NTPSnippetsFetcher::FetchedCategory::FetchedCategory(FetchedCategory&&) =
177 default; 221 default;
178 NTPSnippetsFetcher::FetchedCategory::~FetchedCategory() = default; 222 NTPSnippetsFetcher::FetchedCategory::~FetchedCategory() = default;
179 NTPSnippetsFetcher::FetchedCategory& NTPSnippetsFetcher::FetchedCategory:: 223 NTPSnippetsFetcher::FetchedCategory& NTPSnippetsFetcher::FetchedCategory::
180 operator=(FetchedCategory&&) = default; 224 operator=(FetchedCategory&&) = default;
181 225
182 NTPSnippetsFetcher::NTPSnippetsFetcher( 226 NTPSnippetsFetcher::NTPSnippetsFetcher(
183 SigninManagerBase* signin_manager, 227 SigninManagerBase* signin_manager,
184 OAuth2TokenService* token_service, 228 OAuth2TokenService* token_service,
185 scoped_refptr<URLRequestContextGetter> url_request_context_getter, 229 scoped_refptr<URLRequestContextGetter> url_request_context_getter,
186 PrefService* pref_service, 230 PrefService* pref_service,
187 CategoryFactory* category_factory, 231 CategoryFactory* category_factory,
232 LanguageModel* language_model,
188 const ParseJSONCallback& parse_json_callback, 233 const ParseJSONCallback& parse_json_callback,
189 const std::string& api_key) 234 const std::string& api_key)
190 : OAuth2TokenService::Consumer("ntp_snippets"), 235 : OAuth2TokenService::Consumer("ntp_snippets"),
191 signin_manager_(signin_manager), 236 signin_manager_(signin_manager),
192 token_service_(token_service), 237 token_service_(token_service),
193 waiting_for_refresh_token_(false), 238 waiting_for_refresh_token_(false),
194 url_request_context_getter_(std::move(url_request_context_getter)), 239 url_request_context_getter_(std::move(url_request_context_getter)),
195 category_factory_(category_factory), 240 category_factory_(category_factory),
241 language_model_(language_model),
196 parse_json_callback_(parse_json_callback), 242 parse_json_callback_(parse_json_callback),
197 count_to_fetch_(0), 243 count_to_fetch_(0),
198 fetch_url_(GetFetchEndpoint()), 244 fetch_url_(GetFetchEndpoint()),
199 fetch_api_(UsesChromeContentSuggestionsAPI(fetch_url_) 245 fetch_api_(UsesChromeContentSuggestionsAPI(fetch_url_)
200 ? CHROME_CONTENT_SUGGESTIONS_API 246 ? CHROME_CONTENT_SUGGESTIONS_API
201 : CHROME_READER_API), 247 : CHROME_READER_API),
202 api_key_(api_key), 248 api_key_(api_key),
203 interactive_request_(false), 249 interactive_request_(false),
204 tick_clock_(new base::DefaultTickClock()), 250 tick_clock_(new base::DefaultTickClock()),
205 request_throttler_( 251 request_throttler_(
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
352 : "BACKGROUND_PREFETCH"); 398 : "BACKGROUND_PREFETCH");
353 399
354 auto excluded = base::MakeUnique<base::ListValue>(); 400 auto excluded = base::MakeUnique<base::ListValue>();
355 for (const auto& id : excluded_ids) { 401 for (const auto& id : excluded_ids) {
356 excluded->AppendString(id); 402 excluded->AppendString(id);
357 if (excluded->GetSize() >= kMaxExcludedIds) 403 if (excluded->GetSize() >= kMaxExcludedIds)
358 break; 404 break;
359 } 405 }
360 request->Set("excludedSuggestionIds", std::move(excluded)); 406 request->Set("excludedSuggestionIds", std::move(excluded));
361 407
408 if (ui_language.frequency == 0 && other_top_language.frequency == 0)
409 break;
410
411 auto language_list = base::MakeUnique<base::ListValue>();
412 if (ui_language.frequency > 0)
413 AppendLanguageInfoToList(language_list.get(), ui_language);
414 if (other_top_language.frequency > 0)
415 AppendLanguageInfoToList(language_list.get(), other_top_language);
416 request->Set("top_languages", std::move(language_list));
417
362 // TODO(sfiera): support authentication and personalization 418 // TODO(sfiera): support authentication and personalization
363 // TODO(sfiera): support count_to_fetch 419 // TODO(sfiera): support count_to_fetch
364 break; 420 break;
365 } 421 }
366 } 422 }
367 423
368 std::string request_json; 424 std::string request_json;
369 bool success = base::JSONWriter::WriteWithOptions( 425 bool success = base::JSONWriter::WriteWithOptions(
370 *request, base::JSONWriter::OPTIONS_PRETTY_PRINT, &request_json); 426 *request, base::JSONWriter::OPTIONS_PRETTY_PRINT, &request_json);
371 DCHECK(success); 427 DCHECK(success);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
404 // Try to make fetching the files bit more robust even with poor connection. 460 // Try to make fetching the files bit more robust even with poor connection.
405 url_fetcher_->SetMaxRetriesOn5xx(3); 461 url_fetcher_->SetMaxRetriesOn5xx(3);
406 url_fetcher_->Start(); 462 url_fetcher_->Start();
407 } 463 }
408 464
409 bool NTPSnippetsFetcher::UsesAuthentication() const { 465 bool NTPSnippetsFetcher::UsesAuthentication() const {
410 return (personalization_ == Personalization::kPersonal || 466 return (personalization_ == Personalization::kPersonal ||
411 personalization_ == Personalization::kBoth); 467 personalization_ == Personalization::kBoth);
412 } 468 }
413 469
470 void NTPSnippetsFetcher::SetUpCommonFetchingParameters(
471 RequestParams* params) const {
472 params->fetch_api = fetch_api_;
473 params->host_restricts = hosts_;
474 params->user_locale = locale_;
475 params->excluded_ids = excluded_ids_;
476 params->count_to_fetch = count_to_fetch_;
477 params->interactive_request = interactive_request_;
478 // TODO(jkrcal): add the initializers into the struct and remove it from here
479 // and from the unit-tests (building the request).
480 params->ui_language.frequency = 0;
481 params->other_top_language.frequency = 0;
482
483 // TODO(jkrcal): Add language model factory for iOS and add fakes to tests so
484 // that |language_model_| is never nullptr. Remove this check and add a DCHECK
485 // into the constructor.
486 if (!language_model_ || !IsSendingTopLanguagesEnabled())
487 return;
488
489 params->ui_language.language_code = ISO639FromPosixLocale(locale_);
490 params->ui_language.frequency =
491 language_model_->GetLanguageFrequency(params->ui_language.language_code);
492
493 std::vector<LanguageModel::LanguageInfo> top_languages =
494 language_model_->GetTopLanguages();
495 for (const LanguageModel::LanguageInfo& info : top_languages) {
496 if (info.language_code != params->ui_language.language_code) {
497 params->other_top_language = info;
498 break;
499 }
500 }
501 }
502
414 void NTPSnippetsFetcher::FetchSnippetsNonAuthenticated() { 503 void NTPSnippetsFetcher::FetchSnippetsNonAuthenticated() {
415 // When not providing OAuth token, we need to pass the Google API key. 504 // When not providing OAuth token, we need to pass the Google API key.
416 GURL url(base::StringPrintf(kSnippetsServerNonAuthorizedFormat, 505 GURL url(base::StringPrintf(kSnippetsServerNonAuthorizedFormat,
417 fetch_url_.spec().c_str(), api_key_.c_str())); 506 fetch_url_.spec().c_str(), api_key_.c_str()));
418 507
419 RequestParams params; 508 RequestParams params;
420 params.fetch_api = fetch_api_; 509 SetUpCommonFetchingParameters(&params);
421 params.host_restricts = hosts_;
422 params.excluded_ids = excluded_ids_;
423 params.count_to_fetch = count_to_fetch_;
424 params.interactive_request = interactive_request_;
425 params.user_locale = locale_;
426 FetchSnippetsImpl(url, std::string(), params.BuildRequest()); 510 FetchSnippetsImpl(url, std::string(), params.BuildRequest());
427 } 511 }
428 512
429 void NTPSnippetsFetcher::FetchSnippetsAuthenticated( 513 void NTPSnippetsFetcher::FetchSnippetsAuthenticated(
430 const std::string& account_id, 514 const std::string& account_id,
431 const std::string& oauth_access_token) { 515 const std::string& oauth_access_token) {
432 RequestParams params; 516 RequestParams params;
433 params.fetch_api = fetch_api_; 517 SetUpCommonFetchingParameters(&params);
434 params.obfuscated_gaia_id = account_id; 518 params.obfuscated_gaia_id = account_id;
435 params.only_return_personalized_results = 519 params.only_return_personalized_results =
436 personalization_ == Personalization::kPersonal; 520 personalization_ == Personalization::kPersonal;
437 params.user_locale = locale_;
438 params.host_restricts = hosts_;
439 params.excluded_ids = excluded_ids_;
440 params.count_to_fetch = count_to_fetch_;
441 params.interactive_request = interactive_request_;
442 // TODO(jkrcal, treib): Add unit-tests for authenticated fetches. 521 // TODO(jkrcal, treib): Add unit-tests for authenticated fetches.
443 FetchSnippetsImpl(fetch_url_, 522 FetchSnippetsImpl(fetch_url_,
444 base::StringPrintf(kAuthorizationRequestHeaderFormat, 523 base::StringPrintf(kAuthorizationRequestHeaderFormat,
445 oauth_access_token.c_str()), 524 oauth_access_token.c_str()),
446 params.BuildRequest()); 525 params.BuildRequest());
447 } 526 }
448 527
449 void NTPSnippetsFetcher::StartTokenRequest() { 528 void NTPSnippetsFetcher::StartTokenRequest() {
450 OAuth2TokenService::ScopeSet scopes; 529 OAuth2TokenService::ScopeSet scopes;
451 scopes.insert(fetch_api_ == CHROME_CONTENT_SUGGESTIONS_API 530 scopes.insert(fetch_api_ == CHROME_CONTENT_SUGGESTIONS_API
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
636 UMA_HISTOGRAM_ENUMERATION("NewTabPage.Snippets.FetchResult", 715 UMA_HISTOGRAM_ENUMERATION("NewTabPage.Snippets.FetchResult",
637 static_cast<int>(result), 716 static_cast<int>(result),
638 static_cast<int>(FetchResult::RESULT_MAX)); 717 static_cast<int>(FetchResult::RESULT_MAX));
639 718
640 DVLOG(1) << "Fetch finished: " << last_status_; 719 DVLOG(1) << "Fetch finished: " << last_status_;
641 if (!snippets_available_callback_.is_null()) 720 if (!snippets_available_callback_.is_null())
642 snippets_available_callback_.Run(std::move(fetched_categories)); 721 snippets_available_callback_.Run(std::move(fetched_categories));
643 } 722 }
644 723
645 } // namespace ntp_snippets 724 } // namespace ntp_snippets
OLDNEW
« no previous file with comments | « components/ntp_snippets/remote/ntp_snippets_fetcher.h ('k') | components/ntp_snippets/remote/ntp_snippets_fetcher_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698