Chromium Code Reviews| 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/ntp_snippets_fetcher.h" | 5 #include "components/ntp_snippets/ntp_snippets_fetcher.h" |
| 6 | 6 |
| 7 #include <stdlib.h> | 7 #include <stdlib.h> |
| 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" |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 41 namespace ntp_snippets { | 41 namespace ntp_snippets { |
| 42 | 42 |
| 43 namespace { | 43 namespace { |
| 44 | 44 |
| 45 const char kApiScope[] = "https://www.googleapis.com/auth/webhistory"; | 45 const char kApiScope[] = "https://www.googleapis.com/auth/webhistory"; |
| 46 const char kSnippetsServer[] = | 46 const char kSnippetsServer[] = |
| 47 "https://chromereader-pa.googleapis.com/v1/fetch"; | 47 "https://chromereader-pa.googleapis.com/v1/fetch"; |
| 48 const char kSnippetsServerNonAuthorizedFormat[] = "%s?key=%s"; | 48 const char kSnippetsServerNonAuthorizedFormat[] = "%s?key=%s"; |
| 49 const char kAuthorizationRequestHeaderFormat[] = "Bearer %s"; | 49 const char kAuthorizationRequestHeaderFormat[] = "Bearer %s"; |
| 50 | 50 |
| 51 // Variation parameter for the variant of fetching to use. | 51 // Variation parameter for personalizing fetching of snippets. |
| 52 const char kVariantName[] = "fetching_variant"; | 52 const char kPersonalizationName[] = "fetching_personalization"; |
| 53 // Variation parameter for setting whether to restrict to a passed set of hosts. | |
| 54 const char kHostRestrictionName[] = "fetching_host_restrict"; | |
| 53 | 55 |
| 54 // Constants listing possible values of the "fetching_variant" parameter. | 56 // Constants for possible values of the "fetching_personalization" parameter. |
| 55 const char kVariantRestrictedString[] = "restricted"; | 57 const char kPersonalizationPersonalString[] = "personal"; |
| 56 const char kVariantPersonalizedString[] = "personalized"; | 58 const char kPersonalizationNonPersonalString[] = "non_personal"; |
| 57 const char kVariantRestrictedPersonalizedString[] = "restricted_personalized"; | 59 const char kPersonalizationBothString[] = "both"; // the default value |
| 58 | 60 |
| 59 const char kRequestParameterFormat[] = | 61 // Constants for possible values of the "fetching_host_restrict" parameter. |
| 62 const char kHostRestrictionOnString[] = "on"; // the default value | |
| 63 const char kHostRestrictionOffString[] = "off"; | |
| 64 | |
| 65 const char kRequestFormat[] = | |
| 60 "{" | 66 "{" |
| 61 " \"response_detail_level\": \"STANDARD\"," | 67 " \"response_detail_level\": \"STANDARD\"," |
| 62 "%s" // If authenticated - an obfuscated Gaia ID will be inserted here. | 68 "%s" // If authenticated - an obfuscated Gaia ID will be inserted here. |
| 63 " \"advanced_options\": {" | 69 " \"advanced_options\": {" |
| 64 " \"local_scoring_params\": {" | 70 " \"local_scoring_params\": {" |
| 65 " \"content_params\": {" | 71 " \"content_params\": {" |
| 66 " \"only_return_personalized_results\": false" | 72 " \"only_return_personalized_results\": %s" |
| 67 "%s" // If authenticated - user segment (lang code) will be inserted here. | 73 "%s" // If authenticated - user segment (lang code) will be inserted here. |
| 68 " }," | 74 " }," |
| 69 " \"content_restricts\": [" | 75 " \"content_restricts\": [" |
| 70 " {" | 76 " {" |
| 71 " \"type\": \"METADATA\"," | 77 " \"type\": \"METADATA\"," |
| 72 " \"value\": \"TITLE\"" | 78 " \"value\": \"TITLE\"" |
| 73 " }," | 79 " }," |
| 74 " {" | 80 " {" |
| 75 " \"type\": \"METADATA\"," | 81 " \"type\": \"METADATA\"," |
| 76 " \"value\": \"SNIPPET\"" | 82 " \"value\": \"SNIPPET\"" |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 89 " }" | 95 " }" |
| 90 "}"; | 96 "}"; |
| 91 | 97 |
| 92 const char kGaiaIdFormat[] = " \"obfuscated_gaia_id\": \"%s\","; | 98 const char kGaiaIdFormat[] = " \"obfuscated_gaia_id\": \"%s\","; |
| 93 const char kUserSegmentFormat[] = " ,\"user_segment\": \"%s\""; | 99 const char kUserSegmentFormat[] = " ,\"user_segment\": \"%s\""; |
| 94 const char kHostRestrictFormat[] = | 100 const char kHostRestrictFormat[] = |
| 95 " {" | 101 " {" |
| 96 " \"type\": \"HOST_RESTRICT\"," | 102 " \"type\": \"HOST_RESTRICT\"," |
| 97 " \"value\": \"%s\"" | 103 " \"value\": \"%s\"" |
| 98 " }"; | 104 " }"; |
| 105 const char kTrueString[] = "true"; | |
| 106 const char kFalseString[] = "false"; | |
| 99 | 107 |
| 100 std::string FetchResultToString(NTPSnippetsFetcher::FetchResult result) { | 108 std::string FetchResultToString(NTPSnippetsFetcher::FetchResult result) { |
| 101 switch (result) { | 109 switch (result) { |
| 102 case NTPSnippetsFetcher::FetchResult::SUCCESS: | 110 case NTPSnippetsFetcher::FetchResult::SUCCESS: |
| 103 return "OK"; | 111 return "OK"; |
| 104 case NTPSnippetsFetcher::FetchResult::EMPTY_HOSTS: | 112 case NTPSnippetsFetcher::FetchResult::EMPTY_HOSTS: |
| 105 return "Cannot fetch for empty hosts list."; | 113 return "Cannot fetch for empty hosts list."; |
| 106 case NTPSnippetsFetcher::FetchResult::URL_REQUEST_STATUS_ERROR: | 114 case NTPSnippetsFetcher::FetchResult::URL_REQUEST_STATUS_ERROR: |
| 107 return "URLRequestStatus error"; | 115 return "URLRequestStatus error"; |
| 108 case NTPSnippetsFetcher::FetchResult::HTTP_ERROR: | 116 case NTPSnippetsFetcher::FetchResult::HTTP_ERROR: |
| 109 return "HTTP error"; | 117 return "HTTP error"; |
| 110 case NTPSnippetsFetcher::FetchResult::JSON_PARSE_ERROR: | 118 case NTPSnippetsFetcher::FetchResult::JSON_PARSE_ERROR: |
| 111 return "Received invalid JSON"; | 119 return "Received invalid JSON"; |
| 112 case NTPSnippetsFetcher::FetchResult::INVALID_SNIPPET_CONTENT_ERROR: | 120 case NTPSnippetsFetcher::FetchResult::INVALID_SNIPPET_CONTENT_ERROR: |
| 113 return "Invalid / empty list."; | 121 return "Invalid / empty list."; |
| 122 case NTPSnippetsFetcher::FetchResult::OAUTH_TOKEN_ERROR: | |
| 123 return "Error in obtaining an OAuth2 access token."; | |
| 114 case NTPSnippetsFetcher::FetchResult::RESULT_MAX: | 124 case NTPSnippetsFetcher::FetchResult::RESULT_MAX: |
| 115 break; | 125 break; |
| 116 } | 126 } |
| 117 NOTREACHED(); | 127 NOTREACHED(); |
| 118 return "Unknown error"; | 128 return "Unknown error"; |
| 119 } | 129 } |
| 120 | 130 |
| 131 std::string BuildRequest(const std::string& obfuscated_gaia_id, | |
| 132 bool only_return_personalized_results, | |
| 133 const std::string& user_segment, | |
| 134 const std::string& host_restricts, | |
| 135 int count_to_fetch) { | |
| 136 return base::StringPrintf( | |
| 137 kRequestFormat, obfuscated_gaia_id.c_str(), | |
| 138 only_return_personalized_results ? kTrueString : kFalseString, | |
| 139 user_segment.c_str(), host_restricts.c_str(), count_to_fetch); | |
| 140 } | |
| 141 | |
| 121 } // namespace | 142 } // namespace |
| 122 | 143 |
| 123 NTPSnippetsFetcher::NTPSnippetsFetcher( | 144 NTPSnippetsFetcher::NTPSnippetsFetcher( |
| 124 SigninManagerBase* signin_manager, | 145 SigninManagerBase* signin_manager, |
| 125 OAuth2TokenService* token_service, | 146 OAuth2TokenService* token_service, |
| 126 scoped_refptr<URLRequestContextGetter> url_request_context_getter, | 147 scoped_refptr<URLRequestContextGetter> url_request_context_getter, |
| 127 const ParseJSONCallback& parse_json_callback, | 148 const ParseJSONCallback& parse_json_callback, |
| 128 bool is_stable_channel) | 149 bool is_stable_channel) |
| 129 : OAuth2TokenService::Consumer("ntp_snippets"), | 150 : OAuth2TokenService::Consumer("ntp_snippets"), |
| 130 signin_manager_(signin_manager), | 151 signin_manager_(signin_manager), |
| 131 token_service_(token_service), | 152 token_service_(token_service), |
| 132 waiting_for_refresh_token_(false), | 153 waiting_for_refresh_token_(false), |
| 133 url_request_context_getter_(url_request_context_getter), | 154 url_request_context_getter_(url_request_context_getter), |
| 134 parse_json_callback_(parse_json_callback), | 155 parse_json_callback_(parse_json_callback), |
| 135 is_stable_channel_(is_stable_channel), | 156 is_stable_channel_(is_stable_channel), |
| 136 tick_clock_(new base::DefaultTickClock()), | 157 tick_clock_(new base::DefaultTickClock()), |
| 137 weak_ptr_factory_(this) { | 158 weak_ptr_factory_(this) { |
| 138 // Parse the variation parameters and set the defaults if missing. | 159 // Parse the variation parameters and set the defaults if missing. |
| 139 std::string variant = variations::GetVariationParamValue( | 160 std::string personalization = variations::GetVariationParamValue( |
| 140 ntp_snippets::kStudyName, kVariantName); | 161 ntp_snippets::kStudyName, kPersonalizationName); |
| 141 if (variant == kVariantRestrictedString) { | 162 if (personalization == kPersonalizationNonPersonalString) { |
| 142 variant_ = Variant::kRestricted; | 163 personalization_ = Personalization::kNonPersonal; |
| 143 } else if (variant == kVariantPersonalizedString) { | 164 } else if (personalization == kPersonalizationPersonalString) { |
| 144 variant_ = Variant::kPersonalized; | 165 personalization_ = Personalization::kPersonal; |
| 145 } else { | 166 } else { |
| 146 variant_ = Variant::kRestrictedPersonalized; | 167 personalization_ = Personalization::kBoth; |
| 147 LOG_IF(WARNING, | 168 LOG_IF(WARNING, !personalization.empty() && |
| 148 !variant.empty() && variant != kVariantRestrictedPersonalizedString) | 169 personalization != kPersonalizationBothString) |
| 149 << "Unknown fetching variant provided: " << variant; | 170 << "Unknown value for " << kPersonalizationName << ": " |
| 171 << personalization; | |
| 172 } | |
| 173 | |
| 174 std::string host_restriction = variations::GetVariationParamValue( | |
|
Marc Treib
2016/05/17 14:54:42
Post-commit comment: The non-host-restricted case
| |
| 175 ntp_snippets::kStudyName, kHostRestrictionName); | |
| 176 if (host_restriction == kHostRestrictionOffString) { | |
| 177 use_host_restriction_ = false; | |
| 178 } else { | |
| 179 use_host_restriction_ = true; | |
| 180 LOG_IF(WARNING, !host_restriction.empty() && | |
| 181 host_restriction != kHostRestrictionOnString) | |
| 182 << "Unknown value for " << kHostRestrictionName << ": " | |
| 183 << host_restriction; | |
| 150 } | 184 } |
| 151 } | 185 } |
| 152 | 186 |
| 153 NTPSnippetsFetcher::~NTPSnippetsFetcher() { | 187 NTPSnippetsFetcher::~NTPSnippetsFetcher() { |
| 154 if (waiting_for_refresh_token_) | 188 if (waiting_for_refresh_token_) |
| 155 token_service_->RemoveObserver(this); | 189 token_service_->RemoveObserver(this); |
| 156 } | 190 } |
| 157 | 191 |
| 158 void NTPSnippetsFetcher::SetCallback( | 192 void NTPSnippetsFetcher::SetCallback( |
| 159 const SnippetsAvailableCallback& callback) { | 193 const SnippetsAvailableCallback& callback) { |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 234 for (const std::string& host : hosts_) { | 268 for (const std::string& host : hosts_) { |
| 235 if (!host_restricts.empty()) | 269 if (!host_restricts.empty()) |
| 236 host_restricts.push_back(','); | 270 host_restricts.push_back(','); |
| 237 host_restricts += base::StringPrintf(kHostRestrictFormat, host.c_str()); | 271 host_restricts += base::StringPrintf(kHostRestrictFormat, host.c_str()); |
| 238 } | 272 } |
| 239 } | 273 } |
| 240 return host_restricts; | 274 return host_restricts; |
| 241 } | 275 } |
| 242 | 276 |
| 243 bool NTPSnippetsFetcher::UseHostRestriction() const { | 277 bool NTPSnippetsFetcher::UseHostRestriction() const { |
| 244 return (variant_ == Variant::kRestricted || | 278 return use_host_restriction_ && |
| 245 variant_ == Variant::kRestrictedPersonalized) && | |
| 246 !base::CommandLine::ForCurrentProcess()->HasSwitch( | 279 !base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 247 switches::kDontRestrict); | 280 switches::kDontRestrict); |
| 248 } | 281 } |
| 249 | 282 |
| 250 bool NTPSnippetsFetcher::UseAuthentication() const { | 283 bool NTPSnippetsFetcher::UseAuthentication() const { |
| 251 return (variant_ == Variant::kPersonalized || | 284 return (personalization_ == Personalization::kPersonal || |
| 252 variant_ == Variant::kRestrictedPersonalized); | 285 personalization_ == Personalization::kBoth); |
| 253 } | 286 } |
| 254 | 287 |
| 255 void NTPSnippetsFetcher::FetchSnippetsNonAuthenticated() { | 288 void NTPSnippetsFetcher::FetchSnippetsNonAuthenticated() { |
| 256 // When not providing OAuth token, we need to pass the Google API key. | 289 // When not providing OAuth token, we need to pass the Google API key. |
| 257 const std::string& key = is_stable_channel_ | 290 const std::string& key = is_stable_channel_ |
| 258 ? google_apis::GetAPIKey() | 291 ? google_apis::GetAPIKey() |
| 259 : google_apis::GetNonStableAPIKey(); | 292 : google_apis::GetNonStableAPIKey(); |
| 260 GURL url(base::StringPrintf(kSnippetsServerNonAuthorizedFormat, | 293 GURL url(base::StringPrintf(kSnippetsServerNonAuthorizedFormat, |
| 261 kSnippetsServer, key.c_str())); | 294 kSnippetsServer, key.c_str())); |
| 262 | 295 |
| 263 FetchSnippetsImpl( | 296 FetchSnippetsImpl(url, std::string(), |
| 264 url, std::string(), | 297 BuildRequest(/*obfuscated_gaia_id=*/std::string(), |
| 265 base::StringPrintf(kRequestParameterFormat, "", "", | 298 /*only_return_personalized_results=*/false, |
| 266 GetHostRestricts().c_str(), count_to_fetch_)); | 299 /*user_segment=*/std::string(), |
| 300 GetHostRestricts(), count_to_fetch_)); | |
| 267 } | 301 } |
| 268 | 302 |
| 269 void NTPSnippetsFetcher::FetchSnippetsAuthenticated( | 303 void NTPSnippetsFetcher::FetchSnippetsAuthenticated( |
| 270 const std::string& account_id, | 304 const std::string& account_id, |
| 271 const std::string& oauth_access_token) { | 305 const std::string& oauth_access_token) { |
| 272 std::string auth = base::StringPrintf(kGaiaIdFormat, account_id.c_str()); | 306 std::string gaia_id = base::StringPrintf(kGaiaIdFormat, account_id.c_str()); |
| 273 std::string user_segment = | 307 std::string user_segment = |
| 274 base::StringPrintf(kUserSegmentFormat, locale_.c_str()); | 308 base::StringPrintf(kUserSegmentFormat, locale_.c_str()); |
| 275 | 309 |
| 276 FetchSnippetsImpl( | 310 FetchSnippetsImpl( |
| 277 GURL(kSnippetsServer), | 311 GURL(kSnippetsServer), |
| 278 base::StringPrintf(kAuthorizationRequestHeaderFormat, | 312 base::StringPrintf(kAuthorizationRequestHeaderFormat, |
| 279 oauth_access_token.c_str()), | 313 oauth_access_token.c_str()), |
| 280 base::StringPrintf(kRequestParameterFormat, auth.c_str(), | 314 BuildRequest(gaia_id, personalization_ == Personalization::kPersonal, |
| 281 user_segment.c_str(), GetHostRestricts().c_str(), | 315 user_segment, GetHostRestricts(), count_to_fetch_)); |
| 282 count_to_fetch_)); | |
| 283 } | 316 } |
| 284 | 317 |
| 285 void NTPSnippetsFetcher::StartTokenRequest() { | 318 void NTPSnippetsFetcher::StartTokenRequest() { |
| 286 OAuth2TokenService::ScopeSet scopes; | 319 OAuth2TokenService::ScopeSet scopes; |
| 287 scopes.insert(kApiScope); | 320 scopes.insert(kApiScope); |
| 288 oauth_request_ = token_service_->StartRequest( | 321 oauth_request_ = token_service_->StartRequest( |
| 289 signin_manager_->GetAuthenticatedAccountId(), scopes, this); | 322 signin_manager_->GetAuthenticatedAccountId(), scopes, this); |
| 290 } | 323 } |
| 291 | 324 |
| 292 //////////////////////////////////////////////////////////////////////////////// | 325 //////////////////////////////////////////////////////////////////////////////// |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 303 | 336 |
| 304 FetchSnippetsAuthenticated(oauth_request->GetAccountId(), access_token); | 337 FetchSnippetsAuthenticated(oauth_request->GetAccountId(), access_token); |
| 305 } | 338 } |
| 306 | 339 |
| 307 void NTPSnippetsFetcher::OnGetTokenFailure( | 340 void NTPSnippetsFetcher::OnGetTokenFailure( |
| 308 const OAuth2TokenService::Request* request, | 341 const OAuth2TokenService::Request* request, |
| 309 const GoogleServiceAuthError& error) { | 342 const GoogleServiceAuthError& error) { |
| 310 oauth_request_.reset(); | 343 oauth_request_.reset(); |
| 311 DLOG(ERROR) << "Unable to get token: " << error.ToString() | 344 DLOG(ERROR) << "Unable to get token: " << error.ToString() |
| 312 << " - fetching the snippets without authentication."; | 345 << " - fetching the snippets without authentication."; |
| 313 | 346 FetchFinished( |
| 314 // Fallback to fetching non-authenticated tokens. | 347 OptionalSnippets(), FetchResult::OAUTH_TOKEN_ERROR, |
| 315 FetchSnippetsNonAuthenticated(); | 348 /*extra_message=*/base::StringPrintf(" (%s)", error.ToString().c_str())); |
| 316 } | 349 } |
| 317 | 350 |
| 318 //////////////////////////////////////////////////////////////////////////////// | 351 //////////////////////////////////////////////////////////////////////////////// |
| 319 // OAuth2TokenService::Observer overrides | 352 // OAuth2TokenService::Observer overrides |
| 320 void NTPSnippetsFetcher::OnRefreshTokenAvailable( | 353 void NTPSnippetsFetcher::OnRefreshTokenAvailable( |
| 321 const std::string& account_id) { | 354 const std::string& account_id) { |
| 322 // Only react on tokens for the account the user has signed in with. | 355 // Only react on tokens for the account the user has signed in with. |
| 323 if (account_id != signin_manager_->GetAuthenticatedAccountId()) | 356 if (account_id != signin_manager_->GetAuthenticatedAccountId()) |
| 324 return; | 357 return; |
| 325 | 358 |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 400 tick_clock_->NowTicks() - fetch_start_time_); | 433 tick_clock_->NowTicks() - fetch_start_time_); |
| 401 UMA_HISTOGRAM_ENUMERATION("NewTabPage.Snippets.FetchResult", | 434 UMA_HISTOGRAM_ENUMERATION("NewTabPage.Snippets.FetchResult", |
| 402 static_cast<int>(result), | 435 static_cast<int>(result), |
| 403 static_cast<int>(FetchResult::RESULT_MAX)); | 436 static_cast<int>(FetchResult::RESULT_MAX)); |
| 404 | 437 |
| 405 if (!snippets_available_callback_.is_null()) | 438 if (!snippets_available_callback_.is_null()) |
| 406 snippets_available_callback_.Run(std::move(snippets)); | 439 snippets_available_callback_.Run(std::move(snippets)); |
| 407 } | 440 } |
| 408 | 441 |
| 409 } // namespace ntp_snippets | 442 } // namespace ntp_snippets |
| OLD | NEW |