| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/suggestions/suggestions_service_impl.h" | 5 #include "components/suggestions/suggestions_service_impl.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/feature_list.h" | 10 #include "base/feature_list.h" |
| 11 #include "base/location.h" | 11 #include "base/location.h" |
| 12 #include "base/memory/ptr_util.h" |
| 12 #include "base/metrics/histogram_macros.h" | 13 #include "base/metrics/histogram_macros.h" |
| 13 #include "base/metrics/sparse_histogram.h" | 14 #include "base/metrics/sparse_histogram.h" |
| 14 #include "base/strings/string_number_conversions.h" | 15 #include "base/strings/string_number_conversions.h" |
| 15 #include "base/strings/string_util.h" | 16 #include "base/strings/string_util.h" |
| 16 #include "base/strings/stringprintf.h" | 17 #include "base/strings/stringprintf.h" |
| 17 #include "base/threading/thread_task_runner_handle.h" | 18 #include "base/threading/thread_task_runner_handle.h" |
| 18 #include "build/build_config.h" | 19 #include "build/build_config.h" |
| 19 #include "components/data_use_measurement/core/data_use_user_data.h" | 20 #include "components/data_use_measurement/core/data_use_user_data.h" |
| 20 #include "components/google/core/browser/google_util.h" | 21 #include "components/google/core/browser/google_util.h" |
| 21 #include "components/pref_registry/pref_registry_syncable.h" | 22 #include "components/pref_registry/pref_registry_syncable.h" |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 129 const char kAuthorizationHeaderFormat[] = "Authorization: Bearer %s"; | 130 const char kAuthorizationHeaderFormat[] = "Authorization: Bearer %s"; |
| 130 | 131 |
| 131 const char kFaviconURL[] = | 132 const char kFaviconURL[] = |
| 132 "https://s2.googleusercontent.com/s2/favicons?domain_url=%s&alt=s&sz=32"; | 133 "https://s2.googleusercontent.com/s2/favicons?domain_url=%s&alt=s&sz=32"; |
| 133 | 134 |
| 134 // The default expiry timeout is 168 hours. | 135 // The default expiry timeout is 168 hours. |
| 135 const int64_t kDefaultExpiryUsec = 168 * base::Time::kMicrosecondsPerHour; | 136 const int64_t kDefaultExpiryUsec = 168 * base::Time::kMicrosecondsPerHour; |
| 136 | 137 |
| 137 } // namespace | 138 } // namespace |
| 138 | 139 |
| 139 // Helper class for fetching OAuth2 access tokens. | |
| 140 // To get a token, call |GetAccessToken|. Does not support multiple concurrent | |
| 141 // token requests, i.e. check |HasPendingRequest| first. | |
| 142 class SuggestionsServiceImpl::AccessTokenFetcher | |
| 143 : public OAuth2TokenService::Consumer { | |
| 144 public: | |
| 145 using TokenCallback = base::Callback<void(const std::string&)>; | |
| 146 | |
| 147 AccessTokenFetcher(const SigninManagerBase* signin_manager, | |
| 148 OAuth2TokenService* token_service) | |
| 149 : OAuth2TokenService::Consumer("suggestions_service"), | |
| 150 signin_manager_(signin_manager), | |
| 151 token_service_(token_service) {} | |
| 152 | |
| 153 void GetAccessToken(const TokenCallback& callback) { | |
| 154 callback_ = callback; | |
| 155 std::string account_id; | |
| 156 // |signin_manager_| can be null in unit tests. | |
| 157 if (signin_manager_) | |
| 158 account_id = signin_manager_->GetAuthenticatedAccountId(); | |
| 159 OAuth2TokenService::ScopeSet scopes; | |
| 160 scopes.insert(GaiaConstants::kChromeSyncOAuth2Scope); | |
| 161 token_request_ = token_service_->StartRequest(account_id, scopes, this); | |
| 162 } | |
| 163 | |
| 164 bool HasPendingRequest() const { return !!token_request_.get(); } | |
| 165 | |
| 166 private: | |
| 167 void OnGetTokenSuccess(const OAuth2TokenService::Request* request, | |
| 168 const std::string& access_token, | |
| 169 const base::Time& expiration_time) override { | |
| 170 DCHECK_EQ(request, token_request_.get()); | |
| 171 callback_.Run(access_token); | |
| 172 token_request_.reset(nullptr); | |
| 173 } | |
| 174 | |
| 175 void OnGetTokenFailure(const OAuth2TokenService::Request* request, | |
| 176 const GoogleServiceAuthError& error) override { | |
| 177 DCHECK_EQ(request, token_request_.get()); | |
| 178 LOG(WARNING) << "Token error: " << error.ToString(); | |
| 179 callback_.Run(std::string()); | |
| 180 token_request_.reset(nullptr); | |
| 181 } | |
| 182 | |
| 183 const SigninManagerBase* signin_manager_; | |
| 184 OAuth2TokenService* token_service_; | |
| 185 | |
| 186 TokenCallback callback_; | |
| 187 std::unique_ptr<OAuth2TokenService::Request> token_request_; | |
| 188 }; | |
| 189 | |
| 190 SuggestionsServiceImpl::SuggestionsServiceImpl( | 140 SuggestionsServiceImpl::SuggestionsServiceImpl( |
| 191 const SigninManagerBase* signin_manager, | 141 SigninManagerBase* signin_manager, |
| 192 OAuth2TokenService* token_service, | 142 OAuth2TokenService* token_service, |
| 193 syncer::SyncService* sync_service, | 143 syncer::SyncService* sync_service, |
| 194 net::URLRequestContextGetter* url_request_context, | 144 net::URLRequestContextGetter* url_request_context, |
| 195 std::unique_ptr<SuggestionsStore> suggestions_store, | 145 std::unique_ptr<SuggestionsStore> suggestions_store, |
| 196 std::unique_ptr<ImageManager> thumbnail_manager, | 146 std::unique_ptr<ImageManager> thumbnail_manager, |
| 197 std::unique_ptr<BlacklistStore> blacklist_store) | 147 std::unique_ptr<BlacklistStore> blacklist_store) |
| 198 : sync_service_(sync_service), | 148 : signin_manager_(signin_manager), |
| 149 token_service_(token_service), |
| 150 sync_service_(sync_service), |
| 199 sync_service_observer_(this), | 151 sync_service_observer_(this), |
| 200 url_request_context_(url_request_context), | 152 url_request_context_(url_request_context), |
| 201 suggestions_store_(std::move(suggestions_store)), | 153 suggestions_store_(std::move(suggestions_store)), |
| 202 thumbnail_manager_(std::move(thumbnail_manager)), | 154 thumbnail_manager_(std::move(thumbnail_manager)), |
| 203 blacklist_store_(std::move(blacklist_store)), | 155 blacklist_store_(std::move(blacklist_store)), |
| 204 scheduling_delay_(TimeDelta::FromSeconds(kDefaultSchedulingDelaySec)), | 156 scheduling_delay_(TimeDelta::FromSeconds(kDefaultSchedulingDelaySec)), |
| 205 token_fetcher_(new AccessTokenFetcher(signin_manager, token_service)), | |
| 206 weak_ptr_factory_(this) { | 157 weak_ptr_factory_(this) { |
| 207 // |sync_service_| is null if switches::kDisableSync is set (tests use that). | 158 // |sync_service_| is null if switches::kDisableSync is set (tests use that). |
| 208 if (sync_service_) | 159 if (sync_service_) |
| 209 sync_service_observer_.Add(sync_service_); | 160 sync_service_observer_.Add(sync_service_); |
| 210 // Immediately get the current sync state, so we'll flush the cache if | 161 // Immediately get the current sync state, so we'll flush the cache if |
| 211 // necessary. | 162 // necessary. |
| 212 OnStateChanged(); | 163 OnStateChanged(); |
| 213 } | 164 } |
| 214 | 165 |
| 215 SuggestionsServiceImpl::~SuggestionsServiceImpl() {} | 166 SuggestionsServiceImpl::~SuggestionsServiceImpl() {} |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 380 } | 331 } |
| 381 } | 332 } |
| 382 } | 333 } |
| 383 | 334 |
| 384 void SuggestionsServiceImpl::IssueRequestIfNoneOngoing(const GURL& url) { | 335 void SuggestionsServiceImpl::IssueRequestIfNoneOngoing(const GURL& url) { |
| 385 // If there is an ongoing request, let it complete. | 336 // If there is an ongoing request, let it complete. |
| 386 if (pending_request_.get()) { | 337 if (pending_request_.get()) { |
| 387 return; | 338 return; |
| 388 } | 339 } |
| 389 // If there is an ongoing token request, also wait for that. | 340 // If there is an ongoing token request, also wait for that. |
| 390 if (token_fetcher_->HasPendingRequest()) { | 341 if (token_fetcher_) { |
| 391 return; | 342 return; |
| 392 } | 343 } |
| 393 token_fetcher_->GetAccessToken( | 344 |
| 394 base::Bind(&SuggestionsServiceImpl::IssueSuggestionsRequest, | 345 OAuth2TokenService::ScopeSet scopes{GaiaConstants::kChromeSyncOAuth2Scope}; |
| 395 base::Unretained(this), url)); | 346 token_fetcher_ = base::MakeUnique<AccessTokenFetcher>( |
| 347 "suggestions_service", signin_manager_, token_service_, scopes, |
| 348 base::BindOnce(&SuggestionsServiceImpl::AccessTokenAvailable, |
| 349 base::Unretained(this), url)); |
| 350 } |
| 351 |
| 352 void SuggestionsServiceImpl::AccessTokenAvailable( |
| 353 const GURL& url, |
| 354 const GoogleServiceAuthError& error, |
| 355 const std::string& access_token) { |
| 356 DCHECK(token_fetcher_); |
| 357 std::unique_ptr<AccessTokenFetcher> token_fetcher_deleter( |
| 358 std::move(token_fetcher_)); |
| 359 |
| 360 if (error.state() != GoogleServiceAuthError::NONE) { |
| 361 UpdateBlacklistDelay(false); |
| 362 ScheduleBlacklistUpload(); |
| 363 return; |
| 364 } |
| 365 |
| 366 DCHECK(!access_token.empty()); |
| 367 |
| 368 IssueSuggestionsRequest(url, access_token); |
| 396 } | 369 } |
| 397 | 370 |
| 398 void SuggestionsServiceImpl::IssueSuggestionsRequest( | 371 void SuggestionsServiceImpl::IssueSuggestionsRequest( |
| 399 const GURL& url, | 372 const GURL& url, |
| 400 const std::string& access_token) { | 373 const std::string& access_token) { |
| 401 if (access_token.empty()) { | 374 DCHECK(!access_token.empty()); |
| 402 UpdateBlacklistDelay(false); | |
| 403 ScheduleBlacklistUpload(); | |
| 404 return; | |
| 405 } | |
| 406 pending_request_ = CreateSuggestionsRequest(url, access_token); | 375 pending_request_ = CreateSuggestionsRequest(url, access_token); |
| 407 pending_request_->Start(); | 376 pending_request_->Start(); |
| 408 last_request_started_time_ = TimeTicks::Now(); | 377 last_request_started_time_ = TimeTicks::Now(); |
| 409 } | 378 } |
| 410 | 379 |
| 411 std::unique_ptr<net::URLFetcher> | 380 std::unique_ptr<net::URLFetcher> |
| 412 SuggestionsServiceImpl::CreateSuggestionsRequest( | 381 SuggestionsServiceImpl::CreateSuggestionsRequest( |
| 413 const GURL& url, | 382 const GURL& url, |
| 414 const std::string& access_token) { | 383 const std::string& access_token) { |
| 415 std::unique_ptr<net::URLFetcher> request = | 384 std::unique_ptr<net::URLFetcher> request = |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 558 scheduling_delay_ = TimeDelta::FromSeconds(kDefaultSchedulingDelaySec); | 527 scheduling_delay_ = TimeDelta::FromSeconds(kDefaultSchedulingDelaySec); |
| 559 } else { | 528 } else { |
| 560 TimeDelta candidate_delay = | 529 TimeDelta candidate_delay = |
| 561 scheduling_delay_ * kSchedulingBackoffMultiplier; | 530 scheduling_delay_ * kSchedulingBackoffMultiplier; |
| 562 if (candidate_delay < TimeDelta::FromSeconds(kSchedulingMaxDelaySec)) | 531 if (candidate_delay < TimeDelta::FromSeconds(kSchedulingMaxDelaySec)) |
| 563 scheduling_delay_ = candidate_delay; | 532 scheduling_delay_ = candidate_delay; |
| 564 } | 533 } |
| 565 } | 534 } |
| 566 | 535 |
| 567 } // namespace suggestions | 536 } // namespace suggestions |
| OLD | NEW |