| Index: components/suggestions/suggestions_service.cc
|
| diff --git a/components/suggestions/suggestions_service.cc b/components/suggestions/suggestions_service.cc
|
| deleted file mode 100644
|
| index 47072e811b4356c16219bc1bccad12bbd57368ba..0000000000000000000000000000000000000000
|
| --- a/components/suggestions/suggestions_service.cc
|
| +++ /dev/null
|
| @@ -1,558 +0,0 @@
|
| -// Copyright 2014 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "components/suggestions/suggestions_service.h"
|
| -
|
| -#include <memory>
|
| -#include <utility>
|
| -
|
| -#include "base/feature_list.h"
|
| -#include "base/location.h"
|
| -#include "base/metrics/histogram_macros.h"
|
| -#include "base/metrics/sparse_histogram.h"
|
| -#include "base/strings/string_number_conversions.h"
|
| -#include "base/strings/string_util.h"
|
| -#include "base/strings/stringprintf.h"
|
| -#include "base/threading/thread_task_runner_handle.h"
|
| -#include "build/build_config.h"
|
| -#include "components/data_use_measurement/core/data_use_user_data.h"
|
| -#include "components/google/core/browser/google_util.h"
|
| -#include "components/pref_registry/pref_registry_syncable.h"
|
| -#include "components/signin/core/browser/signin_manager_base.h"
|
| -#include "components/suggestions/blacklist_store.h"
|
| -#include "components/suggestions/image_manager.h"
|
| -#include "components/suggestions/suggestions_store.h"
|
| -#include "components/sync/driver/sync_service.h"
|
| -#include "components/variations/net/variations_http_headers.h"
|
| -#include "google_apis/gaia/gaia_constants.h"
|
| -#include "google_apis/gaia/oauth2_token_service.h"
|
| -#include "net/base/escape.h"
|
| -#include "net/base/load_flags.h"
|
| -#include "net/base/net_errors.h"
|
| -#include "net/base/url_util.h"
|
| -#include "net/http/http_response_headers.h"
|
| -#include "net/http/http_status_code.h"
|
| -#include "net/http/http_util.h"
|
| -#include "net/url_request/url_fetcher.h"
|
| -#include "net/url_request/url_request_status.h"
|
| -
|
| -using base::TimeDelta;
|
| -using base::TimeTicks;
|
| -
|
| -namespace suggestions {
|
| -
|
| -namespace {
|
| -
|
| -// Establishes the different sync states that matter to SuggestionsService.
|
| -// There are three different concepts in the sync service: initialized, sync
|
| -// enabled and history sync enabled.
|
| -enum SyncState {
|
| - // State: Sync service is not initialized, yet not disabled. History sync
|
| - // state is unknown (since not initialized).
|
| - // Behavior: Does not issue a server request, but serves from cache if
|
| - // available.
|
| - NOT_INITIALIZED_ENABLED,
|
| -
|
| - // State: Sync service is initialized, sync is enabled and history sync is
|
| - // enabled.
|
| - // Behavior: Update suggestions from the server. Serve from cache on timeout.
|
| - INITIALIZED_ENABLED_HISTORY,
|
| -
|
| - // State: Sync service is disabled or history sync is disabled.
|
| - // Behavior: Do not issue a server request. Clear the cache. Serve empty
|
| - // suggestions.
|
| - SYNC_OR_HISTORY_SYNC_DISABLED,
|
| -};
|
| -
|
| -SyncState GetSyncState(syncer::SyncService* sync) {
|
| - if (!sync || !sync->CanSyncStart())
|
| - return SYNC_OR_HISTORY_SYNC_DISABLED;
|
| - if (!sync->IsSyncActive() || !sync->ConfigurationDone())
|
| - return NOT_INITIALIZED_ENABLED;
|
| - return sync->GetActiveDataTypes().Has(syncer::HISTORY_DELETE_DIRECTIVES)
|
| - ? INITIALIZED_ENABLED_HISTORY
|
| - : SYNC_OR_HISTORY_SYNC_DISABLED;
|
| -}
|
| -
|
| -// Used to UMA log the state of the last response from the server.
|
| -enum SuggestionsResponseState {
|
| - RESPONSE_EMPTY,
|
| - RESPONSE_INVALID,
|
| - RESPONSE_VALID,
|
| - RESPONSE_STATE_SIZE
|
| -};
|
| -
|
| -// Will log the supplied response |state|.
|
| -void LogResponseState(SuggestionsResponseState state) {
|
| - UMA_HISTOGRAM_ENUMERATION("Suggestions.ResponseState", state,
|
| - RESPONSE_STATE_SIZE);
|
| -}
|
| -
|
| -// Default delay used when scheduling a request.
|
| -const int kDefaultSchedulingDelaySec = 1;
|
| -
|
| -// Multiplier on the delay used when re-scheduling a failed request.
|
| -const int kSchedulingBackoffMultiplier = 2;
|
| -
|
| -// Maximum valid delay for scheduling a request. Candidate delays larger than
|
| -// this are rejected. This means the maximum backoff is at least 5 / 2 minutes.
|
| -const int kSchedulingMaxDelaySec = 5 * 60;
|
| -
|
| -const char kDefaultGoogleBaseURL[] = "https://www.google.com/";
|
| -
|
| -GURL GetGoogleBaseURL() {
|
| - GURL url(google_util::CommandLineGoogleBaseURL());
|
| - if (url.is_valid())
|
| - return url;
|
| - return GURL(kDefaultGoogleBaseURL);
|
| -}
|
| -
|
| -// Format strings for the various suggestions URLs. They all have two string
|
| -// params: The Google base URL and the device type.
|
| -// TODO(mathp): Put this in TemplateURL.
|
| -const char kSuggestionsURLFormat[] =
|
| - "%schromesuggestions?t=%s";
|
| -const char kSuggestionsBlacklistURLPrefixFormat[] =
|
| - "%schromesuggestions/blacklist?t=%s&url=";
|
| -const char kSuggestionsBlacklistClearURLFormat[] =
|
| - "%schromesuggestions/blacklist/clear?t=%s";
|
| -
|
| -const char kSuggestionsBlacklistURLParam[] = "url";
|
| -
|
| -#if defined(OS_ANDROID) || defined(OS_IOS)
|
| -const char kDeviceType[] = "2";
|
| -#else
|
| -const char kDeviceType[] = "1";
|
| -#endif
|
| -
|
| -// Format string for OAuth2 authentication headers.
|
| -const char kAuthorizationHeaderFormat[] = "Authorization: Bearer %s";
|
| -
|
| -const char kFaviconURL[] =
|
| - "https://s2.googleusercontent.com/s2/favicons?domain_url=%s&alt=s&sz=32";
|
| -
|
| -// The default expiry timeout is 168 hours.
|
| -const int64_t kDefaultExpiryUsec = 168 * base::Time::kMicrosecondsPerHour;
|
| -
|
| -} // namespace
|
| -
|
| -// Helper class for fetching OAuth2 access tokens.
|
| -// To get a token, call |GetAccessToken|. Does not support multiple concurrent
|
| -// token requests, i.e. check |HasPendingRequest| first.
|
| -class SuggestionsService::AccessTokenFetcher
|
| - : public OAuth2TokenService::Consumer {
|
| - public:
|
| - using TokenCallback = base::Callback<void(const std::string&)>;
|
| -
|
| - AccessTokenFetcher(const SigninManagerBase* signin_manager,
|
| - OAuth2TokenService* token_service)
|
| - : OAuth2TokenService::Consumer("suggestions_service"),
|
| - signin_manager_(signin_manager),
|
| - token_service_(token_service) {}
|
| -
|
| - void GetAccessToken(const TokenCallback& callback) {
|
| - callback_ = callback;
|
| - std::string account_id;
|
| - // |signin_manager_| can be null in unit tests.
|
| - if (signin_manager_)
|
| - account_id = signin_manager_->GetAuthenticatedAccountId();
|
| - OAuth2TokenService::ScopeSet scopes;
|
| - scopes.insert(GaiaConstants::kChromeSyncOAuth2Scope);
|
| - token_request_ = token_service_->StartRequest(account_id, scopes, this);
|
| - }
|
| -
|
| - bool HasPendingRequest() const {
|
| - return !!token_request_.get();
|
| - }
|
| -
|
| - private:
|
| - void OnGetTokenSuccess(const OAuth2TokenService::Request* request,
|
| - const std::string& access_token,
|
| - const base::Time& expiration_time) override {
|
| - DCHECK_EQ(request, token_request_.get());
|
| - callback_.Run(access_token);
|
| - token_request_.reset(nullptr);
|
| - }
|
| -
|
| - void OnGetTokenFailure(const OAuth2TokenService::Request* request,
|
| - const GoogleServiceAuthError& error) override {
|
| - DCHECK_EQ(request, token_request_.get());
|
| - LOG(WARNING) << "Token error: " << error.ToString();
|
| - callback_.Run(std::string());
|
| - token_request_.reset(nullptr);
|
| - }
|
| -
|
| - const SigninManagerBase* signin_manager_;
|
| - OAuth2TokenService* token_service_;
|
| -
|
| - TokenCallback callback_;
|
| - std::unique_ptr<OAuth2TokenService::Request> token_request_;
|
| -};
|
| -
|
| -SuggestionsService::SuggestionsService(
|
| - const SigninManagerBase* signin_manager,
|
| - OAuth2TokenService* token_service,
|
| - syncer::SyncService* sync_service,
|
| - net::URLRequestContextGetter* url_request_context,
|
| - std::unique_ptr<SuggestionsStore> suggestions_store,
|
| - std::unique_ptr<ImageManager> thumbnail_manager,
|
| - std::unique_ptr<BlacklistStore> blacklist_store)
|
| - : sync_service_(sync_service),
|
| - sync_service_observer_(this),
|
| - url_request_context_(url_request_context),
|
| - suggestions_store_(std::move(suggestions_store)),
|
| - thumbnail_manager_(std::move(thumbnail_manager)),
|
| - blacklist_store_(std::move(blacklist_store)),
|
| - scheduling_delay_(TimeDelta::FromSeconds(kDefaultSchedulingDelaySec)),
|
| - token_fetcher_(new AccessTokenFetcher(signin_manager, token_service)),
|
| - weak_ptr_factory_(this) {
|
| - // |sync_service_| is null if switches::kDisableSync is set (tests use that).
|
| - if (sync_service_)
|
| - sync_service_observer_.Add(sync_service_);
|
| - // Immediately get the current sync state, so we'll flush the cache if
|
| - // necessary.
|
| - OnStateChanged();
|
| -}
|
| -
|
| -SuggestionsService::~SuggestionsService() {}
|
| -
|
| -bool SuggestionsService::FetchSuggestionsData() {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| - // If sync state allows, issue a network request to refresh the suggestions.
|
| - if (GetSyncState(sync_service_) != INITIALIZED_ENABLED_HISTORY)
|
| - return false;
|
| - IssueRequestIfNoneOngoing(BuildSuggestionsURL());
|
| - return true;
|
| -}
|
| -
|
| -SuggestionsProfile SuggestionsService::GetSuggestionsDataFromCache() const {
|
| - SuggestionsProfile suggestions;
|
| - // In case of empty cache or error, |suggestions| stays empty.
|
| - suggestions_store_->LoadSuggestions(&suggestions);
|
| - thumbnail_manager_->Initialize(suggestions);
|
| - blacklist_store_->FilterSuggestions(&suggestions);
|
| - return suggestions;
|
| -}
|
| -
|
| -std::unique_ptr<SuggestionsService::ResponseCallbackList::Subscription>
|
| -SuggestionsService::AddCallback(const ResponseCallback& callback) {
|
| - return callback_list_.Add(callback);
|
| -}
|
| -
|
| -void SuggestionsService::GetPageThumbnail(const GURL& url,
|
| - const BitmapCallback& callback) {
|
| - thumbnail_manager_->GetImageForURL(url, callback);
|
| -}
|
| -
|
| -void SuggestionsService::GetPageThumbnailWithURL(
|
| - const GURL& url,
|
| - const GURL& thumbnail_url,
|
| - const BitmapCallback& callback) {
|
| - thumbnail_manager_->AddImageURL(url, thumbnail_url);
|
| - GetPageThumbnail(url, callback);
|
| -}
|
| -
|
| -bool SuggestionsService::BlacklistURL(const GURL& candidate_url) {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| -
|
| - if (!blacklist_store_->BlacklistUrl(candidate_url))
|
| - return false;
|
| -
|
| - callback_list_.Notify(GetSuggestionsDataFromCache());
|
| -
|
| - // Blacklist uploads are scheduled on any request completion, so only schedule
|
| - // an upload if there is no ongoing request.
|
| - if (!pending_request_.get())
|
| - ScheduleBlacklistUpload();
|
| -
|
| - return true;
|
| -}
|
| -
|
| -bool SuggestionsService::UndoBlacklistURL(const GURL& url) {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| - TimeDelta time_delta;
|
| - if (blacklist_store_->GetTimeUntilURLReadyForUpload(url, &time_delta) &&
|
| - time_delta > TimeDelta::FromSeconds(0) &&
|
| - blacklist_store_->RemoveUrl(url)) {
|
| - // The URL was not yet candidate for upload to the server and could be
|
| - // removed from the blacklist.
|
| - callback_list_.Notify(GetSuggestionsDataFromCache());
|
| - return true;
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -void SuggestionsService::ClearBlacklist() {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| - blacklist_store_->ClearBlacklist();
|
| - callback_list_.Notify(GetSuggestionsDataFromCache());
|
| - IssueRequestIfNoneOngoing(BuildSuggestionsBlacklistClearURL());
|
| -}
|
| -
|
| -// static
|
| -bool SuggestionsService::GetBlacklistedUrl(const net::URLFetcher& request,
|
| - GURL* url) {
|
| - bool is_blacklist_request = base::StartsWith(
|
| - request.GetOriginalURL().spec(), BuildSuggestionsBlacklistURLPrefix(),
|
| - base::CompareCase::SENSITIVE);
|
| - if (!is_blacklist_request) return false;
|
| -
|
| - // Extract the blacklisted URL from the blacklist request.
|
| - std::string blacklisted;
|
| - if (!net::GetValueForKeyInQuery(
|
| - request.GetOriginalURL(),
|
| - kSuggestionsBlacklistURLParam,
|
| - &blacklisted)) {
|
| - return false;
|
| - }
|
| -
|
| - GURL blacklisted_url(blacklisted);
|
| - blacklisted_url.Swap(url);
|
| - return true;
|
| -}
|
| -
|
| -// static
|
| -void SuggestionsService::RegisterProfilePrefs(
|
| - user_prefs::PrefRegistrySyncable* registry) {
|
| - SuggestionsStore::RegisterProfilePrefs(registry);
|
| - BlacklistStore::RegisterProfilePrefs(registry);
|
| -}
|
| -
|
| -// static
|
| -GURL SuggestionsService::BuildSuggestionsURL() {
|
| - return GURL(base::StringPrintf(kSuggestionsURLFormat,
|
| - GetGoogleBaseURL().spec().c_str(),
|
| - kDeviceType));
|
| -}
|
| -
|
| -// static
|
| -std::string SuggestionsService::BuildSuggestionsBlacklistURLPrefix() {
|
| - return base::StringPrintf(kSuggestionsBlacklistURLPrefixFormat,
|
| - GetGoogleBaseURL().spec().c_str(), kDeviceType);
|
| -}
|
| -
|
| -// static
|
| -GURL SuggestionsService::BuildSuggestionsBlacklistURL(
|
| - const GURL& candidate_url) {
|
| - return GURL(BuildSuggestionsBlacklistURLPrefix() +
|
| - net::EscapeQueryParamValue(candidate_url.spec(), true));
|
| -}
|
| -
|
| -// static
|
| -GURL SuggestionsService::BuildSuggestionsBlacklistClearURL() {
|
| - return GURL(base::StringPrintf(kSuggestionsBlacklistClearURLFormat,
|
| - GetGoogleBaseURL().spec().c_str(),
|
| - kDeviceType));
|
| -}
|
| -
|
| -void SuggestionsService::OnStateChanged() {
|
| - switch (GetSyncState(sync_service_)) {
|
| - case SYNC_OR_HISTORY_SYNC_DISABLED:
|
| - // Cancel any ongoing request, to stop interacting with the server.
|
| - pending_request_.reset(nullptr);
|
| - suggestions_store_->ClearSuggestions();
|
| - callback_list_.Notify(SuggestionsProfile());
|
| - break;
|
| - case NOT_INITIALIZED_ENABLED:
|
| - // Keep the cache (if any), but don't refresh.
|
| - break;
|
| - case INITIALIZED_ENABLED_HISTORY:
|
| - // If we have any observers, issue a network request to refresh the
|
| - // suggestions in the cache.
|
| - if (!callback_list_.empty())
|
| - IssueRequestIfNoneOngoing(BuildSuggestionsURL());
|
| - break;
|
| - }
|
| -}
|
| -
|
| -void SuggestionsService::SetDefaultExpiryTimestamp(
|
| - SuggestionsProfile* suggestions,
|
| - int64_t default_timestamp_usec) {
|
| - for (int i = 0; i < suggestions->suggestions_size(); ++i) {
|
| - ChromeSuggestion* suggestion = suggestions->mutable_suggestions(i);
|
| - // Do not set expiry if the server has already provided a more specific
|
| - // expiry time for this suggestion.
|
| - if (!suggestion->has_expiry_ts()) {
|
| - suggestion->set_expiry_ts(default_timestamp_usec);
|
| - }
|
| - }
|
| -}
|
| -
|
| -void SuggestionsService::IssueRequestIfNoneOngoing(const GURL& url) {
|
| - // If there is an ongoing request, let it complete.
|
| - if (pending_request_.get()) {
|
| - return;
|
| - }
|
| - // If there is an ongoing token request, also wait for that.
|
| - if (token_fetcher_->HasPendingRequest()) {
|
| - return;
|
| - }
|
| - token_fetcher_->GetAccessToken(
|
| - base::Bind(&SuggestionsService::IssueSuggestionsRequest,
|
| - base::Unretained(this), url));
|
| -}
|
| -
|
| -void SuggestionsService::IssueSuggestionsRequest(
|
| - const GURL& url,
|
| - const std::string& access_token) {
|
| - if (access_token.empty()) {
|
| - UpdateBlacklistDelay(false);
|
| - ScheduleBlacklistUpload();
|
| - return;
|
| - }
|
| - pending_request_ = CreateSuggestionsRequest(url, access_token);
|
| - pending_request_->Start();
|
| - last_request_started_time_ = TimeTicks::Now();
|
| -}
|
| -
|
| -std::unique_ptr<net::URLFetcher> SuggestionsService::CreateSuggestionsRequest(
|
| - const GURL& url,
|
| - const std::string& access_token) {
|
| - std::unique_ptr<net::URLFetcher> request =
|
| - net::URLFetcher::Create(0, url, net::URLFetcher::GET, this);
|
| - data_use_measurement::DataUseUserData::AttachToFetcher(
|
| - request.get(), data_use_measurement::DataUseUserData::SUGGESTIONS);
|
| - int load_flags = net::LOAD_DISABLE_CACHE | net::LOAD_DO_NOT_SEND_COOKIES |
|
| - net::LOAD_DO_NOT_SAVE_COOKIES;
|
| -
|
| - request->SetLoadFlags(load_flags);
|
| - request->SetRequestContext(url_request_context_);
|
| - // Add Chrome experiment state to the request headers.
|
| - net::HttpRequestHeaders headers;
|
| - variations::AppendVariationHeaders(request->GetOriginalURL(), false, false,
|
| - &headers);
|
| - request->SetExtraRequestHeaders(headers.ToString());
|
| - if (!access_token.empty()) {
|
| - request->AddExtraRequestHeader(
|
| - base::StringPrintf(kAuthorizationHeaderFormat, access_token.c_str()));
|
| - }
|
| - return request;
|
| -}
|
| -
|
| -void SuggestionsService::OnURLFetchComplete(const net::URLFetcher* source) {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| - DCHECK_EQ(pending_request_.get(), source);
|
| -
|
| - // The fetcher will be deleted when the request is handled.
|
| - std::unique_ptr<const net::URLFetcher> request(std::move(pending_request_));
|
| -
|
| - const net::URLRequestStatus& request_status = request->GetStatus();
|
| - if (request_status.status() != net::URLRequestStatus::SUCCESS) {
|
| - // This represents network errors (i.e. the server did not provide a
|
| - // response).
|
| - UMA_HISTOGRAM_SPARSE_SLOWLY("Suggestions.FailedRequestErrorCode",
|
| - -request_status.error());
|
| - DVLOG(1) << "Suggestions server request failed with error: "
|
| - << request_status.error() << ": "
|
| - << net::ErrorToString(request_status.error());
|
| - UpdateBlacklistDelay(false);
|
| - ScheduleBlacklistUpload();
|
| - return;
|
| - }
|
| -
|
| - const int response_code = request->GetResponseCode();
|
| - UMA_HISTOGRAM_SPARSE_SLOWLY("Suggestions.FetchResponseCode", response_code);
|
| - if (response_code != net::HTTP_OK) {
|
| - // A non-200 response code means that server has no (longer) suggestions for
|
| - // this user. Aggressively clear the cache.
|
| - suggestions_store_->ClearSuggestions();
|
| - UpdateBlacklistDelay(false);
|
| - ScheduleBlacklistUpload();
|
| - return;
|
| - }
|
| -
|
| - const TimeDelta latency = TimeTicks::Now() - last_request_started_time_;
|
| - UMA_HISTOGRAM_MEDIUM_TIMES("Suggestions.FetchSuccessLatency", latency);
|
| -
|
| - // Handle a successful blacklisting.
|
| - GURL blacklisted_url;
|
| - if (GetBlacklistedUrl(*source, &blacklisted_url)) {
|
| - blacklist_store_->RemoveUrl(blacklisted_url);
|
| - }
|
| -
|
| - std::string suggestions_data;
|
| - bool success = request->GetResponseAsString(&suggestions_data);
|
| - DCHECK(success);
|
| -
|
| - // Parse the received suggestions and update the cache, or take proper action
|
| - // in the case of invalid response.
|
| - SuggestionsProfile suggestions;
|
| - if (suggestions_data.empty()) {
|
| - LogResponseState(RESPONSE_EMPTY);
|
| - suggestions_store_->ClearSuggestions();
|
| - } else if (suggestions.ParseFromString(suggestions_data)) {
|
| - LogResponseState(RESPONSE_VALID);
|
| - int64_t now_usec =
|
| - (base::Time::NowFromSystemTime() - base::Time::UnixEpoch())
|
| - .ToInternalValue();
|
| - SetDefaultExpiryTimestamp(&suggestions, now_usec + kDefaultExpiryUsec);
|
| - PopulateExtraData(&suggestions);
|
| - suggestions_store_->StoreSuggestions(suggestions);
|
| - } else {
|
| - LogResponseState(RESPONSE_INVALID);
|
| - }
|
| -
|
| - callback_list_.Notify(GetSuggestionsDataFromCache());
|
| -
|
| - UpdateBlacklistDelay(true);
|
| - ScheduleBlacklistUpload();
|
| -}
|
| -
|
| -void SuggestionsService::PopulateExtraData(SuggestionsProfile* suggestions) {
|
| - for (int i = 0; i < suggestions->suggestions_size(); ++i) {
|
| - suggestions::ChromeSuggestion* s = suggestions->mutable_suggestions(i);
|
| - if (!s->has_favicon_url() || s->favicon_url().empty()) {
|
| - s->set_favicon_url(base::StringPrintf(kFaviconURL, s->url().c_str()));
|
| - }
|
| - }
|
| -}
|
| -
|
| -void SuggestionsService::Shutdown() {
|
| - // Cancel pending request.
|
| - pending_request_.reset(nullptr);
|
| -}
|
| -
|
| -void SuggestionsService::ScheduleBlacklistUpload() {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| - TimeDelta time_delta;
|
| - if (blacklist_store_->GetTimeUntilReadyForUpload(&time_delta)) {
|
| - // Blacklist cache is not empty: schedule.
|
| - base::Closure blacklist_cb =
|
| - base::Bind(&SuggestionsService::UploadOneFromBlacklist,
|
| - weak_ptr_factory_.GetWeakPtr());
|
| - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
|
| - FROM_HERE, blacklist_cb, time_delta + scheduling_delay_);
|
| - }
|
| -}
|
| -
|
| -void SuggestionsService::UploadOneFromBlacklist() {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| -
|
| - GURL blacklisted_url;
|
| - if (blacklist_store_->GetCandidateForUpload(&blacklisted_url)) {
|
| - // Issue a blacklisting request. Even if this request ends up not being sent
|
| - // because of an ongoing request, a blacklist request is later scheduled.
|
| - IssueRequestIfNoneOngoing(BuildSuggestionsBlacklistURL(blacklisted_url));
|
| - return;
|
| - }
|
| -
|
| - // Even though there's no candidate for upload, the blacklist might not be
|
| - // empty.
|
| - ScheduleBlacklistUpload();
|
| -}
|
| -
|
| -void SuggestionsService::UpdateBlacklistDelay(bool last_request_successful) {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| -
|
| - if (last_request_successful) {
|
| - scheduling_delay_ = TimeDelta::FromSeconds(kDefaultSchedulingDelaySec);
|
| - } else {
|
| - TimeDelta candidate_delay =
|
| - scheduling_delay_ * kSchedulingBackoffMultiplier;
|
| - if (candidate_delay < TimeDelta::FromSeconds(kSchedulingMaxDelaySec))
|
| - scheduling_delay_ = candidate_delay;
|
| - }
|
| -}
|
| -
|
| -} // namespace suggestions
|
|
|